微信小游戏 实现网站登录.这应该是一个少有人操作的课题.我先开个头.

之前我网站是微信小程序扫码登录的.

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秒内点授权登录的.网站也可以成功获得用户信息.

如果不小心手慢了.那么微信下拉,小程序列表,长按小程序,删除. 然后重新扫码.下次快一点.