• 微信开放平台开发第三方授权登陆(四):微信小程序


    本文转载自:https://blog.csdn.net/qq_34190023/article/details/82351505

    开发小程序需要在公众平台注册一个小程序账号,然后获取到小程序的AppID和AppSecret。就可以进行第三方登陆授权开发。

    一、需求

    拥有第三方微信登录功能,并获取到用户信息。

    二、开发流程

    小程序:

    1. 微信小程序通过wx.login API进行登录获取code。由于AppID和AppSecret不能泄露给用户,根据code获取openid需要在服务端完成,所以需要将code发送给服务端

    (服务端),并且带上授权临时票据code参数;

    2. 服务端通过code和appid、APPSecret获取到openid和SessionKey。服务端需要返回自定义登录态给前端,不能返回SessionKey

    3. 前端保存自定义登录态,获取用户信息时携带自定义登录态给后端。

    获取Token的流程 

    三、开发使用的技术及工具

    1、.后端采用IDEA2017 进行开发

    2、前端使用微信开发者工具V1.02进行开发

    3、使用fastJson对json数据进行处理

    四、具体实现步骤

    1.前端(小程序)

    目录结构如下:

    1)自定义的全局变量

    globalData: {
     
        userInfo: null,
     
        sessionkey:null
     
      }

    自定义userInfo用于存储用户信息

    sessionKey用于存储服务端发回给客户端的sessionkey

    2)index加载时进行登录

    用户登录后,服务端会返回一个sessionkey给客户端保存,如果为空,说明没有登录过,需要调用wx.login进行登录。

    调用wx.login后,微信会返回一个code给小程序,小程序需要通过这个code发送给自身的服务端来获取sessionkey和openid信息。

    onLoad: function() {
     
        var serverUrl = app.serverUrl;
     
        // 加载时,检查当前用户信息是否登录
     
        if (app.globalData.sessionkey != null) { // 已经登录了
     
          // 是否授权
     
          wx.getSetting({
     
            success: function(res) {
     
              if (res.authSetting['scope.userInfo']) {
     
                // 已经授权,可以直接调用 getUserInfo 获取头像昵称
     
                wx.getUserInfo({
     
                  success: function(res) {
     
                    app.globalData.userInfo = JSON.parse(res.rawData);
     
                  }
     
                })
     
              } else {
     
                // 还没有授权,则需要授权
     
                wx.redirectTo({
     
                  url: '../authorization/authorization'
     
                })
     
              }
     
            }
     
          })
     
        } else { // 还没有登录
     
          // 提示用户登录授权
     
          wx.login({
     
            success: res => {
     
              // 发送 res.code 到后台换取 openId, sessionKey, unionId
     
              if (res.code) {
     
                // 发送请求,服务端能获取到openid和unionid,之前登录过则可以获取到之前的用户信息。
     
                wx.request({
     
                  url: serverUrl + '/miniprogram/login/' + res.code, //请求路径
     
                  method: "GET",
     
                  success: function(res) {
     
                    app.globalData.sessionkey = res.data;
     
                    // 进入授权
     
                    wx.redirectTo({
     
                      url: '../authorization/authorization'
     
                    })
     
                  }
     
                })
     
              }
     
            }
     
          })
     
        }
     
    },

    登录成功后,重定向到授权页面

    3)授权页面authorization.wxml

    <view class='tag-title'>
     
      <image mode="widthFix" style='  200rpx;height: 200rpx;margin-top:150rpx' src="/images/logo.jpg"></image>
     
    </view>
     
    <view wx:if="{{canIUse}}">
     
      <view style='text-align:center;margin-top:50rpx'>
     
        允许微信授权后,可体验更多功能</view>
     
      <view>
     
        <button open-type='getUserInfo' bindgetuserinfo="bindGetUserInfo" >授权登录</button>
     
        <button bindtap='navigateBack'>返回首页</button>
     
      </view>
     
    </view>
     
    <view wx:else style='text-align:center;margin-top:50rpx'>
     
      您的微信版本过低,请升级后再次体验</view>

    Button的open-type为getUserInfo时,点击后会调用bindgetuserinfo属性配置的函数,同时带上用户基本信息(不包括Openid等)

    4)用户信息发送给后端

    // 授权登录按钮
     
      bindGetUserInfo: function(e) {
     
        let that = this;
     
        var serverUrl = app.serverUrl;
     
        console.log(e.detail.userInfo)
     
        if (e.detail.userInfo) {  // 成功获取到信息
     
          app.globalData.userInfo = e.detail.userInfo
     
          // 这里可以将用户信息发送给后台
     
          // 获取到sessionkey
     
          if (app.globalData.sessionkey!=null){
     
            wx.request({
     
              url: serverUrl + '/miniprogram/userinfo', //请求路径,
     
              method: "GET",
     
              data: {
     
                // openid: this.openid,
     
                // unionid: this.unionid,
     
                key: app.globalData.sessionkey,
     
                nickname: app.globalData.userInfo.nickName, //获取昵称
     
                gender: app.globalData.userInfo.gender, //获取性别
     
                province: app.globalData.userInfo.province, //获取省份
     
                city: app.globalData.userInfo.city, //获取城市
     
                country: app.globalData.userInfo.country, //获取国家
     
                avatarUrl: app.globalData.userInfo.avatarUrl, //这些是用户的基本信息
     
                language: app.globalData.userInfo.language
     
              },
     
              success: function (res) {
     
                if (res.data.code == 0) {  // 请求成功
     
                  debugger
     
                  app.globalData.userInfo = res.data.data; // 以数据库中返回的数据为准
     
                  // 获取用户信息成功
     
                  wx.switchTab({
     
                    url: '../mine/mine'
     
                  })
     
                }
     
              }
     
            })
     
          }else{
     
            this.showZanTopTips('错误:SessionKey为null');
     
          }
     
     
     
        } else {
     
          this.showZanTopTips('您拒绝了微信授权');
     
        }
     
      },
     
     
     
    }));

    获取用户信息成功后,页面跳转到mine中显示用户详情信息

    5)用户详情页mine.wxml

    <view class="container more">
     
      <view class="userinfo">
     
        <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
     
        <text class="userinfo-nickname">{{userInfo.nickName}}</text>
     
              <text class="userinfo-nickname">性别:{{userInfo.gender === 1 ? '男':'女'}}</text>
     
              <text class="userinfo-nickname">城市:{{userInfo.city}}</text>
     
              <text class="userinfo-nickname">省份:{{userInfo.province}}</text>
     
              <text class="userinfo-nickname">国家:{{userInfo.country}}</text>
     
              <text class="userinfo-nickname">使用语言:{{userInfo.language}}</text>
     
      </view>
     
    </view>

    2.服务端(Java)

    服务端需要做的是:接受小程序前端发送的请求,根据发送过来的code,以及服务端保存的AppId和APPSecret等向微信服务端发送请求,获取到sessionkey和openid,然后将二者关联起来保存到session存储器中(Redis),返回给前端key值。

    接受小程序发送过来的key和用户基本信息,根据key从redis中获取openid,然后对数据库进行查询,若存在数据则封装后返回给前端,若无信息则向数据库中插入数据并返回给前端。

    1).配置文件新增小程序相关配置

    wechat.miniprogram.appid =
    
    wechat.miniprogram.appsecret =

    2)获取openid以及Sessionkey

    @ResponseBody
     
        @RequestMapping("/login/{code}")
     
        public String login(@PathVariable("code") String code) {
     
            String url = "https://api.weixin.qq.com/sns/jscode2session?" +
     
                    "appid=" +
     
                    env.getProperty("wechat.miniprogram.appid") +
     
                    "&secret=" +
     
                    env.getProperty("wechat.miniprogram.appsecret") +
     
                    "&js_code=" +
     
                    code +
     
                    "&grant_type=authorization_code";
     
            JSONObject object = HttpClientUtils.httpGet(url);
     
            // 请求,获取openid或unionid
     
            // 从数据库中查询是否存储
     
            // 成功获取
     
            String unionid = (String) object.get("unionid");
     
            String openid = (String) object.get("openid");//用户唯一标识
     
            // 会话密钥session_key 是对用户数据进行加密签名的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。
     
            String session_key = (String) object.get("session_key");
     
            String key = "wechatminiprogramkey-" + UUID.randomUUID().toString().replaceAll("-", "");
     
            RedisPoolUtil.setEx(key, openid + "---" + session_key, 9600);
     
            return key;
     
    }

    3).获取用户信息:

    小程序能够获取用户基本信息,但是不包括openid等信息,仅有基本的昵称等信息,需要通过后端传输的key作为标识发送到前端,然后找到对应的openid来获取。

    @ResponseBody
     
    @RequestMapping(value = "/userinfo", method = RequestMethod.GET) // 获取用户信息
     
    public Result getOpenId(String key, MiniProgramBaseUserInfo miniProgramBaseUserInfo) {
     
            MiniProgramBaseUserInfo result = null;
     
            String value = RedisPoolUtil.get(key);
     
            if (value != null) {
     
                String values[] = value.split("---");
     
                String openid = values[0];
     
                // 从数据库中查询是否存储(根据openid查询)
     
                result = null; // TODO: 这里是查数据库操作
     
                if (result == null){ // 数据库中没有数据
     
                    // TODO: 向数据库中执行插入操作
     
                    // insert  weChatUserInfo
     
                    result = miniProgramBaseUserInfo;
     
                }
     
                return Result.success(result);
     
            return Result.error(SESSION_KEY_OVER_TIME); // SessionKey失效
     
        }
  • 相关阅读:
    二分查找,你真的学会了吗
    解决Devexpress的RichEditControl控件保存为docx文件后在word里打开字体显示不正确的问题
    protocgengo: unable to determine Go import path for "xxx.proto"
    URL 和 URI 区别
    Ubuntu 强制关闭图形窗口
    centos /lib64/libc.so.6: version `GLIBC_2.28' not found (required by
    Mac OS 修改终端 Terminal 的配色
    Go语言 http 中的 request.Host 和 request.URL.Host 的区别
    Go 中 defer 和 return 执行的先后顺序
    NPOI 将DataSet保存成Excel文件
  • 原文地址:https://www.cnblogs.com/alimayun/p/12427261.html
Copyright © 2020-2023  润新知