WWebhookPay - API nạp tiền tự động

Tích hợp API bằng PHP

Hướng dẫn giới hạn IP, Domain dự án, chữ ký HMAC theo Event, tạo phiếu, kiểm tra trạng thái và nhận webhook.

API hỗ trợ cả HTTP và HTTPS để tương thích nhiều môi trường máy chủ. HTTPS vẫn được khuyến nghị vì HMAC bảo vệ tính toàn vẹn nhưng không mã hóa nội dung truyền qua HTTP. Không đặt API Secret hoặc Webhook Secret trong thư mục public, Git, log hoặc JavaScript phía trình duyệt.

1. Quy trình bắt đầu

  1. Đăng ký tài khoản và gửi yêu cầu cấp API, khai báo đúng Domain dự án, Webhook URL thuộc domain đó và có thể nhập trước IP outbound dự kiến (không bắt buộc).
  2. Khi duyệt, admin sẽ kiểm tra/chỉnh sửa danh sách IP và chỉ cấp API Client khi đã có ít nhất một IP được phép.
  3. Lưu API Key, API Secret và Webhook Secret ngoài thư mục public.
  4. Kiểm tra kết nối bằng GET /api/v1/ping.
  5. Tạo phiếu bằng POST /api/v1/payment-requests, lưu payment_id và dữ liệu thanh toán trả về.
  6. Nhận webhook payment.approved và chống xử lý trùng theo event_id.

2. IP được phép và Domain dự án

Khi gửi yêu cầu cấp API, bạn có thể khai báo trước IPv4/IPv6 outbound hoặc để trống để admin bổ sung. Yêu cầu chỉ được duyệt khi admin đã thiết lập ít nhất một IP hợp lệ. Mỗi API Client chỉ chấp nhận request từ các IP đã được cấp quyền. Client không cần gửi Domain dự án trong header; hệ thống ràng buộc Domain dự án với API Client và Webhook URL đã đăng ký.

Nếu máy chủ không có outbound IP cố định, có thể sử dụng VPS, NAT Gateway, HTTP Proxy hoặc SOCKS5 Proxy có IP tĩnh. Hãy cung cấp IP egress thực tế của proxy/VPS cho admin. Không nên dùng proxy công cộng hoặc proxy tự đổi IP.

3. Xác thực HMAC theo Event

Mỗi request gửi bốn header:

X-API-Key: YOUR_API_KEY
X-API-Event: payment.request.create
X-API-Signature: HMAC_SHA256_SIGNATURE
X-API-Signature-Alg: HMAC-SHA256

Không cần Timestamp, Nonce, Project-Domain hoặc Signature-Version.

Chuỗi ký:

canonical = EVENT + "\n" + RAW_BODY
signature = HMAC_SHA256(canonical, API_SECRET)

Với request GET, RAW_BODY là chuỗi rỗng. Phải ký đúng raw body byte-for-byte trước khi gửi.

4. Event của từng endpoint

EndpointEvent
GET /api/v1/pingsystem.ping
GET /api/v1/payment-methodspayment.methods.list
POST /api/v1/payment-requestspayment.request.create
GET /api/v1/payment-requests/{payment_id}payment.request.status

5. Kiểm tra kết nối

GET /api/v1/ping
X-API-Event: system.ping

GET có raw body rỗng, vì vậy chữ ký được tính trên system.ping + "\n".

6. Phương thức thanh toán đang hoạt động

GET /api/v1/payment-methods
X-API-Event: payment.methods.list

Response trả phương thức đang hoạt động. Có thể bỏ payment_method_code khi tạo phiếu để hệ thống tự sử dụng phương thức hiện hành.

7. Tạo phiếu nạp

POST /api/v1/payment-requests
X-API-Event: payment.request.create
Idempotency-Key: order-ABC123ABCB
Content-Type: application/json

{
  "merchant_invoice_id": "ABC123ABCB",
  "amount": 100000,
  "description": "Nạp số dư"
}

8. Kiểm tra trạng thái phiếu

GET /api/v1/payment-requests/{payment_id}
X-API-Event: payment.request.status

Nếu payment_ready=false, hãy gọi lại endpoint trạng thái. Khi thông tin thanh toán sẵn sàng, response cung cấp snapshot ngân hàng, số tài khoản, tên tài khoản, nội dung chuyển khoản, QR và expires_at nếu có. Website tích hợp nên sử dụng trực tiếp expires_at do API trả về.

Các trạng thái public thường gặp: preparing_payment, pending_payment, payment_reported, approved, expired, rejected, cancelled.

9. Webhook

Khi phiếu được hệ thống xác nhận thành công, webhook được gửi tới URL đã đăng ký. Nếu lần gửi đầu tiên chưa thành công, hệ thống sẽ tự động thử gửi lại.

X-Webhook-ID: evt_xxx
X-Webhook-Event: payment.approved
X-Webhook-Timestamp: UNIX_TIMESTAMP
X-Webhook-Signature: HMAC_SHA256(TIMESTAMP + "." + RAW_BODY, WEBHOOK_SECRET)

Website nhận webhook phải xác minh timestamp, chữ ký bằng hash_equals(), đối chiếu payment_id, merchant_invoice_id, amount, transfer_content và chỉ ghi nhận một lần theo event_id. Trả HTTP 2xx sau khi xử lý thành công.

10. Dùng Proxy để giữ IP ổn định

Nếu hosting thay đổi IP outbound, cấu hình backend PHP đi qua proxy có IP tĩnh rồi gửi IP đó cho admin để cấp quyền. Với HTTP proxy dùng CURLOPT_PROXY/CURLOPT_PROXYPORT. Với SOCKS5 nên dùng CURLPROXY_SOCKS5_HOSTNAME để DNS được resolve qua proxy. Nếu API Base URL là HTTPS, luôn giữ kiểm tra TLS.

11. Mã lỗi xác thực thường gặp

Ý nghĩaCách xử lý
API_AUTH_HEADERS_MISSINGThiếu header xác thựcKiểm tra API Key, Event, Signature và Signature-Alg.
API_IP_DENIEDIP chưa được cấp quyềnKiểm tra IP egress thực tế hoặc IP proxy tĩnh và yêu cầu admin thêm đúng IP.
API_DOMAIN_CONFIG_INVALIDDomain/Webhook cấu hình không khớpLiên hệ admin kiểm tra Domain dự án và Webhook URL của API Client.
API_EVENT_INVALIDEvent không đúng endpointDùng đúng Event trong bảng endpoint.
API_SIGNATURE_ALG_INVALIDThuật toán chữ ký không hỗ trợGửi X-API-Signature-Alg: HMAC-SHA256.
API_SIGNATURE_INVALIDChữ ký saiKiểm tra Event, raw body và API Secret.
API_CLIENT_DISABLEDAPI Client bị khóaLiên hệ quản trị viên.

12. Checklist triển khai

  1. Domain dự án và Webhook URL đã đăng ký đúng.
  2. IP outbound/proxy tĩnh đã được admin cho phép.
  3. API Secret/Webhook Secret không nằm trong public webroot.
  4. Event đúng endpoint và HMAC ký đúng EVENT + "\n" + RAW_BODY.
  5. POST có Idempotency-Key ổn định khi retry.
  6. Webhook có kiểm tra chữ ký và event idempotency.
  7. Ưu tiên HTTPS; chỉ dùng HTTP khi môi trường buộc phải tương thích và hiểu rằng nội dung sẽ không được mã hóa trên đường truyền.