import {z} from 'zod' export type MerchantKey = string; export type BinKey = string; export type Mid = string; export type Mcc = string; export type SellerDoingBusinessAsName = string; export type AmexPhoneNumber = string; export type SellerLegalName = string; export type BusinessRegistrationNumber = string; export type SignerFirstName = string; export type SignerLastName = string; export type SignerIdentificationNumber = string; export type SignerDateOfBirth = string; export type AddressLine = string; export type AddressCity = string; export type PostalCode = string; export type CountryCodeAlpha3 = string; export type CountryCodeOnlyAlpha3 = {alpha3: CountryCodeAlpha3}; export type CountryCodeAlpha2 = string; export type CountryCodeOnlyAlpha2 = {alpha2: CountryCodeAlpha2}; export type CountryCodeNumeric = string; export type CountryCodeOnlyNumeric = {numeric: CountryCodeNumeric}; export type CountryCodeCreate = CountryCodeOnlyAlpha3 | CountryCodeOnlyAlpha2 | CountryCodeOnlyNumeric; export type StateOrProvince = string; export type AddressCreateForAmexSMApi = {line1: AddressLine, line2?: AddressLine | undefined, city: AddressCity, postalCode: PostalCode, countryCode: CountryCodeCreate, stateOrProvince?: StateOrProvince | undefined}; export type SignerCreate = {firstName: SignerFirstName, lastName: SignerLastName, identificationNumber: SignerIdentificationNumber, dateOfBirth: SignerDateOfBirth, address: AddressCreateForAmexSMApi}; export type AmexSponsoredMerchantEnrollmentCreate = {merchantKey: MerchantKey, type: 'amex_sm', binKey: BinKey, mid: Mid, mcc: Mcc, doingBusinessAsName: SellerDoingBusinessAsName, phoneNumber: AmexPhoneNumber, legalName: SellerLegalName, businessRegistrationNumber?: BusinessRegistrationNumber | undefined, signer: SignerCreate, reinstate?: boolean | undefined}; export type DiscoverMerchantType = 'self-managed-outlet' | 'headquarter-account' | 'outlet-reporting-to-headquarter'; export type DiscoverMid = string; export type DiscoverDoingBusinessAsName = string; export type PosDeviceDownloadIndicator = 'host-based-pos-device' | 'terminal-based-pos-device' | 'software-pos-device' | 'all-other-pos-devices' | 'unknown'; export type BusinessPrincipal = {firstName: string, lastName: string, socialSecurityNumber: string, homeAddress: {countryCode: CountryCodeAlpha3, stateOrProvince: string, city: string, line1: string, line2?: string | undefined, postalCode: string}}; export type DiscoverMerchantStatus = 'open' | 'open-active-bankruptcy' | 'open-existing-merchant-entitled-for-card-acceptance' | 'conversion-renumbered'; export type HeadquarterAccountNumber = string; export type DiscoverMerchantEnrollmentCreate = {merchantKey: MerchantKey, type: 'discover-mpr', binKey: BinKey, merchantType: DiscoverMerchantType, mid: DiscoverMid, doingBusinessAsName: DiscoverDoingBusinessAsName, mcc: Mcc, posDeviceDownloadIndicator?: PosDeviceDownloadIndicator | undefined, debtRepaymentIndicator: boolean, businessPrincipal: BusinessPrincipal, merchantStatus: DiscoverMerchantStatus, headquarterAccountNumber?: HeadquarterAccountNumber | undefined}; export type ScofProgramType = 'merchant_obo' | 'commerce_platform_obo'; export type ScofProgramName = string; export type ScofEnrollmentCreate = {merchantKey: MerchantKey, type: 'scof', binKey: BinKey, mid: Mid, programType: ScofProgramType, programName: ScofProgramName, mccs?: Array | undefined}; export type VauEnrollmentCreate = {merchantKey: MerchantKey, type: 'vau', binKey: BinKey, mid: Mid, mcc: Mcc}; export type BusinessIdentificationType = 'ABN' | 'ACN' | 'BIN' | 'BIR' | 'BN' | 'BRN' | 'BRNO' | 'CL' | 'CLN' | 'CN' | 'CNPJ' | 'CR' | 'CUIT' | 'EDRPOU' | 'EIN' | 'HKBR' | 'NATIONAL_ID' | 'NIB' | 'NID' | 'NZBN' | 'PAN' | 'RFC' | 'RNC' | 'RUC' | 'RUT' | 'SIN' | 'SSN' | 'TC' | 'UEN' | 'USCI' | 'VAT'; export type BusinessIdentificationValue = string; export type BusinessIdentification = {type: BusinessIdentificationType, value: BusinessIdentificationValue}; export type VtsEnrollmentCreate = {merchantKey: MerchantKey, type: 'vts', businessIdentification?: BusinessIdentification | undefined, binKey?: string | undefined, mid?: string | undefined}; export type CreateEnrollment = AmexSponsoredMerchantEnrollmentCreate | DiscoverMerchantEnrollmentCreate | ScofEnrollmentCreate | VauEnrollmentCreate | VtsEnrollmentCreate; export type CreateApiEnrollmentsArgs = {body: CreateEnrollment}; export type CreateApiEnrollmentsOptions = {baseUrl?: string | undefined, ApiKey?: {username: string, password: string} | undefined, fetch?: typeof fetch | undefined}; export const enrollmentKey = z.string(); export const status = z.enum(["active", "archived"]); export const agentKey = z.string(); export const merchantKey = z.string().min(5).max(120); export const enrollmentStatus = z.enum(["pending", "enrolled", "unenrolled", "pendingUnenroll", "error", "failed"]); export const authorizationCurrency = z.enum(["EUR", "USD", "AFN", "ALL", "DZD", "AOA", "XCD", "ARS", "AMD", "AWG", "AUD", "AZN", "BSD", "BHD", "BDT", "BBD", "BYN", "BZD", "XOF", "BMD", "INR", "BTN", "BOB", "BAM", "BWP", "NOK", "BRL", "BND", "BGN", "BIF", "CVE", "KHR", "XAF", "CAD", "KYD", "CLP", "CNY", "CNH", "COP", "KMF", "CDF", "NZD", "CRC", "HRK", "CUP", "CUC", "ANG", "CZK", "DKK", "DJF", "DOP", "EGP", "SVC", "ERN", "ETB", "FKP", "FJD", "XPF", "GMD", "GEL", "GHS", "GIP", "GTQ", "GBP", "GNF", "GYD", "HTG", "HNL", "HKD", "HUF", "ISK", "IDR", "IRR", "IQD", "ILS", "JMD", "JPY", "JOD", "KZT", "KES", "KPW", "KRW", "KWD", "KGS", "LAK", "LBP", "LSL", "ZAR", "LRD", "LYD", "CHF", "MOP", "MKD", "MGA", "MWK", "MYR", "MVR", "MRU", "MUR", "MXN", "MDL", "MNT", "MAD", "MZN", "MMK", "NAD", "NPR", "NIO", "NGN", "OMR", "PKR", "PAB", "PGK", "PYG", "PEN", "PHP", "PLN", "QAR", "RON", "RUB", "RWF", "SHP", "WST", "STN", "SAR", "RSD", "SCR", "SLL", "SLE", "SGD", "SBD", "SOS", "SSP", "LKR", "SDG", "SRD", "SZL", "SEK", "SYP", "TWD", "TJS", "TZS", "THB", "TOP", "TTD", "TND", "TRY", "TMT", "UGX", "UAH", "AED", "UYU", "UYW", "UZS", "VUV", "VES", "VND", "YER", "ZMW", "ZWL", "ZWG"]); export const mid = z.string().min(1).max(20); export const mcc = z.string().min(4).max(4); export const sellerLegalName = z.string().min(1).max(60); export const sellerDoingBusinessAsName = z.string().min(1).max(60); export const addressLine = z.string().min(1).max(40); export const addressCity = z.string().min(1).max(40); export const postalCode = z.string().min(1).max(10); export const countryCodeAlpha3 = z.string().min(3).max(3); export const countryCodeAlpha2 = z.string().min(2).max(2); export const countryCodeNumeric = z.string().min(3).max(3); export const countryCode = z.object({alpha3: countryCodeAlpha3, alpha2: countryCodeAlpha2, numeric: countryCodeNumeric}); export const stateOrProvince = z.string().min(1).max(120); export const addressForAmexSMApi = z.object({line1: addressLine, line2: addressLine.optional(), city: addressCity, postalCode: postalCode, countryCode: countryCode, stateOrProvince: stateOrProvince.optional()}); export const url = z.string().min(8).max(2048); export const businessRegistrationNumber = z.string().min(1).max(15); export const amexPhoneNumber = z.string(); export const signerFirstName = z.string().min(1).max(20); export const signerLastName = z.string().min(1).max(20); export const signerIdentificationNumber = z.string().min(1).max(30); export const signerDateOfBirth = z.string(); export const signer = z.object({firstName: signerFirstName, lastName: signerLastName, identificationNumber: signerIdentificationNumber, dateOfBirth: signerDateOfBirth, address: addressForAmexSMApi}); export const amexSponsoredMerchantEnrollmentDetail = z.object({key: z.string(), acquirerBin: z.string().min(10).max(10), sellerCurrency: authorizationCurrency, mid: mid, mcc: mcc, legalName: sellerLegalName, doingBusinessAsName: sellerDoingBusinessAsName, sellerEmail: z.string().max(254), registeredAddress: addressForAmexSMApi, websiteUrl: url, businessRegistrationNumber: businessRegistrationNumber.optional(), phoneNumber: amexPhoneNumber, signer: signer}); export const amexSponsoredMerchantEnrollment = z.object({key: enrollmentKey, status: status, agentKey: agentKey, merchantKey: merchantKey, type: z.literal("amex_sm"), enrollmentStatus: enrollmentStatus, created: z.string(), version: z.number().int(), lastModified: z.string().optional(), errorMessage: z.string().optional(), warningMessage: z.string().optional(), enrollmentDetail: amexSponsoredMerchantEnrollmentDetail}); export const enrollmentType = z.enum(["amex_sm", "discover-mpr", "issm", "scof", "vau", "vts"]); export const discoverMid = z.string().min(1).max(15); export const binKey = z.string().min(5).max(120); export const discoverMerchantType = z.enum(["self-managed-outlet", "headquarter-account", "outlet-reporting-to-headquarter"]); export const discoverAcquirerIdCode = z.string().min(1).max(11); export const discoverIsoId = z.string().min(1).max(11); export const discoverDoingBusinessAsName = z.string().min(1).max(40); export const city = z.string().min(1).max(120); export const line1 = z.string().min(1).max(120); export const line2 = z.string().min(1).max(120); export const address = z.object({countryCode: countryCode, stateOrProvince: stateOrProvince.optional(), city: city, line1: line1, line2: line2.optional(), postalCode: postalCode}); export const phoneNumber = z.string().min(5).max(33); export const taxRegistrationId = z.string().max(20); export const merchantLegalName = z.string().min(1).max(120); export const businessType = z.enum(["corporation", "sole_proprietorship", "partnership", "non_profit_organization", "government_agency", "limited_liability_company"]); export const posDeviceDownloadIndicator = z.enum(["host-based-pos-device", "terminal-based-pos-device", "software-pos-device", "all-other-pos-devices", "unknown"]); export const headquarterAccountNumber = z.string(); export const businessPrincipal = z.object({firstName: z.string().min(1).max(22), lastName: z.string().min(1).max(22), socialSecurityNumber: z.string().min(1).max(9), homeAddress: z.object({countryCode: countryCodeAlpha3, stateOrProvince: z.string().min(1).max(4), city: z.string().min(1).max(28), line1: z.string().min(1).max(40), line2: z.string().min(1).max(40).optional(), postalCode: z.string().min(1).max(15)})}); export const discoverMerchantStatus = z.enum(["open", "open-active-bankruptcy", "open-existing-merchant-entitled-for-card-acceptance", "conversion-renumbered"]); export const discoverMerchantEnrollmentDetail = z.object({key: z.string(), mid: discoverMid, binKey: binKey, mcc: mcc, merchantType: discoverMerchantType, acquirerIdCode: discoverAcquirerIdCode, isoId: discoverIsoId.optional(), doingBusinessAsName: discoverDoingBusinessAsName, registeredAddress: address, customerInquiry: phoneNumber, taxRegistrationId: taxRegistrationId, legalName: merchantLegalName, businessType: businessType, websiteUrl: url, debtRepaymentIndicator: z.boolean(), posDeviceDownloadIndicator: posDeviceDownloadIndicator.optional(), headquarterAccountNumber: headquarterAccountNumber.optional(), businessPrincipal: businessPrincipal, merchantStatus: discoverMerchantStatus}); export const discoverMerchantEnrollment = z.object({key: enrollmentKey, status: status, agentKey: agentKey, merchantKey: merchantKey, type: enrollmentType, enrollmentStatus: enrollmentStatus, created: z.string(), version: z.number().int(), lastModified: z.string().optional(), errorMessage: z.string().optional(), enrollmentDetail: discoverMerchantEnrollmentDetail}); export const acceptorKey = z.string().min(5).max(120); export const version = z.number().int(); export const acceptorRef = z.object({key: acceptorKey, version: version}); export const acquirerBin = z.string().min(6).max(6); export const acquirerIdCode = z.string().min(6).max(6); export const deleteReason = z.enum(["Data Entry Error", "Merchant No Longer Participating", "Acquirer BIN Change", "Acquirer Primary ICA Change", "Other"]); export const issmEnrollmentDetail = z.object({key: z.string(), mid: mid, acquirerBin: acquirerBin, acquirerId: acquirerIdCode, merchantLegalName: z.string().min(1).max(25), deleteReason: deleteReason.optional()}); export const issmEnrollment = z.object({key: enrollmentKey, status: status, agentKey: agentKey, merchantKey: merchantKey, type: enrollmentType, enrollmentStatus: enrollmentStatus, created: z.string(), version: z.number().int(), lastModified: z.string().optional(), errorMessage: z.string().optional(), merchantAcceptorRef: acceptorRef.optional(), enrollmentDetail: issmEnrollmentDetail}); export const scofProgramType = z.enum(["merchant_obo", "commerce_platform_obo"]); export const scofProgramName = z.string().min(1).max(100); export const scofEnrollmentDetail = z.object({key: z.string(), mid: mid, binKey: binKey, programType: scofProgramType, programName: scofProgramName, mccs: z.array(mcc).optional(), serviceId: z.string().optional()}); export const scofEnrollment = z.object({key: enrollmentKey, status: status, agentKey: agentKey, merchantKey: merchantKey, type: enrollmentType, enrollmentStatus: enrollmentStatus, created: z.string(), version: z.number().int(), lastModified: z.string().optional(), errorMessage: z.string().optional(), enrollmentDetail: scofEnrollmentDetail}); export const acquirerSegmentId = z.number(); export const vauEnrollmentDetail = z.object({key: z.string(), acquirerSegmentId: acquirerSegmentId, binKey: binKey, acquirerIdCode: acquirerIdCode, merchantLegalName: z.string().min(1).max(120), merchantCountryCode: countryCode, mid: mid, mcc: mcc}); export const vauEnrollment = z.object({key: enrollmentKey, status: status, agentKey: agentKey, merchantKey: merchantKey, type: enrollmentType, enrollmentStatus: enrollmentStatus, created: z.string(), version: z.number().int(), lastModified: z.string().optional(), errorMessage: z.string().optional(), enrollmentDetail: vauEnrollmentDetail}); export const email = z.string(); export const businessIdentificationValue = z.string(); export const businessIdentificationType = z.enum(["ABN", "ACN", "BIN", "BIR", "BN", "BRN", "BRNO", "CL", "CLN", "CN", "CNPJ", "CR", "CUIT", "EDRPOU", "EIN", "HKBR", "NATIONAL_ID", "NIB", "NID", "NZBN", "PAN", "RFC", "RNC", "RUC", "RUT", "SIN", "SSN", "TC", "UEN", "USCI", "VAT"]); export const tokenizationConfiguration = z.object({tokenRequestorId: z.string(), applicationId: z.string(), profileName: z.string()}); export const vtsEnrollmentDetail = z.object({key: z.string(), merchantName: z.string().min(1).max(120), merchantWebsite: url, merchantCity: city, merchantCountryCode: countryCodeAlpha2, primaryContactEmail: email, acquirerId: acquirerIdCode.optional(), mid: mid.optional(), businessIdentificationValue: businessIdentificationValue.optional(), businessIdentificationType: businessIdentificationType.optional(), externalClientId: z.string().optional(), tokenizationConfiguration: tokenizationConfiguration.optional()}); export const vtsEnrollment = z.object({key: enrollmentKey, status: status, agentKey: agentKey, merchantKey: merchantKey, type: enrollmentType, enrollmentStatus: enrollmentStatus, created: z.string(), version: z.number().int(), lastModified: z.string().optional(), errorMessage: z.string().optional(), enrollmentDetail: vtsEnrollmentDetail}); export const standaloneEnrollment = z.discriminatedUnion("type", [amexSponsoredMerchantEnrollment, discoverMerchantEnrollment, issmEnrollment, scofEnrollment, vauEnrollment, vtsEnrollment]); 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 Enrollment [EXPERIMENTAL] * * POST /enrollments * * Also accepts auth: BearerToken */ export const createApiEnrollments = async (args: CreateApiEnrollmentsArgs, options?: CreateApiEnrollmentsOptions) => { const {baseUrl = "https://eu-west-1.api.silverflow.com/v1", fetch: fetchFn = fetch, ApiKey} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (ApiKey !== undefined) headers.set('authorization', `Basic ${btoa(`${ApiKey.username}:${ApiKey.password}`)}`) const url = `${baseUrl.replace(/\/+$/, '')}/enrollments${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(standaloneEnrollment, await res.json()) };