文件
xionggeshop/addons/shopro_huifu/command/QuerySplitConfig.php
可乐加冰 7767298a43 ```
feat(shopro_huifu): 新增分账配置依赖检查命令并完善online_busi_type支持

- 新增ProbeSplitConfigDeps命令用于检查split/config提交前的依赖项
  (online_busi_type、运营媒介等)
- 在SyncSplitReceivers命令中添加--online-busi-type选项
- 更新QuerySplitConfig显示online_busi_type信息并调整后续步骤提示
- 完善HuifuMerchantSplitService中的online_busi_type解析逻辑
- 添加extended_material_list配置支持
- 在数据库升级脚本中增加新的配置项
```
2026-10-13 11:17:00 +08:00

218 行
9.5 KiB
PHP

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<?php
namespace addons\shopro_huifu\command;
use addons\shopro_huifu\library\Bridge;
use addons\shopro_huifu\library\HuifuClient;
use addons\shopro_huifu\library\HuifuConfig;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\Db;
class QuerySplitConfig extends Command
{
protected function configure()
{
$this->setName('shopro_huifu:query-split-config')
->addOption('huifu-id', null, Option::VALUE_OPTIONAL, '主商户汇付号,默认:商城 platform_huifu_id 或插件 huifu_id')
->addOption('json', null, Option::VALUE_NONE, '输出完整 API data JSON')
->setDescription('Query Huifu merchant split config (rule_origin, div_flag, receivers)');
}
protected function execute(Input $input, Output $output)
{
$output->writeln('=== 汇付商户分账配置查询 (v2/merchant/split/query) ===');
if (!Bridge::isEnabled()) {
$output->writeln('[FAIL] 汇付插件未启用');
return 1;
}
$config = HuifuConfig::getInstance();
$huifuId = trim((string) $input->getOption('huifu-id'));
if ($huifuId === '') {
$huifuId = $this->resolveDefaultHuifuId();
}
$output->writeln('env: ' . $config->get('env', 'prod'));
$output->writeln('sys_id: ' . $config->get('sys_id'));
$output->writeln('product_id: ' . $config->get('product_id'));
$output->writeln('查询 huifu_id: ' . $huifuId);
$output->writeln('插件 huifu_id: ' . $config->get('huifu_id'));
$output->writeln('');
try {
$config->validateKeys();
} catch (\Exception $e) {
$output->writeln('[FAIL] ' . $e->getMessage());
return 1;
}
$client = new HuifuClient();
$result = $client->queryMerchantSplitConfig($huifuId);
if (!$result['ok']) {
$output->writeln('[FAIL] ' . $result['message']);
$output->writeln('提示: 需渠道 sys_id 对该 huifu_id 有数据权限;22000002 排查请确认查的是收款主商户号');
return 1;
}
$data = $result['data'] ?? [];
$respCode = (string) ($data['resp_code'] ?? '');
$respDesc = (string) ($data['resp_desc'] ?? '');
$output->writeln('resp_code=' . $respCode . ' ' . $respDesc);
if ($respCode !== '' && $respCode !== '00000000') {
$output->writeln('[FAIL] 业务未成功,无法读取 rule_origin');
if ($input->getOption('json')) {
$output->writeln(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
}
return 1;
}
if ($input->getOption('json')) {
$output->writeln(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
return 0;
}
$items = HuifuClient::parseSplitBillResult($data['split_bill_result'] ?? null);
if ($items === []) {
$output->writeln('');
$output->writeln('[结论] split_bill_result 为空 = 汇付侧「分账配置申请」尚未生效(或未提交)');
$output->writeln(' 这与支付查单 delay_acct_flag=Y(延时分账/延迟入账)不是同一开关。');
$output->writeln(' 商城 confirm 带 acct_split_bunch 时,无生效分账配置 + 未绑定接收方 → 典型 22000002。');
$output->writeln('');
$output->writeln('应答顶层字段: ' . implode(', ', array_keys($data)));
$nested = HuifuClient::collectNestedKeys($data, ['rule_origin', 'div_flag', 'apply_ratio', 'delay_flag']);
if ($nested !== []) {
$output->writeln('嵌套扫描: ' . json_encode($nested, JSON_UNESCAPED_UNICODE));
}
$output->writeln('');
$output->writeln('--- 商户详情补充 (v2/merchant/basicdata/query + product_id) ---');
$basic = $client->queryMerchantBasicdata($huifuId, true);
if ($basic['ok']) {
$bd = $basic['data'] ?? [];
$bCode = (string) ($bd['resp_code'] ?? '');
$delay = (string) ($bd['delay_flag'] ?? '');
$forced = (string) ($bd['forced_delay_flag'] ?? '');
if ($delay !== '' || $forced !== '') {
$output->writeln('delay_flag(延迟入账): ' . ($delay !== '' ? $delay : '(未返回)'));
$output->writeln('forced_delay_flag: ' . ($forced !== '' ? $forced : '(未返回)'));
} else {
$scan = HuifuClient::collectNestedKeys($bd, [
'delay_flag', 'forced_delay_flag', 'rule_origin', 'div_flag', 'online_busi_type',
]);
if ($scan !== []) {
$output->writeln('详情嵌套: ' . json_encode($scan, JSON_UNESCAPED_UNICODE));
} else {
$output->writeln('未读到 delay_flag(可 --json 看 basicdata 全文)');
}
}
$busiType = trim((string) (HuifuClient::collectNestedKeys($bd, ['online_busi_type'])['online_busi_type'] ?? ''));
if ($busiType !== '') {
$output->writeln('online_busi_type(进件/业务资料): ' . $busiType);
} else {
$output->writeln('[提示] 40% 分账 split/config 须 online_busi_type,主商户详情未返回时可问汇付渠道或查 KYC 编码表');
}
if ($bCode !== '' && $bCode !== '00000000') {
$output->writeln('basicdata resp_code=' . $bCode . ' ' . ($bd['resp_desc'] ?? ''));
}
} else {
$output->writeln('[SKIP] ' . $basic['message']);
}
$output->writeln('');
$output->writeln('下一步(汇付实施/工单):');
$output->writeln(' 1) 配齐 online_busi_type + 运营媒介后 php think shopro_huifu:sync-split-receivers');
$output->writeln(' 2) 进件子户在 confirm 的 acct_split_bunch 中指定;若仍 22000002 再核控台分账关系/实施工单');
$output->writeln(' 3) 生效后再跑本命令,应出现 rule_origin;新订单测分账,勿重试 unconfirm_amt=0 的旧单');
$output->writeln('完整 JSON: php think shopro_huifu:query-split-config --json');
return 2;
}
$idx = 0;
foreach ($items as $row) {
$idx++;
if (count($items) > 1) {
$output->writeln('');
$output->writeln('--- 分账配置 #' . $idx . ' ---');
}
$ruleOrigin = (string) ($row['rule_origin'] ?? '');
$divFlag = (string) ($row['div_flag'] ?? '');
$applyRatio = (string) ($row['apply_ratio'] ?? '');
$output->writeln('rule_origin: ' . HuifuClient::describeRuleOrigin($ruleOrigin));
$output->writeln('div_flag: ' . ($divFlag !== '' ? $divFlag : '(未返回)'));
$output->writeln('apply_ratio(最大分账比例%): ' . ($applyRatio !== '' ? $applyRatio : '(未返回)'));
if (!empty($row['repeal_flag'])) {
$output->writeln('repeal_flag: ' . $row['repeal_flag']);
}
if (!empty($row['refund_flag'])) {
$output->writeln('refund_flag: ' . $row['refund_flag']);
}
$receivers = $this->parseReceiverList($row['acct_split_bunch_list'] ?? null);
if ($receivers !== []) {
$output->writeln('控台分账接收方 (acct_split_bunch_list):');
foreach ($receivers as $r) {
$rid = (string) ($r['huifu_id'] ?? '');
$rate = (string) ($r['fee_rate'] ?? '');
$output->writeln(' - huifu_id=' . $rid . ($rate !== '' ? ' fee_rate=' . $rate . '%' : ''));
}
} elseif ($ruleOrigin === '02') {
$output->writeln('[提示] rule_origin=02 时控台应配置 acct_split_bunch_list');
}
if ($ruleOrigin === '01') {
$output->writeln('[OK] 与商城延时分账 confirm 传 acct_split_bunch 一致');
} elseif ($ruleOrigin === '02') {
$output->writeln('[WARN] 当前为控台规则;商城仍传 acct_split_bunch 可能报 22000002,请改 01 或联系汇付实施');
}
}
return 0;
}
protected function resolveDefaultHuifuId()
{
try {
$platform = trim((string) Db::name('shopro_split_config')->where('name', 'platform_huifu_id')->value('value'));
if ($platform !== '') {
return $platform;
}
} catch (\Exception $e) {
// ignore
}
return trim((string) HuifuConfig::getInstance()->get('huifu_id'));
}
/**
* @return array<int, array<string, mixed>>
*/
protected function parseReceiverList($raw)
{
if ($raw === null || $raw === '') {
return [];
}
if (is_string($raw)) {
$decoded = json_decode($raw, true);
if (!is_array($decoded)) {
return [];
}
$raw = $decoded;
}
if (!is_array($raw)) {
return [];
}
if (isset($raw['huifu_id'])) {
return [$raw];
}
$list = [];
foreach ($raw as $item) {
if (is_array($item)) {
$list[] = $item;
}
}
return $list;
}
}