helper.php 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. <?php
  2. declare(strict_types=1);
  3. use SixShop\Payment\Enum\NumberBizEnum;
  4. if (!function_exists('generate_number')) {
  5. /**
  6. * 生成20位数字编号
  7. * 格式:14位日期时间(YmdHis) + 2位业务码(00-99) + 3位随机数 + 1位校验位
  8. *
  9. * @param NumberBizEnum $bizCode 业务编码(0-99),1 订单号 2 订单支付
  10. * @return string 20位数字编号
  11. * @throws InvalidArgumentException 当业务码不在0-99范围时抛出
  12. */
  13. function generate_number(NumberBizEnum $bizCode): string
  14. {
  15. $bizCode = $bizCode->value;
  16. // 1. 校验业务码范围
  17. if ($bizCode < 0 || $bizCode > 99) {
  18. throw new InvalidArgumentException('业务码必须是0-99之间的整数');
  19. }
  20. // 2. 14位日期时间(年月日时分秒)
  21. $datetime = date('YmdHis');
  22. // 3. 2位业务码(自动补零)
  23. $bizPart = str_pad((string)$bizCode, 2, '0', STR_PAD_LEFT);
  24. // 4. 3位安全随机数
  25. $random = str_pad((string)random_int(0, 999), 3, '0', STR_PAD_LEFT);
  26. // 5. 组合前19位
  27. $prefix = $datetime . $bizPart . $random;
  28. // 6. 计算校验位(简单加权求和)
  29. $sum = 0;
  30. for ($i = 0; $i < 19; $i++) {
  31. $sum += $prefix[$i] * (($i % 2) ? 3 : 1);
  32. }
  33. $checkDigit = (10 - ($sum % 10)) % 10;
  34. return $prefix . $checkDigit;
  35. }
  36. }
  37. if (!function_exists('validate_order_number')) {
  38. /**
  39. * 验证订单号有效性
  40. */
  41. function validate_order_number(string $orderNo): bool
  42. {
  43. // 基础格式检查
  44. if (!preg_match('/^\d{20}$/', $orderNo)) {
  45. return false;
  46. }
  47. // 校验位验证
  48. $prefix = substr($orderNo, 0, 19);
  49. $check = substr($orderNo, -1);
  50. $sum = 0;
  51. for ($i = 0; $i < 19; $i++) {
  52. $sum += $prefix[$i] * (($i % 2) ? 3 : 1);
  53. }
  54. return ((10 - ($sum % 10)) % 10) == $check;
  55. }
  56. }