Search
K

Thanh toán Transaction QR

Giới thiệu dịch vụ

Là giải pháp hỗ trợ cho các đơn vị kinh doanh, đối tác thanh toán qua các thiết bị có thể hiển thị mã QR hoá đơn (máy POS/ web/ app/ in hoá đơn…)
Khi khởi tạo hóa đơn, đối tác gửi thông tin đến hệ thống VinID Pay để tạo mã. Khách hàng sử dụng tính năng “Quét mã” trên ứng dụng VinID để quét mã do nhân viên cửa hàng cung cấp và tiến hành thanh toán mà không cần nhập thêm bất cứ thông tin nào.
Để sử dụng Transaction QR, đối tác có thể lựa chọn 1 trong 2 phương án như sau:
  • Chủ động tích hợp với hệ thống thanh toán VinID Pay.
  • Sử dụng máy POS của các đối tác đã tích hợp thanh toán với VinID Pay như KiotViet, mPOS, iPOS.

Luồng người dùng sử dụng dịch vụ

Luồng người dùng sử dụng dịch vụ Transaction QR trên ứng dụng VinID

Trải nghiệm tính năng thanh toán

Trải nghiệm tính năng thanh toán Transaction QR bằng ví điện tử VinID tại đây

Sequence diagram

APIs

post
{API-HOST}/merchant-integration/v1/orders/
tqr
Generate Transaction QR
//REQUEST TEMPLATE
{
"callback_url": "string",
"description": "string",
"expired_in": 0,
"extra_data": "string",
"order_amount": 0,
"order_currency": "string",
"order_reference_id": "string",
"pos_code": "string",
"service_type": "string",
"store_code": "string"
}
The old endpoint of this API is deprecated.
{API-HOST}/merchant-integration/v1/qr/gen-transaction-qr
Although we will keep it work, but we recommend merchants should move to the new one ASAP.
Please note that the order_reference_id is no more optional in the new endpoint. You should input a unique value every request to make sure the refund process can work correctly.
Thông tin thêm:

Thông tin mã lỗi

Tham khảo Mã lỗi chung

Code mẫu

PHP
C#
Java
function getSign($url, $method, $nonce, $timestamp, $keyCode, $requestBody, $pem_private_key)
{
$data = $url.";".$method.";".$nonce.";".$timestamp.";".$keyCode.";".$requestBody;
try {
$p = openssl_pkey_get_private($pem_private_key);
$signSuccess = openssl_sign($data, $signature, $p, OPENSSL_ALGO_SHA256);
if (!$signSuccess) {
print("False");
return "";
}
$encodedSignature = base64_encode($signature);
openssl_free_key($p);
return $encodedSignature;
} catch (Exception $e) {
print_r($e->getMessage());
}
}
$url = '/merchant-integration/v1/qr/gen-transaction-qr';
$method = 'POST';
$timestamp = time();
$nonce = (string)$timestamp;
$params = [
'callback_url' => 'http://merchant-site/vinid/result',
'description' => 'test qr code',
'extra_data' => '',
'order_amount' => '1000',
'order_currency' => 'VND',
'order_reference_id' => 'merchant-order-id-01',
'pos_code' => 'merchant-pos-code',
'service_type' => 'PURCHASE',
'store_code' => 'merchant-store-code'
];
$requestBody = json_encode($params);
$apiKey = 'Your api key';
$privateKey = 'Your private key';
$sign = getSign($url, $method, $nonce, $timestamp, $apiKey, $requestBody, $privateKey);
$headers = [
'Accept: application/json',
'Content-Type: application/json',
'X-Key-Code: '.$apiKey,
'X-Nonce: '.$nonce,
'X-Timestamp: '.$timestamp,
'X-Signature: '.$sign,
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api-merchant-sandbox.vinid.dev'.$url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
curl_close($ch);
print_r($result);
return $result;
( Đang cập nhật )
import com.google.gson.Gson;
//The method that signs the data using the private key that is stored in keyFile path
public String generateSign(String url, String method, String nonce, String timestamp, String keyCode, String requestBody, String keyFile) throws Exception {
String body = requestBody == null || "".equals(requestBody) ? "" : requestBody;
String data = url + ";" + method + ";" + nonce + ";" + timestamp + ";" + keyCode + ";" + body;
java.security.Signature rsa = java.security.Signature.getInstance("SHA256withRSA");
rsa.initSign(getPrivate(keyFile));
rsa.update(data.getBytes());
return new String(Base64.getEncoder().encode(rsa.sign()));
}
//Method to retrieve the Private Key from a file
private PrivateKey getPrivate(String filename) throws Exception {
byte[] keyBytes = Files.readAllBytes(new File(filename).toPath());
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
// Generate Transaction QR
public static void main(String... args){
String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
UUID uuid = UUID.randomUUID();
String nonce = uuid.toString();
String host = "https://api-merchant-sandbox.vinid.dev";
String url = "/merchant-integration/v1/qr/gen-transaction-qr";
String method = "POST";
String sig = generateSign(url, method, nonce, timeStamp, "your-key-code-here", getJsonSerdes().toJson(reqBody)), "/path/to/private-key");
Map<String, String> headers = new HashMap<>();
headers.put("X-Key-Code", callCtx.getKeyCode());
headers.put("X-Nonce", nonce);
headers.put("X-Timestamp", timeStamp);
headers.put("X-Signature", sig);
HttpClient httpClient = new HttpClient.HttpClientBuilder()
.setEndpoint(host + url)
.setMethod(method)
.setHeader(headers)
.setBody(reqBody)
.build();
System.out.println(httpClient.response());
}