Skip to content

Instantly share code, notes, and snippets.

@gusribeiro
Last active April 17, 2024 20:16
Show Gist options
  • Star 98 You must be signed in to star a gist
  • Fork 17 You must be signed in to fork a gist
  • Save gusribeiro/263a165db774f5d78251 to your computer and use it in GitHub Desktop.
Save gusribeiro/263a165db774f5d78251 to your computer and use it in GitHub Desktop.
Regex para identificar bandeiras do cartão de crédito
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}$
@lucassilvasg1
Copy link

Show demais.

@henrique-smr
Copy link

Muito massa!

@Giovancruz
Copy link

Obrigado!

@sousaweb
Copy link

Desde 2017 a MasterCard tem bins de 222100 a 272099, o que inclui os cartões do Banco Inter por exemplo.
Um RegEx que atende aos bins 5 e 2 da MasterCard seria assim: /^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{14}$/

@WestBonner
Copy link

WestBonner commented Sep 8, 2020

Vou deixar minha contribuição de expressões regulares, se alguém quiser se disponibilizar a deixá-la mais completa, fico grato:

American Express:: '^3[47]\\d{0,13}'
Aura: '^507860'
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])
Fort Brasil: '^628167'
GrandCard: '^605032'
Hipercard: '^606282|^637095|^637599|^637568'
Personal Card: '^636085'
Sorocred: '^627892|^636414'
Valecard: '^606444|^606458|^606482'
Elo: ^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])

Todas as bandeiras acima são atualmente utilizadas pelo gateway da PagSeguro. Sim, sim, o Regex da ELO é gigantesco, talvez haja alguma forma de reduzi-lo, entretanto, em todos os testes que eu fiz ele passou.

@gusribeiro
Copy link
Author

Obrigado @sousaweb e @WestBonner pela contribuição! Já estou atualizando o gist ;)

@JeffersonTeixeira
Copy link

JeffersonTeixeira commented Sep 20, 2020

Alguém tem dos cartões BrasilCard, Mais e PlenoCard? Alguém tem informações sobre os cartões se por exemplo são apenas para alimentação?
As Regex que tenho usado:

            ELO: /^(4011|431274|438935|451416|457393|4576|457631|457632|504175|627780|636297|636368|636369|(6503[1-3])|(6500(3[5-9]|4[0-9]|5[0-1]))|(6504(0[5-9]|1[0-9]|2[0-9]|3[0-9]))|(650(48[5-9]|49[0-9]|50[0-9]|51[1-9]|52[0-9]|53[0-7]))|(6505(4[0-9]|5[0-9]|6[0-9]|7[0-9]|8[0-9]|9[0-8]))|(6507(0[0-9]|1[0-8]))|(6507(2[0-7]))|(650(90[1-9]|91[0-9]|920))|(6516(5[2-9]|6[0-9]|7[0-9]))|(6550(0[0-9]|1[1-9]))|(6550(2[1-9]|3[0-9]|4[0-9]|5[0-8]))|(506(699|77[0-8]|7[1-6][0-9))|(509([0-9][0-9][0-9])))/,
            DN: /^3(?:0[0-5]|[68][0-9])[0-9]/,//Diners
            AE: /^3[47][0-9]{5,}$/, //AMEX
            MC: /^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]/,//MasterCard
            AU: /^((?!504175))^((?!5067))(^50[0-9])/,//Aura        
            VI: /^4\d{5}/, //Visa
            VC: /^606444|^606458|^606482/, //ValeCard
            SC: /^627892|^636414/, //SoroCred
            PC: /^636085/, //PersonalCard
            GC: /^605032/, //GrandCard
            FB: /^628167/, //FortBrasil

@EbenauDev
Copy link

@sousaweb, utilizei a tua Regex em alguns testes meus utilizando os números de cartões da mastercard gerados apartir deste site porém obtive o resultado false em alguns testes.
Procurei no stackoverflow, e encontrei essa Regex:

