PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/drupal/sites/all/modules/civicrm/packages/Validate/Finance/CreditCard.php

https://github.com/michaelmcandrew/vaw
PHP | 297 lines | 127 code | 16 blank | 154 comment | 21 complexity | 9d6fb2a182dcb0b666c91176aa41a1bf MD5 | raw file
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. /**
  4. * Validation methods for credit card related data
  5. *
  6. * PHP Versions 4 and 5
  7. *
  8. * This source file is subject to the New BSD license, That is bundled
  9. * with this package in the file LICENSE, and is available through
  10. * the world-wide-web at
  11. * http://www.opensource.org/licenses/bsd-license.php
  12. * If you did not receive a copy of the new BSDlicense and are unable
  13. * to obtain it through the world-wide-web, please send a note to
  14. * pajoye@php.net so we can mail you a copy immediately.
  15. *
  16. * @category Validate
  17. * @package Validate_Finance_CreditCard
  18. * @author Stefan Neufeind <pear.neufeind@speedpartner.de>
  19. * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
  20. * @copyright 1997-2005 Stefan Neufeind
  21. * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  22. * @version CVS: $Id: CreditCard.php,v 1.13 2007/09/16 16:42:34 kguest Exp $
  23. * @link http://pear.php.net/package/Validate_Finance_CreditCard
  24. */
  25. /**
  26. * Credit card related information validation class
  27. *
  28. * This class provides methods to validate:
  29. * - Credit card number
  30. * - Card security code
  31. * - Card type (i.e. Visa, Mastercard...)
  32. *
  33. * The methods only check the format of the data. For instance
  34. * the package does NOT check if a card is a legitimate card registered
  35. * with a card issuer, or if the card is reported stolen, etc...
  36. *
  37. * @category Validate
  38. * @package Validate_Finance_CreditCard
  39. * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
  40. * @author Ondrej Jombik <nepto@pobox.sk>
  41. * @copyright 1997-2005 Stefan Neufeind
  42. * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  43. * @version Release: @package_version@
  44. * @link http://pear.php.net/package/Validate_Finance_CreditCard
  45. */
  46. class Validate_Finance_CreditCard
  47. {
  48. /**
  49. * Validates a number according to Luhn check algorithm
  50. *
  51. * This function checks given number according Luhn check
  52. * algorithm. It is published on several places. See links for details.
  53. *
  54. * @param string $number number to check
  55. *
  56. * @return bool TRUE if number is valid, FALSE otherwise
  57. * @access public
  58. * @static
  59. * @deprecated
  60. * @link http://www.webopedia.com/TERM/L/Luhn_formula.html
  61. * @link http://www.merriampark.com/anatomycc.htm
  62. * @link http://hysteria.sk/prielom/prielom-12.html#3 (Slovak language)
  63. * @link http://www.speech.cs.cmu.edu/~sburke/pub/luhn_lib.html (Perl lib)
  64. */
  65. function Luhn($number)
  66. {
  67. return Validate_Finance_CreditCard::_luhn($number);
  68. }
  69. /**
  70. * Validates a number according to Luhn check algorithm
  71. *
  72. * This function checks given number according Luhn check
  73. * algorithm. It is published on several places. See links for details.
  74. *
  75. * @param string $number number to check
  76. *
  77. * @return bool TRUE if number is valid, FALSE otherwise
  78. * @access private
  79. * @static
  80. * @link http://www.webopedia.com/TERM/L/Luhn_formula.html
  81. * @link http://www.merriampark.com/anatomycc.htm
  82. * @link http://hysteria.sk/prielom/prielom-12.html#3 (Slovak language)
  83. * @link http://www.speech.cs.cmu.edu/~sburke/pub/luhn_lib.html (Perl lib)
  84. */
  85. function _luhn($number)
  86. {
  87. $len_number = strlen($number);
  88. $sum = 0;
  89. for ($k = $len_number % 2; $k < $len_number; $k += 2) {
  90. if ((intval($number{$k}) * 2) > 9) {
  91. $sum += (intval($number{$k}) * 2) - 9;
  92. } else {
  93. $sum += intval($number{$k}) * 2;
  94. }
  95. }
  96. for ($k = ($len_number % 2) ^ 1; $k < $len_number; $k += 2) {
  97. $sum += intval($number{$k});
  98. }
  99. return ($sum % 10) ? false : true;
  100. }
  101. /**
  102. * Validates a credit card number
  103. *
  104. * If a type is passed, the card will be checked against it.
  105. * This method only checks the number locally. No banks or payment
  106. * gateways are involved.
  107. * This method doesn't guarantee that the card is legitimate. It merely
  108. * checks the card number passes a mathematical algorithm.
  109. *
  110. * @param string $creditCard number (spaces and dashes tolerated)
  111. * @param string $cardType type/brand of card (case insensitive)
  112. * "MasterCard", "Visa", "AMEX", "AmericanExpress",
  113. * "American Express", "Diners", "DinersClub", "Diners Club",
  114. * "CarteBlanche", "Carte Blanche", "Discover", "JCB",
  115. * "EnRoute", "Eurocard", "Eurocard/MasterCard".
  116. *
  117. * @return bool TRUE if number is valid, FALSE otherwise
  118. * @access public
  119. * @static
  120. */
  121. function number($creditCard, $cardType = null)
  122. {
  123. $cc = str_replace(array('-', ' '), '', $creditCard);
  124. if (($len = strlen($cc)) < 13
  125. || strspn($cc, '0123456789') != $len) {
  126. return false;
  127. }
  128. // Only apply the Luhn algorithm for cards other than enRoute
  129. // So check if we have a enRoute card now
  130. if (strlen($cc) != 15
  131. || (substr($cc, 0, 4) != '2014'
  132. && substr($cc, 0, 4) != '2149')) {
  133. if (!Validate_Finance_CreditCard::_luhn($cc)) {
  134. return false;
  135. }
  136. }
  137. if (is_string($cardType)) {
  138. return Validate_Finance_CreditCard::type($cc, $cardType);
  139. }
  140. return true;
  141. }
  142. /**
  143. * Validates the credit card number against a type
  144. *
  145. * This method only checks for the type marker. It doesn't
  146. * validate the card number. Some card "brands" share the same
  147. * numbering system, so checking the card type against any of the
  148. * sister brand will return the same result.
  149. *
  150. * For instance, if a $card is a MasterCard, type($card, 'EuroCard')
  151. * will also return true.
  152. *
  153. * @param string $creditCard number (spaces and dashes tolerated)
  154. * @param string $cardType type/brand of card (case insensitive)
  155. * "MasterCard", "Visa", "AMEX", "AmericanExpress",
  156. * "American Express", "Diners", "DinersClub", "Diners Club",
  157. * "CarteBlanche", "Carte Blanche", "Discover", "JCB",
  158. * "EnRoute", "Eurocard", "Eurocard/MasterCard".
  159. *
  160. * @return bool TRUE is type matches, FALSE otherwise
  161. * @access public
  162. * @static
  163. * @link http://www.beachnet.com/~hstiles/cardtype.html
  164. */
  165. function type($creditCard, $cardType)
  166. {
  167. switch (strtoupper($cardType)) {
  168. case 'MASTERCARD':
  169. case 'EUROCARD':
  170. case 'EUROCARD/MASTERCARD':
  171. $regex = '5[1-5][0-9]{14}';
  172. break;
  173. case 'VISA':
  174. case 'VISA / VISA DEBIT':
  175. $regex = '4([0-9]{12}|[0-9]{15})';
  176. break;
  177. case 'AMEX':
  178. case 'AMERICANEXPRESS':
  179. case 'AMERICAN EXPRESS':
  180. $regex = '3[47][0-9]{13}';
  181. break;
  182. case 'DINERS':
  183. case 'DINERSCLUB':
  184. case 'DINERS CLUB':
  185. case 'CARTEBLANCHE':
  186. case 'CARTE BLANCHE':
  187. $regex = '3(0[0-5][0-9]{11}|[68][0-9]{12})';
  188. break;
  189. case 'DISCOVER':
  190. $regex = '6011[0-9]{12}';
  191. break;
  192. case 'JCB':
  193. $regex = '(3[0-9]{15}|(2131|1800)[0-9]{11})';
  194. break;
  195. case 'ENROUTE':
  196. $regex = '2(014|149)[0-9]{11}';
  197. break;
  198. case 'LASER':
  199. $regex = '(6304|6706|6771|6709)([0-9]{12,15})';
  200. break;
  201. case 'SOLO':
  202. $regex = '(6334[5-9]{1}[0-9]{1}|6767[0-9]{2}|3528[0-9]{2})([0-9]{10}|[0-9]{12}|[0-9]{13})';
  203. break;
  204. case 'SWITCH':
  205. case 'MAESTRO':
  206. case 'SWITCH/MAESTRO':
  207. case 'MAESTRO/SWITCH':
  208. $regex = '(49030[2-9]{1}|49033[5-9]{1}|49110[1-2]{1}|49117[4-9]{1}|49118[0-2]{1}|4936[0-9]{2}|564182|6333[1-4]{1}[0-9]{1}|6331[1-4]{1}[0-9]{1}|6759[0-9]{2})([0-9]{10}|[0-9]{12}|[0-9]{13})';
  209. break;
  210. default:
  211. return false;
  212. }
  213. $regex = '/^' . $regex . '$/';
  214. $cc = str_replace(array('-', ' '), '', $creditCard);
  215. return (bool)preg_match($regex, $cc);
  216. }
  217. /**
  218. * Validates a card verification value format
  219. *
  220. * This method only checks for the format. It doesn't
  221. * validate that the value is the one on the card.
  222. *
  223. * CVV is also known as
  224. * - CVV2 Card Validation Value 2 (Visa)
  225. * - CVC Card Validation Code (MasterCard)
  226. * - CID Card Identification (American Express and Discover)
  227. * - CIN Card Identification Number
  228. * - CSC Card Security Code
  229. *
  230. * Important information regarding CVV:
  231. * If you happen to have to store credit card information, you must
  232. * NOT retain the CVV after transaction is complete. Usually this
  233. * means you cannot store it in a database, not even in an encrypted
  234. * form. See http://www.pcisecuritystandards.org/
  235. *
  236. * This method returns FALSE for card types that don't support CVV.
  237. *
  238. * @param string $cvv value to verify
  239. * @param string $cardType type/brand of card (case insensitive)
  240. * "MasterCard", "Visa", "AMEX", "AmericanExpress",
  241. * "American Express", "Discover", "Eurocard/MasterCard",
  242. * "Eurocard"
  243. *
  244. * @return bool TRUE if format is correct, FALSE otherwise
  245. * @access public
  246. * @static
  247. * @link http://www.pcisecuritystandards.org/
  248. */
  249. function cvv($cvv, $cardType)
  250. {
  251. switch (strtoupper($cardType)) {
  252. case 'MASTERCARD':
  253. case 'EUROCARD':
  254. case 'EUROCARD/MASTERCARD':
  255. case 'VISA':
  256. case 'VISA / VISA DEBIT':
  257. case 'DISCOVER':
  258. case 'LASER':
  259. case 'SWITCH':
  260. case 'MAESTRO':
  261. case 'SWITCH/MAESTRO':
  262. case 'MAESTRO/SWITCH':
  263. case 'SOLO':
  264. $digits = 3;
  265. break;
  266. case 'AMEX':
  267. case 'AMERICANEXPRESS':
  268. case 'AMERICAN EXPRESS':
  269. $digits = 4;
  270. break;
  271. default:
  272. return false;
  273. }
  274. if (strlen($cvv) == $digits
  275. && strspn($cvv, '0123456789') == $digits) {
  276. return true;
  277. }
  278. return false;
  279. }
  280. }
  281. ?>