Double-Redirect Flow
This recipe shows how to implement a Double-Redirect checkout flow.
Overview
The double-redirect flow has five steps:
- Merchant checkout — User clicks Pay button your site which saves the order as Pending and redirects to the Chargx Payment Form site
- External purchase — User pays on the Chargx Payment Form site with their card.
- Automatic redirect back — The Chargx Payment Form redirects the user to your Success URL (provided in the API call) after payment.
- Auto-redemption — Your site receives a transaction completion via the Webhook, then calls the Chargx API server-to-server to verify and claim the value.
- Order completion — Your site updates the order to Paid and shows the receipt.
Steps
1. Merchant checkout — save order and create ChargX Payment Widget
When the user clicks Pay, then:
- your site creates a pending order in your system
- then creates a ChargX Payment Widget via the API and redirect the user to its checkout URL. Include your order ID in the
success_urlso you can reconcile when they return.
Example:
// User clicked "Pay with Credit Card" for $50
const orderId = 345; // your internal order ID
await yourBackend.createOrder({ orderId, amount: 50, status: "pending" });
const successUrl = `https://yoursite.com/checkout/success?orderId=${orderId}`;
const response = await fetch("https://api.chargx.io/v1/payment-request", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": "pk_your_publishable_key",
},
body: JSON.stringify({
amount: 50,
currency: "usd",
success_url: successUrl,
type: "card", // bank-to-bank
}),
});
const data = await response.json();
if (!response.ok) throw new Error(data?.message ?? data?.error ?? "Failed to create payment widget");
const checkoutUrl = data.payment_request.checkout_url;
window.location.href = checkoutUrl;2. External purchase
The user is on the ChargX Payment Form. They use their credit card to make a payment.
3. Automatic redirect back
After the payment is confirmed, the ChargX Payment Form redirects the user to the Success URL you provided in step 1. We also append a chargx_order_id in the URL (query parameter) to identify the order.
Example URL your user might land on:
https://yoursite.com/checkout/success?orderId=345&chargx_order_id=ord_abc123&code=GC-XXXX-YYYY4. Auto-redemption
Webhook setup
This section requires to have Webhook endpoint setup in your site backend.
- Go to the Chargx Dashboard and navigate to the "Settings -> Webhooks" section.
- Click on the "Create webhook" button.
- Enter the name, webhook URL and select the events you want to receive.
- Click on the "Create" button.
See Webhooks Setup for more details.
Your site (backend) receives the Webhook request from Chargx - server-to-server Once receive, then your site (backend) should:
- Verify the code/order_id is valid
- Claim the value
Do not rely only on the URL parameters for security — always verify and claim via the provider’s API on the backend.
Example (server-side):
Read these three values from the webhook payload (data.object):
external_order_id— Your internal order ID (the one you passed when creating the payment).order_id— ChargX order ID.order_display_id— ChargX order display ID.
JavaScript (Node):
// your site backend webhook endpoint
app.post("/webhook", async (req, res) => {
const payload = req.body;
const order_id = parseInt(payload?.data?.object?.external_order_id ?? 0, 10);
const chargx_order_id = payload?.data?.object?.order_id ?? null;
const chargx_order_display_id = payload?.data?.object?.order_display_id ?? null;
if (!order_id) {
return res.status(400).json({ error: "Missing external_order_id" });
}
// Server-to-server: verify and claim (e.g. using chargx_order_id with ChargX API)
const claimResult = await yourBackend.verifyAndClaimFromThirdParty({
order_id,
chargx_order_id,
chargx_order_display_id,
});
if (!claimResult.success) {
throw new Error("Failed to claim the value");
}
// Update order to Paid in your system
await yourBackend.updateOrderStatus(order_id, "paid");
});
async function verifyAndClaimFromThirdParty({ order_id, chargx_order_id, chargx_order_display_id }) {
// 1) Verify with ChargX API (e.g. get order by order_id)
const verifyRes = await fetch(`https://api.chargx.io/v1/orders/${chargx_order_id}`, {
headers: {
"Authorization": "Bearer " + process.env.CHARGX_SECRET_KEY,
},
});
const orderData = await verifyRes.json();
if (!verifyRes.ok || !orderData?.order) {
return { success: false };
}
// 2) Optionally confirm / claim — then update your system
// Use order_id (your external_order_id) to mark the order as paid
return { success: true };
}5. Order completion
Your user is on a Success URL page. The page should show a loader with a text Finalizing your order and updating inventory... and ping your backend for order status. Once status is Paid, then your site should finally navigates a user to the order confirmation page.
Implementation references
The double-redirect flow is implemented by the Chargx Woocommerce plugin (enabled via payment_redirection_flow config).
Use it as a reference to implement the double-redirect flow in your site backend. The plugin also automatically registers a webhook endpoint using Admin API to receive the webhook requests from ChargX.
Payment Form: passing billing information
The Payment Form accepts billing information as query parameters, e.g.
• email
• phone-number
• street-address
• unit-address
• state
• zip-code
• country
• external_order_idhttps://dashboard.chargx.io/payment-form/01KN4JV2DC2V35F2121Z0ZQG9A?success_url=https%3A%2F%2Fwp-test.mysite.com%2F%3Fwc-api%3Dwc_gateway_chargx_card_success_url%26order_id%3D125&email=olena.test%40gmail.com&phone-number=+118731944911&street-address=Molodizhna&unit-address=11&city=NewYork&state=NY&zip-code=11111&country=US&external_order_id=125In this case the Payment Form will be rendered with the billing information fields prefilled.
Security notes
- Always verify and claim server-side. Do not trust the redirect URL alone; the third-party API is the source of truth.
- Idempotency: Use the order ID (or a idempotency key) so that duplicate redirects do not result in double redemption.
- Success URL: Use HTTPS and a URL that only your backend can interpret; avoid exposing sensitive tokens in the client path if possible.