From a8cd2b0ff7dc9460a76254a5928660634bed9d33 Mon Sep 17 00:00:00 2001 From: "aritro.ghosh" Date: Wed, 13 Nov 2024 19:28:02 +0530 Subject: [PATCH 1/4] refactor: card Validation update --- src/CardPattern.res | 12 ++++++------ src/CardUtils.res | 22 +++++++++++++++++----- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/CardPattern.res b/src/CardPattern.res index 08c3cb63e..bb1d2eb9d 100644 --- a/src/CardPattern.res +++ b/src/CardPattern.res @@ -19,7 +19,7 @@ let cardPatterns = [ { issuer: "Maestro", pattern: %re( - "/^(5018|5081|5044|504681|504993|5020|502260|5038|603845|603123|6304|6759|676[1-3]|6220|504834|504817|504645|504775|600206|627741)/" + "/^(5018|5081|5044|504681|504993|5020|502260|5038|5893|603845|603123|6304|6759|676[1-3]|6220|504834|504817|504645|504775|600206|627741)/" ), cvcLength: [3, 4], length: [12, 13, 14, 15, 16, 17, 18, 19], @@ -29,7 +29,7 @@ let cardPatterns = [ { issuer: "RuPay", pattern: %re( - "/^(508227|508[5-9]|603741|60698[5-9]|60699|607[0-8]|6079[0-7]|60798[0-4]|60800[1-9]|6080[1-9]|608[1-4]|608500|6521[5-9]|652[2-9]|6530|6531[0-4]|817290|817368|817378|353800)/" + "/^(508227|508[5-9]|603741|60698[5-9]|60699|607[0-8]|6079[0-7]|60798[0-4]|60800[1-9]|6080[1-9]|608[1-4]|608500|6521[5-9]|652[2-9]|6530|6531[0-4]|817290|817368|817378|353800|82)/" ), cvcLength: [3], length: [16], @@ -38,7 +38,7 @@ let cardPatterns = [ }, { issuer: "DinersClub", - pattern: %re("/^(36|38|30[0-5])/"), + pattern: %re("/^(36|38|39|30[0-5])/"), cvcLength: [3], maxCVCLenth: 3, length: [14, 15, 16, 17, 18, 19], @@ -46,15 +46,15 @@ let cardPatterns = [ }, { issuer: "Discover", - pattern: %re("/^(6011|65|64[4-9]|622)/"), + pattern: %re("/^(6011|64[4-9]|65|622126|622[1-9][0-9][0-9]|6229[0-1][0-9]|622925)/"), cvcLength: [3], - length: [16], + length: [16, 17, 18, 19], maxCVCLenth: 3, pincodeRequired: true, }, { issuer: "Mastercard", - pattern: %re("/^5[1-5]/"), + pattern: %re("/^(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[0-1][0-9]|2720|5[1-5])/"), cvcLength: [3], maxCVCLenth: 3, length: [16], diff --git a/src/CardUtils.res b/src/CardUtils.res index 3bb719c6f..8cae5a394 100644 --- a/src/CardUtils.res +++ b/src/CardUtils.res @@ -177,7 +177,14 @@ let formatCardNumber = (val, cardType) => { let formatedCard = switch cardType { | AMEX => `${clearValue->slice(0, 4)} ${clearValue->slice(4, 10)} ${clearValue->slice(10, 15)}` | DINERSCLUB => - `${clearValue->slice(0, 4)} ${clearValue->slice(4, 10)} ${clearValue->slice(10, 14)}` + if clearValue->String.length > 14 { + `${clearValue->slice(0, 4)} ${clearValue->slice(4, 8)} ${clearValue->slice( + 8, + 12, + )} ${clearValue->slice(12, 16)} ` + } else { + `${clearValue->slice(0, 4)} ${clearValue->slice(4, 10)} ${clearValue->slice(10, 14)}` + } | MASTERCARD | DISCOVER | SODEXO @@ -454,18 +461,23 @@ let generateFontsLink = (fonts: array) => { ->ignore } } + let maxCardLength = cardBrand => { let obj = getobjFromCardPattern(cardBrand) Array.reduce(obj.length, 0, (acc, val) => max(acc, val)) } +let isCardLengthValid = (cardBrand, cardNumberLength) => { + let obj = getobjFromCardPattern(cardBrand) + Array.includes(obj.length, cardNumberLength) +} + let cardValid = (cardNumber, cardBrand) => { let clearValueLength = cardNumber->clearSpaces->String.length if cardBrand == "" && (GlobalVars.isInteg || GlobalVars.isSandbox) { Utils.checkIsTestCardWildcard(cardNumber) } else { - (clearValueLength == maxCardLength(cardBrand) || - (cardBrand === "Visa" && clearValueLength == 16)) && calculateLuhn(cardNumber) + isCardLengthValid(cardBrand, clearValueLength) && calculateLuhn(cardNumber) } } let blurRef = (ref: React.ref>) => { @@ -566,10 +578,10 @@ let setCardValid = (cardnumber, setIsCardValid) => { if cardValid(cardnumber, cardBrand) { setIsCardValid(_ => Some(true)) } else if ( - !cardValid(cardnumber, cardBrand) && cardnumber->String.length == maxCardLength(cardBrand) + !cardValid(cardnumber, cardBrand) && isCardLengthValid(cardBrand, cardnumber->String.length) ) { setIsCardValid(_ => Some(false)) - } else if !(cardnumber->String.length == maxCardLength(cardBrand)) { + } else if !isCardLengthValid(cardBrand, cardnumber->String.length) { setIsCardValid(_ => None) } } From c1075db8cf48df8ee9de3c82010cadcec55c536d Mon Sep 17 00:00:00 2001 From: "aritro.ghosh" Date: Tue, 3 Dec 2024 17:08:57 +0530 Subject: [PATCH 2/4] fix: correction related to card pattern --- src/CardPattern.res | 6 +++--- src/CardUtils.res | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CardPattern.res b/src/CardPattern.res index bb1d2eb9d..24e094ffa 100644 --- a/src/CardPattern.res +++ b/src/CardPattern.res @@ -48,7 +48,7 @@ let cardPatterns = [ issuer: "Discover", pattern: %re("/^(6011|64[4-9]|65|622126|622[1-9][0-9][0-9]|6229[0-1][0-9]|622925)/"), cvcLength: [3], - length: [16, 17, 18, 19], + length: [16], maxCVCLenth: 3, pincodeRequired: true, }, @@ -72,7 +72,7 @@ let cardPatterns = [ issuer: "Visa", pattern: %re("/^4/"), cvcLength: [3], - length: [13, 14, 15, 16, 19], + length: [16, 19], maxCVCLenth: 3, pincodeRequired: true, }, @@ -94,7 +94,7 @@ let cardPatterns = [ }, { issuer: "JCB", - pattern: %re("/^35/"), + pattern: %re("/^35(2[89]|[3-8][0-9])/"), cvcLength: [3], maxCVCLenth: 3, length: [16], diff --git a/src/CardUtils.res b/src/CardUtils.res index 8cae5a394..0e6f459c6 100644 --- a/src/CardUtils.res +++ b/src/CardUtils.res @@ -181,7 +181,7 @@ let formatCardNumber = (val, cardType) => { `${clearValue->slice(0, 4)} ${clearValue->slice(4, 8)} ${clearValue->slice( 8, 12, - )} ${clearValue->slice(12, 16)} ` + )} ${clearValue->slice(12, 16)} ${clearValue->slice(16, 19)}` } else { `${clearValue->slice(0, 4)} ${clearValue->slice(4, 10)} ${clearValue->slice(10, 14)}` } @@ -387,7 +387,7 @@ let getExpiryValidity = cardExpiry => { let valid = if currentYear == year->toInt && month->toInt >= currentMonth && month->toInt <= 12 { true } else if ( - year->toInt > currentYear && year->toInt < 2075 && month->toInt >= 1 && month->toInt <= 12 + year->toInt > currentYear && year->toInt < 2099 && month->toInt >= 1 && month->toInt <= 12 ) { true } else { From e3431d6648fc06f38b721d716fde44e1c95b9137 Mon Sep 17 00:00:00 2001 From: "aritro.ghosh" Date: Wed, 4 Dec 2024 15:39:55 +0530 Subject: [PATCH 3/4] fix: card validation correction --- src/CardPattern.res | 2 +- src/CardUtils.res | 26 ++++++++++++++++---------- src/Payment.res | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/CardPattern.res b/src/CardPattern.res index 24e094ffa..1706eeb06 100644 --- a/src/CardPattern.res +++ b/src/CardPattern.res @@ -72,7 +72,7 @@ let cardPatterns = [ issuer: "Visa", pattern: %re("/^4/"), cvcLength: [3], - length: [16, 19], + length: [13, 14, 15, 16, 19], maxCVCLenth: 3, pincodeRequired: true, }, diff --git a/src/CardUtils.res b/src/CardUtils.res index 0e6f459c6..8a93c3495 100644 --- a/src/CardUtils.res +++ b/src/CardUtils.res @@ -176,15 +176,7 @@ let formatCardNumber = (val, cardType) => { let clearValue = val->clearSpaces let formatedCard = switch cardType { | AMEX => `${clearValue->slice(0, 4)} ${clearValue->slice(4, 10)} ${clearValue->slice(10, 15)}` - | DINERSCLUB => - if clearValue->String.length > 14 { - `${clearValue->slice(0, 4)} ${clearValue->slice(4, 8)} ${clearValue->slice( - 8, - 12, - )} ${clearValue->slice(12, 16)} ${clearValue->slice(16, 19)}` - } else { - `${clearValue->slice(0, 4)} ${clearValue->slice(4, 10)} ${clearValue->slice(10, 14)}` - } + | DINERSCLUB | MASTERCARD | DISCOVER | SODEXO @@ -387,7 +379,10 @@ let getExpiryValidity = cardExpiry => { let valid = if currentYear == year->toInt && month->toInt >= currentMonth && month->toInt <= 12 { true } else if ( - year->toInt > currentYear && year->toInt < 2099 && month->toInt >= 1 && month->toInt <= 12 + year->toInt > currentYear && + year->toInt < Date.getFullYear(Js.Date.fromFloat(Date.now())) + 100 && + month->toInt >= 1 && + month->toInt <= 12 ) { true } else { @@ -480,6 +475,17 @@ let cardValid = (cardNumber, cardBrand) => { isCardLengthValid(cardBrand, clearValueLength) && calculateLuhn(cardNumber) } } + +let focusCardValid = (cardNumber, cardBrand) => { + let clearValueLength = cardNumber->clearSpaces->String.length + if cardBrand == "" && (GlobalVars.isInteg || GlobalVars.isSandbox) { + Utils.checkIsTestCardWildcard(cardNumber) + } else { + (clearValueLength == maxCardLength(cardBrand) || + (cardBrand === "Visa" && clearValueLength == 16)) && calculateLuhn(cardNumber) + } +} + let blurRef = (ref: React.ref>) => { ref.current->Nullable.toOption->Option.forEach(input => input->blur)->ignore } diff --git a/src/Payment.res b/src/Payment.res index 19028b56f..253b89391 100644 --- a/src/Payment.res +++ b/src/Payment.res @@ -88,7 +88,7 @@ let make = (~paymentMode, ~integrateError, ~logger) => { let clearValue = card->clearSpaces setCardValid(clearValue, setIsCardValid) if ( - cardValid(clearValue, cardBrand) && + focusCardValid(clearValue, cardBrand) && (PaymentUtils.checkIsCardSupported(clearValue, supportedCardBrands)->Option.getOr(false) || Utils.checkIsTestCardWildcard(clearValue)) ) { From 6e6dba973e608c428adaaf138f446d1f55728662 Mon Sep 17 00:00:00 2001 From: "aritro.ghosh" Date: Mon, 9 Dec 2024 18:05:29 +0530 Subject: [PATCH 4/4] fix: card validation focus check --- src/CardUtils.res | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/CardUtils.res b/src/CardUtils.res index 8a93c3495..9d0b9beb3 100644 --- a/src/CardUtils.res +++ b/src/CardUtils.res @@ -581,13 +581,12 @@ let swapCardOption = (cardOpts: array, dropOpts: array, selected let setCardValid = (cardnumber, setIsCardValid) => { let cardBrand = getCardBrand(cardnumber) + let isCardMaxLength = cardnumber->String.length == maxCardLength(cardBrand) if cardValid(cardnumber, cardBrand) { setIsCardValid(_ => Some(true)) - } else if ( - !cardValid(cardnumber, cardBrand) && isCardLengthValid(cardBrand, cardnumber->String.length) - ) { + } else if !cardValid(cardnumber, cardBrand) && isCardMaxLength { setIsCardValid(_ => Some(false)) - } else if !isCardLengthValid(cardBrand, cardnumber->String.length) { + } else if !isCardMaxLength { setIsCardValid(_ => None) } }