3DS Simulation
Sandbox testing of secure mode, requires_action, nextAction, challenge, resume, and callback flows.
What does this page cover? How HSRC Pay sandbox simulates 3DS, secure mode, and requires_action flows.
Payment does not always return direct success. Some payments require user action, redirect, HTML render, challenge, or resume/callback flow. HSRC Pay represents this with the normalized requires_action model.
Important: 3DS simulation does not guarantee real authentication; it tests integration behavior. Sandbox 3DS is not real card network authentication or a real issuer ACS connection.
What Is 3DS Simulation?
3DS simulation is sandbox-only challenge behavior that tests whether the merchant integration is ready for multi-step payment flows.
In this flow, the sandbox provider adapter may return requires_action instead of direct authorization. The merchant or checkout frontend shows this next action to the user; after the challenge completes, resume/callback flow finalizes the payment result.
When Should Secure Mode Be Used?
Secure mode should be tested when:
- The merchant API request requires secure mode
- Provider capability supports 3DS
- The payment is confirmed with
secure_mode: trueand the sandbox provider supports the flow - Routing or product configuration requires a secure provider
Confirm Result: requires_action
When the adapter has latestResult.kind === "requires_action", Payment becomes REQUIRES_ACTION. The merchant uses confirmResult.paymentNextAction for redirect:
{
"payment": { "id": "pay_sandbox_123", "status": "REQUIRES_ACTION" },
"confirmResult": {
"ok": true,
"latestResult": { "kind": "requires_action" },
"paymentNextAction": {
"action": "redirect_user_to_url",
"url": "https://sandbox.hsrcpay.com/..."
}
}
}nextAction inside the provider adapter (e.g. render_html) can be handled on checkout or dashboard; for public API redirect, rely on paymentNextAction.
Next Action Types
| Type | Description |
|---|---|
render_html | Checkout or merchant frontend renders HTML challenge content |
redirect | User is redirected to sandbox challenge URL |
collect_input | Conceptual model: additional test input may be collected from the user |
sdk_action | Conceptual model: may be used for SDK-managed actions |
In the current public narrative, render_html and redirect-like models are primary; treat other types as future-compatible conceptual models.
HTML Render / Redirect Flow
If hosted checkout is used, HSRC Pay may manage challenge rendering inside the checkout experience. In API-only integration, the merchant must handle the nextAction result on their own frontend.
Merchant frontend:
- Must not log raw payload when rendering HTML.
- Must use redirect URL only in sandbox context.
- Must wait for resume/callback result after challenge completes.
Resume / Callback Flow
After the challenge completes, the provider returns to GET|POST /v1/gateway/three-d-secure-callback-urls/:chargeId on the HSRC Pay gateway. This flow runs the resumeThreeDSecure use case; the merchant does not need to call resumePayment(paymentId) separately.
const { data } = await api.post("/v1/payments/pay_sandbox_123/confirm", {
payment_method: { id: "pm_sandbox" },
payer_identity: { ip_address: clientIp, user_agent: ua },
});
if (data.confirmResult.paymentNextAction?.url) {
redirectUser(data.confirmResult.paymentNextAction.url);
}
// After callback: verify final status via GET payment or webhookAuthorization After Successful 3DS
When the challenge completes successfully, Payment becomes SUCCEEDED or AUTHORIZED; Charge becomes CAPTURED or AUTHORIZED. Webhook: payment.succeeded, payment.authorized, charge.captured, etc.
Failed or Cancelled Challenge
If the challenge fails, the adapter may return error + declined; Charge becomes DECLINED, Payment stays REQUIRES_PAYMENT_METHOD. The merchant should offer controlled re-confirm or a different method.
Webhook and Event Expectations
The merchant webhook handler must be idempotent. Expect multiple events for the same payment.
Expected event family:
payment.requires_actionpayment.succeededpayment.authorizedcharge.declinedcheckout_session.completed(hosted checkout)
Do not use frontend result alone as the final accounting record; verify with server-side status and webhook/event flow.
Testing Checklist
- Handle
requires_actionresponse. - Test hosted checkout vs API-only integration difference.
- Test gateway 3DS callback and payment GET/webhook verification after callback.
- Test successful and failed challenge outcomes separately.
- Check webhook idempotency behavior.
- Mask raw HTML, card data, and transaction metadata logging.
Limitations and Security Notes
- 3DS simulation is not real card network authentication.
- No real issuer ACS connection is established.
- Fields such as CAVV/ECI/XID/MD should be treated as test metadata in sandbox.
- Raw challenge payload, HTML, and transaction metadata must be masked carefully in logs.
- Production authentication outcome is not guaranteed; only integration flow is tested.