PaymentHelper.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <?php
  2. namespace App\Utils\Library;
  3. use App\Events\PaymentStatusUpdated;
  4. use App\Models\Payment;
  5. use App\Models\PaymentCallback;
  6. use App\Notifications\PaymentReceived;
  7. use Str;
  8. class PaymentHelper
  9. {
  10. /**
  11. * MD5验签.
  12. *
  13. * @param array $data 未加密的数组信息
  14. * @param string $key 密钥
  15. * @param string $signature 加密的签名
  16. * @param bool $filter 是否清理空值
  17. */
  18. public static function verify(array $data, string $key, string $signature, bool $filter = true): bool
  19. {
  20. return hash_equals(self::aliStyleSign($data, $key, $filter), $signature);
  21. }
  22. /**
  23. * Alipay式数据MD5签名.
  24. *
  25. * @param array $data 需要加密的数组
  26. * @param string $key 尾部的密钥
  27. * @param bool $filter 是否清理空值
  28. * @return string md5加密后的数据
  29. */
  30. public static function aliStyleSign(array $data, string $key, bool $filter = true): string
  31. { // 依据: https://opendocs.alipay.com/open/common/104741
  32. unset($data['sign'], $data['sign_type']); // 剃离sign, sign_type
  33. if ($filter) {
  34. $data = array_filter($data); // 剃离空值
  35. }
  36. ksort($data, SORT_STRING); // 排序
  37. return md5(urldecode(http_build_query($data)).$key); // 拼接
  38. }
  39. /**
  40. * @param int $uid 用户ID
  41. * @param int $oid 订单ID
  42. * @param float|int $amount 交易金额
  43. */
  44. public static function createPayment(int $uid, int $oid, float|int $amount): Payment
  45. {
  46. $payment = new Payment;
  47. $payment->trade_no = Str::random(8);
  48. $payment->user_id = $uid;
  49. $payment->order_id = $oid;
  50. $payment->amount = $amount;
  51. $payment->save();
  52. return $payment;
  53. }
  54. /**
  55. * @param string $trade_no 本地订单号
  56. * @param string $out_trade_no 外部订单号
  57. * @param float|int $amount 交易金额
  58. */
  59. public static function createPaymentCallback(string $trade_no, string $out_trade_no, float|int $amount): bool
  60. {
  61. $log = new PaymentCallback;
  62. $log->trade_no = $trade_no;
  63. $log->out_trade_no = $out_trade_no;
  64. $log->amount = $amount;
  65. return $log->save();
  66. }
  67. /**
  68. * @param string $tradeNo 本地订单号
  69. */
  70. public static function paymentReceived(string $tradeNo): bool
  71. {
  72. $payment = Payment::whereTradeNo($tradeNo)->with('order')->first();
  73. if ($payment) {
  74. $ret = $payment->order->complete();
  75. if ($ret) {
  76. $payment->user->notify(new PaymentReceived($payment->order->sn, $payment->amount_tag));
  77. broadcast(new PaymentStatusUpdated($tradeNo, 'success', trans('common.success_item', ['attribute' => trans('user.pay')]))); // 触发支付状态更新事件
  78. }
  79. return $ret;
  80. }
  81. return false;
  82. }
  83. }