273 lines
8.7 KiB
PHP
Raw Normal View History

2025-10-17 16:32:16 +08:00
<?php
namespace addons\shopro\controller;
use addons\shopro\controller\Common;
2025-10-17 17:18:15 +08:00
use addons\shopro\library\ccblife\CcbUrlDecrypt;
use app\admin\model\shopro\user\User;
use think\Db;
2025-10-17 16:32:16 +08:00
use think\Log;
/**
* 建行生活用户登录控制器
2025-10-17 17:18:15 +08:00
* 处理建行用户登录、绑定、参数解密等功能
2025-10-17 16:32:16 +08:00
*/
class Ccblife extends Common
{
/**
* 不需要登录的方法
* @var array
*/
2025-10-20 08:54:02 +08:00
protected $noNeedLogin = ['autoLogin', 'login', 'callback', 'decryptParam'];
2025-10-17 16:32:16 +08:00
/**
* 不需要权限的方法
* @var array
*/
protected $noNeedRight = ['*'];
/**
2025-10-17 17:18:15 +08:00
* 建行生活用户登录URL跳转方式
* 建行App会携带加密参数跳转到此地址
2025-10-17 16:32:16 +08:00
*
2025-10-17 17:18:15 +08:00
* GET /addons/shopro/ccblife/login
*/
public function login()
{
try {
// 获取URL参数
$ccbParamSJ = $this->request->get('ccbParamSJ', '');
$otherParams = $this->request->get();
// 验证必要参数
if (empty($ccbParamSJ)) {
$this->error('缺少必要参数');
}
// 获取配置
$config = config('ccblife');
// 解密参数
$decryptedParams = CcbUrlDecrypt::decrypt($ccbParamSJ, $config['service_id']);
if (!$decryptedParams) {
$this->error('参数解密失败');
}
// 合并所有参数
$allParams = array_merge($otherParams, $decryptedParams);
// 获取建行用户信息
$ccbUserId = $allParams['userid'] ?? '';
$mobile = $allParams['mobile'] ?? '';
$openId = $allParams['openid'] ?? '';
if (empty($ccbUserId)) {
$this->error('用户信息获取失败');
}
// 处理用户登录/注册
$userInfo = $this->processUserLogin($ccbUserId, $mobile, $openId, $allParams);
// 生成商城Token
$this->auth->direct($userInfo['user_id']);
$token = $this->auth->getToken();
// 构建跳转URL
$redirectUrl = $allParams['redirect_url'] ?? '/pages/index/index';
$this->success('登录成功', [
'token' => $token,
'user_info' => $userInfo,
'redirect_url' => $redirectUrl
]);
} catch (\Exception $e) {
Log::error('建行生活登录失败: ' . $e->getMessage());
$this->error($e->getMessage());
}
}
/**
* 建行用户自动登录JSBridge方式
* H5在建行App内打开时,通过JSBridge获取用户信息后调用
2025-10-17 16:32:16 +08:00
*
2025-10-17 17:18:15 +08:00
* POST /addons/shopro/ccblife/autoLogin
2025-10-17 16:32:16 +08:00
*/
public function autoLogin()
{
try {
2025-10-17 17:18:15 +08:00
// 获取请求参数
2025-10-17 16:32:16 +08:00
$ccbUserId = $this->request->post('ccb_user_id', '');
$mobile = $this->request->post('mobile', '');
$nickname = $this->request->post('nickname', '');
$avatar = $this->request->post('avatar', '');
2025-10-17 17:18:15 +08:00
// 验证必需参数
2025-10-17 16:32:16 +08:00
if (empty($ccbUserId)) {
$this->error('建行用户ID不能为空');
}
2025-10-17 17:18:15 +08:00
// 处理用户登录/注册
$userInfo = $this->processUserLogin($ccbUserId, $mobile, '', [
'nickname' => $nickname,
'avatar' => $avatar
]);
// 使用Auth系统登录并生成Token
$this->auth->direct($userInfo['user_id']);
$token = $this->auth->getToken();
// 返回结果
$this->success('登录成功', [
'token' => $token,
'user_id' => $userInfo['user_id'],
'is_new_user' => $userInfo['is_new'],
'userInfo' => $userInfo
]);
} catch (\Exception $e) {
Log::error('建行自动登录失败: ' . $e->getMessage());
$this->error('登录失败: ' . $e->getMessage());
}
}
/**
* 处理用户登录/注册
*
* @param string $ccbUserId 建行用户ID
* @param string $mobile 手机号
* @param string $openId OpenID
* @param array $params 其他参数
* @return array 用户信息
*/
private function processUserLogin($ccbUserId, $mobile, $openId, $params)
{
Db::startTrans();
try {
// 查询是否已存在建行用户
$user = Db::name('user')->where('ccb_user_id', $ccbUserId)->find();
2025-10-17 16:32:16 +08:00
if ($user) {
2025-10-17 17:18:15 +08:00
// 用户已存在,更新登录信息
$isNew = false;
2025-10-17 16:32:16 +08:00
2025-10-17 17:18:15 +08:00
Db::name('user')->where('id', $user['id'])->update([
'logintime' => time(),
'loginip' => $this->request->ip(),
'updatetime' => time()
]);
} else {
// 用户不存在,先尝试通过手机号查找
if ($mobile) {
$user = Db::name('user')->where('mobile', $mobile)->find();
}
2025-10-17 16:32:16 +08:00
2025-10-17 17:18:15 +08:00
if ($user) {
// 手机号已存在更新建行用户ID
$isNew = false;
Db::name('user')->where('id', $user['id'])->update([
2025-10-17 16:32:16 +08:00
'ccb_user_id' => $ccbUserId,
2025-10-17 17:18:15 +08:00
'logintime' => time(),
'loginip' => $this->request->ip(),
'updatetime' => time()
]);
2025-10-17 16:32:16 +08:00
2025-10-17 17:18:15 +08:00
} else {
// 创建新用户
$isNew = true;
$userData = [
2025-10-17 16:32:16 +08:00
'ccb_user_id' => $ccbUserId,
2025-10-17 17:18:15 +08:00
'username' => 'ccb_' . substr(md5($ccbUserId), 0, 8),
'nickname' => $params['nickname'] ?? '建行用户' . substr($ccbUserId, -4),
'mobile' => $mobile,
'avatar' => $params['avatar'] ?? '/assets/img/avatar.png',
'status' => 'normal',
'salt' => \fast\Random::alnum(),
'password' => '', // 建行用户无需密码
'joinip' => $this->request->ip(),
'jointime' => time(),
'logintime' => time(),
'loginip' => $this->request->ip(),
'createtime' => time(),
'updatetime' => time()
];
// 设置随机密码
$userData['password'] = md5(md5(\fast\Random::alnum(32)) . $userData['salt']);
$userId = Db::name('user')->insertGetId($userData);
$user = Db::name('user')->where('id', $userId)->find();
}
2025-10-17 16:32:16 +08:00
}
2025-10-17 17:18:15 +08:00
Db::commit();
2025-10-17 16:32:16 +08:00
2025-10-17 17:18:15 +08:00
return [
'user_id' => $user['id'],
'nickname' => $user['nickname'],
'avatar' => $user['avatar'],
'mobile' => $this->maskMobile($user['mobile']),
'is_new' => $isNew,
'ccb_user_id' => $ccbUserId
];
2025-10-17 16:32:16 +08:00
2025-10-17 17:18:15 +08:00
} catch (\Exception $e) {
Db::rollback();
throw $e;
2025-10-17 16:32:16 +08:00
}
}
2025-10-20 08:54:02 +08:00
/**
* 解密建行参数(调试用)
* 用于前端测试页面解密建行传递的加密参数
*
* POST /addons/shopro/ccblife/decryptParam
*/
public function decryptParam()
{
try {
// 获取加密参数
$ccbParamSJ = $this->request->post('ccbParamSJ', '');
if (empty($ccbParamSJ)) {
$this->error('缺少 ccbParamSJ 参数');
}
// 获取配置
$config = config('ccblife');
// 解密参数
$decryptedParams = CcbUrlDecrypt::decrypt($ccbParamSJ, $config['service_id']);
if (!$decryptedParams) {
$this->error('参数解密失败');
}
// 返回解密后的数据
$this->success('解密成功', $decryptedParams);
} catch (\Exception $e) {
Log::error('建行参数解密失败: ' . $e->getMessage());
$this->error('解密失败: ' . $e->getMessage());
}
}
2025-10-17 16:32:16 +08:00
/**
* 手机号脱敏
*
* @param string $mobile 手机号
* @return string 脱敏后的手机号
*/
private function maskMobile($mobile)
{
if (empty($mobile) || strlen($mobile) !== 11) {
return '';
}
return substr($mobile, 0, 3) . '****' . substr($mobile, -4);
}
}