import { AbstractControl } from "../abstract/abstract-control" ; import { ValidatorFn } from '../models/interface/validator-fn' ; import { RegexValidator } from "../util/regex-validator" ; import { ObjectMaker } from "../util/object-maker" ; import { CreditCardConfig } from "../models/config/credit-card-config" ; import { getConfigObject } from "../util/config-provider" ; import { AnnotationTypes } from "../core/validator.static" ; import { FormProvider } from '../util/form-provider' ; import { checkLength } from '../util/check-length' ; import { calculate } from '../algorithm/luhn-algorithm' ; export function creditCardValidator ( configModel ) { let cardDigits = { AmericanExpress : [ 15 ] , DinersClub : [ 14 , 16 , 19 ] , Discover : [ 16 , 19 ] , JCB : [ 16 , 19 ] , Maestro : [ 12 , 16 , 19 ] , MasterCard : [ 16 ] , Visa : [ 13 , 16 , 19 ] } ; function validate ( creditCardNumber ) { var digit = parseInt ( creditCardNumber . substring ( creditCardNumber . length - 1 , creditCardNumber . length ) ) ; return calculate ( creditCardNumber . substring ( 0 , creditCardNumber . length - 1 ) ) == parseInt ( String ( digit ) ) ? ! 0 : ! 1 ; } function getCardProviderName ( cardNumber ) { var cardProviderName = "" ; return /^(5018|5020|5038|5612|5893|6304|6759|6761|6762|6763|0604|6390)\d+$/ . test ( cardNumber ) ? cardProviderName = "Maestro" : /^5[1-5]/ . test ( cardNumber ) ? cardProviderName = "MasterCard" : /^4/ . test ( cardNumber ) ? cardProviderName = "Visa" : /^3[47]/ . test ( cardNumber ) ? cardProviderName = "AmericanExpress" : /^(?:2131|1800|35)/ . test ( cardNumber ) ? cardProviderName = "JCB" : /^3(?:0[0-5]|[68])/ . test ( cardNumber ) ? cardProviderName = "DinersClub" : /^6(?:011|5)/ . test ( cardNumber ) && ( cardProviderName = "Discover" ) , cardProviderName ; } return ( control ) : { [ key ] : any ; } | null => { const controlValue = control . value ; let config = getConfigObject ( configModel , control ) ; const parentObject = ( control . parent ) ? control . parent . value : undefined ; if ( FormProvider . ProcessRule ( control , config ) ) { if ( RegexValidator . isNotBlank ( controlValue ) ) { let isValid = false ; let cardTypes = config . fieldName && parentObject [ config . fieldName ] ? [ parentObject [ config . fieldName ] ] : config . creditCardTypes ; let cardType = '' ; for ( let creditCardType of cardTypes ) { isValid = checkLength ( controlValue . length , cardDigits [ creditCardType ] ) && getCardProviderName ( controlValue ) == creditCardType && validate ( controlValue ) ; cardType = creditCardType ; if ( isValid ) break ; } if ( ! isValid ) return ObjectMaker . toJson ( AnnotationTypes . creditCard , config , [ controlValue , cardType ] ) ; } } return ObjectMaker . null ( ) ; } ; }