@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.
@@ -0,0 +1,113 @@
1
+ // src/routing/routing-rules.ts
2
+ var ISRAELI_BIN_RANGES = [
3
+ // Isracard
4
+ { start: "458000", end: "458999", issuer: "Isracard", country: "IL" },
5
+ { start: "480000", end: "480999", issuer: "Isracard", country: "IL" },
6
+ // Cal (Visa Cal)
7
+ { start: "532600", end: "532699", issuer: "Cal", country: "IL" },
8
+ { start: "557050", end: "557059", issuer: "Cal", country: "IL" },
9
+ // Leumi Card
10
+ { start: "589200", end: "589299", issuer: "Leumi Card", country: "IL" },
11
+ // Diners Israel
12
+ { start: "363700", end: "363799", issuer: "Diners Israel", country: "IL" },
13
+ // Max (Leumi)
14
+ { start: "491861", end: "491861", issuer: "Max", country: "IL" },
15
+ { start: "458600", end: "458699", issuer: "Max", country: "IL" }
16
+ ];
17
+ var ISRAELI_CARD_BIN_RULES = [
18
+ {
19
+ ranges: ISRAELI_BIN_RANGES.map((r) => ({
20
+ start: r.start,
21
+ end: r.end,
22
+ issuer: r.issuer,
23
+ country: r.country
24
+ })),
25
+ preferredProvider: "hyp",
26
+ priority: 1
27
+ }
28
+ ];
29
+ var ISRAELI_PROVIDER_PRIORITIES = [
30
+ {
31
+ provider: "hyp",
32
+ priority: 1,
33
+ maxFeePercent: 1.8,
34
+ supportsCurrency: ["ILS", "USD", "EUR"],
35
+ supportsRecurring: true,
36
+ isLocalGateway: true
37
+ },
38
+ {
39
+ provider: "cardcom",
40
+ priority: 2,
41
+ maxFeePercent: 2,
42
+ supportsCurrency: ["ILS", "USD", "EUR"],
43
+ supportsRecurring: true,
44
+ isLocalGateway: true
45
+ },
46
+ {
47
+ provider: "stripe",
48
+ priority: 3,
49
+ maxFeePercent: 2.9,
50
+ supportsCurrency: ["USD", "EUR", "GBP", "ILS", "CAD", "AUD"],
51
+ supportsRecurring: true,
52
+ isLocalGateway: false
53
+ }
54
+ ];
55
+ var ISRAELI_ROUTING_RULES = {
56
+ cardBinRules: ISRAELI_CARD_BIN_RULES,
57
+ providerPriorities: ISRAELI_PROVIDER_PRIORITIES
58
+ };
59
+ function isIsraeliCard(bin) {
60
+ if (!bin || bin.length < 6) return false;
61
+ const binPrefix = bin.substring(0, 6);
62
+ return ISRAELI_BIN_RANGES.some(
63
+ (range) => binPrefix >= range.start && binPrefix <= range.end
64
+ );
65
+ }
66
+ function getCardIssuer(bin) {
67
+ if (!bin || bin.length < 6) return null;
68
+ const binPrefix = bin.substring(0, 6);
69
+ const range = ISRAELI_BIN_RANGES.find(
70
+ (r) => binPrefix >= r.start && binPrefix <= r.end
71
+ );
72
+ return range?.issuer ?? null;
73
+ }
74
+ function getOptimalProvider(isIsraeli, currency, requiresRecurring, availableProviders) {
75
+ const candidates = ISRAELI_PROVIDER_PRIORITIES.filter(
76
+ (p) => availableProviders.includes(p.provider)
77
+ );
78
+ if (candidates.length === 0) return null;
79
+ const suitable = candidates.filter((p) => {
80
+ if (!p.supportsCurrency.includes(currency)) return false;
81
+ if (requiresRecurring && !p.supportsRecurring) return false;
82
+ return true;
83
+ });
84
+ if (suitable.length === 0) {
85
+ return candidates[0]?.provider ?? null;
86
+ }
87
+ if (isIsraeli) {
88
+ const localProviders = suitable.filter((p) => p.isLocalGateway);
89
+ if (localProviders.length > 0) {
90
+ return localProviders.sort((a, b) => a.priority - b.priority)[0].provider;
91
+ }
92
+ }
93
+ return suitable.sort((a, b) => a.priority - b.priority)[0].provider;
94
+ }
95
+ function getFallbackProviders(primaryProvider, availableProviders) {
96
+ return ISRAELI_PROVIDER_PRIORITIES.filter(
97
+ (p) => p.provider !== primaryProvider && availableProviders.includes(p.provider)
98
+ ).sort((a, b) => a.priority - b.priority).map((p) => p.provider);
99
+ }
100
+ function getProviderFeePercent(provider) {
101
+ const config = ISRAELI_PROVIDER_PRIORITIES.find((p) => p.provider === provider);
102
+ return config?.maxFeePercent ?? 3;
103
+ }
104
+ export {
105
+ ISRAELI_BIN_RANGES,
106
+ ISRAELI_ROUTING_RULES,
107
+ getCardIssuer,
108
+ getFallbackProviders,
109
+ getOptimalProvider,
110
+ getProviderFeePercent,
111
+ isIsraeliCard
112
+ };
113
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/routing/routing-rules.ts"],"sourcesContent":["/**\r\n * Israeli Routing Rules Configuration\r\n *\r\n * Defines BIN (Bank Identification Number) ranges for smart routing\r\n * and provider selection rules.\r\n *\r\n * Exports ISRAELI_ROUTING_RULES as RoutingRules type from @nehorai/payments,\r\n * so it can be passed directly to createPaymentServices({ routingRules }).\r\n *\r\n * Israeli cards are routed to local gateways (Hyp/Cardcom) for:\r\n * - Better transaction fees (1.8% vs 2.9%)\r\n * - Higher approval rates for Israeli customers\r\n * - ILS currency support\r\n */\r\n\r\nimport type { PaymentProvider } from '@nehorai/payments/types';\r\nimport type {\r\n RoutingRules,\r\n CardBinRule,\r\n ProviderPriorityRule,\r\n} from '@nehorai/payments/services';\r\n\r\n// ============================================================================\r\n// Israeli BIN Ranges\r\n// ============================================================================\r\n\r\n/**\r\n * BIN range definition (local type for documentation purposes)\r\n */\r\nexport interface BINRange {\r\n /** Starting BIN (6 digits) */\r\n start: string;\r\n /** Ending BIN (6 digits) */\r\n end: string;\r\n /** Card issuer name */\r\n issuer: string;\r\n /** Country code */\r\n country: string;\r\n}\r\n\r\n/**\r\n * Israeli credit card BIN ranges\r\n * These cards should be routed to local gateways for better rates\r\n *\r\n * Note: This is not exhaustive. In production, consider using a BIN database\r\n * service for comprehensive coverage.\r\n */\r\nexport const ISRAELI_BIN_RANGES: readonly BINRange[] = [\r\n // Isracard\r\n { start: '458000', end: '458999', issuer: 'Isracard', country: 'IL' },\r\n { start: '480000', end: '480999', issuer: 'Isracard', country: 'IL' },\r\n\r\n // Cal (Visa Cal)\r\n { start: '532600', end: '532699', issuer: 'Cal', country: 'IL' },\r\n { start: '557050', end: '557059', issuer: 'Cal', country: 'IL' },\r\n\r\n // Leumi Card\r\n { start: '589200', end: '589299', issuer: 'Leumi Card', country: 'IL' },\r\n\r\n // Diners Israel\r\n { start: '363700', end: '363799', issuer: 'Diners Israel', country: 'IL' },\r\n\r\n // Max (Leumi)\r\n { start: '491861', end: '491861', issuer: 'Max', country: 'IL' },\r\n { start: '458600', end: '458699', issuer: 'Max', country: 'IL' },\r\n] as const;\r\n\r\n// ============================================================================\r\n// Card BIN Rules (RoutingRules-compatible)\r\n// ============================================================================\r\n\r\n/**\r\n * Israeli card BIN rules in CardBinRule format for the core routing engine.\r\n * All Israeli BIN ranges prefer 'hyp' as the primary local gateway.\r\n */\r\nconst ISRAELI_CARD_BIN_RULES: CardBinRule[] = [\r\n {\r\n ranges: ISRAELI_BIN_RANGES.map((r) => ({\r\n start: r.start,\r\n end: r.end,\r\n issuer: r.issuer,\r\n country: r.country,\r\n })),\r\n preferredProvider: 'hyp',\r\n priority: 1,\r\n },\r\n];\r\n\r\n// ============================================================================\r\n// Provider Priority Rules (RoutingRules-compatible)\r\n// ============================================================================\r\n\r\n/**\r\n * Israeli provider priorities in ProviderPriorityRule format.\r\n * Local gateways (Hyp, Cardcom) are prioritized over international providers.\r\n */\r\nconst ISRAELI_PROVIDER_PRIORITIES: ProviderPriorityRule[] = [\r\n {\r\n provider: 'hyp',\r\n priority: 1,\r\n maxFeePercent: 1.8,\r\n supportsCurrency: ['ILS', 'USD', 'EUR'],\r\n supportsRecurring: true,\r\n isLocalGateway: true,\r\n },\r\n {\r\n provider: 'cardcom',\r\n priority: 2,\r\n maxFeePercent: 2.0,\r\n supportsCurrency: ['ILS', 'USD', 'EUR'],\r\n supportsRecurring: true,\r\n isLocalGateway: true,\r\n },\r\n {\r\n provider: 'stripe',\r\n priority: 3,\r\n maxFeePercent: 2.9,\r\n supportsCurrency: ['USD', 'EUR', 'GBP', 'ILS', 'CAD', 'AUD'],\r\n supportsRecurring: true,\r\n isLocalGateway: false,\r\n },\r\n];\r\n\r\n// ============================================================================\r\n// Exported RoutingRules (core-compatible)\r\n// ============================================================================\r\n\r\n/**\r\n * Israeli routing rules, compatible with the core RoutingRules type.\r\n * Pass directly to createPaymentServices({ routingRules: ISRAELI_ROUTING_RULES }).\r\n */\r\nexport const ISRAELI_ROUTING_RULES: RoutingRules = {\r\n cardBinRules: ISRAELI_CARD_BIN_RULES,\r\n providerPriorities: ISRAELI_PROVIDER_PRIORITIES,\r\n};\r\n\r\n// ============================================================================\r\n// Routing Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Check if a BIN belongs to an Israeli card\r\n */\r\nexport function isIsraeliCard(bin: string): boolean {\r\n if (!bin || bin.length < 6) return false;\r\n\r\n const binPrefix = bin.substring(0, 6);\r\n\r\n return ISRAELI_BIN_RANGES.some(\r\n (range) => binPrefix >= range.start && binPrefix <= range.end\r\n );\r\n}\r\n\r\n/**\r\n * Get card issuer from BIN\r\n */\r\nexport function getCardIssuer(bin: string): string | null {\r\n if (!bin || bin.length < 6) return null;\r\n\r\n const binPrefix = bin.substring(0, 6);\r\n\r\n const range = ISRAELI_BIN_RANGES.find(\r\n (r) => binPrefix >= r.start && binPrefix <= r.end\r\n );\r\n\r\n return range?.issuer ?? null;\r\n}\r\n\r\n/**\r\n * Get optimal provider for a given context\r\n */\r\nexport function getOptimalProvider(\r\n isIsraeli: boolean,\r\n currency: string,\r\n requiresRecurring: boolean,\r\n availableProviders: PaymentProvider[]\r\n): PaymentProvider | null {\r\n const candidates = ISRAELI_PROVIDER_PRIORITIES.filter((p) =>\r\n availableProviders.includes(p.provider)\r\n );\r\n\r\n if (candidates.length === 0) return null;\r\n\r\n const suitable = candidates.filter((p) => {\r\n if (!p.supportsCurrency.includes(currency)) return false;\r\n if (requiresRecurring && !p.supportsRecurring) return false;\r\n return true;\r\n });\r\n\r\n if (suitable.length === 0) {\r\n return candidates[0]?.provider ?? null;\r\n }\r\n\r\n if (isIsraeli) {\r\n const localProviders = suitable.filter((p) => p.isLocalGateway);\r\n if (localProviders.length > 0) {\r\n return localProviders.sort((a, b) => a.priority - b.priority)[0].provider;\r\n }\r\n }\r\n\r\n return suitable.sort((a, b) => a.priority - b.priority)[0].provider;\r\n}\r\n\r\n/**\r\n * Get fallback providers in order of priority\r\n */\r\nexport function getFallbackProviders(\r\n primaryProvider: PaymentProvider,\r\n availableProviders: PaymentProvider[]\r\n): PaymentProvider[] {\r\n return ISRAELI_PROVIDER_PRIORITIES\r\n .filter((p) =>\r\n p.provider !== primaryProvider &&\r\n availableProviders.includes(p.provider)\r\n )\r\n .sort((a, b) => a.priority - b.priority)\r\n .map((p) => p.provider);\r\n}\r\n\r\n/**\r\n * Get estimated fee for a provider\r\n */\r\nexport function getProviderFeePercent(provider: PaymentProvider): number {\r\n const config = ISRAELI_PROVIDER_PRIORITIES.find((p) => p.provider === provider);\r\n return config?.maxFeePercent ?? 3.0;\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@nehorai/payments-il",
3
+ "version": "0.1.0",
4
+ "description": "Israeli payment providers (Hyp, Cardcom) for @nehorai/payments",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./hyp": {
16
+ "types": "./dist/hyp/index.d.ts",
17
+ "import": "./dist/hyp/index.js",
18
+ "require": "./dist/hyp/index.cjs"
19
+ },
20
+ "./cardcom": {
21
+ "types": "./dist/cardcom/index.d.ts",
22
+ "import": "./dist/cardcom/index.js",
23
+ "require": "./dist/cardcom/index.cjs"
24
+ },
25
+ "./routing": {
26
+ "types": "./dist/routing/index.d.ts",
27
+ "import": "./dist/routing/index.js",
28
+ "require": "./dist/routing/index.cjs"
29
+ },
30
+ "./factory": {
31
+ "types": "./dist/factory.d.ts",
32
+ "import": "./dist/factory.js",
33
+ "require": "./dist/factory.cjs"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist"
38
+ ],
39
+ "dependencies": {
40
+ "@nehorai/payments": "0.1.0"
41
+ },
42
+ "devDependencies": {
43
+ "typescript": "^5.7.3",
44
+ "tsup": "^8.0.0",
45
+ "@types/node": "^22.13.4"
46
+ },
47
+ "license": "MIT",
48
+ "author": "Nehorai Hadad",
49
+ "scripts": {
50
+ "build": "tsup",
51
+ "dev": "tsup --watch",
52
+ "typecheck": "tsc --noEmit"
53
+ }
54
+ }