QR Pay
Personal
Business
Create QR payment
QR PAY is a dynamic QR code generated per order with a built-in payment confirmation.
For each generated payment QR code, a virtual account number is also created and linked to a corresponding order.
When the customer makes a payment to this virtual account, the associated order is automatically marked as successfully paid.
When the customer pays to the virtual account number with the exact amount or exact amount and description,
Cas will confirm that your order has been paid.
Your system will receive a webhook of type TRANSACTIONS,
and the paymentMeta will contain the referenceNumber value associated with the QR Pay created earlier.
Steps to Integrate QR Pay
Below are the steps to integrate QR Pay into your product.
-
Create a grant
/grant/tokenwithscopesset toqrpay.- user (optional): the customer information already stored in your system, used to prefill the linking form on Cas Link and to validate it against the bank account information. See details
-
Open the Cas Link interface using the
grantTokenreturned in the previous step.See details -
After the user completes the authentication, your frontend will receive a
publicToken, which you can use to obtain anaccessTokenfor the grant. -
Once you have the
accessToken, call theGet QR Pay Account Identity APIto verify if the account is valid.
If the account is invalid, you should call the/grant/remove APIto revoke the grant. -
You can now call the
Create QR Pay API. -
Generate the QR code from the
qrCodefield in the response and display it in your interface.
To simplify generating VietQR codes, you can use theQuicklink from vietqr.ioto generate the QR code and embed the link into your system. -
Handle the order status in your system when receiving a transaction
webhook,
and thereferenceNumberin thepaymentMetafrom the webhook corresponds to your internal order ID.
Customer information (user)
user is an optional field when creating a grant. If your system already stores the customer's information, send it so that Cas Link can:
- Validate the bank account: Cas Link compares the information you send with the account information returned by the bank. If the account holder name or the identification number does not match, the linking flow is stopped and an error is shown to the user.
- Prefill the linking form: Cas Link fills in the account holder name, identification number, phone number and email, so the user does not have to re-enter what you already have.
| Field | Type | Description |
|---|---|---|
legalName | string | Account holder name (individual) |
idNumber | string | Personal identification number (ID card) of the account holder |
companyName | string | Company name |
companyLegalId | string | Tax code / business registration number |
mobileNumber | string | Phone number registered with the bank |
email | string | Customer email |
Depending on whether the financial service is of type personal or enterprise, Cas Link compares either
legalName/idNumber or companyName/companyLegalId. Any field you omit is skipped during the comparison.
Call API
Create Grant Token for QR Pay
- CURL
- Javascript (Axios)
curl --location 'https://sandbox.bankhub.dev/grant/token' \
--header 'X-BankHub-Api-Version: 2023-01-01' \
--header 'x-client-id: <CLIENT_ID_HERE>' \
--header 'x-secret-key: <SECRET_KEY_HERE>' \
--header 'Content-Type: application/json' \
--data '{
"scopes": "qrpay",
"language": "vi",
"redirectUri": "https://your-domain.vn/link",
"user": {
"legalName": "NGUYEN VAN A",
"idNumber": "079201000123",
"mobileNumber": "0901234567",
"email": "nguyenvana@gmail.com"
}
}'
const axios = require('axios');
const data = JSON.stringify({
"scopes": "qrpay",
"language": "vi",
"redirectUri": "https://your-domain.vn/link",
"user": {
"legalName": "NGUYEN VAN A",
"idNumber": "079201000123",
"mobileNumber": "0901234567",
"email": "nguyenvana@gmail.com"
}
});
const config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://sandbox.bankhub.dev/grant/token',
headers: {
'X-BankHub-Api-Version': '2023-01-01',
'x-client-id': '<CLIENT_ID_HERE>',
'x-secret-key': '<SECRET_KEY_HERE>',
'Content-Type': 'application/json'
},
data: data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
For detail API, here
Get accessToken from publicToken
- CURL
- Javascript (Axios)
curl --location 'https://sandbox.bankhub.dev/grant/exchange' \
--header 'X-BankHub-Api-Version: 2023-01-01' \
--header 'x-client-id: <CLIENT_ID_HERE>' \
--header 'x-secret-key: <SECRET_KEY_HERE>' \
--header 'Content-Type: application/json' \
--data '{
"publicToken": "bdbde2bad-7685-4f95-987c-71309a4a3"
}'
const axios = require('axios');
const data = JSON.stringify({
"publicToken": "bdbde2bad-7685-4f95-987c-71309a4a3"
});
const config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://sandbox.bankhub.dev/grant/exchange',
headers: {
'X-BankHub-Api-Version': '2023-01-01',
'x-client-id': '<CLIENT_ID_HERE>',
'x-secret-key': '<SECRET_KEY_HERE>',
'Content-Type': 'application/json'
},
data: data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
For detail API, here
Retrieve the Identity Information of the Account for QR Pay Creation
- CURL
- Javascript (Axios)
curl --location 'https://sandbox.bankhub.dev/qr-pay/identity' \
--header 'X-BankHub-Api-Version: 2023-01-01' \
--header 'Authorization: <ACCESS_TOKEN_HERE>' \
--header 'x-client-id: <CLIENT_ID_HERE>' \
--header 'x-secret-key: <SECRET_KEY_HERE>'
const axios = require('axios');
const config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://sandbox.bankhub.dev/qr-pay/identity',
headers: {
'X-BankHub-Api-Version': '2023-01-01',
'Authorization': '<ACCESS_TOKEN_HERE>',
'x-client-id': '<CLIENT_ID_HERE>',
'x-secret-key': '<SECRET_KEY_HERE>''
}
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
For detail API, here
Create QR Pay
- CURL
- Javascript (Axios)
curl --location 'https://sandbox.bankhub.dev/qr-pay' \
--header 'X-BankHub-Api-Version: 2023-01-01' \
--header 'Authorization: <ACCESS_TOKEN_HERE>' \
--header 'x-client-id: <CLIENT_ID_HERE>' \
--header 'x-secret-key: <SECRET_KEY_HERE>'
--data '{
"amount": 2000,
"description": "cassotest",
"referenceNumber": "1234455811acbc"
}'
const axios = require('axios');
const data = JSON.stringify({
"amount": 2000,
"description": "cassotest",
"referenceNumber": "1234455811acbc"
});
const config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://sandbox.bankhub.dev/qr-pay',
headers: {
'X-BankHub-Api-Version': '2023-01-01',
'Authorization': '<ACCESS_TOKEN_HERE>',
'x-client-id': '<CLIENT_ID_HERE>',
'x-secret-key': '<SECRET_KEY_HERE>'
},
data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
For detail API, here