You are here

final class CommercePaymentCreditCard in Commerce Core 7

Provides logic for listing card types and validating card details.

Hierarchy

Expanded class hierarchy of CommercePaymentCreditCard

File

modules/payment/includes/commerce_payment.credit_card.inc, line 414
Credit-card helper functions for Drupal commerce.

View source
final class CommercePaymentCreditCard {

  /**
   * Gets all available card types.
   *
   * @return array
   *   The array of card types, keyed by card type ID.
   */
  public static function getTypes() {
    $definitions = array(
      'visa' => array(
        'id' => 'visa',
        'label' => t('Visa'),
        'number_prefixes' => array(
          '4',
        ),
        'number_lengths' => array(
          16,
          18,
          19,
        ),
      ),
      'mastercard' => array(
        'id' => 'mastercard',
        'label' => t('Mastercard'),
        'number_prefixes' => array(
          '51-55',
          '222100-272099',
        ),
      ),
      'maestro' => array(
        'id' => 'maestro',
        'label' => t('Maestro'),
        'number_prefixes' => array(
          '5018',
          '502',
          '503',
          '506',
          '56',
          '58',
          '639',
          '6220',
          '67',
        ),
        'number_lengths' => array(
          12,
          13,
          14,
          15,
          16,
          17,
          18,
          19,
        ),
      ),
      'amex' => array(
        'id' => 'amex',
        'label' => t('American Express'),
        'number_prefixes' => array(
          '34',
          '37',
        ),
        'number_lengths' => array(
          15,
        ),
        'security_code_length' => 4,
      ),
      'dc' => array(
        'id' => 'dc',
        'label' => t('Diners Club'),
        'number_prefixes' => array(
          '300-305',
          '309',
          '36',
          '38',
          '39',
        ),
        'number_lengths' => array(
          14,
          16,
          19,
        ),
      ),
      'discover' => array(
        'id' => 'discover',
        'label' => t('Discover Card'),
        'number_prefixes' => array(
          '6011',
          '622126-622925',
          '644-649',
          '65',
        ),
        'number_lengths' => array(
          16,
          19,
        ),
      ),
      'jcb' => array(
        'id' => 'jcb',
        'label' => t('JCB'),
        'number_prefixes' => array(
          '3528-3589',
        ),
        'number_lengths' => array(
          16,
          17,
          18,
          19,
        ),
      ),
      'unionpay' => array(
        'id' => 'unionpay',
        'label' => t('UnionPay'),
        'number_prefixes' => array(
          '62',
          '88',
        ),
        'number_lengths' => array(
          16,
          17,
          18,
          19,
        ),
        'uses_luhn' => FALSE,
      ),
    );
    drupal_alter('commerce_card_type_info', $definitions);
    foreach ($definitions as &$definition) {
      $definition += array(
        'number_lengths' => array(
          16,
        ),
        'security_code_length' => 3,
        'uses_luhn' => TRUE,
      );
    }
    return $definitions;
  }

  /**
   * Gets the labels of all available credit card types.
   *
   * @return array
   *   The labels, keyed by ID.
   */
  public static function getTypeLabels() {
    $type_labels = array();
    foreach (self::getTypes() as $type) {
      $type_labels[$type['id']] = $type['label'];
    }
    return $type_labels;
  }

  /**
   * Detects the credit card type based on the number.
   *
   * @param string $number
   *   The credit card number.
   *
   * @return array|false
   *   The credit card type, or NULL if unknown.
   */
  public static function detectType($number) {
    if (!is_numeric($number)) {
      return FALSE;
    }
    $types = self::getTypes();
    foreach ($types as $type) {
      foreach ($type['number_prefixes'] as $prefix) {
        if (self::matchPrefix($number, $prefix)) {
          return $type;
        }
      }
    }
    return FALSE;
  }

