<?php

// simply validate a credit card number
function valid_cc_number($number, $type) {
  $number = preg_replace('/\D/','',$number);
  
  // check the number format first
  switch ($type):
    case 'amex':
      if (!preg_match('/^3[4-7]\d{13}$/',$number)) return false;
      break;
    case 'diners':
      if (!preg_match('/^30[0-5]\d{11}|3[678]\d{12}$/',$number)) return false;
      break;
    case 'discover':
      if (!preg_match('/^6011\d{12}$/',$number)) return false;
      break;
    case 'mastercard':
      if (!preg_match('/^5[1-5]\d{14}$/',$number)) return false;
      break;
    case 'visa':
      if (!preg_match('/^4\d{12,15}$/',$number)) return false;
      break;
    default:
      return false;
  endswitch;

  // if we've gotten this far without returning false,
  // then the card number format is okay
  // so now validate the check digit with the Luhn algorithm
  $doublethisdigit = false;
  $sum = 0;
  for ($i = strlen($number)-1; $i >= 0; $i--):  
    if ($doublethisdigit):
      $digit = $number[$i] * 2;
      // subtract 9 if the doubled digit is > 9
      $digit -= ($digit > 9) ? 9 : 0;
    else:
      // the other digits get summed without doubling
      $digit = $number[$i];
    endif;
    $sum += $digit; 
    $doublethisdigit = !$doublethisdigit; // flip flop
  endfor;
  // the check is valid if the sum is a multiple of 10
  return ($sum % 10 == 0);
}

?>