Skip to content

Instantly share code, notes, and snippets.

@baldurrensch
Created August 15, 2012 21:05
Show Gist options
  • Save baldurrensch/3363685 to your computer and use it in GitHub Desktop.
Save baldurrensch/3363685 to your computer and use it in GitHub Desktop.
Credit Card Model class
<?php
namespace Acme\DV2Bundle\Model;
use Acme\DV2Bundle\Exception\UnsupportedCreditCardTypeException;
use Acme\DV2Bundle\Exception\UnknownCreditCardTypeException;
/**
* Acme\DV2Bundle\Entity\CreditCard
*/
class CreditCard
{
// Card Types
const CARD_TYPE_AMERICAN_EXPRESS = "AX";
const CARD_TYPE_DINERS_CLUB = "DC";
const CARD_TYPE_DISCOVER = "DI";
const CARD_TYPE_MASTERCARD = "MC";
const CARD_TYPE_VISA = 'VI';
// Special brands
const CARD_TYPE_BILLMELATER = "BL";
const CARD_TYPE_ELECTRONIC_CHECK = "EC";
const CARD_TYPE_EUROPEAN_DIRECT_DEBIT = "ED";
const CARD_TYPE_PINLESS_DEBIT = "DP";
const CARD_TYPE_SWITCH_SOLO = "SW";
// CVV Presence Indicator
const CVV_PRESENT = 1;
const CVV_ILLEGIBLE = 2;
const CVV_NOT_AVAILABLE = 9;
private $creditCardNumber;
private $creditCardCVV;
private $creditCardExpMonth;
private $creditCardExpYear;
/**
* Since we really always send the same information, it is defaulted now.
*/
private $creditCardPresenceIndicator = self::CVV_PRESENT;
public function getCreditCardNumber()
{
return $this->creditCardNumber;
}
public function getCreditCardCVV()
{
return $this->creditCardCVV;
}
public function getCreditCardPresenceIndicator()
{
return $this->creditCardPresenceIndicator;
}
public function setCreditCardNumber($creditCardNumber)
{
$this->creditCardNumber = $creditCardNumber;
}
public function setCreditCardCVV($param)
{
$this->creditCardCVV = $param;
}
public function getCreditCardExpMonth()
{
return $this->creditCardExpMonth;
}
public function setCreditCardExpMonth($param)
{
$this->creditCardExpMonth = $param;
}
public function getCreditCardExpYear()
{
return $this->creditCardExpYear;
}
public function setCreditCardExpYear($param)
{
$this->creditCardExpYear = $param;
}
/**
* This function tries to detect the credit card brand from the number
*
* @return String (one of the constants)
* @throws UnsupportedCreditCardTypeException
* @throws UnknownCreditCardTypeException
*/
public function getCreditCardType()
{
if (preg_match("/^5[1-5][0-9]{14}$/", $this->creditCardNumber)) {
return self::CARD_TYPE_MASTERCARD;
} elseif (preg_match("/^4[0-9]{12}([0-9]{3})?$/", $this->creditCardNumber)) {
return self::CARD_TYPE_VISA;
} elseif (preg_match("/^3[47][0-9]{13}$/", $this->creditCardNumber)) {
return self::CARD_TYPE_AMERICAN_EXPRESS;
} elseif (preg_match("/^3(0[0-5]|[68][0-9])[0-9]{11}$/", $this->creditCardNumber)) {
return self::CARD_TYPE_DINERS_CLUB;
} elseif (preg_match("/^6(011|5[0-9]{2})[0-9]{12}$/", $this->creditCardNumber)) {
return self::CARD_TYPE_DISCOVER;
} elseif (preg_match("/^(3[0-9]{4}|2131|1800)[0-9]{11}$/", $this->creditCardNumber)) {
throw new UnsupportedCreditCardTypeException("Unsupported Credit Card Type: JCB");
} else {
throw new UnknownCreditCardTypeException("Could not detect credit card type");
}
}
/**
* Performs the Luhn formula (Mod 10) for Validation of Credit Card Numbers. Will return true for
* non credit-card numbers.
*
* @see{http://www.beachnet.com/~hstiles/cardtype.html}
* @return boolean
*/
public function mod10()
{
// We don't want to mod10 check if it isn't a credit card
// ie. if this is a bill me later...
try {
$creditCardType = $this->getCreditCardType();
} catch (UnsupportedCreditCardTypeException $e) {
return false;
} catch (UnknownCreditCardTypeException $e) {
return false;
}
if(in_array($creditCardType,
array(
self::CARD_TYPE_BILLMELATER,
self::CARD_TYPE_ELECTRONIC_CHECK,
self::CARD_TYPE_EUROPEAN_DIRECT_DEBIT,
self::CARD_TYPE_PINLESS_DEBIT,
self::CARD_TYPE_SWITCH_SOLO
)
) == true) {
return true;
}
$ccNumber = strrev($this->creditCardNumber);
$checkDigit = $ccNumber{0};
$total = 0;
for($k = 0; $k < strlen($ccNumber); $k++){
$v = $ccNumber{$k};
if ($k%2 == 1) {
$x = ((int)$v)*2;
$x_str = (string)$x;
if ($x >= 10) {
$total += (int)$x_str{0};
$total += (int)$x_str{1};
} else {
$total += (int)$x;
}
} else {
$total += (int)$v;
}
}
return ($total % 10 == 0 ? true : false);
}
/**
* Verifies that the Credit Card is valid (passes the Mod10 Luhn algorithm test)
*
* @return boolean
*/
public function isValidCreditCard()
{
return $this->mod10();
}
/**
* Checks whether the Credit Card Expiration is valid
*
* @return boolean
*/
public function isValidCCExpiration()
{
if ($this->creditCardExpYear > date('Y') && $this->creditCardExpMonth > 0 &&
$this->creditCardExpMonth < 13) {
return true;
}
if ($this->creditCardExpYear == date('Y') && $this->creditCardExpMonth >= date('n') &&
$this->creditCardExpMonth < 13) {
return true;
}
return false;
}
/**
* This function should never really be called. We always require a CVV. Just here for
* completeness.
*
* @deprecated
* @codeCoverageIgnore
*/
public function setCreditCardPresenceIndicator($param)
{
$this->creditCardPresenceIndicator = $param;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment