Docs cho merchant và đội kỹ thuật tích hợp
Tài liệu PayUSDT
Luồng tích hợp dành cho merchant mới: từ tạo store, cấu hình ví, tới nhận callback webhook.
1. Tạo merchant store
Store sinh ra merchant id, api key và secret key dùng cho webhook verification.
- Đăng ký tài khoản merchant và tạo store trong dashboard.
- Lưu lại
x-merchant-idvàx-api-keyngay sau khi khởi tạo. - Không gửi API key từ frontend. Tất cả request tạo invoice nên đi từ backend của bạn.
2. Cấu hình ví nhận tiền
Ví nhận tiền là nơi blockchain gửi USDT trực tiếp sau khi khách thanh toán.
TRC20
Phổ biến, phí rẻ, địa chỉ bắt đầu bằng T.
BEP20
Phù hợp merchant cần phí thấp trên BNB Chain (0x...).
ERC20
Tương thích hệ EVM Ethereum, địa chỉ 0x.
3. Nạp fee balance
Fee balance tách riêng khỏi tài sản merchant để duy trì mô hình non-custodial.
- Merchant nạp trước một số dư nhỏ vào fee balance.
- PayUSDT trừ phí vận hành từ fee balance sau mỗi giao dịch hoàn tất.
- Invoice mới có thể bị tạm dừng nếu số dư phí về 0.
4. Tạo invoice
Tạo invoice từ backend để nhận về payment URL và thông tin on-chain.
const response = await fetch("https://payusdt.io/api/v1/invoices", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-merchant-id": "m_YOUR_MERCHANT_ID",
"x-api-key": "uk_YOUR_API_KEY"
},
body: JSON.stringify({
orderId: "ORDER-2026-001",
amount: "49.50",
network: "TRC20",
currency: "USDT"
})
});
const result = await response.json();
console.log("Payment URL:", result.data.paymentUrl);5. Xác thực webhook
Webhook là nguồn sự thật để cập nhật đơn hàng của merchant.
import crypto from "node:crypto";
export async function POST(request: Request) {
const signature = request.headers.get("x-payusdt-signature") ?? "";
const rawBody = await request.text();
// Tính HMAC SHA-256 trên raw body bằng Secret Key của store
const expected = crypto
.createHmac("sha256", process.env.PAYUSDT_SECRET_KEY!)
.update(rawBody)
.digest("hex");
if (signature !== expected) {
return new Response("Invalid signature", { status: 401 });
}
const payload = JSON.parse(rawBody);
console.log("Cập nhật đơn hàng thành công:", payload.orderId);
return new Response("OK", { status: 200 });
}