Đăng ký nhận biến động ghi nợ
API này dùng để đăng ký nhận thông báo giao dịch ghi nợ (tiền ra) trên số tài khoản gốc ACB. Sau khi đăng ký thành công, mỗi khi tài khoản phát sinh giao dịch trừ tiền, TINGEE sẽ gửi Webhook về hệ thống của đối tác.
Phạm vi áp dụng
- Chỉ hỗ trợ ngân hàng ACB (
bankBin = "970416"), áp dụng cho tài khoản Cá nhân, Hộ kinh doanh và Doanh nghiệp. - API đăng ký trên số tài khoản gốc, không tạo tài khoản ảo (VA).
- Nếu số tài khoản đã đăng ký nhận biến động ghi có (tạo bằng Tạo/Liên kết số tài khoản với
isNotifyAccountNumber = true), hệ thống sẽ chuyển đăng ký sang nhận cả ghi có và ghi nợ.
Quy trình
- Gọi API này để gửi yêu cầu đăng ký. Ngân hàng ACB gửi mã OTP tới số điện thoại
mobilecủa chủ tài khoản, kết quả trả vềconfirmId. - Gọi API Xác nhận số tài khoản với
confirmIdvàotpNumberđể hoàn tất.confirmIdcó hiệu lực trong 4 phút.
POST
URLhttps://open-api.tingee.vn/v1/create-debit
Khởi tạo yêu cầu đăng ký nhận biến động ghi nợ trên tài khoản ACB. Kết quả trả về confirmId dùng cho bước xác nhận OTP.
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ả |
|---|---|---|---|
bankBin | string | ✓ | Truyền cố định 970416 (ACB). |
accountType | string | ✓ | Loại tài khoản: personal-account, business-account, business-household-account. |
accountNumber | string | ✓ | Số tài khoản ACB cần đăng ký. |
accountName | string | ✓ | Tên chủ tài khoản (viết hoa không dấu). |
mobile | string | ✓ | Số điện thoại đăng ký với ACB, dùng để nhận OTP. Định dạng: 10 chữ số, bắt đầu bằng 0. |
acbUserId | string | ~ | User ID đăng nhập ACB Online / Biz. Bắt buộc với tài khoản Doanh nghiệp và Hộ kinh doanh. |
merchantId | number | ~ | ID của Merchant (Bắt buộc nếu kết nối bằng tài khoản Master Merchant). |
shopId | number | ✕ | ID cửa hàng muốn gán tài khoản vào. Nếu để trống, hệ thống tự tạo cửa hàng mới khi xác nhận. |
name | string | ✕ | Tên gợi nhớ của tài khoản. Mặc định: ACB - {accountNumber} - Ghi nợ. |
merchantName | string | ✕ | Tên cửa hàng (dùng khi hệ thống tự tạo cửa hàng mới). |
merchantAddress | string | ✕ | Địa chỉ cửa hàng (dùng khi hệ thống tự tạo cửa hàng mới). |
Ví dụ mã nguồn
- cURL
- NestJS
- C#
- Java
- PHP
curl --location --request POST 'https://open-api.tingee.vn/v1/create-debit' \
--header 'accept: application/json' \
--header 'x-client-id: YOUR_CLIENT_ID' \
--header 'x-request-timestamp: 20240509154004003' \
--header 'x-signature: YOUR_SIGNATURE' \
--header 'Content-Type: application/json' \
--data '{
"bankBin": "970416",
"accountType": "personal-account",
"accountNumber": "12345678",
"accountName": "NGUYEN VAN A",
"mobile": "0935926988"
}'
import axios from "axios";
import { createHmac } from "crypto";
const CLIENT_ID = "YOUR_CLIENT_ID";
const SECRET_KEY = "YOUR_SECRET_KEY";
// Timestamp theo múi giờ UTC+7, định dạng yyyyMMddHHmmssSSS
function getTimestamp() {
return new Date(Date.now() + 7 * 60 * 60 * 1000)
.toISOString()
.replace(/[-:TZ.]/g, "")
.slice(0, 17);
}
async function createDebit() {
const body = {
bankBin: "970416",
accountType: "personal-account",
accountNumber: "12345678",
accountName: "NGUYEN VAN A",
mobile: "0935926988",
};
const bodyJson = JSON.stringify(body);
const timestamp = getTimestamp();
const signature = createHmac("sha512", SECRET_KEY)
.update(`${timestamp}:${bodyJson}`)
.digest("hex");
const res = await axios.request({
method: "POST",
url: "https://open-api.tingee.vn/v1/create-debit",
data: bodyJson,
headers: {
accept: "application/json",
"Content-Type": "application/json",
"x-client-id": CLIENT_ID,
"x-request-timestamp": timestamp,
"x-signature": signature,
},
});
console.log(res.data);
}
createDebit();
using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
public class Program
{
private const string ClientId = "YOUR_CLIENT_ID";
private const string SecretKey = "YOUR_SECRET_KEY";
private static readonly HttpClient Client = new HttpClient();
public static async Task Main()
{
var body = new
{
bankBin = "970416",
accountType = "personal-account",
accountNumber = "12345678",
accountName = "NGUYEN VAN A",
mobile = "0935926988"
};
// Không escape tiếng Việt / ký tự đặc biệt để khớp với JSON.stringify phía TINGEE
var jsonOptions = new JsonSerializerOptions { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping };
var bodyJson = JsonSerializer.Serialize(body, jsonOptions);
// Timestamp theo múi giờ UTC+7, định dạng yyyyMMddHHmmssSSS
var timestamp = DateTime.UtcNow.AddHours(7).ToString("yyyyMMddHHmmssfff");
var signature = HmacSha512(SecretKey, $"{timestamp}:{bodyJson}");
var request = new HttpRequestMessage(HttpMethod.Post, "https://open-api.tingee.vn/v1/create-debit");
request.Headers.Add("accept", "application/json");
request.Headers.Add("x-client-id", ClientId);
request.Headers.Add("x-request-timestamp", timestamp);
request.Headers.Add("x-signature", signature);
request.Content = new StringContent(bodyJson, Encoding.UTF8, "application/json");
var response = await Client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
private static string HmacSha512(string key, string message)
{
using var hmac = new HMACSHA512(Encoding.UTF8.GetBytes(key));
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
return Convert.ToHexString(hash).ToLower();
}
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class Main {
private static final String CLIENT_ID = "YOUR_CLIENT_ID";
private static final String SECRET_KEY = "YOUR_SECRET_KEY";
public static void main(String[] args) throws Exception {
// JSON minified, giống kết quả JSON.stringify()
String bodyJson = "{\"bankBin\":\"970416\",\"accountType\":\"personal-account\",\"accountNumber\":\"12345678\",\"accountName\":\"NGUYEN VAN A\",\"mobile\":\"0935926988\"}";
// Timestamp theo múi giờ UTC+7, định dạng yyyyMMddHHmmssSSS
String timestamp = ZonedDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh"))
.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
String signature = hmacSha512(SECRET_KEY, timestamp + ":" + bodyJson);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://open-api.tingee.vn/v1/create-debit"))
.header("accept", "application/json")
.header("Content-Type", "application/json")
.header("x-client-id", CLIENT_ID)
.header("x-request-timestamp", timestamp)
.header("x-signature", signature)
.method("POST", HttpRequest.BodyPublishers.ofString(bodyJson, StandardCharsets.UTF_8))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.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");
mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA512"));
byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
StringBuilder hex = new StringBuilder();
for (byte b : hash) hex.append(String.format("%02x", b));
return hex.toString();
}
}
<?php
$clientId = "YOUR_CLIENT_ID";
$secretKey = "YOUR_SECRET_KEY";
$body = [
"bankBin" => "970416",
"accountType" => "personal-account",
"accountNumber" => "12345678",
"accountName" => "NGUYEN VAN A",
"mobile" => "0935926988",
];
// Không escape "/" và tiếng Việt để khớp với JSON.stringify phía TINGEE
$bodyJson = json_encode($body, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
// Timestamp theo múi giờ UTC+7, định dạng yyyyMMddHHmmssSSS
$now = new DateTime("now", new DateTimeZone("Asia/Ho_Chi_Minh"));
$timestamp = $now->format("YmdHisv");
$signature = hash_hmac("sha512", $timestamp . ":" . $bodyJson, $secretKey);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://open-api.tingee.vn/v1/create-debit",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $bodyJson,
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Content-Type: application/json",
"x-client-id: " . $clientId,
"x-request-timestamp: " . $timestamp,
"x-signature: " . $signature,
],
]);
$response = curl_exec($ch);
if ($response === false) {
echo "cURL Error: " . curl_error($ch);
} else {
echo $response;
}
curl_close($ch);
Response mẫu
{
"code": "00",
"message": "Success",
"data": {
"confirmId": "c2a8f3e0-4b1d-4e0a-9a51-7d2f0e6b9c11"
}
}
| 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, dùng để gọi API Xác nhận số tài khoản trong vòng 4 phút. |
Mã lỗi thường gặp
| Code | Mô tả | Hướng xử lý |
|---|---|---|
1059 | Ngân hàng không hỗ trợ thao tác này | API chỉ áp dụng cho ngân hàng ACB. |
1048 | Số tài khoản đã đăng ký | Tài khoản đã đăng ký nhận biến động ghi nợ trước đó. |
1022 | Tài khoản đã tồn tại | Tài khoản đã đăng ký đủ cả ghi có và ghi nợ. |
1031, 1085 | Cửa hàng không tồn tại hoặc ngừng hoạt động | Kiểm tra shopId, hoặc bỏ trống để hệ thống tự tạo cửa hàng. |
1037, 1103 | Thiết bị TingeeBox của cửa hàng không hỗ trợ ngân hàng này | Chọn cửa hàng khác phù hợp với cấu hình thiết bị. |
1095, 1096 | Lỗi merchantId của Master Merchant | Truyền merchantId thuộc Master Merchant đang gọi API. |
400 | Dữ liệu không hợp lệ hoặc lỗi từ ACB | message mô tả chi tiết (ví dụ số điện thoại không khớp với thông tin tại ACB). |
90, 91, 92, 97 | Lỗi xác thực request (timestamp, client-id, chữ ký) | Xem Mã lỗi hệ thống. |
Others | Lỗi khác | Xem Danh sách mã lỗi. |