微信小程序与微信公众号同一用户登录问题

最近在做微信小程序与微信公众号登录合并的接口。整理相关资料以及个人认识的心得写了这篇文章与大家一起分享。

首先,简单说下我遇到的问题是我们的程序调用微信小程序得到openid,然后通过openID得到用户的唯一标识,用户得以登录,然而,当我们调用微信公众号也同样的到openid,同一以用户两个不同的openid,不能区分是否为同一用户,然后发现无论调用微信小程序还是微信公众号同一个用户的到unionid是相同的,所以我们就用unionid来区分是否为同一用户。

UnionID机制说明:

如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。

1、对于小程序获取unionid:

我们来看下用户登录小程序时的时序图:

1、 (JAVA 后台)向微信服务器发起请求附带js_code、appId、secretkey和grant_type参数,以换取用户的openid和session_key(会话密钥)

用code (前端调用微信接口得到)换取 session_key,openid

​这是一个 HTTPS 接口,开发者服务器使用登录凭证 code 获取 session_key 和 openid。
其中 session_key 是对用户数据进行加密签名的密钥。为了自身应用安全,session_key 不应该在网络上传输。后台解密用到。

接口地址:

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

请求参数说明:

1 参数          是否必须    说明
2 appid          是    应用唯一标识,在微信开放平台提交应用审核通过后获得
3 secret         是    应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
4 js_code      是    填写第一步获取的code参数
5 grant_type    是    填authorization_code

Map<String, String> params = new HashMap<String, String>();
params.put("appid", APPID);
params.put("secret", SECRET);
params.put("js_code", "js_Code");
params.put("grant_type", "authorization_code");
String openidtoken = HttpClientUtil.invokeGet(https://api.weixin.qq.com/sns/jscode2session, proxy, params,
utf-8, 60000);

返回参数:

参数 说明
openid  用户唯一标识
session_key  会话密钥

