```
feat(shopro_huifu): 新增汇付商户分账配置查询命令 新增 QuerySplitConfig 命令用于查询汇付商户分账配置, 包括 rule_origin、div_flag、apply_ratio 等字段信息。 - 添加了命令行工具 shopro_huifu:query-split-config - 实现了商户分账配置查询功能 v2/merchant/split/query - 支持输出完整API数据JSON格式 - 提供分账配置详情展示和规则说明 - 在 application/command.php 中注册新命令 ```
这个提交包含在:
@@ -0,0 +1,171 @@
|
||||
<?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('[WARN] 未返回 split_bill_result:主商户可能未开通分账/延时分账,或 product 无权限');
|
||||
$output->writeln('可加 --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;
|
||||
}
|
||||
}
|
||||
@@ -561,6 +561,78 @@ class HuifuClient
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 商户分账配置查询 v2/merchant/split/query(含 rule_origin、div_flag、apply_ratio)
|
||||
*/
|
||||
public function queryMerchantSplitConfig($huifuId = '')
|
||||
{
|
||||
$huifuId = trim((string) $huifuId);
|
||||
if ($huifuId === '') {
|
||||
$huifuId = trim((string) $this->config->get('huifu_id'));
|
||||
}
|
||||
if ($huifuId === '') {
|
||||
return ['ok' => false, 'message' => '缺少 huifu_id', 'data' => null];
|
||||
}
|
||||
|
||||
SdkLoader::requireRequest('V2MerchantSplitQueryRequest.php');
|
||||
$request = new \BsPaySdk\request\V2MerchantSplitQueryRequest();
|
||||
$request->setHuifuId($huifuId);
|
||||
$request->setReqDate(date('Ymd'));
|
||||
$request->setReqSeqId('SPLQ' . date('YmdHis') . mt_rand(1000, 9999));
|
||||
|
||||
return $this->safeApiResult($this->postRequest($request));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 解析 split_bill_result(可能是 array 或 JSON 字符串)
|
||||
*
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public static function parseSplitBillResult($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['rule_origin']) || isset($raw['div_flag'])) {
|
||||
return [$raw];
|
||||
}
|
||||
$list = [];
|
||||
foreach ($raw as $item) {
|
||||
if (is_array($item)) {
|
||||
$list[] = $item;
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function describeRuleOrigin($code)
|
||||
{
|
||||
$code = trim((string) $code);
|
||||
if ($code === '01') {
|
||||
return '01 接口发起(交易确认可传 acct_split_bunch)';
|
||||
}
|
||||
if ($code === '02') {
|
||||
return '02 控台配置(接口带分账串易 22000002,以控台规则为准)';
|
||||
}
|
||||
return $code !== '' ? $code : '(未返回)';
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function probeMiniAppCreate($subOpenid, $subAppid = '', $amount = '0.01')
|
||||
|
||||
{
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace BsPaySdk\request;
|
||||
|
||||
use BsPaySdk\enums\FunctionCodeEnum;
|
||||
|
||||
/**
|
||||
* 商户分账配置查询 v2/merchant/split/query
|
||||
*/
|
||||
class V2MerchantSplitQueryRequest extends BaseRequest
|
||||
{
|
||||
private $reqSeqId;
|
||||
private $reqDate;
|
||||
private $huifuId;
|
||||
|
||||
public function getFunctionCode()
|
||||
{
|
||||
return FunctionCodeEnum::$V2_MERCHANT_SPLIT_QUERY;
|
||||
}
|
||||
|
||||
public function getReqSeqId()
|
||||
{
|
||||
return $this->reqSeqId;
|
||||
}
|
||||
|
||||
public function setReqSeqId($reqSeqId)
|
||||
{
|
||||
$this->reqSeqId = $reqSeqId;
|
||||
}
|
||||
|
||||
public function getReqDate()
|
||||
{
|
||||
return $this->reqDate;
|
||||
}
|
||||
|
||||
public function setReqDate($reqDate)
|
||||
{
|
||||
$this->reqDate = $reqDate;
|
||||
}
|
||||
|
||||
public function getHuifuId()
|
||||
{
|
||||
return $this->huifuId;
|
||||
}
|
||||
|
||||
public function setHuifuId($huifuId)
|
||||
{
|
||||
$this->huifuId = $huifuId;
|
||||
}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户