Webhooks
Certification cases for webhook handler behavior and event coverage.
Part of the Certification guide. Mark your scope on that page before you run these cases. Base payloads and test cards are on the Reference page.
13. Webhooks
Applies to: WEBHOOKS. Register one HTTPS endpoint in the sandbox portal and subscribe it to all events. Each delivery carries a unique IdempotencyKey; redeliveries carry IsResent: true. order.completed, order.cancelled, and order.expired are sent only when the order status changes and the endpoint subscribes to the event. Match each delivery to the merchant order by OrderId, with ExternalOrderId as the fallback. Every sandbox delivery carries IsTestMode: true; never update production order state from it.
Reference: Webhooks, Testing webhooks, Appendix C.3.
13.1 Handler behavior
| ID | Scenario | Setup / action | Expected result | Evidence |
|---|---|---|---|---|
| WEBHOOK-01 | Immediate 2xx | Trigger any order event | The endpoint returns a 2xx within 2 seconds, before any processing logic runs | HTTP status and response time |
| WEBHOOK-02 | Non-JSON content type accepted | Inspect a received delivery | The handler parses the text body as JSON regardless of the Content-Type header | Parsed payload |
| WEBHOOK-03 | Redelivery processed one time | Return HTTP 500 for one delivery | FlexFactor redelivers the event with IsResent: true. The merchant order is updated one time, keyed on IdempotencyKey | Both payloads |
| WEBHOOK-04 | Signature verification (recommended) | Verify x-fc-authorization on a received delivery with the sandbox subscriber key | The recomputed HMAC-SHA512 matches; a tampered body fails verification | Verification result |
13.2 Event coverage
The order events are produced by the flow cases. Record the IdempotencyKey of each event against the source case on the result sheet; no separate case is needed.
| Event | Produced by | Expected handling |
|---|---|---|
order.completed | CIT-PURCHASE-01, CIT-AUTHORIZE-02, MIT-ASYNC-PURCHASE-02, MIT-ASYNC-AUTHORIZE-03, SYNC-MIT-03 | Received after the API response; the merchant order is marked paid one time |
order.cancelled | MIT-ASYNC-PURCHASE-03, CANCEL-01, CANCEL-03 | The merchant order is marked cancelled or returned to dunning |
order.expired | MIT-ASYNC-PURCHASE-04, SYNC-MIT-05, CIT-AUTHORIZE-04 | The merchant order is marked failed |
order.capturerequired | MIT-ASYNC-AUTHORIZE-02, SYNC-MIT-04 | A capture is issued within the capture window |
order.refunded | REFUND-01 | EventData.Amount is in cents and matches the refund |
challenge.presented | CIT-PURCHASE-03 | The merchant order remains declined |
The dispute events are not produced by any flow case. FlexFactor triggers them on request.
| ID | Scenario | Setup / action | Expected result | Evidence |
|---|---|---|---|---|
| WEBHOOK-05 | payment.chargeback.received and payment.chargeback.reversed | Support: request a test chargeback on a completed sandbox order, then a test reversal | Both events received. EventData on the chargeback carries DisputeDateTime, Reason, Amount, and Currency. The merchant order is flagged disputed, then the flag is cleared | Both IdempotencyKey values |
| WEBHOOK-06 | payment.early_warning.received | Support: request a simulated alert | Received; the alert is recorded against the order | IdempotencyKey |
Two events that are easy to misreadA Visa RDR resolution is surfaced through
payment.chargeback.received, notorder.refunded.order.refundedechoes a refund you initiated, and no reversal action is required on receipt.
Updated about 8 hours ago

