公众号基础的小程序搭建(并处理小程序获取不到用户unionid问题)


最近因为小程序的火爆,再加上老板的要求。需要搭建并将部分公众号功能开发到小程序,所以自己着手了解并搭建了小程序。(其中跳过很多坑,看过很多博客。希望这个博客可以帮助到同样需求的童鞋把),博主做了一次更新2019.2.18日(解决关于小程序获取不到unionid的问题)

微信小程序和公众号的区别、关联

说起小程序和公众号,其实基本上差不多,都有微信需要的openid,和对应的处理的微信接口(如推送模板消息、支付等都需要对应的openid)最主要的还是unionId(这个需要在开放平台上关联公众号和小程序,才能将两个独立的openId识别出相同的用户,具体可以百度一下,这里不做太多赘述)

微信小程序最重要的一点(!!!)

因为这边博主自己遇到,巨坑的一点。小程序通过公众平台关联公众号的时候。必须使用encryptedData获取,否则只通过code再在后端通过接口直接获取用户信息时,未关注、登录过公众号的小程序获取不到unionid
获取unionid必须要通过解密encryptedData方式获取到加密的用户数据。
简单说流程:客户端获取使用wx.login+wx.getUserInfo[参数withCredentials: true]再将code(wx.login的返回值)、encryptedData、iv发送到后端;后端操作:使用code获取临时的session_key,再用session_key,encryptedData、iv。解密获取到unionid(这个一定不会空!!!)

封装wx.request并且保持登陆的session,前提:用户已经授权

虽然小程序可以直接获取用户openid作为用户,之后获取用户授权关联unionId的时候再同步数据。为了不操作麻烦,我的设计是在授权之后才能使用对应的功能。
好处:
方便统一处理某些情况,如请求session过期时自动刷新,接口调用失败显示错误信息。简化写法等。这边根据我们的后台业务做了一定的封装,可以借鉴一下

 /**
   * 初始化方法,包含获取用户信息和登陆后台(项目中所有请求都必须先通过该方法初始化)
   * callback 只有用户授权成功并且登陆后才处理回调函数
   */
 wxInit: function(callback) {
   
    // 如果还没监测配置成功
    if (!this.globalData.hasUserInfo) {
   
      wx.getSetting({
   
        success: res => {
   
          if (res.authSetting['scope.userInfo']) {
   
            // 已经授权,可以直接调用 getUserInfo获取头像昵称,不会弹框
            //微信登录
            this.wxLogin(null, callback)
          } else {
   
            wx.navigateTo({
   
              url: '../userInfo/index'
            });
          }
        }
      })
    } else {
   
      if (callback && typeof callback === "function") {
   
        callback()
      }
    }
  }
  
/**
   * 封装wx.request
   * param  obj 正常ajax内对象url,data等
   * param acFail方法,当活动返回错误-1时做的操作 func,这边是后台特定业务的返回值,做特殊处理
   */
  wxRequest: function(obj, acFail) {
   
    const that = this;
    let method = "POST"
    //更换请求方式
    if (obj.method) {
   
      method = obj.method
    }
    let header
    //根据请求方式,切换内容类型
    if (method.toUpperCase() == "GET") {
   
      header = {
   
        'content-type': 'application/json'
      }
    } else {
   
      header = {
   
        'content-type': 'application/x-www-form-urlencoded'
      }
    }
    //放入服务端session
    const sessionId = wx.getStorageSync("sessionId")
    if (sessionId) {
   
      header.cookie = 'SESSION=' + sessionId
    }
    // 封装request
    wx.request({
   
      url: getApp().config.apiServer + obj.url,
      data: obj.data,
      method: method,
      header: header,
      success: function(res) {
   
      	//请求状态不是200现实错误
        if (res.statusCode != 200) {
   
          if (obj.fail && typeof obj.fail === "function") {
   
            obj.fail(res);
          } else {
   
            wx.showToast({
   
              title: '请求失败,错误' + res.statusCode,
              icon: "none"
            })
          }
          return
        }
        const data = res.data
        if (data.status == 2) {
   
          //session过期超时,需要刷新session,并重新调用方法
          //判断当前是否是未授权前请求,如果是,则直接返回
          wx.getSetting({
   
            success: res => {
   
              if (res.authSetting['scope.userInfo']) {
   
                getApp().wxLogin(obj)
              } else {
   
                //未授权请求
                console.log("未授权请求" + obj.url)
              }
            }
          })

        } else if (data.status == 1) {
   
          wx.showToast({
   
            title: data.msg,
            icon: "none",
            duration: 2000
          })
          console.log("error_url:", obj.url)
          console.log("err_msg:", data.msg)
        } else if (data.status == -1) {
   
          //定义活动失败操作
          if (acFail && typeof acFail === 'function') {
   
            acFail()
          }
        } else {
   
          obj.success(data);
        }
      },
      fail: function(res) {
   
        if (obj.fail && typeof obj.fail === "function") {
   
          obj.fail(res);
        }
      }
    })
  }

其中有对错误情况的统一处理,重要的还是对session过期的处理,d=====( ̄▽ ̄*)b

/**
   * 微信登录方法,获得code更新后台session
   * userInfo 用户信息对象
   * callbackObj 请求过期时需要重新执行的请求参数
   * action 登录成功之后要做的事情
   */
  wxLogin: function(callbackObj, action) {
   
    wx.login({
   
      success: res => {
   
        const code = res.code
        wx.getUserInfo({
   
          withCredentials: true,
          lang: "zh_CN",
          success: res => {
   
            getApp().globalData.hasUserInfo = true
            const userInfo = res.userInfo
            getApp().globalData.userInfo = res.userInfo
            res.rawData = ""
            const jsonStr = JSON.stringify(res)
            //正式登陆
            getApp().wxRequest({
   
              url: "tokenHandle/smallProgramLogin",
              data: {
   
                code: code,
                loginType: 1,
                jsonStr: jsonStr
              },
              success: function(res) {
   
                if (res.status == 0) {
   
                  wx.setStorageSync("sessionId", res.data.sessionId)
                  wx.setStorageSync("isMember", res.data.isMember)
                  wx.setStorageSync("memberNum", res.data.memberNum)
                  if (res.data.isMember == "true") {
   
                    wx.setStorageSync("user", res.data.unionid)
                  } else {
   
                    wx.removeStorageSync("user")
                  }
                  wx.setStorageSync("userSign", res.data.unionid)
                  //如果有该对象,表示之前session过期,并且需要重新执行请求
                  if (callbackObj) {
   
                    getApp().wxRequest(callbackObj)
                  }
                  if (action && typeof action === 'function') {
   
                    action()
                  }
                }
                console.log(res)
              }
            })

            // 所以此处加入 callback 以防止这种情况
            if (this.userInfoReadyCallback) {
   
              this.userInfoReadyCallback(res)
            }
          }
        })
      }
    })
  }

知识点:
1.wx.login()
调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key)等。
2.封装request中的回调函数的使用和其中:请求过期后重新登陆需要再次执行一次过期的request

前端获取用户授权请求

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值