Tạo tài khoản ảo (VA)
API này dùng để tạo mới tài khoản ảo (Virtual Account - VA) cho Merchant, cho phép nhận thông báo biến động số dư và quản lý dòng tiền tách biệt.
POST
URLhttps://uat-open-api.tingee.vn/v1/create-va
API khởi tạo yêu cầu tạo hoặc liên kết tài khoản ảo với ngân hàng. Kết quả trả về confirmId cần được dùng cho bước xác nhận tiếp theo.
Header Request
| Header | Bắt buộc | Mô tả |
|---|---|---|
Content-Type | ✓ | application/json |
x-client-id | ✓ | Mã định danh của đối tác do TINGEE cung cấp. |
x-signature | ✓ | Chữ ký xác thực HMAC SHA512. Xem thêm tại Cách sinh chữ ký. |
x-request-timestamp | ✓ | Thời gian gửi request (format: yyyyMMddHHmmssSSS, múi giờ UTC+7) |
Body Parameter
| Trường | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
merchantId | number | ✕ | ID của Merchant (Bắt buộc nếu kết nối bằng tài khoản Master Merchant). |
accountType | string | ✓ | Loại tài khoản (personal-account, business-account, business-household-account). |
bankBin | string | ✓ | Mã BIN ngân hàng. Xem tại Danh sách ngân hàng hỗ trợ. |
accountNumber | string | ✓ | Số tài khoản ngân hàng muốn liên kết. |
accountName | string | ✓ | Tên chủ tài khoản. |
identity | string | ✓ | GTTT của khách hàng (CMND/CCCD hoặc Mã số thuế). |
mobile | string | ✓ | Số điện thoại đăng ký (Tùy theo yêu cầu từng ngân hàng). |
isNotifyAccountNumber | boolean | ✕ | true nếu muốn liên kết STK gốc, mặc định false để tạo STK ảo. |
Ví dụ mã nguồn
- cURL
- NestJS
- C#
- Java
- PHP
curl --location --request POST 'https://uat-open-api.tingee.vn/v1/create-va' \
--header 'accept: application/json' \
--header 'x-signature: YOUR_SIGNATURE' \
--header 'x-request-timestamp: 20250723142001111' \
--header 'x-client-id: YOUR_CLIENT_ID' \
--header 'Content-Type: application/json' \
--data '{
"isNotifyAccountNumber": false,
"accountType": "personal-account",
"bankBin": "970418",
"accountNumber": "0935926988",
"accountName": "NGUYEN THI HUYEN",
"identity": "040191014068",
"mobile": "0123456789"
}'
import axios from "axios";
import { createHmac } from "crypto";
import { format } from 'date-fns';
async function createVA() {
const body = {
isNotifyAccountNumber: false,
accountType: 'personal-account',
bankBin: '970418',
accountNumber: '0935926988',
accountName: 'NGUYEN THI HUYEN',
identity: '040191014068',
mobile: '0123456789'
};
const timestamp = format(new Date(), "yyyyMMddHHmmssSSS");
const secretKey = "YOUR_SECRET_KEY";
const message = `${timestamp}:${JSON.stringify(body)}`;
const signature = createHmac('sha512', secretKey).update(message).digest('hex');
const res = await axios.post('https://uat-open-api.tingee.vn/v1/create-va', body, {
headers: {
accept: 'application/json',
'x-signature': signature,
'x-request-timestamp': timestamp,
'x-client-id': 'YOUR_CLIENT_ID',
'Content-Type': 'application/json',
},
});
console.log(res.data);
}
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Security.Cryptography;
using System.Threading.Tasks;
public class CreateVAExample
{
private static readonly HttpClient client = new HttpClient();
public static async Task Main()
{
var body = new {
isNotifyAccountNumber = false,
accountType = "personal-account",
bankBin = "970418",
accountNumber = "0935926988",
accountName = "NGUYEN THI HUYEN",
identity = "040191014068",
mobile = "0123456789"
};
var timestamp = DateTime.Now.ToString("yyyyMMddHHmmssfff");
var secretKey = "YOUR_SECRET_KEY";
var bodyJson = JsonSerializer.Serialize(body);
var message = $"{timestamp}:{bodyJson}";
var signature = CreateHmacSha512(secretKey, message);
var request = new HttpRequestMessage(HttpMethod.Post, "https://uat-open-api.tingee.vn/v1/create-va");
request.Headers.Add("x-signature", signature);
request.Headers.Add("x-request-timestamp", timestamp);
request.Headers.Add("x-client-id", "YOUR_CLIENT_ID");
request.Content = new StringContent(bodyJson, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
private static string CreateHmacSha512(string key, string message)
{
using var hmac = new HMACSHA512(Encoding.UTF8.GetBytes(key));
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}
import java.net.http.*;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class CreateVA {
public static void main(String[] args) throws Exception {
String bodyJson = "{\"isNotifyAccountNumber\":false,\"accountType\":\"personal-account\",\"bankBin\":\"970418\",\"accountNumber\":\"0935926988\",\"accountName\":\"NGUYEN THI HUYEN\",\"identity\":\"040191014068\",\"mobile\":\"0123456789\"}";
String secretKey = "YOUR_SECRET_KEY";
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
String message = timestamp + ":" + bodyJson;
String signature = hmacSha512(secretKey, message);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://uat-open-api.tingee.vn/v1/create-va"))
.header("accept", "application/json")
.header("x-signature", signature)
.header("x-request-timestamp", timestamp)
.header("x-client-id", "YOUR_CLIENT_ID")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(bodyJson))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
private static String hmacSha512(String key, String data) throws Exception {
Mac mac = Mac.getInstance("HmacSHA512");
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA512");
mac.init(secretKeySpec);
byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
return toHex(hash);
}
private static String toHex(byte[] bytes) {
StringBuilder hex = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
hex.append(String.format("%02x", b));
}
return hex.toString();
}
}
function createVA() {
$body = [
"isNotifyAccountNumber" => false,
"accountType" => "personal-account",
"bankBin" => "970418",
"accountNumber" => "0935926988",
"accountName" => "NGUYEN THI HUYEN",
"identity" => "040191014068",
"mobile" => "0123456789"
];
$jsonBody = json_encode($body);
$timestamp = date("YmdHis") . substr((string)microtime(true), -3);
$secretKey = "YOUR_SECRET_KEY";
$message = $timestamp . ":" . $jsonBody;
$signature = hash_hmac("sha512", $message, $secretKey);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://uat-open-api.tingee.vn/v1/create-va",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $jsonBody,
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Content-Type: application/json",
"x-client-id: YOUR_CLIENT_ID",
"x-request-timestamp: " . $timestamp,
"x-signature: " . $signature
]
]);
$response = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);
if ($err) {
echo "cURL Error: " . $err;
} else {
echo $response;
}
}
Response mẫu
{
"code": "00",
"message": "Success",
"data": {
"confirmId": "VA_CONFIRM_123456"
}
}
| Trường | Kiểu | Mô tả |
|---|---|---|
code | string | Mã kết quả (00 = Thành công). |
message | string | Thông điệp phản hồi. |
data.confirmId | string | Mã xác nhận cần dùng cho API confirm-va. |
Mã lỗi thường gặp
| Code | Mô tả | Hướng xử lý |
|---|---|---|
90 | Sai format timestamp | Kiểm tra format yyyyMMddHHmmssSSS. |
91 | Request quá hạn | Kiểm tra thời gian gửi request. |
97 | Sai chữ ký | Kiểm tra lại Secret Key và logic tạo Signature. |
Others | Lỗi khác | Xem Danh sách mã lỗi. |