ShiftxPay
Accept payments

3-D Secure & redirects

Handling authentication redirects and return URLs.

Some payments cannot complete in one synchronous step. A 3-D Secure challenge sends the buyer to their bank's authentication page; redirect-based methods (instant EFT, some wallets) send them to a bank or app. In both cases the buyer leaves the page and must come back. ShiftxPay handles this with a returnUrl, a return marker, a poll-confirm loop, and a webhook backstop.

returnUrl

Set returnUrl on mountCheckout to the page the buyer should land on after an external authentication or redirect step:

await mountCheckout({
  baseUrl: "https://api.lite.shiftxpay.com",
  sessionId: "cs_...",
  sessionSecret: "cs_secret_...",
  container: "#payment-element",
  returnUrl: "https://shop.example.com/checkout/return",
});
  • Peach embedded widget — straight-through card payments complete in place and never leave the page. A 3-D Secure challenge or a redirect-based method (instant EFT, some wallets) runs inside the widget's own flow and returns the buyer to your returnUrl.

For the hosted checkout page you do not set this yourself: the gateway threads its own return URL of the form {checkout-origin}/{id}?pp_return=1#{session_secret} into the PSP. The session secret rides in the fragment so it never reaches server logs or the Referer header.

The pp_return marker

The hosted page distinguishes a fresh open from a redirect return using the pp_return=1 query marker on the return URL:

  • No marker → a fresh open: mount the PSP surface and wait for the buyer.
  • pp_return=1 → the buyer is returning from an external step: do not re-mount the widget, go straight to confirming the outcome.

The poll-confirm loop

On return, the page confirms the session against the gateway:

POST /v1/checkout/{id}/confirm?secret={session_secret}

The gateway verifies the intent server-side at the PSP (it never trusts the browser) and responds with the session status:

StatusMeaningPage behaviour
completedThe payment is recorded.Show success; stop polling.
processingThe PSP is still settling.Keep polling, backing off.
requires_actionFurther authentication is pending.Keep polling, backing off.
failedThe payment failed.Show failure; stop polling.

The confirm call is idempotent — a completed session always returns its recorded payment — and is safe to retry, which is exactly what the poll loop does until the status resolves to completed or failed.

The webhook backstop

A buyer might close the tab and never return — yet the payment still settles at the PSP. ShiftxPay does not depend on the buyer coming back: the Peach inbound webhook drives the session to completion independently. The browser-confirm path and the webhook path both finalize through the same row- locked transition, so whichever arrives first records the payment and the other observes completed — the payment is never double-booked.

This is why you should treat your outbound webhook as the source of truth for the final payment state. The SDK's onSuccess is a fast path for the common case; the webhook is the guarantee. See Webhooks.

On this page