From 25cf56abbcdb8d011cba87817cc72fe959cc84b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bieszczad?= Date: Mon, 20 Jul 2026 08:37:48 +0200 Subject: [PATCH 1/4] chore(POCP-1226): support 8-digit IINs in card event --- src/dynamic-checkout/payment-methods/card.ts | 7 ++++++- src/processout/card.ts | 4 ++-- src/processout/processout.ts | 5 ++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/dynamic-checkout/payment-methods/card.ts b/src/dynamic-checkout/payment-methods/card.ts index c7e3be86..dcc6b668 100644 --- a/src/dynamic-checkout/payment-methods/card.ts +++ b/src/dynamic-checkout/payment-methods/card.ts @@ -918,7 +918,12 @@ module ProcessOut { return } - const isAllowedIin = restrictToIins.indexOf(iin) !== -1 + // card_iin may carry more digits than the configured entries (IINs can + // be 6 or 8 digits), so match on prefix: an allowed entry matches when + // the detected IIN starts with it. + const isAllowedIin = restrictToIins.some(function (allowedIin) { + return allowedIin.length > 0 && iin.substring(0, allowedIin.length) === allowedIin + }) this.setCardRestrictionState(!isAllowedIin) } diff --git a/src/processout/card.ts b/src/processout/card.ts index 480d8789..f7e111bf 100644 --- a/src/processout/card.ts +++ b/src/processout/card.ts @@ -456,8 +456,8 @@ module ProcessOut { number = Card.parseNumber(number); // Remove potential spaces var l = number.length; - if (l > 6) - l = 6; + if (l > 8) + l = 8; return number.substring(0, l); } diff --git a/src/processout/processout.ts b/src/processout/processout.ts index 2ae80956..d5a8df4c 100644 --- a/src/processout/processout.ts +++ b/src/processout/processout.ts @@ -1676,7 +1676,10 @@ module ProcessOut { return } - const iin = cardNumber.substring(0, 6) + // Support up to 8-digit IINs (some networks issue 8-digit IINs, which + // yield more accurate issuer information); fall back to whatever is + // available when fewer digits were provided. + const iin = cardNumber.substring(0, 8) const apiEndpoint = `iins/${iin}` this.apiRequest( From a1bf701874f64bb5269622a045615c5042ee459e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bieszczad?= Date: Mon, 20 Jul 2026 08:52:20 +0200 Subject: [PATCH 2/4] update example --- examples/card-form/index.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/card-form/index.html b/examples/card-form/index.html index e4824ff6..8d09bf09 100644 --- a/examples/card-form/index.html +++ b/examples/card-form/index.html @@ -55,7 +55,7 @@ function (form) { let preferredCardType = null; form.getNumberField().on("input", function (e) { - if (e.card_number_length == 6) { + if (e.card_number_length == 8) { client.getCardInformation( e.card_iin, function(cardInfo) { @@ -65,7 +65,7 @@ const radioGroup = document.createElement('div') radioGroup.className = 'combo-card-types' radioGroup.style.cssText = 'margin: 15px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; background: #f9f9f9;' - + radioGroup.innerHTML = `

Select Card Type:

${cardInfo.combo_card_types.map((type, index) => ` @@ -75,11 +75,11 @@

Select Card Type:

`).join('')} ` - + // Insert before the Pay button const payButton = document.querySelector('.submit-button') payButton.parentNode.insertBefore(radioGroup, payButton) - + // Add event listener to track selection changes const radioButtons = radioGroup.querySelectorAll('input[name="cardType"]') radioButtons.forEach(radio => { @@ -88,7 +88,7 @@

Select Card Type:

console.log("User selected card type:", preferredCardType) }) }) - + // Set initial value preferredCardType = null } @@ -98,7 +98,7 @@

Select Card Type:

} ) } - + document.getElementById("errors").innerHTML = "" }) From 1f3179d0912b6167d6baf3d1c219f33e1fc55cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bieszczad?= Date: Thu, 23 Jul 2026 15:01:59 +0200 Subject: [PATCH 3/4] fix(POCP-1226): cap 8-digit IIN exposure per scheme Card.getIIN emitted a flat 8-digit IIN for every scheme, over-exposing the BIN for schemes the backend caps at 6 (notably Amex). Mirror the allow-list in api (controllers/card_inn.go): only visa, mastercard, discover, jcb, union-pay and carte bancaire surface 8 digits; every other scheme - plus unknown or co-badged/ambiguous prefixes - falls back to 6. Applies to both consumers of getIIN: the emitted card_iin field event and the Dynamic Checkout restrict_to_iins prefix match. Note: the backend api-deactivate-eight-digit-bin LaunchDarkly flag is per-project and server-side, so the client cap is scheme-based only. --- src/processout/card.ts | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/processout/card.ts b/src/processout/card.ts index f7e111bf..65329180 100644 --- a/src/processout/card.ts +++ b/src/processout/card.ts @@ -455,12 +455,47 @@ module ProcessOut { public static getIIN(number: string): string { number = Card.parseNumber(number); // Remove potential spaces + // Only expose an 8-digit IIN for schemes the backend allows to + // do so; every other scheme is capped at 6 to avoid + // over-exposing the BIN. Mirrors api (controllers/card_inn.go). + var max = Card.canExpose8DigitIIN(number) ? 8 : 6; var l = number.length; - if (l > 8) - l = 8; + if (l > max) + l = max; return number.substring(0, l); } + /** + * Schemes permitted to surface an 8-digit IIN, mirroring the backend + * allow-list in api (controllers/card_inn.go). Every other scheme - + * notably American Express - is capped at 6 digits. Note the JS + * scheme key "union-pay" maps to the backend's "china union pay". + */ + private static iin8DigitSchemes: Array = [ + "visa", "mastercard", "discover", "jcb", "union-pay", "carte bancaire" + ]; + + /** + * canExpose8DigitIIN reports whether the card number's detected + * scheme(s) are allowed to surface an 8-digit IIN. Conservative: every + * detected scheme must be in the allow-list, so co-badged or ambiguous + * prefixes (and unknown schemes) fall back to 6 digits. + * @param {string} number + * @return {boolean} + */ + public static canExpose8DigitIIN(number: string): boolean { + var schemes = Card.getPossibleSchemes(number); + if (schemes.length == 0) + return false; + + for (var i = 0; i < schemes.length; i++) { + if (Card.iin8DigitSchemes.indexOf(schemes[i]) === -1) + return false; + } + + return true; + } + /** * GetLast4Digits returns the last4 digits of the card number * @param {string} number From eb0808516a23bf706cfee027191a9afc3c234e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Bieszczad?= Date: Mon, 20 Jul 2026 08:38:25 +0200 Subject: [PATCH 4/4] v1.9.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 01c213d8..24836bcf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "processout.js", - "version": "1.9.7", + "version": "1.9.8", "description": "ProcessOut.js is a JavaScript library for ProcessOut's payment processing API.", "scripts": { "build:processout": "tsc -p src/processout && uglifyjs --compress --keep-fnames --ie8 dist/processout.js -o dist/processout.js",