alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
121 lines (108 loc) • 3.9 kB
text/typescript
import type { PaymentIntentEntity } from "../entities/paymentIntents.ts";
export interface CreateSessionResult {
url: string;
providerRef: string;
}
export interface RefundResult {
providerRef: string;
}
export interface WebhookEvent {
providerRef: string;
/**
* Secondary reference to try when `providerRef` matches no stored intent.
* Checkout-session events carry BOTH a session id and a PaymentIntent id,
* while the stored intent ref is whichever existed at session-creation
* time (the PI when eager, the session id when the PSP creates the PI
* lazily — e.g. Stripe Checkout on connected accounts).
*/
providerRefAlt?: string;
status: string;
/**
* PSP account that emitted the event, when delivered by a
* connected-accounts endpoint (Stripe: `acct_…` on `connect: true`
* endpoints). Lets multi-tenant consumers route the event to the right
* tenant before resolving the intent.
*/
account?: string;
raw: unknown;
}
export interface CreatePaymentMethodResult {
providerRef: string;
type: string;
brand?: string;
last4?: string;
expMonth?: number;
expYear?: number;
}
export abstract class PaymentProvider {
/**
* Create a checkout session with the PSP.
* Returns a URL to redirect the user to, and the PSP's reference ID.
*/
abstract createSession(
intent: PaymentIntentEntity,
options: {
returnUrl: string;
authorize?: boolean;
stripeAccount?: string;
applicationFeeAmount?: number;
/** Pre-fill the payer's email on the hosted checkout page. */
customerEmail?: string;
},
): Promise<CreateSessionResult>;
/**
* Capture a previously authorized payment.
* Amount can differ from the original authorization (partial capture).
*/
abstract capturePayment(providerRef: string, amount: number): Promise<void>;
/**
* Void/cancel a previously authorized payment before capture.
*/
abstract voidPayment(providerRef: string): Promise<void>;
/**
* Refund a captured payment (partial or full).
*/
abstract refundPayment(
providerRef: string,
amount: number,
options?: { stripeAccount?: string },
): Promise<RefundResult>;
/**
* Parse and verify the authenticity of an incoming PSP webhook request.
*
* Implementations MUST establish authenticity before returning. Two
* common strategies, both acceptable:
*
* - Signature verification (Stripe, Adyen): verify an HMAC header
* against the raw body using a shared secret. Throw if invalid.
* - Re-fetch (Mollie, legacy webhooks): the body only carries an id;
* call back into the PSP API with your authenticated client to
* fetch the real resource state. The fetch itself is the auth —
* an attacker can POST a fake id but cannot influence the result.
*
* Throw an error if authenticity cannot be established. This endpoint
* has no $secure middleware; provider verification is its only auth.
*/
abstract parseWebhook(request: Request): Promise<WebhookEvent>;
/**
* Store a payment method token with the PSP and return the saved
* instrument's reference. Implementations that don't support
* tokenize-then-attach (e.g. Mollie, where mandates are created by
* making a "first" payment) MAY throw to signal the host app to use
* the checkout flow with `setup_future_usage`-style options instead.
*/
abstract createPaymentMethod(
userId: string,
token: string,
): Promise<CreatePaymentMethodResult>;
/**
* Delete a stored payment method from the PSP. Implementations that
* don't manage payment methods directly MAY no-op.
*/
abstract deletePaymentMethod(providerRef: string): Promise<void>;
/**
* Expire/cancel a checkout session on the PSP side.
* Called during stale session cleanup.
*/
abstract expireSession(providerRef: string): Promise<void>;
}