```
feat(shopro): 完善汇付分账功能的错误处理和调试信息 - 添加主商户号验证逻辑,当platform_huifu_id为空时使用插件主商户 - 改进分账剩余金额显示逻辑,区分主商户留存和平台分账情况 - 更新错误提示信息,明确2200002错误的处理方式 - 新增acct_infos预览功能,便于调试分账配置 - 优化分账服务中的商户号处理,避免主商户重复分账 fix(shopro_huifu): 修复汇付分账配置错误提示和分账逻辑 - 更新22000002错误排查说明,简化表述并突出关键点 - 修复分账服务中构建分账信息的逻辑,确保不包含收款主商户 - 添加日志记录,当跳过分账方为自己时进行警告 - 优化剩余金额处理,当日志平台即收款主商户时剩余款项保留在主商户 - 增强分账验证,当无有效分账接收方时抛出异常 ```
这个提交包含在:
@@ -428,13 +428,18 @@ function diagnoseOrderSplitBlockers($orderId)
|
||||
);
|
||||
}
|
||||
$payFee = number_format((float) $order['pay_fee'], 2, '.', '');
|
||||
$payHuifuId = trim((string) Db::name('shopro_huifu_config')->where('name', 'huifu_id')->value('value'));
|
||||
$platformId = trim((string) ($sc['platform_huifu_id'] ?? ''));
|
||||
if ($platformId === '') {
|
||||
$platformId = $payHuifuId;
|
||||
}
|
||||
$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';
|
||||
if ($platformId !== '' && $platformId === $payHuifuId) {
|
||||
$reasons[] = ' → 主商户留存(不写 acct_infos)huifu_id=' . $payHuifuId . ' 金额=' . $remain;
|
||||
} else {
|
||||
$reasons[] = ' → 平台分账 huifu_id=' . $platformId . ' 金额=' . $remain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,7 +493,7 @@ function printTrySplitChannelHints(array $order)
|
||||
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";
|
||||
echo "\n【最近失败】id={$latest['id']} → 22000002:若已部署「主商户不写 acct_infos」仍失败,请在控台绑定子商户分账关系\n";
|
||||
} elseif (strpos($raw, 'FREEZE') !== false) {
|
||||
echo "\n【最近失败】id={$latest['id']} → 资金冻结,见上查单\n";
|
||||
}
|
||||
@@ -498,6 +503,44 @@ function printTrySplitChannelHints(array $order)
|
||||
if ($payHuifuId) {
|
||||
echo " · 插件支付 huifu_id={$payHuifuId}(应与 platform_huifu_id / 控台主商户一致)\n";
|
||||
}
|
||||
|
||||
printHuifuAcctInfosPreview($order);
|
||||
}
|
||||
|
||||
function printHuifuAcctInfosPreview(array $order)
|
||||
{
|
||||
if (!class_exists('\\addons\\shopro\\library\\split\\SplitCalculator')
|
||||
|| !class_exists('\\addons\\shopro_huifu\\library\\HuifuSplitService')) {
|
||||
return;
|
||||
}
|
||||
$items = (new \addons\shopro\library\split\SplitCalculator())->calculate($order['id']);
|
||||
if (empty($items)) {
|
||||
return;
|
||||
}
|
||||
$service = new \addons\shopro_huifu\library\HuifuSplitService();
|
||||
$payFee = number_format((float) $order['pay_fee'], 2, '.', '');
|
||||
$confirmBase = $service->previewConfirmPayFee($order['order_sn'], $payFee);
|
||||
$ref = new \ReflectionClass($service);
|
||||
$method = $ref->getMethod('buildAcctInfos');
|
||||
$method->setAccessible(true);
|
||||
try {
|
||||
$acctInfos = $method->invoke($service, $items, $confirmBase);
|
||||
} catch (\Throwable $e) {
|
||||
echo "\n【acct_infos 预览】组装失败: " . $e->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
echo "\n【将提交汇付 acct_infos】confirm_base={$confirmBase}\n";
|
||||
foreach ($acctInfos as $row) {
|
||||
echo ' · huifu_id=' . ($row['huifu_id'] ?? '-') . ' div_amt=' . ($row['div_amt'] ?? '-') . "\n";
|
||||
}
|
||||
$splitSum = '0.00';
|
||||
foreach ($acctInfos as $row) {
|
||||
$splitSum = bcadd($splitSum, number_format((float) ($row['div_amt'] ?? 0), 2, '.', ''), 2);
|
||||
}
|
||||
$stay = bcsub($confirmBase, $splitSum, 2);
|
||||
if (bccomp($stay, '0.00', 2) > 0) {
|
||||
echo " · (其余 {$stay} 元留在收款主商户,不写入分账串)\n";
|
||||
}
|
||||
}
|
||||
|
||||
function diagnoseMissingSplitOrders($limit)
|
||||
|
||||
在新工单中引用
屏蔽一个用户