Guides · Payments

Bank transfer at checkout

Customers can pay any checkout session by bank transfer to a one-time account. Transfers for the wrong amount, or that arrive too late, are never lost.

How it works

When the customer picks bank transfer, rafiqPay opens a one-time account for that checkout, for the exact amount. The account stays open until the checkout expires, within limits, and the page shows a countdown. If the account closes before they pay, the customer can ask for a new one on the same page.

A transfer of the exact amount, while the account is open, settles the checkout’s charge. You get checkout.session.completed and charge.succeeded, and the usual fee applies.

You do not call the bank-transfer route

The checkout page opens the account itself with POST /v1/public/checkout/sessions/:id/bank-transfer. It is a public route for the customer’s browser. It returns the same account while that account is open, and opens a new one after it expires. Your server only creates the session and listens for webhooks.

Wrong amount, or too late

A transfer that is more or less than the amount asked for, or that arrives after the account has closed, does not pay the checkout. The checkout stays as it was. The customer is told on the checkout page that their money is safe and what happens next.

What happens to the money depends on how your account is set up. Ask rafiqPay which applies to you.

ParameterTypeRequirementDescription
Held for youtransfer.heldOptionalThe money is kept aside for you, out of your available balance, until you accept it as a payment or return it to the customer. See Held transfers below.
Returned by the banktransfer.refunded_by_providerOptionalThe bank sends the money straight back to the sender. rafiqPay records it so you can see it happened. There is nothing for you to do.

Held transfers

Each held transfer has a reason (mismatch or expired), the amount expected and the amount received, and the sender’s name. List them with GET /v1/held-transfers?status=held, or see them in the dashboard. Then decide:

Accept: POST /v1/held-transfers/:id/accept credits the amount that arrived as a new charge of its own, with the usual fee. The original checkout is left as it was. You get transfer.accepted and charge.succeeded.

Return: POST /v1/held-transfers/:id/return sends the full amount back, with no fee, to the account the customer gives you (bankCode from GET /v1/transfers/banks, and accountNumber). The bank does not tell us which account the money came from, so ask the customer. When the money has gone you get transfer.returned. If the payout fails, the money is held again.

Testing

In test mode the one-time account number starts with 99. Call POST /v1/public/checkout/sessions/:id/bank-transfer/simulate to pretend the customer paid. Pass { amount } with a different amount to test a held transfer.