Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions examples/card-form/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,13 @@
color: "#ababab",
},
},
exposeIIN8: true,
Comment thread
lukasz-k-bieszczad-cko marked this conversation as resolved.
},
function (form) {
let preferredCardType = null;
form.getNumberField().on("input", function (e) {
if (e.card_number_length == 6) {
if (e.card_number_length == 6 || e.card_number_length == 16) {
// use 6 digit IIN or 8 digit IIN (accessible only when card_number_lenght == 16)
client.getCardInformation(
e.card_iin,
function(cardInfo) {
Expand All @@ -65,7 +67,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 = `
<h4 style="margin: 0 0 10px 0; color: #333;">Select Card Type:</h4>
${cardInfo.combo_card_types.map((type, index) => `
Expand All @@ -75,11 +77,11 @@ <h4 style="margin: 0 0 10px 0; color: #333;">Select Card Type:</h4>
</label>
`).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 => {
Expand All @@ -88,7 +90,7 @@ <h4 style="margin: 0 0 10px 0; color: #333;">Select Card Type:</h4>
console.log("User selected card type:", preferredCardType)
})
})

// Set initial value
preferredCardType = null
}
Expand All @@ -98,7 +100,7 @@ <h4 style="margin: 0 0 10px 0; color: #333;">Select Card Type:</h4>
}
)
}

document.getElementById("errors").innerHTML = ""
})

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "processout.js",
"version": "1.9.13",
"version": "1.9.14",
"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",
Expand Down
8 changes: 7 additions & 1 deletion src/dynamic-checkout/payment-methods/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,13 @@ module ProcessOut {
return
}

const isAllowedIin = restrictToIins.indexOf(iin) !== -1
// card_iin may carry 6 or 8 digits (8 when the merchant opted into
// exposeIIN8 and PCI rules allow), while configured entries 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)
}
Expand Down
57 changes: 57 additions & 0 deletions src/processout/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,63 @@ module ProcessOut {
return number.substring(0, l);
}

/**
* GetIIN8 returns the IIN of the card number, exposing up to 8 digits
* when PCI rules allow it (scheme in the allow-list and a 16-digit
* PAN) and 6 digits otherwise.
* @param {string} number
* @return {string}
*/
public static getIIN8(number: string): string {
Comment thread
lukasz-k-bieszczad-cko marked this conversation as resolved.
number = Card.parseNumber(number); // Remove potential spaces

if (number.length < 6)
return number;

if (Card.canExpose8DigitIIN(number))
return number.substring(0, 8);

return number.substring(0, 6);
}

/**
* Schemes permitted to surface an 8-digit IIN, mirroring the backend
* allow-list in api (controllers/card_inn.go). Every other scheme -
Comment thread
lukasz-k-bieszczad-cko marked this conversation as resolved.
* 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<string> = [
"visa", "mastercard", "discover", "jcb", "union-pay", "carte bancaire"
Comment thread
lukasz-k-bieszczad-cko marked this conversation as resolved.
];

/**
* canExpose8DigitIIN reports whether an 8-digit IIN may be surfaced
* for the given card number. Mirrors binder's TruncateNumber: the PAN
* must be exactly 16 digits and every detected scheme must be in the
* allow-list. Conservative on co-badged or ambiguous prefixes (and
* unknown schemes), which fall back to 6 digits.
* @param {string} number
* @return {boolean}
*/
public static canExpose8DigitIIN(number: string): boolean {
number = Card.parseNumber(number); // Remove potential spaces

// PCI: 8-digit BINs are only defined for 16-digit PANs.
if (number.length != 16)
return false;

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
Expand Down
Loading
Loading