F2Fpay.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. namespace App\Utils\Payments;
  3. use App\Models\Payment;
  4. use App\Utils\Library\AlipayF2F;
  5. use App\Utils\Library\PaymentHelper;
  6. use App\Utils\Library\Templates\Gateway;
  7. use Exception;
  8. use Illuminate\Http\JsonResponse;
  9. use Illuminate\Http\Request;
  10. use Log;
  11. class F2FPay implements Gateway
  12. {
  13. private static AlipayF2F $aliClient;
  14. public function __construct()
  15. {
  16. self::$aliClient = new AlipayF2F([
  17. 'app_id' => sysConfig('f2fpay_app_id'),
  18. 'ali_public_key' => sysConfig('f2fpay_public_key'),
  19. 'rsa_private_key' => sysConfig('f2fpay_private_key'),
  20. 'notify_url' => route('payment.notify', ['method' => 'f2fpay']),
  21. ]);
  22. }
  23. public static function metadata(): array
  24. {
  25. return [
  26. 'key' => 'f2fpay',
  27. 'method' => ['ali'],
  28. 'settings' => [
  29. 'f2fpay_app_id' => null,
  30. 'f2fpay_private_key' => null,
  31. 'f2fpay_public_key' => null,
  32. ],
  33. ];
  34. }
  35. public function purchase(Request $request): JsonResponse
  36. {
  37. $payment = PaymentHelper::createPayment(auth()->id(), $request->input('id'), $request->input('amount'));
  38. $data = [
  39. 'subject' => sysConfig('subject_name') ?: sysConfig('website_name'),
  40. 'out_trade_no' => $payment->trade_no,
  41. 'total_amount' => $payment->amount,
  42. ];
  43. try {
  44. $result = self::$aliClient->qrCharge($data);
  45. $payment->update(['qr_code' => 1, 'url' => $result['qr_code']]);
  46. } catch (Exception $e) {
  47. Log::alert('【支付宝当面付】支付错误: '.$e->getMessage());
  48. $payment->failed();
  49. exit;
  50. }
  51. return response()->json(['status' => 'success', 'data' => $payment->trade_no, 'message' => trans('user.payment.order_creation.success')]);
  52. }
  53. public function notify(Request $request): void
  54. {
  55. try {
  56. if (sysConfig('f2fpay_app_id') === $request->input('app_id') && self::$aliClient->validate_notification_sign($request->except('method'), $request->input('sign'))) {
  57. $payment = Payment::whereTradeNo($request->input('out_trade_no'))->with('order')->first();
  58. if ($payment && abs($payment->amount - $request->input('total_amount')) < 0.01 && in_array($request->input('trade_status'), ['TRADE_FINISHED', 'TRADE_SUCCESS']) && PaymentHelper::paymentReceived($request->input('out_trade_no'))) {
  59. exit('success');
  60. }
  61. }
  62. Log::error('【支付宝当面付】异步验证失败,尝试订单查询');
  63. if ($this->capture($request->input('out_trade_no'), $request->input('trade_no'))) {
  64. exit('success');
  65. }
  66. Log::notice('【支付宝当面付】异步验证失败:'.var_export($request->all(), true));
  67. } catch (Exception $e) {
  68. Log::alert('【支付宝当面付】回调信息错误: '.$e->getMessage());
  69. exit;
  70. }
  71. // 返回验证结果
  72. exit('fail');
  73. }
  74. public function capture(?string $trade_no = null, ?string $ali_trade_no = null): bool
  75. {
  76. $result = self::$aliClient->tradeQuery(array_filter([
  77. 'out_trade_no' => $trade_no,
  78. 'trade_no' => $ali_trade_no,
  79. ]));
  80. if ($result['code'] === '10000' && $result['msg'] === 'Success') {
  81. if ($result['out_trade_no'] && in_array($result['trade_status'], ['TRADE_FINISHED', 'TRADE_SUCCESS'])) {
  82. if (PaymentHelper::paymentReceived($result['out_trade_no'])) {
  83. return true;
  84. }
  85. Log::error('【支付宝当面付】收单交易订单结算失败:'.var_export($result, true));
  86. return false;
  87. }
  88. } else {
  89. Log::error('【支付宝当面付】收单交易查询失败:'.var_export($result, true));
  90. }
  91. return false;
  92. }
  93. }