EdfaPay Logo

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).

ProviderExternalPaymentMethodShape
TabbyTABBY (Flutter/Swift: .tabby)Flat — phoneNumber, email, additionalData
TamaraTAMARA / .tamaraFlat
Hosted checkoutCHECKOUT / .checkoutFlat
SADADSADAD / .sadadNested — 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).

FieldTabbyTamaraCheckoutSADAD
paymentMethodtabbytamaracheckoutsadad
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.