API Sự kiện
1. Inbound — IPN (do @nx/mq-pay xử lý)
Các endpoint IPN của nhà cung cấp thanh toán thuộc sở hữu của @nx/mq-pay (được đăng ký làm controller khi chạy ở mode FULL hoặc API). Bản thân package payment không khai báo route IPN.
| Nhà cung cấp | Endpoint IPN | Xác thực |
|---|---|---|
| VNPAY QR MMS | (theo nhà cung cấp) | Xác minh chữ ký nhà cung cấp (trong MQ-Pay PaymentVerificationService) |
| VNPAY PhonePOS | (theo nhà cung cấp) | Tương tự |
| SYSTEM | n/a (in-platform) | n/a |
Đường dẫn IPN chính xác được định nghĩa bên trong registry nhà cung cấp của
@nx/mq-pay; tham khảo package đó để biết các route.
2. Outbound — HTTP Webhooks
Subscriber đăng ký endpoint của họ thông qua
WebhookConfigController(REST). Trên mỗi thay đổi trạng thái MQ-Pay,WebhookEventHandlerHelpertruy vấn các webhook đang hoạt động đã đăng ký theo loại sự kiện và điều phối quaWebhookDispatcherService.
Bộ lọc
WebhookEventHandlerHelper.handle() (src/helpers/webhook-event-handler/helper.ts:54-96):
- Bỏ qua dispatch cho các sự kiện không actionable (
TRANSACTION_CREATED,ATTEMPT_CREATED,ATTEMPT_SENT) — những sự kiện này chỉ dùng cho WS. - Truy vấn
WebhookConfigRepository.find({ status=ACTIVATED, eventTypes contains eventType }). - Với mỗi webhook khớp →
WebhookDispatcherService.dispatch({ webhookConfig, eventType, payload }).
Loại sự kiện
Từ
@nx/mq-pay/src/common/events/index.ts:14-28.
| Sự kiện | Kiểu payload | Kích hoạt bởi | Webhook gửi |
|---|---|---|---|
mq-pay:transaction.created | ITransactionCreatedPayload | Insert Transaction | ✗ (chỉ WS) |
mq-pay:transaction.settled | ITransactionSettledPayload | Thanh toán đầy đủ | ✓ |
mq-pay:transaction.cancelled | ITransactionCancelledPayload | Hủy tự động/admin | ✓ |
mq-pay:attempt.created | IAttemptCreatedPayload | Insert Attempt | ✗ (chỉ WS) |
mq-pay:attempt.sent | IAttemptSentPayload | Gọi nhà cung cấp thành công (đã có QR) | ✗ (chỉ WS) |
mq-pay:attempt.success | IAttemptSuccessPayload | IPN xác nhận | ✓ |
mq-pay:attempt.failed | IAttemptFailedPayload | Gọi nhà cung cấp thất bại | ✓ |
mq-pay:attempt.expired | IAttemptExpiredPayload | QR hết hạn không thanh toán | ✓ |
mq-pay:attempt.cancelled | IAttemptCancelledPayload | Hủy lan truyền | ✓ |
Cấu trúc payload webhook
{
event: string, // e.g. 'mq-pay:attempt.success'
transaction?: TTransaction,
attempt?: TPaymentAttempt,
timestamp: ISO,
source?: { id: string, type: string }, // typically SaleOrder/SaleCheck
}Phía subscriber (sale)
PaymentWebhookController của sale nhận chúng tại POST /v1/api/sale/webhooks/payment. Xem sale/payments.md để biết logic handler đầy đủ.
3. Outbound — WebSocket
PaymentSocketEventService(src/services/payment-socket-event.service.ts).
| Topic | Hằng số | Kích hoạt |
|---|---|---|
observation/payment/transaction | PaymentWebSocketTopics.TRANSACTION | Bất kỳ sự kiện transaction nào (*.created, *.settled, *.cancelled) |
observation/payment/payment-attempt | PaymentWebSocketTopics.ATTEMPT | Bất kỳ sự kiện attempt nào (*.created, *.sent, *.success, *.failed, *.expired, *.cancelled) |
Phân phối room
// Transaction (PaymentWebSocketRooms.getTransactionRooms)
[
'merchants/<merchantId>',
'merchants/<merchantId>/transactions',
'transactions/<transactionId>',
]
// Attempt (PaymentWebSocketRooms.getPaymentAttemptRooms)
[
'merchants/<merchantId>',
'merchants/<merchantId>/payment-attempts',
'payment-attempts/<attemptId>',
'transactions/<transactionId>/payment-attempts', // when transactionId present
]merchantId được trích từ transaction.metadata.merchant.source.id hoặc attempt.metadata.merchant.source.id.
4. BullMQ (nội bộ — bên trong MQ-Pay)
| Queue | Loại | Concurrency | Nguồn |
|---|---|---|---|
scheduler | scheduler jobs (3 partition: P01–P03) | 10 jobs / partition | @nx/mq-pay/src/services/queue/... |
confirmation | confirmation jobs (3 partition) | 10 jobs / partition | tương tự |
Queue là nội bộ của
@nx/mq-pay. Worker tiêu thụ từ những queue này. Phụ thuộc mode: modeFULLvàWORKERsinh worker; modeAPItạo job nhưng không tiêu thụ.
5. Idempotency & Thứ tự
| Bề mặt | Phân phối | Khôi phục |
|---|---|---|
| Webhook (HTTP) | at-most-once mỗi lần dispatch; retry khi lỗi truyền | Chính sách retry của WebhookDispatcherService (mặc định: timeoutMs=30000, maxRetries=3 từ WebhookConfig.metadata) |
| WebSocket | best-effort | client refetch qua REST khi reconnect |
| BullMQ | at-least-once | khóa idempotency theo từng job trong @nx/mq-pay |
6. Trang liên quan
- Điều phối Webhook — chi tiết handler đầy đủ
- Tích hợp — sale đăng ký các sự kiện này
- Kiến trúc — luồng IPN