Appearance
Payment Gateways: Asia & Africa
This page covers the gateways for the Philippines, Indonesia, India and Africa. For how these gateways work in general, and for the go-live checklist that applies to all of them, see Payment Gateways.
PayMongo
For merchants in the Philippines. The customer pays on PayMongo's hosted Checkout page with GCash, QR Ph (InstaPay), Maya, GrabPay, BillEase or a card. The store currency must be PHP.
InstaPay and GCash: InstaPay payments use QR Ph, the Philippine national QR standard. PayMongo shows a QR code and the customer scans it in their bank or e-wallet app. GCash is a separate method, where the customer pays in their GCash account.
Available from v3.13.0
payment_gateway="paymongo"Setup
- Log in to the PayMongo Dashboard.
- Go to Developers → API Keys and copy the test and live secret keys (
sk_test_...andsk_live_...). - Make sure every payment method you want to offer (at least GCash and QR Ph) is activated on your PayMongo account.
- Create a webhook as described under Webhook below.
| Field | Description |
|---|---|
| Debug mode | On uses the test fields, off uses the live fields |
| Available payment methods | The methods shown on the PayMongo Checkout page: GCash, QR Ph (InstaPay), Card, Maya, GrabPay, BillEase. Each method must also be activated on your PayMongo account. If you select none, GCash and QR Ph are offered |
| Test Secret Key | Developers → API Keys (test mode) |
| Test Webhook Secret | The signing secret of the test mode webhook |
| Live Secret Key | Developers → API Keys (live mode) |
| Live Webhook Secret | The signing secret of the live mode webhook |
Webhook
In the PayMongo Dashboard, go to Developers → Webhooks and add a webhook with the notify URL shown in the CP. Subscribe it to the event checkout_session.payment.paid. Copy its signing secret into the matching Webhook Secret field. Do this for both test mode and live mode.
The module checks the Paymongo-Signature header with this secret. A webhook with an invalid signature is refused. Without a secret, the webhook is still processed (the payment is fetched from the API anyway) and an error is logged. Other events are ignored.
The webhook matters most for QR Ph: a customer who scans the code and pays in their bank app often doesn't come back to your site. The webhook then completes the order.
How the payment works
- On checkout, the module creates a PayMongo Checkout Session for the order total (one line for the whole order) and sends the customer to it.
- When the payment is paid, on return or through the webhook, the order becomes complete. An open payment (for example a QR code that hasn't been scanned yet) leaves the order as it is.
- A session that expires sets the order to expired. When the customer cancels on the Checkout page, they return to the checkout and the order becomes cancelled.
- Refunds of the full amount can be issued from the order in the CP. QR Ph refunds follow PayMongo's QR Ph refund rules.
Limitations
- PHP only.
- Only the full order amount can be refunded. A refund needs the PayMongo payment id, which the module stores when it sees the payment as paid.
Test checklist
- [ ] A webhook with the
Paymongo-Signatureheader verifies with the webhook secret you entered (nowebhook verification failedin the Store log). - [ ] GCash and QR Ph are activated on your PayMongo account, in test and in live mode, and both show up on the Checkout page.
- [ ] A QR Ph payment where the customer closes the page after paying still completes the order through the webhook.
- [ ] A refund of a QR Ph payment: check it against PayMongo's QR Ph refund rules.
- [ ] Test cards and test e-wallets: see PayMongo's payment acceptance testing. In test mode, QR Ph creates real QR codes: do not scan and pay them, use the test page PayMongo offers instead.
Xendit
For merchants in the Philippines. The customer pays on Xendit's hosted Invoice page with GCash, QR Ph (InstaPay), Maya, GrabPay, ShopeePay or a card. The store currency must be PHP.
InstaPay and GCash: InstaPay payments use QR Ph, the Philippine national QR standard. Xendit shows a QR code and the customer scans it in their bank or e-wallet app. GCash is a separate method, where the customer pays in their GCash account.
Available from v3.13.0
payment_gateway="xendit"Setup
- Log in to the Xendit Dashboard.
- Go to Settings → API Keys and create a secret key with write access for Money-in. Do this in test mode and in live mode.
- Make sure every payment method you want to offer (at least GCash and QR Ph) is activated on your Xendit account.
- Set up the webhook as described under Webhook below.
| Field | Description |
|---|---|
| Debug mode | On uses the test fields, off uses the live fields |
| Available payment methods | The methods shown on the Invoice page: GCash, QR Ph (InstaPay), Card, Maya, GrabPay, ShopeePay. Each method must also be activated on your Xendit account. If you select none, GCash and QR Ph are offered |
| Invoice duration (minutes) | How long the customer has to pay. Defaults to 60 minutes |
| Test Secret Key | Settings → API Keys (test mode) |
| Test Webhook Verification Token | Settings → Webhooks (test mode) |
| Live Secret Key | Settings → API Keys (live mode) |
| Live Webhook Verification Token | Settings → Webhooks (live mode) |
Webhook
In the Xendit Dashboard, go to Settings → Webhooks. Enter the notify URL shown in the CP as the Invoices paid URL and enable Also notify my application when an invoice has expired. Copy the verification token on that page into the matching Webhook Verification Token field. Do this for both test mode and live mode.
The module compares the X-Callback-Token header with this token. A webhook with a wrong token is refused. Without a token, the webhook is still processed (the invoice is fetched from the API anyway) and an error is logged.
How the payment works
- On checkout, the module creates a Xendit Invoice for the order total, valid for the configured duration, and sends the customer to it.
- When the invoice is paid (
PAIDorSETTLED), on return or through the webhook, the order becomes complete. An unpaid invoice (for example a QR code that hasn't been scanned yet) leaves the order as it is. - When the invoice expires, the order becomes expired (via the expired webhook, or when the customer returns).
- When the payment fails, Xendit sends the customer back to the checkout and the order becomes cancelled.
- Refunds of the full amount can be issued from the order in the CP. Not every channel supports refunds through the API: QR Ph refunds are not supported by every bank. Xendit then returns an error, which is shown in the CP.
Limitations
- PHP only.
- Only the full order amount can be refunded, and not for every channel.
Test checklist
- [ ] Invoices are accepted with the QR Ph method selected (the
QRPHpayment method code). GCash (GCASH) is confirmed to work. If Xendit returns an error when creating the invoice, check the Store log. - [ ] The Invoices paid webhook completes the order, and the token check passes (no
webhook verification failedin the Store log). - [ ] With Also notify my application when an invoice has expired enabled, an invoice that runs out sets the order to expired. Use a short Invoice duration to test this.
- [ ] A refund of a QR Ph payment: QR Ph refunds are not supported by every bank, so check what happens for the banks your customers use.
- [ ] Simulate payments in test mode by opening the invoice link and using the test banner, see How can I simulate payment using Invoice on test mode.
Midtrans
For merchants in Indonesia. The customer pays on the hosted Snap page with GoPay, QRIS, ShopeePay, bank virtual accounts, Mandiri Bill Payment, cards, Indomaret/Alfamart, Akulaku or Kredivo. The store currency must be IDR, in whole rupiah.
Available from v3.13.0
payment_gateway="midtrans"Setup
- Log in to the Midtrans Dashboard, once for the sandbox and once for production.
- Go to Settings → Access Keys and copy the Server Key.
- Make sure the payment methods you want to offer are activated on your Midtrans account.
| Field | Description |
|---|---|
| Debug mode | On uses the Midtrans sandbox and the Sandbox Server Key, off uses production |
| Available payment methods | The methods shown on the Snap page. Each method must also be activated on your Midtrans account. If you select none, all methods enabled in your Snap Preference are offered |
| Sandbox Server Key | Settings → Access Keys in the sandbox dashboard |
| Production Server Key | Settings → Access Keys in the production dashboard |
Webhook
No setup needed. The module sends its notify URL with every payment, so the notification URL in the Midtrans dashboard is not used for these orders.
Notifications are verified with their signature_key, using your Server Key. A notification with an invalid signature is refused.
How the payment works
- On checkout, the module creates a Snap transaction for the order total, rounded to whole rupiah, and sends the customer to the Snap page.
- When the payment is settled (or a card payment is captured), the order becomes complete. A card payment flagged by Midtrans' fraud detection (
challenge) becomes pending until it is reviewed. - Methods that are paid later, such as virtual accounts and Indomaret/Alfamart, set the order to pending. The notification completes it once the customer has paid. A customer who returns while the order is pending is sent to the home page of your site, not to the order page.
- Denied or failed payments set the order to failed, expired ones to expired, cancelled ones to cancelled.
- When the customer comes back without choosing a method, the order stays open and they return to the checkout.
- Refunds of the full amount can be issued from the order in the CP. A card payment that is not settled yet is cancelled instead. Refunds work only for cards, GoPay, ShopeePay, DANA, OVO, QRIS, Kredivo and Akulaku, and Midtrans may need to activate them for your account. For other methods Midtrans returns an error.
Limitations
- IDR only. Amounts are rounded to whole rupiah.
- Refunds only for some payment methods (see above).
Test checklist
- [ ] After a successful payment, the customer lands on the order page. Snap adds its own parameters (
order_id,status_code,transaction_status) to the return URL; check that this still works. - [ ] Payments in IDR only, in whole rupiah: check an order with a total that has decimals.
- [ ] A refund for each payment method you offer. Refunds only work for some methods, and Midtrans may need to activate them on your account.
- [ ] A virtual account payment: the order becomes pending first and complete after you simulate the payment.
- [ ] Test cards and the payment simulator: see Testing Payment on Sandbox.
Razorpay
For merchants in India. The customer pays via a hosted Razorpay Payment Link with UPI, cards, netbanking, wallets and the other methods enabled on your account. Any currency your Razorpay account supports.
Available from v3.13.0
payment_gateway="razorpay"Setup
- Log in to the Razorpay Dashboard.
- Go to Account & Settings → API Keys and generate a Key Id and Key Secret, in Test mode and in Live mode.
- Set up the webhook as described under Webhook below.
| Field | Description |
|---|---|
| Debug mode | On uses the test fields, off uses the live fields |
| Test Key Id | Starts with rzp_test_ |
| Test Key Secret | Shown once when you generate the test key |
| Test Webhook Secret | The secret you set on the test mode webhook |
| Live Key Id | Starts with rzp_live_ |
| Live Key Secret | Shown once when you generate the live key |
| Live Webhook Secret | The secret you set on the live mode webhook |
Webhook
In the Razorpay Dashboard, go to Account & Settings → Webhooks and add a webhook with the notify URL shown in the CP. Subscribe it to the events payment_link.paid, payment_link.expired and payment_link.cancelled, and set a secret. Enter the same secret in the matching Webhook Secret field. Do this for both Test mode and Live mode.
The module checks the X-Razorpay-Signature header with this secret. A webhook with an invalid signature is refused. Without a secret, the webhook is still processed (the payment link is fetched from the API anyway) and an error is logged. Events that don't start with payment_link. are ignored.
How the payment works
- On checkout, the module creates a Payment Link for the order total (no partial payments) and sends the customer to it. Razorpay sends no SMS or email for it.
- When the link is paid, on return or through the webhook, the order becomes complete. Razorpay only lists captured payments on the link, so an authorized payment that is not captured doesn't count.
- An expired link sets the order to expired, a cancelled link to cancelled.
- Refunds of the full amount can be issued from the order in the CP.
Limitations
- Only the full order amount can be refunded. A refund needs the Razorpay payment id, which the module stores when it sees the captured payment.
- The customer can't cancel back to your checkout from the Payment Link page. The order stays open until the link is paid, expires or is cancelled.
Test checklist
- [ ] The payment link webhooks (
payment_link.paid,payment_link.expired,payment_link.cancelled) arrive and pass the signature check with your webhook secret (nowebhook verification failedin the Store log). - [ ] If you sell in a three-decimal currency (such as KWD, BHD or OMR), check that the amount on the Razorpay page matches the order total.
- [ ] Only captured payments complete the order: if your account doesn't capture payments automatically, check your capture settings in Razorpay.
- [ ] Test cards and the test bank page: see Razorpay's test card details.
Paystack
For merchants in Nigeria, Ghana, South Africa, Kenya and Côte d'Ivoire. The customer pays on Paystack's hosted Checkout with cards, bank, bank transfer, USSD, QR, mobile money, EFT or Apple Pay. Supported currencies: NGN, GHS, ZAR, KES, USD and XOF.
Available from v3.13.0
payment_gateway="paystack"Setup
- Log in to the Paystack Dashboard.
- Go to Settings → API Keys & Webhooks and copy the test and live secret keys.
- On the same page, enter the notify URL as the Webhook URL (see Webhook below).
| Field | Description |
|---|---|
| Debug mode | On uses the test key, off uses the live key |
| Available payment channels | The channels shown on the Checkout: Card, Bank, Bank transfer, USSD, QR, Mobile money, EFT, Apple Pay. Each channel must also be available for your Paystack account and currency. If you select none, all channels enabled on your account are offered |
| Test Secret Key | Starts with sk_test_, also used to verify the webhooks |
| Live Secret Key | Starts with sk_live_, also used to verify the webhooks |
Webhook
In the Paystack Dashboard, go to Settings → API Keys & Webhooks and enter the notify URL shown in the CP as the Webhook URL, for both test mode and live mode. There is no separate secret: the module checks the X-Paystack-Signature header with your secret key. A webhook with an invalid signature is refused. Only charge.success events are processed.
How the payment works
- On checkout, the module starts a Paystack transaction for the order total and sends the customer to the Checkout.
- When the transaction succeeds, on return or through the webhook, the order becomes complete. Pending or queued transactions set the order to pending, failed ones to failed.
- When the customer cancels on the Checkout, Paystack sends them back to the checkout (the cancel action) and the order becomes cancelled.
- Refunds of the full amount can be issued from the order in the CP. A reversed transaction (refund or chargeback) sets the order to refunded.
Limitations
- Currencies: NGN, GHS, ZAR, KES, USD and XOF. Which ones you can use depends on your Paystack account and country.
- Only the full order amount can be refunded.
Test checklist
- [ ] After a successful payment, the customer lands on the order page. Paystack adds
trxrefandreferenceto the callback URL; check that the rest of the URL is kept. - [ ] Cancelling on the Checkout sends the customer back to the checkout and sets the order to cancelled (the cancel action).
- [ ] A payment in each currency you sell in, and that the currency is enabled on your Paystack account.
- [ ] Test cards and test bank accounts: see the test payments section of the Paystack documentation.
Flutterwave
For merchants in Africa. The customer pays on Flutterwave's hosted payment page with cards, bank transfer, bank account, USSD, M-Pesa, mobile money (Ghana, Uganda, Rwanda, Zambia, Tanzania, Francophone Africa), Apple Pay or Google Pay. Any currency your Flutterwave account supports.
Available from v3.13.0
payment_gateway="flutterwave"Setup
- Log in to the Flutterwave Dashboard.
- Go to Settings → API Keys and copy the secret keys, in test mode and live mode.
- Set up the webhook as described under Webhook below.
The module uses Flutterwave Standard on the v3 API, because the v4 API has no hosted payment page yet. Use v3 API keys.
| Field | Description |
|---|---|
| Debug mode | On uses the test fields, off uses the live fields |
| Available payment methods | The methods shown on the payment page. Only used when Disable preferred payment methods is off in your Flutterwave business preferences. If you select none, the methods enabled on your account are offered |
| Test Secret Key | Starts with FLWSECK_TEST- |
| Test Webhook Secret Hash | The secret hash you set on the webhook (test mode) |
| Live Secret Key | Starts with FLWSECK- |
| Live Webhook Secret Hash | The secret hash you set on the webhook (live mode) |
Webhook
In the Flutterwave Dashboard, go to Settings → Webhooks, enter the notify URL shown in the CP as the URL and choose a secret hash. Enter the same value in the matching Webhook Secret Hash field. Do this for both test mode and live mode.
The module compares the verif-hash header with this value. A webhook with a wrong hash is refused. Without a secret hash, the webhook is still processed (the transaction is fetched from the API anyway) and an error is logged. Only charge.completed events are processed.
How the payment works
- On checkout, the module creates a hosted payment link for the order total and sends the customer to it.
- When the transaction is successful, on return or through the webhook, the module checks that the amount and currency match the order. Only then does the order become complete. A pending transaction sets the order to pending.
- A failed attempt leaves the order as it is, because the customer can retry on the same payment page.
- When the customer cancels, Flutterwave sends them back with
status=cancelled(orfailed). They return to the checkout and the order becomes cancelled. - Refunds of the full amount can be issued from the order in the CP. Flutterwave may report a refund as in progress first. Only a refund with a failed status is reported as failed.
Limitations
- Only the full order amount can be refunded. A refund needs the Flutterwave transaction id, which the module stores when it sees the successful transaction.
- A payment for less than the order total, or in another currency, is not accepted: the order stays as it is and an error is logged.
Test checklist
- [ ] Cancelling on the payment page sends the customer back with
status=cancelledorstatus=failedand sets the order to cancelled. - [ ] Flutterwave keeps the query string of the redirect URL when it adds its own parameters (
status,tx_ref,transaction_id): after paying, the customer lands on the order page. - [ ] The payment methods you selected (the
payment_optionsvalues) show up on the payment page. If they don't, check Disable preferred payment methods in your business preferences. - [ ] A refund from the CP, and the refund status Flutterwave reports for it in the dashboard.
- [ ] Your account and keys work with the Flutterwave v3 API.
- [ ] Test cards: see Flutterwave's testing documentation.
