微信授权接口的实践

因为新项目涉及到前后端分离,需要前端跳转到授权页,然后后端把授权数据返回给前端。同时考虑高并发下的负载能力,打算把静态页面和后端的服务器(包括域名)分离。

这样就遇到了问题。

前后端跨域

假设我们的前端页面是h5.a.com
后端(微信授权的服务器)为wx.a.com。

首先因为授权需要由微信后台 开发者选项中的域名发起,那么授权之后如何把授权信息给前端页面呢?
1.cookie 跨域似乎并不能设置cookie,当然把cookie的域设置成/理论上是可行的
2.以get参数传递 明文传递似乎容易被篡改用户信息


思考之后,修改为如下

1.授权登录接口
整个操作在后端页面完成,直到获取到用户信息。跳转回活动页,同时在参数中附带当前用户的openid。

2.获取用户信息接口
前端传递openid之后,后端根据该openid从数据库中查找对应的用户信息返回。

这个设计导致了几个问题
1.获取用户接口需要频繁查表,几万的数据量和小规模请求无所谓,量级一大数据库可能会堵塞。
2.因为项目需要获取用户的关注状态,即使非关注状态下也需要返回用户授权的信息。这样 1 接口的授权信息需要额外数据库存储或者被丢失


再次思考修改之后,解决。

解决思路如下

1.每次授权之后 加密openid(md5,sha1之类的,保证token唯一性就好)作为redis的key,然后把本次授权的用户数据存到redis里

2.跳转回活动页,附带上token值。前端以是否存在token作为授权成功的依据

3.前端使用该token请求服务器,获取用户数据。

这样的话
1.使用了redis持久化内存数据库存储数据,写入读取极快。基本不会出现堵塞
2.把用户数据存储到redis之后,可以实现前后端分离,前端每次使用token获取用户数据即可
3.因为保存的是授权信息,而不是从关注用户表中查。即使未关注用户,也能取到他的数据


后记

关于如何实时获取用户的关注状态

因为用户授权不会返回用户是否关注公众号,常规操作是从关注用户表中查询数据。
一种是数据表做好openid索引,提高数据库搜索速度。另一种奇淫异技就是借用微信的获取用户基本信息接口

服务号获取用户基本信息的日接口调用次数为5000W,一般的活动,日PV 5000W次已经不得了,倒那个级别应该会有别的不同的视角去解决这个问题了。

一般的活动几万人参加 日PV也不过100W(参考去年发的某篇文章,日IP10多W,PV也不过80多W),所以5000W这个次数足够一般公司使用了,重点是这个接口调用速度极快,且实时。

区分是否已关注,从返回json里的subscribe属性获取即可
关注状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"subscribe": 1,
"openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M",
"nickname": "Band",
"sex": 1,
"language": "zh_CN",
"city": "广州",
"province": "广东",
"country": "中国",
"headimgurl":"http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"subscribe_time": 1382694957,
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL",
"remark": "",
"groupid": 0,
"tagid_list":[128,2],
"subscribe_scene": "ADD_SCENE_QR_CODE",
"qr_scene": 98765,
"qr_scene_str": ""
}

未关注状态

1
2
3
4
5
6
{
"subscribe": 0,
"openid": "o0mOfxJ8r236mPAjxvtu3AIdpITY",
"unionid": "o39051qStbZ2WqEFP9Br_iNeedIM",
"tagid_list": {}
}


评论区