^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$
Com essa Regex, não tive problema com a validação dos cartões mastercard começados com 222100 a 272099.

Pergunta do stackoverflow onde eu consegui a Regex acima:
https://stackoverflow.com/questions/9315647/regex-credit-card-number-tests

@gusribeiro
Copy link
Author

@sousaweb, utilizei a tua Regex em alguns testes meus utilizando os números de cartões da mastercard gerados apartir deste site porém obtive o resultado false em alguns testes.
Procurei no stackoverflow, e encontrei essa Regex:

^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$
Com essa Regex, não tive problema com a validação dos cartões mastercard começados com 222100 a 272099.

Pergunta do stackoverflow onde eu consegui a Regex acima:
https://stackoverflow.com/questions/9315647/regex-credit-card-number-tests

obrigado @sousaweb, irei atualizar o gist. assim teremos uma fonte cada dia mais atualizada ;)

@diafrit
Copy link

diafrit commented Mar 5, 2021

A Regex pra cartões Aura do @JeffersonTeixeira se saiu mais acertiva nos testes que fiz pra essa bandeira.
Quanto a cartões Elo, tomei a liberdade de diminuir/limpar um pouco a Regex atual, mantendo as mesmas regras. Ficou assim:

/^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]))/

Se alguém tiver alguma lista de cartões Elo e puder compartilhar e testar, ficarei grato :)

@JeffersonTeixeira
Copy link

JeffersonTeixeira commented Mar 8, 2021

Se alguém tiver alguma lista de cartões Elo e puder compartilhar e testar, ficarei grato :)

@diafrit Testa esse site: https://www.vccgenerator.com/

@wanderdevof
Copy link

ELO: ^(50(67(0[78]|1[5789]|2[012456789]|3[01234569]|4[0-7]|53|7[4-8])|9(0(0[0-9]|1[34]|2[0-7]|3[0359]|4[01235678]|5[01235789]|6[0-9]|7[01346789]|8[01234789]|9[123479])|1(0[34568]|4[6-9]|5[1-8]|8[356789])|2(2[0-2]|5[78]|6[1-9]|7[0-9]|8[01235678]|90)|357|4(0[7-9]|1[0-9]|2[0-2]|31|5[7-9]|6[0-6]|84)|55[01]|636|7(2[2-9]|6[5-9])))|4(0117[89]|3(1274|8935)|5(1416|7(393|63[12])))|6(27780|36368|5(0(0(3[12356789]|4[0-7]|7[78])|4(0[6-9]|1[0234]|2[2-9]|3[045789]|8[5-9]|9[0-9])|5(0[012346789]|1[0-9]|2[0-9]|3[0178]|5[2-9]|6[0-6]|7[7-9]|8[0-8]|9[1-8])|72[0-7]|9(0[1-9]|1[0-9]|2[0128]|3[89]|4[6-9]|5[0145]|6[235678]|71))|16(5[2-9]|6[0-9]|7[01456789])|50(0[0-9]|1[02345678]|36|5[1267]))))\\d{0,13}$

HIPERCARD: ^606282|^3841(?:[0|4|6]{1})0

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})

AMEX: ^3[47][0-9]{13}$

VISA: ^4[0-9]{15}$

Atualização 2021

@eamax
Copy link

eamax commented May 3, 2021

A Regex pra cartões Aura do @JeffersonTeixeira se saiu mais acertiva nos testes que fiz pra essa bandeira.
Quanto a cartões Elo, tomei a liberdade de diminuir/limpar um pouco a Regex atual, mantendo as mesmas regras. Ficou assim:

/^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]))/

Se alguém tiver alguma lista de cartões Elo e puder compartilhar e testar, ficarei grato :)

De todos os testes que eu fiz com os regex dessa discussão, esse do diafrit foi o único que passou em todos testes que eu fiz para cartão ELO
regexr.com/5s4ov

