Skip to content

Payments

GatewayStatusFeatures
StripeProductionCards, Apple Pay, Google Pay, 3DS
AirwallexProductionCards, WeChat Pay, Alipay, 3DS
MockTestingSimulates success/failure
[payment]
default_gateway = "stripe" # or "airwallex"
[payment.stripe]
enabled = true
secret_key = "sk_..."
publishable_key = "pk_..."
[payment.airwallex]
enabled = true
client_id = "..."
api_key = "..."
demo = false # true for sandbox
  1. POST /checkout/complete — creates order + payment intent, returns client_secret
  2. Client-side: mount Stripe Elements or Airwallex Drop-in with client_secret
  3. User enters card details and confirms
  4. POST /checkout/confirm — server verifies payment and finalizes order

Stripe Elements integration. The client_secret from checkout complete is passed to Stripe.js on the client.

const stripe = await loadStripe(publishableKey);
const { error } = await stripe.confirmCardPayment(clientSecret, {
payment_method: { card: cardElement }
});

Airwallex Drop-in integration. Load the SDK from CDN:

<script src="https://static.airwallex.com/components/sdk/v1/index.js"></script>
await AirwallexComponentsSDK.init({ env: 'prod', enabledElements: ['payments'] });
const dropIn = await AirwallexComponentsSDK.createElement('dropIn', {
client_secret: result.client_secret,
currency: 'USD',
intent_id: result.payment_intent_id,
});
dropIn.mount('airwallex-drop-in');
dropIn.on('success', () => { /* confirm with server */ });
Terminal window
POST /api/v1/payments/:id/refund
{ "amount": 50.00, "reason": "Customer request" }

Partial refunds supported. The refund is processed through the original gateway.

Payment status changes trigger webhooks:

  • payment.succeeded — payment confirmed
  • payment.failed — payment declined
  • refund.succeeded — refund processed

Configure webhook endpoints in the admin or via API.