2、AES解密核心代码:(包含用户敏感信息的encryptedData信息由前端提供,后台负责解密数据,得到unionId)

  1. public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {
  2. initialize();
  3. try {
  4. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
  5. Key sKeySpec = new SecretKeySpec(keyByte, "AES");
  6. cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
  7. byte[] result = cipher.doFinal(content);
  8. return result;
  9. } catch (NoSuchAlgorithmException e) {
  10. e.printStackTrace();
  11. } catch (NoSuchPaddingException e) {
  12. e.printStackTrace();
  13. } catch (InvalidKeyException e) {
  14. e.printStackTrace();
  15. } catch (IllegalBlockSizeException e) {
  16. e.printStackTrace();
  17. } catch (BadPaddingException e) {
  18. e.printStackTrace();
  19. } catch (NoSuchProviderException e) {
  20. // TODO Auto-generated catch block
  21. e.printStackTrace();
  22. } catch (Exception e) {
  23. // TODO Auto-generated catch block
  24. e.printStackTrace();
  25. }

3、解密用户信息:

  1. byte[] resultByte = Aes.decrypt(
  2. Base64.decodeBase64(encryptedData),
  3. Base64.decodeBase64(session_key),
  4. Base64.decodeBase64(ivByte));
  5. if (null != resultByte && resultByte.length > 0) {
  6. String userInfo = new String(resultByte, "UTF-8");
  7. // 结果转json
  8. JsonObject jsonobject = null;
  9. try {
  10. JsonParser par = new JsonParser();
  11. JsonElement jsonelement = par.parse(userInfo);
  12. jsonobject = jsonelement.getAsJsonObject();
  13. } catch (Exception e) {
  14. 。。。。。。
  15. }
  16. // 获取unionid
  17. unionID = jsonobject.get("unionId").getAsString() + "";
  18. }

注:String和字节数组之间的转换:

通过 Base64.decodeBase64(String)就可以得到字节数组。

通过 String userInfo = new String(resultByte, "UTF-8"); 就得到了想要的String

4、解密得到的结果:
加密过程微信服务器完成,解密过程在我们的服务器完成,即由 encryptData 得到如下数据:
{
"openId": "OPENID",
"nickName": "NICKNAME",
"gender": GENDER,
"city": "CITY",
"province": "PROVINCE",
"country": "COUNTRY",
"avatarUrl": "AVATARURL",
"unionId": "UNIONID",
"watermark":
{
"appid":"APPID",
"timestamp":TIMESTAMP
}
}
5、把得到的unionId与用户的唯一标识绑定在一起,通过标识就可以进行下一步操作,系统不同,操作不同,这里不再详谈。

2、对于公众号获取unionId:

1、先拿code获取网页授权access_token以及openid

接口地址:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=JSCODE&grant_type=authorization_code

请求参数说明:

1 参数          是否必须    说明
2 appid          是    应用唯一标识,在微信开放平台提交应用审核通过后获得
3 secret         是    应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
4 code           是    填写第一步获取的code参数
5 grant_type     是    填authorization_code

Map<String, String> params = new HashMap<String, String>();
params.put("appid", APPID);
params.put("secret", SECRET);
params.put("code", "Code");
params.put("grant_type", "authorization_code");
String openidtoken = HttpClientUtil.invokeGet(https://api.weixin.qq.com/sns/oauth2/access_token, proxy, params,
utf-8, 60000);

返回参数:
{ 
"access_token":"ACCESS_TOKEN", 
"expires_in":7200, 
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID", 
"scope":"SCOPE" 
}
参数             说明
access_token    接口调用凭证
expires_in      access_token接口调用凭证超时时间,单位(秒)
refresh_token   用户刷新access_token
openid          授权用户唯一标识
scope           用户授权的作用域,使用逗号(,)分隔.

2、可以看到除access_token外,还可以获得openid,用拿到的access_token和openid获取unionID

接口地址:

https://api.weixin.qq.com/sns/userinfo?appid=APPID&secret=SECRET&code=JSCODE&grant_type=authorization_code

请求参数说明:

1 参数          是否必须    说明
2 access_token 
是 接口调用凭证
3 openid         
是    授权用户唯一标识
4 lang           
否    一般为固定值zh_CN

Map<String, String> params = new HashMap<String, String>();
params.put("access_token", access_token);
params.put("openid", openId);
params.put("lang", "zh_CN");
String openidtoken = HttpClientUtil.invokeGet(https://api.weixin.qq.com/sns/userinfo, proxy, params,
utf-8, 60000);

在返回值里就包含有用户的unionID。这里不再详述。

每天努力一点,每天都在进步。

微信小程序与微信公众号同一用户登录问题的更多相关文章

  1. 微信小程序和微信公众号的id是一个吗

    首先,简单说下我遇到的问题是我们的程序调用微信小程序得到openid,然后通过openID得到用户的唯一标识,用户得以登录,然而,当我们调用微信公众号也同样的到openid,同一以用户两个不同的ope ...

  2. [转]微信小程序、微信公众号、H5之间相互跳转

    本文转自:https://www.cnblogs.com/colorful-paopao1/p/8608609.html 转自慕课网 一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加 ...

  3. 微信小程序、微信公众号、H5之间相互跳转

    转自慕课网 一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加小程序. 图片有点小,我把文字打出来吧: 可关联已有的小程序或快速创建小程序.已关联的小程序可被使用在自定义菜单和模版消息 ...

  4. 使用Appium 测试微信小程序和微信公众号方法

    由于腾讯系QQ.微信等都是基于腾讯自研X5内核,不是google原生webview,需要打开TBS内核Inspector调试功能才能用Chrome浏览器查看页面元素,并实现Appium自动化测试微信小 ...

  5. 微信小程序结合微信公众号进行消息发送

    微信小程序结合微信公众号进行消息发送 由于小程序的模板消息已经废弃了,官方让使用订阅消息功能.而订阅消息的使用限制比较大,用户必须得订阅.需要获取用户同意接收消息的权限.用户必须得和小程序有交互的时候 ...

  6. 微信小程序(原名微信应用号)开发工具0.9版安装教程

    微信小程序全称微信公众平台·小程序,原名微信公众平台·应用号(简称微信应用号) 声明 微信小程序开发工具类似于一个轻量级的IDE集成开发环境,目前仅开放给了少部分受微信官方邀请的人士(据说仅200个名 ...

  7. 微信小程序(微信应用号)开发ide安装解决方法

    这两天整个技术圈都炸锅了,微信小程序(微信应用号)发布内测,首批200家收到邀请,但是没受邀请的同学,也不用担心,下面介绍一下解决方法. 首先需要下载ide,昨天只需要下载0.9版本的编辑器并替换文件 ...

  8. 微信小程序(微信应用号)组件讲解[申明:来源于网络]

    微信小程序(微信应用号)组件讲解[申明:来源于网络] 地址:http://www.cnblogs.com/muyixiaoguang/p/5902008.html

  9. 微信小程序使用场景延伸:扫码登录、扫码支付

    微信小程序使用场景延伸:扫码登录.扫码支付 小程序最适合的使用场景有哪些?相比大家能列举出来很多,但这个场景,大家可能多数没想到_^ 笔者团队近期接到了一个PC项目:转转游戏租号PC官网,该项目要求在 ...

随机推荐

  1. python_selenium之xpath的使用

    python_selenium之xpath的使用 一.xpath介绍 Xpath:XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言.XPath基于X ...

  2. YOLO2解读,训练自己的数据及相关转载以供学习

    https://pjreddie.com/darknet/yolo/ 具体安装及使用可以参考官方文档https://github.com/pjreddie/darknet https://blog.c ...

  3. C# 关于在原图中寻找子图片坐标的类

    在网上找了好久,没有一个现成的例子,自己也发帖子可惜没有找到好办法. 只好自己动手写了, 以下为个人想法所写,算法可能不会太好,如果各位有好的例子发来大家一起分享一下. 这个类主要实现了图片坐标查找功 ...

  4. 2014江西理工大学C语言程序设计竞赛高级组题解

    1001 Beautiful Palindrome Number 枚举回文数字前半部分,然后判断该数字是否满足,复杂度为O(sqrt(n))! 1002 Recovery Sequence  本题的核 ...

  5. Uvalive6885(最短路)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=129723 题目大意:n个点,m条边,求出从0到n的最短距离,输出途 ...

  6. 【BZOJ2819】Nim 树状数组+LCA

    [BZOJ2819]Nim Description 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可 ...

  7. 整合swagger2生成Restful Api接口文档

    整合swagger2生成Restful Api接口文档 swagger Restful文档生成工具 2017-9-30 官方地址:https://swagger.io/docs/specificati ...

  8. Error: member names cannot be the same as their enclosing type

    在编译的时候会遇到如下问题:member names cannot be the same as their enclosing type 原因:方法名和类名不能一样,如果一样就是一个构造函数.而构造 ...

  9. java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x87<b

    实际开发中遇到的 情景: 解决方案:  复制的别人的博客,没测试, Incorrect string value: '\xF0\x9F...' for column 'XXX' at row 1 这个 ...

  10. The JVM found at JAVA_HOME is damaged.Please reinstall or define EXE4J_JAVA_HOME to point to an installed 32-bit JDK or JRE

    一.介绍 exe4j是一个很棒的工具,可以把jar包打包成exe进行运行.他可以把jre环境和打包的exe进行集成,使得打包后的exe应用程序可以在没有安装java的机器上运行(前提是要把exe和jr ...