Edit: aproveitei e deixei uma grande lista de cartões para teste

@eamax
Copy link

eamax commented May 3, 2021

^(4011(78|79)|43(1274|8935)|45(1416|7393|763(1|2))|50(4175|6699|67[0-7][0-9]|9000)|50(9[0-9][0-9][0-9])|627780|63(6297|6368)|650(03([^4])|04([0-9])|05(0|1)|05([7-9])|06([0-9])|07([0-9])|08([0-9])|4([0-3][0-9]|8[5-9]|9[0-9])|5([0-9][0-9]|3[0-8])|9([0-6][0-9]|7[0-8])|7([0-2][0-9])|541|700|720|727|901)|65165([2-9])|6516([6-7][0-9])|65500([0-9])|6550([0-5][0-9])|655021|65505([6-7])|6516([8-9][0-9])|65170([0-4]))

Esse regex da Jumori funcionou igualmente bem ao do comentário anterior, passou em todos os testes.
Esse é de um aviso direto da Elo, me parece mais confiável.

@BrunaoW
Copy link

BrunaoW commented Jul 20, 2021

Oi pessoal, o Regex da VISA e Elo citados acabam coincidindo pra esse número de cartão gerado: 4576329166124130, o que está me causando uma dor de cabeça pra pensar numa solução.

Gerei nesse site: https://www.vccgenerator.com/

@rafaelsiq94
Copy link

Alguém tem o regex para Credz?

@WestBonner
Copy link

Alguém tem o regex para Credz?

Tecnicamente falando, é possível criar o regex para uma grande diversidade de cartões tendo por base o Número de Identificação do Emissor (IIN), também chamado de Número de Identificação Bancária (BIN). Isso significa que o reconhecimento da bandeira do cartão geralmente ocorre após inseridos os 4 ou 6 primeiros números desse cartão.
Eu não conheço o emissor do cartão em questão, mas creio que o BIN seja 6367 60XX XXXX XXXX. Se eu estiver correto, ou seja, se todos os cartões da Credz se iniciarem com os seis números citados acima, gerar um regex é tarefa bem simples, basta ver os exemplos acima.

@WestBonner
Copy link

Oi pessoal, o Regex da VISA e Elo citados acabam coincidindo pra esse número de cartão gerado: 4576329166124130, o que está me causando uma dor de cabeça pra pensar numa solução.

Gerei nesse site: https://www.vccgenerator.com/

Oi pessoal, o Regex da VISA e Elo citados acabam coincidindo pra esse número de cartão gerado: 4576329166124130, o que está me causando uma dor de cabeça pra pensar numa solução.

Gerei nesse site: https://www.vccgenerator.com/

Coincidências não deveriam ocorrer. Os emissores de cartões definem números de forma a não haver Coincidências. Provavelmente há algum conflito na formação de alguma das regex acima. Estou a muito tempo longe desse tipo de programação, não acho que eu teria expertise - ou paciência - para encontrar o conflito. Talvez alguém se disponibilize a fazê-lo. No entanto, se ninguém o fizer ou se o conflito persistir, você poderá tentar soluções alternativas. Uma delas é, em caso de um conflito, solicitar ao cliente que informe ele mesmo a bandeira do cartão. Pode não ser a solução ideal, mas nem tudo no mundo é...

@GianAlbino
Copy link

Esse Regex já está levando em consideração a quantidade de dígitos?
(Pode ser que seja uma pergunta meio besta, mas não me aventuro muito em Regex, então as vezes me perco rsrs)

@IkaroFox
Copy link

Efetuei Alguns testes e o padrão do Visa tbm valida o do Elo, esse é o padrão que utilizei para evitar isso, com um negativo lookahead do Elo.

^(?!504175|506699|5067|509|6500|6501|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])))4[0-9]{12}(?:[0-9]{3})?$

