海南旅游SAAS
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.

149 lines
4.6 KiB

  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use App\Http\Controllers\Controller;
  4. use App\Models\Order;
  5. use EasyWeChat\Factory;
  6. use EasyWeChat\Kernel\Exceptions\Exception;
  7. use Illuminate\Support\Facades\DB;
  8. use App\Service\OrderStatus;
  9. class WxpayController extends Controller
  10. {
  11. //微信支付 支付结果通知网址
  12. public function notify()
  13. {
  14. // {"sign": "3F99E6044C503B0E0131F95A1410B630", "appid": "wxb35ef055a4dd8ad4", "mch_id": "1606181693", "openid": "oBYj55W0gLv5MYUnsYUuJfzYzmsg", "cash_fee": "1", "fee_type": "CNY", "time_end": "20210623222330", "bank_type": "OTHERS", "nonce_str": "60d343d820e94", "total_fee": "1", "trade_type": "JSAPI", "result_code": "SUCCESS", "return_code": "SUCCESS", "is_subscribe": "N", "out_trade_no": "2842908479209865216", "transaction_id": "4200001210202106237487333085"}
  15. $config = config('wechat.payment.default');
  16. $app = Factory::payment($config);
  17. try {
  18. $response = $app->handlePaidNotify(function ($message, $fail) {
  19. // 请求成功
  20. if ($message['return_code'] === 'SUCCESS') {
  21. $order = Order::query()
  22. ->where(['order_no' => $message['out_trade_no']])
  23. ->first();
  24. //已经处理过的订单直接返回true
  25. if ($order && $order->paid_at) {
  26. return true;
  27. }
  28. // 支付成功
  29. if ($message['result_code'] === 'SUCCESS') {
  30. DB::beginTransaction();
  31. try {
  32. //TODO 需要判断尾款和全款
  33. $order->status = OrderStatus::PAID;
  34. $order->paid_at = time();
  35. $snowflake = resolve('snowflake');
  36. $confirmCode = $snowflake->id(); // TODO 这个码太长后续可以找方案搞短些
  37. $order->confirm_code = isset($params['platform:']) && $params['platform']
  38. ? $params['platform:'] . '|' . $confirmCode
  39. : $confirmCode;
  40. $order->save();
  41. // 计算销量
  42. GoodsSpecs::query()
  43. ->where([
  44. 'id' => $order->goods_specs_id,
  45. 'goods_id' => $order->goods_id,
  46. ])
  47. ->update([
  48. 'sold_stock' => DB::raw('sold_stock+' . $order->number . ''),
  49. ]);
  50. DB::commit();
  51. return true;
  52. } catch (\Exception $e) {
  53. DB::rollBack();
  54. $fail('Unknown error');
  55. }
  56. } // 支付失败
  57. elseif ($message['result_code'] === 'FAIL') {
  58. $order->state = UserGoodsOrder::PAID_FAIL;
  59. $order->save();
  60. return true;
  61. }
  62. }
  63. // 希望微信重试
  64. $fail('Order not exists.');
  65. });
  66. } catch (Exception $e) {
  67. $time = time();
  68. $filename = storage_path('/wxpay/notify/') . date('Y-m-d-H', $time) . '.log';
  69. $data = '[' . date('Y-m-d H:i:s', $time) . ']' . PHP_EOL;
  70. $data .= '[message]:' . $e->getMessage() . PHP_EOL . PHP_EOL;
  71. file_put_contents($filename, $data, FILE_APPEND);
  72. }
  73. return $response;
  74. }
  75. //退款通知
  76. public function refund()
  77. {
  78. // {"sign": "3F99E6044C503B0E0131F95A1410B630", "appid": "wxb35ef055a4dd8ad4", "mch_id": "1606181693", "openid": "oBYj55W0gLv5MYUnsYUuJfzYzmsg", "cash_fee": "1", "fee_type": "CNY", "time_end": "20210623222330", "bank_type": "OTHERS", "nonce_str": "60d343d820e94", "total_fee": "1", "trade_type": "JSAPI", "result_code": "SUCCESS", "return_code": "SUCCESS", "is_subscribe": "N", "out_trade_no": "2842908479209865216", "transaction_id": "4200001210202106237487333085"}
  79. $config = config('wechat.payment.default');
  80. $app = Factory::payment($config);
  81. $response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail) {
  82. // 记录一下本地调试
  83. file_put_contents(storage_path('/wxpay/refund'.date('Y-m-d-H').'.log'), date('Y-m-d H:i:s').PHP_EOL.json_encode($message).PHP_EOL.json_encode($reqInfo), FILE_APPEND);
  84. // 请求成功
  85. if ($message['return_code'] === 'SUCCESS') {
  86. $order = UserGoodsOrder::query()
  87. ->where(['order_sn' => $reqInfo['out_trade_no']])
  88. ->first();
  89. // 退款成功
  90. if ($reqInfo['refund_status'] === 'SUCCESS') {
  91. DB::beginTransaction();
  92. try {
  93. $apply = RefundApply::query()
  94. ->where('refund_sn', $reqInfo['out_refund_no'])
  95. ->first();
  96. if (!$apply) {
  97. $fail('退款单没找到');
  98. }
  99. $apply->state = 2;
  100. $apply->save();
  101. $order->state = UserGoodsOrder::REFUNDED;
  102. $order->save();
  103. // 退库存
  104. GoodsSpecs::query()
  105. ->where([
  106. 'id' => $order->goods_specs_id,
  107. 'goods_id' => $order->goods_id,
  108. ])
  109. ->update([
  110. 'stock' => DB::raw('stock+'.$order->number.''),
  111. ]);
  112. DB::commit();
  113. return true;
  114. } catch (\Exception $e) {
  115. DB::rollBack();
  116. $fail('Unknown error');
  117. }
  118. }
  119. }
  120. $fail('Unknown error');
  121. });
  122. return $response;
  123. }
  124. }