fastadmin+uniapp实现公众号登录
代码:/**
* 公众号登录
*/
public function mplogin()
{
// 参数
$params = $this->request->param();
// 公众号CODE
if (!empty($params['code'])) {
// 系统配置
$config = Config::get('nianbao');
// 未开启登录
if ($config['login_type'] == 0) {
$this->error('系统未开启登录');
}
// 用户已登录
if ($this->auth->isLogin()) {
$this->error('用户已登录', null, 300);
}
\think\Log::record('未登录执行1');
// 支付配置
$epay = get_addon_config('epay');
$appid = $epay['wechat']['app_id'];
$secret = $epay['wechat']['app_secret'];
$code = $params['code'];
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code";
$response = Http::post($url);
\think\Log::record($response);
$data = json_decode($response, true);
if (isset($data['errcode'])) {
$this->error('错误码:'.$data['errcode'].',错误信息:'.$data['errmsg']);
}
// 公众号注册登录
$third = null;
//存在openid则先判断是否存在对应账号
if ($data['openid']) {
$third = Third::get(['platform' => 'wechat', 'openid' => $data['openid']], 'user');
}
if ($third) {
\think\Log::record('已存在第三方粉丝数据');
if (!$third->user) {
\think\Log::record('第三方粉丝数据未绑定用户ID');
$third->delete();
$third = null;
} else {
//如果已存在第三方账号且已绑定用户ID则直接登录
\think\Log::record('已存在第三方粉丝数据且已绑定');
$direct = $this->auth->direct($third->user_id);
if ($direct) {
\think\Log::record('已存在第三方粉丝数据且已绑定并登录成功');
$userinfo = $this->auth->getUserinfo();
$userinfo['openid'] = $data['openid'];
$third->save(['logintime' => time()]);
// 处理头像
$userinfo['avatarUrl'] = cdnurl($userinfo['avatar'], true);
// 返回值
$return = [
'openid' => $data['openid'],
'userinfo' => $userinfo
];
$this->success('登录成功', $return);
} else {
\think\Log::record('已存在第三方粉丝数据且已绑定并登录失败');
$this->error('授权登录失败,请重试!');
}
}
}
// 当前时间戳
$time = time();
// 默认昵称
$nickname = '微信用户';
// 第三方粉丝表单
$values = [
'platform' => 'wechat',
'apptype' => 'mp',
'openid' => $data['openid'],
'openname' => $nickname,
'access_token'=> $data['access_token'] ?? '',
'refresh_token' => $data['refresh_token'] ?? '',
'expires_in' => $data['expires_in'],
'logintime' => $time,
'expiretime' => $time + $data['expires_in'],
];
// 如果用户已登录则第三方粉丝表直接绑定该用户
if ($this->auth->id) {
\think\Log::record('已存在第三方粉丝数据且已绑定并登录成功');
$values['user_id'] = $this->auth->id;
Third::create($values, true);
$userinfo = $this->auth->getUserinfo();
$userinfo['openid'] = $data['openid'];
// 处理头像
$userinfo['avatarUrl'] = cdnurl($userinfo['avatar'], true);
// 返回值
$return = [
'openid' => $data['openid'],
'userinfo' => $userinfo
];
$this->success('登录成功', $return);
}
// 用户未登录也未创建第三方粉丝账号执行以下代码
// 先随机一个用户名,随后再变更为u+数字id
$username = Random::alnum(20);
$email = $data['openid'] . '@wechat.com';
Db::startTrans();
$result = false;
try {
// 注册会员账号
$extend = [
'group_id' => 1,
'avatar' => $config['avatar']
];
$register = $this->auth->register($username, Random::alnum(6), $email, '', $extend);
if (!$register) {
throw new Exception($this->auth->getError());
}
// 注册后获取会员信息
$user = $this->auth->getUser();
// 重置用户名
$username = $time . 'u' . $user->id;
$fields = [];
//判断用户名和邮箱是否已存在
$existusername = UserModel::getByUsername($username);
if (!$existusername) {
$fields['username'] = $username;
}
$existemail = UserModel::getByEmail($email);
if (!$existemail) {
$fields['email'] = $email;
}
//如果昵称为空或为微信用户则修改
if (!$user['nickname'] || $user['nickname'] == '微信用户') {
$fields['nickname'] = $nickname = $fields['username'];
}
if ($nickname) {
$fields['nickname'] = xss_clean(strip_tags($nickname));
}
// 更新会员资料
$user = UserModel::get($user->id);
$user->save($fields);
if (!$third) {
// 保存第三方信息
$values['user_id'] = $this->auth->id;
Third::create($values, true);
}
$result = true;
Db::commit();
} catch (\Exception $e) {
Db::rollback();
\think\Log::record($e->getMessage());
$this->auth->logout();
$result = false;
}
if ($result === false) {
$this->error('公众号登录失败');
}
$userinfo = $this->auth->getUserinfo();
$userinfo['openid'] = $data['openid'];
// 处理头像
$userinfo['avatarUrl'] = cdnurl($userinfo['avatar'], true);
// 返回值
$return = [
'openid' => $data['openid'],
'userinfo' => $userinfo
];
$this->success('登录成功', $return);
}
$this->error('code参数不正确');
}
uniapp端:
<template>
<view class="container">
<view class="nui-userbox">
<view class="nui-user-left">
<image :src="userinfo.avatarUrl" class="nui-avatar" mode="widthFix"></image>
</view>
<view class="nui-user-right">
<view class="nui-nickname">
{{userinfo.nickname}}
</view>
</view>
</view>
<tui-footer :fixed="false" :copyright="copyright"></tui-footer>
<!-- 登录弹窗 -->
<tui-modal :show="loginbox" :maskClosable="false" @cancel="hideLogin" :custom="true">
<view class="tui-modal-custom">
<view class="tui-prompt-title">提示</view>
<view class="tui-modal-custom-text">您尚未登录,请先登录</view>
<view class="tui-btn-box">
<view class="nui-btn">
<tui-button height="72rpx" :size="28" type="gray" shape="circle" @click="notLogin">暂不登录</tui-button>
</view>
<view class="nui-btn">
<!-- #ifdef H5 -->
<tui-button height="72rpx" :size="28" type="warning" shape="circle" @click="hfivelogin">去登录</tui-button>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<tui-button height="72rpx" :size="28" type="green" shape="circle" @click="authlogin">授权登录</tui-button>
<!-- #endif -->
</view>
</view>
</view>
</tui-modal>
<!-- 授权获取手机号 -->
<tui-modal :show="mobileloginbox" :maskClosable="false" @cancel="hideMobileLogin" :custom="true">
<view class="tui-modal-custom">
<view class="tui-prompt-title">授权获取您的手机号</view>
<view class="tui-modal-custom-text">只差最后一步,绑定手机即可登录哦</view>
<view class="tui-btn-box">
<view class="nui-btn">
<tui-button height="72rpx" :size="28" type="gray" shape="circle" @click="notLogin">拒绝授权</tui-button>
</view>
<view class="nui-btn">
<!-- #ifdef MP-WEIXIN -->
<tui-button height="72rpx" :size="28" type="green" shape="circle" openType="getPhoneNumber" @getphonenumber="bindgetphonenumber">授权手机号</tui-button>
<!-- #endif -->
</view>
</view>
</view>
</tui-modal>
</view>
</template>
<script>
const app = getApp();
export default {
data() {
return {
userinfo: {
avatarUrl: '/static/mine_def_touxiang_3x.png',
nickname: '请先登录'
},
appid: '',//公众号appid
scope: 'snsapi_base',
openid: '',
loginbox: false,//登录弹框
mobileloginbox: false,//授权手机号弹框
copyright: '©2024 企业登记',
}
},
onLoad() {
uni.setNavigationBarColor({
backgroundColor: app.globalData.topbgcolor,
frontColor: app.globalData.toptcolor
})
let that = this;
that.tui.request('user/index').then((res) => {
console.log(res)
if (res.code == 1) {
that.appid = res.data.appid,//公众号appid
that.copyright = res.data.copyright;
if (res.data.userinfo) {
that.userinfo = res.data.userinfo;
that.openid = res.data.openid;
uni.setStorageSync('userinfo', res.data.userinfo);
uni.setStorageSync('openid', res.data.openid);
}
// #ifdef H5
if (!res.data.login) {
if (that.isWeiXin()) {
console.log('在微信内')
let code = that.getUrlCode('code');
if (code) {
console.log(code)
// Url有code参数
that.checkWeChatCode(code);
} else {
// Url没有code参数,需要发起公众号授权
that.getWeChatCode();
}
} else {
that.loginbox = true;
}
}
// #endif
}
})
},
onShow() {
let that = this;
var userinfo = uni.getStorageSync('userinfo');
if (!that.isWeiXin()) {
if (!userinfo) {
that.loginbox = true;
} else {
that.tui.request('user/checklogin').then((res) => {
console.log(res);
if (res.code == 1) {
that.hideLogin();
that.userinfo = res.data.userinfo;
that.openid = res.data.openid;
uni.setStorageSync('userinfo', res.data.userinfo);
uni.setStorageSync('openid', res.data.openid);
} else if (res.code == 200) {
uni.removeStorageSync('userinfo');
that.loginbox = true;
} else {
uni.showModal({
title: '提示',
content: res.msg,
showCancel: false,
success() {
uni.reLaunch({
url: '/pages/index/index'
})
}
})
}
})
}
}
},
methods: {
// 关闭登录框
hideLogin() {
this.loginbox = false;
},
// 关闭授权手机号弹框
hideMobileLogin() {
this.mobileloginbox = false;
},
// 暂不登录
notLogin() {
this.hideLogin();
uni.navigateBack();
},
// H5登录
hfivelogin() {
this.hideLogin();
uni.navigateTo({
url: '/pages/user/login'
})
},
// 小程序授权登录
authlogin() {
// #ifdef MP-WEIXIN
uni.login({
onlyAuthorize: true,
success(t) {
console.log(t)
that.tui.request('user/authlogin', {
code: t.code
}).then((res) => {
console.log(res)
if (res.code == 1) {
that.userinfo = res.data.userinfo;
uni.setStorageSync('userinfo', res.data.userinfo);
uni.setStorageSync('openid', res.data.openid);
uni.showToast({
title: res.msg,
icon: 'none'
})
} else if (res.code == 2) {
// 获取openid成功
that.openid = res.data.openid;
that.loginbox = true;
} else {
uni.showModal({
title: '提示',
content: res.msg,
success() {
uni.reLaunch({
url: '/pages/index/index'
})
}
})
}
})
},
fail(t) {
console.log(t)
uni.showModal({
title: '提示',
content: '授权失败,请稍后重试!',
success() {
uni.reLaunch({
url: '/pages/index/index'
})
}
})
}
})
// #endif
},
// 微信授权登录
bindgetphonenumber(e) {
console.log(e)
this.hideLogin();
var that = this;
if (e.errMsg == 'getPhoneNumber:fail user deny') {
uni.showModal({
title: '提示',
content: '无法获取你的手机号',
showCancel: false,
success() {
that.loginbox = true;
}
})
return;
}
// 推广商户
var hotel_id = uni.getStorageSync('hotel_id') || 0;
// 注册登录
that.tui.request('user/mobilelogin', {
code: e.code,
openid: that.openid,
hotel_id: hotel_id
}).then((res) => {
// console.log(res)
if (res.code == 1) {
// uni.removeStorageSync('hotel_id');
that.userinfo = res.data.userinfo;
uni.setStorageSync('userinfo', res.data.userinfo);
}
uni.showToast({
title: res.msg,
icon: 'none'
})
})
},
// 判断是否微信内访问
isWeiXin() {
let ua = window.navigator.userAgent.toLowerCase();
// console.log(ua)
if (ua.match(/MicroMessenger/i) == 'micromessenger') {
return true;
} else {
return false;
}
},
// 获取公众号授权登录回调结果code
getUrlCode(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, '']).replace(/\+/g, '%20')) || null
},
// 发起公众号授权获取code
getWeChatCode() {
// console.log(this.appid)
let appid = this.appid;
let local = encodeURIComponent(window.location.href);
let scope = this.scope;
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${local}&response_type=code&scope=${scope}&state=1#wechat_redirect`;
},
// 将code发送服务端获取用户openid
checkWeChatCode(code) {
var that = this;
if (code) {
// 这里需要有一个逻辑判断公众号授权用户未注册自动注册并登录,已注册就登录
that.tui.request('user/mplogin', {
code: code
}).then((res) => {
console.log(res)
if (res.code == 1) {
that.openid = res.data.openid;
that.userinfo = res.data.userinfo;
uni.setStorageSync('userinfo', res.data.userinfo);
uni.setStorageSync('openid', res.data.openid);
} else {
uni.showModal({
title: '提示',
content: res.msg,
showCancel: false,
success() {
uni.reLaunch({
url: '/pages/index/index'
})
}
})
}
})
}
}
}
}
</script>
<style>
page {
background-color: #f5f5f5;
}
.nui-userbox {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
box-sizing: border-box;
background-color: #ffffff;
}
.nui-user-left {
width: 25%;
}
.nui-avatar {
width: 90%;
height: auto;
display: block;
border-radius: 50%;
}
.nui-user-right {
width: 75%;
}
/* 登录框 */
.tui-modal-custom {
text-align: center;
}
.tui-modal-custom-text {
font-size: 30rpx;
color: #333;
padding: 30rpx 0 50rpx;
}
.tui-prompt-title {
padding-bottom: 20rpx;
font-size: 34rpx;
}
.tui-btn-box {
display: flex;
justify-content: space-between;
align-items: center;
}
.nui-btn {
width: 45%;
}
</style>
/**
* 检查登录
*/
public function checklogin()
{
// 系统配置
$config = Config::get('nianbao');
// 请求参数
$params = $this->request->param();
// 开启登录
if ($config['login_type'] == 1) {
if (!$this->auth->isLogin()) {
$this->error('您尚未登录或登录已失效', null, 200);
} else {
$userinfo = $this->auth->getUserinfo();
// 头像
$userinfo['avatarUrl'] = cdnurl($userinfo['avatar'], true);
// 第三方会员
$third = Third::where(['user_id'=>$this->auth->id, 'platform'=>$params['platform'], 'apptype'=>$params['apptype']])->find();
$openid = '';
if (!empty($third)) {
$openid = $third->openid;
}
$this->success('用户已登录', ['userinfo'=>$userinfo, 'openid'=>$openid]);
}
}
$this->error('系统未开启登录');
}
页:
[1]