route('agent_id'); $agent = Agent::find($agent_id); $config = config('wechat.payment.default'); $config = array_merge($config, [ 'app_id' => $agent->appid, 'mch_id' => $agent->mchid, 'key' => $agent->mchkey, ]); $app = Factory::payment($config); try { $response = $app->handlePaidNotify(function ($message, $fail) { //TODO 仅测试用 DB::table('pay_debugs')->insert(['content' => json_encode($message)]); $this->log($message); // 请求成功 if ($message['return_code'] === 'SUCCESS') { //主要是为了区分定金支付和尾款支付,订单号带有-status后缀,分割后前面才是真正的订单号 list($order_no, $status) = explode('-', $message['out_trade_no']); $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 { $status = $order->status; $pay_type = $order->pay_type; $money = $message['total_fee'] / 100; //定金支付和首付款支付 if (in_array($pay_type, [PayType::SUBSCRIPTION, PayType::DEPOSIT, PayType::DOWN_PAYMENT])) { if ($status == OrderStatus::UNPAID) { $order->status = OrderStatus::PAY_EARNEST; } else if ($status == OrderStatus::PAY_EARNEST) { //只有支付的金额大于等于订单总价,才将订单状态修改为PAID_RETAINAGE if ($order->paid_money + $money >= $order->price) { $order->status = OrderStatus::PAID_RETAINAGE; } } } else if ($pay_type == 0) { $order->status = OrderStatus::PAID; } //支付金额>=订单金额之后生成核销码 if ($order->paid_money + $money >= $order->price) { $order->verify_code = uniqid(); //生成核销码 } $order->paid_at = now(); $order->paid_money = DB::raw('`paid_money` + ' . $money); $order->save(); //增加销量,库存在拍下时已经减了 AgentProduct::query() ->where('id', $order->agent_product_id) ->increment('sale', $order->num); Product::query() ->where('id', $order->product_id) ->increment('sale', $order->num); //资金流水 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,无法自动写入时间 ]); 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 $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); $config = config('wechat.payment.default'); $config = array_merge($config, [ 'app_id' => $agent->appid, 'mch_id' => $agent->mchid, 'key' => $agent->mchkey, ]); $app = Factory::payment($config); try { $response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail) { // 记录一下本地调试 $this->log(['message' => $message, 'reqInfo' => $reqInfo], 'refund'); // 请求成功 if ($message['return_code'] === 'SUCCESS') { //主要是为了区分定金支付和尾款支付,订单号带有-status后缀,分割后前面才是真正的订单号 list($order_no, $status) = explode('-', $message['out_trade_no']); $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,无法自动写入时间 ]); // 退库存 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 $e) { 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); } }