PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/application/libraries/Zend/Validate/CreditCard.php

https://bitbucket.org/masnug/grc276-blog-laravel
PHP | 317 lines | 187 code | 32 blank | 98 comment | 27 complexity | 87f62596482df18965e18b631951c073 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Validate
  17. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: CreditCard.php 23775 2011-03-01 17:25:24Z ralph $
  20. */
  21. /**
  22. * @see Zend_Validate_Abstract
  23. */
  24. require_once 'Zend/Validate/Abstract.php';
  25. /**
  26. * @category Zend
  27. * @package Zend_Validate
  28. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_Validate_CreditCard extends Zend_Validate_Abstract
  32. {
  33. /**
  34. * Detected CCI list
  35. *
  36. * @var string
  37. */
  38. const ALL = 'All';
  39. const AMERICAN_EXPRESS = 'American_Express';
  40. const UNIONPAY = 'Unionpay';
  41. const DINERS_CLUB = 'Diners_Club';
  42. const DINERS_CLUB_US = 'Diners_Club_US';
  43. const DISCOVER = 'Discover';
  44. const JCB = 'JCB';
  45. const LASER = 'Laser';
  46. const MAESTRO = 'Maestro';
  47. const MASTERCARD = 'Mastercard';
  48. const SOLO = 'Solo';
  49. const VISA = 'Visa';
  50. const CHECKSUM = 'creditcardChecksum';
  51. const CONTENT = 'creditcardContent';
  52. const INVALID = 'creditcardInvalid';
  53. const LENGTH = 'creditcardLength';
  54. const PREFIX = 'creditcardPrefix';
  55. const SERVICE = 'creditcardService';
  56. const SERVICEFAILURE = 'creditcardServiceFailure';
  57. /**
  58. * Validation failure message template definitions
  59. *
  60. * @var array
  61. */
  62. protected $_messageTemplates = array(
  63. self::CHECKSUM => "'%value%' seems to contain an invalid checksum",
  64. self::CONTENT => "'%value%' must contain only digits",
  65. self::INVALID => "Invalid type given. String expected",
  66. self::LENGTH => "'%value%' contains an invalid amount of digits",
  67. self::PREFIX => "'%value%' is not from an allowed institute",
  68. self::SERVICE => "'%value%' seems to be an invalid creditcard number",
  69. self::SERVICEFAILURE => "An exception has been raised while validating '%value%'",
  70. );
  71. /**
  72. * List of allowed CCV lengths
  73. *
  74. * @var array
  75. */
  76. protected $_cardLength = array(
  77. self::AMERICAN_EXPRESS => array(15),
  78. self::DINERS_CLUB => array(14),
  79. self::DINERS_CLUB_US => array(16),
  80. self::DISCOVER => array(16),
  81. self::JCB => array(16),
  82. self::LASER => array(16, 17, 18, 19),
  83. self::MAESTRO => array(12, 13, 14, 15, 16, 17, 18, 19),
  84. self::MASTERCARD => array(16),
  85. self::SOLO => array(16, 18, 19),
  86. self::UNIONPAY => array(16, 17, 18, 19),
  87. self::VISA => array(16),
  88. );
  89. /**
  90. * List of accepted CCV provider tags
  91. *
  92. * @var array
  93. */
  94. protected $_cardType = array(
  95. self::AMERICAN_EXPRESS => array('34', '37'),
  96. self::DINERS_CLUB => array('300', '301', '302', '303', '304', '305', '36'),
  97. self::DINERS_CLUB_US => array('54', '55'),
  98. self::DISCOVER => array('6011', '622126', '622127', '622128', '622129', '62213',
  99. '62214', '62215', '62216', '62217', '62218', '62219',
  100. '6222', '6223', '6224', '6225', '6226', '6227', '6228',
  101. '62290', '62291', '622920', '622921', '622922', '622923',
  102. '622924', '622925', '644', '645', '646', '647', '648',
  103. '649', '65'),
  104. self::JCB => array('3528', '3529', '353', '354', '355', '356', '357', '358'),
  105. self::LASER => array('6304', '6706', '6771', '6709'),
  106. self::MAESTRO => array('5018', '5020', '5038', '6304', '6759', '6761', '6763'),
  107. self::MASTERCARD => array('51', '52', '53', '54', '55'),
  108. self::SOLO => array('6334', '6767'),
  109. self::UNIONPAY => array('622126', '622127', '622128', '622129', '62213', '62214',
  110. '62215', '62216', '62217', '62218', '62219', '6222', '6223',
  111. '6224', '6225', '6226', '6227', '6228', '62290', '62291',
  112. '622920', '622921', '622922', '622923', '622924', '622925'),
  113. self::VISA => array('4'),
  114. );
  115. /**
  116. * CCIs which are accepted by validation
  117. *
  118. * @var array
  119. */
  120. protected $_type = array();
  121. /**
  122. * Service callback for additional validation
  123. *
  124. * @var callback
  125. */
  126. protected $_service;
  127. /**
  128. * Constructor
  129. *
  130. * @param string|array $type OPTIONAL Type of CCI to allow
  131. */
  132. public function __construct($options = array())
  133. {
  134. if ($options instanceof Zend_Config) {
  135. $options = $options->toArray();
  136. } else if (!is_array($options)) {
  137. $options = func_get_args();
  138. $temp['type'] = array_shift($options);
  139. if (!empty($options)) {
  140. $temp['service'] = array_shift($options);
  141. }
  142. $options = $temp;
  143. }
  144. if (!array_key_exists('type', $options)) {
  145. $options['type'] = self::ALL;
  146. }
  147. $this->setType($options['type']);
  148. if (array_key_exists('service', $options)) {
  149. $this->setService($options['service']);
  150. }
  151. }
  152. /**
  153. * Returns a list of accepted CCIs
  154. *
  155. * @return array
  156. */
  157. public function getType()
  158. {
  159. return $this->_type;
  160. }
  161. /**
  162. * Sets CCIs which are accepted by validation
  163. *
  164. * @param string|array $type Type to allow for validation
  165. * @return Zend_Validate_CreditCard Provides a fluid interface
  166. */
  167. public function setType($type)
  168. {
  169. $this->_type = array();
  170. return $this->addType($type);
  171. }
  172. /**
  173. * Adds a CCI to be accepted by validation
  174. *
  175. * @param string|array $type Type to allow for validation
  176. * @return Zend_Validate_CreditCard Provides a fluid interface
  177. */
  178. public function addType($type)
  179. {
  180. if (is_string($type)) {
  181. $type = array($type);
  182. }
  183. foreach($type as $typ) {
  184. if (defined('self::' . strtoupper($typ)) && !in_array($typ, $this->_type)) {
  185. $this->_type[] = $typ;
  186. }
  187. if (($typ == self::ALL)) {
  188. $this->_type = array_keys($this->_cardLength);
  189. }
  190. }
  191. return $this;
  192. }
  193. /**
  194. * Returns the actual set service
  195. *
  196. * @return callback
  197. */
  198. public function getService()
  199. {
  200. return $this->_service;
  201. }
  202. /**
  203. * Sets a new callback for service validation
  204. *
  205. * @param unknown_type $service
  206. */
  207. public function setService($service)
  208. {
  209. if (!is_callable($service)) {
  210. require_once 'Zend/Validate/Exception.php';
  211. throw new Zend_Validate_Exception('Invalid callback given');
  212. }
  213. $this->_service = $service;
  214. return $this;
  215. }
  216. /**
  217. * Defined by Zend_Validate_Interface
  218. *
  219. * Returns true if and only if $value follows the Luhn algorithm (mod-10 checksum)
  220. *
  221. * @param string $value
  222. * @return boolean
  223. */
  224. public function isValid($value)
  225. {
  226. $this->_setValue($value);
  227. if (!is_string($value)) {
  228. $this->_error(self::INVALID, $value);
  229. return false;
  230. }
  231. if (!ctype_digit($value)) {
  232. $this->_error(self::CONTENT, $value);
  233. return false;
  234. }
  235. $length = strlen($value);
  236. $types = $this->getType();
  237. $foundp = false;
  238. $foundl = false;
  239. foreach ($types as $type) {
  240. foreach ($this->_cardType[$type] as $prefix) {
  241. if (substr($value, 0, strlen($prefix)) == $prefix) {
  242. $foundp = true;
  243. if (in_array($length, $this->_cardLength[$type])) {
  244. $foundl = true;
  245. break 2;
  246. }
  247. }
  248. }
  249. }
  250. if ($foundp == false){
  251. $this->_error(self::PREFIX, $value);
  252. return false;
  253. }
  254. if ($foundl == false) {
  255. $this->_error(self::LENGTH, $value);
  256. return false;
  257. }
  258. $sum = 0;
  259. $weight = 2;
  260. for ($i = $length - 2; $i >= 0; $i--) {
  261. $digit = $weight * $value[$i];
  262. $sum += floor($digit / 10) + $digit % 10;
  263. $weight = $weight % 2 + 1;
  264. }
  265. if ((10 - $sum % 10) % 10 != $value[$length - 1]) {
  266. $this->_error(self::CHECKSUM, $value);
  267. return false;
  268. }
  269. if (!empty($this->_service)) {
  270. try {
  271. require_once 'Zend/Validate/Callback.php';
  272. $callback = new Zend_Validate_Callback($this->_service);
  273. $callback->setOptions($this->_type);
  274. if (!$callback->isValid($value)) {
  275. $this->_error(self::SERVICE, $value);
  276. return false;
  277. }
  278. } catch (Zend_Exception $e) {
  279. $this->_error(self::SERVICEFAILURE, $value);
  280. return false;
  281. }
  282. }
  283. return true;
  284. }
  285. }