This guide explains how to integrate the Stripe payment gateway using the unified-pay-core package. It covers setup, configuration, and key operations like creating payments, capturing payments, processing refunds, and handling webhooks.
Prerequisites
- Node.js and npm installed.
- A Stripe account with API keys (test or live).
- A webhook secret for verifying webhook events.
- Install the unified-pay-core package:
npm install unified-pay-core
Setup
Obtain Stripe Credentials
- Log in to your Stripe Dashboard.
- Get your Secret Key (
sk_test_...
for testing,sk_live_...
for production). - Set up a webhook endpoint in Stripe and obtain the Webhook Secret (
whsec_...
).
Install Dependencies
Ensure you have express and cors for the example server:
npm install express cors
Configure the Gateway
Initialize the Stripe gateway using the createGateways
function from unified-pay-core.
const express = require("express");
const cors = require("cors");
const { createGateways } = require("unified-pay-core");
const app = express();
app.use(cors());
app.use("/webhook", express.raw({ type: "application/json" }));
app.use(express.json());
const { stripe } = createGateways([
{
gateway: "stripe",
config: {
apiSecret: process.env.API_SECRET,
environment: "sandbox",
webhookId: process.env.WEBHOOK_SECRET,
},
},
]);
Key Operations
1. Create a Payment
Initiate a payment request to create a PaymentIntent.
app.post("/create-payment", async (req, res) => {
try {
const { amount = 20 } = req.body;
const payment = await stripe.processPayment(amount, "usd", {
test_run: "Sample Payment",
});
res.json({
success: true,
transactionId: payment.transactionId,
clientSecret: payment.metadata?.clientSecret || null,
});
} catch (err) {
console.error("Payment creation error:", err);
res.status(500).json({ success: false, error: "Payment creation failed" });
}
});
Input:
amount
: Payment amount (e.g., 20 for $20.00).currency
: Currency code (e.g., "usd").metadata
: Optional key-value pairs for additional data.
Output:
transactionId
: Stripe PaymentIntent ID (pi_...
).clientSecret
: Used for client-side confirmation (e.g., 3D Secure).
2. Capture a Payment
Capture a previously authorized payment (if captureMethod was set to "manual").
app.get("/return", async (req, res) => {
try {
const { transactionId } = req.query;
if (!transactionId) {
return res.status(400).json({ error: "Missing transactionId" });
}
const capture = await stripe.capturePayment(transactionId);
const verification = await stripe.verifyPayment(capture.transactionId);
res.json({ capture, verification });
} catch (err) {
console.error("Payment capture error:", err);
res.status(500).json({ error: "Payment capture failed" });
}
});
Input:
transactionId
: The PaymentIntent ID to capture.
Output:
capture
: Payment response with status, amount, and currency.verification
: Verification details confirming the payment status.
3. Process a Refund
Refund a payment (full or partial).
app.post("/refund", async (req, res) => {
try {
const { transactionId, amount } = req.body;
if (!transactionId) {
return res.status(400).json({ error: "transactionId is required" });
}
const refund = await stripe.processRefund(
transactionId,
amount ? parseFloat(amount) : undefined
);
res.json({
success: refund.success,
refundId: refund.refundId,
transactionId,
status: refund.status,
amount: refund.amount,
currency: refund.currency,
});
} catch (err) {
console.error("Refund error:", err);
res.status(500).json({ success: false, error: "Refund failed" });
}
});
Input:
transactionId
: The PaymentIntent ID to refund.amount
: Optional partial refund amount (e.g., 10 for $10.00).
Output:
refundId
: Stripe Refund ID (re_...
).status
: Refund status (succeeded, pending, failed).
4. Verify a Payment
Verify the status of a payment.
const verification = await stripe.verifyPayment(transactionId);
Input:
transactionId
: The PaymentIntent ID to verify.
Output:
verified
: Boolean indicating if the verification was successful.status
: Payment status (succeeded, pending, failed, cancelled).isValid
: Boolean indicating if the payment is valid (e.g., succeeded).
5. Handle Webhooks
Set up a webhook endpoint to receive and process Stripe events.
app.post("/webhook/stripe", async (req, res) => {
try {
const result = await stripe.handleWebhookEvent(req.body, req.headers);
res.status(result === "INVALID" ? 400 : 200).send(result);
} catch (error) {
console.error("Webhook processing error:", error);
res.status(500).send("Webhook processing failed");
}
});
Setup:
- Use
express.raw({ type: "application/json" })
for the webhook route to preserve the raw body for signature verification. - Configure the webhook URL in the Stripe Dashboard (e.g.,
https://yourdomain.com/webhook/stripe
).
Supported Events:
payment_intent.succeeded
charge.captured
charge.succeeded
payment_intent.payment_failed
charge.failed
charge.refunded
refund.created
refund.updated
Webhook Testing
- Use tools like ngrok to expose your local server:
ngrok http 3000
. - Update the webhook URL in the Stripe Dashboard.
- Test events like
payment_intent.succeeded
orcharge.refunded
using Stripe's test tools.
Notes
- Amount Handling: Stripe expects amounts in cents (e.g., $20.00 = 2000).
- 3D Secure: Enable
require3DS: true
in processPayment options for enhanced security. - Webhook Secret: Ensure
webhookId
is set to verify webhook signatures. - Error Handling: Check
success
anderror
fields in responses to handle failures.