-
Star
(103)
You must be signed in to star a gist -
Fork
(18)
You must be signed in to fork a gist
-
-
Save gusribeiro/263a165db774f5d78251 to your computer and use it in GitHub Desktop.
Amex: ^3[47][0-9]{13}$ | |
Aura: /^((?!504175))^((?!5067))(^50[0-9])/ | |
Banese Card: '^636117' | |
Cabal: '(60420[1-9]|6042[1-9][0-9]|6043[0-9]{2}|604400)' | |
Diners: '(36[0-8][0-9]{3}|369[0-8][0-9]{2}|3699[0-8][0-9]|36999[0-9]) | |
Discover: /^6(?:011|5[0-9]{2})[0-9]{12}/ | |
Elo: /^4011(78|79)|^43(1274|8935)|^45(1416|7393|763(1|2))|^50(4175|6699|67[0-6][0-9]|677[0-8]|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9])|^627780|^63(6297|6368|6369)|^65(0(0(3([1-3]|[5-9])|4([0-9])|5[0-1])|4(0[5-9]|[1-3][0-9]|8[5-9]|9[0-9])|5([0-2][0-9]|3[0-8]|4[1-9]|[5-8][0-9]|9[0-8])|7(0[0-9]|1[0-8]|2[0-7])|9(0[1-9]|[1-6][0-9]|7[0-8]))|16(5[2-9]|[6-7][0-9])|50(0[0-9]|1[0-9]|2[1-9]|[3-4][0-9]|5[0-8]))/ | |
Fort Brasil: '^628167' | |
GrandCard: '^605032' | |
Hipercard: ^606282|^3841(?:[0|4|6]{1})0 | |
JCB: /^(?:2131|1800|35\d{3})\d{11}/ | |
Mastercard: ^((5(([1-2]|[4-5])[0-9]{8}|0((1|6)([0-9]{7}))|3(0(4((0|[2-9])[0-9]{5})|([0-3]|[5-9])[0-9]{6})|[1-9][0-9]{7})))|((508116)\\d{4,10})|((502121)\\d{4,10})|((589916)\\d{4,10})|(2[0-9]{15})|(67[0-9]{14})|(506387)\\d{4,10}) | |
Personal Card: '^636085' | |
Sorocred: '^627892|^636414' | |
Valecard: '^606444|^606458|^606482' | |
Visa: ^4[0-9]{15}$ |
Comlementando, os cartões que deram errado passam na REGEX da bandeira esperada, mas também passam na da Discover/Aura. Eu comentei essas duas bandeiras e a maioria passou, só o 5031433215406351 que não está passando na REGEX do mastercard
Implementei essa função em typescript e testei os cartões que o @MMortari mandou, alguns falharam:
export function getCardBrandName (cardNumber: string): string | null { const numbers = cardNumber.replace(/[^0-9]+/g, '') const cards = { amex: /^3[47][0-9]{13}$/, aura: /^((?!504175))^((?!5067))(^50[0-9])/, banese_card: /^636117/, cabal: /(60420[1-9]|6042[1-9][0-9]|6043[0-9]{2}|604400)/, diners: /(36[0-8][0-9]{3}|369[0-8][0-9]{2}|3699[0-8][0-9]|36999[0-9])/, discover: /^6(?:011|5[0-9]{2})[0-9]{12}/, elo: /^4011(78|79)|^43(1274|8935)|^45(1416|7393|763(1|2))|^50(4175|6699|67[0-6][0-9]|677[0-8]|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9])|^627780|^63(6297|6368|6369)|^65(0(0(3([1-3]|[5-9])|4([0-9])|5[0-1])|4(0[5-9]|[1-3][0-9]|8[5-9]|9[0-9])|5([0-2][0-9]|3[0-8]|4[1-9]|[5-8][0-9]|9[0-8])|7(0[0-9]|1[0-8]|2[0-7])|9(0[1-9]|[1-6][0-9]|7[0-8]))|16(5[2-9]|[6-7][0-9])|50(0[0-9]|1[0-9]|2[1-9]|[3-4][0-9]|5[0-8]))/, fort_brasil: /^628167/, grand_card: /^605032/, hipercard: /^606282|^3841(?:[0|4|6]{1})0/, jbc: /^(?:2131|1800|35\d{3})\d{11}/, mastercard: /^((5(([1-2]|[4-5])[0-9]{8}|0((1|6)([0-9]{7}))|3(0(4((0|[2-9])[0-9]{5})|([0-3]|[5-9])[0-9]{6})|[1-9][0-9]{7})))|((508116)\\d{4,10})|((502121)\\d{4,10})|((589916)\\d{4,10})|(2[0-9]{15})|(67[0-9]{14})|(506387)\\d{4,10})/, personal_card: /^636085/, sorocred: /^627892|^636414/, valecard: /^606444|^606458|^606482/, visa: /^4[0-9]{15}$/ } const match = Object.entries(cards).find(([_, value]) => { if (value.test(numbers)) { return true } return false }) if (match) { return match[0] } return null }6505050000001000: Esperado: Elo. Resultado: Discover 6505050000001091: Esperado: Elo. Resultado: Discover 6505050000001018: Esperado: Elo. Resultado: Discover 6505050000001109: Esperado: Elo. Resultado: Discover 5031433215406351: Esperado: Mastercard. Resultado: Aura 5098176533461570: Esperado: Elo. Resultado: Aura 5098193894226609: Esperado: Elo. Resultado: Aura 5091084515027541: Esperado: Elo. Resultado: Aura 5098177024386094: Esperado: Elo. Resultado: Aura
Interessante esse comportamento, vou fazer alguns testes aqui e quem sabe com um negative lookahead ele funcione corretamente, posteriormente comentarei com um retorno ...
Comlementando, os cartões que deram errado passam na REGEX da bandeira esperada, mas também passam na da Discover/Aura. Eu comentei essas duas bandeiras e a maioria passou, só o 5031433215406351 que não está passando na REGEX do mastercard
Isso acontece porque o padrão desses cartões ELO realmente batem com o padrão da discover, porém por algum motivo a caixa registrou o BIN antes (não sei como funciona esses registros de BIN). Essas exceções já estão no regex da elo, podemos ver na parte "|6505[0-2][0-9]". Se jogarmos no bincheck.io inicialmente ele também da discover, mas se fizer o POST pra verificar ele irá retornar elo.
pra resolver podemos criar um switch e dar break antes para não continuar a verificação, e sempre verificar o ELO primeiro. Um exemplo em PHP
$bandeira = match (1) {
preg_match(
'/^4011(78|79)|^43(1274|8935)|^45(1416|7393|763(1|2))|^504175|^627780|^63(6297|6368|6369)|(65003[5-9]|65004[0-9]|65005[01])|(65040[5-9]|6504[1-3][0-9])|(65048[5-9]|65049[0-9]|6505[0-2][0-9]|65053[0-8])|(65054[1-9]|6505[5-8][0-9]|65059[0-8])|(65070[0-9]|65071[0-8])|(65072[0-7])|(65090[1-9]|6509[1-6][0-9]|65097[0-8])|(65165[2-9]|6516[67][0-9])|(65500[0-9]|65501[0-9])|(65502[1-9]|6550[34][0-9]|65505[0-8])|^(506699|5067[0-6][0-9]|50677[0-8])|^(509[0-8][0-9]{2}|5099[0-8][0-9]|50999[0-9])|^65003[1-3]|^(65003[5-9]|65004\d|65005[0-1])|^(65040[5-9]|6504[1-3]\d)|^(65048[5-9]|65049\d|6505[0-2]\d|65053[0-8])|^(65054[1-9]|6505[5-8]\d|65059[0-8])|^(65070\d|65071[0-8])|^65072[0-7]|^(65090[1-9]|65091\d|650920)|^(65165[2-9]|6516[6-7]\d)|^(65500\d|65501\d)|^(65502[1-9]|6550[3-4]\d|65505[0-8])/',
$cartaoNumero
) => 'elo',
preg_match('/^4[0-9]{12}(?:[0-9]{3})?/', $cartaoNumero) => 'visa',
preg_match('/^((5(([1-2]|[4-5])[0-9]{8}|0((1|6)([0-9]{7}))|3(0(4((0|[2-9])[0-9]{5})|([0-3]|[5-9])[0-9]{6})|[1-9][0-9]{7})))|((508116)\\d{4,10})|((502121)\\d{4,10})|((589916)\\d{4,10})|(2[0-9]{15})|(67[0-9]{14})|(506387)\\d{4,10})/', $cartaoNumero) => 'mastercard',
preg_match('/^3[47][0-9]{13}/', $cartaoNumero) => 'amexs',
preg_match('/^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})/', $cartaoNumero) => 'discover',
preg_match('/^3(?:0[0-5]|[68][0-9])[0-9]{11}/', $cartaoNumero) => 'diners',
preg_match('/^(?:2131|1800|35\d{3})\d{11}/', $cartaoNumero) => 'jcb',
preg_match('/^(606282\d{10}(\d{3})?)|(3841\d{12})|(637\d{13})/', $cartaoNumero) => 'hipercard',
default => ''
};
Agora todos os números vão bater corretamente!
Esta bandeira 5031433215406351 no bincheck.io deu que não existe, então pode ser retirada.
Eu pequei os cartões dessa resposta do @MMortari :
Boa tarde pessoal,
Minha pequena contribuição, segue uma lista com alguns cartões que estou colecionando de alguns provedores para teste.
const cards = { // PagSeguro // https://dev.pagbank.uol.com.br/reference/cartoes-de-teste '4539620659922097': EnumCardBrand.VISA, '4929291898380766': EnumCardBrand.VISA, '5240082975622454': EnumCardBrand.MASTERCARD, '5530062640663264': EnumCardBrand.MASTERCARD, '345817690311361': EnumCardBrand.AMEX, '372938001199778': EnumCardBrand.AMEX, '4514161122113757': EnumCardBrand.ELO, '4389350446134811': EnumCardBrand.ELO, '6062828598919021': EnumCardBrand.HIPERCARD, '6062822916014409': EnumCardBrand.HIPERCARD, // https://dev.pagbank.uol.com.br/reference/criar-pagar-pedido-com-3ds-validacao-pagbank '4000000000002701': EnumCardBrand.VISA, '5200000000001005': EnumCardBrand.MASTERCARD, '6505050000001000': EnumCardBrand.ELO, '4000000000002503': EnumCardBrand.VISA, '5200000000001096': EnumCardBrand.MASTERCARD, '6505050000001091': EnumCardBrand.ELO, '4000000000002925': EnumCardBrand.VISA, '5200000000001013': EnumCardBrand.MASTERCARD, '6505050000001018': EnumCardBrand.ELO, '4000000000002370': EnumCardBrand.VISA, '5200000000001104': EnumCardBrand.MASTERCARD, '6505050000001109': EnumCardBrand.ELO, // Mercado pago // https://www.mercadopago.com.br/developers/pt/docs/checkout-api/additional-content/your-integrations/test/cards '5067766783888311': EnumCardBrand.ELO, '5031433215406351': EnumCardBrand.MASTERCARD, '4235647728025682': EnumCardBrand.VISA, '375365153556885': EnumCardBrand.AMEX, // Gerados // https://www.vccgenerator.org/ '5098176533461570': EnumCardBrand.ELO, '5067349319312260': EnumCardBrand.ELO, '5098193894226609': EnumCardBrand.ELO, '5091084515027541': EnumCardBrand.ELO, '5098177024386094': EnumCardBrand.ELO, '4391395999142147': EnumCardBrand.VISA, '4103922157715577': EnumCardBrand.VISA, '4380208328771358': EnumCardBrand.VISA, '4297672575052840': EnumCardBrand.VISA, '4380277454970936': EnumCardBrand.VISA, '5551555128049017': EnumCardBrand.MASTERCARD, '5268003770982262': EnumCardBrand.MASTERCARD, '5448382804657501': EnumCardBrand.MASTERCARD, '5582852950163914': EnumCardBrand.MASTERCARD, '5448384161742298': EnumCardBrand.MASTERCARD, '340205640990176': EnumCardBrand.AMEX, '340205958483061': EnumCardBrand.AMEX, '340205254489929': EnumCardBrand.AMEX, '340205493225258': EnumCardBrand.AMEX, '340205571301401': EnumCardBrand.AMEX, };
E usei os regex da última resposta, conforme o @gfucci colocou em sua resposta:
Comlementando, os cartões que deram errado passam na REGEX da bandeira esperada, mas também passam na da Discover/Aura. Eu comentei essas duas bandeiras e a maioria passou, só o 5031433215406351 que não está passando na REGEX do mastercard
Isso acontece porque o padrão desses cartões ELO realmente batem com o padrão da discover, porém por algum motivo a caixa registrou o BIN antes (não sei como funciona esses registros de BIN). Essas exceções já estão no regex da elo, podemos ver na parte "|6505[0-2][0-9]". Se jogarmos no bincheck.io inicialmente ele também da discover, mas se fizer o POST pra verificar ele irá retornar elo.
pra resolver podemos criar um switch e dar break antes para não continuar a verificação, e sempre verificar o ELO primeiro. Um exemplo em PHP
$bandeira = match (1) { preg_match( '/^4011(78|79)|^43(1274|8935)|^45(1416|7393|763(1|2))|^504175|^627780|^63(6297|6368|6369)|(65003[5-9]|65004[0-9]|65005[01])|(65040[5-9]|6504[1-3][0-9])|(65048[5-9]|65049[0-9]|6505[0-2][0-9]|65053[0-8])|(65054[1-9]|6505[5-8][0-9]|65059[0-8])|(65070[0-9]|65071[0-8])|(65072[0-7])|(65090[1-9]|6509[1-6][0-9]|65097[0-8])|(65165[2-9]|6516[67][0-9])|(65500[0-9]|65501[0-9])|(65502[1-9]|6550[34][0-9]|65505[0-8])|^(506699|5067[0-6][0-9]|50677[0-8])|^(509[0-8][0-9]{2}|5099[0-8][0-9]|50999[0-9])|^65003[1-3]|^(65003[5-9]|65004\d|65005[0-1])|^(65040[5-9]|6504[1-3]\d)|^(65048[5-9]|65049\d|6505[0-2]\d|65053[0-8])|^(65054[1-9]|6505[5-8]\d|65059[0-8])|^(65070\d|65071[0-8])|^65072[0-7]|^(65090[1-9]|65091\d|650920)|^(65165[2-9]|6516[6-7]\d)|^(65500\d|65501\d)|^(65502[1-9]|6550[3-4]\d|65505[0-8])/', $cartaoNumero ) => 'elo', preg_match('/^4[0-9]{12}(?:[0-9]{3})?/', $cartaoNumero) => 'visa', preg_match('/^((5(([1-2]|[4-5])[0-9]{8}|0((1|6)([0-9]{7}))|3(0(4((0|[2-9])[0-9]{5})|([0-3]|[5-9])[0-9]{6})|[1-9][0-9]{7})))|((508116)\\d{4,10})|((502121)\\d{4,10})|((589916)\\d{4,10})|(2[0-9]{15})|(67[0-9]{14})|(506387)\\d{4,10})/', $cartaoNumero) => 'mastercard', preg_match('/^3[47][0-9]{13}/', $cartaoNumero) => 'amexs', preg_match('/^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})/', $cartaoNumero) => 'discover', preg_match('/^3(?:0[0-5]|[68][0-9])[0-9]{11}/', $cartaoNumero) => 'diners', preg_match('/^(?:2131|1800|35\d{3})\d{11}/', $cartaoNumero) => 'jcb', preg_match('/^(606282\d{10}(\d{3})?)|(3841\d{12})|(637\d{13})/', $cartaoNumero) => 'hipercard', default => '' };
Agora todos os números vão bater corretamente!
Esta bandeira 5031433215406351 no bincheck.io deu que não existe, então pode ser retirada.
Aparentemente está falhando para alguns ainda... Olha o resultado que eu tive:
Comlementando, os cartões que deram errado passam na REGEX da bandeira esperada, mas também passam na da Discover/Aura. Eu comentei essas duas bandeiras e a maioria passou, só o 5031433215406351 que não está passando na REGEX do mastercard
Isso acontece porque o padrão desses cartões ELO realmente batem com o padrão da discover, porém por algum motivo a caixa registrou o BIN antes (não sei como funciona esses registros de BIN). Essas exceções já estão no regex da elo, podemos ver na parte "|6505[0-2][0-9]". Se jogarmos no bincheck.io inicialmente ele também da discover, mas se fizer o POST pra verificar ele irá retornar elo.
pra resolver podemos criar um switch e dar break antes para não continuar a verificação, e sempre verificar o ELO primeiro. Um exemplo em PHP
$bandeira = match (1) { preg_match( '/^4011(78|79)|^43(1274|8935)|^45(1416|7393|763(1|2))|^504175|^627780|^63(6297|6368|6369)|(65003[5-9]|65004[0-9]|65005[01])|(65040[5-9]|6504[1-3][0-9])|(65048[5-9]|65049[0-9]|6505[0-2][0-9]|65053[0-8])|(65054[1-9]|6505[5-8][0-9]|65059[0-8])|(65070[0-9]|65071[0-8])|(65072[0-7])|(65090[1-9]|6509[1-6][0-9]|65097[0-8])|(65165[2-9]|6516[67][0-9])|(65500[0-9]|65501[0-9])|(65502[1-9]|6550[34][0-9]|65505[0-8])|^(506699|5067[0-6][0-9]|50677[0-8])|^(509[0-8][0-9]{2}|5099[0-8][0-9]|50999[0-9])|^65003[1-3]|^(65003[5-9]|65004\d|65005[0-1])|^(65040[5-9]|6504[1-3]\d)|^(65048[5-9]|65049\d|6505[0-2]\d|65053[0-8])|^(65054[1-9]|6505[5-8]\d|65059[0-8])|^(65070\d|65071[0-8])|^65072[0-7]|^(65090[1-9]|65091\d|650920)|^(65165[2-9]|6516[6-7]\d)|^(65500\d|65501\d)|^(65502[1-9]|6550[3-4]\d|65505[0-8])/', $cartaoNumero ) => 'elo', preg_match('/^4[0-9]{12}(?:[0-9]{3})?/', $cartaoNumero) => 'visa', preg_match('/^((5(([1-2]|[4-5])[0-9]{8}|0((1|6)([0-9]{7}))|3(0(4((0|[2-9])[0-9]{5})|([0-3]|[5-9])[0-9]{6})|[1-9][0-9]{7})))|((508116)\\d{4,10})|((502121)\\d{4,10})|((589916)\\d{4,10})|(2[0-9]{15})|(67[0-9]{14})|(506387)\\d{4,10})/', $cartaoNumero) => 'mastercard', preg_match('/^3[47][0-9]{13}/', $cartaoNumero) => 'amexs', preg_match('/^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})/', $cartaoNumero) => 'discover', preg_match('/^3(?:0[0-5]|[68][0-9])[0-9]{11}/', $cartaoNumero) => 'diners', preg_match('/^(?:2131|1800|35\d{3})\d{11}/', $cartaoNumero) => 'jcb', preg_match('/^(606282\d{10}(\d{3})?)|(3841\d{12})|(637\d{13})/', $cartaoNumero) => 'hipercard', default => '' };
Agora todos os números vão bater corretamente!
Esta bandeira 5031433215406351 no bincheck.io deu que não existe, então pode ser retirada.
Opa, consegui fazer funcionar. Só joguei a linha do elo para ser a primeira regex para checar e funcionou em todos (após remover o 5031433215406351)
Segue o código completo:
export function getCardBrandName (cardNumber: string): string | null {
const numbers = cardNumber.replace(/[^0-9]+/g, '')
const brands = {
elo: /^4011(78|79)|^43(1274|8935)|^45(1416|7393|763(1|2))|^50(4175|6699|67[0-6][0-9]|677[0-8]|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9])|^627780|^63(6297|6368|6369)|^65(0(0(3([1-3]|[5-9])|4([0-9])|5[0-1])|4(0[5-9]|[1-3][0-9]|8[5-9]|9[0-9])|5([0-2][0-9]|3[0-8]|4[1-9]|[5-8][0-9]|9[0-8])|7(0[0-9]|1[0-8]|2[0-7])|9(0[1-9]|[1-6][0-9]|7[0-8]))|16(5[2-9]|[6-7][0-9])|50(0[0-9]|1[0-9]|2[1-9]|[3-4][0-9]|5[0-8]))/,
amex: /^3[47][0-9]{13}$/,
aura: /^((?!504175))^((?!5067))(^50[0-9])/,
banese_card: /^636117/,
cabal: /(60420[1-9]|6042[1-9][0-9]|6043[0-9]{2}|604400)/,
diners: /(36[0-8][0-9]{3}|369[0-8][0-9]{2}|3699[0-8][0-9]|36999[0-9])/,
discover: /^6(?:011|5[0-9]{2})[0-9]{12}/,
fort_brasil: /^628167/,
grand_card: /^605032/,
hipercard: /^606282|^3841(?:[0|4|6]{1})0/,
jbc: /^(?:2131|1800|35\d{3})\d{11}/,
mastercard: /^((5(([1-2]|[4-5])[0-9]{8}|0((1|6)([0-9]{7}))|3(0(4((0|[2-9])[0-9]{5})|([0-3]|[5-9])[0-9]{6})|[1-9][0-9]{7})))|((508116)\\d{4,10})|((502121)\\d{4,10})|((589916)\\d{4,10})|(2[0-9]{15})|(67[0-9]{14})|(506387)\\d{4,10})/,
personal_card: /^636085/,
sorocred: /^627892|^636414/,
valecard: /^606444|^606458|^606482/,
visa: /^4[0-9]{15}$/
}
const match = Object.entries(brands).find(([_, value]) => {
if (value.test(numbers)) {
return true
}
return false
})
if (match) {
return match[0]
}
return null
}
const cards = {
// PagSeguro
// https://dev.pagbank.uol.com.br/reference/cartoes-de-teste
'4539620659922097': 'visa',
'4929291898380766': 'visa',
'5240082975622454': 'mastercard',
'5530062640663264': 'mastercard',
'345817690311361': 'amex',
'372938001199778': 'amex',
'4514161122113757': 'elo',
'4389350446134811': 'elo',
'6062828598919021': 'hipercard',
'6062822916014409': 'hipercard',
// https://dev.pagbank.uol.com.br/reference/criar-pagar-pedido-com-3ds-validacao-pagbank
'4000000000002701': 'visa',
'5200000000001005': 'mastercard',
'6505050000001000': 'elo',
'4000000000002503': 'visa',
'5200000000001096': 'mastercard',
'6505050000001091': 'elo',
'4000000000002925': 'visa',
'5200000000001013': 'mastercard',
'6505050000001018': 'elo',
'4000000000002370': 'visa',
'5200000000001104': 'mastercard',
'6505050000001109': 'elo',
// Mercado pago
// https://www.mercadopago.com.br/developers/pt/docs/checkout-api/additional-content/your-integrations/test/cards
'5067766783888311': 'elo',
'4235647728025682': 'visa',
'375365153556885': 'amex',
// Gerados
// https://www.vccgenerator.org/
'5098176533461570': 'elo',
'5067349319312260': 'elo',
'5098193894226609': 'elo',
'5091084515027541': 'elo',
'5098177024386094': 'elo',
'4391395999142147': 'visa',
'4103922157715577': 'visa',
'4380208328771358': 'visa',
'4297672575052840': 'visa',
'4380277454970936': 'visa',
'5551555128049017': 'mastercard',
'5268003770982262': 'mastercard',
'5448382804657501': 'mastercard',
'5582852950163914': 'mastercard',
'5448384161742298': 'mastercard',
'340205640990176': 'amex',
'340205958483061': 'amex',
'340205254489929': 'amex',
'340205493225258': 'amex',
'340205571301401': 'amex',
};
for (const card in cards) {
const expectedBrand = cards[card]
const calculatedBrand = getCardBrandName(card)
if (expectedBrand == calculatedBrand) {
console.log(`${card} OK`)
} else {
console.log(`${card} ERROR. Expected ${expectedBrand}, got ${calculatedBrand}`)
}
}
Eu pequei os cartões dessa resposta do @MMortari :
Boa tarde pessoal,
Minha pequena contribuição, segue uma lista com alguns cartões que estou colecionando de alguns provedores para teste.const cards = { // PagSeguro // https://dev.pagbank.uol.com.br/reference/cartoes-de-teste '4539620659922097': EnumCardBrand.VISA, '4929291898380766': EnumCardBrand.VISA, '5240082975622454': EnumCardBrand.MASTERCARD, '5530062640663264': EnumCardBrand.MASTERCARD, '345817690311361': EnumCardBrand.AMEX, '372938001199778': EnumCardBrand.AMEX, '4514161122113757': EnumCardBrand.ELO, '4389350446134811': EnumCardBrand.ELO, '6062828598919021': EnumCardBrand.HIPERCARD, '6062822916014409': EnumCardBrand.HIPERCARD, // https://dev.pagbank.uol.com.br/reference/criar-pagar-pedido-com-3ds-validacao-pagbank '4000000000002701': EnumCardBrand.VISA, '5200000000001005': EnumCardBrand.MASTERCARD, '6505050000001000': EnumCardBrand.ELO, '4000000000002503': EnumCardBrand.VISA, '5200000000001096': EnumCardBrand.MASTERCARD, '6505050000001091': EnumCardBrand.ELO, '4000000000002925': EnumCardBrand.VISA, '5200000000001013': EnumCardBrand.MASTERCARD, '6505050000001018': EnumCardBrand.ELO, '4000000000002370': EnumCardBrand.VISA, '5200000000001104': EnumCardBrand.MASTERCARD, '6505050000001109': EnumCardBrand.ELO, // Mercado pago // https://www.mercadopago.com.br/developers/pt/docs/checkout-api/additional-content/your-integrations/test/cards '5067766783888311': EnumCardBrand.ELO, '5031433215406351': EnumCardBrand.MASTERCARD, '4235647728025682': EnumCardBrand.VISA, '375365153556885': EnumCardBrand.AMEX, // Gerados // https://www.vccgenerator.org/ '5098176533461570': EnumCardBrand.ELO, '5067349319312260': EnumCardBrand.ELO, '5098193894226609': EnumCardBrand.ELO, '5091084515027541': EnumCardBrand.ELO, '5098177024386094': EnumCardBrand.ELO, '4391395999142147': EnumCardBrand.VISA, '4103922157715577': EnumCardBrand.VISA, '4380208328771358': EnumCardBrand.VISA, '4297672575052840': EnumCardBrand.VISA, '4380277454970936': EnumCardBrand.VISA, '5551555128049017': EnumCardBrand.MASTERCARD, '5268003770982262': EnumCardBrand.MASTERCARD, '5448382804657501': EnumCardBrand.MASTERCARD, '5582852950163914': EnumCardBrand.MASTERCARD, '5448384161742298': EnumCardBrand.MASTERCARD, '340205640990176': EnumCardBrand.AMEX, '340205958483061': EnumCardBrand.AMEX, '340205254489929': EnumCardBrand.AMEX, '340205493225258': EnumCardBrand.AMEX, '340205571301401': EnumCardBrand.AMEX, };E usei os regex da última resposta, conforme o @gfucci colocou em sua resposta:
Comlementando, os cartões que deram errado passam na REGEX da bandeira esperada, mas também passam na da Discover/Aura. Eu comentei essas duas bandeiras e a maioria passou, só o 5031433215406351 que não está passando na REGEX do mastercard
Isso acontece porque o padrão desses cartões ELO realmente batem com o padrão da discover, porém por algum motivo a caixa registrou o BIN antes (não sei como funciona esses registros de BIN). Essas exceções já estão no regex da elo, podemos ver na parte "|6505[0-2][0-9]". Se jogarmos no bincheck.io inicialmente ele também da discover, mas se fizer o POST pra verificar ele irá retornar elo.
pra resolver podemos criar um switch e dar break antes para não continuar a verificação, e sempre verificar o ELO primeiro. Um exemplo em PHP$bandeira = match (1) { preg_match( '/^4011(78|79)|^43(1274|8935)|^45(1416|7393|763(1|2))|^504175|^627780|^63(6297|6368|6369)|(65003[5-9]|65004[0-9]|65005[01])|(65040[5-9]|6504[1-3][0-9])|(65048[5-9]|65049[0-9]|6505[0-2][0-9]|65053[0-8])|(65054[1-9]|6505[5-8][0-9]|65059[0-8])|(65070[0-9]|65071[0-8])|(65072[0-7])|(65090[1-9]|6509[1-6][0-9]|65097[0-8])|(65165[2-9]|6516[67][0-9])|(65500[0-9]|65501[0-9])|(65502[1-9]|6550[34][0-9]|65505[0-8])|^(506699|5067[0-6][0-9]|50677[0-8])|^(509[0-8][0-9]{2}|5099[0-8][0-9]|50999[0-9])|^65003[1-3]|^(65003[5-9]|65004\d|65005[0-1])|^(65040[5-9]|6504[1-3]\d)|^(65048[5-9]|65049\d|6505[0-2]\d|65053[0-8])|^(65054[1-9]|6505[5-8]\d|65059[0-8])|^(65070\d|65071[0-8])|^65072[0-7]|^(65090[1-9]|65091\d|650920)|^(65165[2-9]|6516[6-7]\d)|^(65500\d|65501\d)|^(65502[1-9]|6550[3-4]\d|65505[0-8])/', $cartaoNumero ) => 'elo', preg_match('/^4[0-9]{12}(?:[0-9]{3})?/', $cartaoNumero) => 'visa', preg_match('/^((5(([1-2]|[4-5])[0-9]{8}|0((1|6)([0-9]{7}))|3(0(4((0|[2-9])[0-9]{5})|([0-3]|[5-9])[0-9]{6})|[1-9][0-9]{7})))|((508116)\\d{4,10})|((502121)\\d{4,10})|((589916)\\d{4,10})|(2[0-9]{15})|(67[0-9]{14})|(506387)\\d{4,10})/', $cartaoNumero) => 'mastercard', preg_match('/^3[47][0-9]{13}/', $cartaoNumero) => 'amexs', preg_match('/^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})/', $cartaoNumero) => 'discover', preg_match('/^3(?:0[0-5]|[68][0-9])[0-9]{11}/', $cartaoNumero) => 'diners', preg_match('/^(?:2131|1800|35\d{3})\d{11}/', $cartaoNumero) => 'jcb', preg_match('/^(606282\d{10}(\d{3})?)|(3841\d{12})|(637\d{13})/', $cartaoNumero) => 'hipercard', default => '' };
Agora todos os números vão bater corretamente!
Esta bandeira 5031433215406351 no bincheck.io deu que não existe, então pode ser retirada.Aparentemente está falhando para alguns ainda... Olha o resultado que eu tive:
Qual código você tá usando?
No meu exemplo em TypeScript funcionou todos os cartões
Implementei essa função em typescript e testei os cartões que o @MMortari mandou, alguns falharam:
6505050000001000: Esperado: Elo. Resultado: Discover
6505050000001091: Esperado: Elo. Resultado: Discover
6505050000001018: Esperado: Elo. Resultado: Discover
6505050000001109: Esperado: Elo. Resultado: Discover
5031433215406351: Esperado: Mastercard. Resultado: Aura
5098176533461570: Esperado: Elo. Resultado: Aura
5098193894226609: Esperado: Elo. Resultado: Aura
5091084515027541: Esperado: Elo. Resultado: Aura
5098177024386094: Esperado: Elo. Resultado: Aura