system/Validation/CreditCardRules.php
public function valid_cc_number(string $ccNumber = null, string $type, array $data): bool
	{
		$type = strtolower($type);
		$info = null;

		// Get our card info based on provided name.
		foreach ($this->cards as $card)
		{
			if ($card['name'] === $type)
			{
				$info = $card;
				break;
			}
		}

		// If empty, it's not a card type we recognize, or invalid type.
		if (empty($info))
		{
			return false;
		}

		// Make sure we have a valid length
		if (strlen($ccNumber) === 0)
		{
			return false;
		}

		// Remove any spaces and dashes
		$ccNumber = str_replace([' ', '-'], '', $ccNumber);

		// Non-numeric values cannot be a number...duh
		if (! is_numeric($ccNumber))
		{
			return false;
		}

		// Make sure it's a valid length for this card
		$lengths = explode(',', $info['length']);

		if (! in_array(strlen($ccNumber), $lengths))
		{
			return false;
		}

		// Make sure it has a valid prefix
		$prefixes = explode(',', $info['prefixes']);

		$validPrefix = false;

		foreach ($prefixes as $prefix)
		{
			if (strpos($ccNumber, $prefix) === 0)
			{
							  $validPrefix = true;
							  break;
			}
		}

		if ($validPrefix === false)
		{
			return false;
		}

		// Still here? Then check the number against the Luhn algorithm, if required
		// @see https://en.wikipedia.org/wiki/Luhn_algorithm
		// @see https://gist.github.com/troelskn/1287893
		if ($info['checkdigit'] === true)
		{
			return $this->isValidLuhn($ccNumber);
		}

		return true;
	}
public function valid_cc_number(string $ccNumber = null, string $type, array $data): bool
	{
		$type = strtolower($type);
		$info = null;

		// Get our card info based on provided name.
		foreach ($this->cards as $card)
		{
			if ($card['name'] === $type)
			{
				$info = $card;
				break;
			}
		}

		// If empty, it's not a card type we recognize, or invalid type.
		if (empty($info))
		{
			return false;
		}

		// Make sure we have a valid length
		if (strlen($ccNumber) === 0)
		{
			return false;
		}

		// Remove any spaces and dashes
		$ccNumber = str_replace([' ', '-'], '', $ccNumber);

		// Non-numeric values cannot be a number...duh
		if (! is_numeric($ccNumber))
		{
			return false;
		}

		// Make sure it's a valid length for this card
		$lengths = explode(',', $info['length']);

		if (! in_array(strlen($ccNumber), $lengths))
		{
			return false;
		}

		// Make sure it has a valid prefix
		$prefixes = explode(',', $info['prefixes']);

		$validPrefix = false;

		foreach ($prefixes as $prefix)
		{
			if (strpos($ccNumber, $prefix) === 0)
			{
							  $validPrefix = true;
							  break;
			}
		}

		if ($validPrefix === false)
		{
			return false;
		}

		// Still here? Then check the number against the Luhn algorithm, if required
		// @see https://en.wikipedia.org/wiki/Luhn_algorithm
		// @see https://gist.github.com/troelskn/1287893
		if ($info['checkdigit'] === true)
		{
			return $this->isValidLuhn($ccNumber);
		}

		return true;
	}
Verifies that a credit card number is valid and matches the known
formats for a wide number of credit card types. This does not verify
that the card is a valid card, only that the number is formatted correctly.

Example:
$rules = [
'cc_num' => 'valid_cc_number[visa]'
];

@param string $ccNumber
@param string $type
@param array  $data

@return boolean