2025-08-01 11:39:06 +08:00

439 lines
14 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace addons\third\library;
use addons\third\model\Third;
use app\common\model\User;
use fast\Random;
use think\Db;
use think\Exception;
/**
* 第三方登录服务类
*
*/
class Service
{
/**
* 第三方登录
* @param string $platform 平台
* @param array $params 参数
* @param array $extend 会员扩展信息
* @param int $keeptime 有效时长
* @return boolean
*/
public static function connect($platform, $params = [], $extend = [], $keeptime = 0)
{
$time = time();
$nickname = $params['nickname'] ?? ($params['userinfo']['nickname'] ?? '');
$avatar = $params['avatar'] ?? ($params['userinfo']['avatar'] ?? '');
$expires_in = $params['expires_in'] ?? 0;
$openid = !empty($params['openid']) ? $params['openid'] : '';
$unionid = !empty($params['unionid']) ? $params['unionid'] : '';
$values = [
'platform' => $platform,
'unionid' => $unionid,
'openid' => $openid,
'openname' => $nickname,
'access_token' => $params['access_token'] ?? '',
'refresh_token' => $params['refresh_token'] ?? '',
'expires_in' => $expires_in,
'logintime' => $time,
'expiretime' => $time + $expires_in,
];
$values = array_merge($values, $params);
$auth = \app\common\library\Auth::instance();
$auth->keeptime($keeptime);
$third = null;
//存在openid则先判断是否存在对应账号
if ($openid) {
$third = Third::get(['platform' => $platform, 'openid' => $openid], 'user');
}
//存在unionid就需要判断是否需要生成新记录
if (!$third && $unionid) {
$third = Third::get(['platform' => $platform, 'unionid' => $unionid], 'user');
}
if ($third) {
if (!$third->user) {
$third->delete();
$third = null;
} else {
//优化头像存储
$update = [
'nickname' => !$third->user->nickname || $third->user->nickname == '微信用户' ? ($nickname ?: '') : '',
'avatar' => !$third->user->avatar ? ($avatar ?: '') : ''
];
$data = array_filter($update);
if ($data) {
$third->user->save($data);
}
return $auth->direct($third->user_id);
}
}
// 如果已登录则直接绑定
if ($auth->id) {
$values['user_id'] = $auth->id;
Third::create($values, true);
$user = $auth->getUser();
return true;
}
// 先随机一个用户名,随后再变更为u+数字id
$username = Random::alnum(20);
$password = Random::alnum(6);
$domain = request()->host();
if (!empty($extend['mobile'])) {
$username = $extend['mobile'];
$nickname = $extend['nickname'] ?? substr_replace($username, '****', 3, 4);
}
Db::startTrans();
try {
// 默认注册一个会员
$result = $auth->register($username, $password, $username . '@' . $domain, '', $extend);
if (!$result) {
throw new Exception($auth->getError());
}
$user = $auth->getUser();
$username = 'u' . $user->id;
$email = $username . '@' . $domain;
$fields = [];
//判断用户名和邮箱是否已存在
$exist = User::getByUsername($username);
if (!$exist) {
$fields['username'] = $username;
}
$exist = User::getByEmail($email);
if (!$exist) {
$fields['email'] = $email;
}
//如果昵称为空或为微信用户则修改
if (!$user['nickname'] || $user['nickname'] == '微信用户') {
$fields['nickname'] = $nickname = $fields['username'];
}
if ($nickname) {
$fields['nickname'] = xss_clean(strip_tags($nickname));
}
if ($avatar) {
$fields['avatar'] = xss_clean(strip_tags($avatar));
}
// 更新会员资料
$user = User::get($user->id);
$user->save($fields);
if (!$third) {
// 保存第三方信息
$values['user_id'] = $auth->id;
Third::create($values, true);
}
Db::commit();
} catch (\Exception $e) {
Db::rollback();
\think\Log::record($e->getMessage());
$auth->logout();
return false;
}
return $auth->direct($user->id);
}
/**
* 判断是否绑定第三方
* @param string $platform 平台
* @param string $openid Openid
* @param string $apptype 平台类型(web/miniapp/mp)
* @param string $unionid Unionid
* @return bool
*/
public static function isBindThird($platform, $openid, $apptype = '', $unionid = '')
{
$conddtions = [
'platform' => $platform,
'openid' => $openid
];
if ($apptype) {
$conddtions['apptype'] = $apptype;
}
$third = Third::get($conddtions, 'user');
//第三方存在
if ($third) {
//用户失效
if (!$third->user) {
$third->delete();
return false;
}
return true;
}
if ($unionid) {
$third = Third::get(['platform' => $platform, 'unionid' => $unionid], 'user');
if ($third) {
//
if (!$third->user) {
$third->delete();
return false;
}
return true;
}
}
return false;
}
/**
* 判断是否在微信内
* @return bool
*/
public static function isWechat()
{
return strpos(request()->server('HTTP_USER_AGENT'), 'MicroMessenger') !== false;
}
/**
* 获取平台类型
* @return string
*/
public static function getApptype()
{
//如果是公众号则为mp,网页为web,小程序为miniapp单独判断
return self::isWechat() ? 'mp' : 'web';
}
/**
* 账号合并自动登录注册手机号唯一
* @param string $platform 平台
* @param array $params 参数
* @param array $extend 会员扩展信息
* @param int $keeptime 有效时长
* @return boolean
*/
public static function loginAndRegisterByMobile($platform, $params = [], $extend = [], $keeptime = 0)
{
$time = time();
$expires_in = $params['expires_in'] ?? 0;
$openid = !empty($params['openid']) ? $params['openid'] : '';
$unionid = !empty($params['unionid']) ? $params['unionid'] : '';
$apptype = !empty($params['apptype']) ? $params['apptype'] : 'miniapp';
if(!$apptype) $apptype= 'miniapp';
if(!$platform) $platform= 'wechat';
$mobile = !empty($params['mobile']) ? $params['mobile'] : '';
if(!$mobile)$mobile = !empty($extend['mobile']) ? $extend['mobile'] : '';
// if(!$mobile)throw new Exception("手机号不存在");
if(!$openid)throw new \Exception("openid不存在");
$nickname = $params['nickname'] ?? (config("site.default_nickname") . $mobile);
$avatar = $params['avatar'] ?? config("site.default_avatar");
$values = [
'platform' => $platform,
'apptype' => $apptype,
'unionid' => $unionid,
'openid' => $openid,
'openname' => $nickname,
'access_token' => $params['access_token'] ?? '',
'refresh_token' => $params['refresh_token'] ?? '',
'expires_in' => $expires_in,
'logintime' => $time,
'expiretime' => $time + $expires_in,
];
$values = array_merge($values, $params);
$auth = \app\common\library\Auth::instance();
$auth->keeptime($keeptime);
$third = Third::get(['platform' => $platform,'apptype'=>$apptype, 'openid' => $openid], 'user');
$user = null;
$judge_mobile_flag = false;//是否传手机号判断标识
$third_party_flag = false;//创建第三方账号流程判断标识
$register_user_flag = false;//创建用户判断标识
//修复用户信息缺失情况
if($third){
$user = $third->user;
if(!$user){
$third->delete();
$third = null;
}
}
if($third && $user){
//已绑定并查询到用户主账号
if(!$user['mobile']){
if(!$mobile)throw new \Exception("手机号不存在",30001);
$user->mobile = $mobile;
$user->save();
}
}else{
//不存在则未绑定继续判断
if($unionid){
$third = Third::get(['platform' => $platform,'apptype'=>$apptype, 'unionid' => $unionid], 'user');
if($third){
//用户为对方用户
$user = $third->user;
//创建第三方账号流程
$third_party_flag = true;
}else{
//回到是否传了手机号判断
$judge_mobile_flag = true;
}
}else{
//回到是否传了手机号判断
$judge_mobile_flag = true;
}
//手机号判断
if($judge_mobile_flag){
if(!$mobile)throw new \Exception("手机号不存在",30001);
//查询手机号是否可绑定
$user = User::where('mobile',$mobile)->find();
if(!$user){
//注册新用户
$register_user_flag = true;
//创建第三方账号流程
$third_party_flag = true;
}else{
$user_id = $user->id;
$third = Third::get(['user_id' => $user_id], 'user');
if(!$third){
//创建第三方账号流程
$third_party_flag = true;
}else{
//手机号已绑定其它三方账号
if($third->openid!=$openid){
throw new \Exception( "手机号已绑定其它三方账号",30001 );
}
}
}
}
}
Db::startTrans();
try {
if($register_user_flag){
// 先随机一个用户名,随后再变更为u+数字id
$username = Random::alnum(20);
$password = Random::alnum(6);
$domain = request()->host();
if (!empty($extend['mobile'])) {
$username = $extend['mobile'];
$nickname = $extend['nickname'] ?? config("site.default_nickname"). substr_replace($username, '****', 3, 4);
}
// 默认注册一个会员
$result = $auth->register($username, $password, $username . '@' . $domain, '', $extend);
if (!$result) {
throw new \Exception($auth->getError());
}
$user = $auth->getUser();
$username = 'u' . $user->id;
$email = $username . '@' . $domain;
$fields = [];
//判断用户名和邮箱是否已存在
$exist = User::getByUsername($username);
if (!$exist) {
$fields['username'] = $username;
}
$exist = User::getByEmail($email);
if (!$exist) {
$fields['email'] = $email;
}
//如果昵称为空或为微信用户则修改
if (!$user['nickname'] || $user['nickname'] == '微信用户') {
$fields['nickname'] = $nickname = $fields['username'];
}
if ($nickname) {
$fields['nickname'] = xss_clean(strip_tags($nickname));
}
if ($avatar) {
$fields['avatar'] = xss_clean(strip_tags($avatar));
}
// 更新会员资料
$user = User::get($user->id);
$user->save($fields);
//更新已认证方式
$user = User::where("id", $user->id)->find();
$verification = $user->verification;
$verification->mobile = 1;
$user->verification = $verification;
$user->save();
}
//登录
$res = $auth->direct($user->id);
if(!$res)throw new \Exception("登录失败");
//创建第三方账号流程
if($third_party_flag){
// 保存第三方信息
$values['user_id'] = $auth->id;
$third = Third::create($values, true);
$user = $third->user;
//已绑定并查询到用户主账号
if(!$user['mobile']){
if(!$mobile)throw new \Exception("手机号不存在",30001);
$user->mobile = $mobile;
$user->save();
//更新已认证方式
$user = User::where("id", $user->id)->find();
$verification = $user->verification;
$verification->mobile = 1;
$user->verification = $verification;
$user->save();
}
//更新已认证方式
$user = User::where("id", $user->id)->find();
$verification = $user->Verification;
$auth_type = $platform."_".$apptype;
$verification->{$auth_type} = 1;
$user->verification = $verification;
$user->save();
}
Db::commit();
} catch (Exception $e) {
\think\Log::record($e->getMessage());
$auth->logout();
Db::rollback();
throw new \Exception($e->getMessage());
// return false;
}
return true;
}
}