External Payments
A single externalPayment call routes to tabby, tamara, hosted checkout, or SADAD. Pick the provider via ExternalPaymentMethod; the SDK derives the API path, paymentType, and body shape, and canonicalises the response so your code reads the same keys everywhere.
Overview
One entry point — externalPayment(ExternalPaymentRequest) — covers four external providers. The provider is selected by ExternalPaymentMethod; the SDK fills in the request path, paymentType, and the correct body shape (flat for tabby / tamara / checkout, nested for SADAD).
| Provider | ExternalPaymentMethod | Shape |
|---|---|---|
| Tabby | TABBY (Flutter/Swift: .tabby) | Flat — phoneNumber, email, additionalData |
| Tamara | TAMARA / .tamara | Flat |
| Hosted checkout | CHECKOUT / .checkout | Flat |
| SADAD | SADAD / .sadad | Nested — customerDetails, address, invoice |
Amount units differ
The top-level amount is in MINOR units (e.g. 5000 for SAR 50.00). InvoiceDto / LineItemDto amounts are in MAJOR units (50.0). Keep them consistent — the gateway reconciles both sides.
Flat Shape (tabby / tamara / checkout)
For tabby, tamara, and hosted checkout, supply the order id, amount (minor units), currency, phone, email, and optionally additionalData (e.g. storeId). Open the returned checkoutDeeplink in a WebView / Custom Tab to complete the payment.
Loading...Nested Shape (SADAD)
SADAD uses the nested shape — pass customerDetails (a CustomerDto / Customer). The SDK auto-fills address with a SA / Riyadh default when omitted, sets issueDate to today, and computes expireDate as today + expiryInMinutes (default 7 days = 10 080 minutes). InvoiceDto amounts are in major units.
Loading...Optional fields default sensibly
Omit address to let the SDK fill a SA / Riyadh default; omit invoice to send a single zero-priced placeholder line item; omit expiryInMinutes for a 7-day bill. Show the returned sadadNumber / billNumber to the payer so they can settle in their banking app.
Unified Response
The response is a JsonObject / Map with the same keys regardless of provider — the SDK canonicalises per-provider aliases (e.g. tabby sessionId → checkoutId, tabby paymentId → paymentGatewayTransactionId, link checkout redirectUrl → checkoutDeeplink).
| Field | Tabby | Tamara | Checkout | SADAD |
|---|---|---|---|---|
| paymentMethod | tabby | tamara | checkout | sadad |
| checkoutDeeplink | ✅ | ✅ | ✅ | — |
| checkoutId | ✅ | ✅ | — | — |
| transactionId | ✅ | ✅ | ✅ | ✅ |
| paymentGatewayTransactionId | ✅ | ✅ | — | — |
| sadadNumber / billNumber | — | — | — | ✅ |
| status | ✅ | ✅ | ✅ | ✅ |
Checking Final Status
The externalPayment response only confirms the provider session was created — the customer has not paid yet. Settlement happens after they redirect to the provider or pay the SADAD bill, and the SDK is not in the loop for that step. Always verify the FINAL status with a query helper before fulfilling the order.
Loading...Never treat the session as proof of payment
For tabby / tamara / checkout, after the WebView is dismissed, call getTransactionByOrderId(orderId) or getTransactionById(paymentGatewayTransactionId). For SADAD, poll on a backoff (or rely on a server webhook) until the row is APPROVED. Never retry externalPayment for the same orderId without querying first — duplicate sessions can cause duplicate charges.
On this page
Downloads
Coming SoonSample apps, release bundles, and more content will be available here soon.