# Tabby for mobile app
Accept Tabby payments on your app with [Flow for mobile](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app.md), our pre-built, customizable payment user interface that you can embed directly into your mobile application. Flow enables you to accept payments using Checkout.com’s global network of payment methods with a single integration.
---
## How it works
1. The customer opens the checkout screen.
2. When you load the page, you perform a server-side request to create a payment session.
3. You use the payment session data on the client side to create and render Flow for mobile.
4. Flow for mobile displays the available payment methods to the customer. If the customer's chosen payment method requires additional customer data, Flow captures the data from the customer.
5. When the customer taps _Pay_, Flow for mobile performs a payment request and handles any additional actions required. For example, third-party payment page redirects.
6. You receive a webhook notifying you of the payment status.
---
## Before you start
Make sure you have a [test account](https://www.checkout.com/get-test-account) with Checkout.com.
Create a [public key and a secret key](https://www.checkout.com/docs/resources/api-authentication/api-keys.md) from the [Dashboard](https://dashboard.checkout.com), with the following key scopes:
- Public key – `payment-sessions:pay` and `vault-tokenization`
- Secret key – `payment-sessions`
To receive webhooks for the [payment events](https://www.checkout.com/docs/developer-resources/event-notifications/event-types.md#Gateway), [configure your webhook server](https://www.checkout.com/docs/developer-resources/event-notifications/receive-webhooks/configure-your-webhook-server.md).
Integrate with [Flow for mobile](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app/get-started-with-flow-for-mobile.md) before continuing.
Ensure your merchant account has Tabby enabled. To enable Tabby, contact your account manager or [request support](https://dashboard.checkout.com/support/new?topic=case_account_management_and_access&issue=issue_account_changes).
---
## Add the SDK dependency
**Android**
In your project-level `build.gradle`, add the following repositories:
```gradle
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
maven { url = uri("https://maven.fpregistry.io/releases") }
}
```
In your app-level `build.gradle`, add the following dependency:
```gradle
dependencies {
implementation 'com.checkout:checkout-android-components:$latest_version'
implementation('com.checkout:checkout-android-components-payment-methods-redirect:$latest_version')
}
}
```
**iOS**
To add payment methods to your iOS app, enable the `CheckoutPaymentMethods` plugin.
If you have already added the `checkout-ios-components` package:
1. In Xcode, select your project, then select the _Package Dependencies_ tab.
2. Find `checkout-ios-components` and select the pencil icon to edit it.
3. Select `CheckoutPaymentMethods` in the product list and confirm.
If you are adding the package for the first time:
1. Select _File_ > _Add Package Dependencies_.
2. Enter the `checkout-ios-components` repository URL.
3. Select both `CheckoutComponents` and `CheckoutPaymentMethods` from the product list.
4. Select _Add Package_.
---
## Create a new payment session `Server side`
When the customer is ready to pay, send a server-side request to securely create a `PaymentSession` object. The `PaymentSession` contains the information required to handle all steps of the payment flow.
> **Note**
>
> Do not embed your secret key in your client-side code.
Call the [Create a Payment Session](https://api-reference.checkout.com/tag/Flow/#operation/CreatePaymentSession) endpoint.
> **Information**
>
> Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md).
**Production**
`POST` `https://{prefix}.api.checkout.com/payment-sessions`
**Sandbox**
`POST` `https://{prefix}.api.sandbox.checkout.com/payment-sessions`
### Request example
```json
{
"amount": 1000,
"currency": "AED",
"reference": "ORDER_01234",
"billing": {
"address": {
"country": "AE"
},
"phone": {
"country_code": "971",
"number": "500000001"
}
},
"shipping": {
"address": {
"address_line1": "Building No. 22",
"city": "Dubai",
"zip": "00000",
"country": "AE"
},
"phone": {
"country_code": "971",
"number": "500000001"
}
},
"customer": {
"name": "Jia Tsang",
"email": "jia.tsang@example.com"
},
"items": [
{
"name": "Gold Necklace",
"quantity": 1,
"unit_price": 1000
}
],
"success_url": "https://example.com/payments/success",
"failure_url": "https://example.com/payments/failure"
}
```
In the request body, provide the following:
| Field | Description |
| --- | --- |
| `currency` | The three-letter ISO 4217 [currency code](https://www.checkout.com/docs/developer-resources/codes/currency-codes.md). Must be one of:
- `SAR`
- `AED`
- `KWD`.
**Required** |
| `customer.name` | The customer's name.
**Required** |
| `customer.email` | The customer's email address.
**Required** |
| `billing.address` | The customer's billing address.
**Required** |
| `billing.phone` | The customer's billing phone number, required for KSA compliance.
**Required** |
| `shipping.address` | The customer's shipping address.
**Required** |
| `shipping.phone` | The customer's shipping phone number.
**Required** |
| `reference` | A reference shown to the customer in the Tabby checkout page. |
| `description` | The description of the order. |
| `items` | Items to show in the Tabby checkout page. |
### Response example
```json
{
"id": "ps_2Un6I6lRpIAiIEwQIyxWVnV9CqQ",
"payment_session_secret": "pss_e21237b4-214a-4e35-a35d-f33wkwo158f6"
}
```
The payment session response also determines which payment methods can be displayed to the customer. The response is determined by the customer's device and region.
---
## Enable Tabby in Flow for mobile
Enable Tabby in Flow for mobile when creating a `CheckoutComponents` instance.
**Android**
Pass `Tabby.NAME` when creating a flow or standalone component. `Tabby.NAME` is a pre-built `PaymentMethodName("tabby")` constant exposed by the SDK:
```kotlin
import com.checkout.components.paymentmethods.redirect.tabby.Tabby
// Include Tabby in a Flow component (renders all available payment methods)
val flow = checkoutComponents.create(ComponentName.Flow)
// Or create a standalone Tabby component
val tabbyComponent = checkoutComponents.create(Tabby.NAME)
```
Tabby only renders when the backend payment session includes it in `supportedPaymentMethods`. Creating the component when the session does not support it has no effect.
Render the component in Compose UI with `Render()` or in a View container with `provideView()`:
```kotlin
// Compose
tabbyComponent.Render()
// View
tabbyComponent.provideView(containerView)
```
If the session body does not satisfy Tabby's eligibility rules, the method is not returned in `supportedPaymentMethods` and does not render, even if you pass it in the `Tabby.NAME` constant when creating the component.
**iOS**
Pass the providers you want to support to the `providers:` parameter when you create a flow component:
```swift
import CheckoutComponents
import CheckoutPaymentMethods
let configuration = try await CheckoutComponents.Configuration(
paymentSession: session,
publicKey: "pk_...",
environment: .sandbox,
callbacks: callbacks
)
let sdk = CheckoutComponents(configuration: configuration)
let flow = try sdk.create(
.flow(
options: [
.card(),
.applePay(merchantIdentifier: "merchant.com.example")
],
providers: [CheckoutPaymentMethods.Provider.tabby]
)
)
```
Additionally, if you only want to render Tabby, you can create a standalone Tabby component:
```swift
import CheckoutComponents
import CheckoutPaymentMethods
let configuration = try await CheckoutComponents.Configuration(
paymentSession: session,
publicKey: "pk_...",
environment: .sandbox,
callbacks: callbacks
)
let sdk = CheckoutComponents(configuration: configuration)
let tabby = try sdk.create(CheckoutPaymentMethods.Provider.tabby)
```
If the session body does not satisfy Tabby's eligibility rules, the method is not returned in `supportedPaymentMethods` and does not render, even if you pass it in the `providers:` array when creating the component.
---
## Handle the payment response `Client side`
Depending on the payment outcome, Checkout.com redirects the customer to the `success_url` or `failure_url` you specified when you created the `PaymentSession`.
We send you a webhook notifying you of changes to the payment's status. Wait for the webhook callback before you start your order fulfillment process.
For payments submitted with Flow, the `PaymentSession` ID appears in the webhook payload's `data.metadata.cko_payment_session_id` field.
**Android**
You can listen to the existing `onSuccess` [callback](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app/flow-for-mobile-library-reference/android/componentcallback.md#onSuccess(PaymentMethodComponent,_PaymentId)) or `onError` [callback](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app/flow-for-mobile-library-reference/android/componentcallback.md#onError(PaymentMethodComponent,_CheckoutError)) to handle the payment response for Tabby payments, alongside card and Google Pay outcomes:
```kotlin
val configuration = CheckoutComponentConfiguration(
context = context,
paymentSession = PaymentSessionResponse(
id = paymentSessionID,
paymentSessionToken = paymentSessionToken,
paymentSessionSecret = paymentSessionSecret,
),
publicKey = "pk_...",
environment = Environment.SANDBOX, // or Environment.PRODUCTION
componentCallback = object : ComponentCallback {
override fun onSuccess(component: Component, paymentID: String) {
// Payment completed — navigate to confirmation screen
}
override fun onError(component: Component, error: CheckoutError) {
// Payment declined, failed, or cancelled — show error UI
}
}
)
```
**iOS**
You can listen to the existing `onSuccess` [callback](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app/flow-for-mobile-library-reference/ios/componentcallback.md#onSuccess(Describable,_PaymentID)) or `onError` [callback](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app/flow-for-mobile-library-reference/ios/componentcallback.md#onError(CheckoutComponents.Error)) to handle the payment response for Tabby payments, alongside card and Apple Pay outcomes:
```swift
let callbacks = CheckoutComponents.Callbacks(
onSuccess: { component, paymentID in
// Payment completed — navigate to confirmation screen
},
onError: { error in
// Payment declined or failed — show error UI
}
)
```
If the customer dismisses the redirect, Flow does not trigger any callback.
---
## Next steps
**[Customize Flow for mobile](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app/get-started-with-flow-for-mobile.md)**
Learn how to customize Flow for mobile.
**[Flow for mobile library reference](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app/flow-for-mobile-library-reference.md)**
See the configuration options and error handling steps for Flow for mobile.