> ## Documentation Index
> Fetch the complete documentation index at: https://developer.tazapay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# mobilebanking_thb

### How It Works

#### On Mobile

1. The buyer selects Mobile Banking at checkout and chooses their bank.
2. They are automatically deep-linked into their bank's mobile app.
3. The buyer authenticates and approves the payment inside the app.
4. Once approved, the buyer is returned to the merchant's app or browser.

#### On Desktop

1. The buyer selects Mobile Banking at checkout and chooses their bank (KTB, KMA, KPlus, or SCB).
2. A QR code is displayed on the checkout page.
3. The buyer scans the QR code using their phone's camera or QR scanner.
4. The bank's mobile app opens on their phone, where they authenticate and approve the payment.
5. Once approved, the desktop page updates to confirm the payment.

#### Payment Expiry

The expiry timer starts once the payment attempt is made. The expiry time applies to both the QR code and deep-link flows.

| Bank            | Expiry Time |
| --------------- | ----------- |
| KPlus (KBank)   | 10 minutes  |
| SCB             | 15 minutes  |
| KMA (Krungthai) | 15 minutes  |
| KTB (Krungthai) | 15 minutes  |

If the session expires, the buyer will need to restart the payment.

# Integrating on your website / application

## Step 1: Create a payin

Tazapay uses a `payin` object to represent your intent to collect a payment from your customer. The payin object tracks state changes from transaction creation to payment completion via mobile banking.\
Create a payin on your server with an amount, invoice\_currency `THB` and a transaction\_description using the [create payin API](https://developer.tazapay.com/API-Reference/tazapay-api/payin/create-payin)

A payin is created with the status `requires_payment_method`.

### Sample cURL

```json theme={null}
curl --request POST \
     --url https://service-sandbox.tazapay.com/v3/payin \
     --header 'accept: application/json' \
     --header 'authorization: Basic xxxxxxxXXXXxxxxxxxxxxxxxxxxx' \
     --header 'content-type: application/json' \
     --data '
{
  "invoice_currency": "THB",
  "amount": 10000,
  "transaction_description": "Test",
}
'
```

## Step 2: Confirm a payin

Confirm the payin created in step 1 using the confirm payin API. Upon confirmation of the payin, a redirect URL is generated to redirect the customer. The status of the payin moves to `requires_action`

Refer the below for the fields to be passed in `payment_method_details`

| Field      | Type   | Mandatory (Y/N) | Description                                                                           |
| ---------- | ------ | --------------- | ------------------------------------------------------------------------------------- |
| type       | string | Y               | `mobilebanking_thb`                                                                   |
| bank\_name | string | Y               | Bank code for the customer's mobile banking app. One of: `ktb`, `kma`, `kplus`, `scb` |

The following top-level fields are also required for `mobilebanking_thb`:

| Field          | Type   | Mandatory (Y/N) | Description                                                              |
| -------------- | ------ | --------------- | ------------------------------------------------------------------------ |
| mobile\_number | string | Y               | Customer's mobile number in thai mobile-no format (e.g. `+664673826278`) |
| session\_id    | string | Y               | Session ID retrieved from the Risk SDK                                   |

### Sample cURL

```json theme={null}
curl --request POST \
     --url https://service-sandbox.tazapay.com/v3/payin/pay_cttprok2ukmk385sbfm0/confirm \
     --header 'accept: application/json' \
     --header 'authorization: Basic xxxxxxxXXXXxxxxxxxxxxxxxxxxx' \
     --header 'content-type: application/json' \
     --data '
{
  "customer_details": {
    "name": "Andrea Lark",
    "email": "andrea@example.com",
    "country": "TH"
  },
  "payment_method_details": {
    "type": "mobilebanking_thb",
    "bank_name": "ktb",
  },
  "mobile_number" : "+664673826278",
  "session_id": "<session_id>"
}
'
```

### Combining Steps 1 and 2 into a single step

Instead of making 2 API calls, you can also combine steps 1 and 2 into a single API call. To do so, pass the parameters in both the create payin and confirm payin endpoints to the create payin API.

Also, pass the following field and set the field to ‘true’

| Field   | type    | Mandatory (Y/N) | Description                              |
| ------- | ------- | --------------- | ---------------------------------------- |
| confirm | boolean | Y               | To confirm the payin along with creation |

### Sample cURL

```json theme={null}
curl --request POST \
     --url https://service-sandbox.tazapay.com/v3/payin \
     --header 'accept: application/json' \
     --header 'authorization: Basic xxxxxxxXXXXxxxxxxxxxxxxxxxxx' \
     --header 'content-type: application/json' \
     --data '
{
  "customer_details": {
    "name": "Andrea Lark",
    "email": "andrea@example.com",
    "country": "TH"
  },
  "confirm": true,
  "invoice_currency": "THB",
  "amount": 10000,
  "transaction_description": "test",
  "payment_method_details": {
    "type": "mobilebanking_thb",
    "bank_name": "ktb",
  },
  "mobile_number": "+664673826278",
  "session_id": "<session_id>"
}
'
```

## Step 3: Handle the confirm payin response

The confirm payin response differs based on the customer's device type. Tazapay determines the device from the context of the request.

### Desktop

For desktop sessions, the response includes a `qr_code` field inside `latest_payment_attempt_data`. You must render this QR code on your checkout page. The customer then scans the QR code using their mobile banking app to complete the payment.

```json theme={null}
{
  "status": "success",
  "data": {
    ...
    "latest_payment_attempt_data": {
      "expires_at": "2025-01-15T10:35:05Z",
      "qr_code": "<base64-encoded-qr-image-or-qr-string>"
    },
    "status": "requires_action"
  }
}
```

> Render the `latest_payment_attempt_data.qr_code` value as a QR code image on your checkout page. The customer scans this with their mobile banking app.

### Mobile

For mobile sessions, the response includes a `deep_link` field inside `latest_payment_attempt_data`. Since the customer has already provided their mobile number, you only need to redirect them to this deep link. It takes the customer directly into their mobile banking app to authorise and complete the payment.

```json theme={null}
{
  "status": "success",
  "data": {
    ...
    "latest_payment_attempt_data": {
      "expires_at": "2025-01-15T10:35:05Z",
      "deep_link": "bankapp://pay?ref=MIykUpsyrxRgjWOu1U5csBzZOqk9RaNPzDhMMDErEgc="
    },
    "status": "requires_action"
  }
}
```

> Redirect the customer to `latest_payment_attempt_data.deep_link` to take them directly into their mobile banking app to complete the payment.

### Full response example

```json theme={null}
{
  "status": "success",
  "message": "",
  "data": {
    "amount": 10000,
    "amount_paid": 0,
    "billing_details": {
      "address": null,
      "label": "",
      "name": "",
      "phone": null
    },
    "cancel_url": "",
    "cancelled_at": null,
    "client_token": "MIykUpsyrxRgjWOu1U5csBzZOqk9RaNPzDhMMDErEgc=",
    "confirm": true,
    "created_at": "2025-01-15T10:27:09.896074Z",
    "customer": "cus_cu3osb970g0h95qr5c00",
    "customer_details": {
      "country": "TH",
      "email": "andrea@example.com",
      "name": "Andrea Lark",
      "phone": {
        "calling_code": "",
        "number": ""
      }
    },
    "form": "",
    "holding_currency": "USD",
    "id": "pay_cu3oqvd3t210o3k432k0",
    "invoice_currency": "THB",
    "items": [],
    "latest_payment_attempt": "pat_cu3osbd3t210o3k434f0",
    "latest_payment_attempt_data": {
      "expires_at": "2025-01-15T10:35:05Z",
      "deep_link": "bankapp://pay?ref=MIykUpsyrxRgjWOu1U5csBzZOqk9RaNPzDhMMDErEgc="
    },
    "metadata": null,
    "object": "payin",
    "paid_in_excess": false,
    "partially_paid": false,
    "payment_attempts": [],
    "payment_method_details": {
      "type": "mobilebanking_thb"
    },
    "redirect_url": "https://checkout-sandbox.tazapay.com/simulate/MIykUpsyrxRgjWOu1U5csBzZOqk9RaNPzDhMMDErEgc=/pay_cu3oqvd3t210o3k432k0/mobilebanking_thb",
    "reference_id": "",
    "shipping_details": {
      "address": null,
      "label": "",
      "name": "",
      "phone": null
    },
    "statement_descriptor": "",
    "status": "requires_action",
    "status_description": "",
    "success_url": "",
    "transaction_data": [],
    "transaction_description": "test",
    "transaction_documents": [],
    "webhook_url": ""
  }
}
```

## Step 4: Handle post-payment events

Tazapay sends a `payin.succeeded` event as soon as the funds are received from the customer.  Tazapay sends these events to the endpoint configured from your dashboard. You can receive these events and run actions (for example, sending an order confirmation email to your customers, logging the sale in a database, starting a shipping workflow, etc.)

If the payment is not made by the customer and the URL expires, Tazapay sends a `payment_attempt.failed`  event. To generate a new URL, confirm the payin again using Step 2.

| Event                   | Description                                   | Next Steps                                                                                  |
| ----------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------- |
| payin.succeeded         | The customer paid before 30 days              | Fulfill the goods or services that the customer purchased                                   |
| payment\_attempt.failed | The customer did not pay, and the URL expired | Allow the customer to generate a new URL or complete the payment via another payment method |

# Test the Integration

## Simulating success

Click on `Simulate Success` CTA on the redirect\_url. You will receive a `payin.succeeded` event.

## Simulating Failure / Expiry

Click on  `Simulate Expire` CTA on the redirect\_url. You will receive a `payment_attempt.failed` event.

# Integrating Refunds

**Refund is not supported.**
