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

Môi trường và sandbox

Thanh toán là sản phẩm duy nhất của Hạ Tầng có môi trường. Mỗi doanh nghiệp có môi trường development và production, và dữ liệu thanh toán của hai bên tách biệt hoàn toàn: tài khoản ngân hàng, payment, giao dịch, nhà cung cấp hóa đơn, hóa đơn và khoá tích hợp. API key và webhook endpoint dùng chung. Trang này giải thích cách chọn môi trường và cách test trọn luồng mà không cần tiền thật.

Khác nhau ở đâu​

developmentproduction
Ngân hàngNgân hàng giả lập (simulator): mã xác nhận 000000, chuyển khoản giả lập bằng APITài khoản ngân hàng thật của bạn
Hóa đơn điện tửSandbox của nhà cung cấp (Mắt Bão demo); không gửi cơ quan thuếHóa đơn thật theo mã số thuế của bạn
Giả lập chuyển khoảnPOST /payments/simulate/transfer, cùng nút trên trang checkout và trang payment trên dashboardKhông có (403 environment_mismatch)
Khoá tích hợpak_test_… / sk_test_…ak_… / sk_…
Chọn bằngHatang-Environment: developmentKhông gửi header (mặc định), hoặc Hatang-Environment: production

Chọn môi trường cho từng request​

Gửi header Hatang-Environment trong mỗi request:

HeaderKết quả
Hatang-Environment: developmentRequest đọc và ghi dữ liệu development
Hatang-Environment: production hoặc không gửiProduction
Giá trị khác422 validation_error: "Hatang-Environment must be development or production"

Mọi phản hồi lặp lại môi trường đã dùng trong header Hatang-Environment, và mọi object thanh toán (payment, giao dịch, kết nối ngân hàng, hóa đơn) có trường environment.

curl https://api.hatang.dev/payments \
-H "Authorization: Bearer $HATANG_API_KEY" \
-H "Hatang-Environment: development"
mẹo

Đọc môi trường từ cấu hình (HATANG_ENVIRONMENT=development trên server staging, không đặt gì ở production) thay vì viết cứng trong code, để cùng một code chạy được ở cả hai nơi.

Key development cũ

Key bắt đầu bằng ht_test_ gắn với development: không gửi header thì dùng development, còn yêu cầu production sẽ trả về 403 environment_mismatch.

Id của môi trường này không tồn tại ở môi trường kia: đọc một payment development khi đang chọn production sẽ trả về 404 not_found.

Trên dashboard​

Thanh trên cùng của mọi trang Thanh toán hiển thị môi trường hiện tại và cho phép chuyển. Production có màu đỏ, và chuyển sang production sẽ hỏi xác nhận. Các sản phẩm khác không có nút chuyển này.

Ngân hàng giả lập​

Liên kết bằng { "provider": "simulator" } và xác nhận bằng mã 000000 (xem Bắt đầu nhanh). Mặc định, mã QR ghi ngân hàng MB và số tài khoản là số tự sinh (bắt đầu bằng SIM), nên không ngân hàng thật nào nhận ra.

Để có VietQR thật cho ngân hàng của bạn, truyền bank_code và số tài khoản:

{
"provider": "simulator",
"bank_code": "BIDV",
"account_number": "96247001234",
"account_name": "NGUYEN VAN A"
}

bank_code nhận các mã ngắn quen thuộc: MB (mặc định), BIDV, ACB, VCB, ICB, TCB, VPB, TPB, STB và các ngân hàng VietQR khác. Với số tài khoản thật, app ngân hàng của người mua sẽ chuyển tiền thật cho bạn. Nhưng development không tích hợp ngân hàng nào, nên Hạ Tầng không thấy tiền về: payment chỉ chuyển trạng thái khi bạn giả lập chuyển khoản hoặc đánh dấu đã thanh toán.

Giả lập chuyển khoản​

# Trả đủ một payment
curl https://api.hatang.dev/payments/simulate/transfer \
-H "Authorization: Bearer $HATANG_API_KEY" \
-H "Hatang-Environment: development" \
-H "Content-Type: application/json" \
-d '{ "payment_id": "pay_123" }'

# Trả thiếu
curl https://api.hatang.dev/payments/simulate/transfer \
-H "Authorization: Bearer $HATANG_API_KEY" \
-H "Hatang-Environment: development" \
-H "Content-Type: application/json" \
-d '{ "payment_id": "pay_123", "amount": 50000 }'
TrườngÝ nghĩa
payment_idPayment cần trả. Tự điền tài khoản ngân hàng, số tiền còn thiếu và mã
connection_idTài khoản ngân hàng, cho giao dịch không gắn payment. Cần payment_id hoặc connection_id
amountSố tiền khác, để test trả thiếu và trả thừa. Mặc định là số tiền còn thiếu
contentNội dung chuyển khoản như ngân hàng báo. Mặc định CHUYEN TIEN <code>
directionin (mặc định) hoặc out
referenceMã tham chiếu ngân hàng. Dùng lại một mã để giả lập ngân hàng đẩy cùng giao dịch hai lần
counterparty_nameTên người chuyển. Mặc định NGUYEN VAN KHACH

Lời gọi trả về 202:

{
"object": "simulated_transfer",
"reference": "SIM1758274452930A1B2C3",
"amount": 50000,
"direction": "in",
"description": "CHUYEN TIEN HTBF7RDGVQ",
"connection_id": "bcn_01a0b90428fd7c499145a12c133abe41",
"duplicate": false
}
Trang checkout ở môi trường development có nút giả lập
Ở development, trang checkout có thêm nút giả lập chuyển khoản

Giao dịch giả lập đi qua đúng quy trình như giao dịch từ ngân hàng thật: khớp mã, sự kiện, IPN và webhook. Handler của bạn nhận đúng những gì sẽ nhận ở production.

Lỗi​

LỗiKhi nào
403 environment_mismatchRequest ở production
422 validation_errorKhông có payment_id lẫn connection_id, hoặc tài khoản không phải tài khoản ngân hàng giả lập
409 invalid_stateTài khoản ngân hàng không ở trạng thái active
422 missing_required_fieldKhông có amount và payment không còn thiếu tiền

Kịch bản test​

Kịch bảnCách làm
Trả đủGiả lập chỉ với payment_id
Trả thiếu rồi trả nốtGiả lập amount nhỏ hơn tổng, rồi giả lập lần nữa không có amount
Trả thừaGiả lập amount lớn hơn tổng
Hết hạnTạo với expires_in: 60, đợi vài phút, kiểm tra payment.expired
Tiền về sau khi hết hạnGiả lập trên payment đã hết hạn: payment chuyển sang paid
Người mua quên ghi mãGiả lập với connection_id và content không chứa mã
Ngân hàng đẩy trùngGiả lập hai lần cùng reference và amount: lần hai trả về duplicate: true và không thay đổi gì
Endpoint của bạn bị lỗiĐặt ipn_url trỏ tới URL trả 500, rồi xem GET /payments/{id}/ipn-deliveries
cảnh báo

Handler của bạn phải kiểm tra environment. Một payment development không bao giờ được mở khóa đơn hàng thật.

Bước tiếp theo​

Xem trang này dạng Markdown