Mobile SDKs

Accept payments inside your Android, iOS or Flutter app. The SDK opens the same YallaPay checkout your customers already know — cards, Apple Pay and Google Pay — as a sheet inside your app, and hands you a result you can trust.

What the SDK is, and is not

The YallaPay SDK is a small library that presents a payment sheet inside your app and tells you, reliably, whether the customer paid. It is deliberately narrow:

  • It presents checkout. Card entry, Apple Pay, Google Pay and 3-D Secure all happen on a YallaPay-hosted page shown as a sheet over your screen. Card numbers never enter your app, so your app stays out of PCI scope.
  • It confirms the outcome. When the sheet closes, the SDK asks the YallaPay API what happened and returns one of three results: completed, cancelled, or failed. It never trusts the browser redirect on its own.
  • It survives interruptions. If the operating system kills your app while the customer is paying, the next launch can recover the payment instead of losing it.
  • It does not create payments. Creating a payment needs your secret key, and a secret key inside an app is public. Your own server creates the payment session; your app only presents it.

An integration is therefore two halves: a few lines on your server, and a few lines in your app. This documentation covers both, plus the dashboard settings that make them work.

Native or Flutter?

There are three SDKs. Pick the one that matches how your app is built.

Which one is for you
Your app is written in Kotlin or Java Use the native Android SDK. Java callers can use it too: every entry point is annotated for Java, and the suspending calls can be driven from a coroutine scope.
Your app is written in Swift or Objective-C Use the native iOS SDK. It offers async/await and a completion-handler variant for UIKit code.
Your app is written in Flutter Use the Flutter plugin. It ships the native SDKs inside it, so you never touch Kotlin or Swift; you only declare a return scheme on each platform.
Your app is React Native, Ionic, or a website There is no SDK for these yet. Create a session from your server and open its checkout URL in the system browser or a web view; the customer is returned to your return URL when they finish. Payments through API

All three SDKs share one API, one vocabulary and one set of results. Everything on this page applies to all of them.

How a payment works

Three things happen, in this order:

1. Your server   POST /api/v1/sessions      →  session_id
2. Your app      YallaPay.pay(session_id)   →  customer pays in the sheet
3. Your server   webhook arrives           →  you fulfil the order

In more detail, this is what passes between your app, your server and YallaPay for one payment:

Customer taps Pay in your app
  │
  ├─► Your app asks your server to start a payment
  │     └─► Your server calls POST /api/v1/sessions with the secret key
  │           └─► YallaPay answers with a session_id (cs_live_…)
  │
  ├─► Your app calls YallaPay.pay(session_id)
  │     ├─ SDK reads the session with the publishable key
  │     ├─ SDK opens the checkout sheet
  │     ├─ Customer pays (card, Apple Pay, Google Pay, 3-D Secure)
  │     ├─ Checkout returns to your app through your return URL
  │     └─ SDK re-reads the session, then returns Completed / Canceled / Failed
  │
  └─► YallaPay signs and POSTs a webhook to your server
        └─► Your server verifies the signature and fulfils the order

Two details matter more than they look:

  • The SDK result is read back from the YallaPay API, not inferred from the redirect. A Completed result means the server agrees the session is paid.
  • Even so, your app is the wrong place to ship goods from. Fulfil on the webhook, on your server, where nobody can tamper with the answer.

Your two keys

Find both under Apps & Return URLs in your dashboard.

Keys
pk_live_… Publishable. Goes in your app. It can read the status of a payment whose id it already knows, and nothing else.
sk_live_… Secret. Server-side only. It creates payments and signs your webhooks, so anyone holding it can take money as you.

On the sandbox the same two keys are issued with pk_test_ and sk_test_ prefixes. A key only works on the host that issued it.

Never put your secret key in an app.

An APK or IPA can be unzipped by anyone who downloads it. A secret key inside one is a secret key in public. The SDKs refuse a key beginning with sk_ for this reason.

What you need before you start

  • A YallaPay merchant account that can take payments. Your account must be approved and active. Until then, creating a session returns merchant_not_approved.
  • Your two API keys. Copied from Apps & Return URLs.
  • A return target registered for your app. A URL scheme such as myapp for mobile apps, or a host for websites. Sessions with an unregistered return URL are refused.
  • A webhook endpoint on your server. This is where you fulfil orders. Configure it once under Webhooks.
  • A sandbox account for testing. Optional but strongly recommended. Sandbox is a separate deployment with its own signup, keys and test cards.

