$setting['payee_appid'], 'mch_id' => $setting['payee_mchid'], 'key' => $setting['payee_mchkey'], ]; $this->app = Factory::payment($config); } //微信支付 支付结果通知网址 public function notify() { $agent_id = request()->route('agent_id'); // $agent = Agent::find($agent_id); try { $response = $this->app->handlePaidNotify(function ($message, $fail) use ($agent_id) { //仅测试用,回调记录 DB::table('pay_debugs')->insert(['agent_id' => $agent_id, 'type' => 1, 'content' => json_encode($message)]); // $this->log($message); // 请求成功 if ($message['return_code'] === 'SUCCESS') { //主要是为了区分定金支付和尾款支付,订单号带有-status后缀,分割后前面才是真正的订单号 $order_no = explode('-', $message['out_trade_no'])[0]; $order = Order::query() ->where(['order_no' => $order_no]) ->first(); //已经处理过的订单直接返回true if ($order && in_array($order->status, [OrderStatus::PAID, OrderStatus::PAID_RETAINAGE, OrderStatus::SUCCESS])) { return true; } //判断该微信支付订单号有没有处理过 $exist_log = UserMoneyLog::where([ 'user_id' => $order->user_id, 'order_id' => $order->id, 'type' => 1, 'transaction_id' => $message['transaction_id'], ])->first(); if ($exist_log) { return true; } // 支付成功 if ($message['result_code'] === 'SUCCESS') { DB::beginTransaction(); try { //增加销量,库存在拍下时已经减了 $agent_product = AgentProduct::find($order->agent_product_id); $agent_product->increment('sale', $order->num); if ($order->product_id) { //兼容代理商自营产品 Product::query() ->where('id', $order->product_id) ->increment('sale', $order->num); } $status = $order->status; $pay_type = $order->pay_type; $money = $message['total_fee'] / 100; //定金支付和首付款支付 if (in_array($pay_type, [PayType::DEPOSIT_PAY, PayType::EARNEST_PAY, PayType::DOWN_PAYMENT])) { if ($status == OrderStatus::UNPAID) { $order->status = OrderStatus::PAY_EARNEST; } else if ($status == OrderStatus::PAY_EARNEST) { $order->status = OrderStatus::PAID_RETAINAGE; $order->verify_code = uniqid(); //生成核销码 } } else if ($pay_type == PayType::ONLINE) { $order->status = OrderStatus::PAID; $order->verify_code = uniqid(); //生成核销码 } $order->paid_at = now(); $order->paid_money = DB::raw('`paid_money` + ' . $money); //如果是已付定金,重新设置超时时间,否则清除超时时间 if ($order->status == OrderStatus::PAY_EARNEST) { if ($pay_type == PayType::DEPOSIT_PAY || $pay_type == PayType::EARNEST_PAY) { //订金超时 $time = $order->prepay_timeout * 60; } if (empty($time)) { //默认订单超时 $time = (AgentSetting::val($agent_id, 'order_timeout') ?? 60) * 60; } $order->timeout = date('Y-m-d H:i:s', time() + $time); //订单超时 OrderTimeout::dispatch($order->order_no,$time); //尾款通知时间 默认为剩余三小时自动通知 $smsEarnest = env('SMS_EARNEST',60*60*24*3); //短信通知 if(env('SMS_SWITCH' , '') == true && $time > $smsEarnest) { //如果剩余时间大于三小时 在订单到期前三小时给用户发短信 if ($time > $smsEarnest) { BalanceDue::dispatch($order->order_no,$time - $smsEarnest); } } } else { $order->timeout = null; } $order->save(); //资金流水 UserMoneyLog::query()->create([ 'user_id' => $order->user_id, 'agent_id' => $order->agent_id, 'money' => $money, 'order_id' => $order->id, 'type' => 1, 'desc' => DB::raw("LEFT('购买产品:{$order->title}', 250)"), 'transaction_id' => $message['transaction_id'], //微信支付订单号 'created_at' => now(), //模型没有updated_at,无法自动写入时间 'out_trade_no' => $message['out_trade_no'] ?? '', ]); DB::commit(); return true; } catch (Exception $e) { DB::rollBack(); $fail('Unknown error'); } } // 支付失败 else if ($message['result_code'] === 'FAIL') { return true; } } // 希望微信重试 $fail('Unknown error 2'); }); } catch (InvalidSignException | Exception | \Exception $e) { $this->log($e->getMessage() . $e->getFile() . $e->getLine()); return 'error'; } return $response; } //退款通知 public function refund() { $agent_id = request()->route('agent_id'); // $agent = Agent::find($agent_id); try { $response = $this->app->handleRefundedNotify(function ($message, $reqInfo, $fail) use ($agent_id) { //仅测试用,回调记录 DB::table('pay_debugs')->insert(['agent_id' => $agent_id, 'type' => 2, 'content' => json_encode($message)]); // 记录一下本地调试 // $this->log(['message' => $message, 'reqInfo' => $reqInfo], 'refund'); // 请求成功 if ($message['return_code'] === 'SUCCESS') { //主要是为了区分定金支付和尾款支付,订单号带有-status后缀,分割后前面才是真正的订单号 $order_no = explode('-', $reqInfo['out_trade_no'])[0]; $order = Order::query() ->where(['order_no' => $order_no]) ->first(); //如果已经处理过则不再处理 if ($order->status == OrderStatus::REFUNDED) { return true; } //如果已经存在相关的退款记录,也不再处理 $exist_log = UserMoneyLog::where([ 'user_id' => $order->user_id, 'order_id' => $order->id, 'type' => 2, 'transaction_id' => $reqInfo['transaction_id'], ])->first(); if ($exist_log) { return true; } $log = UserMoneyLog::query() ->where([ 'user_id' => $order->user_id, 'order_id' => $order->id, 'type' => 1, 'transaction_id' => $reqInfo['transaction_id'], ])->first(); if (!$log) { $fail('找不到交易信息'); } // 退款成功 if ($reqInfo['refund_status'] === 'SUCCESS') { DB::beginTransaction(); try { //更新订单状态为退款成功 $order->status = OrderStatus::REFUNDED; $order->save(); //记录日志 UserMoneyLog::create([ 'user_id' => $order->user_id, 'agent_id' => $order->agent_id, 'money' => -$reqInfo['settlement_refund_fee'] / 100, 'order_id' => $order->id, 'type' => 2, 'desc' => DB::raw("LEFT('退款:{$order->title}', 250)"), 'transaction_id' => $reqInfo['transaction_id'], 'created_at' => now(), //模型没有updated_at,无法自动写入时间 ]); // 退库存 if ($order->product_id) { Product::query() ->where('id', $order->product_id) ->increment('stock', $order->num); } DB::commit(); return true; } catch (\Exception $e) { DB::rollBack(); $fail('Unknown error'); } } } $fail('Unknown error 2'); }); } catch (Exception | \Exception $e) { $this->log($e->getMessage() . $e->getFile() . $e->getLine()); return 'error'; } return $response; } //保存消息,用于调试 private function log($write_data, $type = 'notify') { $dir = storage_path('wxpay'); if (!is_dir($dir)) { mkdir($dir); } $filename = $dir . '/' . $type . '_' . date('Y-m-d-H') . '.log'; $data = '[' . date('Y-m-d H:i:s') . ']' . PHP_EOL; $data .= '[message]: ' . (is_array($write_data) ? json_encode($write_data) : $write_data) . PHP_EOL . PHP_EOL; file_put_contents($filename, $data, FILE_APPEND); } /** * 行业产品支付回调 */ public function IndustryProductNotify() { try { $response = $this->app->handlePaidNotify(function ($message, $fail) { //仅测试用,回调记录 DB::table('pay_debugs')->insert(['agent_id' => -1, 'type' => 1, 'content' => json_encode($message)]); // 请求成功 if ($message['return_code'] === 'SUCCESS') { //主要是为了区分定金支付和尾款支付,订单号带有-status后缀,分割后前面才是真正的订单号 $order_no = explode('-', $message['out_trade_no'])[0]; $order = IndustryOrder::query() ->where(['order_no' => $order_no]) ->first(); //已经处理过的订单直接返回true if ($order && in_array($order->status, [OrderStatus::PAID, OrderStatus::PAID_RETAINAGE, OrderStatus::SUCCESS])) { return true; } //判断该微信支付订单号有没有处理过 $exist_log = IndustryPayLog::where([ 'agent_id' => $order->agent_id, 'supplier_id' => $order->supplier_id, 'industry_order_id' => $order->id, 'type' => 1, 'transaction_id' => $message['transaction_id'], ])->first(); if ($exist_log) { return true; } // 支付成功 if ($message['result_code'] === 'SUCCESS') { DB::beginTransaction(); try { //增加销量,库存在拍下时已经减了 IndustryProduct::query() ->where('id', $order->industry_product_id) ->increment('sale', $order->num); $old_status = $order->status; $pay_type = $order->pay_type; $money = $message['total_fee'] / 100; //定金支付和首付款支付 if (in_array($pay_type, [PayType::DEPOSIT_PAY, PayType::EARNEST_PAY, PayType::DOWN_PAYMENT])) { if ($old_status == OrderStatus::UNPAID) { $order->status = OrderStatus::PAY_EARNEST; } else if ($old_status == OrderStatus::PAY_EARNEST) { $order->status = OrderStatus::PAID_RETAINAGE; $order->verify_code = uniqid(); //生成核销码 } } else if ($pay_type == PayType::ONLINE) { $order->status = OrderStatus::PAID; $order->verify_code = uniqid(); //生成核销码 } $order->paid_at = now(); $order->paid_money = DB::raw('`paid_money` + ' . $money); $order->timeout = null; $order->save(); //资金流水 IndustryPayLog::create([ 'agent_id' => $order->agent_id, 'supplier_id' => $order->supplier_id, 'money' => $money, 'industry_order_id' => $order->id, 'type' => 1, 'desc' => DB::raw("LEFT('购买产品:{$order->title}', 250)"), 'transaction_id' => $message['transaction_id'], //微信支付订单号 'created_at' => now(), //模型没有updated_at,无法自动写入时间 'out_trade_no' => $message['out_trade_no'] ?? '', ]); DB::commit(); return true; } catch (Exception $e) { DB::rollBack(); $fail('Unknown error'); } } // 支付失败 else if ($message['result_code'] === 'FAIL') { return true; } } // 希望微信重试 $fail('Unknown error 2'); }); } catch (InvalidSignException | Exception | \Exception $e) { LOG::debug('行业产品支付:', [$e->getFile(), $e->getLine(), $e->getMessage()]); return 'error'; } return $response; } /** * 商家入驻支付回调 */ public function SettledNotify() { try { $response = $this->app->handlePaidNotify(function ($message, $fail) { //仅测试用,回调记录 DB::table('pay_debugs')->insert(['agent_id' => -2, 'type' => 1, 'content' => json_encode($message)]); // 请求成功 if ($message['return_code'] === 'SUCCESS') { $order_no = $message['out_trade_no']; $order = SettledOrder::query()->where(['order_no' => $order_no])->first(); //已经处理过的订单直接返回true if ($order && $order->status == 1) { return true; } // 支付成功 if ($message['result_code'] === 'SUCCESS') { try { $order->transaction_id = $message['transaction_id']; $order->paid_money = $message['total_fee'] / 100; $order->paid_at = now(); $order->status = 1; $order->save(); return true; } catch (Exception $e) { $fail('Unknown error'); } } // 支付失败 else if ($message['result_code'] === 'FAIL') { return true; } } // 希望微信重试 $fail('Unknown error 2'); }); } catch (Exception | \Exception $e) { LOG::debug('商家入驻支付回调:', [$e->getFile(), $e->getLine(), $e->getMessage()]); return 'error'; } return $response; } }