Article

How We Built a Multi-Provider Booking Platform with 3 Payment Gateways

Three payment gateways, multiple booking providers, and cancellation policies that had to be transparent. Here's how we built Omraty's travel booking platform.

June 23, 2026
7 min read

Travel booking platforms have a problem that most software doesn't: the product you're selling isn't yours. You're an intermediary between the customer and the provider — the hotel, the transport company, the tour operator. Your platform's job is to make that intermediation invisible.

When Omraty came to us, they wanted exactly that: a booking platform for Umrah travel packages where customers see a clean, unified search experience, but behind the scenes, the system pulls availability and pricing from multiple external providers, each with their own APIs, rate structures, and cancellation policies.

Six months and a three-person team later, the platform was live. Here's what made this project technically interesting — and what we'd do differently.

The real challenge wasn't building a booking system

Building a booking flow — search, select, pay, confirm — is well-understood. The hard part was everything behind it.

Multiple providers with different behaviors. Each provider's API works differently. One returns prices in real time. Another caches prices and updates hourly. One supports instant confirmation. Another requires a manual step. Our platform needed to present a consistent experience regardless of which provider was fulfilling the booking.

Three payment gateways. Stripe for international cards. PayPal for customers who prefer it. Mada for Saudi domestic payments. Each gateway has its own integration pattern, webhook structure, and reconciliation flow. A failed payment on one gateway shouldn't block the booking — the customer should retry on another.

Cancellation policies that had to be transparent. Each provider has different cancellation windows and refund percentages. The platform needed to display these clearly during the booking flow, not bury them in terms and conditions.

The architecture

We built a provider-agnostic service layer. The booking engine doesn't know which provider is fulfilling a booking — it works with a standardized internal model. Each provider has an adapter that translates between the provider's API and our internal format.

Laravel backend — handles the booking engine, payment orchestration, admin tools, and all business logic. The service layer pattern was essential: BookingService works with ProviderAdapterInterface, and each provider implements that interface differently.

Next.js frontend — handles the customer-facing search, booking flow, and account management. Server-side rendering was important for SEO on search result pages.

The key decision was treating providers as plugins. Adding a new provider means writing a new adapter — not changing the booking engine. This paid off when the client added a second hotel provider three months after launch.

What made the integration hard

Rate and availability caching

You can't call a provider's API for every search query — you'll hit rate limits instantly and response times would be unacceptable. But you can't cache prices too long or customers see stale rates and get angry at checkout.

We built a background sync system that pulls availability on a schedule, caches it locally, and marks the cache age so the frontend shows "prices updated X minutes ago." At booking time, we do a real-time verification against the provider. If the price changed, the customer sees the update before confirming — no surprises.

Payment reconciliation across gateways

Three gateways means three webhook formats, three timing behaviors for confirmations, and three approaches to refunds. We normalized everything through a payment service that translates each gateway's events into internal states: pending, confirmed, failed, refunded. The booking engine only knows about these internal states — it never touches gateway-specific logic.

Adding a payment gateway follows the same pattern as adding a provider: write an adapter, implement the interface.

Cancellation and refund logic

Cancellation seems simple until you account for different refund percentages based on timing, partial cancellations, refunds to the original payment method, and provider-side fees that don't match what the customer was charged.

We built a cancellation engine that calculates the refund based on the provider's policy, applies it to the correct payment transaction, and handles the accounting automatically. The admin dashboard shows the full breakdown so operations staff can verify and override if needed.

What the admin side looks like

The operations team needed to manage bookings without understanding provider APIs. The admin panel provides booking review with full audit trail, refund processing with automatic calculation and manual override, customer communication tools, provider-level reporting and reconciliation, and alerts for failed syncs or provider downtime.

One principle guided admin design: hide the provider complexity. Operations works with bookings, customers, and payments — never with API calls or webhook payloads.

What we learned

Hide provider complexity behind stable services. The adapter pattern isn't exotic architecture — it's survival. When a provider changes their API, you update one file, not the entire booking flow.

Show policy details early in the customer journey. Cancellation rules shown at checkout feel like gotchas. The same information during search feels like transparency. We moved cancellation display to search results, and support tickets about "unexpected" policies dropped.

Reconciliation jobs keep finance tidy. Automated nightly reconciliation between our records and each provider catches discrepancies before they become problems. This saved hours of manual checking weekly.

Background syncs and caching reduce delays. Real-time API calls for every search is a recipe for slow pages. Cache aggressively, sync in the background, verify at the point of commitment.

The result

Omraty launched with a unified booking experience across providers, transparent rate options and cancellation rules, admin workflows for review, refunds, and reports, and performance improvements through caching and background syncs.

For the full project details, read the complete Omraty case study.

Building a platform with complex integrations?

Multi-provider platforms, payment orchestration, and booking systems share the same core challenge: making complexity invisible to the end user. We've written about how long these projects take, how we price them, and what maintenance looks like after launch.

Have a platform that needs to integrate with external providers? Let's talk architecture →

Enjoyed this article?

Subscribe to our newsletter for more insights and stay updated with the latest in technology