1. 微信登录思路:
1. 在main.js 中封装公共函数,用于判断用户是否登录
2. 在main.js 中分定义全局变量,用于存储接口地址
3. 如果没有登录、则跳转至登录页面
4. 进入登录页面
5. 通过 wx.login 获取用户的 code
6. 通过 code 获取用户的 SessionKey、OpenId 等信息【本应后台接口、但是此处使用js发送请求】
7. 通过 openId 调用后台 Api 获取用户的信息
8. 获取成功,则说明已经授权过了,直接登录成功
9. 获取失败,则说明没有授权过,需要授权之后才能进行登录
10. 用户点击页面微信登录按钮【 】
11. 获取用户数据,然后调用后台接口写入数据库
2. 在 applets/main.js 中添加如下
~~~js
// 封装全局登录函数
// backpage, backtype 2个参数分别代表:
// backpage : 登录后返回的页面
// backtype : 打开页面的类型[1 : redirectTo 2 : switchTab]
Vue.prototype.checkLogin = function( backpage, backtype ){
// 同步获取本地数据(uid、随机码、用户名、头像)
var user_id = uni.getStorageSync('user_id');
var user_nu = uni.getStorageSync('user_nu');
var user_nm = uni.getStorageSync('user_nm');
var user_fa = uni.getStorageSync('user_fa');
if( user_id == '' || user_nu == '' || user_fa == ''){
// 使用重定向的方式跳转至登录页面
uni.redirectTo({url:'../login/login?backpage='+backpage+'&backtype='+backtype});
return false;
}
// 登录成功、已经登录返回数组 [用户 id, 用户随机码, 用户昵称, 用户表情]
return [user_id, user_nu, user_nm, user_fa];
}
// 定义一个全局的请求地址
Vue.prototype.apiServer = 'http://0608.cc/'
~~~
3. 在 pages/login/login.vue 中添加如下
~~~vue
<template>
<view>
<!-- login view html start -->
<view>
<view>
<view class="header"><image src="/static/img/public/login-wx.png"></image></view>
<view class="content">
<view>申请获取以下权限</view>
<text>获得你的公开信息(昵称,头像、地区等)</text>
</view>
<button class="bottom" type="primary" open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo">授权登录</button>
</view>
</view>
<!-- login view html end -->
</view>
</template>
<script>
export default {
data() {
return {
appid: '*************',
secret: '*************************',
code: '',
sessionKey: '',
openId: '',
userInfo: {
avatarUrl: '',
city: '',
country: '',
gender: 1,
language: '',
nickName: ''
},
pageOption: {}
};
},
methods: {
// 第一授权获取用户信息 ===》按钮触发
wxGetUserInfo() {
let _self = this;
// 1.获取用户的信息
uni.getUserInfo({
provider: 'weixin',
success: ( infoRes ) => {
console.log( infoRes )
_self.userInfo = infoRes.userInfo
// 2.提交数据到后台、写入数据库
uni.request({
url: _self.apiServer + 'appletsUserInfo',
data: {
openid: _self.openId,
avatarUrl: _self.userInfo.avatarUrl,
city: _self.userInfo.city,
country: _self.userInfo.country,
gender: _self.userInfo.gender,
language: _self.userInfo.language,
nickName: _self.userInfo.nickName
},
method: 'POST',
success: res => {
if( res.data.code != 0 )
{
uni.showToast({ title: res.data.msg, icon: 'none' });
return false;
}
// 用户信息写入缓存
uni.showToast({title: '登录成功'})
uni.setStorageSync( 'user_id', res.data.res.u_id );
uni.setStorageSync( 'user_nm', res.data.res.u_nickName );
uni.setStorageSync( 'user_fa', res.data.res.u_avatarUrl );
uni.setStorageSync( 'user_nu', res.data.res.u_regtime );
// 然后跳回原页面
if( _self.pageOption.backtype == 1 )
{
uni.redirectTo({ url: _self.pageOption.backpage })
}else{
uni.switchTab({ url: _self.pageOption.backpage })
}
},
fail: () => {
uni.showToast({ title: '用户信息操作失败', icon: 'none' });
}
});
},
fail: () => {
uni.showToast({ title: '获取用户信息失败', icon: 'none' });
}
});
return false
},
// 登录
login() {
let _self = this;
// 0. 显示加载的效果
uni.showLoading({
title: '登录中...'
});
// 1. wx 获取登录用户 code
uni.login({
provider: 'weixin',
success: loginRes => {
console.log(loginRes);
_self.code = loginRes.code;
// 2. 将用户登录code传递到后台置换用户SessionKey、OpenId等信息
uni.request({
url:
'https://api.weixin.qq.com/sns/jscode2session?appid=' +
_self.appid +
'&secret=' +
_self.secret +
'&js_code=' +
_self.code +
'&grant_type=authorization_code',
success: codeRes => {
console.log(codeRes);
_self.openId = codeRes.data.openid;
_self.sessionKey = codeRes.data.session_key;
// 3.通过 openId 判断用户是否授权
uni.request({
url: _self.apiServer + 'loginApplets',
data: {
openid: _self.openId
},
method: 'POST',
success: openIdRes => {
console.log(openIdRes);
// 隐藏loading
uni.hideLoading();
// 还没授权登录、请先授权然后登录
if (openIdRes.data.code == 1) {
// 提示消息、让用户授权
uni.showToast({ title: openIdRes.data.msg, icon: 'none' });
}
// 已经授权了、查询到用户的数据了
if (openIdRes.data.code == 0) {
// 用户信息写入缓存
uni.showToast({title: '登录成功'})
uni.setStorageSync( 'user_id', openIdRes.data.res.u_id );
uni.setStorageSync( 'user_nm', openIdRes.data.res.u_nickName );
uni.setStorageSync( 'user_fa', openIdRes.data.res.u_avatarUrl );
uni.setStorageSync( 'user_nu', openIdRes.data.res.u_regtime );
// 然后跳回原页面
if( _self.pageOption.backtype == 1 )
{
uni.redirectTo({ url: _self.pageOption.backpage })
}else{
uni.switchTab({ url: _self.pageOption.backpage })
}
}
},
fail: () => {
uni.showToast({ title: '获取授权信息失败', icon: 'none' });
return false;
}
});
},
fail: () => {
uni.showToast({ title: '获取 SesssionKey OpenId 失败', icon: 'none' });
return false;
}
});
},
fail: () => {
uni.showToast({ title: '获取 code 失败', icon: 'none' });
return false;
}
});
return false;
}
},
onLoad( options ) {
// 接收跳转的参数
this.pageOption = options
//默认加载
this.login();
}
};
</script>
<style>
.header {
margin: 90rpx 0 90rpx 50rpx;
border-bottom: 1px solid #ccc;
text-align: center;
width: 650rpx;
height: 300rpx;
line-height: 450rpx;
}
.header image {
width: 200rpx;
height: 200rpx;
}
.content {
margin-left: 50rpx;
margin-bottom: 90rpx;
}
.content text {
display: block;
color: #9d9d9d;
margin-top: 40rpx;
}
.bottom {
border-radius: 80rpx;
margin: 70rpx 50rpx;
font-size: 35rpx;
}
</style>
~~~
4. 在 pages/my/my.vue 中添加如下:
~~~vue
<template>
<view>我的页面</view>
</template>
<script>
var loginRes;
export default {
data() {
return {};
},
onLoad() {
// 加载定义好的方法
loginRes = this.checkLogin('../my/my', 2);
// 没有登录成功,返回空
if (!loginRes) {
return;
}
},
methods: {}
};
</script>
<style></style>
~~~
5. PHP 接口 loginApplets
~~~php
public function loginApplets(Request $request, UserInfo $userInfo)
{
// 获取数据
$data['u_openid'] = $request->param('openid', '');
// 验证数据
$rule = [
'u_openid' => 'require|max:200|min:10'
];
$message = [
'u_openid.require' => 'openid 不能为空',
'u_openid.max' => 'openid 格式错误',
'u_openid.min' => 'openid 格式错误'
];
$validate = Validate::rule($rule)->message($message);
if (!$validate->check($data)) {
return json(['code' => 1, 'msg' => $validate->getError(), 'res' => null]);
}
// 根据 openid 判断是否存在
$where['u_openid'] = $data['u_openid'];
$user = $userInfo->selOne($where);
if (!$user) {
return json(['code' => 1, 'msg' => '还没授权登录、请先授权然后登录', 'res' => $user]);
}
return json(['code' => 0, 'msg' => '已授权获取到用户的数据', 'res' => $user]);
}
~~~
6. PHP 接口 appletsUserInfo
~~~php
public function appletsUserInfo(Request $request, UserInfo $userInfo)
{
// 获取数据
$data['u_openid'] = $request->param('openid', '');
$data['u_avatarUrl'] = $request->param('avatarUrl', '');
$data['u_city'] = $request->param('city', '');
$data['u_country'] = $request->param('country', '');
$data['u_gender'] = $request->param('gender', '');
$data['u_language'] = $request->param('language', '');
$data['u_nickName'] = $request->param('nickName', '');
// 验证数据
$rule = [
'u_openid' => 'require|max:200|min:10',
'u_avatarUrl' => 'require',
'u_nickName' => 'require'
];
$message = [
'u_openid.require' => 'openid 不能为空',
'u_openid.max' => 'openid 格式错误',
'u_openid.min' => 'openid 格式错误',
'u_avatarUrl.require' => '用户头像 不能为空',
'u_nickName.max' => '用户名 格式错误',
];
$validate = Validate::rule($rule)->message($message);
if (!$validate->check($data)) {
return json(['code' => 1, 'msg' => $validate->getError(), 'res' => null]);
}
// 根据 openid 判断是否存在
$where['u_openid'] = $data['u_openid'];
$user = $userInfo->selOne($where);
// 存在、执行修改
if ($user) {
$user_res = $userInfo->updOne($where, $data);
$res = [];
$res['u_id'] = $user['u_id'];
$res['u_regtime'] = $user['u_regtime'];
}
// 不存在、执行添加
if (empty($user)) {
$res = [];
$res = $data;
$res['u_regtime'] = time();
$res['u_id'] = $userInfo->addOne($res);
}
// 判断是否添加成功
if (empty($res['u_id'])) {
return json(['code' => 1, 'msg' => '注册失败,返回重试', 'res' => null]);
}
return json(['code' => 0, 'msg' => 'ok', 'res' => $res]);
}
~~~
7. 完工!!!
- thinkphp6执行流程(一)
- php中use关键字用法详解
- Thinkphp6使用腾讯云发送短信步骤
- 路由配置
- Thinkphp6,static静态资源访问路径问题
- ThinkPHP6.0+ 使用Redis 原始用法
- smarty在thinkphp6.0中的最佳实践
- Thinkphp6.0 搜索器使用方法
- 从已有安装包(vendor)恢复 composer.json
- tp6with的用法,表间关联查询
- thinkphp6.x多对多如何添加中间表限制条件
- thinkphp6 安装JWT
- 缓存类型
- 请求信息和HTTP头信息
- 模型事件用法
- 助手函数汇总
- tp6集成Alipay 手机和电脑端支付的方法
- thinkphp6使用jwt
- 6.0session cookie cache
- tp6笔记
- TP6(thinkphp6)队列与延时队列
- thinkphp6 command(自定义指令)
- command(自定义指令)
- 本地文件上传
- 缓存
- 响应
- 公共函数配置
- 七牛云+文件上传
- thinkphp6:访问多个redis数据源(thinkphp6.0.5 / php 7.4.9)
- 富文本编辑器wangEditor3
- IP黑名单
- 增删改查 +文件上传
- workerman 定时器操作控制器的方法
- 上传文件到阿里云oss
- 短信或者邮箱验证码防刷代码
- thinkphp6:访问redis6(thinkphp 6.0.9/php 8.0.14)
- 实现关联多个id以逗号分开查询数据
- thinkphp6实现邮箱注册功能的细节和代码(点击链接激活方式)
- 用mpdf生成pdf文件(php 8.1.1 / thinkphp v6.0.10LTS )
- 生成带logo的二维码(php 8.1.1 / thinkphp v6.0.10LTS )
- mysql数据库使用事务(php 8.1.1 / thinkphp v6.0.10LTS)
- 一,创建过滤IP的中间件
- 源码解析请求流程
- 验证码生成
- 权限管理
- 自定义异常类
- 事件监听event-listene
- 安装与使用think-addons
- 事件与多应用
- Workerman 基本使用
- 查询用户列表按拼音字母排序
- 扩展包合集
- 查询用户数据,但是可以通过输入用户昵称来搜索用户同时还要统计用户的文章和粉丝数
- 根据图片的minetype类型获取文件真实拓展名思路
- 到处excel
- 用imagemagick库生成缩略图
- 生成zip压缩包并下载
- API 多版本控制
- 用redis+lua做限流(php 8.1.1 / thinkphp v6.0.10LTS )
- 【thinkphp6源码分析三】 APP类之父, 容器Container类
- thinkphp6表单重复提交解决办法
- 小程序授权
- 最简单的thinkphp6导出Excel
- 根据访问设备不同访问不同模块
- 服务系统
- 前置/后置中间件
- 给接口api做签名验证(php 8.1.1 / thinkphp v6.0.10LTS )
- 6实现邮箱注册功能的细节和代码(点击链接激活方式)
- 使用前后端分离的验证码(thinkphp 6.0.9/php 8.0.14/vue 3.2.26)
- 前后端分离:用jwt+middleware做用户登录验证(php 8.1.1 / thinkphp v6.0.10LTS )
- vue前后端分离多图上传
- thinkphp 分组、页面跳转与ajax
- thinkphp6 常用方法文档
- 手册里没有的一些用法
- Swagger 3 API 注释
- PHP 秒级定时任务
- thinkphp6集成gatewayWorker(workerman)实现实时监听
- thinkphp6按月新增数据表
- 使用redis 实现消息队列
- api接口 统一结果返回处理类
- 使用swoole+thinkphp6.0+redis 结合开发的登录模块
- 给接口api做签名验证
- ThinkPHP6.0 + UniApp 实现小程序的 微信登录
- ThinkPHP6.0 + Vue + ElementUI + axios 的环境安装到实现 CURD 操作!
- 异常$e
- 参数请求验证自定义和异常错误自定义