HSRCPAY Documentation

Payment Flows

High-level map of create, confirm, requires_action, success, decline, capture, refund, cancel, and webhook flows in HSRC Pay.

This page provides a high-level map of HSRC Pay payment flows. Read it to enter the payment lifecycle, see the difference between Hosted Checkout and API-only integration, and move through sub-pages in the right order.

Payment integration is not only calling endpoints; it is state, provider behavior, risk, routing, and event discipline.

What is a payment flow?

In HSRC Pay, a payment flow starts when the merchant creates a Payment (CREATED), enters provider execution with Confirm, and reflects adapter results in Payment/Charge states.

Core model:

  1. Payment is created (POST /v1/payments).
  2. Payment Method is selected or collected inside Checkout Session.
  3. Confirm call starts execution (POST /v1/payments/:id/confirm).
  4. Routing plan orders provider candidates.
  5. For each candidate, a Charge is created and the provider adapter runs pay.
  6. Adapter result returns as success, requires_action, or error (including declined).
  7. Payment status and Charge status are updated.
  8. Event/webhook is sent to the merchant system.

Core flow: create -> confirm -> result

StageResponsibilityNote
CreatePrepares payment intentstatus: CREATED, does not pull funds
ConfirmStarts provider executionResponse: data.payment + data.confirmResult
ResultAdapter + Payment/Charge statusRead confirmResult.latestResult.kind together with payment.status
Event/WebhookCarries state change to backendCritical for final verification
const { data: created } = await api.post("/v1/payments", {
  amount: 12500,
  currency: "TRY",
  auto_capture: true,
});

const { data } = await api.post(`/v1/payments/${created.payment.id}/confirm`, {
  payment_method: { id: "pm_123" },
  payer_identity: { ip_address: clientIp, user_agent: ua },
});

if (data.payment.status === "REQUIRES_ACTION" && data.confirmResult.paymentNextAction?.url) {
  redirectUser(data.confirmResult.paymentNextAction.url);
}

Hosted Checkout flow

Hosted Checkout manages the payment experience inside Checkout Session.

In this model the merchant:

  • Creates a Checkout Session.
  • Redirects the user with checkout URL/token.
  • Leaves payment method collection and some 3DS/REQUIRES_ACTION steps to the checkout experience.
  • Verifies the final result with webhook or GET /v1/payments/:id.

Hosted Checkout is recommended for fast integration and a more controlled payment experience.

API-only flow

In the API-only model the merchant manages its own frontend and backend experience.

In this model the merchant:

  • Manages Payment Method collection UI.
  • Calls Confirm directly.
  • Handles redirect/challenge when REQUIRES_ACTION and paymentNextAction arrive.
  • Verifies final state after gateway 3DS callback via webhook or payment query.

API-only flow suits teams that want custom checkout, platform experience, or more UI control.

3DS / requires_action flow

Not every payment returns SUCCEEDED or AUTHORIZED immediately. With secure_mode or provider requirements, the adapter may return requires_action; Payment becomes REQUIRES_ACTION.

In this case:

  1. Confirm result may have confirmResult.ok === true and payment.status === "REQUIRES_ACTION".
  2. Merchant redirects the user with confirmResult.paymentNextAction.url.
  3. After challenge, the gateway processes resume via three-d-secure-callback-urls/:id.
  4. Final state is verified with event/webhook or payment GET.

Async and uncertain outcomes

Some provider behaviors may not produce an immediate terminal result. On timeout or uncertain status, the merchant should query the existing Payment (include_charges=true) idempotently instead of opening a new Payment.

There is no separate PENDING adapter kind on Payment; async waiting is usually managed with PROCESSING status or operational monitoring.

Webhook/event flow

Frontend or confirm response guides user experience; webhook closes merchant backend state.

Webhook handler should:

  • Be idempotent
  • Tolerate duplicate delivery
  • Match records by Payment ID and trace/request id
  • Interpret event types such as payment.succeeded, payment.requires_action, payment.authorized, charge.declined separately

Capture / refund / cancel

OperationConditionEffect
CapturePayment AUTHORIZED, auto_capture: falseCharge capture, Payment SUCCEEDED
RefundAfter successful collectionRefund record, Payment REFUNDED
CancelPayment AUTHORIZEDAuthorization cancel, Payment CANCELED

These operations appear in Payment context; financial effect is tracked at Charge level.

Error / decline behaviors

A successful payment integration is understood by handling decline, timeout, 3DS, and webhook behavior correctly, not only success responses.

  • Decline: Charge DECLINED, Payment usually REQUIRES_PAYMENT_METHOD (re-confirm can be planned).
  • Hard decline: Do not retry aggressively with the same card; ask for a different method or user action.
  • Soft decline: Routing may try the next provider candidate (new charge attempt).
  • Timeout: Check GET /payments/:id and webhook logs before opening a new payment.
  • 3DS failed: Controlled retry after REQUIRES_ACTION or REQUIRES_PAYMENT_METHOD.

On this page