Each of these is explained step by step on the Dashboard setup page.

The 15-minute path

The shortest route from nothing to a completed test payment.

  1. Register a return target Dashboard → Apps & Return URLs → Add return target. Platform: your app. Scheme: myapp. Copy the publishable and secret keys while you are there.
  2. Create a session from your server
    curl -X POST "https://yallapay.net/api/v1/sessions" \
      -H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: order-881-attempt-1" \
      -d '{
        "amount": 250.00,
        "currency": "AED",
        "purpose": "Order #881",
        "external_id": "881",
        "return_url": "myapp://yallapay/return"
      }'
    The response carries a session_id. Send it to your app.
  3. Install the SDK and pay Add the dependency, declare the myapp scheme, call configure once with the publishable key, then:
    // Android
    when (val result = YallaPay.pay(activity, sessionId)) {
        is PaymentResult.Completed -> order.markPaid(result.transactionId)
        is PaymentResult.Canceled  -> showCancelled()
        is PaymentResult.Failed    -> showError(result.error.message)
    }
    The iOS and Flutter calls are the same shape.
  4. Handle the webhook Verify the X-YallaPay-Signature header, then mark the order paid. Your server is the source of truth.
  5. Recover interrupted payments On every app launch, check PendingSessionStore and call sessionStatus for anything left there. Two lines, and the one step most integrations forget.

Every SDK returns the same three outcomes:

Results
Completed YallaPay confirmed the session is paid. Carries the transaction id and the payment method (card, Apple Pay or Google Pay).
Canceled The customer closed checkout without paying. Nothing was charged. Your app may offer to try again with the same session while it is still open.
Failed Something went wrong: the payment was declined, the session expired, the key was rejected, or the network dropped. Carries an error code and a message you can show.
A network error is not a failed payment.

If the SDK could not reach YallaPay after checkout closed, the customer may still have paid. Treat that error as "unknown", and call sessionStatus again before telling the customer anything final.

The security model

It helps to know why the pieces are shaped the way they are.

Design decisions
Two keys, two audiences The secret key creates sessions and never leaves your server. The publishable key reads a session and is safe in an app binary. Extracting it from your app yields the ability to read the status of payments whose ids are already known, and nothing more.
The session id is the client token A session id is long, random, single-use and locked to one amount. Nothing a client can do with it changes what will be charged.
Hosted checkout Card details are entered on a YallaPay page, shown as a sheet inside your app. Your app never sees a card number, which keeps you at the lightest PCI level, and Apple Pay, Google Pay and 3-D Secure work because they run in a real browser context.
The redirect is a hint, not an answer Checkout returns the customer to your return URL with a status and a signature. The SDK ignores those values and asks the API instead. Your server may verify the signature to trust a return before the webhook arrives.
No processor identity, ever Results describe the payment method the customer used, never which acquirer settled it. Which processor sits behind a payment is a YallaPay concern, and it can change without affecting your integration.
Fulfil on the webhook The webhook is signed with your secret key and carries a timestamp. Verify it, then ship. A phone can be lied to; your server cannot.

Where everything is

This documentation
Dashboard setup Account approval, keys, return targets, webhook endpoint, sandbox account. Do this first.
Server integration Creating and reading sessions: every field, idempotency, errors, examples in curl, PHP, Node and Python.
Android SDK Kotlin. Install, return scheme, configure, pay, interrupted payments, errors, reference.
iOS SDK Swift. Install, return scheme, configure, pay, Apple Pay, interrupted payments, errors, reference.
Flutter SDK Dart. Install, per-platform setup, configure, pay, interrupted payments, errors, reference.
Webhooks & fulfilment The signed webhook, the signed return URL, and how to verify both in PHP, Node and Python.
Sandbox & go-live Environments, test cards, an end-to-end test checklist, the go-live checklist, and troubleshooting.
Not building an app?

Websites use the same session API and open the checkout URL directly; see Payments through API. WooCommerce stores have a ready-made plugin; see WordPress Plugin.