import {z} from 'zod' export type PaymentSessionPaymentPlanRecurring = {amount_variability?: ('Fixed' | 'Variable') | undefined, days_between_payments?: number | undefined, total_number_of_payments?: number | undefined, current_payment_number?: number | undefined, expiry?: string | undefined, name?: string | undefined, start_date?: string | undefined, amount?: number | undefined}; export type IPAddress = string; export type PaymentInterfacesReference = string; export type AmountAllocations = Array<{id: string, amount: number, reference?: string | undefined, commission?: ({amount?: number | undefined, percentage?: number | undefined}) | undefined}>; export type PaymentInterfacesPhoneNumber = {country_code?: string | undefined, number?: string | undefined}; export type PaymentInterfacesCustomerSummary = {registration_date?: string | undefined, first_transaction_date?: string | undefined, last_payment_date?: string | undefined, total_order_count?: number | undefined, last_payment_amount?: number | undefined, is_premium_customer?: boolean | undefined, is_returning_customer?: boolean | undefined, lifetime_value?: number | undefined}; export type Address = {address_line1?: string | undefined, address_line2?: string | undefined, city?: string | undefined, state?: string | undefined, zip?: string | undefined, country?: string | undefined}; export type PhoneNumber = {country_code?: string | undefined, number?: string | undefined}; export type PaymentInterfacesRecipient = {dob?: string | undefined, account_number?: string | undefined, address?: Address | undefined, first_name?: string | undefined, last_name?: string | undefined}; export type PaymentInterfacesProcessingAirlinePassengerData = {first_name?: string | undefined, last_name?: string | undefined, date_of_birth?: string | undefined, address?: ({country?: string | undefined}) | undefined}; export type PaymentInterfacesProcessingAirlineData = Array<{ticket?: ({number?: string | undefined, issue_date?: string | undefined, issuing_carrier_code?: string | undefined, travel_package_indicator?: string | undefined, travel_agency_name?: string | undefined, travel_agency_code?: string | undefined}) | undefined, passenger?: (Array | PaymentInterfacesProcessingAirlinePassengerData) | undefined, flight_leg_details?: (Array<{flight_number?: string | undefined, carrier_code?: string | undefined, class_of_travelling?: string | undefined, departure_airport?: string | undefined, departure_date?: string | undefined, departure_time?: string | undefined, arrival_airport?: string | undefined, stop_over_code?: string | undefined, fare_basis_code?: string | undefined}>) | undefined}>; export type PaymentInterfacesProcessingAccommodationData = Array<{name?: string | undefined, booking_reference?: string | undefined, check_in_date?: string | undefined, check_out_date?: string | undefined, address?: ({address_line1?: string | undefined, zip?: string | undefined}) | undefined, state?: string | undefined, country?: string | undefined, city?: string | undefined, number_of_rooms?: number | undefined, guests?: (Array<{first_name?: string | undefined, last_name?: string | undefined, date_of_birth?: string | undefined}>) | undefined, room?: (Array<{rate?: string | undefined, number_of_nights_at_room_rate?: string | undefined}>) | undefined}>; export type PaymentInterfacesPanPreference = 'fpan' | 'dpan'; export type PaymentInterfacesProvisionNetworkToken = boolean; export type PaymentInterfacesProcessingAggregator = {sub_merchant_id?: string | undefined, aggregator_id_visa?: string | undefined, aggregator_id_mc?: string | undefined}; export type PaymentInterfacesProcessing = {aft?: boolean | undefined, discount_amount?: number | undefined, shipping_amount?: number | undefined, tax_amount?: number | undefined, invoice_id?: string | undefined, brand_name?: string | undefined, locale?: string | undefined, partner_customer_risk_data?: ({key?: string | undefined, value?: string | undefined}) | undefined, custom_payment_method_ids?: Array | undefined, airline_data?: PaymentInterfacesProcessingAirlineData | undefined, accommodation_data?: PaymentInterfacesProcessingAccommodationData | undefined, order_id?: string | undefined, surcharge_amount?: number | undefined, duty_amount?: number | undefined, shipping_tax_amount?: number | undefined, affiliate_id?: string | undefined, affiliate_url?: string | undefined, purchase_country?: string | undefined, merchant_initiated_reason?: ('Delayed_charge' | 'Resubmission' | 'No_show' | 'Reauthorization') | undefined, campaign_id?: number | undefined, original_order_amount?: number | undefined, receipt_id?: string | undefined, merchant_callback_url?: string | undefined, line_of_business?: string | undefined, pan_preference?: PaymentInterfacesPanPreference | undefined, provision_network_token?: PaymentInterfacesProvisionNetworkToken | undefined, reconciliation_id?: string | undefined, aggregator?: PaymentInterfacesProcessingAggregator | undefined}; export type PaymentInterfacesPaymentMethodEnum = 'alipay_cn' | 'alipay_hk' | 'alma' | 'applepay' | 'bancontact' | 'benefit' | 'bizum' | 'card' | 'dana' | 'eps' | 'gcash' | 'googlepay' | 'ideal' | 'kakaopay' | 'klarna' | 'knet' | 'mbway' | 'mobilepay' | 'multibanco' | 'octopus' | 'p24' | 'paynow' | 'paypal' | 'plaid' | 'qpay' | 'sepa' | 'stcpay' | 'stored_card' | 'tabby' | 'tamara' | 'tng' | 'truemoney' | 'twint' | 'vipps' | 'wechatpay'; export type PaymentInterfacesPaymentMethods = Array; export type PaymentInterfacesProducts = Array<{reference?: string | undefined, url?: string | undefined, name: string, quantity: number, price: number}>; export type PaymentInterfacesSender = Record; export type Timestamp = string; export type Purpose = 'donations' | 'education' | 'emergency_need' | 'expatriation' | 'family_support' | 'financial_services' | 'gifts' | 'income' | 'insurance' | 'investment' | 'it_services' | 'leisure' | 'loan_payment' | 'medical_treatment' | 'other' | 'pension' | 'royalties' | 'savings' | 'travel_and_tourism'; export type PaymentInterfacesStorePaymentDetails = 'disabled' | 'enabled'; export type HostedPaymentsRequest = {amount?: number | undefined, currency: string, payment_type?: ('Regular' | 'Recurring') | undefined, authorization_type?: ('Final' | 'Estimated') | undefined, payment_plan?: PaymentSessionPaymentPlanRecurring | undefined, payment_ip?: IPAddress | undefined, billing_descriptor?: ({name: string, city: string, reference?: string | undefined}) | undefined, reference?: PaymentInterfacesReference | undefined, description?: string | undefined, display_name?: string | undefined, processing_channel_id?: string | undefined, amount_allocations?: AmountAllocations | undefined, customer?: ({email?: string | undefined, name?: string | undefined, phone?: PaymentInterfacesPhoneNumber | undefined, summary?: PaymentInterfacesCustomerSummary | undefined}) | undefined, shipping?: ({address: Address, phone?: PhoneNumber | undefined}) | undefined, billing: {address: Address, phone?: PhoneNumber | undefined}, recipient?: PaymentInterfacesRecipient | undefined, processing?: PaymentInterfacesProcessing | undefined, allow_payment_methods?: PaymentInterfacesPaymentMethodEnum | undefined, disabled_payment_methods?: PaymentInterfacesPaymentMethods | undefined, products?: PaymentInterfacesProducts | undefined, risk?: {enabled: boolean} | undefined, customer_retry?: ({max_attempts?: number | undefined}) | undefined, sender?: PaymentInterfacesSender | undefined, success_url: string, cancel_url: string, failure_url: string, metadata?: Record | undefined, locale?: ('ar' | 'da-DK' | 'de-DE' | 'el' | 'en-GB' | 'es-ES' | 'fi-FI' | 'fil-PH' | 'fr-FR' | 'hi-IN' | 'id-ID' | 'it-IT' | 'ja-JP' | 'ms-MY' | 'nb-NO' | 'nl-NL' | 'pt-PT' | 'sv-SE' | 'th-TH' | 'vi-VN' | 'zh-CN' | 'zh-HK' | 'zh-TW') | undefined, '3ds'?: ({enabled?: boolean | undefined, attempt_n3d?: boolean | undefined, challenge_indicator?: ('no_preference' | 'no_challenge_requested' | 'challenge_requested' | 'challenge_requested_mandate') | undefined, allow_upgrade?: boolean | undefined, exemption?: ('low_value' | 'secure_corporate_payment' | 'trusted_listing' | 'transaction_risk_assessment' | '3ds_outage' | 'sca_delegation' | 'out_of_sca_scope' | 'other' | 'low_risk_program' | 'recurring_operation') | undefined}) | undefined, capture?: boolean | undefined, capture_on?: Timestamp | undefined, instruction?: ({purpose?: Purpose | undefined}) | undefined, payment_method_configuration?: ({applepay?: ({account_holder?: {type: string} | undefined, store_payment_details?: PaymentInterfacesStorePaymentDetails | undefined}) | undefined, card?: ({store_payment_details?: ('disabled' | 'enabled' | 'collect_consent') | undefined, account_holder?: {type: string} | undefined}) | undefined, googlepay?: ({account_holder?: {type: string} | undefined, store_payment_details?: PaymentInterfacesStorePaymentDetails | undefined}) | undefined, stored_card?: ({customer_id?: string | undefined, instrument_ids?: Array | undefined, default_instrument_id?: string | undefined}) | undefined}) | undefined}; export type CreateApiHostedPaymentsArgs = {body: HostedPaymentsRequest}; export type CreateApiHostedPaymentsOptions = {baseUrl: string, ApiSecretKey?: string | undefined, fetch?: typeof fetch | undefined}; export const hostedPaymentId = z.string().min(16).max(16); export const link = z.object({href: z.string()}); export const hostedPaymentsResponse = z.object({id: hostedPaymentId, reference: z.string().optional(), warnings: z.array(z.object({code: z.string().optional(), description: z.string().optional(), value: z.enum(["card", "sofort", "ideal", "knet", "bancontact", "eps", "p24", "multibanco"]).optional()})).optional(), _links: z.object({self: link.optional(), redirect: link.optional()})}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Create a Hosted Payments Page session * * POST /hosted-payments */ export const createApiHostedPayments = async (args: CreateApiHostedPaymentsArgs, options: CreateApiHostedPaymentsOptions) => { const {baseUrl, fetch: fetchFn = fetch, ApiSecretKey} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (ApiSecretKey !== undefined) headers.set("Authorization", ApiSecretKey) const url = `${baseUrl.replace(/\/+$/, '')}/hosted-payments${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(hostedPaymentsResponse, await res.json()) };