文件
xionggeshop/addons/shopro/controller/UserWalletApply.php
可乐加冰 9a82b33515 fix(huifu): 修复汇付进件表单回显失败及小程序端渲染异常问题
- 后端优化 primary 角色选择逻辑,优先使用包含 draft 回显的角色
- 后端增加兜底机制,本地 payload 为空时远程查询汇付接口重建回显数据
- 后端接口顶层新增 draft 字段,防止前端漏读嵌套数据导致页面空白
- 前端表单组件新增 draft 属性,解决小程序端深层监听不稳定问题
- 前端优化表单数据赋值逻辑,使用 $set 和 $forceUpdate 确保视图更新
- 前端调整数据加载顺序并增加延迟重试,修复小程序首屏偶发未刷出问题
2026-11-15 16:03:40 +08:00

395 行
15 KiB
PHP

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

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

<?php
namespace addons\shopro\controller;
class UserWalletApply extends Base
{
protected $noNeedLogin = ['rule'];
protected $noNeedRight = ['*'];
public function index()
{
$this->success('提现记录', \addons\shopro\model\UserWalletApply::getList());
}
// 申请提现
public function apply()
{
$type = $this->request->post('type');
$money = $this->request->post('money');
$apply = \think\Db::transaction(function () use ($type, $money) {
try {
return \addons\shopro\model\UserWalletApply::apply($type, $money);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
});
if ($apply) {
$this->success('申请成功');
}
$this->error('申请失败');
}
public function rule()
{
// 提现规则
$config = \addons\shopro\model\UserWalletApply::getWithdrawConfig();
$min = round(floatval($config['min']), 2);
$max = round(floatval($config['max']), 2);
$service_fee = floatval($config['service_fee']) * 100;
$service_fee = round($service_fee, 1); // 1 位小数
$perday_amount = isset($config['perday_amount']) ? round(floatval($config['perday_amount']), 2) : 0;
$perday_num = isset($config['perday_num']) ? round(floatval($config['perday_num']), 2) : 0;
$rule = [
'min' => $min,
'max' => $max,
'service_fee' => $service_fee,
'perday_amount' => $perday_amount,
'perday_num' => $perday_num,
'methods' => $config['methods'] ?? [],
'wechat_alipay_auto' => ($config['wechat_alipay_auto'] ?? '0') == '1',
];
$this->success('提现规则', $rule);
}
/**
* 提现页分账进件绑定信息(分销商 / 区域公司)
*/
public function onboard()
{
$this->success('进件绑定', $this->resolveWalletOnboard($this->auth->id));
}
/**
* 汇付进件:支行联行号检索(桥接 shopro_huifu 插件)
*/
public function searchBranch()
{
if (!class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardBankBranch')) {
$this->error('汇付插件未安装');
}
$keyword = $this->request->get('keyword', $this->request->post('keyword', ''));
$cityCode = $this->request->get('city_code', $this->request->post('city_code', ''));
$limit = intval($this->request->get('limit', 20));
$list = \addons\shopro_huifu\library\onboard\HuifuOnboardBankBranch::search($keyword, $cityCode, $limit);
$this->success('ok', ['list' => $list]);
}
/**
* 提现页提交 / 重新提交分账进件资料
*/
public function onboardSubmit()
{
if (!class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardGate')
|| !\addons\shopro_huifu\library\onboard\HuifuOnboardGate::isOnboardRequired()) {
$this->error('当前无需绑定进件资料');
}
$form = $this->request->post('huifu_onboard/a', []);
if (empty($form) || !is_array($form)) {
$this->error('请填写进件资料');
}
$userId = $this->auth->id;
$bindings = $this->collectOnboardBindings($userId);
if (!$bindings) {
$this->error('您暂无可绑定进件的角色');
}
$service = new \addons\shopro_huifu\library\onboard\HuifuOnboardService();
$did = false;
$resubmit = false;
try {
// 汇付 API 不放在 DB 事务内,避免长耗时锁表
foreach ($bindings as $binding) {
$huifu = $binding['huifu_onboard'];
if (!empty($huifu['can_submit'])) {
$service->resubmit($userId, $binding['role_type'], $binding['role_ref_id'], $form);
$did = true;
$resubmit = true;
} elseif (!empty($huifu['can_save_draft'])) {
// 用户提交即直连汇付(不再只存 draft 等后台/定时任务)
$service->submit($userId, $binding['role_type'], $binding['role_ref_id'], $form);
$did = true;
}
}
} catch (\InvalidArgumentException $e) {
$this->error($e->getMessage());
} catch (\RuntimeException $e) {
$msg = class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardError')
? \addons\shopro_huifu\library\onboard\HuifuOnboardError::translate($e->getMessage())
: $e->getMessage();
$this->error($msg);
} catch (\Throwable $e) {
$msg = class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardError')
? \addons\shopro_huifu\library\onboard\HuifuOnboardError::translate($e->getMessage())
: $e->getMessage();
$this->error($msg ?: '提交汇付进件失败');
}
if (!$did) {
$this->error('当前状态不可提交进件资料');
}
$msg = $resubmit
? '汇付进件已重新提交,请耐心等待审核'
: '已提交汇付进件,请耐心等待审核';
$this->success($msg, $this->resolveWalletOnboard($userId));
}
/**
* 进件已通过后更换结算银行卡
*/
public function onboardModifyCard()
{
if (!class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardGate')
|| !\addons\shopro_huifu\library\onboard\HuifuOnboardGate::isOnboardRequired()) {
$this->error('当前无需绑定进件资料');
}
$form = $this->request->post('huifu_onboard/a', []);
if (empty($form) || !is_array($form)) {
$this->error('请填写结算银行卡信息');
}
$userId = $this->auth->id;
$bindings = $this->collectOnboardBindings($userId);
if (!$bindings) {
$this->error('您暂无可更换结算卡的角色');
}
$roleType = trim((string) $this->request->post('role_type', ''));
$roleRefId = intval($this->request->post('role_ref_id', 0));
$modifiable = [];
$pending = false;
foreach ($bindings as $binding) {
$huifu = $binding['huifu_onboard'];
if (!empty($huifu['card_modify_pending'])) {
$pending = true;
continue;
}
if (($huifu['status'] ?? '') === 'approved' && !empty($huifu['can_modify_card'])) {
$modifiable[] = $binding;
}
}
if (!$modifiable) {
$this->error($pending ? '结算卡更换审核中,请耐心等待' : '当前状态不可更换结算卡');
}
$target = null;
if ($roleType !== '') {
foreach ($modifiable as $binding) {
if ($binding['role_type'] !== $roleType) {
continue;
}
if ($roleType === 'promoter' || $roleRefId <= 0 || intval($binding['role_ref_id']) === $roleRefId) {
$target = $binding;
break;
}
}
if (!$target) {
$this->error('未找到可更换结算卡的指定角色');
}
} elseif (count($modifiable) === 1) {
$target = $modifiable[0];
} else {
$this->error('存在多个已进件角色,请指定要更换结算卡的角色');
}
try {
$service = new \addons\shopro_huifu\library\onboard\HuifuOnboardService();
$service->modifySettleCard(
$userId,
$target['role_type'],
$target['role_ref_id'],
$form
);
} catch (\InvalidArgumentException $e) {
$this->error($e->getMessage());
} catch (\RuntimeException $e) {
$msg = class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardError')
? \addons\shopro_huifu\library\onboard\HuifuOnboardError::translate($e->getMessage())
: $e->getMessage();
$this->error($msg);
} catch (\Throwable $e) {
$msg = class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardError')
? \addons\shopro_huifu\library\onboard\HuifuOnboardError::translate($e->getMessage())
: $e->getMessage();
$this->error($msg ?: '更换结算卡失败');
}
$result = $this->resolveWalletOnboard($userId);
$pending = !empty($result['huifu_onboard']['card_modify_pending']);
$this->success(
$pending ? '结算卡更换已提交,请耐心等待审核' : '结算卡更换成功',
$result
);
}
protected function resolveWalletOnboard($userId)
{
if (!class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardGate')) {
return ['show' => false, 'required' => false];
}
$required = \addons\shopro_huifu\library\onboard\HuifuOnboardGate::isOnboardRequired();
if (!$required) {
return ['show' => false, 'required' => false];
}
$bindings = $this->collectOnboardBindings($userId);
if (!$bindings) {
return ['show' => false, 'required' => $required, 'role_labels' => []];
}
$primary = null;
foreach ($bindings as $binding) {
$huifu = $binding['huifu_onboard'];
if (!empty($huifu['can_submit']) || !empty($huifu['can_save_draft'])) {
$primary = $binding;
break;
}
if (($huifu['status'] ?? '') !== 'approved' && !$primary) {
$primary = $binding;
}
}
// 已通过场景:优先选「可换卡且有 draft 回显」的角色
if (!$primary || (($primary['huifu_onboard']['status'] ?? '') === 'approved' && empty($primary['huifu_onboard']['draft']))) {
foreach ($bindings as $binding) {
$h = $binding['huifu_onboard'];
if (!empty($h['can_modify_card']) && !empty($h['draft'])) {
$primary = $binding;
break;
}
}
}
if (!$primary) {
foreach ($bindings as $binding) {
if (!empty($binding['huifu_onboard']['can_modify_card'])
|| !empty($binding['huifu_onboard']['card_modify_pending'])) {
$primary = $binding;
break;
}
}
}
if (!$primary) {
$primary = $bindings[0];
}
$huifu = $primary['huifu_onboard'];
// 若当前 primary 无 draft,从其他角色补一份回显(避免页面空白)
if (empty($huifu['draft'])) {
foreach ($bindings as $binding) {
if (!empty($binding['huifu_onboard']['draft'])) {
$huifu['draft'] = $binding['huifu_onboard']['draft'];
break;
}
}
}
$show = count($bindings) > 0;
$canSubmitBind = false;
$canModifyCardBind = false;
foreach ($bindings as $binding) {
$item = $binding['huifu_onboard'];
if (!empty($item['can_submit']) || !empty($item['can_save_draft'])) {
$canSubmitBind = true;
}
if (!empty($item['can_modify_card'])) {
$canModifyCardBind = true;
}
}
$config = [
'account_types' => [
['value' => 'indv', 'label' => '个人'],
['value' => 'ent', 'label' => '个体户/企业'],
],
'bank_account_types' => [
['value' => '0', 'label' => '对私'],
['value' => '1', 'label' => '对公'],
],
];
return [
'show' => $show,
'required' => true,
'role_labels' => array_column($bindings, 'role_label'),
'role_type' => $primary['role_type'],
'role_ref_id' => intval($primary['role_ref_id']),
'huifu_onboard' => $huifu,
// 顶层再挂一份,避免前端漏读嵌套 draft
'draft' => $huifu['draft'] ?? null,
'can_submit_bind' => $canSubmitBind,
'can_modify_card_bind' => $canModifyCardBind,
'onboard_config' => $config,
'bindings' => array_map(function ($b) {
return [
'role_type' => $b['role_type'],
'role_ref_id' => intval($b['role_ref_id']),
'role_label' => $b['role_label'],
'status' => $b['huifu_onboard']['status'] ?? null,
'can_modify_card' => !empty($b['huifu_onboard']['can_modify_card']),
'card_modify_pending' => !empty($b['huifu_onboard']['card_modify_pending']),
'has_draft' => !empty($b['huifu_onboard']['draft']),
];
}, $bindings),
];
}
protected function collectOnboardBindings($userId)
{
if (!class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardGate')) {
return [];
}
$bindings = [];
$promoterStatuses = ['normal', 'pending', 'needinfo', 'freeze', 'reject'];
$commissionAgent = \addons\shopro\model\commission\Agent::where('user_id', $userId)->find();
if ($commissionAgent && in_array($commissionAgent['status'], $promoterStatuses, true)) {
$onboardRow = \addons\shopro_huifu\model\Onboard::findByRole($userId, 'promoter', $userId);
$bindings[] = [
'role_type' => 'promoter',
'role_ref_id' => $userId,
'role_label' => '分销商',
'huifu_onboard' => \addons\shopro_huifu\library\onboard\HuifuOnboardGate::publicStatus(
$onboardRow,
$userId,
'promoter',
$userId,
$commissionAgent['status'] ?? ''
),
];
}
$regionalAgents = \addons\shopro\model\regional_agent\Agent::where('user_id', $userId)
->where('status', 'in', ['normal', 'pending'])
->order('id desc')
->select();
foreach ($regionalAgents as $regionalAgent) {
$onboardRow = \addons\shopro_huifu\model\Onboard::findByRole($userId, 'regional_agent', $regionalAgent['id']);
$bindings[] = [
'role_type' => 'regional_agent',
'role_ref_id' => $regionalAgent['id'],
'role_label' => '区域公司',
'huifu_onboard' => \addons\shopro_huifu\library\onboard\HuifuOnboardGate::publicStatus(
$onboardRow,
$userId,
'regional_agent',
$regionalAgent['id'],
$regionalAgent['status'] ?? ''
),
];
}
return $bindings;
}
}