小程序开发中最常用也是最容易混淆的几个api接口和概念有

  • wx.login(OBJECT)
  • wx.getUserInfo(OBJECT)
  • openid
  • unionid

什么情况下需要进行小程序的登录?什么情况下需要获取用户信息?什么情况下需要用户授权?openid和unionid有什么区别?什么情况下使用openid?什么情况下使用unionid?带着这些疑问,我们来对这些api和概念逐个击破。

wx.login(OBJECT)详解

还是官方这张图:

alt

官方说明:

  1. 小程序调用wx.login(OBJECT) 获取临时登录凭证code ,并回传到开发者服务器。

  2. 开发者服务器以code换取用户唯一标识openid 和会话密钥session_key。

之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。

可以看出:

  1. wx.login的目的主要就是向微信服务器获取openid和会话密钥session_key
  2. 获取后将openid和session_key两个参数作为value,后台再生成一个key(自定义登录态)对应这个value
  3. 生成后将这个key和value组成的键值对存入开发者后台数据库或者类似redis的缓存里
  4. 将key(自定义登录态)返回给小程序端
  5. 下次小程序端再发请求给开发者服务器后端的时候必须要带上这个key,然后后端接收到这个key,去匹配对应的value,识别出访问用户

注意:

  • 开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥
  • 微信服务器返回后端openid+session_key或者openid+session_key+unionid,返不返回unionid取决于是否开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用。

结合微信登录,可以做小程序API接口攻击防护。之前的博文已经有详细描述。另外微信支付也有提到登录,参见小程序微信支付详解与代码示例

wx.getUserInfo(OBJECT)详解

这个接口今年微信官方做了一个比较大的调整,具体可以参考小程序获取用户信息接口调整方案。

在调用该接口之前,必须进行用户授权,否则将会报错。

当调用该接口发送请求时携带的 withCredentials 为 true 时,要求此前有调用过 wx.login 且登录态尚未过期,此时返回的数据会包含 encryptedData, iv 等敏感信息;当 withCredentials 为 false 时,不要求有登录态,返回的数据不包含 encryptedData, iv 等敏感信息。

为什么withCredentials 为 true时要登录呢?因为encryptedData, iv 解密的时候需要用到session_key,这个session_key是在wx.login的时候得到的。

那encryptedData解密出来的数据多了啥呢?多出的数据如下:

{
    "openId": "OPENID",
    "unionId": "UNIONID",
    "watermark":
    {
        "appid":"APPID",
    "timestamp":TIMESTAMP
    }
}

这里还特意加了watermark,其中有个timestamp,是为了校验数据的时效性。

另外一个比较关键的参数就是unionId,这里是区别为wx.login,不管你关没关注同一微信开发平台下的公众号,只要你的小程序绑定了微信开发平台,就能够直接获取到unionId。

unionId和openid的区别

那这个unionId到底有什么用呢?先来看它的特点:同一微信开放平台下的应用(App、小程序、公众号)的unionId是一样的。适用场景就是,如果一个用户先使用了小程序,然后再关注了公众号,对于开发者的你来说,当你想给小程序上的这位用户发送公众号模板消息的时候你能精确的通过unionId找到他。

那么问题又来了,openid是干嘛用的呢?openid是小程序或公众号的唯一识别id,就是说不管你的小程序或公众号绑定的是哪个微信开发平台,用户他的openid都不会变,但是绑定不同微信开发平台用户的unionid会不一样。

用户什么时候需要授权?

只有当开发者想要获取用户信息,如nickName、avatarUrl等,或者unionId这种敏感信息并保存到后端数据库的时候才需要调用wx.getUserInfo(OBJECT)接口,进而需要进行用户授权。而当仅仅需要获取用户的openid时,则可以通过调用wx.login后由后端服务器再向微信服务器发请求获得。

那么为什么需要获取nickName、avatarUrl等用户信息呢?这个的目的就多了,当小程序端需要展示一堆用户列表的时候,当需要对用户进行区域划分的时候,当需要对用户信息进行数据分析的时候,等等等等。