Stripe is the default answer for a reason. The API is clean, the docs are good, the webhooks are reliable, and it covers the US and Western Europe without much thought. The moment a marketplace needs to collect payments in Brazil, India, Saudi Arabia, South Africa, or most of sub-Saharan Africa, that story gets more complicated. Buyers in those markets often don't have international cards at all, or pay measurable foreign-exchange fees when they do, or simply prefer a local rail that's faster and cheaper than any card network. This post covers the regional gateways worth wiring up first, when to do it, and how to architect a router that doesn't turn into a pile of switch statements.
Why Stripe alone isn't enough
Four gaps show up consistently. First, method coverage — Stripe supports PIX in Brazil and UPI in India through partners, but checkout conversion is notably lower than going through a native local provider. Second, payout geography — Stripe pays out to a supported list of countries, and a local seller in Egypt or Kenya either doesn't appear on that list or has to bridge through a third-party dollar account. Third, pricing — cross-border cards carry 1.5–2% FX plus interchange, while a local rail like PIX costs around 33 bps all-in. Fourth, compliance — local payment regulators (RBI in India, SAMA in Saudi, Central Bank of Brazil) increasingly require local licensing, KYC flows that Stripe does not run, and data residency that Stripe's unified account does not offer by default.
The regional gateways, at a glance
| Gateway | Region | Flagship methods | Pricing (typical) | Payout timing |
|---|---|---|---|---|
| PayTabs | MENA (UAE, KSA, Egypt, Jordan, Oman, Kuwait) | Cards (Mada, Meeza), Apple Pay, STC Pay | ~2.5–2.85% + fixed | T+1 to T+3 depending on market |
| Razorpay | India | UPI, cards, NetBanking, wallets, EMI | UPI near zero, cards 2% + 18% GST | T+2 standard, T+1 on upgrade |
| Mercado Pago | LatAm (Brazil, Argentina, Mexico, Chile, Colombia) | Cards, Pix, boleto, account balance | ~4–6% card in BR, lower on Pix | 14 days standard in BR, instant on upgrade |
| Paystack | Nigeria, Ghana, Kenya, South Africa, Côte d'Ivoire | Cards, bank transfer, USSD, mobile money | 1.5% + NGN100 local; 3.9% international | T+1 Nigeria, T+1 to T+2 elsewhere |
| Ozow | South Africa | Instant EFT (bank pull), PayShap | ~1.5–2% per transaction | Same-day for approved merchants |
| PIX (via PSP) | Brazil | Bank-to-bank instant, 24/7 | ~0.33% merchant (regulated) | Instant settlement to merchant account |
Pricing shown is indicative, not contractual. Every gateway negotiates bespoke rates for marketplaces with meaningful volume, and headline rates on the public site are usually the worst rate offered. If monthly processing crosses roughly $100K, a direct conversation with a sales rep is worth more than any published tier.
Payment rails worth understanding deeper
Three bear calling out individually because they behave unlike card networks and reshape what a marketplace checkout looks like.
- PIX (Brazil): bank-to-bank instant transfers settled 24/7 by the Central Bank, mandatory participation for regulated banks, capped merchant pricing. A QR code checkout that settles in under three seconds at sub-40-bp cost is the template competitors outside Brazil are still trying to match. In 2025, Pix Automático added recurring-payment support, which matters for subscription marketplaces.
- UPI (India): same shape as Pix — instant, cheap, universal. Razorpay and the other Indian PSPs sit on top of UPI and add reconciliation, webhook delivery, and dispute tooling. UPI volume in India exceeds card volume by a factor of ten.
- Instant EFT (South Africa, via Ozow and similar): user logs into their bank through a pop-up, authorizes a push payment, money lands in the merchant account the same day. Not real-time like Pix, but meaningfully cheaper than cards and trusted by banks. PayShap is the bank-native instant rail layered on top.
Architecting a multi-gateway router
The anti-pattern is a payment service with a switch statement on country code dispatching to seven different SDKs with seven different error shapes. The pattern that actually scales is a thin provider interface — create payment intent, capture, refund, emit webhook events — with one adapter per gateway behind it. The selection logic lives above the interface and is declarative: given a buyer country, a seller country, a currency, and an amount, pick the gateway. The rest of the app talks to the interface.
// payments/provider.ts — the common interface every gateway adapter implements
export interface PaymentProvider {
readonly name: string;
createIntent(input: {
amount: number;
currency: string;
buyerId: string;
orderId: string;
metadata?: Record<string, string>;
}): Promise<{ id: string; clientSecret?: string; redirectUrl?: string }>;
capture(intentId: string): Promise<{ status: "succeeded" | "failed" | "pending" }>;
refund(intentId: string, amount?: number): Promise<{ id: string }>;
verifyWebhook(rawBody: string, signature: string): Promise<WebhookEvent>;
}
// payments/router.ts — declarative selection based on country + currency
import { StripeProvider } from "./providers/stripe";
import { PaytabsProvider } from "./providers/paytabs";
import { RazorpayProvider } from "./providers/razorpay";
import { PaystackProvider } from "./providers/paystack";
import { MercadoPagoProvider } from "./providers/mercado-pago";
const providers = {
stripe: new StripeProvider(),
paytabs: new PaytabsProvider(),
razorpay: new RazorpayProvider(),
paystack: new PaystackProvider(),
mercadoPago: new MercadoPagoProvider(),
} as const;
type ProviderKey = keyof typeof providers;
const countryToProvider: Record<string, ProviderKey> = {
IN: "razorpay",
BR: "mercadoPago", // handles Pix + cards
NG: "paystack",
GH: "paystack",
KE: "paystack",
ZA: "paystack", // or Ozow for Instant EFT — see fallback below
AE: "paytabs",
SA: "paytabs",
EG: "paytabs",
};
export function pickProvider(ctx: {
buyerCountry: string;
currency: string;
}): PaymentProvider {
const key = countryToProvider[ctx.buyerCountry];
if (key) return providers[key];
// Default to Stripe for the US, EU, UK, AU, and anywhere unmapped
return providers.stripe;
}
// Usage — everything above this line doesn't know which gateway will handle the intent
const provider = pickProvider({ buyerCountry: order.buyerCountry, currency: order.currency });
const intent = await provider.createIntent({
amount: order.amountMinor,
currency: order.currency,
buyerId: order.buyerId,
orderId: order.id,
});The shape above is boring on purpose. Adding a new gateway is a new adapter file, a new entry in the country map, and a new webhook route. Removing one is deleting a file and redirecting traffic. The order service, the refund service, and the reconciliation cron never change.
KYC, onboarding, and payouts — the boring hard part
Collecting money is easier than paying out. Every gateway has its own onboarding flow for sellers, its own KYC requirements, and its own payout rules. Stripe Connect is famously opinionated — it takes over a lot of the seller-facing UI, which is fine if the marketplace wants to ship fast and less fine if brand control matters. PayTabs and Paystack tend toward lighter onboarding but require more document handling on the marketplace side. Razorpay's Route product handles split payouts to sub-merchants but the GST and PAN verification flows are India-specific and have no equivalent elsewhere. Mercado Pago's 14-day standard hold in Brazil is a cashflow consideration that changes the economics of a marketplace meaningfully at scale.
- Payout currency. Some gateways only pay out in local currency — a seller in Nigeria gets paid in NGN, full stop. If the marketplace needs to aggregate earnings across regions, plan a treasury function or a partner like Wise or Airwallex.
- Payout timing. Stripe's T+2 or T+7 defaults are standard. Mercado Pago's 14-day hold in Brazil is an outlier worth financial-modeling.
- Sub-merchant KYC. Marketplaces moving money on behalf of sellers are legally different from marketplaces of record. The provider's onboarding flow determines whether the marketplace is a principal or an aggregator, and the compliance implications follow from there.
- Dispute and chargeback handling. Each gateway exposes these differently. Normalize the webhook into a single internal dispute event early — otherwise the support team ends up looking at five different dashboards.
Cross-border fees sneak up on marketplaces that grow into new regions piecemeal. A buyer in Lagos paying a seller in São Paulo on a US-based Stripe account will see FX markups on the card (1–2%), an international processing surcharge (~1%), potential dynamic currency conversion, and the seller will face a payout conversion fee. The all-in cost is easily 4–6% before the marketplace's own take rate. Routing both sides to local rails usually cuts that in half.
Webhooks, idempotency, and reconciliation
Every gateway sends webhooks, and every gateway sends them imperfectly — retries, out-of-order delivery, occasional duplicates, occasional drops. The pattern that survives is: one inbound webhook route per provider, signature verified before parsing, stored as raw rows in a received_webhooks table keyed on the provider's event ID, then processed idempotently. Reconciliation runs as a scheduled job that walks payouts from each gateway against the internal ledger and flags discrepancies. This sounds fussy until the first time a gateway sends a refund webhook twice and an unsuspecting handler refunds twice.
When to add the second gateway
Not on day one. The overhead of a multi-gateway setup — adapters, webhook routing, reconciliation per provider, dual-dashboard support — is real, and paying it before revenue exists in a new region is premature. The practical trigger is: when a specific region represents 10%+ of attempted transactions and checkout conversion in that region is meaningfully below the marketplace average. That's the signal that the missing local rail is costing real money. At that point the business case writes itself.
Key takeaways
- Stripe covers the US, UK, EU, and AU gracefully. It covers India, Brazil, MENA, and sub-Saharan Africa less gracefully — and usually at higher cost and lower conversion than native local gateways.
- Build a thin provider interface once; add adapters per gateway behind it. Selection is a declarative country+currency lookup, not a growing switch statement.
- PIX (Brazil) and UPI (India) are instant, near-free, bank-native rails that card networks cannot compete with locally. Route buyers to them wherever possible.
- Payout timing, payout currency, and sub-merchant KYC differ meaningfully across gateways and reshape marketplace cashflow and compliance posture.
- Webhooks arrive imperfectly everywhere. Verify signature, store raw, process idempotently, reconcile nightly — the same discipline regardless of provider.
- Don't add the second gateway on day one. Wait for a region to clear 10% of attempted volume with sub-par conversion before paying the integration cost.