文件
可乐加冰 fec4d58e41 ```
feat(wallet): 用户提交时直连汇付API优化流程

- 移除数据库事务包装汇付API调用,避免长耗时锁表问题
- 用户提交申请时直接连接汇付服务,不再仅保存草稿等待后台处理
- 修改汇付重提交方法名为resubmit以明确区分不同操作
- 更新异常处理机制,增加Throwable捕获确保错误正确处理
- 调整提交成功后的消息提示内容,准确反映当前处理状态

fix(agent): 代理申请流程汇付集成优化

- 统一汇付进件提交失败的消息提示文本
- 优化代理申请状态判断逻辑,根据汇付载荷存在性决定提交方式
- 更新区域代理申请成功提示,区分已提交汇付和待提交场景
- 修复业务审核通过后的汇付提交触发机制

docs(huifu): 更新汇付进件相关文档说明

- 修改后台管理界面描述,体现用户直连汇付的新流程
- 更新业务审核状态下的操作指引说明
- 调整汇付网关类的方法注释,明确各方法职责变化
- 修正canSaveHuifuDraft方法注释,说明字段兼容性和新功能
```
2026-10-08 21:03:04 +08:00

537 行
21 KiB
PHP

<?php
namespace addons\shopro\controller\commission;
use addons\shopro\model\commission\Agent as AgentModel;
use addons\shopro\model\commission\Level;
use addons\shopro\model\commission\Reward;
use addons\shopro\model\User;
use addons\shopro\library\commission\Agent as AgentLibrary;
use addons\shopro\library\commission\Config as ConfigLibrary;
use addons\shopro\library\commission\InviteCode;
class Agent extends Commission
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
/**
* 分销商详情
*/
public function info()
{
$user = $this->auth->getUserinfo();
$agent = new AgentLibrary($user['id']);
$agentInfo = $agent->getAgentInfo();
// 是否显示申请信息入口
$agentInfo['agent_form'] = $this->config->getAgentForm() == 0 ? false : true;
$agentInfo['upgrade_display'] = $this->config->isUpgradeDisplay();
// 未满足成为分销商条件
// if($agentInfo['status'] == null) {
$agentInfo['become_agent'] = $this->config->getBecomeAgentEvent();
// }
if ($agent->isAgentAvaliable()) {
$agentInfo['data']['agent_level'] = $agent->getAgentLevelInfo();
// 待入账佣金
$agentInfo['data']['delay_money'] = $agent->getAgentDelayMoney();
}
if (class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardGate')) {
$onboardRow = \addons\shopro_huifu\model\Onboard::findByRole($user['id'], 'promoter', $user['id']);
$agentInfo['huifu_onboard'] = \addons\shopro_huifu\library\onboard\HuifuOnboardGate::publicStatus(
$onboardRow,
$user['id'],
'promoter',
$user['id'],
$agentInfo['status'] ?? ''
);
}
$this->success('获取成功', $agentInfo);
}
/**
* 提交资料
*/
public function submitInfo()
{
$data = $this->request->post();
if (empty($data['avatar']) || empty($data['name']) || !isset($data['gender']) || empty($data['address'])) {
$this->error('参数错误');
}
$res = \db()->transaction(function () use ($data) {
\db('user')->update([
'id' => $this->auth->id,
'avatar' => $data['avatar'],
'nickname' => $data['name'],
'address' => $data['address'],
'gender' => $data['gender'],
'updatetime' => time()
]);
\db('shopro_commission_agent')->update([
'user_id' => $this->auth->id,
'info_status' => 1
]);
return true;
});
if (!empty($res)) {
$this->success('资料保存成功');
} else {
$this->error('资料保存失败');
}
}
/**
* 我的团队
*
* @return void
*/
public function team()
{
$params = $this->request->get();
extract($params);
$this->auth->setAllowFields(['id', 'username', 'nickname', 'mobile', 'avatar', 'score', 'money', 'parent_user_id']);
$user = $this->auth->getUserinfo();
if (isset($id)) {
// 查询 id 是否是当前用户的下级
$childUser = User::where('parent_user_id', $user['id'])->where('id', $id)->count();
if (!$childUser) {
$this->error('用户不存在');
}
} else {
$id = $user['id'];
}
$fields = 'id,nickname,avatar,parent_user_id,child_user_count_1,createtime';
$teams = User::where('parent_user_id', $id)->with(['agent' => function ($query) {
$query->avaliable()->with(['level' => function ($query) {
$query->field('level,name,image');
}]);
}])
->field($fields)
->order('createtime', 'asc')
->paginate($per_page ?? 10);
$parentUser = null;
if ($user['parent_user_id']) {
$parentUser = User::where('id', $user['parent_user_id'])->field('id,nickname,avatar')->find();
}
$this->success('我的团队', [
'teams' => $teams,
'parent_user' => $parentUser
]);
}
/**
* 分销商申请表单
*/
public function agentForm()
{
$config = new ConfigLibrary();
$agentForm = $config->getAgentForm();
if (!$agentForm) {
$this->error('系统未开启分销商自助申请');
}
$backgroundImage = cdnurl($agentForm['background_image'], true);
// 系统开启完善资料
$agent = new AgentLibrary($this->auth->id);
list($applyStatus, $applyInfo) = $this->checkApplyStatus($agent);
// 合并已有表单信息
if ($applyInfo) {
$userApplyInfoName = array_column($applyInfo, 'name');
foreach ($agentForm['content'] as &$form) {
if (in_array($form['name'], $userApplyInfoName) && $applyInfo[array_search($form['name'], $userApplyInfoName)]['type'] === $form['type']) {
$form = $applyInfo[array_search($form['name'], $userApplyInfoName)];
}
if ($form['type'] === 'image' && isset($form['value'])) {
$form['value'] = cdnurl($form['value'], true);
}
}
}
$agentInfo = $agent->getAgentInfo();
if ($agentInfo['status'] === AgentLibrary::AGENT_STATUS_NULL) {
$this->error($agentInfo['msg'] ?: '您暂时不能申请成为分销商');
}
list($applyStatus, $hasSavedApplyInfo) = $this->normalizeApplyStatus($agent, $applyStatus, $applyInfo);
list($pageMode, $formReadonly, $applyStatus) = $this->resolveFormPageMode(
$agent,
$agentInfo,
$applyStatus,
$hasSavedApplyInfo
);
$data = [
'apply_protocol' => $config->getApplyProtocol(),
'apply_status' => $applyStatus,
'shop_apply_status' => $applyStatus,
'form_readonly' => $formReadonly,
'page_mode' => $pageMode,
'has_saved_apply_info' => $hasSavedApplyInfo,
'agent_status' => $agentInfo['status'],
'apply_info' => $agentForm['content'],
'background_image' => $backgroundImage
];
if (class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardGate')) {
$uid = $this->auth->id;
$onboardRow = \addons\shopro_huifu\model\Onboard::findByRole($uid, 'promoter', $uid);
$data['huifu_onboard'] = \addons\shopro_huifu\library\onboard\HuifuOnboardGate::publicStatus(
$onboardRow,
$uid,
'promoter',
$uid,
$agentInfo['status'] ?? ''
);
if (!empty($data['huifu_onboard']['can_submit']) || !empty($data['huifu_onboard']['can_save_draft'])) {
$data['apply_status'] = true;
if ($data['page_mode'] !== 'profile' || !empty($data['huifu_onboard']['can_save_draft'])) {
$data['form_readonly'] = false;
}
}
}
$this->success('申请表单', $data);
}
/**
* 提交表单申请
*
*/
public function applyForm()
{
$config = new ConfigLibrary();
$agentForm = $config->getAgentForm();
if (!$agentForm) {
$this->error('系统未开启分销商自助申请');
}
$agent = new AgentLibrary($this->auth->id);
list($applyStatus, $applyInfo) = $this->checkApplyStatus($agent);
list($applyStatus,) = $this->normalizeApplyStatus($agent, $applyStatus, $applyInfo);
$post = $this->request->post();
$agentInfo = $agent->getAgentInfo();
$huifuResubmit = false;
$canSaveHuifuDraft = false;
if (class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardGate')) {
$agentStatus = $agentInfo['status'] ?? '';
$uid = $this->auth->id;
$huifuResubmit = !$applyStatus && \addons\shopro_huifu\library\onboard\HuifuOnboardGate::canSubmitOnboard(
$uid,
'promoter',
$uid,
$agentStatus
);
$canSaveHuifuDraft = \addons\shopro_huifu\library\onboard\HuifuOnboardGate::canSaveHuifuDraft(
$uid,
'promoter',
$uid,
$agentStatus
);
}
// 提交资料
\think\Db::transaction(function () use ($agent, $applyStatus, $huifuResubmit, $canSaveHuifuDraft, $post) {
if (!$applyStatus && !$huifuResubmit && !$canSaveHuifuDraft) {
$agentInfo = $agent->getAgentInfo();
if ($agentInfo['status'] === AgentLibrary::AGENT_STATUS_PENDING) {
$this->error('您的资料正在审核中,请耐心等待');
}
if ($agentInfo['status'] === AgentLibrary::AGENT_STATUS_NORMAL) {
$this->error('您已是分销商,无需重复申请');
}
$this->error('您暂时不能申请,请联系客服');
}
$userApplyInfo = $post['data'] ?? [];
$agentInfo = $agent->getAgentInfo();
if ($applyStatus && $userApplyInfo) {
if ($agentInfo['status'] == AgentLibrary::AGENT_STATUS_NEEDINFO) {
$agent->becomeAgent(json_encode($userApplyInfo, JSON_UNESCAPED_UNICODE));
$agent->agent = AgentModel::get($this->auth->id);
} else {
$agent->agent->apply_info = json_encode($userApplyInfo, JSON_UNESCAPED_UNICODE);
\addons\shopro\library\commission\Log::write($agent->user->id, 'agent', ['type' => 'apply_info']);
}
if (!empty($agent->agent)) {
$agent->agent->apply_num += 1;
$agent->agent->info_status = AgentLibrary::INFO_STATUS_COMPLETED;
if (class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardGate')
&& \addons\shopro_huifu\library\onboard\HuifuOnboardGate::isOnboardRequired()
&& !in_array($agent->agent->status, [
AgentLibrary::AGENT_STATUS_NORMAL,
AgentLibrary::AGENT_STATUS_FORBIDDEN,
AgentLibrary::AGENT_STATUS_FREEZE,
], true)) {
$agent->agent->status = AgentLibrary::AGENT_STATUS_PENDING;
}
$agent->agent->save();
}
}
$huifuPayload = $post['huifu_onboard'] ?? [];
if (class_exists('\\addons\\shopro_huifu\\library\\Bridge') && !empty($huifuPayload)) {
$hookParams = [
'user_id' => $this->auth->id,
'huifu_onboard' => $huifuPayload,
'huifu_resubmit' => $huifuResubmit,
];
try {
\think\Hook::listen('shopro_commission_apply_after', $hookParams);
} catch (\Throwable $e) {
$failMsg = '汇付进件提交失败';
$this->error($e->getMessage() ?: $failMsg);
}
}
});
if ($huifuResubmit) {
$msg = '汇付进件已重新提交,请耐心等待审核';
} elseif (!empty($huifuPayload)) {
$msg = '申请已提交,汇付进件已同步提交,请耐心等待审核';
} else {
$msg = '申请已提交,请等待后台审核';
if (class_exists('\\addons\\shopro_huifu\\library\\onboard\\HuifuOnboardGate')
&& \addons\shopro_huifu\library\onboard\HuifuOnboardGate::isOnboardRequired()) {
$msg = '申请已提交,请等待后台审核;通过后请到「提现」页完成汇付进件';
}
}
$this->success($msg, null);
}
public function ranking()
{
$params = $this->request->get();
$agents = AgentModel::getRanking($params);
$this->success('分销商排行', $agents);
}
public function level()
{
if ($this->config->isUpgradeDisplay()) {
$data['level'] = Level::order('level asc')->select();
$data['commission_level'] = $this->config->getCommissionLevel();
$this->success('升级进度', $data);
} else {
$this->error('未开启升级显示');
}
}
/**
* 推广数据看板
*/
public function dashboard()
{
$userId = $this->auth->id;
$agent = $this->agent;
$user = User::where('id', $userId)->field('id,child_user_count,child_user_count_1,child_user_count_2,total_consume,invite_code')->find();
// InviteCode::ensureForUser($userId);
// $user = User::where('id', $userId)->field('id,child_user_count,child_user_count_1,child_user_count_2,total_consume,invite_code')->find();
$agentData = $agent->agent;
$delayMoney = $agent->isAgentAvaliable() ? $agent->getAgentDelayMoney() : 0;
$totalIncome = $agentData ? $agentData['total_income'] : 0;
$directOrderCount = $agentData ? $agentData['order_count'] : 0;
$directOrderMoney = $agentData ? $agentData['order_money'] : 0;
$teamOrderCount = $agentData ? $agentData['child_order_count'] : 0;
$teamOrderMoney = $agentData ? $agentData['child_order_money'] : 0;
$todayIncome = Reward::where('agent_id', $userId)
->where('status', 1)
->whereTime('createtime', 'today')
->sum('commission');
$monthIncome = Reward::where('agent_id', $userId)
->where('status', 1)
->whereTime('createtime', 'month')
->sum('commission');
// 实时统计团队人数(不依赖队列刷新的缓存字段)
$directUsers = User::where(['parent_user_id' => $userId, 'status' => 'normal'])
->field('id,child_user_count,child_user_count_1')
->select();
$directUserCount = count($directUsers);
$indirectUserCount = 0;
$teamUserCount = 0;
foreach ($directUsers as $directUser) {
$indirectUserCount += intval($directUser['child_user_count_1']);
$teamUserCount += 1 + intval($directUser['child_user_count']);
}
$this->success('推广数据看板', [
'team_user_count' => $teamUserCount,
'direct_user_count' => $directUserCount,
'indirect_user_count' => $indirectUserCount,
'direct_order_count' => $directOrderCount,
'direct_order_money' => $directOrderMoney,
'team_order_count' => $teamOrderCount,
'team_order_money' => $teamOrderMoney,
'total_income' => $totalIncome,
'delay_money' => $delayMoney,
'today_income' => round($todayIncome, 2),
'month_income' => round($monthIncome, 2),
'invite_code' => '', // 邀请码功能暂时关闭
'invite_code_enable' => false,
'commission_mode' => $this->config->getCommissionMode(),
'repurchase_enable' => $this->config->isRepurchaseEnable(),
]);
}
/**
* 获取我的邀请码(暂时关闭)
*/
public function inviteCode()
{
$this->error('邀请码功能暂未开放');
// $code = InviteCode::ensureForUser($this->auth->id);
// $this->success('邀请码', ['invite_code' => $code]);
}
/**
* 通过邀请码绑定推广关系(暂时关闭)
*/
public function bindInviteCode()
{
$this->error('邀请码功能暂未开放');
// $code = $this->request->post('invite_code');
// if (empty($code)) {
// $this->error('请输入邀请码');
// }
// $agent = new AgentLibrary($this->auth->id);
// $result = $agent->bindByInviteCode($code);
// if ($result) {
// $this->success('绑定成功');
// } else {
// $this->error('绑定失败,邀请码无效或您已有上级');
// }
}
private function checkApplyStatus($agent)
{
$applyStatus = false; // 提交状态
$agentInfo = $agent->getAgentInfo();
$applyInfo = !empty($agentInfo['data']['apply_info']) ? json_decode($agentInfo['data']['apply_info'], true) : [];
if (!is_array($applyInfo)) {
$applyInfo = [];
}
switch ($agentInfo['status']) {
case AgentLibrary::AGENT_STATUS_NEEDINFO: // 分销商条件已达成,只剩资料未完善
$applyStatus = true;
break;
case AgentLibrary::AGENT_STATUS_NORMAL: // 分销商状态正常 视情况可更新信息
if (!empty($agent->agent)) {
$infoStatus = $agent->agent->info_status;
if ((int) $infoStatus === AgentLibrary::INFO_STATUS_NONE) { // 补全信息
$applyStatus = true;
} else if ((int) $infoStatus === AgentLibrary::INFO_STATUS_REJECT) { // 修改信息
$applyStatus = true;
}
}
break;
// 用户资料被驳回 需要做信息合并 重新提交
case AgentLibrary::AGENT_STATUS_REJECT:
$applyStatus = true;
break;
case AgentLibrary::AGENT_STATUS_PENDING:
if (!empty($agent->agent)) {
$infoStatus = $agent->agent->info_status;
if ($infoStatus === null || $infoStatus === AgentLibrary::INFO_STATUS_NULL) {
$applyStatus = true;
} elseif ((int) $infoStatus === AgentLibrary::INFO_STATUS_NONE || (int) $infoStatus === AgentLibrary::INFO_STATUS_REJECT) {
$applyStatus = true;
}
}
break;
}
// 尚未填写申请资料时,允许继续填写(兼容 pending + info_status 异常的历史数据)
if (!$applyStatus && !$this->hasFilledApplyInfo($applyInfo) && in_array($agentInfo['status'], [
AgentLibrary::AGENT_STATUS_NEEDINFO,
AgentLibrary::AGENT_STATUS_PENDING,
AgentLibrary::AGENT_STATUS_REJECT,
], true)) {
$applyStatus = true;
}
return [$applyStatus, $applyInfo];
}
/**
* 区分「申请页」与「我的资料(只读)」
*/
private function resolveFormPageMode($agent, $agentInfo, $applyStatus, $hasSavedApplyInfo)
{
$pageMode = 'apply';
$formReadonly = false;
if ($agentInfo['status'] === AgentLibrary::AGENT_STATUS_PENDING && $hasSavedApplyInfo) {
return ['pending', true, false];
}
if (in_array($agentInfo['status'], [AgentLibrary::AGENT_STATUS_NORMAL, AgentLibrary::AGENT_STATUS_FREEZE], true)) {
if (!empty($agent->agent)) {
$infoStatus = (int) $agent->agent->info_status;
if ($infoStatus === AgentLibrary::INFO_STATUS_NONE || $infoStatus === AgentLibrary::INFO_STATUS_REJECT) {
return ['apply', false, true];
}
}
if ($hasSavedApplyInfo || !$applyStatus) {
return ['profile', true, false];
}
}
if (!$applyStatus && $hasSavedApplyInfo) {
$formReadonly = true;
}
return [$pageMode, $formReadonly, $applyStatus];
}
/**
* 与 agentForm 保持一致:空资料 / 异常 info_status 时允许提交
*/
private function normalizeApplyStatus($agent, $applyStatus, $applyInfo)
{
$hasSavedApplyInfo = $this->hasFilledApplyInfo($applyInfo);
$agentInfo = $agent->getAgentInfo();
if (!$hasSavedApplyInfo && !empty($agent->agent) && in_array($agentInfo['status'], [
AgentLibrary::AGENT_STATUS_PENDING,
AgentLibrary::AGENT_STATUS_NEEDINFO,
], true)) {
if ((int) $agent->agent->info_status === AgentLibrary::INFO_STATUS_COMPLETED) {
$agent->agent->info_status = AgentLibrary::INFO_STATUS_NONE;
$agent->agent->save();
}
$applyStatus = true;
}
return [$applyStatus, $hasSavedApplyInfo];
}
/**
* 申请资料是否已有有效填写内容
*/
private function hasFilledApplyInfo($applyInfo)
{
if (!is_array($applyInfo) || empty($applyInfo)) {
return false;
}
foreach ($applyInfo as $item) {
if (!empty($item['value'])) {
return true;
}
}
return false;
}
}