Accepting a payment
The flow
Section titled “The flow”- Customer clicks pay; you open the checkout.
- The SDK creates the payment and shows the available chains and tokens.
- Customer connects a wallet and switches to the right chain.
- The SDK checks the balance before letting them submit.
- Customer signs;
onSuccessfires. - Your server confirms the payment and fulfils the order.
Steps 2 to 5 are the SDK’s job. Step 6 is yours, and it is the one that gets skipped.
Why step 6 is not optional
Section titled “Why step 6 is not optional”onSuccess means the wallet accepted the transaction and broadcast it. It does
not mean the money arrived. The transaction can fail, be replaced by a
higher-fee one, or be dropped from the mempool.
It is also client-side, so it can be triggered by anyone who can open the browser console on your checkout page. Fulfilment decided in the browser is fulfilment anyone can ask for.
onSuccess={(paymentId, txHash) => { // Right: hand it to your server and let the server decide. fetch('/api/orders/awaiting-confirmation', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ paymentId, txHash }), });
// Wrong: fulfilling here trusts the browser. // grantAccess();}}Then confirm server-side, either by webhook or by reading the status with your key.
Balance checks
Section titled “Balance checks”The SDK checks the customer has enough of the token, and enough native currency for gas, before allowing submission. This catches the most common failure, having USDC but no ETH for gas, before a transaction is attempted rather than after it reverts.
Amounts that do not match
Section titled “Amounts that do not match”A customer can send more or less than invoiced. Neither breaks the payment, and both have defined handling: see Overpayments and refunds.
