NEW PayNext Extra Installment QR
Topics covered on this page
PayNext Extra Installment QR
Accept offline installment payments from TrueMoney Wallet users through your point-of-sale (POS) system using the PayNext Extra Installment QR payment method.
ð Overview
| Property | Value |
|---|---|
| Payment method | PayNext Extra Installment QR |
| Source type | installment_paynext_extra_qr |
| Payment flow | offline |
| Supported countries | Thailand |
| Currency | THB |
| Minimum amount | No minimum |
| Maximum amount | āļŋ5,000.00 (500000) |
| Minimum API version | 2017-11-02 |
â How to enable PayNext Extra Installment QR
To enable PayNext Extra Installment QR for your account, email support@omise.co to request the feature. You will be required to review and accept updated terms and conditions before the payment method is activated.
ð Payment flow
PayNext Extra Installment QR uses an offline payment flow. Once the charge is created, your POS terminal displays a QR code which the customer scans using their TrueMoney Wallet app. Authorization happens entirely offline â there is no browser redirect.

Important: There are two separate expiry windows to be aware of: - Source expiry: If the customer does not scan the QR code within the time allowed, the source expires and the charge becomes
expired. - Charge expiry: If the charge is not completed within 1 day of creation (seeexpires_atin the charge response), it expires automatically.These are independent. Build your retry logic to handle both: display a new QR code for a scan timeout; treat a 1-day expiry as an abandoned order.
The payment flow proceeds as follows:
- The customer selects PayNext Extra Installment QR as their payment method at the POS terminal.
- Your POS system generates and displays a QR code.
- The customer opens the TrueMoney Wallet app and scans the QR code.
- The customer selects their preferred installment term and interest rate.
- A payment summary is displayed for review.
- The customer confirms the payment.
âïļ Implementation
To accept a PayNext Extra Installment QR payment, complete the following steps:
- Create a source â Create a new payment source with
type: installment_paynext_extra_qrusing Omise.js or a mobile SDK (iOS / Android). - Create a charge â Create a new charge using the source identifier returned in Step 1. The charge response contains the QR code image.
- Display the QR code â Extract the QR code from
source.scannable_code.image.download_uriin the charge response and display it on the POS terminal. - Verify the charge â After receiving the
charge.completewebhook event, retrieve the charge to confirm its status (optional but recommended).
Use your public key to create the source (client-side). Use your secret key to create the charge (server-side).
If source creation and charge creation must both happen server-side, you can combine them into a single API request using your secret key.
Step 1 â Creating a source
When the customer confirms they want to pay with PayNext Extra Installment QR, create a new source with the following parameters.
| Parameter | Type | Required | Description |
|---|---|---|---|
amount |
integer | Yes | Payment amount in subunits. Maximum 500000 (āļŋ5,000.00). No minimum. See Limits. |
currency |
string | Yes | Must be THB. |
type |
string | Yes | Must be installment_paynext_extra_qr. |
promotion_code |
string | No | A promotional code provided by TrueMoney. |
The following examples create a new PayNext Extra Installment QR source for āļŋ500.00 (50000). Replace omise_public_key / $OMISE_PUBLIC_KEY with your test public key from your dashboard.
In Omise.js,
typeis passed as the first argument tocreateSource.
Omise.js
Omise.setPublicKey(omise_public_key);
Omise.createSource('installment_paynext_extra_qr', {
"amount": 50000,
"currency": "THB"
}, function(statusCode, response) {
console.log(response);
});
cURL
curl https://api.omise.co/sources \
-u $OMISE_PUBLIC_KEY: \
-d "amount=50000" \
-d "currency=THB" \
-d "type=installment_paynext_extra_qr"
Example response
{
"object": "source",
"id": "src_test_601oy3f2u9m8llki4eh",
"livemode": false,
"location": "/sources/src_test_601oy3f2u9m8llki4eh",
"amount": 50000,
"currency": "THB",
"flow": "offline",
"type": "installment_paynext_extra_qr",
"charge_status": "unknown",
"created_at": "2024-06-11T01:52:37Z",
"barcode": null,
"bank": null,
"email": null,
"installment_term": null,
"ip": "35.198.236.178",
"absorption_type": null,
"name": null,
"mobile_number": null,
"phone_number": null,
"platform_type": null,
"scannable_code": null,
"billing": null,
"shipping": null,
"items": [],
"references": null,
"provider_references": null,
"store_id": null,
"store_name": null,
"terminal_id": null,
"zero_interest_installments": null,
"receipt_amount": null,
"discounts": [],
"promotion_code": null
}
The id field (prefixed src_) is the source identifier used in the following step.
Notable response fields
| Field | Description |
|---|---|
installment_term |
null at source creation. The customer selects their installment term after scanning the QR code in the TrueMoney Wallet app. Do not expect or validate this value at this stage. |
scannable_code |
null at source creation. The QR code is populated here once the charge is created. See Displaying the QR code. |
absorption_type |
Controls whether the merchant or the customer absorbs the installment interest. null indicates the default configured for your account. Contact support@omise.co if you need to change the absorption behaviour. |
charge_status |
Reflects the status of any charge associated with this source. unknown at source creation; updates to pending once a charge is created. |
Step 2 â Creating a charge
Create a charge using the source identifier from Step 1.
| Parameter | Type | Required | Description |
|---|---|---|---|
amount |
integer | Yes | Must match the amount of the source. |
currency |
string | Yes | Must match the currency of the source. |
source |
string | Yes | The source id returned in Step 1. |
return_uri |
string | No | URL to redirect the customer to after payment completion. |
Replace $OMISE_SECRET_KEY with your test secret key from your dashboard and $SOURCE_ID with the id of the source.
cURL
curl https://api.omise.co/charges \
-u $OMISE_SECRET_KEY: \
-d "amount=50000" \
-d "currency=THB" \
-d "return_uri=http://example.com/orders/345678/complete" \
-d "source=$SOURCE_ID"
Example response
{
"object": "charge",
"id": "chrg_test_601oy3hvu3uq3nq3tyd",
"location": "/charges/chrg_test_601oy3hvu3uq3nq3tyd",
"amount": 50000,
"currency": "THB",
"funding_currency": "THB",
"funding_amount": 50000,
"net": 48047,
"fee": 1825,
"fee_vat": 128,
"interest": 0,
"interest_vat": 0,
"refunded_amount": 0,
"transaction_fees": {
"fee_flat": "0.0",
"fee_rate": "3.65",
"vat_rate": "7.0"
},
"status": "pending",
"authorize_uri": "https://pay.omise.co/payments/pay2_test_601oy3hxhpyo26m91kh/authorize",
"return_uri": "http://example.com/orders/345678/complete",
"source": {
"object": "source",
"id": "src_test_601oy2ze4198tfx1qme",
"livemode": false,
"amount": 50000,
"currency": "THB",
"flow": "offline",
"type": "installment_paynext_extra_qr",
"charge_status": "pending",
"scannable_code": {
"object": "barcode",
"type": "qr",
"image": {
"object": "document",
"livemode": false,
"id": "docu_test_601oy3k3ijlgvs0a2d8",
"deleted": false,
"filename": "qrcode.png",
"location": "/charges/chrg_test_601oy3hvu3uq3nq3tyd/documents/docu_test_601oy3k3ijlgvs0a2d8",
"kind": "qr",
"download_uri": "https://api.omise.co/charges/chrg_test_601oy3hvu3uq3nq3tyd/documents/docu_test_601oy3k3ijlgvs0a2d8/downloads/9F489F5C90D7AD27",
"created_at": "2024-06-11T01:52:38Z"
}
},
"provider_references": {
"reference_number_1": "pay2_test_601oy3hxhpyo26m91kh",
"reference_number_2": null
}
},
"authorized": false,
"capturable": false,
"capture": true,
"paid": false,
"expired": false,
"reversed": false,
"reversible": false,
"refundable": false,
"partially_refundable": false,
"disputable": false,
"voided": false,
"can_perform_void": false,
"livemode": false,
"created_at": "2024-06-11T01:52:38Z",
"paid_at": null,
"expires_at": "2024-06-12T01:52:38Z"
}
Notable response fields
| Field | Description |
|---|---|
source.scannable_code.image.download_uri |
The URL of the QR code image to display on your POS terminal. Fetch and render this image immediately after the charge is created. The URL requires authentication with your secret key. |
expires_at |
The datetime at which the charge automatically expires if not completed. For PayNext Extra Installment QR this is 1 day after creation. |
source.provider_references.reference_number_1 |
A TrueMoney-issued transaction reference number. Retain this value â it is required when raising support tickets or performing reconciliation with TrueMoney. reference_number_2 is not used for this payment method and will always be null. |
net |
The amount that will be settled to your account after fees and VAT are deducted. |
Creating a source and charge in a single request
If both source creation and charge creation must happen server-side, you can combine them into a single API call using your secret key.
curl https://api.omise.co/charges \
-u $OMISE_SECRET_KEY: \
-d "amount=50000" \
-d "currency=THB" \
-d "return_uri=http://example.com/orders/345678/complete" \
-d "source[type]=installment_paynext_extra_qr"
Step 3 â Completing the charge
The charge is created with a status of pending. The following sections explain how to display the QR code, receive the webhook event, and confirm the final charge status.
Full payment sequence
Authorising the charge
Extract the QR code URL from the charge response and display it on your POS terminal:
charge
âââ source
âââ scannable_code
âââ image
âââ download_uri â QR code image URL
Fetch the image from download_uri using your secret key and render it at the POS terminal. The customer then scans the QR code with their TrueMoney Wallet app to complete the payment.
Testing: In test mode, go to the specific charge on the Omise dashboard, click Actions, and manually mark the charge as Successful or Failed. Use this to verify your webhook handler before going live.
Receiving the charge completion webhook
Set up an endpoint on your server to receive webhook events, and register it on the Omise dashboard. Omise sends a charge.complete event when the charge reaches a final status.
Verifying the charge status
After receiving the charge.complete webhook, retrieve the charge by its id and confirm that the status in the retrieved charge matches the status in the webhook event.
| Status | Meaning |
|---|---|
successful |
Payment was received. |
failed |
Payment failed. Check failure_code and failure_message for details. |
expired |
The charge was not completed within the allowed time. |
Possible failure codes
| Failure code | Description |
|---|---|
failed_processing |
General payment processing failure. |
âĐïļ Voids and refunds
- Voids: A PayNext Extra Installment QR charge can only be voided on the same day as the transaction authorisation.
- Refunds: Refunds can only be issued within 30 days of a successful payment.
For refund instructions, see the Refunds API documentation.
ð Limits
| Amount (subunits) | Amount (THB) | |
|---|---|---|
| Minimum | None | No minimum |
| Maximum | 500000 |
āļŋ5,000.00 |
ð§ Troubleshooting
The charge status is expired
There are two causes:
- Scan timeout: The customer did not scan the QR code within the allowed time. Display a new QR code by creating a new source and charge.
- 1-day charge timeout: The charge was not completed within 1 day of creation (see
expires_atin the charge response). This typically indicates an abandoned order. No retry is necessary unless the customer returns.
The charge status is failed with failure_code: failed_processing
A general processing failure occurred on the TrueMoney side. Prompt the customer to retry the payment. If the issue persists, contact support@omise.co.
The customer was redirected to return_uri but the charge is still pending
Do not rely solely on the return_uri redirect to determine charge status. Always wait for the charge.complete webhook event and verify the charge status by retrieving it from the API.
The QR code is not displaying
Confirm that your POS system is fetching the image from source.scannable_code.image.download_uri in the charge response. This field is null at source creation and only populated once the charge is created. Also confirm the request is authenticated with your secret key.
The amount is rejected with a validation error
Confirm the amount does not exceed the maximum of 500000 (āļŋ5,000.00). There is no minimum. Also confirm the amount and currency values on the charge request exactly match those on the source.
The promotion_code field has no effect
Promotional codes are issued by TrueMoney and must be valid and active at the time of source creation. Contact TrueMoney directly to verify that the code is active and applicable to your transaction.
â Frequently asked questions
Which countries and currencies does PayNext Extra Installment QR support? PayNext Extra Installment QR is supported in Thailand only and processes payments in Thai Baht (THB).
Does the customer need a TrueMoney Wallet account? Yes. The customer must have an active TrueMoney Wallet account to scan the QR code and complete the payment.
What is the difference between PayNext Extra Installment QR and PayNext Extra Installment App Redirection? PayNext Extra Installment QR is designed for offline POS environments. Your terminal displays a QR code that the customer scans. PayNext Extra Installment App Redirection is designed for online checkouts, where the customer is redirected to TrueMoney Wallet via their browser or the app. QR charges expire after 1 day; App Redirection charges expire after 7 days.
Where is the QR code in the API response?
The QR code image URL is at source.scannable_code.image.download_uri inside the charge response. It is null at source creation and only populated after the charge is created.
What happens if the customer does not scan the QR code in time?
The charge status becomes expired. Create a new source and charge to generate a fresh QR code.
Can I use this payment method without Omise.js? Yes. If both source creation and charge creation occur on your server, you can use the single-request approach with your secret key â no client-side SDK required. See Creating a source and charge in a single request.
Can I refund a PayNext Extra Installment QR charge? Yes, refunds are supported within 30 days of a successful payment. Voids are only possible on the same day as the transaction. See the Refunds API documentation.
How do I test this integration? Use your test public and secret keys from the Omise dashboard. After creating a charge, go to the charge on the dashboard, click Actions, and manually mark it as Successful or Failed.
Where can I find my API keys? See How to access Omise API keys.
ð API keys
For information on how to obtain your public and secret keys, see How to access Omise API keys.