Chuyển tới nội dung chính

Cổng thanh toán

Bộ API này cho phép tạo yêu cầu thanh toán và cung cấp cập nhật trạng thái thanh toán qua webhook.

Tổng quan thanh toán

Tham chiếu nhanh

EndpointPhương thứcMô tả
/api/v1/paymentsPOSTTạo yêu cầu thanh toán mới
/api/v1/paymentsGETLiệt kê tất cả yêu cầu thanh toán
/api/v1/payments/:idGETLấy yêu cầu thanh toán cụ thể

Phương thức thanh toán

Có hai phương thức chính để tạo liên kết thanh toán:

1. Thanh toán trực tiếp qua mã QR

Sử dụng trường qr_code từ tài khoản ngân hàng của bạn để nhận thanh toán qua VietQR.

  1. Gọi API Lấy danh sách tài khoản ngân hàng
  2. Sử dụng URL qr_code từ phản hồi
  3. Thông báo thanh toán được gửi đến webhook đã đăng ký của bạn

2. Tạo yêu cầu thanh toán

Tạo yêu cầu thanh toán riêng cho mỗi giao dịch với số tiền, danh sách sản phẩm và URL chuyển hướng tùy chỉnh.


API Endpoints

Tạo yêu cầu thanh toán

Tạo yêu cầu thanh toán mới cho một giao dịch.

POST /api/v1/payments
curl -X POST 'https://api.finan.one/open/api/v1/payments' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999' \
-d '{
"merchant": {
"name": "Finan pte",
"phone": "02833223243",
"address": "195/10A, Dien Bien Phu, P15, Binh Thanh",
"email": "[email protected]"
},
"items": [
{
"name": "So Ban Hang Pro 3 Nam",
"price": 3000000,
"quantity": 2,
"amount": 6000000
}
],
"customer": {
"name": "Nguyen Van A",
"phone": "0933450210",
"address": "15, Le Duan, q3, Quan 1",
"email": "[email protected]"
},
"payment_method": "bank_transfer",
"account_id": "54957437-0cb5-4992-ad0e-76d26ba4ddc3",
"amount": 6000000,
"description": "thanh toan don hang",
"reference_id": "54fgi4537-0cb5-4992-ad0e-76d26ba4ddc3",
"reference_type": "invoice",
"success_redirect_url": "https://your-site.com/success",
"failure_redirect_url": "https://your-site.com/failure"
}'

Nội dung request

TrườngKiểuBắt buộcMô tả
merchantobjectThông tin đơn vị bán hàng
merchant.namestringTên doanh nghiệp
merchant.phonestringSố điện thoại liên hệ
merchant.addressstringĐịa chỉ doanh nghiệp
merchant.emailstringEmail liên hệ
itemsarrayDanh sách sản phẩm trong giao dịch
items[].namestringTên sản phẩm
items[].priceintegerGiá mỗi đơn vị (đơn vị tiền tệ nhỏ nhất)
items[].quantityintegerSố lượng
items[].amountintegerTổng số tiền (price * quantity)
customerobjectThông tin khách hàng
customer.namestringHọ tên đầy đủ khách hàng
customer.phonestringSố điện thoại liên hệ
customer.addressstringĐịa chỉ thanh toán/giao hàng
customer.emailstringEmail nhận thông báo
payment_methodstringbank_transfer, card, hoặc ewallet_momo
account_iduuidBắt buộc cho Shinhan bank_transfer. Lấy từ API Tài khoản
amountintegerTổng số tiền (đơn vị tiền tệ nhỏ nhất)
descriptionstringGhi chú thanh toán (tối đa 30 ký tự)
reference_idstringID giao dịch duy nhất của bạn
reference_typestringĐặt thành invoice để liên kết với Hóa đơn
success_redirect_urlstringURL chuyển hướng khi thành công
failure_redirect_urlstringURL chuyển hướng khi thất bại
Tạo nhanh từ hóa đơn

Để tạo thanh toán cho hóa đơn, chỉ cần đặt reference_type: "invoice"reference_id là ID hóa đơn. Không cần thông tin merchant, items hay customer.

Phản hồi

{
"message": { "content": "Tạo thành công" },
"code": 102001,
"request_id": "d0a463bc089ea27859e2ebb5d33857c3",
"data": {
"payment_request_id": "3fde043e-c3d6-40e8-9031-6eadfa02d2a2",
"payment_request_code": "PRJXH9KU",
"payment_url": "",
"bank_transfer_detail": {
"qr_code": "00020101021238570010A000000727...",
"bank_name": "MB",
"account_name": "TRAN TU THIEN",
"account_number": "0933450210",
"remark": "TTVD7ZZS"
}
}
}

Các trường phản hồi

TrườngKiểuMô tả
payment_request_idstringĐịnh danh duy nhất của yêu cầu thanh toán
payment_request_codestringMã thanh toán ngắn
payment_urlstringURL trang thanh toán (cho card hoặc ewallet_momo, trống cho bank_transfer)
bank_transfer_detailobjectThông tin chuyển khoản ngân hàng (cho bank_transfer)
bank_transfer_detail.qr_codestringChuỗi mã VietQR
bank_transfer_detail.bank_namestringMã ngân hàng thụ hưởng
bank_transfer_detail.account_namestringTên tài khoản thụ hưởng
bank_transfer_detail.account_numberstringSố tài khoản thụ hưởng
bank_transfer_detail.remarkstringNội dung chuyển khoản (dùng làm tham chiếu thanh toán)
Thời hạn liên kết thanh toán

