/** * Public payment-link + checkout-status routes — owned by * `@voyant-travel/storefront`. * * agent-quality: file-size exception -- the public payment-link surface * (config, retry, resolve, start-card, trip/booking summary, checkout-status) * is one cohesive route family backed by the finance payment-session record; * splitting it would scatter a single checkout contract. * * GET /v1/public/payment-link-config * POST /v1/public/payment-link/:sessionId/retry * GET /v1/public/payment-link/resolve * POST /v1/public/payment-link/:sessionId/start-card * GET /v1/public/payment-link/:sessionId/trip-summary * GET /v1/public/payment-link/:sessionId/booking-summary * GET /v1/public/bookings/:bookingId/checkout-status * * The routes are mounted at their ABSOLUTE public paths so the deployment can * lazy-mount them via `lazyRoutes.paths`. All cross-module access that * storefront does not already depend on (inventory product media, trip * envelopes/components reconciliation, the card-payment provider, and the * operator settings + checkout base URL) is INJECTED via `options` — the * package never statically imports inventory / trips / the netopia plugin / * the operator settings module. * * Storefront already depends acyclically on `@voyant-travel/bookings` and * `@voyant-travel/finance`, so the booking / invoice / payment-session reads * use those schemas directly. */ import { OpenAPIHono } from "@hono/zod-openapi"; import { applyPaymentAdapterCallbackEvent, refreshPaymentAdapterStatus } from "@voyant-travel/finance"; import type { ApiModule } from "@voyant-travel/hono/module"; import { type PaymentAdapter, type PaymentCallbackRequest } from "@voyant-travel/payments"; import type { Context } from "hono"; /** Absolute path matchers for the deployment's lazy route composition. */ export declare const PAYMENT_LINK_ROUTE_PATHS: readonly ["/v1/public/payment-link-config", "/v1/public/payment-link/:sessionId/retry", "/v1/public/payment-link/resolve", "/v1/public/payment-link/:sessionId/start-card", "/v1/public/payment-link/:sessionId/trip-summary", "/v1/public/payment-link/:sessionId/booking-summary", "/v1/public/bookings/:bookingId/checkout-status", "/v1/public/payment-link/callback"]; /** Resolved bank-transfer beneficiary details from operator settings + env. */ export interface PaymentLinkBankTransferDetails { beneficiary: string; iban: string; bankName?: string | null; } /** A resolved trip component, with optional product enrichment. */ export interface PaymentLinkTripComponent { id: string; kind: string; entityModule: string | null; entityId: string | null; description: string | null; status: string | null; sequence: number | null; componentTotalAmountCents: number | null; componentCurrency: string | null; metadata: Record | null; } /** A resolved trip envelope + its visible components and product enrichment. */ export interface PaymentLinkTripData { envelope: { id: string; status: string | null; }; /** * Visible (non-removed, non-cancelled) components, already ordered by * sequence then createdAt. */ components: PaymentLinkTripComponent[]; /** product id → display name (from the inventory product record). */ productNameById: Map; /** product id → cover image (from inventory product media). */ mediaByProductId: Map; } /** The payment-session record fields the handlers read across routes. */ export interface PaymentLinkSessionInput { invoiceId: string | null; amountCents: number; currency: string; } export interface PaymentLinkCardPaymentBilling { email: string; phone?: string; firstName: string; lastName?: string; city?: string; country?: number | string; state?: string; postalCode?: string; details?: string; } export interface PaymentLinkStartCardPaymentInput { id: string; payerName: string | null; payerEmail: string | null; notes: string | null; redirectUrl: string | null; billing?: PaymentLinkCardPaymentBilling; description?: string; returnUrl?: string; cancelUrl?: string; shipping?: Record; } /** * Deployment-supplied access the payment-link handlers need. Everything here * encapsulates a module storefront does not statically depend on, so the * package stays free of inventory / trips / netopia / operator-settings * imports. */ export interface PaymentLinkRoutesOptions { /** * Resolve the bank-transfer beneficiary details (operator settings merged * with deploy-wide env defaults), or `null` when not configured. */ resolveBankTransferDetails(c: Context): Promise; /** Resolve the public checkout base URL from the deployment bindings. */ resolvePublicCheckoutBaseUrl(c: Context): string | null; /** * Best-effort: ensure a fresh payment session can be started on the card * provider, returning the redirect URL (or null). Returns `{ configured: * false }` when no card processor is wired so the handler can 503. May throw * — the handler maps the error to a 502. */ startCardPayment(c: Context, session: PaymentLinkStartCardPaymentInput): Promise<{ configured: true; redirectUrl: string | null; } | { configured: false; }>; /** * Verify an inbound processor IPN/webhook and apply its event (mark the * payment session paid → complete the booking). Absent when no payment * adapter is wired. Fails closed: an unverified callback is rejected. */ verifyAndApplyPaymentCallback?(c: Context, request: PaymentCallbackRequest): Promise<{ ok: true; } | { ok: false; reason: string; }>; /** * Best-effort reconciliation for a booking-scoped card session. Managed * deployments use the deployment-authenticated status RPC; the adapter and * Finance own canonical provider correlation, leasing, and idempotent * completion. */ refreshPaymentSessionStatus?(c: Context, paymentSessionId: string): Promise; /** * Resolve a trip envelope (+ reconcile a paid checkout) and its visible * components with product-media enrichment, or `null` when the envelope is * gone. Encapsulates the trips + inventory schema reads. */ resolveTripData(c: Context, tripEnvelopeId: string, session: { id: string; status: string | null; amountCents: number; currency: string; provider: string | null; }): Promise; } /** * Build the public payment-link routes. Paths are ABSOLUTE so the deployment * can lazy-mount the returned app directly via `lazyRoutes.paths`. */ export declare function createPaymentLinkRoutes(options: PaymentLinkRoutesOptions): OpenAPIHono; /** Package-owned module descriptor; deployments inject provider and projection adapters. */ export declare function createPaymentLinkApiModule(options: PaymentLinkRoutesOptions): ApiModule; export declare const createPaymentLinkVoyantRuntime: import("@voyant-travel/core/project").VoyantGraphRuntimeFactory; export declare function createPaymentStatusRefreshHandler(adapter: PaymentAdapter, dependencies?: { refreshStatus?: typeof refreshPaymentAdapterStatus; }): NonNullable; export declare function createVerifiedPaymentCallbackHandler(adapter: PaymentAdapter, dependencies?: { applyEvent?: typeof applyPaymentAdapterCallbackEvent; }): NonNullable;