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

189 lines
6.2 KiB

  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use App\Models\Agent;
  4. use App\Models\AgentProduct;
  5. use App\Models\Order;
  6. use App\Models\Product;
  7. use App\Models\UserMoneyLog;
  8. use EasyWeChat\Factory;
  9. use EasyWeChat\Kernel\Exceptions\Exception;
  10. use EasyWeChat\Payment\Kernel\Exceptions\InvalidSignException;
  11. use Illuminate\Support\Facades\DB;
  12. use App\Service\OrderStatus;
  13. class WxpayController
  14. {
  15. //微信支付 支付结果通知网址
  16. public function notify()
  17. {
  18. // {"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"}
  19. $agent_id = request()->route('agent_id');
  20. $agent = Agent::find($agent_id);
  21. $config = config('wechat.payment.default');
  22. $config = array_merge($config, [
  23. 'app_id' => $agent->appid,
  24. 'mch_id' => $agent->mchid,
  25. 'key' => $agent->mchkey,
  26. ]);
  27. $app = Factory::payment($config);
  28. try {
  29. $response = $app->handlePaidNotify(function ($message, $fail) {
  30. // 请求成功
  31. if ($message['return_code'] === 'SUCCESS') {
  32. //订单号带有pay_type后缀,主要是为了区分定金支付和尾款支付,前24位才是真正的订单号
  33. $order_no = substr($message['out_trade_no'], 0, 24);
  34. $order = Order::query()
  35. ->where(['order_no' => $order_no])
  36. ->first();
  37. //已经处理过的订单直接返回true
  38. if ($order && in_array($order->status, [OrderStatus::PAID, OrderStatus::PAID_RETAINAGE])) {
  39. return true;
  40. }
  41. // 支付成功
  42. if ($message['result_code'] === 'SUCCESS') {
  43. DB::beginTransaction();
  44. try {
  45. $status = $order->status;
  46. $pay_type = $order->pay_type;
  47. //定金支付和首付款支付
  48. if (in_array($pay_type, [1, 2])) {
  49. if ($pay_type == OrderStatus::UNPAID) {
  50. $order->status = OrderStatus::PAY_EARNEST;
  51. } else if ($status == OrderStatus::PAY_EARNEST) {
  52. $order->status = OrderStatus::PAID_RETAINAGE;
  53. }
  54. } else if ($pay_type == 0) {
  55. $order->status = OrderStatus::PAID;
  56. }
  57. $money = $message['total_fee'] / 100;
  58. $order->paid_at = time();
  59. $order->paid_money = DB::raw('`paid_money` + ' . $money);
  60. $order->save();
  61. //增加销量,库存在拍下时已经减了
  62. AgentProduct::query()
  63. ->where('id', $order->agent_product_id)
  64. ->increment('sale', $order->num);
  65. Product::query()
  66. ->where('id', $order->product_id)
  67. ->increment('sale', $order->num);
  68. //资金流水
  69. UserMoneyLog::query()->create([
  70. 'user_id' => $order->user_id,
  71. 'agent_id' => $order->agent_id,
  72. 'money' => -$money,
  73. 'order_id' => $order->id,
  74. 'type' => 1,
  75. 'desc' => '购买产品:' . $order->title,
  76. 'created_at' => time(), //模型没有updated_at,无法自动写入时间
  77. ]);
  78. DB::commit();
  79. return true;
  80. } catch (Exception $e) {
  81. DB::rollBack();
  82. $fail('Unknown error');
  83. }
  84. } // 支付失败
  85. else if ($message['result_code'] === 'FAIL') {
  86. return true;
  87. }
  88. }
  89. // 希望微信重试
  90. $fail('Order not exists.');
  91. });
  92. } catch (InvalidSignException | Exception $e) {
  93. $time = time();
  94. $filename = storage_path('logs/wxpay_notify_') . date('Y-m-d-H', $time) . '.log';
  95. $data = '[' . date('Y-m-d H:i:s', $time) . ']' . PHP_EOL;
  96. $data .= '[message]:' . $e->getMessage() . $e->getFile() . $e->getLine() . PHP_EOL . PHP_EOL;
  97. file_put_contents($filename, $data, FILE_APPEND);
  98. return 'error';
  99. }
  100. return $response;
  101. }
  102. //退款通知
  103. public function refund()
  104. {
  105. // {"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"}
  106. $agent_id = request()->route('agent_id');
  107. $agent = Agent::find($agent_id);
  108. $config = config('wechat.payment.default');
  109. $config = array_merge($config, [
  110. 'app_id' => $agent->appid,
  111. 'mch_id' => $agent->mchid,
  112. 'key' => $agent->mchkey,
  113. ]);
  114. $app = Factory::payment($config);
  115. try {
  116. $response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail) {
  117. // 记录一下本地调试
  118. 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);
  119. // 请求成功
  120. if ($message['return_code'] === 'SUCCESS') {
  121. //订单号带有pay_type后缀,主要是为了区分定金支付和尾款支付,前24位才是真正的订单号
  122. $order_no = substr($message['out_trade_no'], 0, 24);
  123. $order = Order::query()
  124. ->where(['order_sn' => $order_no])
  125. ->first();
  126. // 退款成功
  127. if ($reqInfo['refund_status'] === 'SUCCESS') {
  128. DB::beginTransaction();
  129. try {
  130. $apply = RefundApply::query()
  131. ->where('refund_sn', $reqInfo['out_refund_no'])
  132. ->first();
  133. if (!$apply) {
  134. $fail('退款单没找到');
  135. }
  136. $apply->state = 2;
  137. $apply->save();
  138. $order->state = UserGoodsOrder::REFUNDED;
  139. $order->save();
  140. // 退库存
  141. GoodsSpecs::query()
  142. ->where([
  143. 'id' => $order->goods_specs_id,
  144. 'goods_id' => $order->goods_id,
  145. ])
  146. ->update([
  147. 'stock' => DB::raw('stock+' . $order->number . ''),
  148. ]);
  149. DB::commit();
  150. return true;
  151. } catch (\Exception $e) {
  152. DB::rollBack();
  153. $fail('Unknown error');
  154. }
  155. }
  156. }
  157. $fail('Unknown error');
  158. });
  159. } catch (Exception $e) {
  160. return 'error';
  161. }
  162. return $response;
  163. }
  164. }