Gateway Interface
Payment gateway contract used by order checkout and buy-now flows.
Gateway Interface
Audience: Backend developers implementing gateways Scope: Initiate, verify, redirect payload parsing, optional webhook support
Interface Contract
export type InitiationType = "form_post" | "redirect" | "sdk" | "cod";
export interface PaymentGateway {
readonly name: string;
initiate(params: InitiatePaymentParams): Promise<InitiatePaymentResult>;
verify(params: VerifyPaymentParams): Promise<VerifyPaymentResult>;
parseRedirectPayload?(rawPayload: Record<string, unknown>):
| ParsedPaymentRedirectPayload
| Promise<ParsedPaymentRedirectPayload>;
}initiate()
PaymentService creates a pending payment, then calls gateway initiate().
export interface InitiatePaymentParams {
amountNpr: number;
referenceId: number;
referenceType: string;
userId: string;
successUrl: string;
failureUrl: string;
}
export interface InitiatePaymentResult {
gatewayTransactionId: string;
initiationType: InitiationType;
redirectUrl: string;
gatewayPayload: Record<string, string>;
}verify()
Used during redirect reconciliation.
export interface VerifyPaymentParams {
gatewayTransactionId: string;
gatewayResponse: Record<string, unknown>;
}
export interface VerifyPaymentResult {
success: boolean;
amountNpr: number;
}Stripe-Specific Extension
Stripe gateway adds a webhook signature helper for controller use:
constructWebhookEvent(rawBody: Buffer | string, signature: string): Stripe.EventWebhook-first finalization is handled by PaymentService.processStripeWebhookEvent(...).
Frontend Rule
Frontend logic is always:
- call initiation endpoint once;
- perform redirect/form-post by
initiationType; - wait for result-page redirect.
No frontend manual verification call is required.
Pending-Collection Gateways (COD)
COD is a special gateway that does not require a redirect or webhook. The PaymentService detects initiationType: "cod" after gateway.initiate() returns and creates a pending collection reference without completing payment inline:
CodGateway.initiate()returnsinitiationType: "cod",gatewayTransactionId: "",redirectUrl: "".PaymentServiceupdates the payment record withgatewayTransactionId = "cod_{paymentId}"and keeps status"pending".PaymentServicedoes not emitpayment.completedfor COD checkout.- Order checkout confirms COD after reservation by setting
orders.paymentStatus = "cod_pending"while keepingorders.orderStatus = "payment_pending". - Admin cash collection completes the existing pending payment row and sets
orders.paymentStatus = "cod_collected". - Response to frontend:
initiationType: "cod",redirectUrl: returnUrl(set by order-customer service, not gateway).
No parseRedirectPayload() is needed for COD. No redirect controller is involved.