Mỗi liên kết thanh toán có hiệu lực trong 30 phút. Tạo yêu cầu thanh toán mới nếu yêu cầu trước đó hết hạn.


Lấy danh sách yêu cầu thanh toán

Truy xuất tất cả yêu cầu thanh toán hoặc lọc theo tham chiếu.

GET /api/v1/payments
# List all payments
curl -X GET 'https://api.finan.one/open/api/v1/payments' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999'

# Filter by reference
curl -X GET 'https://api.finan.one/open/api/v1/payments?reference_type=invoice&reference_id=INV-001' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999'

Tham số truy vấn

Tham sốKiểuMô tả
reference_typestringLọc theo loại tham chiếu (ví dụ: invoice)
reference_idstringLọc theo ID tham chiếu

Phản hồi

{
"message": { "content": "Thực thi API thành công" },
"code": 102000,
"request_id": "abc123...",
"data": [
{
"payment_request_id": "PR-550e8400-e29b-41d4-a716-446655440000",
"paid_amount": 6000000,
"status": "paid",
"payment_method": "bank_transfer",
"amount": 6000000,
"description": "thanh toan don hang",
"reference_type": "invoice",
"reference_id": "INV-001",
"payments": [
{
"id": "PAY-001",
"amount": 6000000,
"method": "bank_transfer",
"created_at": "2024-01-20T14:30:00Z"
}
],
"merchant": {
"name": "Finan pte",
"email": "[email protected]"
},
"customer": {
"name": "Nguyen Van A",
"email": "[email protected]"
}
}
]
}

Trạng thái thanh toán

Trạng tháiMô tả
unpaidChưa nhận được thanh toán (paid_amount = 0)
partial_paidThanh toán một phần (0 < paid_amount < amount)
paidĐã thanh toán đầy đủ (paid_amount = amount)
extra_paidThanh toán vượt mức (paid_amount > amount)
Lấy một yêu cầu thanh toán

Để lấy một yêu cầu thanh toán cụ thể:

GET /api/v1/payments/:payment_request_id

Webhook thanh toán

Sau khi thu tiền thành công, Finan gửi thông báo đến URL webhook đã đăng ký của bạn.

Luồng Webhook

Dữ liệu Webhook

Webhook của bạn sẽ nhận được một request POST với dữ liệu sau:

{
"id": "PAY-001",
"reference_id": "DH970422",
"payment_method": "bank_transfer",
"payment_request_id": "PR-550e8400-e29b-41d4-a716-446655440000",
"amount": 6000000,
"created_at": "2024-01-20T14:30:00Z"
}

Các trường Webhook

TrườngKiểuMô tả
idstringĐịnh danh thanh toán duy nhất
amountintegerSố tiền thanh toán (đơn vị tiền tệ nhỏ nhất)
created_atdatetimeThời gian thanh toán (ISO 8601)
payment_methodstringbank_transfer, card, hoặc ewallet_momo
payment_request_idstringID yêu cầu thanh toán liên quan
reference_typestringLoại tham chiếu (ví dụ: invoice)
reference_idstringID tham chiếu giao dịch của bạn

Phản hồi Webhook

Endpoint webhook của bạn phải phản hồi với HTTP 200 để xác nhận đã nhận:

{
"status": "success",
"message": "Payment processed successfully",
"timestamp": "2024-01-20T14:30:05Z"
}
Quan trọng

Luôn phản hồi với HTTP 200 ngay cả khi xử lý nội bộ thất bại. Điều này tránh các lần thử lại không cần thiết. Xử lý lỗi bất đồng bộ trong hệ thống của bạn.

Tự động thử lại

Các lần gửi webhook thất bại sẽ được tự động thử lại với khoảng thời gian tăng dần theo cấp số nhân:

Lần thử lạiKhoảng thời gianTổng thời gian
Lần 15 phút5 phút
Lần 210 phút15 phút
Lần 315 phút30 phút
thông tin
  • Tự động thử lại được bật mặc định cho tất cả tài khoản
  • Cấu hình cài đặt thử lại trong Cài đặt Webhook
  • Các sự kiện có trạng thái URL Not Set hoặc Timeout không được tự động thử lại
  • Sử dụng thử lại thủ công cho các trường hợp đó

Xác minh chữ ký Webhook

Xác minh tính xác thực của webhook bằng các header chữ ký:

func verifyWebhookSignature(secretKey, method, path, body, timestamp, receivedSignature string) bool {
expectedSignature := generateSignature(secretKey, method, path, body, timestamp)
return expectedSignature == receivedSignature
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)

clientID := r.Header.Get("x-client-id")
signature := r.Header.Get("x-signature")
timestamp := r.Header.Get("x-timestamp")

if !verifyWebhookSignature(secretKey, "POST", "/webhook", string(body), timestamp, signature) {
http.Error(w, "Invalid signature", http.StatusUnauthorized)
return
}

// Process the webhook payload
var payment WebhookPayload
json.Unmarshal(body, &payment)

// Always respond 200
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{
"status": "success",
})
}

Bước tiếp theo

  • Chi hộ - Gửi chi hộ đến tài khoản ngân hàng bên ngoài
  • Hóa đơn - Tạo hóa đơn và liên kết với thanh toán
  • Tạo chữ ký - Hướng dẫn xác thực