import {z} from 'zod' export type GetApiPaymentsArgs = {limit?: number | undefined, skip?: number | undefined, reference: string}; export type GetApiPaymentsOptions = {baseUrl: string, OAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const paymentId = z.string().min(30).max(30); export const serverTimestamp = z.string(); export const address = z.object({address_line1: z.string().max(200).optional(), address_line2: z.string().max(200).optional(), city: z.string().max(50).optional(), state: z.string().max(3).optional(), zip: z.string().max(50).optional(), country: z.string().min(2).max(2).optional()}); export const phoneNumber = z.object({country_code: z.string().min(1).max(7).optional(), number: z.string().max(25).optional()}); export const paymentResponseAchAccountHolder = z.object({account_name_inquiry: z.enum(["full_match", "partial_match", "no_match", "not_performed"]).optional(), account_name_inquiry_details: z.object({description: z.string().optional()}).optional()}); export const accountHolderEps = z.object({first_name: z.string(), last_name: z.string()}); export const paymentDetailsResponseSource = z.discriminatedUnion("type", [z.object({type: z.literal("card"), id: z.string().optional(), billing_address: address.optional(), phone: phoneNumber.optional(), expiry_month: z.number().int().gte(1), expiry_year: z.number().int(), name: z.string().optional(), scheme: z.string().optional(), scheme_local: z.string().optional(), local_schemes: z.array(z.string()).optional(), last4: z.string(), fingerprint: z.string(), bin: z.string().max(8), card_type: z.enum(["CREDIT", "DEBIT", "PREPAID", "CHARGE", "DEFERRED DEBIT"]).optional(), card_category: z.enum(["CONSUMER", "COMMERCIAL"]).optional(), card_wallet_type: z.enum(["applepay", "googlepay"]).optional(), issuer: z.string().optional(), issuer_country: z.string().min(2).max(2).optional(), product_id: z.string().optional(), product_type: z.string().optional(), avs_check: z.string().optional(), cvv_check: z.string().optional(), payment_account_reference: z.string().optional(), encrypted_card_number: z.string().optional(), account_update_status: z.enum(["card_updated", "card_expiry_updated", "card_closed", "contact_cardholder"]).optional(), account_update_failure_code: z.string().optional(), account_holder: z.object({}).optional()}), z.object({type: z.literal("ach"), id: z.string(), account_holder: paymentResponseAchAccountHolder.optional()}), z.object({type: z.literal("alma")}), z.object({type: z.literal("bancontact"), iban: z.string().max(34).optional(), bic: z.string().max(11).optional()}), z.object({type: z.literal("blik"), id: z.string().optional()}), z.object({type: z.literal("currency_account"), id: z.string(), amount: z.number().int().optional()}), z.object({type: z.literal("eps"), purpose: z.string().max(27).optional(), bic: z.string().max(11).optional(), iban: z.string().max(34).optional(), account_holder_name: z.string().optional(), account_holder: accountHolderEps.optional()}), z.object({type: z.literal("ideal"), account_holder: z.string().optional(), account_holder_name: z.string().optional(), bic: z.string().optional(), description: z.string().optional(), iban: z.string().max(34).optional()}), z.object({type: z.literal("klarna"), account_holder: z.object({first_name: z.string().optional(), last_name: z.string().optional(), billing_address: z.object({address_line1: z.string().optional(), address_line2: z.string().optional(), city: z.string(), zip: z.string(), country: z.string().min(2).max(2)}).optional(), email: z.string().optional(), date_of_birth: z.string().optional(), account_holder_name: z.string().optional(), iban: z.string().optional(), account_number: z.string().optional(), bank_code: z.string().optional(), bank_name: z.string().optional(), bic: z.string().optional(), gender: z.string().optional(), phone: z.object({country_code: z.string().min(1).max(7).optional(), number: z.string().min(6).max(25).optional()}).optional()}).optional()}), z.object({type: z.literal("knet"), language: z.enum(["ar", "en"]).optional(), user_defined_field1: z.string().optional(), user_defined_field2: z.string().optional(), user_defined_field3: z.string().optional(), user_defined_field4: z.string().optional(), user_defined_field5: z.string().optional(), card_token: z.string().optional(), ptlf: z.string().max(45).optional(), knet_payment_id: z.string().optional(), knet_result: z.string().optional(), inquiry_result: z.string().optional(), bank_reference: z.string().optional(), knet_transaction_id: z.string().optional(), auth_code: z.string().optional(), auth_response_code: z.string().optional(), post_date: z.string().optional(), avr: z.string().optional(), error: z.string().optional(), error_text: z.string().optional()}), z.object({type: z.literal("multibanco"), payment_reference: z.string().optional(), service_supplier_id: z.string().optional()}), z.object({type: z.literal("p24"), p24_descriptor: z.string().optional()}), z.object({type: z.literal("paypal"), account_holder: z.object({email: z.string().optional(), full_name: z.string().optional()}).optional()}), z.object({type: z.literal("qpay"), description: z.string(), qpay_status: z.string().optional(), status_message: z.string().optional(), confirmation_id: z.string().optional(), pun: z.string()}), z.object({type: z.literal("sepa"), id: z.string()}), z.object({type: z.literal("bacs"), id: z.string()}), z.object({type: z.literal("swish")}), z.object({type: z.literal("sequra")}), z.object({type: z.literal("tamara")})]); export const paymentResponseDestination = z.object({type: z.literal("bank_account"), id: z.string()}); export const paymentResponseBalances = z.object({total_authorized: z.number().int().optional(), total_voided: z.number().int().optional(), available_to_void: z.number().int().optional(), total_captured: z.number().int().optional(), available_to_capture: z.number().int().optional(), total_refunded: z.number().int().optional(), available_to_refund: z.number().int().optional()}); export const responseCode = z.enum(["Y", "N", "U", "A", "C", "D", "R", "I"]); export const trustedListing = z.object({status: z.enum(["Y", "N", "E", "P", "R", "U"]).optional(), source: z.string().optional()}); export const schema3dsData = z.object({downgraded: z.boolean().optional(), enrolled: z.string().optional(), signature_valid: z.string().optional(), authentication_response: responseCode.optional(), authentication_status_reason: z.string().optional(), cryptogram: z.string().optional(), xid: z.string().optional(), eci: z.string().optional(), version: z.string().optional(), exemption: z.enum(["3ds_outage", "data_share", "low_risk_program", "low_value", "none", "other", "out_of_sca_scope", "sca_delegation", "secure_corporate_payment", "transaction_risk_assessment", "trusted_listing", "trusted_listing_prompt"]).optional(), exemption_applied: z.string().optional(), challenged: z.boolean().optional(), upgrade_reason: z.string().optional(), trusted_listing: trustedListing.optional()}); export const paymentAuthenticationData = z.object({experience: z.enum(["google_spa", "3ds"]).optional()}); export const customerSummary = z.object({registration_date: z.string().optional(), first_transaction_date: z.string().optional(), last_payment_date: z.string().optional(), total_order_count: z.number().int().optional(), last_payment_amount: z.number().optional(), is_premium_customer: z.boolean().optional(), is_returning_customer: z.boolean().optional(), lifetime_value: z.number().optional()}); export const localBillingDescriptor = z.object({name: z.string(), character_set: z.enum(["kanji", "katakana"])}); export const billingDescriptor = z.object({name: z.string().max(25), city: z.string().max(13), reference: z.string().max(50).optional(), local_descriptors: z.array(localBillingDescriptor).nullable().optional()}); export const iPAddress = z.string().max(45); export const paymentDetailsResponseSender = z.discriminatedUnion("type", [z.object({type: z.enum(["individual", "corporate", "instrument"]), reference: z.string().optional(), first_name: z.string(), last_name: z.string(), address: address}), z.object({type: z.enum(["individual", "corporate", "instrument"]), reference: z.string().optional(), company_name: z.string(), address: address.optional()}), z.object({type: z.enum(["individual", "corporate", "instrument"]), reference: z.string().optional()})]); export const amountAllocations = z.array(z.object({id: z.string(), amount: z.number().int().gte(0).lte(9999999999), reference: z.string().max(50).optional(), commission: z.object({amount: z.number().int().gte(0).optional(), percentage: z.number().gte(0).lte(100).optional()}).optional()})); export const paymentRecipient = z.object({dob: z.string().max(10).optional(), account_number: z.string().max(34).optional(), address: address.optional(), zip: z.string().max(10).optional(), first_name: z.string().max(50).optional(), last_name: z.string().max(50).optional()}); export const airlineData = z.array(z.object({ticket: z.object({number: z.string().optional(), issue_date: z.string().optional(), issuing_carrier_code: z.string().optional(), travel_package_indicator: z.string().optional(), travel_agency_name: z.string().optional(), travel_agency_code: z.string().optional()}).optional(), passenger: z.array(z.object({first_name: z.string().optional(), last_name: z.string().optional(), date_of_birth: z.string().optional(), address: z.object({country: z.string().optional()}).optional()})).optional(), flight_leg_details: z.array(z.object({flight_number: z.string().optional(), carrier_code: z.string().optional(), class_of_travelling: z.string().optional(), departure_airport: z.string().optional(), departure_date: z.string().optional(), departure_time: z.string().optional(), arrival_airport: z.string().optional(), stop_over_code: z.string().optional(), fare_basis_code: z.string().optional()})).optional()})); export const accommodationData = z.array(z.object({name: z.string().optional(), booking_reference: z.string().optional(), check_in_date: z.string().optional(), check_out_date: z.string().optional(), address: z.object({address_line1: z.string().optional(), zip: z.string().optional()}).optional(), state: z.string().optional(), country: z.string().optional(), city: z.string().optional(), number_of_rooms: z.number().int().optional(), guests: z.array(z.object({first_name: z.string().optional(), last_name: z.string().optional(), date_of_birth: z.string().optional()})).optional(), room: z.array(z.object({rate: z.string().optional(), number_of_nights_at_room_rate: z.string().optional()})).optional(), property_phone: z.array(z.object({country_code: z.string().optional(), number: z.string().optional()})).optional(), customer_service_phone: z.array(z.object({country_code: z.string().optional(), number: z.string().optional()})).optional()})); export const processingData = z.object({preferred_scheme: z.enum(["mastercard", "visa", "cartes_bancaires", "accel", "discover", "eftpos", "maestro", "nyce", "pulse", "star"]).optional(), app_id: z.string().optional(), airline_data: airlineData.optional(), accommodation_data: accommodationData.optional(), partner_customer_id: z.string().optional(), partner_payment_id: z.string().optional(), partner_code: z.string().min(6).max(6).optional(), failure_code: z.string().optional(), partner_response_code: z.string().optional(), tax_amount: z.number().optional(), locale: z.string().min(2).max(10).optional(), retrieval_reference_number: z.string().optional(), partner_order_id: z.string().optional(), partner_status: z.string().optional(), partner_transaction_id: z.string().optional(), partner_error_codes: z.array(z.string()).optional(), partner_merchant_advice_code: z.string().optional(), partner_error_message: z.string().optional(), partner_authorization_code: z.string().optional(), partner_authorization_response_code: z.string().optional(), partner_fraud_status: z.string().optional(), pan_type_processed: z.enum(["fpan", "dpan"]).optional(), fallback_source_used: z.boolean().optional(), custom_payment_method_ids: z.array(z.string()).optional(), aft: z.boolean().optional(), merchant_category_code: z.string().optional(), scheme_merchant_id: z.string().optional(), scheme: z.string().optional(), scheme_transaction_link_id: z.string().optional()}); export const items = z.array(z.object({type: z.enum(["digital", "discount", "physical"]).optional(), sub_type: z.enum(["blockchain", "cbdc", "cryptocurrency", "nft", "stablecoin"]).optional(), name: z.string().max(255).optional(), quantity: z.number().int().gte(1).optional(), unit_price: z.number().int().gte(0).optional(), reference: z.string().max(255).optional(), commodity_code: z.string().max(12).optional(), unit_of_measure: z.string().max(12).optional(), total_amount: z.number().optional(), tax_rate: z.number().optional(), tax_amount: z.number().optional(), tax_exempt: z.boolean().optional(), discount_amount: z.number().optional(), wxpay_goods_id: z.string().max(32).optional(), url: z.string().max(1024).optional(), image_url: z.string().max(1024).optional(), service_ends_on: z.string().optional(), purchase_country: z.string().max(2).optional(), foreign_retailer_amount: z.number().int().gte(0).optional()})); export const actionId = z.string().min(30).max(30); export const paymentActionSummary = z.object({id: actionId, type: z.enum(["Authorization", "Card Verification", "Void", "Capture", "Refund"]), response_code: z.string(), response_summary: z.string().optional()}); export const timestamp = z.string(); export const retryGetResponse = z.object({enabled: z.boolean(), attempts_made: z.number().int().gte(0).optional(), max_attempts: z.number().int().gte(1).lte(15).optional(), ends_on: timestamp.optional(), next_attempt_on: timestamp.optional()}); export const link = z.object({href: z.string()}); export const paymentDetails = z.object({id: paymentId, requested_on: serverTimestamp, source: paymentDetailsResponseSource.optional(), destination: paymentResponseDestination.optional(), amount: z.number().int(), amount_requested: z.number().int().optional(), currency: z.string().min(3).max(3), payment_type: z.enum(["Regular", "Recurring", "MOTO", "Installment", "PayLater", "Unscheduled"]).optional(), payment_plan: z.union([z.object({amount_variability: z.enum(["Fixed", "Variable"]).optional(), days_between_payments: z.number().int().optional(), total_number_of_payments: z.number().int().optional(), current_payment_number: z.number().int().optional(), expiry: z.string().optional(), name: z.string().max(35).optional(), start_date: z.string().optional(), amount: z.number().int().gte(1).optional()}), z.object({financing: z.boolean().optional(), days_between_payments: z.number().int().optional(), total_number_of_payments: z.number().int().optional(), current_payment_number: z.number().int().optional(), expiry: z.string().optional(), name: z.string().max(35).optional(), start_date: z.string().optional(), amount: z.number().int().gte(1).optional()})]).optional(), reference: z.string().optional(), description: z.string().optional(), approved: z.boolean(), expires_on: z.string().optional(), status: z.enum(["Pending", "Authorized", "Card Verified", "Voided", "Partially Captured", "Captured", "Partially Refunded", "Refunded", "Declined", "Canceled", "Expired", "Paid", "Retry Scheduled"]), balances: paymentResponseBalances.optional(), "3ds": schema3dsData.optional(), authentication: paymentAuthenticationData.optional(), risk: z.object({flagged: z.boolean().optional(), score: z.number().gte(0).lte(100).optional()}).optional(), customer: z.object({id: z.string(), email: z.string().optional(), name: z.string().optional(), summary: customerSummary.optional()}).optional(), billing_descriptor: billingDescriptor.optional(), shipping: z.object({address: address.optional(), phone: phoneNumber.optional()}).optional(), payment_ip: iPAddress.optional(), sender: paymentDetailsResponseSender.optional(), amount_allocations: amountAllocations.optional(), recipient: paymentRecipient.optional(), processing: processingData.optional(), items: items.optional(), metadata: z.object({}).optional(), eci: z.string().optional(), scheme_id: z.string().optional(), actions: z.array(paymentActionSummary).optional(), retry: retryGetResponse.optional(), cko_network_token_available: z.boolean().optional(), instruction: z.object({purpose: z.string().optional()}).optional(), _links: z.object({self: link, actions: link, authorize: link.optional(), void: link.optional(), capture: link.optional(), refund: link.optional()})}); export const paymentPaged = z.object({limit: z.number().int().optional(), skip: z.number().int().optional(), total_count: z.number().int().optional(), data: z.array(paymentDetails).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 }; /** * Get payment lists * * GET /payments * * Also accepts auth: ApiSecretKey */ export const getApiPayments = async (args: GetApiPaymentsArgs, options: GetApiPaymentsOptions) => { const {baseUrl, fetch: fetchFn = fetch, OAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.limit != null) query.append("limit", String(args.limit)) if (args.skip != null) query.append("skip", String(args.skip)) if (args.reference != null) query.append("reference", String(args.reference)) if (OAuth !== undefined) headers.set('authorization', `Bearer ${OAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/payments${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(paymentPaged, await res.json()) };