官方文档
开发小程序, openId 和 unionId 几乎是没法绕过去的, 但官方文档又讲得不是那么详细,还是自己总结一下以备自己哪天忘了
简介
openId: 用户对于某一应用里的唯一标识, 如同一用户的订阅号, 服务好, 小程序1, 小程序2的 openId 是相互独立的. openId 可以静默获取.
unionId: 在同一个微信开放平台里绑定的移动应用, 网站应用, 公众号, 小程序或第三方平台, 通过一样的 unionId 来标识同一个用户. unionId 的获取需要得到用户的授权, 或用户曾在同一平台的其他应用登录/授权过.
所以, 如果只有一个应用, 那么 openId 是够用的, 但为了后续开发方便, 还是使用 unionId 比较好.
ps: openId 长度为12, unionId 长度为28
如何获取 openId
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| wx.login({ success: loginCode => { getApp().getOpenId(loginCode); }
getOpenId: function(loginCode){ var that = this; var appid = 'wx19110c392ee93159'; var secret = '9223a34383d998f0d531ec796c297ead'; wx.request({ url: 'https://api.weixin.qq.com/sns/jscode2session?appid=' + appid + '&secret=' + secret +'&grant_type=authorization_code&js_code=' + loginCode.code, header: { 'content-type': 'application/json' }, success: function (res) { that.globalData.openId = res.data.openid; console.log('openid in app.js: '+that.globalData.openId); } }) },
|
关于 api 返回的数据:
不满足 unionId 下发条件的情况下返回的参数:
1 2 3 4
| { "openid": "OPENID", "session_key": "SESSIONKEY", }
|
满足 unionId 下发条件的情况下返回的参数:
1 2 3 4 5
| { "openid": "OPENID", "session_key": "SESSIONKEY", "unionid": "UNIONID" }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
public void requestOpenid(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ resp.setContentType("text/html:charset=utf8"); resp.setCharacterEncoding("UTF-8"); PrintWriter out = resp.getWriter();
String loginCode = new String(req.getParameter("loginCode").getBytes("iso-8859-1"), "UTF-8");
try{ StringBuilder sb = new StringBuilder(); URL url = new URL("https://api.weixin.qq.com/sns/jscode2session?appid=" + appIds.getMasterOrderId() + "&secret=" + appIds.getMasterOrderSecret() + "&grant_type=authorization_code&js_code=" + loginCode); InputStream in = new BufferedInputStream(url.openStream()); BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); String line; while((line=reader.readLine())!=null){ sb.append(line); } JSONObject json = JSONObject.fromObject(sb.toString()); session_key = json.get("session_key").toString(); openid = json.get("openid").toString(); unionid = json.get("unionid").toString(); }catch (Exception e){ e.printStackTrace(); } }
|
如何获取 unionId
这里得分两种情况:
用户初次在该平台的应用登录
需要调用接口 wx.getUserInfo, 从解密数据中获取 unionId( 注意处理用户拒绝授权的情况 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| getUserInfo: function(e){ var that = this; if (e.detail.userInfo) { app.getOpenId(e.detail.signature), app.globalData.userInfo = e.detail.userInfo, this.setData({ userInfo: e.detail.userInfo, hasUserInfo: true }), console.log(e.detail) wx.navigateTo({ url: '../subInfo/subInfo', }) }else{ app.toastShow(that, "小程序需要您的授权才能正常使用, 请重新授权", "", 2000) } },
|
用户授权后返回的信息里 encryptedData 解密后结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { "openId": "OPENID", "nickName": "NICKNAME", "gender": GENDER, "city": "CITY", "province": "PROVINCE", "country": "COUNTRY", "avatarUrl": "AVATARURL", "unionId": "UNIONID", "watermark": { "appid":"APPID", "timestamp":TIMESTAMP } }
|
用户已经关注了公众号, 或曾登录同一平台内的其他应用
直接通过 wx.login 获取到该用户的 unionId, 无需用户授权
关于 wx.getUserInfo
官方文档
直接调用该接口不会再出现授权弹窗:
用户未授权, 调用这个接口直接进入 fail 回调
用户授权过, 可以通过这个接口获得用户信息
将这个方法写再 welcome 界面的判断中
解密 encryptedData 后没有 unionId?
微信毒瘤, 没说清楚 unionId 的必要条件, 艹: 将小程序绑定到微信开放平台
如果暂时不想交那300块, 那么要求小程序主体, 及开放平台主体是一样的, 及拥有者是同一人
如何解密 unionId [转]
需要元素: 加密的数据: encryptedData, 密钥: session_key( 通过 wx.login 获得的临时登录凭证 loginCode 向微信请求后获得, session_key 有时效性 ), 初始向量: iv
详细解密步骤见参考链接:
参考链接( 都是 java 的):
微信小程序之用户数据解密(七)
微信小程序之获取并解密用户数据(获取openId、unionId)
顺便吐槽一下, 他们的代码块怎么这么乱(码)…
可能会缺失的包( 由maven引入 ):
1 2 3 4 5 6 7 8 9 10 11 12
| <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.60</version> </dependency>
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.9</version> </dependency>
|
后续问题
微信小程序会记住用户是否授权过, 当用户第一次授权时, 通过服务器解密可以获取到用户的 unionid. 此时如果用户继续操作, 进行注册操作, 那么将 unionid, 用户注册信息存入临时用户表, 等待管理员确认.
用户第二次进入小程序, 通过 wx.getUserInfo 获得数据, 此时用户未得到确认, 进入等待页面
管理员确认后, unionid, 用户注册信息存入正式用户表
用户第三次进入小程序, 同样通过 ws.getUserInfo 获得数据, 经过确认的用户可以进入 shop 页面
关于要不要用用户表 id 来进行小程序与服务器进行对接: 目前觉得这样要多几步判断, 还是继续用 unionid 吧
详细图解见 微信小程序登录流程控制