Hủy đơn hàng POS
API này dùng để hủy một đơn hàng POS đã tạo trên máy POS Payoo, ví dụ khi khách hàng không tiếp tục thanh toán.
PUT
URLhttps://open-api.tingee.vn/v1/update-pos-bill
Hủy đơn hàng POS theo billId trên hệ thống Payoo.
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 PAYOO. |
vaAccountNumber | string | ✓ | Mã thiết bị POS Payoo. |
billId | string | ✓ | Mã đơn hàng cần hủy, nhận được từ API Tạo đơn hàng POS. |
Ví dụ mã nguồn
- cURL
- NestJS
- C#
- Java
- PHP
curl --location --request PUT 'https://open-api.tingee.vn/v1/update-pos-bill' \
--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": "PAYOO",
"vaAccountNumber": "POS00012345",
"billId": "9f1c2b7e4a5d4c3b8e2f1a0b9c8d7e6f"
}'
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 updatePosBill() {
const body = {
bankBin: "PAYOO",
vaAccountNumber: "POS00012345",
billId: "9f1c2b7e4a5d4c3b8e2f1a0b9c8d7e6f",
};
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: "PUT",
url: "https://open-api.tingee.vn/v1/update-pos-bill",
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);
}
updatePosBill();
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 = "PAYOO",
vaAccountNumber = "POS00012345",
billId = "9f1c2b7e4a5d4c3b8e2f1a0b9c8d7e6f"
};
// 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.Put, "https://open-api.tingee.vn/v1/update-pos-bill");
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\":\"PAYOO\",\"vaAccountNumber\":\"POS00012345\",\"billId\":\"9f1c2b7e4a5d4c3b8e2f1a0b9c8d7e6f\"}";
// 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/update-pos-bill"))
.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("PUT", 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" => "PAYOO",
"vaAccountNumber" => "POS00012345",
"billId" => "9f1c2b7e4a5d4c3b8e2f1a0b9c8d7e6f",
];
// 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/update-pos-bill",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "PUT",
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": {
"ReturnCode": "0",
"Description": "Success"
}
}
| 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 | object | Phản hồi gốc từ Payoo. ReturnCode = "0" nghĩa là hủy đơn thành công. |
Lưu ý
Đơn hàng đã hủy không thể thanh toán tiếp trên máy POS. Nếu cần thu tiền lại, hãy tạo đơn hàng mới bằng API Tạo đơn hàng POS.
Mã lỗi thường gặp
| Code | Mô tả | Hướng xử lý |
|---|---|---|
1010 | Không tìm thấy số tài khoản của Merchant | Kiểm tra vaAccountNumber và bankBin của máy POS đã liên kết. |
1063 | Không hỗ trợ đối với ngân hàng này | API chỉ áp dụng cho bankBin = "PAYOO". |
400 | Lỗi từ Payoo hoặc dữ liệu không hợp lệ | message chứa mô tả lỗi chi tiết từ Payoo (ví dụ đơn hàng không tồn tại hoặc đã bị hủy). |
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. |