  /**
   * Checks whether the given credit card number matches the given prefix.
   *
   * @param string $number
   *   The credit card number.
   * @param string $prefix
   *   The prefix to match against. Can be a single number such as '43' or a
   *   range such as '30-35'.
   *
   * @return bool
   *   TRUE if the credit card number matches the prefix, FALSE otherwise.
   */
  public static function matchPrefix($number, $prefix) {
    if (is_numeric($prefix)) {
      return substr($number, 0, strlen($prefix)) == $prefix;
    }
    else {
      list($start, $end) = explode('-', $prefix);
      $number = substr($number, 0, strlen($start));
      return $number >= $start && $number <= $end;
    }
  }

  /**
   * Validates the given credit card number.
   *
   * @param string $number
   *   The credit card number.
   * @param array $type
   *   The credit card type.
   *
   * @return bool
   *   TRUE if the credit card number is valid, FALSE otherwise.
   */
  public static function validateNumber($number, array $type) {
    if (!is_numeric($number)) {
      return FALSE;
    }
    if (!in_array(strlen($number), $type['number_lengths'])) {
      return FALSE;
    }
    if ($type['uses_luhn'] && !self::validateLuhn($number)) {
      return FALSE;
    }
    return TRUE;
  }

  /**
   * Validates the given credit card number using the Luhn algorithm.
   *
   * @param string $number
   *   The credit card number.
   *
   * @return bool
   *   TRUE if the credit card number is valid, FALSE otherwise.
   */
  public static function validateLuhn($number) {
    $total = 0;
    foreach (array_reverse(str_split($number)) as $i => $digit) {
      $digit = $i % 2 ? $digit * 2 : $digit;
      $digit = $digit > 9 ? $digit - 9 : $digit;
      $total += $digit;
    }
    return $total % 10 === 0;
  }

  /**
   * Validates the given credit card expiration date.
   *
   * @param string $month
   *   The 1 or 2-digit numeric representation of the month, i.e. 1, 6, 12.
   * @param string $year
   *   The 4-digit numeric representation of the year, i.e. 2010.
   *
   * @return bool
   *   TRUE if the credit card expiration date is valid, FALSE otherwise.
   */
  public static function validateExpirationDate($month, $year) {
    if ($month < 1 || $month > 12) {
      return FALSE;
    }
    if ($year < date('Y')) {
      return FALSE;
    }
    elseif ($year == date('Y') && $month < date('n')) {
      return FALSE;
    }
    return TRUE;
  }

  /**
   * Calculates the unix timestamp for a credit card expiration date.
   *
   * @param string $month
   *   The 1 or 2-digit numeric representation of the month, i.e. 1, 6, 12.
   * @param string $year
   *   The 4-digit numeric representation of the year, i.e. 2010.
   *
   * @return int
   *   The expiration date as a unix timestamp.
   */
  public static function calculateExpirationTimestamp($month, $year) {

    // Credit cards expire on the last day of the month.
    $month_start = strtotime($year . '-' . $month . '-01');
    $last_day = date('t', $month_start);
    return strtotime($year . '-' . $month . '-' . $last_day);
  }

  /**
   * Validates the given credit card security code.
   *
   * @param string $security_code
   *   The credit card security code.
   * @param array $type
   *   The credit card type.
   *
   * @return bool
   *   TRUE if the credit card security code is valid, FALSE otherwise.
   */
  public static function validateSecurityCode($security_code, array $type) {
    if (!is_numeric($security_code)) {
      return FALSE;
    }
    if (strlen($security_code) != $type['security_code_length']) {
      return FALSE;
    }
    return TRUE;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CommercePaymentCreditCard::calculateExpirationTimestamp public static function Calculates the unix timestamp for a credit card expiration date.
CommercePaymentCreditCard::detectType public static function Detects the credit card type based on the number.
CommercePaymentCreditCard::getTypeLabels public static function Gets the labels of all available credit card types.
CommercePaymentCreditCard::getTypes public static function Gets all available card types.
CommercePaymentCreditCard::matchPrefix public static function Checks whether the given credit card number matches the given prefix.
CommercePaymentCreditCard::validateExpirationDate public static function Validates the given credit card expiration date.
CommercePaymentCreditCard::validateLuhn public static function Validates the given credit card number using the Luhn algorithm.
CommercePaymentCreditCard::validateNumber public static function Validates the given credit card number.
CommercePaymentCreditCard::validateSecurityCode public static function Validates the given credit card security code.