Node.js8 min read
Payment Integration with Stripe
Accept payments with Stripe. Handle webhooks and subscriptions.
Sarah Chen
December 19, 2025
0.0k0
Stripe Payment Integration
Accept payments securely with Stripe.
Setup
npm install stripe
const stripe = require('stripe')('sk_test_your_secret_key');
Create Payment Intent
const express = require('express');
const app = express();
app.use(express.json());
app.post('/create-payment-intent', async (req, res) => {
const { amount } = req.body;
try {
const paymentIntent = await stripe.paymentIntents.create({
amount: amount,
currency: 'usd',
payment_method_types: ['card'],
metadata: {
orderId: 'order_123'
}
});
res.json({
clientSecret: paymentIntent.client_secret
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);
Client Side (React)
import { loadStripe } from '@stripe/stripe-js';
import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';
const stripePromise = loadStripe('pk_test_your_publishable_key');
function CheckoutForm() {
const stripe = useStripe();
const elements = useElements();
const handleSubmit = async (e) => {
e.preventDefault();
const { clientSecret } = await fetch('/create-payment-intent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount: 5000 })
}).then(r => r.json());
const { error, paymentIntent } = await stripe.confirmCardPayment(
clientSecret,
{
payment_method: {
card: elements.getElement(CardElement)
}
}
);
if (error) {
console.error(error.message);
} else if (paymentIntent.status === 'succeeded') {
console.log('Payment successful!');
}
};
return (
<form onSubmit={handleSubmit}>
<CardElement />
<button type="submit" disabled={!stripe}>Pay</button>
</form>
);
}
Webhooks
app.post('/webhook',
express.raw({ type: 'application/json' }),
async (req, res) => {
const sig = req.headers['stripe-signature'];
const webhookSecret = 'whsec_your_webhook_secret';
let event;
try {
event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
} catch (err) {
return res.status(400).send(\`Webhook Error: \${err.message}\`);
}
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log('Payment succeeded:', paymentIntent.id);
await updateOrderStatus(paymentIntent.metadata.orderId, 'paid');
break;
case 'payment_intent.payment_failed':
console.log('Payment failed');
break;
}
res.json({ received: true });
}
);
Subscriptions
app.post('/create-subscription', async (req, res) => {
const { customerId, priceId } = req.body;
try {
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [{ price: priceId }],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent']
});
res.json({
subscriptionId: subscription.id,
clientSecret: subscription.latest_invoice.payment_intent.client_secret
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
Key Takeaway
Never expose secret keys. Verify amounts server-side. Use webhooks for payment confirmations. Test with Stripe test cards. Handle errors gracefully. Always use HTTPS in production.
#Node.js#Payments#Stripe#E-commerce