diff --git a/addons/shopro_huifu/command/SplitRetry.php b/addons/shopro_huifu/command/SplitRetry.php index 8294336..a83ca29 100644 --- a/addons/shopro_huifu/command/SplitRetry.php +++ b/addons/shopro_huifu/command/SplitRetry.php @@ -7,13 +7,18 @@ use addons\shopro\model\split\SplitOrder; use addons\shopro_huifu\library\HuifuSplitService; use think\console\Command; use think\console\Input; +use think\console\input\Option; use think\console\Output; +use think\Db; class SplitRetry extends Command { protected function configure() { - $this->setName('shopro_huifu:split-retry')->setDescription('Retry failed Huifu split confirm orders'); + $this->setName('shopro_huifu:split-retry') + ->addOption('sn', null, Option::VALUE_OPTIONAL, '指定订单号重试,多个用逗号分隔') + ->addOption('force', null, Option::VALUE_NONE, '忽略 next_retry_time,立即重试') + ->setDescription('Retry failed Huifu split confirm orders'); } protected function execute(Input $input, Output $output) @@ -21,20 +26,79 @@ class SplitRetry extends Command $config = new Config(); if (!$config->isEnable()) { $output->writeln('Split disabled.'); - return; + return 1; } - $rows = SplitOrder::where('channel', 'huifu') - ->where('status', 4) - ->where('retry_count', '<', $config->getRetryMax()) - ->where('next_retry_time', '<=', time()) - ->limit(20) - ->select(); - + $force = (bool) $input->getOption('force'); + $snOpt = trim((string) $input->getOption('sn')); $service = new HuifuSplitService(); - foreach ($rows as $row) { - $service->retry($row['id']); + $rows = []; + + if ($snOpt !== '') { + foreach (preg_split('/[\s,,]+/', $snOpt) as $sn) { + $sn = trim($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) { + $output->writeln("[SKIP] 订单不存在: {$sn}"); + continue; + } + $split = SplitOrder::where('order_id', $order['id']) + ->where('channel', 'huifu') + ->order('id', 'desc') + ->find(); + if (!$split) { + $output->writeln("[SKIP] 无汇付分账记录: {$sn}"); + continue; + } + if ((int) $split['status'] === 2) { + $output->writeln("[OK] 已分账成功: {$sn}"); + continue; + } + $rows[] = $split; + } + } else { + $query = SplitOrder::where('channel', 'huifu') + ->where('status', 4) + ->where('retry_count', '<', $config->getRetryMax()); + if (!$force) { + $query->where('next_retry_time', '<=', time()); + } + $rows = $query->limit(20)->select(); } - $output->writeln('Huifu split retry finished.'); + + if (!$rows) { + $output->writeln('无可重试记录。若刚 confirm 成功,可等 5–30 分钟或加 --force;指定单号:--sn=订单号 --force'); + return 0; + } + + $ok = 0; + $fail = 0; + foreach ($rows as $row) { + $output->writeln('retry split#' . $row['id'] . ' order_sn=' . ($row['order_sn'] ?? '')); + $result = $service->retry($row['id']); + if ($result) { + $output->writeln(' [OK]'); + $ok++; + } else { + $latest = SplitOrder::where('order_id', $row['order_id']) + ->where('channel', 'huifu') + ->order('id', 'desc') + ->find(); + $hint = $latest && !empty($latest['wx_result']) + ? mb_substr((string) $latest['wx_result'], 0, 200) + : '仍失败,见后台分账详情'; + $output->writeln(' [FAIL] ' . $hint); + $fail++; + } + } + + $output->writeln("完成:成功 {$ok},失败 {$fail}"); + return $fail > 0 ? 1 : 0; } }