利用 微信小游戏 实现网站登录
文章目录
微信小游戏 实现网站登录.这应该是一个少有人操作的课题.我先开个头.
之前我网站是微信小程序扫码登录的.
QQ和支付宝都是小程序扫码登录的. 3个平台用的一套代码.
上个月突然我小程序被官方停用了,说"信息查询分类不对个人开放".申诉或者修改分类都不行,被迫注销了小程序.本来我有其他小程序代替的.
然后发现腾讯回收了 获取昵称和头像功能. --> 官方公告
所以用小程序实现网站登录已经没啥意义了.
获取微信头像昵称
目前还能成功获取微信用户头像和昵称的办法.
1,web应用,auth登录. (缺点:每年300块钱开发者认证费用)
2,手机APP应用. (缺点:每年300块钱开发者认证费用)
3,微信公众号用户列表 (缺点:仅关注公众号的用户)
4,微信小游戏.(缺点:小游戏加载比较慢)
适合个人且免费的办法,仅有小游戏了.根据上面的腾讯公告,小游戏是没有被回收用户昵称和头像获取能力的.
网站端
和之前一样代码一模一样,都不改
网站利用小程序SDK生成一个带参数二维码
说明
使用的是接口B生成无限制的小程序码. --> 官方文档
生成的小程序URL 大致是
page/index/index?scene=99834576a46802269885c413bdcfddbb
99834576a46802269885c413bdcfddbb就是生成的登录参数.参数存数据库.
有效期可以设置30分钟.(主要是小程序生成二维码每分钟次数有限,相同参数请求会扣掉次数,建议将二维码的二进制缓存到用户本地)
表现
小游戏端
参数获取
在game.js 入口获取传入的参数
if (wx.getLaunchOptionsSync().query.scene !== undefined) {
console.log("有参数:", wx.getLaunchOptionsSync().query.scene)
}
获取CODE
如果缓存有code那么直接用之前的,没有的话调用wx.login 可以静默获取.
注意,这个wx.login是异步的,有延时的.
var t_code = wx.getStorageSync('code') || "";
console.log("获取之前缓存的CODE:");
console.log(t_code);
//如果code空,那么还得触发login一次.
if (!t_code) {
wx.login({
success: res => {
console.log("获取code:", res.code);
wx.setStorageSync('code', res.code); //存起来,下次用
t_code = res.code;
}
})
}
读取缓存
主要是iv 和 encryptedData
var iv = wx.getStorageSync('iv') || "";
var rawData = wx.getStorageSync('rawData') || ""; //非必须
var signature = wx.getStorageSync('signature') || ""; //非必须
var encryptedData = wx.getStorageSync('encryptedData') || "";
没有缓存的话,就表示没有,必须用户授权才可以
创建按钮
小游戏必须用官方提供这个 wx.createUserInfoButton 按钮创建,和点击事件.
补充说明,这个按钮默认的Z-INDEX一般都在整个小游戏最上层.
if (!iv) {
const button = wx.createUserInfoButton({
type: 'text',
text: '授权登录GetCe.Cn',
style: {
width: 200,
height: 40,
left: (wx.getSystemInfoSync().windowWidth - 200) / 2,
top: (wx.getSystemInfoSync().windowHeight - 40 - 40) / 2,
lineHeight: 40,
backgroundColor: '#ff0000',
color: '#ffffff',
textAlign: 'center',
fontSize: 16,
borderRadius: 4
}
})
button.onTap((res) => {
// 用户点击授权后,此处可以获取到用户信息
console.log("成功获取到用户", res);
wx.setStorageSync('iv', res.iv); //网站登录用
wx.setStorageSync('rawData', res.rawData); //用户信息非加密部分,小游戏本身用
wx.setStorageSync('signature', res.signature); //非必须
wx.setStorageSync('encryptedData', res.encryptedData); //网站登录用
wx.setStorageSync('user_pic', res.userInfo.avatarUrl); //小游戏本身用
wx.setStorageSync('user_nick', res.userInfo.nickName);//小游戏本身用
iv = res.iv;
rawData = res.rawData;
signature = res.signature;
encryptedData = res.encryptedData;
user_pic = res.userInfo.avatarUrl;
user_nick = res.userInfo.nickName;
console.log("开始登录...");
var cc = {
'code': t_code,
'scene': scene,
'iv': iv,
'encryptedData': encryptedData,
}
_this.postLogin(cc); //post服务器
});
}
POST数据到服务器
成功或者失败后重启小游戏.(当然可以销毁登录按钮,继续小游戏)
参数只需要4个,详细见上一步代码.
var cc = {
'code': t_code, //wx.login获取
'scene': scene, //小程序扫码进来的scene值
'iv': iv, //点按钮用户授权登录后获取iv值
'encryptedData': encryptedData, //点按钮用户授权登录后获取encryptedData值
}
具体的小程序登录部分.
postLogin: function (cc) {
console.log("cc:", cc);
let url = 'https://api.getce.cn/*/*/*.html'; //你自己web服务器接收数据的.
wxhttp.post(url, cc).then((res) => {
if (res.data.code == 1) {
console.log("登录ok");
wx.showModal({
title: '提示',
content: "登录ok",
success(res) {
if (res.confirm) {
console.log('用户点击确定')
wx.restartMiniProgram();
} else if (res.cancel) {
console.log('用户点击取消')
wx.restartMiniProgram();
}
}
})
} else {
wx.showModal({
title: '提示',
content: "登录失败:" + res.data.msg,
success(res) {
if (res.confirm) {
console.log('用户点击确定');
wx.restartMiniProgram();
} else if (res.cancel) {
console.log('用户点击取消');
wx.restartMiniProgram();
}
}
})
}
});
}
网站端接收
这里我都是前面小程序登录的代码,一模一样,不需要改.
scene主要是判断哪个前台用户.
其他几个参数都是用于获取用户头像和昵称的.
获取session_key
这步是通过CODE获取.
其实这部就可以获取到UninoID,但是用户头像和昵称还有OpenID是获取不到的.
$res = @$this->miniapp->auth->session($code);
if (!empty($res) && !empty($res['session_key'])){
$session_key = $res['session_key'] ;
if (!empty($res['unionid'])){
$unionid=$res['unionid'];
}
}else{
return $this->error(-21703,'微信错误,考虑清空小程序缓存.','微信错误信息: ' . $res['errmsg']);
}
注意:
这个获取Session_key,同一个CODE只能获取一次.
不可以反复获取.一般短期内连续扫码会执行报错,因为CODE对小程序还在有效期.
所以自己要服务器缓存CODE和Session_key. CODE相同就用缓存,没有就用SDK获取新的Session_key.
解密用户信息
解密代码和解密后数据参考如下.
一般获取头像和昵称和 unionId 和 openId 即可.其他数据没啥用.
try {
$rrs = @$this->miniapp->encryptor->decryptData($session_key, $iv, $encryptedData);
} catch (Exception $e) {
throw new Exception('小程序解密异常,考虑清小程序缓存.');
}
/*
"rrs": {
"openId": "o1kM****************",
"nickName": "yake-job",
"gender": 1,
"language": "zh_CN",
"city": "Xinyu",
"province": "Jiangxi",
"country": "China",
"avatarUrl": "https://wx.qlogo.cn/mmopen/vi_32/WWCC67raM9t3A05kuyjmR3tXlLor4DQkFwmSBY3icN0YYjPtZudf2mBsVv1C5CGkaAibjKBDBicOysRP1nFqtgjrA/132",
"unionId": "o72nbt0K*************",
"watermark": {
"timestamp": 1543412981,
"appid": "wx8a18e3c3091991ef"
}
*/
新增或更新用户
根据 unionId 或者 openId判断自己网站有没有该用户.
推荐unionId.(微信开发者平台,绑定小程序,个人可以绑定5个,绑定后会返回unionId)
用户A,访问我名下所有小程序unionId是同一个的.(而openId是每个小程序都不同的.)
所以有unionId小程序挂了没有关系.换一个小程序又可以接盘. 而且解绑的小程序是会释放5个的那个额度的.
测试
已经成功安排到我网站.可以在网站底部,下方评论那里登录尝试登录本站.
扫码后
会自动打开小游戏.
这里有个按钮.
点击按钮
用户同意授权.可以选择默认头像或者自定义的昵称和头像.
成功登录
缺点
1,小游戏审核比普通小程序复杂很多.
2,小游戏加载比普通小程序要慢很多.
3,重要的一点,小游戏会弹出需要实名认证.未实名的用户无法成功进入小游戏.
不完美解决方法:
小游戏在执行后10秒后才会弹出实名认证的.
只要你手速够快,可以在10秒内点授权登录的.网站也可以成功获得用户信息.
如果不小心手慢了.那么微信下拉,小程序列表,长按小程序,删除. 然后重新扫码.下次快一点.