From 66641f8a05543c66165827957b989929be001db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=AF=E4=B9=90=E5=8A=A0=E5=86=B0?= <11869599+addie66@user.noreply.gitee.com> Date: Fri, 9 Oct 2026 13:01:01 +0800 Subject: [PATCH] =?UTF-8?q?```=20feat(shopro=5Fwechat=5Ftrade):=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=87=8D=E6=96=B0=E5=90=8C=E6=AD=A5=E7=89=A9?= =?UTF-8?q?=E6=B5=81=E4=BF=A1=E6=81=AF=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 ResyncShipping 命令,支持强制重新上传微信物流信息, 不依赖 sync 表的 failed/pending 状态,适用于修改自提配置后 需要重传的场景。 同时修改 RetryFailed 命令,在没有待重试记录时提供操作提示, 并扩展 WxShippingService 的 retryFailed 方法支持处理 failed 状态的记录。 ``` --- .../command/ResyncShipping.php | 65 +++++++++++++++++++ .../command/RetryFailed.php | 4 ++ .../library/WxShippingService.php | 40 +++++++++++- application/command.php | 1 + 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 addons/shopro_wechat_trade/command/ResyncShipping.php diff --git a/addons/shopro_wechat_trade/command/ResyncShipping.php b/addons/shopro_wechat_trade/command/ResyncShipping.php new file mode 100644 index 0000000..451ed49 --- /dev/null +++ b/addons/shopro_wechat_trade/command/ResyncShipping.php @@ -0,0 +1,65 @@ +setName('shopro_wechat_trade:resync-shipping') + ->addOption('sn', null, Option::VALUE_REQUIRED, '订单号,多个英文逗号分隔') + ->addOption('id', null, Option::VALUE_REQUIRED, '订单 id,多个英文逗号分隔') + ->setDescription('Force re-upload WeChat shipping (e.g. after force self-pickup config)'); + } + + protected function execute(Input $input, Output $output) + { + if (!Bridge::isEnabled()) { + $output->writeln('[FAIL] shopro_wechat_trade 未启用'); + return 1; + } + + $sns = []; + $snOpt = trim((string) $input->getOption('sn')); + if ($snOpt !== '') { + foreach (preg_split('/[\s,,]+/', $snOpt) as $sn) { + $sn = trim($sn); + if ($sn !== '') { + $sns[] = $sn; + } + } + } + $idOpt = trim((string) $input->getOption('id')); + if ($idOpt !== '') { + foreach (preg_split('/[\s,,]+/', $idOpt) as $id) { + $id = intval($id); + if ($id > 0) { + $row = \think\Db::name('shopro_order')->where('id', $id)->value('order_sn'); + if ($row) { + $sns[] = $row; + } + } + } + } + if (!$sns) { + $output->writeln('请指定 --sn=订单号 或 --id=订单id'); + return 1; + } + + $service = new WxShippingService(); + $result = $service->resyncShippingByOrderSns(array_unique($sns)); + $output->writeln('Resync shipping: ok=' . $result['ok'] . ', fail=' . $result['fail']); + $output->writeln('说明:retry-failed 只处理 sync 表 pending/failed;已成功的老单请用本命令重传。'); + return $result['fail'] > 0 ? 1 : 0; + } +} diff --git a/addons/shopro_wechat_trade/command/RetryFailed.php b/addons/shopro_wechat_trade/command/RetryFailed.php index f2da5d9..3116b9b 100644 --- a/addons/shopro_wechat_trade/command/RetryFailed.php +++ b/addons/shopro_wechat_trade/command/RetryFailed.php @@ -22,5 +22,9 @@ class RetryFailed extends Command $limit = intval($input->getOption('limit') ?: 50); $count = (new WxShippingService())->retryFailed($limit); $output->writeln('Retried ' . $count . ' sync record(s).'); + if ($count === 0) { + $output->writeln('若无 pending/failed 记录,已成功同步的单需:php think shopro_wechat_trade:resync-shipping --sn=订单号'); + $output->writeln('从未同步且已发货:php think shopro_wechat_trade:backfill --limit=100'); + } } } diff --git a/addons/shopro_wechat_trade/library/WxShippingService.php b/addons/shopro_wechat_trade/library/WxShippingService.php index 934e8b6..4d81e1f 100644 --- a/addons/shopro_wechat_trade/library/WxShippingService.php +++ b/addons/shopro_wechat_trade/library/WxShippingService.php @@ -142,9 +142,13 @@ class WxShippingService { $now = time(); $rows = Db::name('shopro_wechat_trade_sync') - ->where('status', 'pending') - ->where('retry_count', '>', 0) - ->where('next_retry_time', '<=', $now) + ->where(function ($q) use ($now) { + $q->where(function ($q2) use ($now) { + $q2->where('status', 'pending') + ->where('retry_count', '>', 0) + ->where('next_retry_time', '<=', $now); + })->whereOr('status', 'failed'); + }) ->order('id', 'asc') ->limit($limit) ->select(); @@ -164,4 +168,34 @@ class WxShippingService } return $count; } + + /** + * 按订单号再次调用 upload_shipping_info(已有 success 也会重传,用于改自提等) + */ + public function resyncShippingByOrderSns(array $orderSns) + { + $ok = 0; + $fail = 0; + foreach ($orderSns as $sn) { + $sn = trim((string) $sn); + if ($sn === '') { + continue; + } + $order = Db::name('shopro_order')->where('order_sn', $sn)->find(); + if (!$order && strlen($sn) < 24) { + $order = Db::name('shopro_order')->where('order_sn', 'like', $sn . '%')->order('id', 'desc')->find(); + } + if (!$order) { + $fail++; + continue; + } + try { + $this->syncOrderShipping((int) $order['id']); + $ok++; + } catch (\Exception $e) { + $fail++; + } + } + return ['ok' => $ok, 'fail' => $fail]; + } } diff --git a/application/command.php b/application/command.php index ca02e81..bec8bac 100644 --- a/application/command.php +++ b/application/command.php @@ -33,6 +33,7 @@ return [ 'addons\shopro_wechat_trade\command\ProbeOrderPath', 'addons\shopro_wechat_trade\command\BackfillShipping', 'addons\shopro_wechat_trade\command\RetryFailed', + 'addons\shopro_wechat_trade\command\ResyncShipping', 'addons\shopro_wechat_trade\command\ConfirmOrders', 'addons\shopro_wechat_trade\command\VerifyInstall', 'addons\shopro_wechat_trade\command\InstallFull',