request->get('ccbParamSJ', ''); $otherParams = $this->request->get(); // 验证必要参数 if (empty($ccbParamSJ)) { $this->error('缺少必要参数'); } // 获取配置 $config = config('ccblife'); // 解密参数(使用服务方私钥) $decryptedParams = CcbUrlDecrypt::decrypt($ccbParamSJ, $config['private_key']); 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获取用户信息后调用 * * POST /addons/shopro/ccblife/autoLogin */ public function autoLogin() { try { // 获取请求参数 $ccbUserId = $this->request->post('ccb_user_id', ''); $mobile = $this->request->post('mobile', ''); $nickname = $this->request->post('nickname', ''); $avatar = $this->request->post('avatar', ''); // 验证必需参数 if (empty($ccbUserId)) { $this->error('建行用户ID不能为空'); } // 处理用户登录/注册 $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 其他参数(包含 Usr_Name 等建行返回的数据) * @return array 用户信息 */ private function processUserLogin($ccbUserId, $mobile, $openId, $params) { Db::startTrans(); try { // 查询是否已存在建行用户 $user = Db::name('user')->where('ccb_user_id', $ccbUserId)->find(); if ($user) { // 用户已存在,更新登录信息 $isNew = false; Db::name('user')->where('id', $user['id'])->update([ 'prevtime' => $user['logintime'] ?? null, // 记录上次登录时间 'logintime' => time(), 'loginip' => $this->request->ip(), 'updatetime' => time() ]); // 重新获取更新后的用户信息 $user = Db::name('user')->where('id', $user['id'])->find(); } else { // 用户不存在,先尝试通过手机号查找 if (!empty($mobile)) { $user = Db::name('user')->where('mobile', $mobile)->find(); } if ($user) { // 手机号已存在,绑定建行用户ID $isNew = false; Db::name('user')->where('id', $user['id'])->update([ 'ccb_user_id' => $ccbUserId, 'prevtime' => $user['logintime'] ?? null, 'logintime' => time(), 'loginip' => $this->request->ip(), 'updatetime' => time() ]); // 重新获取更新后的用户信息 $user = Db::name('user')->where('id', $user['id'])->find(); } else { // 创建新用户 $isNew = true; // 从建行参数中获取用户名(Usr_Name 或 nickname) $userName = $params['Usr_Name'] ?? $params['nickname'] ?? ''; if (empty($userName)) { $userName = '建行用户' . substr($ccbUserId, -4); } // 生成盐值 $salt = \fast\Random::alnum(); $userData = [ 'ccb_user_id' => $ccbUserId, 'username' => 'ccb_' . substr(md5($ccbUserId), 0, 10), // 唯一用户名 'nickname' => $userName, 'mobile' => $mobile ?: '', 'avatar' => $params['avatar'] ?? '/assets/img/avatar.png', 'status' => 'normal', 'salt' => $salt, 'password' => md5(md5(\fast\Random::alnum(32)) . $salt), // 随机密码 'group_id' => 0, // 默认用户组 'level' => 0, // 默认等级 'gender' => 0, // 未知性别 'money' => 0.00, 'commission' => 0.00, 'score' => 0, 'successions' => 1, 'maxsuccessions' => 1, 'loginfailure' => 0, 'joinip' => $this->request->ip(), 'jointime' => time(), 'logintime' => time(), 'loginip' => $this->request->ip(), 'createtime' => time(), 'updatetime' => time() ]; Log::info('创建建行新用户', [ 'ccb_user_id' => $ccbUserId, 'mobile' => $mobile, 'nickname' => $userName ]); $userId = Db::name('user')->insertGetId($userData); if (!$userId) { throw new \Exception('创建用户失败'); } $user = Db::name('user')->where('id', $userId)->find(); } } Db::commit(); Log::info('建行用户登录处理成功', [ 'user_id' => $user['id'], 'ccb_user_id' => $ccbUserId, 'is_new' => $isNew ]); return [ 'user_id' => $user['id'], 'nickname' => $user['nickname'], 'avatar' => $user['avatar'], 'mobile' => $user['mobile'], 'is_new' => $isNew, 'ccb_user_id' => $ccbUserId ]; } catch (\Exception $e) { Db::rollback(); Log::error('建行用户登录处理失败', [ 'error' => $e->getMessage(), 'ccb_user_id' => $ccbUserId, 'trace' => $e->getTraceAsString() ]); throw $e; } } /** * 解密建行参数(调试用) * 用于前端测试页面解密建行传递的加密参数 * * POST /addons/shopro/ccblife/decryptParam */ public function decryptParam() { try { // 获取加密参数 $ccbParamSJ = $this->request->post('ccbParamSJ', ''); if (empty($ccbParamSJ)) { $this->error('缺少 ccbParamSJ 参数'); } // 从插件配置文件直接加载(避免config()缓存问题) $configFile = __DIR__ . '/../config/ccblife.php'; if (!file_exists($configFile)) { $this->error('建行配置文件不存在'); } $config = include $configFile; // 验证配置 if (empty($config['private_key'])) { $this->error('配置错误:private_key 为空'); } Log::info('解密建行参数', [ 'ccbParamSJ_length' => strlen($ccbParamSJ), 'service_id' => $config['service_id'], 'private_key_length' => strlen($config['private_key']) ]); // 解密参数(使用服务方私钥) $decryptedParams = CcbUrlDecrypt::decrypt($ccbParamSJ, $config['private_key']); if ($decryptedParams === false || empty($decryptedParams)) { // 检查日志文件获取详细错误 $logFile = RUNTIME_PATH . 'log/' . date('Ymd') . '.log'; $errorDetail = ''; if (file_exists($logFile)) { $logContent = file_get_contents($logFile); // 提取最后几行日志 $lines = explode("\n", $logContent); $errorDetail = implode("\n", array_slice($lines, -10)); } $this->error('参数解密失败,请查看日志: ' . $errorDetail); } // 返回解密后的数据 $this->success('解密成功', $decryptedParams); } catch (\Exception $e) { Log::error('建行参数解密失败', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); $this->error('解密失败: ' . $e->getMessage()); } } }