When payment orchestration makes sense, how to implement PSP routing, and practical patterns for failover and optimization.
Payment orchestration is the practice of routing transactions through multiple payment service providers based on rules, performance data, and business logic. Instead of being locked into a single PSP, you create an abstraction layer that can send each transaction to the optimal provider.
Create a common interface that each PSP implementation satisfies:
interface PaymentGateway {
public function createPayment(PaymentRequest $request): PaymentResponse;
public function getPayment(string $id): PaymentStatus;
public function refund(string $id, int $amount): RefundResponse;
}
class MollieGateway implements PaymentGateway { /* ... */ }
class StripeGateway implements PaymentGateway { /* ... */ }
class AdyenGateway implements PaymentGateway { /* ... */ }
A router decides which gateway handles each transaction:
class PaymentRouter {
public function route(PaymentRequest $request): PaymentGateway {
// Country-based routing
if ($request->country === 'NL' && $request->method === 'ideal') {
return app(MollieGateway::class);
}
// Cost optimization
if ($request->amount > 50000) {
return $this->lowestCostProvider($request);
}
// Performance-based routing
return $this->highestAcceptanceProvider($request);
}
}
When a PSP returns an error or times out, automatically retry with a different provider:
class PaymentOrchestrator {
public function process(PaymentRequest $request): PaymentResponse {
$providers = $this->router->ranked($request);
foreach ($providers as $provider) {
try {
$response = $provider->createPayment($request);
if ($response->isSuccessful()) {
return $response;
}
} catch (GatewayTimeoutException $e) {
$this->metrics->recordFailover($provider, $request);
continue;
}
}
throw new PaymentFailedException('All providers failed');
}
}
Cost-based: Route to the cheapest PSP for each transaction type. Requires tracking per-transaction costs including interchange, scheme fees, and PSP markup.
Performance-based: Route to the PSP with the highest acceptance rate for the specific card type, country, and amount combination. Requires collecting and analyzing acceptance data.
Availability-based: Simple failover. Use primary PSP, switch to secondary when primary is down.
Market-based: Route to the PSP with the best local payment method coverage per country.
For effective orchestration, track per transaction:
Aggregate this data to build routing intelligence. Without it, you are guessing.
Payment orchestration is powerful but complex. Start with simple failover, add market-based routing when you expand across borders, and only invest in dynamic optimization when your transaction volume makes the engineering investment worthwhile.
Whether you're modernizing your infrastructure, navigating compliance, or building new software - we can help.
Book a 30-min Call