uploader = new TencentCosUploader($config); } /** * 处理用户的UID * * @param User $user 用户对象 */ private function processUid($user) { // 如果用户已有uid,不处理 if (!empty($user['uid'])) { return; } // 生成uid $uid = $this->generateUid($user['id']); if ($uid) { // 更新用户uid User::where('id', $user['id'])->update(['uid' => $uid]); } } /** * 生成用户UID * * @param int $user_id 用户ID * @return string 生成的UID */ private function generateUid($user_id) { // 获取用户uid配置 $user_config = getConfig('user_config'); if (empty($user_config) || !isset($user_config['uid_type'])) { return (string) $user_id; // 默认使用真实ID } $uid_type = (int) $user_config['uid_type']; $uid_length = isset($user_config['uid_length']) ? (int) $user_config['uid_length'] : 6; // 限制长度范围 if ($uid_length < 4) { $uid_length = 4; } elseif ($uid_length > 16) { $uid_length = 16; } // 根据不同类型生成UID switch ($uid_type) { case 0: // 真实ID return (string) $user_id; case 1: // 数字ID // 生成不以0开头的随机数字 $max_attempts = 10; $attempt = 0; while ($attempt < $max_attempts) { // 生成随机数字 $min = pow(10, $uid_length - 1); $max = pow(10, $uid_length) - 1; $uid = (string) mt_rand($min, $max); // 检查是否唯一 $exists = User::where('uid', $uid)->count(); if ($exists == 0) { return $uid; } $attempt++; } // 如果多次尝试后仍无法生成唯一ID,则使用更可靠的方法 return $this->generateUniqueNumericId($uid_length); case 2: // 随机字符和数字 $length = max(8, $uid_length); // 字母数字混合至少8位 $max_attempts = 10; $attempt = 0; while ($attempt < $max_attempts) { // 生成随机字母数字 $characters = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'; // 排除容易混淆的字符 $uid = ''; // 确保第一个字符不是数字 $uid .= $characters[mt_rand(8, strlen($characters) - 1)]; // 从字母开始 // 生成剩余字符 for ($i = 1; $i < $length; $i++) { $uid .= $characters[mt_rand(0, strlen($characters) - 1)]; } // 检查是否唯一 $exists = User::where('uid', $uid)->count(); if ($exists == 0) { return $uid; } $attempt++; } // 如果多次尝试后仍无法生成唯一ID,使用时间戳+随机数确保唯一性 return $this->generateUniqueAlphaNumId($length); default: return (string) $user_id; } } /** * 生成唯一的数字ID(备用方法) */ private function generateUniqueNumericId($length) { // 使用时间微秒 + 随机数的方式保证唯一性 $base = microtime(true) * 10000 . mt_rand(1000, 9999); $uid = substr(preg_replace('/[^0-9]/', '', $base), 0, $length); // 确保不以0开头且长度正确 while (strlen($uid) < $length || $uid[0] == '0') { $uid = mt_rand(1, 9) . substr($uid, 1); $uid = substr($uid, 0, $length); } return $uid; } /** * 生成唯一的字母数字ID(备用方法) */ private function generateUniqueAlphaNumId($length) { // 使用时间戳 + 随机字符 $base = time() . mt_rand(1000, 9999); $hash = md5($base); // 转换为字母数字混合 $uid = ''; $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // 排除容易混淆的字符 // 确保第一个字符是字母 $uid .= $chars[mt_rand(0, 25)]; // 前26个是字母 // 生成剩余字符 for ($i = 1; $i < $length; $i++) { $uid .= $chars[mt_rand(0, strlen($chars) - 1)]; } return $uid; } /** * 微信授权,登录接口 */ public function login() { try { $code = request()->param("code", ''); if (empty($code)) { return $this->renderError('请求参数错误'); } $click_id = request()->header('clickid'); $wxServer = new \app\common\server\Wx($this->app); $user_base = $wxServer->getOpenid($code); $openid = $user_base['openid']; $user = null; $wx_unionid = null; if ($user_base['unionid'] != null && $user_base['unionid'] != '') { $wx_unionid = $user_base['unionid']; $user = User::getInfo(['unionid' => $wx_unionid]); } if ($user == null) { $user = User::getInfo(['openid' => $openid]); } // return $this->renderSuccess("登录成功", $user); if ($user) { if ($user['click_id'] != $click_id) { $res[] = User::where(['id' => $user['id']])->update(['click_id' => $click_id]); } //设置unionId if ($wx_unionid && !empty($wx_unionid)) { $unionid = $user['unionid']; if ($unionid == null || empty($unionid)) { $user['unionid'] = $wx_unionid; // User::update($user); $user->save(); } } // 检查并生成uid $this->processUid($user); #token时间戳 $time = time(); #token字符串 $token_num = getRandStr(10); #加密token $account_token = user_md5($user['id'] . $token_num . $time); #更新账号信息 $last_login_ip1 = $this->getRealIp(); $result = $this->ip_location($last_login_ip1); $ip_province = ''; $ip_city = ''; $ip_adcode = ''; if ($result) { $ip_province = $result['province']; $ip_city = $result['city']; $ip_adcode = $result['adcode']; } else { } $res[] = UserAccount::where(['user_id' => $user['id']])->update([ 'account_token' => $account_token, 'token_num' => $token_num, 'token_time' => $time, 'last_login_time' => $time, 'last_login_ip' => ip2long($last_login_ip1), 'last_login_ip1' => $last_login_ip1, 'ip_adcode' => $ip_adcode, 'ip_province' => $ip_province, 'ip_city' => $ip_city, ]); // 记录用户登录日志(每天只记录一次) UserLoginLog::recordLogin( $user['id'], 'wechat', $last_login_ip1, $ip_province . $ip_city ); return $this->renderSuccess("登录成功", $account_token); } else { $nickname = request()->param('nickname', ''); $headimg = request()->param('headimg', ''); if (!$nickname) { return $this->renderError('请求参数错误!'); } $pid = 0; $pid_pid = request()->param('pid', 0); if ($pid_pid > 0) { log::info("获取推荐人id" . $pid_pid); } $randx = rand(1000, 9999); if ($nickname == "微信用户") { $nickname = $nickname . $randx; } $identicon = new \Identicon\Identicon(); $imageData = $identicon->getImageData($openid . $nickname); $uploadResult = $this->uploader->uploadFile($imageData, "storage/users/icon/default/" . $randx . ".png"); $headimg = $uploadResult['full_url']; if ($pid_pid) { $pid_info = User::where('id', '=', $pid_pid)->value("id"); if ($pid_info) { log::info("获取推荐人id" . $pid_info); $pid = $pid_info; } } Db::startTrans(); $res[] = $user_id = User::insertGetId([ 'openid' => $openid, 'nickname' => $nickname, 'headimg' => $headimg, 'pid' => $pid, 'addtime' => time(), 'click_id' => $click_id, 'unionid' => $wx_unionid, 'uid' => '', ]); // 生成用户uid $uid = $this->generateUid($user_id); if ($uid) { User::where('id', $user_id)->update(['uid' => $uid]); } $time = time(); #token字符串 $token_num = getRandStr(10); #加密token $account_token = user_md5($user_id . $token_num . $time); #更新账号信息 $last_login_ip1 = $this->getRealIp(); $result = $this->ip_location($last_login_ip1); $ip_province = ''; $ip_city = ''; $ip_adcode = ''; if ($result) { $ip_province = $result['province']; $ip_city = $result['city']; $ip_adcode = $result['adcode']; } else { } $res[] = UserAccount::insert([ 'user_id' => $user_id, 'account_token' => $account_token, 'token_num' => $token_num, 'token_time' => $time, 'last_login_time' => $time, 'last_login_ip' => ip2long($last_login_ip1), 'last_login_ip1' => $last_login_ip1, 'ip_adcode' => $ip_adcode, 'ip_province' => $ip_province, 'ip_city' => $ip_city, ]); #记录登录日志 #推荐成功之后获取一张抽奖券 #配置 $rule = getConfig('base'); $draw_people_num = $rule['draw_people_num']; if (!empty($pid)) { $num = 0; $num = ProfitDraw::where(['type' => 5, 'user_id' => $pid, 'share_uid' => $user_id])->count(); if (bccomp("$num", "$draw_people_num") < 0) { #可以获得一张抽奖券 $res[] = User::changeDraw($pid, 1, 5, '获得一张抽奖券', $user_id); } } if (resCheck($res)) { // 新用户注册也要记录登录日志 UserLoginLog::recordLogin( $user_id, 'wechat', $last_login_ip1, $ip_province . $ip_city ); Db::commit(); return $this->renderSuccess("登录成功", $account_token); } else { Db::rollback(); return $this->renderError("登录失败"); } } } catch (\Exception $e) { Log::error('错误信息' . $e->getMessage()); Log::error('错误行数' . $e->getLine()); } } /** * 微信授权 */ public function h5login() { try { $code = request()->param("code", ''); if (empty($code)) { return $this->renderError('请求参数错误'); } $click_id = request()->header('clickid'); $wxServer = new \app\common\server\WechatOfficialAccount($this->app); $user_base = $wxServer->getAccessToken($code); // $user_base_info = $wxServer->getUserInfo($user_base); $retrieved_openid = $user_base['openid']; $openid = $retrieved_openid; $user = null; if ($user_base['unionid'] != null && $user_base['unionid'] != '') { $unionid = $user_base['unionid']; $user = User::getInfo(['unionid' => $unionid]); if ($user != null) { // $user if ($user['gzh_openid'] == null || $user['gzh_openid'] != $retrieved_openid) { $user['gzh_openid'] = $retrieved_openid; $user->save(); } } } if ($user == null) { $user = User::getInfo(['openid' => $openid]); } // return $this->renderSuccess("登录成功", $user); if ($user) { if ($user['click_id'] != $click_id) { $res[] = User::where(['id' => $user['id']])->update(['click_id' => $click_id]); } #token时间戳 $time = time(); #token字符串 $token_num = getRandStr(10); #加密token $account_token = user_md5($user['id'] . $token_num . $time); #更新账号信息 $last_login_ip1 = $this->getRealIp(); $result = $this->ip_location($last_login_ip1); $ip_province = ''; $ip_city = ''; $ip_adcode = ''; if ($result) { $ip_province = $result['province']; $ip_city = $result['city']; $ip_adcode = $result['adcode']; } else { } $res[] = UserAccount::where(['user_id' => $user['id']])->update([ 'account_token' => $account_token, 'token_num' => $token_num, 'token_time' => $time, 'last_login_time' => $time, 'last_login_ip' => ip2long($last_login_ip1), 'last_login_ip1' => $last_login_ip1, 'ip_adcode' => $ip_adcode, 'ip_province' => $ip_province, 'ip_city' => $ip_city, ]); // 记录用户登录日志(每天只记录一次) UserLoginLog::recordLogin( $user['id'], 'wechat_h5', $last_login_ip1, $ip_province . $ip_city ); return $this->renderSuccess("登录成功", $account_token); } else { $userinfo = $wxServer->getUserInfo($user_base); $nickname = $userinfo['nickname']; $headimg = $userinfo['headimgurl']; if (!$nickname || !$headimg) { return $this->renderError('请求参数错误!'); } $pid = 0; $pid_pid = request()->param('pid', 0); if ($pid_pid > 0) { log::info("获取推荐人id" . $pid_pid); } if ($pid_pid) { $pid_info = User::where('id', '=', $pid_pid)->value("id"); if ($pid_info) { log::info("获取推荐人id" . $pid_info); $pid = $pid_info; } } Db::startTrans(); $res[] = $user_id = User::insertGetId([ 'openid' => $openid, 'nickname' => $nickname, 'headimg' => $headimg, 'pid' => $pid, 'addtime' => time(), 'click_id' => $click_id, 'uid' => '', ]); $time = time(); #token字符串 $token_num = getRandStr(10); #加密token $account_token = user_md5($user_id . $token_num . $time); #更新账号信息 $last_login_ip1 = $this->getRealIp(); $result = $this->ip_location($last_login_ip1); $ip_province = ''; $ip_city = ''; $ip_adcode = ''; if ($result) { $ip_province = $result['province']; $ip_city = $result['city']; $ip_adcode = $result['adcode']; } else { } $res[] = UserAccount::insert([ 'user_id' => $user_id, 'account_token' => $account_token, 'token_num' => $token_num, 'token_time' => $time, 'last_login_time' => $time, 'last_login_ip' => ip2long($last_login_ip1), 'last_login_ip1' => $last_login_ip1, 'ip_adcode' => $ip_adcode, 'ip_province' => $ip_province, 'ip_city' => $ip_city, ]); #记录登录日志 #推荐成功之后获取一张抽奖券 #配置 $rule = getConfig('base'); $draw_people_num = $rule['draw_people_num']; if (!empty($pid)) { $num = 0; $num = ProfitDraw::where(['type' => 5, 'user_id' => $pid, 'share_uid' => $user_id])->count(); if (bccomp("$num", "$draw_people_num") < 0) { #可以获得一张抽奖券 $res[] = User::changeDraw($pid, 1, 5, '获得一张抽奖券', $user_id); } } if (resCheck($res)) { // 新用户注册也要记录登录日志 UserLoginLog::recordLogin( $user_id, 'wechat_h5', $last_login_ip1, $ip_province . $ip_city ); Db::commit(); return $this->renderSuccess("登录成功", $account_token); } else { Db::rollback(); return $this->renderError("登录失败"); } } } catch (\Exception $e) { Log::error('错误信息' . $e->getMessage()); Log::error('错误行数' . $e->getLine()); return $this->renderError('非法请求'); } } public function ip_location($last_login_ip) { if ($last_login_ip) { $url = "https://restapi.amap.com/v3/ip?key=6a46ad822120e393956e89d498e8c40b&ip=" . "$last_login_ip" . ""; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($ch); curl_close($ch); $result = json_decode($result, true); if ($result['status'] == '1') { return $result; } else { return false; } } else { return false; } } /** * 绑定手机号 */ public function login_bind_mobile() { $user = $this->getUser(); $user_id = $user['id']; $code = request()->param("code", ''); $wxServer = new \app\common\server\Wx($this->app); $mobile = $wxServer->getMobile($code); // return $this->renderError($mobile,[$mobile,$code]); Db::startTrans(); $res = []; // $res[] = User::where(['id' => $user['id']])->update([ // 'mobile' => $mobile, // 'update_time' => time(), // ]); $user_mobile = User::where(['mobile' => $mobile])->find(); if ($user_mobile) { $old_user_account = UserAccount::where(['user_id' => $user_id])->find(); #修改openid $res[] = User::where(['id' => $user_mobile['id']]) ->update([ 'openid' => $user['openid'], // 'nickname' => $user['nickname'], // 'headimg' => $user['headimg'], ]); #修改token $res[] = UserAccount::where(['user_id' => $user_mobile['id']])->update([ 'account_token' => $old_user_account['account_token'], 'token_num' => $old_user_account['token_num'], 'token_time' => $old_user_account['token_time'], 'last_login_time' => $old_user_account['last_login_time'], 'last_login_ip' => $old_user_account['last_login_ip'], ]); #修改 $res[] = User::where(['id' => $user['id']])->delete(); $res[] = UserAccount::where(['user_id' => $user_id])->delete(); // $res[] = UserAccount::where(['user_id' => $user['id']])->update([ // 'token_time' => time(), // ]); } else { $res[] = User::where(['id' => $user['id']])->update([ 'mobile' => $mobile, 'update_time' => time(), ]); } if (resCheck($res)) { Db::commit(); return $this->renderSuccess("绑定成功2"); } else { Db::rollback(); return $this->renderSuccess("绑定成功3"); } } /** * 绑定手机号 */ public function login_bind_mobile_h5() { $user = $this->getUser(); $user_id = $user['id']; $mobile = request()->param("mobile", ''); Db::startTrans(); $res = []; $res[] = User::where(['id' => $user_id])->update([ 'mobile' => $mobile, 'update_time' => time(), ]); if (resCheck($res)) { Db::commit(); return $this->renderSuccess("绑定成功2"); } else { Db::rollback(); return $this->renderSuccess("绑定成功3"); } } /** * * * @return mixed */ public function getAccessTokenOffiaccountSign() { $wxServer = new \app\common\server\WechatOfficialAccount($this->app); $url = request()->param("url", ''); $data = $wxServer->getAccessTokenOffiaccountSign($url); return $this->renderSuccess('', $data); } public function test() { $account_token['token'] = "77f6358084be8d5545747911e7f9d5ad5644a114"; $account_token['logintype'] = "2"; return $this->renderSuccess("登录成功", $account_token); } public function test1() { $share_image = getConfig("base")['share_image']; $public_path = dirname($_SERVER['SCRIPT_FILENAME']); $poster_bg = $public_path . $share_image; // var_dump($poster_bg); // $rule = getConfig('base'); // $draw_people_num = $rule['draw_people_num']; // $user_id = 31; // $pid = 24; // if(!empty($pid)){ // $num = 0; // $num = ProfitDraw::where(['type'=>5,'user_id'=>$pid])->count(); // if(bccomp("$num","$draw_people_num") < 0){ // #可以获得一张抽奖券 // $res= User::changeDraw($pid, 1,5 , '获得一张抽奖券',$user_id); // var_dump($res); // } // } // log::info($res); } /** * 记录用户登录 * 小程序每次打开时调用此方法记录登录信息 */ public function recordLogin() { try { // $user_id = $this->getUserid1(); // //去redis中查询一下,如果存在今日的数据,则不在往下执行 // $redis = (new RedisHelper())->getRedis(); // $today = date('Y-m-d'); // $redis_key = "login_record:" . $today . ":" . $user_id; // $redis_data = $redis->get($redis_key); // if ($redis_data) { // return $this->renderSuccess('登录记录成功'); // } $user = $this->getUser(); if (empty($user)) { return $this->renderError('用户不存在'); } // 获取设备信息 $device = request()->param('device', ''); // 设备类型 $device_info = request()->param('device_info', ''); // 设备详细信息 // 获取IP和地理位置信息 $ip = $this->getRealIp(); $location = ''; $ip_province = ''; $ip_city = ''; $ip_adcode = ''; $result = $this->ip_location($ip); if ($result) { $ip_province = $result['province']; $ip_city = $result['city']; $ip_adcode = $result['adcode']; $location = $ip_province . $ip_city; } // 记录登录日志 UserLoginLog::recordLogin( $user['id'], $device, $ip, $location ); // //将数据写入redis,过期时间为当天剩余的时间 // $redis->set($redis_key, json_encode($user), 86400 - time() % 86400); return $this->renderSuccess('登录记录成功', [ 'uid' => $user['uid'] ?: $user['id'], 'nickname' => $user['nickname'], 'headimg' => imageUrl($user['headimg']) ]); } catch (\Exception $e) { Log::error('记录登录错误: ' . $e->getMessage()); Log::error('错误行数: ' . $e->getLine()); return $this->renderError('网络故障,请稍后再试'); } } }