Payments
Supported gateways
Section titled “Supported gateways”| Gateway | Status | Features |
|---|---|---|
| Stripe | Production | Cards, Apple Pay, Google Pay, 3DS |
| Airwallex | Production | Cards, WeChat Pay, Alipay, 3DS |
| Mock | Testing | Simulates success/failure |
Configuration
Section titled “Configuration”[payment]default_gateway = "stripe" # or "airwallex"
[payment.stripe]enabled = truesecret_key = "sk_..."publishable_key = "pk_..."
[payment.airwallex]enabled = trueclient_id = "..."api_key = "..."demo = false # true for sandboxCheckout flow
Section titled “Checkout flow”POST /checkout/complete— creates order + payment intent, returnsclient_secret- Client-side: mount Stripe Elements or Airwallex Drop-in with
client_secret - User enters card details and confirms
POST /checkout/confirm— server verifies payment and finalizes order
Stripe
Section titled “Stripe”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
Section titled “Airwallex”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 */ });Refunds
Section titled “Refunds”POST /api/v1/payments/:id/refund{ "amount": 50.00, "reason": "Customer request" }Partial refunds supported. The refund is processed through the original gateway.
Webhooks
Section titled “Webhooks”Payment status changes trigger webhooks:
payment.succeeded— payment confirmedpayment.failed— payment declinedrefund.succeeded— refund processed
Configure webhook endpoints in the admin or via API.