realmente é grande, mas não acontece mais essa exceção.

@Fer-code
Copy link

Boa tarde, pessoal!

Estou precisando de uma ajuda pq tmb não tenho experiência em REGEX, esse que foi informado é para qual bandeira? E em suma, quais seriam para cada bandeira?

Efetuei Alguns testes e o padrão do Visa tbm valida o do Elo, esse é o padrão que utilizei para evitar isso, com um negativo lookahead do Elo.

^(?!504175|506699|5067|509|6500|6501|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])))4[0-9]{12}(?:[0-9]{3})?$

realmente é grande, mas não acontece mais essa exceção.

@gusribeiro
Copy link
Author

@GianAlbino não, não está limitando a quantidade de caracteres.

@Fer-code talvez esteja um pouco desatualizado pois não tive mais tempo de vir aqui atualizar a postagem inicial, mas no início da thread eu separei os regex para cada bandeira.

Essa último post, foi relacionado ao Visa e Elo apenas, pelo que eu pude entender.

@IkaroFox
Copy link

@Fer-code o que informei é para o Visa.

pois ao utilizar o regex para Visa : ^4[0-9]{15}$ tambem valida para um cartão Elo e do jeito que informei, não acontece isso.

REGEXR é uma opção muito boa para fazer testes.

@Fer-code
Copy link

Fer-code commented Nov 14, 2023

Ola pessoal, fiz as correcoes que vcs falaram. Porem percebi que HIPERCARD esta desatualizado. Por isso fiz um novo validando todos que estao nesse site: "https://bincheck.io/pt/br/itau-unibanco,-s.a./hipercard".


HIPERCARD ATUALIZADO: /^(606282\d{10}(\d{3})?)|(3841\d{12})|(637\d{13})$/


AO TODO:

'AMERICAN_EXPRESS': /^3[47]\d{13}$/,

 'DINERS_CLUB': /^3(?:0[0-5]|[68]\d)\d{11}$/,

'ELO': /(4011|431274|438935|451416|457393|4576|457631|457632|504175|627780|636297|636368|636369|(6503[1-3])|(6500(3[5-9]|4[0-9]|5[0-1]))|(6504(0[5-9]|1[0-9]|2[0-9]|3[0-9]))|(650(48[5-9]|49[0-9]|50[0-9]|51[1-9]|52[0-9]|53[0-7]))|(6505(4[0-9]|5[0-9]|6[0-9]|7[0-9]|8[0-9]|9[0-8]))|(6507(0[0-9]|1[0-8]))|(6507(2[0-7]))|(650(90[1-9]|91[0-9]|920))|(6516(5[2-9]|6[0-9]|7[0-9]))|(6550(0[0-9]|1[1-9]))|(6550(2[1-9]|3[0-9]|4[0-9]|5[0-8]))|(506(699|77[0-8]|7[1-6][0-9))|(509([0-9][0-9][0-9])))/,

 'HIPERCARD': /^(606282\d{10}(\d{3})?)|(3841\d{12})|(637\d{13})$/,

'MASTERCARD': /^5[1-5]\d{14}$|^2(?:2(?:2[1-9]|[3-9]\d)|[3-6]\d\d|7(?:[01]\d|20))\d{12}$/,

 'VISA': /^(?!504175|506699|5067|509|6500|6501|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])))4[0-9]{12}(?:[0-9]{3})?$/

@IkaroFox
Copy link

IkaroFox commented Nov 15, 2023

@Fer-code , show de bola, ficou top viu, vou até utilizar kkk

image

@Fer-code
Copy link

@Fer-code , show de bola, ficou top viu, vou até utilizar kkk

image

Valeuuu! Mais atualizações vamos mandando ai :)

@MMortari
Copy link

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,
};

@GabrielLasso
Copy link

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

@GabrielLasso
Copy link

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

@IkaroFox
Copy link

IkaroFox commented Apr 5, 2024

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 ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment