USD Integration Flow
Recommended integration path
For Echezona and partner teams, the recommended pattern is:
- Single server call to Clive checkout-intent
- Client-side Stripe Payment Element confirmation
- Clive transaction orchestration + partner webhook finalization
This aligns directly with:
POST /transactions/checkout-intent
Step-by-step sequence
1) Create checkout intent in Clive
Call POST /transactions/checkout-intent from your backend.
Clive will:
- initialize the transaction
- create Stripe PaymentIntent
- attach the intent internally
- return
clive_tx_id,stripe_payment_intent_id, andclient_secret
Persist:
clive_tx_idstripe_payment_intent_idclient_secret(short-lived, for frontend use)- your immutable reference (
echezona_reference) - your optional
metaobject - chosen
statement_descriptor_suffix
2) Confirm payment in frontend
Use Stripe Payment Element and the client_secret.
Frontend engineers should follow this sequence exactly:
- Receive
client_secret,stripe_publishable_key, andclive_tx_idfrom your backend. - Initialize Stripe with
loadStripe(stripe_publishable_key). - Render
<Elements options={{ clientSecret }}>. - Render
<PaymentElement />inside your checkout form. - On submit, call
elements.submit()first. - Then call
stripe.confirmPayment({ elements, confirmParams, redirect: "if_required" }). - If no Stripe error, refresh status for
clive_tx_idand display final order state.
Recommended confirmation call (same style as sandbox-web):
const result = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: window.location.href
},
redirect: "if_required"
});
if (result.error) {
// show result.error.message
} else {
// poll/fetch transaction status and render success
}
3) Handle final status with Clive status updates
- Clive updates transaction status and computed fees.
- Clive sends signed status notification to your webhook URL.
Do not mark orders as paid from frontend callback alone; only finalize after Clive status/webhook confirmation.
Sequence diagram
Echezona Backend -> Clive: POST /transactions/checkout-intent
Clive -> Stripe: create PaymentIntent
Stripe -> Clive: payment_intent_id + client_secret (internal processing)
Clive -> Echezona Backend: clive_tx_id + payment_intent_id + client_secret (pending)
User + Echezona Frontend -> Stripe: confirm payment
Clive -> Echezona Webhook URL: signed transaction update
Example backend orchestration (pseudo-code)
// 1) Create checkout intent on Clive
const checkout = await clive.createCheckoutIntent({
partner_id: "ECHEZONA001",
client_id: "AIRPEACE001",
amount: 750,
currency: "USD",
email: "buyer@example.com",
statement_descriptor_suffix: "AIRPEACE",
echezona_reference: "EZ12345",
meta: {
order_id: "ORD-1001",
customer_tier: "gold"
}
});
return {
clientSecret: checkout.client_secret,
cliveTxId: checkout.clive_tx_id,
stripePaymentIntentId: checkout.stripe_payment_intent_id
};
Example frontend checkout page (minimal)
<Elements stripe={stripePromise} options={{ clientSecret }}>
<form
onSubmit={async (e) => {
e.preventDefault();
await stripe.confirmPayment({
elements,
confirmParams: { return_url: window.location.href },
redirect: "if_required"
});
}}
>
<PaymentElement />
<button type="submit">Pay now</button>
</form>
</Elements>
Frontend checklist before shipping
- Payment page mounts
<PaymentElement />only after backend returnsclient_secret. - Submit handler uses both
elements.submit()andstripe.confirmPayment(...). - UI handles and displays Stripe errors cleanly.
- Checkout page can resume/reconcile state using
clive_tx_id. - Backend/webhook path, not frontend callback alone, marks the transaction as paid.
Operational best practices
- Reuse the same
idempotency-keywhen retrying the same business action. - Do not mark order paid based only on frontend callback; rely on webhook-confirmed success.
- Verify
X-Clive-Signatureon incoming Clive webhooks. - Treat the webhook
metaobject as your round-tripped partner metadata from transaction initialization. - Use a dead-letter or retry queue for failed webhook processing on your side.
- Re-fetch transaction status after
confirmPaymentso UI always reflects Clive final state. - Enforce a deterministic suffix convention (for example
AIRPEACE,ECHEZONA AIR) and persist it per transaction for support/reconciliation. - Legacy integrations can still use
/transactions/initialize+/transactions/attach-intent, but new integrations should use checkout-intent.