lockForUpdate()->first(); if ($payLog === null) { throw new InvalidPaySerialNumberException(); } return $this->handleSuccess($payLog, $params); } /** * 处理支付成功业务 * * @param \App\Models\PayLog $payLog * @param array $params * @return \App\Models\PayLog * * @throws \App\Exceptions\BizException * @throws \App\Exceptions\InvalidPaySerialNumberException */ public function handleSuccess(PayLog $payLog, array $params = []): PayLog { if (! $payLog->isPending()) { throw new InvalidPaySerialNumberException(); } $payLog->update([ 'pay_at' => $params['pay_at'] ?? now(), 'out_trade_no' => $params['out_trade_no'] ?? null, 'status' => PayLog::STATUS_SUCCESS, ]); $payable = $payLog->payable; $userId = null; if ($payable instanceof Order) { if ($payable->isPaid()) { throw new BizException('订单已支付'); } if ($payable->isCompleted()) { throw new BizException('订单已完成'); } $userId = $payable->user_id; $payable->update([ 'pay_sn' => $payLog->pay_sn, 'pay_way' => $payLog->pay_way, 'pay_at' => $payLog->pay_at, 'out_trade_no' => $payLog->out_trade_no, 'status' => Order::STATUS_PAID, ]); } elseif ($payable instanceof OfflineOrder) { if ($payable->isPaid()) { throw new BizException('订单已支付'); } elseif ($payable->isRevoked()) { throw new BizException('订单取消'); } $userId = $payable->user_id; OfflineOrderService::make()->paySuccess($payable, [ 'payment_sn' => $payLog->pay_sn, 'payment_method' => $payLog->pay_way, 'payment_time' => $payLog->pay_at, 'out_trade_no' => $payLog->out_trade_no, 'status' => OfflineOrderStatus::Paid, ]); } elseif ($payable instanceof \App\Models\UserVip) { $userId = $payable->user_id; (new \App\Services\VipService())->success($payable, ['pay_at' => $payLog->pay_at]); } // TODO 延迟1分钟执行, 不然会出现错误信息: (10060001)支付单不存在 // TODO 订单支付成功, 调用发货信息API // try { // if (!$userId) { // throw new BizException("未找到userId"); // } // $socialite = SocialiteUser::where('user_id', $userId)->where('socialite_type', SocialiteType::WechatMiniProgram)->first(); // if (!$socialite) { // throw new BizException("未找到 SocialiteUser 记录, userId: " . $userId); // } // $openid = $socialite->socialite_id; // if (!$openid) { // throw new BizException("未找到 openid, userId: " . $userId); // } // $data = [ // "order_key" => [ // // "mchid" => config("wechat.payment.sub.mch_id"), // // "out_trade_no" => $payLog->pay_sn, // "order_number_type" => 2, // "transaction_id" => $payLog->out_trade_no, // ], // "logistics_type" => 4, // "delivery_mode" => 1, // "shipping_list" => [ // ["item_desc" => "定制服务"] // ], // "upload_time" => $payLog->pay_at->format('Y-m-d\TH:i:s.vP'), // "payer" => [ // "openid" => $openid // ] // ]; // WxMpService::make()->uploadShippingInfo($data); // } catch (\Exception $e) { // logger()->error("微信小程序-发货信息录入, " . $e->getMessage(), ['pay_log_id' => $payLog->id]); // } return $payLog; } /** * 根据支付流水号处理支付失败业务 * * @param string $sn * @param array $params * @return \App\Models\PayLog * * @throws \App\Exceptions\BizException * @throws \App\Exceptions\InvalidPaySerialNumberException */ public function handleFailedByPaySerialNumber(string $paySerialNumber, array $params = []): PayLog { $payLog = PayLog::where('pay_sn', $paySerialNumber)->lockForUpdate()->first(); if ($payLog === null) { throw new InvalidPaySerialNumberException(); } return $this->handleFailed($payLog, $params); } /** * 处理支付失败业务 * * @param \App\Models\PayLog $payLog * @param array $params * @return \App\Models\PayLog * * @throws \App\Exceptions\BizException * @throws \App\Exceptions\InvalidPaySerialNumberException */ public function handleFailed(PayLog $payLog, array $params = []): PayLog { if (! $payLog->isPending()) { throw new InvalidPaySerialNumberException(); } $payLog->update([ 'out_trade_no' => $params['out_trade_no'] ?? null, 'status' => PayLog::STATUS_FAILED, 'failed_reason' => $params['failed_reason'] ?? null, ]); return $payLog; } }