@nehorai/payments-il 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/cardcom/index.cjs +734 -0
- package/dist/cardcom/index.cjs.map +1 -0
- package/dist/cardcom/index.d.cts +188 -0
- package/dist/cardcom/index.d.ts +188 -0
- package/dist/cardcom/index.js +678 -0
- package/dist/cardcom/index.js.map +1 -0
- package/dist/cardcom-provider-uGEDtf_i.d.cts +56 -0
- package/dist/cardcom-provider-uGEDtf_i.d.ts +56 -0
- package/dist/factory.cjs +1418 -0
- package/dist/factory.cjs.map +1 -0
- package/dist/factory.d.cts +67 -0
- package/dist/factory.d.ts +67 -0
- package/dist/factory.js +1381 -0
- package/dist/factory.js.map +1 -0
- package/dist/hyp/index.cjs +885 -0
- package/dist/hyp/index.cjs.map +1 -0
- package/dist/hyp/index.d.cts +119 -0
- package/dist/hyp/index.d.ts +119 -0
- package/dist/hyp/index.js +841 -0
- package/dist/hyp/index.js.map +1 -0
- package/dist/hyp-types-BTLDpI0a.d.cts +235 -0
- package/dist/hyp-types-BTLDpI0a.d.ts +235 -0
- package/dist/index.cjs +1724 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1642 -0
- package/dist/index.js.map +1 -0
- package/dist/routing/index.cjs +146 -0
- package/dist/routing/index.cjs.map +1 -0
- package/dist/routing/index.d.cts +66 -0
- package/dist/routing/index.d.ts +66 -0
- package/dist/routing/index.js +113 -0
- package/dist/routing/index.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/hyp/hyp-provider.ts","../src/providers/hyp/hyp-types.ts","../src/providers/cardcom/cardcom-provider.ts","../src/providers/cardcom/cardcom-types.ts","../src/providers/hyp/hyp-webhook-handler.ts","../src/providers/cardcom/cardcom-webhook-handler.ts","../src/factory.ts"],"sourcesContent":["/**\r\n * Hyp (CreditGuard) Provider Implementation\r\n *\r\n * Implements IPaymentProvider for Hyp/CreditGuard payment processing.\r\n * Supports Two-Phase Commit (J5) with manual capture via TxOnly validation.\r\n *\r\n * API Documentation: https://cgpay3.creditguard.co.il/docs\r\n *\r\n * @see https://www.creditguard.co.il\r\n */\r\n\r\nimport type {\r\n PaymentProvider,\r\n CreatePaymentIntentParams,\r\n PaymentIntentResult,\r\n AuthorizePaymentParams,\r\n AuthorizationResult,\r\n CapturePaymentParams,\r\n CaptureResult,\r\n VoidPaymentParams,\r\n VoidResult,\r\n RefundParams,\r\n RefundResult,\r\n ProviderHealthStatus,\r\n} from '@nehorai/payments/types';\r\nimport type {\r\n IPaymentProvider,\r\n SavePaymentMethodParams,\r\n SavePaymentMethodResult,\r\n DeletePaymentMethodResult,\r\n CreateSetupIntentParams,\r\n SetupIntentResult,\r\n CreateCustomerParams,\r\n CreateCustomerResult,\r\n} from '@nehorai/payments/providers';\r\nimport { calculateCaptureDeadline } from '@nehorai/payments/types';\r\nimport {\r\n DEFAULT_HYP_ENDPOINTS,\r\n HYP_SUPPORTED_CURRENCIES,\r\n HYP_VALIDATION_MODES,\r\n HYP_TRANSACTION_TYPES,\r\n HYP_TRANSACTION_CODES,\r\n HYP_CREDIT_TYPES,\r\n mapHypStatus,\r\n mapHypError,\r\n isHypSuccess,\r\n formatHypAmount,\r\n} from './hyp-types.js';\r\nimport type {\r\n HypConfig,\r\n HypDoDealRequest,\r\n HypDoDealResponse,\r\n HypRefundDealRequest,\r\n HypRefundDealResponse,\r\n} from './hyp-types.js';\r\n\r\n/**\r\n * Hyp Payment Provider\r\n *\r\n * Full implementation of IPaymentProvider for CreditGuard.\r\n */\r\nexport class HypProvider implements IPaymentProvider {\r\n readonly name: PaymentProvider = 'hyp';\r\n readonly supportedCurrencies = HYP_SUPPORTED_CURRENCIES;\r\n readonly supportsRecurring = true;\r\n readonly supportsSplitPayments = false;\r\n\r\n private config: HypConfig & { baseUrl: string };\r\n\r\n constructor(config: HypConfig) {\r\n if (!config.terminalNumber || !config.user || !config.password) {\r\n throw new Error(\r\n 'HypProvider requires terminalNumber, user, and password in config'\r\n );\r\n }\r\n\r\n // Resolve baseUrl: explicit baseUrl > environment > default to sandbox\r\n const baseUrl = config.baseUrl\r\n ?? (config.environment === 'production'\r\n ? DEFAULT_HYP_ENDPOINTS.production\r\n : DEFAULT_HYP_ENDPOINTS.test);\r\n\r\n this.config = { ...config, baseUrl };\r\n }\r\n\r\n // ==========================================================================\r\n // Payment Intent Operations\r\n // ==========================================================================\r\n\r\n /**\r\n * Create a payment intent\r\n *\r\n * For Hyp, this generates a hosted payment page or prepares for direct charge.\r\n */\r\n async createPaymentIntent(\r\n params: CreatePaymentIntentParams\r\n ): Promise<PaymentIntentResult> {\r\n try {\r\n // For hosted page flow (no payment method provided)\r\n if (!params.paymentMethodId) {\r\n return await this.createHostedPage(params);\r\n }\r\n\r\n // For direct charge with saved payment method\r\n return await this.chargeWithToken(params);\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n /**\r\n * Create hosted payment page\r\n */\r\n private async createHostedPage(\r\n params: CreatePaymentIntentParams\r\n ): Promise<PaymentIntentResult> {\r\n const uniqueid = params.idempotencyKey;\r\n\r\n const request: HypDoDealRequest = {\r\n terminalNumber: this.config.terminalNumber,\r\n user: this.config.user,\r\n password: this.config.password,\r\n total: formatHypAmount(params.amount.amountMinor),\r\n currency: params.amount.currency,\r\n transactionType: HYP_TRANSACTION_TYPES.DEBIT,\r\n transactionCode:\r\n params.captureMethod === 'manual'\r\n ? HYP_TRANSACTION_CODES.VERIFY\r\n : HYP_TRANSACTION_CODES.REGULAR,\r\n validation:\r\n params.captureMethod === 'manual'\r\n ? HYP_VALIDATION_MODES.TX_ONLY\r\n : HYP_VALIDATION_MODES.AUTO_COMM,\r\n uniqueid,\r\n successUrl: params.returnUrl,\r\n errorUrl: params.returnUrl,\r\n cancelUrl: params.returnUrl,\r\n language: 'en',\r\n };\r\n\r\n const response = await this.sendDoDealRequest(request);\r\n\r\n if (!isHypSuccess(response.resultCode)) {\r\n return {\r\n success: false,\r\n error: response.resultDescription ?? 'Transaction failed',\r\n errorCode: mapHypError(response.resultCode),\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n providerIntentId: response.transactionId ?? uniqueid,\r\n redirectUrl: response.redirectUrl,\r\n status: 'created',\r\n };\r\n }\r\n\r\n /**\r\n * Charge with saved payment method token\r\n */\r\n private async chargeWithToken(\r\n params: CreatePaymentIntentParams\r\n ): Promise<PaymentIntentResult> {\r\n const uniqueid = params.idempotencyKey;\r\n\r\n const request: HypDoDealRequest = {\r\n terminalNumber: this.config.terminalNumber,\r\n user: this.config.user,\r\n password: this.config.password,\r\n total: formatHypAmount(params.amount.amountMinor),\r\n currency: params.amount.currency,\r\n transactionType: HYP_TRANSACTION_TYPES.DEBIT,\r\n transactionCode:\r\n params.captureMethod === 'manual'\r\n ? HYP_TRANSACTION_CODES.VERIFY\r\n : HYP_TRANSACTION_CODES.REGULAR,\r\n validation:\r\n params.captureMethod === 'manual'\r\n ? HYP_VALIDATION_MODES.TX_ONLY\r\n : HYP_VALIDATION_MODES.AUTO_COMM,\r\n creditType: HYP_CREDIT_TYPES.TOKEN,\r\n cardToken: params.paymentMethodId,\r\n uniqueid,\r\n };\r\n\r\n const response = await this.sendDoDealRequest(request);\r\n\r\n if (!isHypSuccess(response.resultCode)) {\r\n return {\r\n success: false,\r\n error: response.resultDescription ?? 'Transaction failed',\r\n errorCode: mapHypError(response.resultCode),\r\n };\r\n }\r\n\r\n const status = mapHypStatus(response.resultCode) ?? 'created';\r\n\r\n return {\r\n success: true,\r\n providerIntentId: response.transactionId ?? uniqueid,\r\n status,\r\n };\r\n }\r\n\r\n async authorize(params: AuthorizePaymentParams): Promise<AuthorizationResult> {\r\n try {\r\n return {\r\n success: true,\r\n authorizationCode: params.providerIntentId,\r\n status: 'authorized',\r\n captureDeadline: calculateCaptureDeadline(new Date()),\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n async capture(params: CapturePaymentParams): Promise<CaptureResult> {\r\n try {\r\n const request: HypDoDealRequest = {\r\n terminalNumber: this.config.terminalNumber,\r\n user: this.config.user,\r\n password: this.config.password,\r\n total: params.amount\r\n ? formatHypAmount(params.amount.amountMinor)\r\n : undefined,\r\n currency: params.amount?.currency ?? 'ILS',\r\n transactionType: HYP_TRANSACTION_TYPES.DEBIT,\r\n transactionCode: HYP_TRANSACTION_CODES.FORCE,\r\n validation: HYP_VALIDATION_MODES.AUTO_COMM,\r\n uniqueid: params.idempotencyKey,\r\n authorizationCode: params.providerIntentId,\r\n };\r\n\r\n const response = await this.sendDoDealRequest(request);\r\n\r\n if (!isHypSuccess(response.resultCode)) {\r\n return {\r\n success: false,\r\n error: response.resultDescription ?? 'Capture failed',\r\n errorCode: mapHypError(response.resultCode),\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n providerTransactionId: response.transactionId ?? params.providerIntentId,\r\n status: 'captured',\r\n capturedAmount: params.amount ?? {\r\n amountMinor: 0,\r\n currency: 'ILS',\r\n },\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n async void(params: VoidPaymentParams): Promise<VoidResult> {\r\n try {\r\n const request: HypRefundDealRequest = {\r\n terminalNumber: this.config.terminalNumber,\r\n user: this.config.user,\r\n password: this.config.password,\r\n transactionId: params.providerIntentId,\r\n currency: 'ILS',\r\n uniqueid: params.providerIntentId,\r\n };\r\n\r\n const response = await this.sendRefundRequest(request);\r\n\r\n if (!isHypSuccess(response.resultCode)) {\r\n return {\r\n success: false,\r\n error: response.resultDescription ?? 'Void failed',\r\n };\r\n }\r\n\r\n return { success: true, status: 'voided' };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n // ==========================================================================\r\n // Refunds\r\n // ==========================================================================\r\n\r\n async refund(params: RefundParams): Promise<RefundResult> {\r\n try {\r\n const request: HypRefundDealRequest = {\r\n terminalNumber: this.config.terminalNumber,\r\n user: this.config.user,\r\n password: this.config.password,\r\n transactionId: params.providerTransactionId,\r\n total: params.amount\r\n ? formatHypAmount(params.amount.amountMinor)\r\n : undefined,\r\n currency: params.amount?.currency ?? 'ILS',\r\n uniqueid: params.idempotencyKey,\r\n };\r\n\r\n const response = await this.sendRefundRequest(request);\r\n\r\n if (!isHypSuccess(response.resultCode)) {\r\n return {\r\n success: false,\r\n error: response.resultDescription ?? 'Refund failed',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n providerRefundId: response.transactionId ?? params.idempotencyKey,\r\n refundedAmount: params.amount ?? {\r\n amountMinor: 0,\r\n currency: 'ILS',\r\n },\r\n status: 'succeeded',\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n // ==========================================================================\r\n // Payment Methods (Tokenization)\r\n // ==========================================================================\r\n\r\n async createSetupIntent(\r\n params: CreateSetupIntentParams\r\n ): Promise<SetupIntentResult> {\r\n try {\r\n const uniqueid = `setup_${params.userId}_${Date.now()}`;\r\n\r\n const request: HypDoDealRequest = {\r\n terminalNumber: this.config.terminalNumber,\r\n user: this.config.user,\r\n password: this.config.password,\r\n total: 0,\r\n currency: 'ILS',\r\n transactionType: HYP_TRANSACTION_TYPES.DEBIT,\r\n transactionCode: HYP_TRANSACTION_CODES.VERIFY,\r\n validation: HYP_VALIDATION_MODES.TX_ONLY,\r\n creditType: HYP_CREDIT_TYPES.TOKEN,\r\n customerData: params.customerId ?? params.userId,\r\n uniqueid,\r\n language: 'en',\r\n };\r\n\r\n const response = await this.sendDoDealRequest(request);\r\n\r\n if (!isHypSuccess(response.resultCode)) {\r\n return {\r\n success: false,\r\n error: response.resultDescription ?? 'Setup failed',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n setupIntentId: response.transactionId ?? uniqueid,\r\n clientSecret: response.redirectUrl,\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n async savePaymentMethod(\r\n params: SavePaymentMethodParams\r\n ): Promise<SavePaymentMethodResult> {\r\n try {\r\n const cardToken = params.setupData.cardToken as string;\r\n const cardMask = params.setupData.cardMask as string;\r\n const cardBrand = params.setupData.cardBrand as string;\r\n const cardExpiration = params.setupData.cardExpiration as string;\r\n\r\n if (!cardToken) {\r\n return {\r\n success: false,\r\n error: 'No card token received',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n paymentMethodId: cardToken,\r\n cardBrand: cardBrand ?? 'unknown',\r\n cardLast4: cardMask?.slice(-4) ?? '0000',\r\n cardExpMonth: cardExpiration?.substring(0, 2) ?? '01',\r\n cardExpYear: `20${cardExpiration?.substring(2, 4) ?? '99'}`,\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n async deletePaymentMethod(\r\n _paymentMethodId: string\r\n ): Promise<DeletePaymentMethodResult> {\r\n return {\r\n success: true,\r\n };\r\n }\r\n\r\n // ==========================================================================\r\n // Customer Management\r\n // ==========================================================================\r\n\r\n async createCustomer(\r\n params: CreateCustomerParams\r\n ): Promise<CreateCustomerResult> {\r\n return {\r\n success: true,\r\n customerId: params.userId,\r\n };\r\n }\r\n\r\n async getOrCreateCustomer(\r\n userId: string,\r\n _email: string\r\n ): Promise<CreateCustomerResult> {\r\n return {\r\n success: true,\r\n customerId: userId,\r\n };\r\n }\r\n\r\n // ==========================================================================\r\n // Health & Security\r\n // ==========================================================================\r\n\r\n async getHealth(): Promise<ProviderHealthStatus> {\r\n const start = Date.now();\r\n try {\r\n const response = await fetch(`${this.config.baseUrl}/xpo/Relay`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'text/xml',\r\n },\r\n body: this.buildTestXML(),\r\n signal: AbortSignal.timeout(5000),\r\n });\r\n\r\n const healthy = response.ok;\r\n\r\n return {\r\n provider: 'hyp',\r\n healthy,\r\n lastChecked: new Date(),\r\n avgLatencyMs: Date.now() - start,\r\n circuitBreakerOpen: false,\r\n };\r\n } catch {\r\n return {\r\n provider: 'hyp',\r\n healthy: false,\r\n lastChecked: new Date(),\r\n circuitBreakerOpen: false,\r\n };\r\n }\r\n }\r\n\r\n validateWebhookSignature(_payload: string, _signature: string): boolean {\r\n if (!this.config.webhookSecret) return false;\r\n return !!this.config.webhookSecret;\r\n }\r\n\r\n async getPaymentIntentStatus(\r\n _providerIntentId: string\r\n ): Promise<{ status: string; error?: string }> {\r\n return {\r\n status: 'unknown',\r\n error: 'Status query not supported by Hyp basic integration',\r\n };\r\n }\r\n\r\n // ==========================================================================\r\n // XML Request Builders\r\n // ==========================================================================\r\n\r\n private buildDoDealXML(request: HypDoDealRequest): string {\r\n const parts: string[] = [];\r\n\r\n parts.push('<?xml version=\"1.0\" encoding=\"utf-8\"?>');\r\n parts.push('<ashrait>');\r\n parts.push('<request>');\r\n parts.push(`<version>1000</version>`);\r\n parts.push('<language>ENG</language>');\r\n\r\n parts.push('<command>doDeal</command>');\r\n parts.push(`<terminalNumber>${this.escapeXml(request.terminalNumber)}</terminalNumber>`);\r\n parts.push(`<user>${this.escapeXml(request.user)}</user>`);\r\n parts.push(`<password>${this.escapeXml(request.password)}</password>`);\r\n\r\n if (request.cardNo) {\r\n parts.push(`<cardNo>${this.escapeXml(request.cardNo)}</cardNo>`);\r\n }\r\n if (request.cardExpiration) {\r\n parts.push(`<cardExpiration>${this.escapeXml(request.cardExpiration)}</cardExpiration>`);\r\n }\r\n if (request.cvv) {\r\n parts.push(`<cvv>${this.escapeXml(request.cvv)}</cvv>`);\r\n }\r\n if (request.cardToken) {\r\n parts.push(`<cardToken>${this.escapeXml(request.cardToken)}</cardToken>`);\r\n }\r\n if (request.authorizationCode) {\r\n parts.push(`<authNumber>${this.escapeXml(request.authorizationCode)}</authNumber>`);\r\n }\r\n\r\n if (request.total !== undefined) {\r\n parts.push(`<total>${request.total}</total>`);\r\n }\r\n parts.push(`<currency>${this.escapeXml(request.currency)}</currency>`);\r\n parts.push(`<transactionType>${this.escapeXml(request.transactionType)}</transactionType>`);\r\n\r\n if (request.transactionCode) {\r\n parts.push(`<transactionCode>${this.escapeXml(request.transactionCode)}</transactionCode>`);\r\n }\r\n if (request.creditType) {\r\n parts.push(`<creditType>${request.creditType}</creditType>`);\r\n }\r\n if (request.validation) {\r\n parts.push(`<validation>${this.escapeXml(request.validation)}</validation>`);\r\n }\r\n if (request.uniqueid) {\r\n parts.push(`<uniqueid>${this.escapeXml(request.uniqueid)}</uniqueid>`);\r\n }\r\n if (request.customerData) {\r\n parts.push(`<customerData>${this.escapeXml(request.customerData)}</customerData>`);\r\n }\r\n\r\n if (request.successUrl) {\r\n parts.push(`<successUrl>${this.escapeXml(request.successUrl)}</successUrl>`);\r\n }\r\n if (request.errorUrl) {\r\n parts.push(`<errorUrl>${this.escapeXml(request.errorUrl)}</errorUrl>`);\r\n }\r\n if (request.cancelUrl) {\r\n parts.push(`<cancelUrl>${this.escapeXml(request.cancelUrl)}</cancelUrl>`);\r\n }\r\n\r\n parts.push('</request>');\r\n parts.push('</ashrait>');\r\n\r\n return parts.join('');\r\n }\r\n\r\n private buildRefundXML(request: HypRefundDealRequest): string {\r\n const parts: string[] = [];\r\n\r\n parts.push('<?xml version=\"1.0\" encoding=\"utf-8\"?>');\r\n parts.push('<ashrait>');\r\n parts.push('<request>');\r\n parts.push(`<version>1000</version>`);\r\n parts.push('<language>ENG</language>');\r\n\r\n parts.push('<command>refundDeal</command>');\r\n parts.push(`<terminalNumber>${this.escapeXml(request.terminalNumber)}</terminalNumber>`);\r\n parts.push(`<user>${this.escapeXml(request.user)}</user>`);\r\n parts.push(`<password>${this.escapeXml(request.password)}</password>`);\r\n\r\n parts.push(`<transactionId>${this.escapeXml(request.transactionId)}</transactionId>`);\r\n parts.push(`<currency>${this.escapeXml(request.currency)}</currency>`);\r\n\r\n if (request.total !== undefined) {\r\n parts.push(`<total>${request.total}</total>`);\r\n }\r\n if (request.uniqueid) {\r\n parts.push(`<uniqueid>${this.escapeXml(request.uniqueid)}</uniqueid>`);\r\n }\r\n\r\n parts.push('</request>');\r\n parts.push('</ashrait>');\r\n\r\n return parts.join('');\r\n }\r\n\r\n private buildTestXML(): string {\r\n return `<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<ashrait>\r\n <request>\r\n <version>1000</version>\r\n <language>ENG</language>\r\n <command>echo</command>\r\n </request>\r\n</ashrait>`;\r\n }\r\n\r\n // ==========================================================================\r\n // HTTP Helpers\r\n // ==========================================================================\r\n\r\n private async sendDoDealRequest(\r\n request: HypDoDealRequest\r\n ): Promise<HypDoDealResponse> {\r\n const xmlBody = this.buildDoDealXML(request);\r\n\r\n const response = await fetch(`${this.config.baseUrl}/xpo/Relay`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'text/xml; charset=utf-8',\r\n },\r\n body: xmlBody,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n\r\n const xmlResponse = await response.text();\r\n return this.parseDoDealResponse(xmlResponse);\r\n }\r\n\r\n private async sendRefundRequest(\r\n request: HypRefundDealRequest\r\n ): Promise<HypRefundDealResponse> {\r\n const xmlBody = this.buildRefundXML(request);\r\n\r\n const response = await fetch(`${this.config.baseUrl}/xpo/Relay`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'text/xml; charset=utf-8',\r\n },\r\n body: xmlBody,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n\r\n const xmlResponse = await response.text();\r\n return this.parseRefundResponse(xmlResponse);\r\n }\r\n\r\n // ==========================================================================\r\n // XML Parsing\r\n // ==========================================================================\r\n\r\n private parseDoDealResponse(xml: string): HypDoDealResponse {\r\n return {\r\n resultCode: this.extractXmlValue(xml, 'resultCode') ?? '100',\r\n resultDescription: this.extractXmlValue(xml, 'resultDescription'),\r\n transactionId: this.extractXmlValue(xml, 'transactionId'),\r\n authorizationCode: this.extractXmlValue(xml, 'authorizationCode'),\r\n voucherNumber: this.extractXmlValue(xml, 'voucherNumber'),\r\n cardToken: this.extractXmlValue(xml, 'cardToken'),\r\n cardMask: this.extractXmlValue(xml, 'cardMask'),\r\n cardBrand: this.extractXmlValue(xml, 'cardBrand'),\r\n cardExpiration: this.extractXmlValue(xml, 'cardExpiration'),\r\n redirectUrl: this.extractXmlValue(xml, 'redirectUrl'),\r\n uniqueid: this.extractXmlValue(xml, 'uniqueid'),\r\n rawXml: xml,\r\n };\r\n }\r\n\r\n private parseRefundResponse(xml: string): HypRefundDealResponse {\r\n return {\r\n resultCode: this.extractXmlValue(xml, 'resultCode') ?? '100',\r\n resultDescription: this.extractXmlValue(xml, 'resultDescription'),\r\n transactionId: this.extractXmlValue(xml, 'transactionId'),\r\n authorizationCode: this.extractXmlValue(xml, 'authorizationCode'),\r\n uniqueid: this.extractXmlValue(xml, 'uniqueid'),\r\n };\r\n }\r\n\r\n private extractXmlValue(xml: string, tagName: string): string | undefined {\r\n const regex = new RegExp(`<${tagName}>([^<]*)</${tagName}>`, 'i');\r\n const match = xml.match(regex);\r\n return match ? match[1].trim() : undefined;\r\n }\r\n\r\n private escapeXml(str: string): string {\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''');\r\n }\r\n\r\n // ==========================================================================\r\n // Error Handling\r\n // ==========================================================================\r\n\r\n private handleError(error: unknown): {\r\n success: false;\r\n error: string;\r\n errorCode?: string;\r\n } {\r\n if (error instanceof Error) {\r\n return {\r\n success: false,\r\n error: error.message,\r\n errorCode: 'unknown',\r\n };\r\n }\r\n return {\r\n success: false,\r\n error: 'Unknown error occurred',\r\n errorCode: 'unknown',\r\n };\r\n }\r\n}\r\n","/**\r\n * Hyp (CreditGuard) Types\r\n *\r\n * Type definitions for Hyp/CreditGuard API interactions.\r\n * CreditGuard uses XML-based requests over HTTPS.\r\n *\r\n * @see https://cgpay3.creditguard.co.il/docs\r\n */\r\n\r\nimport type { TransactionStatus } from '@nehorai/payments/types';\r\n\r\n// ============================================================================\r\n// Hyp Configuration\r\n// ============================================================================\r\n\r\n/**\r\n * Hyp API configuration\r\n *\r\n * Provide either `environment` (auto-selects baseUrl) or `baseUrl` directly.\r\n * If both are provided, `baseUrl` takes precedence.\r\n */\r\nexport interface HypConfig {\r\n /** Terminal number assigned by CreditGuard */\r\n terminalNumber: string;\r\n /** API username */\r\n user: string;\r\n /** API password */\r\n password: string;\r\n /** Webhook secret for callback validation */\r\n webhookSecret?: string;\r\n /** Environment shortcut - auto-selects the correct baseUrl */\r\n environment?: 'sandbox' | 'production';\r\n /** Base URL override (takes precedence over environment) */\r\n baseUrl?: string;\r\n}\r\n\r\n/**\r\n * Hyp API endpoints\r\n */\r\nexport const DEFAULT_HYP_ENDPOINTS = {\r\n test: 'https://cguat2.creditguard.co.il',\r\n production: 'https://cgpay3.creditguard.co.il',\r\n} as const;\r\n\r\n/**\r\n * Hyp supported currencies (subset)\r\n */\r\nexport const HYP_SUPPORTED_CURRENCIES = [\r\n 'ILS', // Israeli Shekel (primary)\r\n 'USD', // US Dollar\r\n 'EUR', // Euro\r\n 'GBP', // British Pound\r\n] as const;\r\n\r\n// ============================================================================\r\n// XML Request/Response Types\r\n// ============================================================================\r\n\r\n/**\r\n * Hyp doDeal request parameters\r\n */\r\nexport interface HypDoDealRequest {\r\n /** Terminal number */\r\n terminalNumber: string;\r\n /** API username */\r\n user: string;\r\n /** API password */\r\n password: string;\r\n /** Card number (for direct charge) */\r\n cardNo?: string;\r\n /** Card expiration (MMYY) */\r\n cardExpiration?: string;\r\n /** CVV code */\r\n cvv?: string;\r\n /** Card token (for saved card transactions) */\r\n cardToken?: string;\r\n /** Authorization code (for force/capture transactions) */\r\n authorizationCode?: string;\r\n /** Amount in minor units (agorot for ILS) */\r\n total?: number;\r\n /** Currency code (ILS, USD, EUR, GBP) */\r\n currency: string;\r\n /** Transaction type (Debit, Credit, etc.) */\r\n transactionType: string;\r\n /** Transaction code for J5: Regular, Verify, etc. */\r\n transactionCode?: string;\r\n /** Credit type: 1=Regular, 8=Credit/Token */\r\n creditType?: string;\r\n /** Validation mode: AutoComm, TxOnly */\r\n validation?: string;\r\n /** Customer ID for tokenization */\r\n customerData?: string;\r\n /** Unique transaction identifier */\r\n uniqueid?: string;\r\n /** Success URL for hosted page */\r\n successUrl?: string;\r\n /** Error URL for hosted page */\r\n errorUrl?: string;\r\n /** Cancel URL for hosted page */\r\n cancelUrl?: string;\r\n /** Language code (he, en) */\r\n language?: string;\r\n}\r\n\r\n/**\r\n * Hyp doDeal response\r\n */\r\nexport interface HypDoDealResponse {\r\n /** Result code (000 = success) */\r\n resultCode: string;\r\n /** Result description */\r\n resultDescription?: string;\r\n /** Transaction ID from CreditGuard */\r\n transactionId?: string;\r\n /** Authorization number */\r\n authorizationCode?: string;\r\n /** Voucher number */\r\n voucherNumber?: string;\r\n /** Card token (if tokenization requested) */\r\n cardToken?: string;\r\n /** Card mask (last 4 digits) */\r\n cardMask?: string;\r\n /** Card brand (Visa, MasterCard, etc.) */\r\n cardBrand?: string;\r\n /** Card expiration */\r\n cardExpiration?: string;\r\n /** Redirect URL for hosted page */\r\n redirectUrl?: string;\r\n /** Unique ID echo */\r\n uniqueid?: string;\r\n /** Raw XML response for debugging */\r\n rawXml?: string;\r\n}\r\n\r\n/**\r\n * Hyp refundDeal request parameters\r\n */\r\nexport interface HypRefundDealRequest {\r\n /** Terminal number */\r\n terminalNumber: string;\r\n /** API username */\r\n user: string;\r\n /** API password */\r\n password: string;\r\n /** Original transaction ID */\r\n transactionId: string;\r\n /** Amount to refund in minor units (optional for full refund) */\r\n total?: number;\r\n /** Currency code */\r\n currency: string;\r\n /** Unique identifier */\r\n uniqueid?: string;\r\n}\r\n\r\n/**\r\n * Hyp refundDeal response\r\n */\r\nexport interface HypRefundDealResponse {\r\n /** Result code (000 = success) */\r\n resultCode: string;\r\n /** Result description */\r\n resultDescription?: string;\r\n /** Refund transaction ID */\r\n transactionId?: string;\r\n /** Authorization code for refund */\r\n authorizationCode?: string;\r\n /** Unique ID echo */\r\n uniqueid?: string;\r\n}\r\n\r\n// ============================================================================\r\n// Status Mapping\r\n// ============================================================================\r\n\r\n/**\r\n * Hyp result codes\r\n */\r\nexport type HypResultCode = '000' | '001' | '002' | '003' | '004' | '005' | '006' | string;\r\n\r\n/**\r\n * Map Hyp result codes to our TransactionStatus\r\n */\r\nexport const HYP_RESULT_CODE_MAP: Record<string, TransactionStatus> = {\r\n '000': 'captured', // Success\r\n '001': 'failed', // Declined\r\n '002': 'failed', // Invalid card\r\n '003': 'failed', // Expired card\r\n '004': 'failed', // Insufficient funds\r\n '005': 'failed', // Invalid CVV\r\n '006': 'failed', // Card not permitted\r\n '033': 'failed', // Lost/Stolen card\r\n '034': 'failed', // Suspected fraud\r\n '051': 'failed', // Insufficient funds\r\n '054': 'failed', // Expired card\r\n '057': 'failed', // Transaction not permitted\r\n '100': 'failed', // System error\r\n '200': 'pending_authorization', // Pending\r\n};\r\n\r\n/**\r\n * Hyp transaction types\r\n */\r\nexport const HYP_TRANSACTION_TYPES = {\r\n /** Regular charge (immediate capture) */\r\n DEBIT: 'Debit',\r\n /** Refund */\r\n CREDIT: 'Credit',\r\n /** Authorization only (J5) */\r\n DEBIT_J5: 'Debit',\r\n} as const;\r\n\r\n/**\r\n * Hyp transaction codes for J5\r\n */\r\nexport const HYP_TRANSACTION_CODES = {\r\n /** Regular transaction */\r\n REGULAR: 'Regular',\r\n /** Verify only (authorization) */\r\n VERIFY: 'Verify',\r\n /** Force transaction */\r\n FORCE: 'Force',\r\n} as const;\r\n\r\n/**\r\n * Hyp validation modes\r\n */\r\nexport const HYP_VALIDATION_MODES = {\r\n /** Auto commit (immediate capture) */\r\n AUTO_COMM: 'AutoComm',\r\n /** Transaction only (authorization, requires manual capture) */\r\n TX_ONLY: 'TxOnly',\r\n} as const;\r\n\r\n/**\r\n * Hyp credit types\r\n */\r\nexport const HYP_CREDIT_TYPES = {\r\n /** Regular credit card */\r\n REGULAR: '1',\r\n /** Token/Saved card */\r\n TOKEN: '8',\r\n} as const;\r\n\r\n// ============================================================================\r\n// Error Mapping\r\n// ============================================================================\r\n\r\n/**\r\n * Map Hyp result codes to our error codes\r\n */\r\nexport const HYP_ERROR_MAP: Record<string, string> = {\r\n '001': 'card_declined',\r\n '002': 'invalid_card',\r\n '003': 'expired_card',\r\n '004': 'insufficient_funds',\r\n '005': 'invalid_cvc',\r\n '006': 'card_declined',\r\n '033': 'card_declined',\r\n '034': 'card_declined',\r\n '051': 'insufficient_funds',\r\n '054': 'expired_card',\r\n '057': 'card_declined',\r\n '100': 'processing_error',\r\n '200': 'authentication_required',\r\n};\r\n\r\n// ============================================================================\r\n// Helper Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Map Hyp result code to our transaction status\r\n */\r\nexport function mapHypStatus(resultCode: string): TransactionStatus | null {\r\n return HYP_RESULT_CODE_MAP[resultCode] ?? null;\r\n}\r\n\r\n/**\r\n * Map Hyp error code to our error code\r\n */\r\nexport function mapHypError(resultCode: string): string {\r\n return HYP_ERROR_MAP[resultCode] ?? 'unknown';\r\n}\r\n\r\n/**\r\n * Check if currency is supported by Hyp\r\n */\r\nexport function isHypSupportedCurrency(currency: string): boolean {\r\n return HYP_SUPPORTED_CURRENCIES.includes(\r\n currency as (typeof HYP_SUPPORTED_CURRENCIES)[number]\r\n );\r\n}\r\n\r\n/**\r\n * Check if result code indicates success\r\n */\r\nexport function isHypSuccess(resultCode: string): boolean {\r\n return resultCode === '000';\r\n}\r\n\r\n/**\r\n * Format amount for Hyp (already in minor units, no conversion needed)\r\n */\r\nexport function formatHypAmount(amountMinor: number): number {\r\n return amountMinor;\r\n}\r\n\r\n/**\r\n * Format card expiration for Hyp (MMYY format)\r\n */\r\nexport function formatCardExpiration(month: string, year: string): string {\r\n const mm = month.padStart(2, '0');\r\n const yy = year.slice(-2);\r\n return `${mm}${yy}`;\r\n}\r\n\r\n/**\r\n * Parse card expiration from Hyp format (MMYY)\r\n */\r\nexport function parseCardExpiration(expiration: string): {\r\n month: string;\r\n year: string;\r\n} {\r\n const mm = expiration.substring(0, 2);\r\n const yy = expiration.substring(2, 4);\r\n return {\r\n month: mm,\r\n year: `20${yy}`,\r\n };\r\n}\r\n","/**\r\n * Cardcom Provider Implementation\r\n *\r\n * Implements IPaymentProvider for Cardcom payment gateway (Israeli market).\r\n * Uses Low Profile (hosted page) for PCI compliance and direct API for operations.\r\n * Supports Two-Phase Commit (J5) with SuspendDealOnly operation.\r\n *\r\n * @see https://secure.cardcom.solutions/api/v11/swagger/ui/index\r\n */\r\n\r\nimport * as crypto from 'crypto';\r\nimport type {\r\n PaymentProvider,\r\n CreatePaymentIntentParams,\r\n PaymentIntentResult,\r\n AuthorizePaymentParams,\r\n AuthorizationResult,\r\n CapturePaymentParams,\r\n CaptureResult,\r\n VoidPaymentParams,\r\n VoidResult,\r\n RefundParams,\r\n RefundResult,\r\n ProviderHealthStatus,\r\n} from '@nehorai/payments/types';\r\nimport type {\r\n IPaymentProvider,\r\n SavePaymentMethodParams,\r\n SavePaymentMethodResult,\r\n DeletePaymentMethodResult,\r\n CreateSetupIntentParams,\r\n SetupIntentResult,\r\n CreateCustomerParams,\r\n CreateCustomerResult,\r\n} from '@nehorai/payments/providers';\r\nimport { calculateCaptureDeadline } from '@nehorai/payments/types';\r\nimport {\r\n CARDCOM_API_BASE,\r\n CARDCOM_ENDPOINTS,\r\n CARDCOM_SUPPORTED_CURRENCIES,\r\n CardcomOperation,\r\n getCurrencyCode,\r\n mapCardcomDealResponseToStatus,\r\n mapCardcomError,\r\n type CardcomLowProfileRequest,\r\n type CardcomLowProfileResponse,\r\n type CardcomLowProfileStatusResponse,\r\n type CardcomRefundRequest,\r\n type CardcomRefundResponse,\r\n} from './cardcom-types.js';\r\n\r\n/**\r\n * Cardcom provider constructor config\r\n */\r\nexport interface CardcomProviderConfig {\r\n terminalNumber: string;\r\n apiName: string;\r\n apiPassword: string;\r\n webhookSecret?: string;\r\n}\r\n\r\n/**\r\n * Cardcom Payment Provider\r\n *\r\n * Full implementation of IPaymentProvider for Cardcom.\r\n */\r\nexport class CardcomProvider implements IPaymentProvider {\r\n readonly name: PaymentProvider = 'cardcom';\r\n readonly supportedCurrencies = CARDCOM_SUPPORTED_CURRENCIES;\r\n readonly supportsRecurring = true;\r\n readonly supportsSplitPayments = false;\r\n\r\n private config: CardcomProviderConfig;\r\n\r\n constructor(config: CardcomProviderConfig) {\r\n if (!config.terminalNumber || !config.apiName || !config.apiPassword) {\r\n throw new Error(\r\n 'CardcomProvider requires terminalNumber, apiName, and apiPassword in config'\r\n );\r\n }\r\n this.config = config;\r\n }\r\n\r\n // ==========================================================================\r\n // Payment Intent Operations\r\n // ==========================================================================\r\n\r\n async createPaymentIntent(\r\n params: CreatePaymentIntentParams\r\n ): Promise<PaymentIntentResult> {\r\n try {\r\n const amountMajor = params.amount.amountMinor / 100;\r\n\r\n const operation =\r\n params.captureMethod === 'manual'\r\n ? CardcomOperation.SUSPEND_DEAL_ONLY\r\n : params.metadata?.savePaymentMethod\r\n ? CardcomOperation.BILL_AND_CREATE_TOKEN\r\n : CardcomOperation.BILL_ONLY;\r\n\r\n const request: CardcomLowProfileRequest = {\r\n TerminalNumber: this.config.terminalNumber,\r\n ApiName: this.config.apiName,\r\n ApiPassword: this.config.apiPassword,\r\n Sum: amountMajor,\r\n CoinID: getCurrencyCode(params.amount.currency),\r\n Operation: operation,\r\n Language: 'en',\r\n ReturnUrl: params.returnUrl,\r\n ErrorUrl: params.returnUrl,\r\n ProductName: params.description ?? 'Payment',\r\n InternalDealNumber: params.idempotencyKey,\r\n SendEmail: false,\r\n };\r\n\r\n if (params.metadata?.customerName) {\r\n request.CustomerName = String(params.metadata.customerName);\r\n }\r\n if (params.metadata?.customerEmail) {\r\n request.Email = String(params.metadata.customerEmail);\r\n }\r\n\r\n const response = await this.makeRequest<CardcomLowProfileResponse>(\r\n CARDCOM_ENDPOINTS.LOW_PROFILE_CREATE,\r\n request as unknown as Record<string, unknown>\r\n );\r\n\r\n if (response.ResponseCode !== 0 || !response.PaymentUrl) {\r\n return {\r\n success: false,\r\n error: mapCardcomError(response.ResponseCode),\r\n errorCode: String(response.ResponseCode),\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n providerIntentId: response.LowProfileCode!,\r\n redirectUrl: response.PaymentUrl,\r\n status: 'created',\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n async authorize(params: AuthorizePaymentParams): Promise<AuthorizationResult> {\r\n try {\r\n const statusResponse = await this.getLowProfileStatus(\r\n params.providerIntentId\r\n );\r\n\r\n if (!statusResponse.success || !statusResponse.data) {\r\n return {\r\n success: false,\r\n error: statusResponse.error ?? 'Failed to check payment status',\r\n };\r\n }\r\n\r\n const status = statusResponse.data;\r\n\r\n if (status.DealResponse === 1) {\r\n return {\r\n success: true,\r\n authorizationCode: status.InternalDealNumber ?? params.providerIntentId,\r\n status: 'authorized',\r\n captureDeadline: calculateCaptureDeadline(new Date()),\r\n };\r\n }\r\n\r\n if (status.DealResponse === 2) {\r\n return {\r\n success: false,\r\n error: 'Payment declined',\r\n status: 'failed',\r\n };\r\n }\r\n\r\n return {\r\n success: false,\r\n error: 'Payment not yet completed',\r\n status: 'pending_authorization',\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n async capture(params: CapturePaymentParams): Promise<CaptureResult> {\r\n try {\r\n const statusResponse = await this.getLowProfileStatus(\r\n params.providerIntentId\r\n );\r\n\r\n if (!statusResponse.success || !statusResponse.data) {\r\n return {\r\n success: false,\r\n error: statusResponse.error ?? 'Failed to capture payment',\r\n };\r\n }\r\n\r\n const status = statusResponse.data;\r\n\r\n if (status.DealResponse === 1) {\r\n return {\r\n success: true,\r\n providerTransactionId: status.InternalDealNumber ?? params.providerIntentId,\r\n status: 'captured',\r\n capturedAmount: {\r\n amountMinor: Math.round((status.Amount ?? 0) * 100),\r\n currency: status.Currency ?? params.amount?.currency ?? 'ILS',\r\n },\r\n };\r\n }\r\n\r\n return {\r\n success: false,\r\n error: 'Payment not authorized for capture',\r\n status: mapCardcomDealResponseToStatus(status.DealResponse ?? 3),\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n async void(_params: VoidPaymentParams): Promise<VoidResult> {\r\n return {\r\n success: false,\r\n error: 'Void operation not supported via API. Please use Cardcom merchant dashboard.',\r\n };\r\n }\r\n\r\n async refund(params: RefundParams): Promise<RefundResult> {\r\n try {\r\n const refundAmount = params.amount\r\n ? params.amount.amountMinor / 100\r\n : undefined;\r\n\r\n if (!refundAmount) {\r\n return {\r\n success: false,\r\n error: 'Refund amount is required',\r\n };\r\n }\r\n\r\n const request: CardcomRefundRequest = {\r\n TerminalNumber: this.config.terminalNumber,\r\n ApiName: this.config.apiName,\r\n ApiPassword: this.config.apiPassword,\r\n InternalDealNumber: params.providerTransactionId,\r\n Amount: refundAmount,\r\n CoinID: params.amount ? getCurrencyCode(params.amount.currency) : 1,\r\n };\r\n\r\n const response = await this.makeRequest<CardcomRefundResponse>(\r\n CARDCOM_ENDPOINTS.REFUND,\r\n request as unknown as Record<string, unknown>\r\n );\r\n\r\n if (response.ResponseCode !== 0) {\r\n return {\r\n success: false,\r\n error: mapCardcomError(response.ResponseCode),\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n providerRefundId: response.InternalDealNumber ?? params.providerTransactionId,\r\n refundedAmount: {\r\n amountMinor: Math.round((response.Amount ?? 0) * 100),\r\n currency: params.amount?.currency ?? 'ILS',\r\n },\r\n status: 'succeeded',\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n // ==========================================================================\r\n // Payment Method Tokenization\r\n // ==========================================================================\r\n\r\n async createSetupIntent(\r\n params: CreateSetupIntentParams\r\n ): Promise<SetupIntentResult> {\r\n try {\r\n const request: CardcomLowProfileRequest = {\r\n TerminalNumber: this.config.terminalNumber,\r\n ApiName: this.config.apiName,\r\n ApiPassword: this.config.apiPassword,\r\n Sum: 0,\r\n Operation: CardcomOperation.CREATE_TOKEN_ONLY,\r\n Language: 'en',\r\n InternalDealNumber: `setup_${params.userId}_${Date.now()}`,\r\n };\r\n\r\n const response = await this.makeRequest<CardcomLowProfileResponse>(\r\n CARDCOM_ENDPOINTS.LOW_PROFILE_CREATE,\r\n request as unknown as Record<string, unknown>\r\n );\r\n\r\n if (response.ResponseCode !== 0 || !response.PaymentUrl) {\r\n return {\r\n success: false,\r\n error: mapCardcomError(response.ResponseCode),\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n setupIntentId: response.LowProfileCode!,\r\n clientSecret: response.PaymentUrl,\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n async savePaymentMethod(\r\n params: SavePaymentMethodParams\r\n ): Promise<SavePaymentMethodResult> {\r\n try {\r\n const lowProfileCode = params.setupData.lowProfileCode as string;\r\n\r\n if (!lowProfileCode) {\r\n return {\r\n success: false,\r\n error: 'Low profile code is required',\r\n };\r\n }\r\n\r\n const statusResponse = await this.getLowProfileStatus(lowProfileCode);\r\n\r\n if (!statusResponse.success || !statusResponse.data) {\r\n return {\r\n success: false,\r\n error: statusResponse.error ?? 'Failed to retrieve payment method',\r\n };\r\n }\r\n\r\n const status = statusResponse.data;\r\n\r\n if (!status.Token) {\r\n return {\r\n success: false,\r\n error: 'No token created',\r\n };\r\n }\r\n\r\n const [expMonth, expYear] = (status.CardExpiration ?? '/').split('/');\r\n\r\n return {\r\n success: true,\r\n paymentMethodId: status.Token,\r\n cardBrand: status.CardType ?? 'unknown',\r\n cardLast4: status.CardMask?.slice(-4),\r\n cardExpMonth: expMonth?.padStart(2, '0'),\r\n cardExpYear: expYear ? `20${expYear}` : undefined,\r\n cardBin: status.CardBin,\r\n };\r\n } catch (error) {\r\n return this.handleError(error);\r\n }\r\n }\r\n\r\n async deletePaymentMethod(\r\n _paymentMethodId: string\r\n ): Promise<DeletePaymentMethodResult> {\r\n return {\r\n success: true,\r\n };\r\n }\r\n\r\n // ==========================================================================\r\n // Customer Management\r\n // ==========================================================================\r\n\r\n async createCustomer(params: CreateCustomerParams): Promise<CreateCustomerResult> {\r\n return {\r\n success: true,\r\n customerId: params.userId,\r\n };\r\n }\r\n\r\n async getOrCreateCustomer(\r\n userId: string,\r\n email: string\r\n ): Promise<CreateCustomerResult> {\r\n return this.createCustomer({ userId, email });\r\n }\r\n\r\n // ==========================================================================\r\n // Health & Status\r\n // ==========================================================================\r\n\r\n async getHealth(): Promise<ProviderHealthStatus> {\r\n const start = Date.now();\r\n try {\r\n const request: CardcomLowProfileRequest = {\r\n TerminalNumber: this.config.terminalNumber,\r\n ApiName: this.config.apiName,\r\n ApiPassword: this.config.apiPassword,\r\n Sum: 1,\r\n Operation: CardcomOperation.BILL_ONLY,\r\n InternalDealNumber: `health_check_${Date.now()}`,\r\n };\r\n\r\n const response = await this.makeRequest<CardcomLowProfileResponse>(\r\n CARDCOM_ENDPOINTS.LOW_PROFILE_CREATE,\r\n request as unknown as Record<string, unknown>\r\n );\r\n\r\n const healthy = response.ResponseCode === 0 || response.ResponseCode === 1;\r\n\r\n return {\r\n provider: 'cardcom',\r\n healthy,\r\n lastChecked: new Date(),\r\n avgLatencyMs: Date.now() - start,\r\n circuitBreakerOpen: false,\r\n };\r\n } catch {\r\n return {\r\n provider: 'cardcom',\r\n healthy: false,\r\n lastChecked: new Date(),\r\n circuitBreakerOpen: false,\r\n };\r\n }\r\n }\r\n\r\n validateWebhookSignature(payload: string, signature: string): boolean {\r\n if (!this.config.webhookSecret) {\r\n return false;\r\n }\r\n\r\n try {\r\n const expectedSignature = crypto\r\n .createHmac('sha256', this.config.webhookSecret)\r\n .update(payload)\r\n .digest('hex');\r\n\r\n return crypto.timingSafeEqual(\r\n Buffer.from(signature),\r\n Buffer.from(expectedSignature)\r\n );\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n async getPaymentIntentStatus(\r\n providerIntentId: string\r\n ): Promise<{ status: string; error?: string }> {\r\n try {\r\n const result = await this.getLowProfileStatus(providerIntentId);\r\n\r\n if (!result.success || !result.data) {\r\n return {\r\n status: 'unknown',\r\n error: result.error,\r\n };\r\n }\r\n\r\n const status = mapCardcomDealResponseToStatus(\r\n result.data.DealResponse ?? 0\r\n );\r\n\r\n return { status };\r\n } catch (error) {\r\n return {\r\n status: 'unknown',\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n };\r\n }\r\n }\r\n\r\n // ==========================================================================\r\n // Helper Methods\r\n // ==========================================================================\r\n\r\n private async makeRequest<T>(\r\n endpoint: string,\r\n data: Record<string, unknown>\r\n ): Promise<T> {\r\n const url = `${CARDCOM_API_BASE}${endpoint}`;\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(data),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Cardcom API error: ${response.status} ${response.statusText}`);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n }\r\n\r\n private async getLowProfileStatus(\r\n lowProfileCode: string\r\n ): Promise<{\r\n success: boolean;\r\n data?: CardcomLowProfileStatusResponse;\r\n error?: string;\r\n }> {\r\n try {\r\n const params = new URLSearchParams({\r\n terminalnumber: this.config.terminalNumber,\r\n lowprofilecode: lowProfileCode,\r\n username: this.config.apiName,\r\n });\r\n\r\n const url = `${CARDCOM_API_BASE}${CARDCOM_ENDPOINTS.LOW_PROFILE_STATUS}?${params}`;\r\n\r\n const response = await fetch(url, {\r\n method: 'GET',\r\n });\r\n\r\n if (!response.ok) {\r\n return {\r\n success: false,\r\n error: `Status check failed: ${response.status}`,\r\n };\r\n }\r\n\r\n const data = (await response.json()) as CardcomLowProfileStatusResponse;\r\n\r\n if (data.ResponseCode !== 0) {\r\n return {\r\n success: false,\r\n error: mapCardcomError(data.ResponseCode),\r\n };\r\n }\r\n\r\n return { success: true, data };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Status check failed',\r\n };\r\n }\r\n }\r\n\r\n private handleError(error: unknown): {\r\n success: false;\r\n error: string;\r\n errorCode?: string;\r\n } {\r\n const errorMessage =\r\n error instanceof Error ? error.message : 'Unknown error occurred';\r\n\r\n return {\r\n success: false,\r\n error: errorMessage,\r\n };\r\n }\r\n}\r\n","/**\r\n * Cardcom Type Definitions\r\n *\r\n * Type definitions for Cardcom payment gateway API v11.\r\n * Supports JSON API endpoints for Low Profile (hosted page) and direct transactions.\r\n *\r\n * @see https://secure.cardcom.solutions/api/v11/swagger/ui/index\r\n */\r\n\r\nimport type { TransactionStatus } from '@nehorai/payments/types';\r\n\r\n// ============================================================================\r\n// API Configuration\r\n// ============================================================================\r\n\r\nexport const CARDCOM_API_BASE = 'https://secure.cardcom.solutions';\r\n\r\nexport const CARDCOM_ENDPOINTS = {\r\n LOW_PROFILE_CREATE: '/api/v11/LowProfile/Create',\r\n LOW_PROFILE_STATUS: '/Interface/BillGoldGetLowProfileIndicator.aspx',\r\n DIRECT_CHARGE: '/api/v11/Transactions/Transaction',\r\n REFUND: '/api/v11/Transactions/RefundByTransactionId',\r\n} as const;\r\n\r\nexport const CARDCOM_SUPPORTED_CURRENCIES = ['ILS', 'USD', 'EUR', 'GBP'] as const;\r\n\r\nexport const CARDCOM_API_VERSION = 'v11';\r\n\r\n// ============================================================================\r\n// Cardcom Configuration\r\n// ============================================================================\r\n\r\nexport interface CardcomConfig {\r\n /** Terminal number (merchant ID) */\r\n terminalNumber: string;\r\n /** API username */\r\n apiName: string;\r\n /** API password */\r\n apiPassword: string;\r\n /** Webhook secret for signature validation */\r\n webhookSecret?: string;\r\n /** Environment (sandbox uses same endpoints but different credentials) */\r\n environment: 'sandbox' | 'production';\r\n}\r\n\r\n// ============================================================================\r\n// Operation Types\r\n// ============================================================================\r\n\r\nexport enum CardcomOperation {\r\n /** Charge immediately */\r\n BILL_ONLY = 1,\r\n /** Charge + save card token */\r\n BILL_AND_CREATE_TOKEN = 2,\r\n /** Save card without charging */\r\n CREATE_TOKEN_ONLY = 3,\r\n /** Authorize without capture (J5) */\r\n SUSPEND_DEAL_ONLY = 4,\r\n}\r\n\r\nexport enum CardcomTransactionType {\r\n REGULAR = 1,\r\n CREDIT = 2,\r\n INSTALLMENTS = 3,\r\n}\r\n\r\n// ============================================================================\r\n// Request Types\r\n// ============================================================================\r\n\r\nexport interface CardcomLowProfileRequest {\r\n TerminalNumber: string;\r\n ApiName: string;\r\n ApiPassword: string;\r\n Sum: number;\r\n CoinID?: number;\r\n Operation?: CardcomOperation;\r\n Language?: string;\r\n ReturnUrl?: string;\r\n ErrorUrl?: string;\r\n ProductName?: string;\r\n CustomerName?: string;\r\n Email?: string;\r\n InvoiceLanguage?: string;\r\n SendEmail?: boolean;\r\n IndicatorUrl?: string;\r\n InternalDealNumber?: string;\r\n}\r\n\r\nexport interface CardcomLowProfileStatusRequest {\r\n terminalnumber: string;\r\n lowprofilecode: string;\r\n username: string;\r\n}\r\n\r\nexport interface CardcomDirectChargeRequest {\r\n TerminalNumber: string;\r\n ApiName: string;\r\n ApiPassword: string;\r\n CardNumber: string;\r\n CVV: string;\r\n Year: string;\r\n Month: string;\r\n CardOwnerID: string;\r\n Sum: number;\r\n CoinID?: number;\r\n NumOfPayments?: number;\r\n Operation?: CardcomOperation;\r\n Token?: string;\r\n}\r\n\r\nexport interface CardcomRefundRequest {\r\n TerminalNumber: string;\r\n ApiName: string;\r\n ApiPassword: string;\r\n InternalDealNumber: string;\r\n Amount: number;\r\n CoinID?: number;\r\n}\r\n\r\n// ============================================================================\r\n// Response Types\r\n// ============================================================================\r\n\r\nexport interface CardcomLowProfileResponse {\r\n ResponseCode: number;\r\n Description?: string;\r\n LowProfileCode?: string;\r\n PaymentUrl?: string;\r\n DealCode?: string;\r\n}\r\n\r\nexport interface CardcomLowProfileStatusResponse {\r\n ResponseCode: number;\r\n Description?: string;\r\n DealResponse?: number;\r\n OperationResponse?: number;\r\n InternalDealNumber?: string;\r\n Token?: string;\r\n CardMask?: string;\r\n CardType?: string;\r\n CardExpiration?: string;\r\n Amount?: number;\r\n Currency?: string;\r\n CardBin?: string;\r\n}\r\n\r\nexport interface CardcomDirectChargeResponse {\r\n ResponseCode: number;\r\n Description?: string;\r\n InternalDealNumber?: string;\r\n ApprovalNumber?: string;\r\n CardMask?: string;\r\n Token?: string;\r\n DealCode?: string;\r\n}\r\n\r\nexport interface CardcomRefundResponse {\r\n ResponseCode: number;\r\n Description?: string;\r\n InternalDealNumber?: string;\r\n Amount?: number;\r\n}\r\n\r\n// ============================================================================\r\n// Webhook Types\r\n// ============================================================================\r\n\r\nexport interface CardcomWebhookParams {\r\n ResponseCode?: string;\r\n LowProfileCode?: string;\r\n DealResponse?: string;\r\n OperationResponse?: string;\r\n InternalDealNumber?: string;\r\n Amount?: string;\r\n Currency?: string;\r\n CardMask?: string;\r\n Token?: string;\r\n}\r\n\r\nexport const CARDCOM_WEBHOOK_EVENTS = [\r\n 'payment.completed',\r\n 'payment.declined',\r\n 'payment.authorized',\r\n] as const;\r\n\r\nexport type CardcomWebhookEventType = (typeof CARDCOM_WEBHOOK_EVENTS)[number];\r\n\r\nexport const CARDCOM_DEAL_RESPONSE_ACTIONS: Record<number, string> = {\r\n 0: 'pending',\r\n 1: 'approved',\r\n 2: 'declined',\r\n 3: 'error',\r\n};\r\n\r\n// ============================================================================\r\n// Response Code Mapping\r\n// ============================================================================\r\n\r\nexport const CARDCOM_RESPONSE_CODE_MAP: Record<number, TransactionStatus> = {\r\n 0: 'created',\r\n 1: 'failed',\r\n 2: 'failed',\r\n 3: 'failed',\r\n 4: 'failed',\r\n 5: 'failed',\r\n 6: 'failed',\r\n 7: 'failed',\r\n 8: 'failed',\r\n 9: 'failed',\r\n 10: 'failed',\r\n};\r\n\r\nexport function mapCardcomDealResponseToStatus(\r\n dealResponse: number\r\n): TransactionStatus {\r\n switch (dealResponse) {\r\n case 0:\r\n return 'pending_authorization';\r\n case 1:\r\n return 'captured';\r\n case 2:\r\n return 'failed';\r\n case 3:\r\n return 'failed';\r\n default:\r\n return 'failed';\r\n }\r\n}\r\n\r\nexport function mapCardcomError(responseCode: number): string {\r\n const errorMessages: Record<number, string> = {\r\n 0: 'Success',\r\n 1: 'General error',\r\n 2: 'Invalid API credentials',\r\n 3: 'Invalid terminal number',\r\n 4: 'Invalid operation type',\r\n 5: 'Invalid card details',\r\n 6: 'Card declined by issuer',\r\n 7: 'Insufficient funds',\r\n 8: 'Invalid amount',\r\n 9: 'Transaction not found',\r\n 10: 'Duplicate transaction',\r\n 11: 'Terminal not active',\r\n 12: 'CVV validation failed',\r\n 13: 'Card expired',\r\n 14: 'Invalid currency',\r\n 15: 'Operation not supported',\r\n };\r\n\r\n return errorMessages[responseCode] ?? `Error code ${responseCode}`;\r\n}\r\n\r\nexport const CARDCOM_CURRENCY_CODES: Record<string, number> = {\r\n ILS: 1,\r\n USD: 2,\r\n EUR: 3,\r\n GBP: 4,\r\n};\r\n\r\nexport function getCurrencyCode(currency: string): number {\r\n return CARDCOM_CURRENCY_CODES[currency.toUpperCase()] ?? 1;\r\n}\r\n\r\nexport const CARDCOM_LANGUAGE_CODES = {\r\n en: 'en',\r\n he: 'he',\r\n} as const;\r\n","/**\r\n * Hyp (CreditGuard) Webhook Handler\r\n *\r\n * Handles incoming webhooks/callbacks from Hyp/CreditGuard.\r\n * CreditGuard uses URL callbacks after transaction completion.\r\n *\r\n * @see https://cgpay3.creditguard.co.il/docs/callbacks\r\n */\r\n\r\nimport type {\r\n PaymentProvider,\r\n TransactionStatus,\r\n WebhookProcessingResult,\r\n ReconciliationResult,\r\n} from '@nehorai/payments/types';\r\nimport type {\r\n IWebhookHandler,\r\n ParsedWebhookEvent,\r\n ParseWebhookResult,\r\n} from '@nehorai/payments/providers';\r\nimport { mapHypStatus, mapHypError, isHypSuccess } from './hyp-types.js';\r\n\r\n/**\r\n * Hyp event types (synthesized from result codes)\r\n */\r\nconst HYP_EVENT_TYPES = {\r\n TRANSACTION_SUCCESS: 'transaction.success',\r\n TRANSACTION_FAILED: 'transaction.failed',\r\n TRANSACTION_PENDING: 'transaction.pending',\r\n REFUND_SUCCESS: 'refund.success',\r\n REFUND_FAILED: 'refund.failed',\r\n} as const;\r\n\r\n/**\r\n * Hyp Webhook Handler\r\n *\r\n * Processes callbacks from CreditGuard hosted pages and direct integrations.\r\n */\r\nexport class HypWebhookHandler implements IWebhookHandler {\r\n readonly provider: PaymentProvider = 'hyp';\r\n readonly supportedEventTypes = Object.values(HYP_EVENT_TYPES);\r\n\r\n parseEvent(rawPayload: Record<string, unknown>): ParseWebhookResult {\r\n try {\r\n const resultCode = String(rawPayload.resultCode ?? '100');\r\n const resultDescription = String(rawPayload.resultDescription ?? '');\r\n const transactionId = String(rawPayload.transactionId ?? '');\r\n const uniqueid = String(rawPayload.uniqueid ?? '');\r\n const total = Number(rawPayload.total ?? 0);\r\n const currency = String(rawPayload.currency ?? 'ILS');\r\n\r\n const eventType = this.determineEventType(resultCode);\r\n const newStatus = mapHypStatus(resultCode);\r\n\r\n const event: ParsedWebhookEvent = {\r\n provider: 'hyp',\r\n eventId: uniqueid || transactionId || `hyp_${Date.now()}`,\r\n eventType,\r\n providerTransactionId: transactionId,\r\n amountMinor: total,\r\n currency,\r\n newStatus: newStatus ?? undefined,\r\n error: isHypSuccess(resultCode)\r\n ? undefined\r\n : {\r\n code: resultCode,\r\n message: resultDescription,\r\n },\r\n timestamp: new Date(),\r\n rawPayload,\r\n };\r\n\r\n return {\r\n success: true,\r\n event,\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Failed to parse webhook',\r\n };\r\n }\r\n }\r\n\r\n async processEvent(\r\n event: ParsedWebhookEvent\r\n ): Promise<WebhookProcessingResult> {\r\n try {\r\n if (!event.providerTransactionId) {\r\n return {\r\n success: false,\r\n error: 'Missing transaction ID in webhook',\r\n action: 'ignored_event_type',\r\n };\r\n }\r\n\r\n const action = this.determineAction(event);\r\n\r\n return {\r\n success: true,\r\n transactionId: event.providerTransactionId,\r\n action,\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Processing failed',\r\n action: 'ignored_event_type',\r\n };\r\n }\r\n }\r\n\r\n canHandle(eventType: string): boolean {\r\n return this.supportedEventTypes.includes(\r\n eventType as (typeof HYP_EVENT_TYPES)[keyof typeof HYP_EVENT_TYPES]\r\n );\r\n }\r\n\r\n async reconcile(\r\n _transactionId: string,\r\n _providerTransactionId: string\r\n ): Promise<ReconciliationResult> {\r\n return {\r\n reconciled: false,\r\n finalStatus: 'pending_authorization',\r\n source: 'webhook',\r\n statusChanged: false,\r\n };\r\n }\r\n\r\n mapEventType(providerEventType: string): string {\r\n return providerEventType;\r\n }\r\n\r\n mapStatus(providerStatus: string): TransactionStatus | null {\r\n return mapHypStatus(providerStatus);\r\n }\r\n\r\n // ==========================================================================\r\n // Helper Methods\r\n // ==========================================================================\r\n\r\n private determineEventType(resultCode: string): string {\r\n if (isHypSuccess(resultCode)) {\r\n return HYP_EVENT_TYPES.TRANSACTION_SUCCESS;\r\n }\r\n\r\n if (resultCode === '200') {\r\n return HYP_EVENT_TYPES.TRANSACTION_PENDING;\r\n }\r\n\r\n return HYP_EVENT_TYPES.TRANSACTION_FAILED;\r\n }\r\n\r\n private determineAction(\r\n event: ParsedWebhookEvent\r\n ): WebhookProcessingResult['action'] {\r\n switch (event.eventType) {\r\n case HYP_EVENT_TYPES.TRANSACTION_SUCCESS:\r\n case HYP_EVENT_TYPES.TRANSACTION_FAILED:\r\n case HYP_EVENT_TYPES.TRANSACTION_PENDING:\r\n case HYP_EVENT_TYPES.REFUND_FAILED:\r\n return 'status_updated';\r\n\r\n case HYP_EVENT_TYPES.REFUND_SUCCESS:\r\n return 'refund_processed';\r\n\r\n default:\r\n return 'ignored_event_type';\r\n }\r\n }\r\n\r\n // ==========================================================================\r\n // Webhook Validation\r\n // ==========================================================================\r\n\r\n validateSignature(\r\n payload: Record<string, unknown>,\r\n signature?: string,\r\n secret?: string\r\n ): boolean {\r\n const hasRequiredParams =\r\n payload.resultCode !== undefined &&\r\n (payload.transactionId !== undefined || payload.uniqueid !== undefined);\r\n\r\n if (!hasRequiredParams) {\r\n return false;\r\n }\r\n\r\n if (secret && signature) {\r\n return this.validateHMAC(payload, signature, secret);\r\n }\r\n\r\n return hasRequiredParams;\r\n }\r\n\r\n private validateHMAC(\r\n _payload: Record<string, unknown>,\r\n signature: string,\r\n _secret: string\r\n ): boolean {\r\n try {\r\n return !!signature;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n // ==========================================================================\r\n // Callback URL Builders\r\n // ==========================================================================\r\n\r\n buildSuccessUrl(baseUrl: string, transactionId: string): string {\r\n return `${baseUrl}/api/payments/hyp/callback?status=success&txId=${transactionId}`;\r\n }\r\n\r\n buildErrorUrl(baseUrl: string, transactionId: string): string {\r\n return `${baseUrl}/api/payments/hyp/callback?status=error&txId=${transactionId}`;\r\n }\r\n\r\n buildCancelUrl(baseUrl: string, transactionId: string): string {\r\n return `${baseUrl}/api/payments/hyp/callback?status=cancel&txId=${transactionId}`;\r\n }\r\n\r\n // ==========================================================================\r\n // Response Parsing\r\n // ==========================================================================\r\n\r\n extractErrorDetails(payload: Record<string, unknown>): {\r\n code: string;\r\n message: string;\r\n userMessage: string;\r\n } {\r\n const resultCode = String(payload.resultCode ?? 'unknown');\r\n const resultDescription = String(payload.resultDescription ?? 'Unknown error');\r\n\r\n return {\r\n code: resultCode,\r\n message: resultDescription,\r\n userMessage: this.getUserFriendlyMessage(resultCode),\r\n };\r\n }\r\n\r\n private getUserFriendlyMessage(resultCode: string): string {\r\n const errorCode = mapHypError(resultCode);\r\n\r\n const messages: Record<string, string> = {\r\n card_declined: 'Your card was declined. Please try another payment method.',\r\n invalid_card: 'The card information is invalid. Please check and try again.',\r\n expired_card: 'Your card has expired. Please use a different card.',\r\n insufficient_funds: 'Insufficient funds. Please try another payment method.',\r\n invalid_cvc: 'The security code (CVV) is incorrect.',\r\n processing_error: 'A processing error occurred. Please try again.',\r\n authentication_required:\r\n 'Additional authentication is required. Please complete the verification.',\r\n unknown: 'An error occurred. Please try again or contact support.',\r\n };\r\n\r\n return messages[errorCode] ?? messages.unknown;\r\n }\r\n\r\n extractCardDetails(payload: Record<string, unknown>): {\r\n cardToken?: string;\r\n cardMask?: string;\r\n cardBrand?: string;\r\n cardExpiration?: string;\r\n last4?: string;\r\n } {\r\n const cardToken = payload.cardToken as string | undefined;\r\n const cardMask = payload.cardMask as string | undefined;\r\n const cardBrand = payload.cardBrand as string | undefined;\r\n const cardExpiration = payload.cardExpiration as string | undefined;\r\n\r\n return {\r\n cardToken,\r\n cardMask,\r\n cardBrand,\r\n cardExpiration,\r\n last4: cardMask?.slice(-4),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Create Hyp webhook handler instance\r\n */\r\nexport function createHypWebhookHandler(): HypWebhookHandler {\r\n return new HypWebhookHandler();\r\n}\r\n","/**\r\n * Cardcom Webhook Handler\r\n *\r\n * Processes incoming Cardcom webhooks with idempotency.\r\n * Maps Cardcom callback events to transaction status updates.\r\n *\r\n * Cardcom uses GET callback parameters instead of POST webhooks.\r\n * Parameters are sent to ReturnUrl after payment completion.\r\n */\r\n\r\nimport type {\r\n PaymentProvider,\r\n TransactionStatus,\r\n WebhookProcessingResult,\r\n ReconciliationResult,\r\n} from '@nehorai/payments/types';\r\nimport type {\r\n IWebhookHandler,\r\n ParsedWebhookEvent,\r\n ParseWebhookResult,\r\n} from '@nehorai/payments/providers';\r\nimport {\r\n CARDCOM_WEBHOOK_EVENTS,\r\n CARDCOM_DEAL_RESPONSE_ACTIONS,\r\n mapCardcomDealResponseToStatus,\r\n type CardcomWebhookEventType,\r\n type CardcomWebhookParams,\r\n} from './cardcom-types.js';\r\n\r\n/**\r\n * Cardcom Webhook Handler Implementation\r\n */\r\nexport class CardcomWebhookHandler implements IWebhookHandler {\r\n readonly provider: PaymentProvider = 'cardcom';\r\n readonly supportedEventTypes = CARDCOM_WEBHOOK_EVENTS;\r\n\r\n parseEvent(rawPayload: Record<string, unknown>): ParseWebhookResult {\r\n try {\r\n const params = rawPayload as unknown as CardcomWebhookParams;\r\n\r\n const responseCode = parseInt(params.ResponseCode ?? '1', 10);\r\n const dealResponse = parseInt(params.DealResponse ?? '0', 10);\r\n const lowProfileCode = params.LowProfileCode ?? '';\r\n const internalDealNumber = params.InternalDealNumber ?? '';\r\n\r\n if (!lowProfileCode && !internalDealNumber) {\r\n return {\r\n success: false,\r\n error: 'Missing LowProfileCode or InternalDealNumber in callback',\r\n };\r\n }\r\n\r\n let eventType: CardcomWebhookEventType;\r\n if (dealResponse === 1) {\r\n eventType = 'payment.completed';\r\n } else if (dealResponse === 2) {\r\n eventType = 'payment.declined';\r\n } else if (dealResponse === 0 && responseCode === 0) {\r\n eventType = 'payment.authorized';\r\n } else {\r\n eventType = 'payment.declined';\r\n }\r\n\r\n const status = mapCardcomDealResponseToStatus(dealResponse);\r\n\r\n const amountString = params.Amount ?? '0';\r\n const amountMajor = parseFloat(amountString);\r\n const amountMinor = Math.round(amountMajor * 100);\r\n\r\n const parsed: ParsedWebhookEvent = {\r\n provider: 'cardcom',\r\n eventId: `${lowProfileCode}_${internalDealNumber}_${Date.now()}`,\r\n eventType,\r\n providerTransactionId: internalDealNumber || lowProfileCode,\r\n timestamp: new Date(),\r\n rawPayload,\r\n newStatus: status,\r\n amountMinor,\r\n currency: params.Currency ?? 'ILS',\r\n };\r\n\r\n if (dealResponse === 2 || responseCode !== 0) {\r\n parsed.error = {\r\n code: String(responseCode),\r\n message: CARDCOM_DEAL_RESPONSE_ACTIONS[dealResponse] ?? 'Payment failed',\r\n };\r\n }\r\n\r\n return { success: true, event: parsed };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Parse error',\r\n };\r\n }\r\n }\r\n\r\n async processEvent(\r\n event: ParsedWebhookEvent\r\n ): Promise<WebhookProcessingResult> {\r\n const action = this.getActionForEvent(event.eventType);\r\n\r\n if (action === 'ignored') {\r\n return {\r\n success: true,\r\n action: 'ignored_event_type',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n transactionId: event.providerTransactionId,\r\n action: 'status_updated',\r\n };\r\n }\r\n\r\n canHandle(eventType: string): boolean {\r\n return this.supportedEventTypes.includes(\r\n eventType as CardcomWebhookEventType\r\n );\r\n }\r\n\r\n async reconcile(\r\n _transactionId: string,\r\n _providerTransactionId: string\r\n ): Promise<ReconciliationResult> {\r\n return {\r\n reconciled: false,\r\n finalStatus: 'created',\r\n source: 'provider_query',\r\n statusChanged: false,\r\n };\r\n }\r\n\r\n mapEventType(providerEventType: string): string {\r\n return providerEventType;\r\n }\r\n\r\n mapStatus(providerStatus: string): TransactionStatus | null {\r\n const dealResponse = parseInt(providerStatus, 10);\r\n if (isNaN(dealResponse)) {\r\n return null;\r\n }\r\n return mapCardcomDealResponseToStatus(dealResponse);\r\n }\r\n\r\n private getActionForEvent(eventType: string): 'status_update' | 'ignored' {\r\n switch (eventType) {\r\n case 'payment.completed':\r\n case 'payment.declined':\r\n case 'payment.authorized':\r\n return 'status_update';\r\n default:\r\n return 'ignored';\r\n }\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Callback Utility Functions\r\n// ============================================================================\r\n\r\nexport function validateCardcomCallback(\r\n params: Record<string, unknown>\r\n): { valid: boolean; error?: string } {\r\n const requiredFields = ['ResponseCode', 'LowProfileCode'];\r\n\r\n for (const field of requiredFields) {\r\n if (!params[field]) {\r\n return {\r\n valid: false,\r\n error: `Missing required field: ${field}`,\r\n };\r\n }\r\n }\r\n\r\n const responseCode = parseInt(String(params.ResponseCode), 10);\r\n if (isNaN(responseCode)) {\r\n return {\r\n valid: false,\r\n error: 'Invalid ResponseCode format',\r\n };\r\n }\r\n\r\n return { valid: true };\r\n}\r\n\r\nexport function parseCardcomCallbackUrl(url: string): CardcomWebhookParams {\r\n try {\r\n const urlObj = new URL(url);\r\n const params: CardcomWebhookParams = {};\r\n\r\n params.ResponseCode = urlObj.searchParams.get('ResponseCode') ?? undefined;\r\n params.LowProfileCode =\r\n urlObj.searchParams.get('LowProfileCode') ?? undefined;\r\n params.DealResponse = urlObj.searchParams.get('DealResponse') ?? undefined;\r\n params.OperationResponse =\r\n urlObj.searchParams.get('OperationResponse') ?? undefined;\r\n params.InternalDealNumber =\r\n urlObj.searchParams.get('InternalDealNumber') ?? undefined;\r\n params.Amount = urlObj.searchParams.get('Amount') ?? undefined;\r\n params.Currency = urlObj.searchParams.get('Currency') ?? undefined;\r\n params.CardMask = urlObj.searchParams.get('CardMask') ?? undefined;\r\n params.Token = urlObj.searchParams.get('Token') ?? undefined;\r\n\r\n return params;\r\n } catch {\r\n return {};\r\n }\r\n}\r\n\r\nexport function isCardcomCallbackSuccess(params: CardcomWebhookParams): boolean {\r\n const responseCode = parseInt(params.ResponseCode ?? '1', 10);\r\n const dealResponse = parseInt(params.DealResponse ?? '0', 10);\r\n\r\n return responseCode === 0 && dealResponse === 1;\r\n}\r\n\r\nexport function isCardcomCallbackAuthorized(\r\n params: CardcomWebhookParams\r\n): boolean {\r\n const responseCode = parseInt(params.ResponseCode ?? '1', 10);\r\n const dealResponse = parseInt(params.DealResponse ?? '0', 10);\r\n\r\n return responseCode === 0 && (dealResponse === 0 || dealResponse === 1);\r\n}\r\n\r\nexport function getCardcomCallbackError(\r\n params: CardcomWebhookParams\r\n): string | null {\r\n const responseCode = parseInt(params.ResponseCode ?? '1', 10);\r\n const dealResponse = parseInt(params.DealResponse ?? '0', 10);\r\n\r\n if (responseCode === 0 && dealResponse === 1) {\r\n return null;\r\n }\r\n\r\n if (dealResponse === 2) {\r\n return 'Payment declined by card issuer';\r\n }\r\n\r\n if (responseCode !== 0) {\r\n return `Payment failed with code ${responseCode}`;\r\n }\r\n\r\n return 'Payment processing error';\r\n}\r\n","/**\r\n * Israeli Payment Providers Factory\r\n *\r\n * Convenience function to register Hyp and Cardcom providers\r\n * into an existing PaymentServices instance.\r\n *\r\n * Follows the same pattern as @nehorai/payments-stripe's addStripeProvider.\r\n */\r\n\r\nimport type { HypConfig } from './providers/hyp/hyp-types.js';\r\nimport type { CardcomProviderConfig } from './providers/cardcom/cardcom-provider.js';\r\nimport { HypProvider } from './providers/hyp/hyp-provider.js';\r\nimport { CardcomProvider } from './providers/cardcom/cardcom-provider.js';\r\nimport { HypWebhookHandler } from './providers/hyp/hyp-webhook-handler.js';\r\nimport { CardcomWebhookHandler } from './providers/cardcom/cardcom-webhook-handler.js';\r\n\r\n/**\r\n * Service registry interface for provider registration.\r\n * Compatible with PaymentServices from @nehorai/payments.\r\n */\r\ninterface ProviderRegistry {\r\n providers: Map<string, unknown>;\r\n webhookHandlers: Map<string, unknown>;\r\n}\r\n\r\n/**\r\n * Configuration for adding Israeli providers\r\n */\r\nexport interface IsraeliProvidersConfig {\r\n hyp?: HypConfig;\r\n cardcom?: CardcomProviderConfig;\r\n}\r\n\r\n/**\r\n * Register Israeli payment providers into a PaymentServices instance.\r\n *\r\n * Mutates the services Maps in-place (same pattern as addStripeProvider).\r\n * Only registers providers for which configuration is provided.\r\n *\r\n * @param services - PaymentServices instance to register into\r\n * @param config - Israeli providers configuration\r\n * @returns The same services object for chaining\r\n *\r\n * @example\r\n * ```typescript\r\n * import { createPaymentServices } from '@nehorai/payments';\r\n * import { addIsraeliProviders, ISRAELI_ROUTING_RULES } from '@nehorai/payments-il';\r\n *\r\n * const services = createPaymentServices({\r\n * providers: new Map(),\r\n * routingRules: ISRAELI_ROUTING_RULES,\r\n * });\r\n *\r\n * addIsraeliProviders(services, {\r\n * hyp: {\r\n * terminalNumber: '123',\r\n * user: 'user',\r\n * password: 'pass',\r\n * environment: 'sandbox',\r\n * },\r\n * cardcom: {\r\n * terminalNumber: '456',\r\n * apiName: 'api',\r\n * apiPassword: 'pass',\r\n * },\r\n * });\r\n * ```\r\n */\r\nexport function addIsraeliProviders<T extends ProviderRegistry>(\r\n services: T,\r\n config: IsraeliProvidersConfig\r\n): T {\r\n if (config.hyp) {\r\n services.providers.set('hyp', new HypProvider(config.hyp));\r\n services.webhookHandlers.set('hyp', new HypWebhookHandler());\r\n }\r\n\r\n if (config.cardcom) {\r\n services.providers.set('cardcom', new CardcomProvider(config.cardcom));\r\n services.webhookHandlers.set('cardcom', new CardcomWebhookHandler());\r\n }\r\n\r\n return services;\r\n}\r\n"],"mappings":"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","names":["calculateCaptureDeadline","calculateCaptureDeadline"]}
|