Developer

Mô phỏng thanh toán đơn demo

✧ Mở bằng AI

Sao chép tài liệu, mở AI rồi dán vào cuộc trò chuyện.

ChatGPTClaudePerplexityGrok
≡ Xem Markdown

Tự động kiểm thử Create đơn demo → mô phỏng thanh toán → nhận IPN. Dùng ngay Secret Key của tài khoản demo làm Bearer token; không cần token mới hoặc ký HMAC request.

Request

POST https://payment.pay2s.vn/v1/gateway/api/simulate-payment
Authorization: Bearer YOUR_DEMO_SECRET_KEY
Content-Type: application/json
{
  "orderId": "DEVd33eb13817916599723201625c7",
  "resendIpn": false
}

Điều kiện

Create vẫn dùng API hiện tại. Response create phải có environment: "demo": tài khoản là demo và tất cả ngân hàng được chọn đều là demo. Server kiểm tra tài khoản, ngân hàng nhận và cờ demo đã lưu của đơn; không tin cờ môi trường do client tự gửi.

Đơn phải thuộc phạm vi Secret Key, có ipnUrl và đang pending hoặc đã thanh toán demo trước đó. Đơn production, đơn đã hủy và orderId trùng nhiều đơn bị từ chối. Secret Key cửa hàng demo chỉ truy cập đơn cửa hàng đó; Secret Key tài khoản truy cập đơn không gắn cửa hàng, cùng phạm vi create.

Không chuyển tiền thật. API giữ nguyên dữ liệu/yêu cầu hóa đơn từ create, không tự thêm yêu cầu xuất hóa đơn. Luồng hóa đơn demo phụ thuộc cấu hình sandbox.

Postman

Import collection và Environment mẫu. Điền secretKey, orderId rồi chọn:

Cả hai đọc Secret Key từ Environment, đặt header Authorization và tạo body. Không có script ký HMAC cho hai request này. Create, Cancel và API HĐĐT vẫn giữ cách xác thực riêng.

Response

{
  "status": true,
  "message": "Đã ghi nhận giao dịch demo và khớp đơn thành công.",
  "data": {
    "partnerCode": "PAY2S7EPF0SB1ZP27W71",
    "orderId": "DEVd33eb13817916599723201625c7",
    "invoiceNumber": "PAY2SJSCE21278F7A19FE328",
    "environment": "demo",
    "orderStatus": "completed",
    "transactionNumber": "DEMO-20261011021933-1720299E09",
    "alreadyPaid": false,
    "ipnRequeued": false,
    "ipnStatus": "queued"
  }
}

alreadyPaid: true nghĩa là đơn đã thanh toán trước đó; không có giao dịch mới. ipnRequeued: true nghĩa là request này đã đặt lại hàng chờ IPN. ipnStatus có thể là queued, sending, sent, retrying, failed tại thời điểm trả kết quả.

Gửi và gửi lại IPN

Worker gửi POST tới ipnUrl của đơn. IPN vẫn có chữ ký m2signature như thanh toán thật; chỉ request giả lập được đơn giản hóa. Kiểm tra theo chữ ký IPN, phản hồi HTTP 200 và {"success":true} khi xử lý xong.

IPN gửi bất đồng bộ; response mô phỏng thành công không đảm bảo callback đã tới. Bộ test cần đợi IPN với thời gian chờ phù hợp. Đối chiếu bằng orderId; IPN hiện dùng requestId là ID nội bộ, requestTrace là requestId từ create.

Mỗi lần gọi resendIpn: true sau khi lượt trước hoàn tất có thể tạo callback mới. Không dùng cờ này cho retry thanh toán thông thường. Callback giữ mã đơn/giao dịch nhưng thời gian và chữ ký có thể khác; phía nhận phải tránh cộng tiền/kích hoạt dịch vụ trùng.

Mã lỗi

HTTP Ý nghĩa
400 JSON, orderId hoặc kiểu resendIpn không hợp lệ
401 Thiếu/sai Secret Key
403 Tài khoản hoặc đơn production
404 Không có đơn trong phạm vi khóa
409 Đơn đã hủy, ngân hàng demo không hợp lệ, thiếu ipnUrl hoặc mã đơn bị trùng
500 Lỗi xử lý; có thể thử lại cùng orderId

Không tìm thấy đơn thì báo lỗi; không tạo giao dịch độc lập thay thế.

Request và response đối chiếu ngày 11/10/2026

Các mẫu dưới đây giữ cấu trúc trường và kiểu dữ liệu. Khóa, chữ ký, URL phiên đã được thay bằng placeholder; danh sách chỉ giữ tối đa hai phần tử và dữ liệu ảnh/PDF/XML dài được rút gọn. Không sao chép placeholder để gọi API thật.

Mô phỏng tiền vào đơn demo

Đã gọi API demo/UAT.

POST /v1/gateway/api/simulate-payment

Body:

{
  "orderId": "DEVd33eb13817916599723201625c7",
  "resendIpn": false
}

HTTP 200. Response:

{
  "status": true,
  "message": "Đã ghi nhận giao dịch demo và khớp đơn thành công.",
  "data": {
    "partnerCode": "PAY2S7EPF0SB1ZP27W71",
    "orderId": "DEVd33eb13817916599723201625c7",
    "invoiceNumber": "PAY2SJSCE21278F7A19FE328",
    "environment": "demo",
    "orderStatus": "completed",
    "transactionNumber": "DEMO-20261011021933-1720299E09",
    "alreadyPaid": false,
    "ipnRequeued": false,
    "ipnStatus": "queued"
  }
}
Tìm trong 57 trang tài liệu · Esc để đóng