```
feat(shopro): 完善分账诊断功能并优化错误提示 - 在分账诊断中增加 split_max_rate 限制显示,并添加详细的分账明细条目信息 - 添加推广员进件状态检查,验证汇付ID与接收账户一致性 - 新增 printTrySplitChannelHints 函数,提供汇付查单服务和延迟分账标识查询 - 增强错误码 220002 的排查指引,包含详细的问题解决步骤 - 更新执行提示信息,强调确认汇付控台分账关系后再执行 - 添加关于测试单双轨风险的警告提示 ```
这个提交包含在:
@@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户