Indochina Bank QR
Create Indochina Bank QR payments and handle the outcome.
Current availability
TEST simulates payments without contacting a bank. LIVE creation requires approved, unexpired KYC and an enabled bank merchant configuration for the requested method. Each request must fit its currency amount range. Bank callback verification, polling and LIVE cancellation remain unavailable pending bank authentication implementation; creation alone does not confirm settlement.
Flow
Step 1
Your server signs the creation request.
Step 2
Vantra returns PENDING and payment identifiers.
Step 3
TEST: open the portal simulator. LIVE, once enabled: display the QR or supported deep link.
Step 4
Receive and verify the callback; reconcile the order before fulfillment.
Create a payment
POST /api/v1/payments/generate-ib-qr
Use HMAC headers. Idempotency-Key is optional; the examples omit it. Supply your orderId to detect duplicate orders. Example JSON body:
{
"amount": 10000,
"currency": "LAK",
"orderId": "order-20261110-0001",
"description": "Order payment",
"metadata": {
"shopId": "SHOP-01",
"customerId": "CUSTOMER-42",
"remark": "Pickup order"
}
}metadata is an optional JSON object for extra information from your application, such as a shop ID, customer reference, or order note. Put your custom fields inside metadata, as shown above. You can omit the entire field when you have no extra data; it is not required to generate a QR.
If you choose to use the optional Idempotency-Key, when retrying with the same key, send the same request data, including metadata. Changing metadata with an existing key returns 409 Conflict.
Render the returned qrCode string with a QR encoder. Use a returned deep link only if present. Bank-reference inquiry needs a reference actually recorded from bank callback evidence; it is not a bank status refresh.
Using the request helper from the authentication guide:
Preview, copy, or download vantra-client.mjs for Node.js/Express/Next.js and vantra_client.py for Python. For Next.js, place the JavaScript helper in src/lib/. Express/Next.js examples require your own orders adapters; they are integration templates, not complete checkout applications. Use the request fields above in attempt.body. Install Express with npm install express; run standalone scripts with node create-payment.mjs or python3 create_payment.py. Keep credentials in server environment variables.
import { gatewayRequest } from './vantra-client.mjs';
// Supply your order ID so the gateway can detect duplicate orders.
const payment = await gatewayRequest({
origin: process.env.VANTRA_API_ORIGIN,
apiKey: process.env.VANTRA_API_KEY,
secret: process.env.VANTRA_API_SECRET,
path: '/api/v1/payments/generate-ib-qr',
data: {
"amount": 10000,
"currency": "LAK",
"orderId": "order-20261110-0001",
"description": "Order payment"
},
});
console.log(payment);Handle the response
Read data.transactionId, data.status, and data.environment. For TEST, use the returned deepLink or paymentUrl to open Sandbox; the QR is synthetic. The provider implementation for future LIVE support returns qrCode, optional deepLink, and expiredAt; the provider response also defines deepLinks.coolpay and deepLinks.iblaos. Always use the returned expiration value.
Do not fulfill on creation or browser return. Follow callback handling and status/reconciliation.
TEST response example
HTTP 201 Created. This is the full HTTP envelope; gatewayRequest() returns only its data object. IDs, URLs, timestamps, and QR values below are illustrative. Replace the portal domain for your deployment.
{
"success": true,
"title": "CREATED",
"message": "Simulated payment created; no funds move",
"timestamp": "2026-11-10T05:00:00.000Z",
"data": {
"transactionId": "TEST-EXAMPLE-A1B2C3D4",
"referenceId": "INV-202611-01234",
"externalRef": "ABCD1234",
"orderId": "order-20261110-0001",
"status": "PENDING",
"environment": "TEST",
"amount": 10000,
"currency": "LAK",
"paymentMethod": "INDOCHINA_BANK_QR",
"qrCode": "GATEWAY_TEST:31ea4910-e8b9-45a8-b539-4c0addf01614",
"deepLink": "https://portal.example.com/en/sandbox?transaction=31ea4910-e8b9-45a8-b539-4c0addf01614",
"paymentUrl": "https://portal.example.com/en/sandbox?transaction=31ea4910-e8b9-45a8-b539-4c0addf01614",
"expiredAt": "2026-11-10T05:15:00.000Z",
"simulationId": "31ea4910-e8b9-45a8-b539-4c0addf01614"
}
}Responses differ by payment method
The envelope is shared, but the fields inside data depend on the method and environment. Card payments use paymentUrl; QR and wallet payments use qrCode and may include deepLink. Indochina QR can also include deepLinks. Optional fields can be absent. TEST uses a common simulated response, even for cards; do not infer the LIVE shape from it.
Future LIVE response shape
Illustrative provider response only; settlement verification remains unavailable. These URLs and tokens are not usable, optional fields are shown when present, and expiry/message text can vary by provider and configuration. simulationId is TEST-only. LIVE creation does not return a status token.
{
"success": true,
"title": "CREATED",
"message": "QR Code generated successfully",
"timestamp": "2026-11-10T05:00:00.000Z",
"data": {
"transactionId": "TXN-EXAMPLE",
"referenceId": "INV-202611-01234",
"orderId": "order-20261110-0001",
"status": "PENDING",
"amount": 10000,
"currency": "LAK",
"paymentMethod": "INDOCHINA_BANK_QR",
"qrCode": "PROVIDER_QR_PAYLOAD_EXAMPLE",
"deepLink": "https://provider.example.com/pay/example",
"deepLinks": {
"coolpay": "coolpay://qr/#/PROVIDER_QR_PAYLOAD_EXAMPLE",
"iblaos": "https://www.iblaos.com/qr/?code=PROVIDER_QR_PAYLOAD_EXAMPLE"
},
"expiredAt": "2026-11-10T05:15:00.000Z",
"environment": "LIVE"
}
}Sandbox payment app
The planned Vantra sandbox app will act like a bank payment app for testing only: open or scan a supported test payment, review it, and simulate a payment outcome. This APK/PWA flow is not implemented yet and will not move real funds. For now, open the returned portal simulator link and choose an outcome there.
See sandbox app and testing for the current and planned flows.