diff --git a/addons/shopro_huifu/command/QuerySplitConfig.php b/addons/shopro_huifu/command/QuerySplitConfig.php new file mode 100644 index 0000000..1ee4c74 --- /dev/null +++ b/addons/shopro_huifu/command/QuerySplitConfig.php @@ -0,0 +1,171 @@ +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> + */ + 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; + } +} diff --git a/addons/shopro_huifu/library/HuifuClient.php b/addons/shopro_huifu/library/HuifuClient.php index efd9302..3f52d1e 100644 --- a/addons/shopro_huifu/library/HuifuClient.php +++ b/addons/shopro_huifu/library/HuifuClient.php @@ -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> + */ + 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') { diff --git a/addons/shopro_huifu/library/sdk/extracted/huifurepo-bspay-php-sdk-45b895b/BsPaySdk/request/V2MerchantSplitQueryRequest.php b/addons/shopro_huifu/library/sdk/extracted/huifurepo-bspay-php-sdk-45b895b/BsPaySdk/request/V2MerchantSplitQueryRequest.php new file mode 100644 index 0000000..a647b3a --- /dev/null +++ b/addons/shopro_huifu/library/sdk/extracted/huifurepo-bspay-php-sdk-45b895b/BsPaySdk/request/V2MerchantSplitQueryRequest.php @@ -0,0 +1,50 @@ +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; + } +} diff --git a/application/command.php b/application/command.php index 1c20bb2..bef3885 100644 --- a/application/command.php +++ b/application/command.php @@ -24,6 +24,7 @@ return [ 'addons\shopro_huifu\command\InstallFull', 'addons\shopro_huifu\command\TestPayConnection', 'addons\shopro_huifu\command\ProbeWechatOnboarding', + 'addons\shopro_huifu\command\QuerySplitConfig', 'addons\shopro_huifu\command\OnboardPoll', 'addons\shopro_huifu\command\ImportBankBranch', 'addons\shopro_wechat_trade\command\InitOrderPath',