From fe83f69638f9d451b5c322d187abc95434494cb8 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: Tue, 29 Sep 2026 11:49:10 +0800 Subject: [PATCH] =?UTF-8?q?```=20=E5=88=86=E8=B4=A6=E8=AF=8A=E6=96=AD?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shopro/tests/split_commission_verify.php | 196 +++++++++++++++++- .../shopro/tests/split_commission_verify.sql | 2 +- 2 files changed, 196 insertions(+), 2 deletions(-) diff --git a/addons/shopro/tests/split_commission_verify.php b/addons/shopro/tests/split_commission_verify.php index 2f183ea..c3e22b4 100644 --- a/addons/shopro/tests/split_commission_verify.php +++ b/addons/shopro/tests/split_commission_verify.php @@ -7,6 +7,8 @@ * php addons/shopro/tests/split_commission_verify.php anomalies * php addons/shopro/tests/split_commission_verify.php order {order_sn} * php addons/shopro/tests/split_commission_verify.php recent-success [limit=20] + * php addons/shopro/tests/split_commission_verify.php diagnose-missing [limit=20] + * php addons/shopro/tests/split_commission_verify.php try-split {order_sn} --execute # 补跑汇付分账(慎用) */ if (PHP_SAPI !== 'cli') { @@ -49,9 +51,18 @@ switch ($command) { $limit = max(1, min(100, intval($argv[2] ?? 20))); printRecentSuccess($limit); break; + case 'diagnose-missing': + $limit = max(1, min(50, intval($argv[2] ?? 20))); + diagnoseMissingSplitOrders($limit); + break; + case 'try-split': + $sn = $argv[2] ?? ''; + $execute = in_array('--execute', $argv, true); + trySplitOrder($sn, $execute); + break; default: echo "未知命令: {$command}\n"; - echo "可用: summary | anomalies | order {order_sn} | recent-success [limit]\n"; + echo "可用: summary | anomalies | order {order_sn} | recent-success [limit] | diagnose-missing [limit] | try-split {order_sn} --execute\n"; exit(1); } @@ -240,9 +251,187 @@ function printAnomalies() foreach ($missing as $r) { echo " {$r['order_sn']} pay_fee={$r['pay_fee']}\n"; } + echo "\n → 执行 diagnose-missing 查看每笔未分账原因\n"; } } +/** + * @return array> + */ +function fetchMissingSplitOrders($since, $limit = 20) +{ + return Db::name('shopro_order')->alias('o') + ->where('o.pay_type', 'huifu_wechat') + ->where('o.paytime', '>=', $since) + ->whereNotExists(function ($q) { + $q->name('shopro_split_order')->alias('so') + ->whereRaw('so.order_id = o.id') + ->where('so.channel', 'huifu') + ->where('so.status', 'in', [1, 2, 3]); + }) + ->where(function ($q) { + $q->whereExists(function ($sq) { + $sq->name('shopro_commission_reward')->alias('cr') + ->whereRaw('cr.order_id = o.id') + ->where('cr.status', '>=', 0); + })->whereOr(function ($sq) { + $sq->name('shopro_regional_agent_reward')->alias('rr') + ->whereRaw('rr.order_id = o.id') + ->where('rr.status', '>=', 0); + }); + }) + ->field('o.id, o.order_sn, o.pay_fee, o.pay_type, o.paytime, o.transaction_id') + ->order('o.id desc') + ->limit($limit) + ->select(); +} + +function diagnoseOrderSplitBlockers($orderId) +{ + $reasons = []; + $order = Db::name('shopro_order')->where('id', $orderId)->find(); + if (!$order) { + return ['订单不存在']; + } + if ($order['pay_type'] !== 'huifu_wechat') { + $reasons[] = "pay_type={$order['pay_type']},非 huifu_wechat,汇付分账不会执行"; + } + $sc = splitConfigMap(); + if (($sc['split_enable'] ?? '0') !== '1') { + $reasons[] = '当前 split_enable=0(若支付时也为关,则当时不会分账)'; + } + + $ext = Db::name('shopro_huifu_pay_ext')->where('order_id', $orderId)->find(); + if (!$ext) { + $reasons[] = '无 shopro_huifu_pay_ext 记录,可能非汇付支付或扩展未写入'; + } elseif (($ext['delay_acct_flag'] ?? 'N') !== 'Y') { + $reasons[] = '支付时 delay_acct_flag≠Y(历史配置未开延时分账),补跑 confirm 可能被汇付拒绝'; + } + + $calcItems = []; + if (class_exists('\\addons\\shopro\\library\\split\\SplitCalculator')) { + $calcItems = (new \addons\shopro\library\split\SplitCalculator())->calculate($orderId); + } + if (empty($calcItems)) { + $reasons[] = 'SplitCalculator 结果为空(最常见:推广员/区域无 channel=huifu 的分账接收方)'; + $rewards = Db::name('shopro_commission_reward')->alias('r') + ->join('shopro_commission_agent a', 'a.id = r.agent_id') + ->where('r.order_id', $orderId) + ->where('r.status', '>=', 0) + ->field('r.id, r.commission, a.user_id') + ->select(); + foreach ($rewards as $rw) { + $uid = $rw['user_id']; + $recv = Db::name('shopro_split_receiver') + ->where('role_type', 'promoter') + ->where('role_id', $uid) + ->where('channel', 'huifu') + ->where('status', 'normal') + ->find(); + $onboard = Db::name('shopro_huifu_onboard') + ->where('user_id', $uid) + ->where('role_type', 'promoter') + ->order('id desc') + ->find(); + $ob = $onboard ? ($onboard['onboard_status'] . '/' . ($onboard['huifu_id'] ?: '-')) : '无进件'; + $rc = $recv ? $recv['receiver_account'] : '无 receiver'; + $reasons[] = " 推广员 user_id={$uid} 佣金={$rw['commission']} 进件={$ob} split_receiver={$rc}"; + } + $regRewards = Db::name('shopro_regional_agent_reward') + ->where('order_id', $orderId) + ->where('status', '>=', 0) + ->select(); + foreach ($regRewards as $rw) { + $uid = $rw['agent_user_id']; + $recv = Db::name('shopro_split_receiver') + ->where('role_type', 'regional_agent') + ->where('role_id', $uid) + ->where('channel', 'huifu') + ->where('status', 'normal') + ->find(); + $onboard = Db::name('shopro_huifu_onboard') + ->where('user_id', $uid) + ->where('role_type', 'regional_agent') + ->order('id desc') + ->find(); + $ob = $onboard ? ($onboard['onboard_status'] . '/' . ($onboard['huifu_id'] ?: '-')) : '无进件'; + $rc = $recv ? $recv['receiver_account'] : '无 receiver'; + $reasons[] = " 区域 user_id={$uid} 佣金={$rw['commission']} 进件={$ob} split_receiver={$rc}"; + } + } else { + $sum = array_sum(array_column($calcItems, 'amount')); + $reasons[] = '当前可算出分账明细 ' . count($calcItems) . ' 条,合计 ' . $sum . ' 元(具备补跑条件,注意 delay_acct_flag)'; + } + + $walletCnt = 0; + $crIds = Db::name('shopro_commission_reward')->where('order_id', $orderId)->where('status', 1)->column('id'); + $rrIds = Db::name('shopro_regional_agent_reward')->where('order_id', $orderId)->where('status', 1)->column('id'); + $allIds = array_merge($crIds ?: [], $rrIds ?: []); + if ($allIds) { + $walletCnt = Db::name('shopro_user_wallet_log') + ->where('item_id', 'in', $allIds) + ->where('wallet_type', 'money') + ->where('type', 'in', ['commission_income', 'regional_agent_income']) + ->count(); + } + if ($walletCnt > 0) { + $reasons[] = "佣金已入钱包({$walletCnt} 条流水)→ 资金目前在用户余额,非汇付分账账户"; + } + + return $reasons; +} + +function diagnoseMissingSplitOrders($limit) +{ + $since = time() - 90 * 86400; + $rows = fetchMissingSplitOrders($since, $limit); + echo "========================================\n"; + echo " 未分账订单诊断(近90天,最多 {$limit} 笔)\n"; + echo "========================================\n\n"; + if (empty($rows)) { + echo "无匹配订单。\n"; + return; + } + foreach ($rows as $row) { + echo str_repeat('-', 60) . "\n"; + echo "订单: {$row['order_sn']} id={$row['id']} pay_fee={$row['pay_fee']}\n"; + echo '支付: ' . date('Y-m-d H:i:s', $row['paytime']) . " pay_type={$row['pay_type']}\n"; + foreach (diagnoseOrderSplitBlockers($row['id']) as $line) { + echo " · {$line}\n"; + } + echo "\n"; + } + echo "补跑(需 delay_acct_flag=Y 且接收方齐全):\n"; + echo " php addons/shopro/tests/split_commission_verify.php try-split {order_sn} --execute\n"; +} + +function trySplitOrder($orderSn, $execute) +{ + if ($orderSn === '') { + fwrite(STDERR, "请指定订单号\n"); + exit(1); + } + $order = Db::name('shopro_order')->where('order_sn', $orderSn)->find(); + if (!$order) { + fwrite(STDERR, "订单不存在\n"); + exit(1); + } + echo "诊断:\n"; + foreach (diagnoseOrderSplitBlockers($order['id']) as $line) { + echo " · {$line}\n"; + } + if (!$execute) { + echo "\n未执行分账。确认后加 --execute\n"; + return; + } + if (!class_exists('\\addons\\shopro_huifu\\library\\HuifuSplitService')) { + fwrite(STDERR, "未安装 shopro_huifu\n"); + exit(1); + } + $ok = (new \addons\shopro_huifu\library\HuifuSplitService())->executeByOrderId($order['id']); + echo $ok ? "\n分账执行返回: 成功\n" : "\n分账执行返回: 失败(查日志 / shopro_split_order)\n"; +} + function printOrderDetail($orderSn) { $order = Db::name('shopro_order')->where('order_sn', $orderSn)->find(); @@ -294,6 +483,11 @@ function printOrderDetail($orderSn) echo "\n【汇付支付扩展】\n"; print_r($ext); } + + echo "\n【分账阻塞诊断】\n"; + foreach (diagnoseOrderSplitBlockers($oid) as $line) { + echo " · {$line}\n"; + } } function printRecentSuccess($limit) diff --git a/addons/shopro/tests/split_commission_verify.sql b/addons/shopro/tests/split_commission_verify.sql index 4795198..edd9b12 100644 --- a/addons/shopro/tests/split_commission_verify.sql +++ b/addons/shopro/tests/split_commission_verify.sql @@ -305,7 +305,7 @@ FROM fa_shopro_commission_reward r INNER JOIN fa_shopro_order o ON o.id = r.order_id INNER JOIN fa_shopro_commission_agent a ON a.id = r.agent_id INNER JOIN fa_user u ON u.id = a.user_id -LEFT JOIN fa_shopro_huifu_onboard ho ON ho.user_id = a.user_id AND ho.status = 'approved' +LEFT JOIN fa_shopro_huifu_onboard ho ON ho.user_id = a.user_id AND ho.onboard_status = 'approved' LEFT JOIN fa_shopro_split_receiver sr ON sr.role_type = 'promoter' AND sr.role_id = a.user_id AND sr.channel = 'huifu' AND sr.status = 'normal' WHERE r.status >= 0