A payment gateway is a hosted transaction system that securely collects payment after a merchant creates a payment request and redirects the user into a gateway-controlled payment page.

The gateway frontend is responsible for:

  • loading payment session context
  • rendering payment methods
  • collecting payment input
  • handling payment state
  • returning final transaction result

Because payment involves external providers and banks, the frontend must handle both immediate user interaction and delayed transaction state safely.

R — Requirements

Functional Requirements

Core Payment Flow

The gateway should support:

  • session-based entry
  • payment method selection
  • payment submission
  • authentication flow
  • final status display
  • retry when allowed

Payment Methods

The gateway should support:

  • card
  • UPI
  • wallet
  • net banking

Payment State Handling

The UI should clearly represent:

  • processing
  • success
  • failed
  • pending

Non-Functional Requirements

Security

Sensitive payment input must remain isolated.

Reliability

Duplicate payment attempts should be prevented.

Performance

Payment UI should load quickly after redirect.

Accessibility

Payment controls should remain keyboard accessible.

A — Architecture

At architecture level, a hosted payment gateway usually exposes a JavaScript SDK so merchants do not directly handle sensitive payment details.

Instead of sending raw card data to the merchant backend, the browser loads the gateway SDK, tokenizes payment data inside the browser, and submits only a secure token for transaction execution.

This reduces merchant security burden and keeps sensitive payment data inside gateway-controlled boundaries.



End-to-End Payment Flow

A typical hosted payment flow with SDK-based tokenization works in two stages:

  • merchant creates payment session
  • gateway frontend executes payment using browser SDK

Complete Payment Flow

User clicks Pay


Merchant Frontend

POST /create-payment

Merchant Backend

│ create paymentIntent + session

Payment Gateway Backend

│ returns redirectUrl + sdk config

Browser redirects

Gateway Frontend (/session/:sessionId)

│ fetch session

Load Payment SDK

│ tokenize payment data

Gateway Backend

│ confirm payment using token

Payment Provider / Bank


Gateway Frontend Final State

Why JavaScript SDK Is Used

Sensitive payment details such as card number, CVV, and expiry should not pass through merchant-controlled systems.

The gateway SDK isolates this by handling sensitive input directly in the browser.

The merchant or gateway UI only interacts with secure SDK components.

Typical responsibilities of the SDK:

  • render secure payment fields
  • validate payment input
  • tokenize sensitive data
  • return secure payment token

This ensures raw payment data never becomes part of normal application state.


SDK Initialization

Once the gateway frontend loads session data, it initializes the SDK using session-bound configuration.

Example

const sdk = Gateway.init({
sessionId: "sess_7890"
});

The SDK now knows which active transaction it belongs to.

This binding is important because tokenization must remain tied to one valid payment session.


Secure Field Rendering

The SDK usually injects secure hosted fields into the payment page.

Instead of normal input fields, secure fields are controlled by the gateway.

Examples:

  • card number
  • expiry
  • CVV

This allows the gateway to isolate sensitive data from surrounding frontend logic.

Tokenization in Browser

When the user submits payment details, the SDK converts raw input into a payment token.

Example

const token = await sdk.tokenize();

The returned token represents payment data safely.

Example token:

tok_x9ab23

At this point raw payment details are discarded.

The frontend never stores card details after token generation.


Payment Confirmation Using Token

The gateway frontend sends only the token and payment intent reference to backend.

Example

POST /payments/pi_10234/confirm
{
token: "tok_x9ab23"
}

The backend uses this token to complete payment with provider systems.

This separation ensures backend never receives raw payment fields directly from UI.


Authentication Step

Some payment methods require additional verification after tokenization.

Typical examples:

  • OTP
  • bank challenge
  • redirect-based verification

The SDK or gateway frontend moves into authentication state before final payment completion.


Final Transaction Resolution

After provider processing completes, frontend queries current transaction status.

Possible final states:

  • success
  • failed
  • pending

The UI should always reflect backend-confirmed payment state.

SSR vs CSR vs SSG

Chosen: CSR

Area

Rendering Strategy

Why

Checkout interaction

CSR

Requires browser-side payment SDK execution

Payment status page

CSR

Depends on live transaction state

Confirmation page

SSR (optional)

Useful after payment completes

Payment systems are interaction-heavy.

Checkout requires:

  • provider SDK loading
  • secure iframe rendering
  • browser event handling

These are browser-native behaviors.

Server rendering adds little value during active payment execution.

That makes CSR the primary rendering model.

SPA vs MPA

Chosen: SPA

Payment flows benefit from single-page continuity.

SPA allows:

  • preserve transaction state
  • avoid full reload during payment step transitions
  • maintain provider SDK lifecycle

This is important because payment state must remain stable during:

  • retries
  • intermediate authentication
  • delayed responses

MPA introduces full navigation boundaries which increase state recovery complexity.

For critical checkout flows, SPA gives smoother control.

REST vs GraphQL

Chosen: REST

Payment systems typically use REST because transaction operations are strongly action-oriented.

Examples:

  • create payment intent
  • fetch payment status
  • confirm transaction

These operations map naturally to explicit endpoints.

REST also simplifies:

  • idempotency enforcement
  • backend observability
  • provider interoperability

GraphQL is less common because payments usually require strict endpoint semantics rather than flexible query composition.

Transport Protocol Choice

Chosen: HTTP/2

Payment systems benefit strongly from HTTP/2 because checkout often loads:

  • payment SDK
  • provider assets
  • transaction APIs

HTTP/2 improves:

  • multiplexing
  • header compression
  • parallel resource delivery

Compared to HTTP/1.1:

This reduces latency during checkout initialization.

HTTP/3 may help further on unstable mobile networks, but HTTP/2 remains standard for most payment stacks.

Communication Protocols

Payment systems are mostly request-driven, but some transaction visibility requires controlled realtime updates.

Primary Flow: HTTP

Used for:

  • create payment
  • confirm payment
  • fetch final status

This remains the core transport.

Delayed Confirmation: Short Polling

Chosen for browser-side status visibility

After payment submission, frontend may periodically request latest status:

GET /payments/:id/status

Why polling is required:

Because backend webhook updates are invisible directly to browser.

Polling allows frontend to detect delayed final confirmation safely.