You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
1.7 KiB

3 years ago
  1. <?php
  2. namespace App\Helper;
  3. class TransactionCodeHelper
  4. {
  5. private const VALID_CHARS = [
  6. '2',
  7. '3',
  8. '4',
  9. '5',
  10. '6',
  11. '7',
  12. '8',
  13. '9',
  14. 'A',
  15. 'B',
  16. 'C',
  17. 'D',
  18. 'E',
  19. 'F',
  20. 'G',
  21. 'H',
  22. 'J',
  23. 'K',
  24. 'L',
  25. 'M',
  26. 'N',
  27. 'P',
  28. 'Q',
  29. 'R',
  30. 'S',
  31. 'T',
  32. 'U',
  33. 'V',
  34. 'W',
  35. 'X',
  36. 'Y',
  37. 'Z',
  38. ];
  39. private const FACTOR = 2;
  40. /**
  41. * Validate the transaction code
  42. *
  43. * @param $key string
  44. * @return bool
  45. */
  46. public static function verifyKey(string $key): bool
  47. {
  48. if (strlen($key) !== 10) {
  49. return false;
  50. }
  51. $checkDigit = self::generateCheckCharacter(strtoupper(substr($key, 0, 9)));
  52. return $key[9] === $checkDigit;
  53. }
  54. /**
  55. * generate the check character that should correspond to the last letter of the string
  56. *
  57. * @param $input
  58. * @return string
  59. */
  60. public static function generateCheckCharacter(string $input): string
  61. {
  62. $factor = self::FACTOR;
  63. $sum = 0;
  64. $n = count(self::VALID_CHARS);
  65. for ($i = strlen($input) - 1; $i >= 0; $i--) {
  66. $code_point = array_search($input[$i], self::VALID_CHARS, true);
  67. $addend = $factor * $code_point;
  68. $factor = ($factor === 2) ? 1 : 2;
  69. $addend = ($addend / $n) + ($addend % $n);
  70. $sum += $addend;
  71. }
  72. $remainer = ($sum % $n);
  73. $checkCodePoint = ($n - $remainer) % $n;
  74. return self::VALID_CHARS[$checkCodePoint];
  75. }
  76. }