feat(shopro): 完善分账诊断功能并优化错误提示

- 在分账诊断中增加 split_max_rate 限制显示,并添加详细的分账明细条目信息
- 添加推广员进件状态检查,验证汇付ID与接收账户一致性
- 新增 printTrySplitChannelHints 函数,提供汇付查单服务和延迟分账标识查询
- 增强错误码 220002 的排查指引,包含详细的问题解决步骤
- 更新执行提示信息,强调确认汇付控台分账关系后再执行
- 添加关于测试单双轨风险的警告提示
```
这个提交包含在:
可乐加冰
2026-10-05 10:29:38 +08:00
父节点 702154d68f
当前提交 da2ce90ae5
共有 2 个文件被更改,包括 90 次插入 和 2 次删除

查看文件

@@ -397,7 +397,45 @@ function diagnoseOrderSplitBlockers($orderId)
} }
} else { } else {
$sum = array_sum(array_column($calcItems, 'amount')); $sum = array_sum(array_column($calcItems, 'amount'));
$reasons[] = '当前可算出分账明细 ' . count($calcItems) . ' 条,合计 ' . $sum . ' 元(具备补跑条件,注意 delay_acct_flag)'; $maxRate = floatval($sc['split_max_rate'] ?? 30);
$reasons[] = '当前可算出分账明细 ' . count($calcItems) . ' 条,合计 ' . $sum . ' 元(受 split_max_rate=' . $maxRate . '% 与 pay_fee 上限约束)';
foreach ($calcItems as $item) {
$uid = intval($item['role_id'] ?? 0);
$acct = $item['receiver_account'] ?? '-';
$onboardHint = '';
if ($uid > 0 && ($item['role_type'] ?? '') === 'promoter') {
$onboard = Db::name('shopro_huifu_onboard')
->where('user_id', $uid)
->where('role_type', 'promoter')
->order('id desc')
->find();
if ($onboard) {
$onboardHint = ' 进件=' . ($onboard['onboard_status'] ?? '') . '/' . ($onboard['huifu_id'] ?: '-');
if (($onboard['huifu_id'] ?? '') !== '' && $onboard['huifu_id'] !== $acct) {
$onboardHint .= ' ⚠与 receiver 不一致';
}
} else {
$onboardHint = ' 进件=无';
}
}
$reasons[] = sprintf(
' → %s user_id=%s huifu_id=%s 金额=%s%s',
$item['role_type'] ?? '-',
$uid ?: '-',
$acct,
number_format((float) ($item['amount'] ?? 0), 2, '.', ''),
$onboardHint
);
}
$payFee = number_format((float) $order['pay_fee'], 2, '.', '');
$platformId = trim((string) ($sc['platform_huifu_id'] ?? ''));
$remain = bcsub($payFee, number_format($sum, 2, '.', ''), 2);
if (bccomp($remain, '0.00', 2) > 0) {
$reasons[] = ' → platform 剩余 huifu_id=' . ($platformId !== '' ? $platformId : '(未配 platform_huifu_id,将用插件主商户)') . ' 金额=' . $remain;
}
if ($platformId === '') {
$reasons[] = ' ⚠ platform_huifu_id 为空,请与汇付收款主商户 huifu_id 一致,否则易 22000002';
}
} }
$walletCnt = 0; $walletCnt = 0;
@@ -420,6 +458,48 @@ function diagnoseOrderSplitBlockers($orderId)
return $reasons; return $reasons;
} }
function printTrySplitChannelHints(array $order)
{
if (!class_exists('\\addons\\shopro_huifu\\library\\HuifuQueryService')) {
return;
}
echo "\n【汇付查单】\n";
try {
$query = (new \addons\shopro_huifu\library\HuifuQueryService())->queryByOrderSn($order['order_sn']);
$keys = ['trans_stat', 'delay_acct_flag', 'unconfirm_amt', 'fund_freeze_stat', 'unfreeze_time'];
foreach ($keys as $key) {
if (isset($query[$key]) && $query[$key] !== '' && $query[$key] !== null) {
echo " · {$key}=" . $query[$key] . "\n";
}
}
$freeze = strtoupper(trim((string) ($query['fund_freeze_stat'] ?? '')));
if ($freeze === 'FREEZE') {
echo " → 仍 FREEZE:请先启用 shopro_wechat_trade 并完成发货/微信确认收货,勿 --execute\n";
}
} catch (\Throwable $e) {
echo ' · 查单失败: ' . $e->getMessage() . "\n";
}
$latest = Db::name('shopro_split_order')
->where('order_id', $order['id'])
->where('channel', 'huifu')
->order('id desc')
->find();
if ($latest && intval($latest['status']) === 4 && !empty($latest['wx_result'])) {
$raw = is_string($latest['wx_result']) ? $latest['wx_result'] : json_encode($latest['wx_result'], JSON_UNESCAPED_UNICODE);
if (strpos($raw, '22000002') !== false || strpos($raw, '分账配置') !== false) {
echo "\n【最近失败】id={$latest['id']} → 22000002 分账配置有误:控台绑定上述 huifu_id 后再重试\n";
} elseif (strpos($raw, 'FREEZE') !== false) {
echo "\n【最近失败】id={$latest['id']} → 资金冻结,见上查单\n";
}
}
$payHuifuId = Db::name('shopro_huifu_config')->where('name', 'huifu_id')->value('value');
if ($payHuifuId) {
echo " · 插件支付 huifu_id={$payHuifuId}(应与 platform_huifu_id / 控台主商户一致)\n";
}
}
function diagnoseMissingSplitOrders($limit) function diagnoseMissingSplitOrders($limit)
{ {
$since = time() - 90 * 86400; $since = time() - 90 * 86400;
@@ -459,8 +539,10 @@ function trySplitOrder($orderSn, $execute)
foreach (diagnoseOrderSplitBlockers($order['id']) as $line) { foreach (diagnoseOrderSplitBlockers($order['id']) as $line) {
echo " · {$line}\n"; echo " · {$line}\n";
} }
printTrySplitChannelHints($order);
if (!$execute) { if (!$execute) {
echo "\n未执行分账。确认后加 --execute\n"; echo "\n未执行分账。确认汇付控台分账关系 + 非 FREEZE 后再加 --execute\n";
echo "(本单若佣金已入钱包,--execute 成功可能造成测试单双轨,正式单请先对齐 split_timing 与分销结算)\n";
return; return;
} }
if (!class_exists('\\addons\\shopro_huifu\\library\\HuifuSplitService')) { if (!class_exists('\\addons\\shopro_huifu\\library\\HuifuSplitService')) {

查看文件

@@ -397,6 +397,12 @@ class HuifuClient
} }
if ($respCode === '22000002') {
$parts[] = '排查: 1) 汇付控台主商户已开通延时分账/分账业务 2) acct_split_bunch 中每个 huifu_id 已在控台绑定为分账接收方 3) 商城「平台汇付商户号 platform_huifu_id」= 收款主商户 huifu_id 4) 分账接收方账号为进件 huifu_id(非微信 openid)5) 推广员进件成功且与 receiver 一致';
}
return implode(',', $parts); return implode(',', $parts);
} }