Função para validar cartões de crédito com detecção automática da bandeira

Função para validar cartões de crédito, com suporte a validação de CVC.

O primeiro parâmetro é o número do cartão e o segundo o CVC (opcional), os dados serão sanitizados, sendo filtrado somente os números.

A saida é um array de três posições, a primeira retorna false (em caso de erro) ou a bandeira, a segunda se o número do cartão é válido e a terceira se o CVC é válido.

 

/**
 * @author Felipe Braz
 * @website https://braz.dev/blog
 * @param int $cartao
 * @param int $cvc
 * @return array
 */
function valida_cartao($cartao, $cvc=false){
	$cartao = preg_replace("/[^0-9]/", "", $cartao);
	if($cvc) $cvc = preg_replace("/[^0-9]/", "", $cvc);

	$cartoes = array(
			'visa'		 => array('len' => array(13,16),    'cvc' => 3),
			'mastercard' => array('len' => array(16),       'cvc' => 3),
			'diners'	 => array('len' => array(14,16),    'cvc' => 3),
			'elo'		 => array('len' => array(16),       'cvc' => 3),
			'amex'	 	 => array('len' => array(15),       'cvc' => 4),
			'discover'	 => array('len' => array(16),       'cvc' => 4),
			'aura'		 => array('len' => array(16),       'cvc' => 3),
			'jcb'		 => array('len' => array(16),       'cvc' => 3),
			'hipercard'  => array('len' => array(13,16,19), 'cvc' => 3),
	);

	
	switch($cartao){
		case (bool) preg_match('/^(636368|438935|504175|451416|636297)/', $cartao) :
			$bandeira = 'elo';			
		break;

		case (bool) preg_match('/^(606282)/', $cartao) :
			$bandeira = 'hipercard';			
		break;

		case (bool) preg_match('/^(5067|4576|4011)/', $cartao) :
			$bandeira = 'elo';			
		break;

		case (bool) preg_match('/^(3841)/', $cartao) :
			$bandeira = 'hipercard';			
		break;

		case (bool) preg_match('/^(6011)/', $cartao) :
			$bandeira = 'discover';			
		break;

		case (bool) preg_match('/^(622)/', $cartao) :
			$bandeira = 'discover';			
		break;

		case (bool) preg_match('/^(301|305)/', $cartao) :
			$bandeira = 'diners';			
		break;

		case (bool) preg_match('/^(34|37)/', $cartao) :
			$bandeira = 'amex';			
		break;

		case (bool) preg_match('/^(36,38)/', $cartao) :
			$bandeira = 'diners';			
		break;

		case (bool) preg_match('/^(64,65)/', $cartao) :
			$bandeira = 'discover';			
		break;

		case (bool) preg_match('/^(50)/', $cartao) :
			$bandeira = 'aura';			
		break;

		case (bool) preg_match('/^(35)/', $cartao) :
			$bandeira = 'jcb';			
		break;

		case (bool) preg_match('/^(60)/', $cartao) :
			$bandeira = 'hipercard';			
		break;

		case (bool) preg_match('/^(4)/', $cartao) :
			$bandeira = 'visa';			
		break;

		case (bool) preg_match('/^(5)/', $cartao) :
			$bandeira = 'mastercard';			
		break;
	}

	$dados_cartao = $cartoes[$bandeira];
	if(!is_array($dados_cartao)) return array(false, false, false);

	$valid     = true;
	$valid_cvc = false;

	if(!in_array(strlen($cartao), $dados_cartao['len'])) $valid = false;
	if($cvc AND strlen($cvc) <= $dados_cartao['cvc'] AND strlen($cvc) !=0) $valid_cvc = true;
	return array($bandeira, $valid, $valid_cvc);
}

Ah, a minha esposa queria que eu botasse nesse post uma foto de gatinho, então lá vai:

Picture-86

Fonte: https://gist.github.com/erikhenrique/5931368