打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
微信公众号开发

由于当时是刚学习微信公众号开发当时的思路虽然可行,不过不是最好的,最近也用到了需要获取用户信息的地方,再次整理一下。

流程

注意点

第一

如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。

必须是在微信客户端

第二

通过code换取网页授权access_tokencode作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

在第二步中通过code换取网页授权access_token,这个access_token和其他接口中使用的access_token,不一样。

如果是静默授权,这里的access_token没什么用,反而是换取access_token时得到的openid非常有用

code只能用一次,注意这里的access_token和基础接口中的access_token不一样

实现步骤

第一步: 配置网页授权回调域名

开发 - 接口权限 - 网页服务 - 网页授权 - 网页授权获取用户基本信息

配置网页授权域名

我这个是测试号,花生壳做的域名

域名不需要配置http://开头,也不需要项目路径

第二步: 生成网页链接

这里有两种一种是scope为snsapi_base另一种是scope为snsapi_userinfo

snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid)

snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)

先看第一种

官方给的示例

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect
  • 1
  • 2
  • 3

前缀为

https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的appId&redirect_uri=
  • 1

后缀为

&response_type=code&scope=snsapi_base&state=123#wechat_redirect
  • 1

顺序必能乱,中间是你的网址。网址还经过了转码处理,java使用java.net.URLEncoder提供的encode方法即可

好了,这里我们拼接一个我们的链接

http://gwchsk.imwork.net/myair/auth/user

我们在这个地址下获取用户信息,encode之后为

http%3A%2F%2Fgwchsk.imwork.net%2Fmyair%2Fauth%2Fuser

然后将前缀和后缀都拼接好,不要忘了前缀中的appId

拼接好之后在浏览器输入,找个能生成二维码的浏览器,再扫描一下

一个简单的Controller如下,我们只是看第一步是否可以得到code

package com.airport.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;@Controller@RequestMapping('/auth')public class WechatUserController { @RequestMapping(path = '/user', method = RequestMethod.GET) public String user(String code) { System.out.println('得到的code:'+code); return 'user'; }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

用微信扫码之后就可以看到控制台输出了code

第三步:通过code换取网页授权access_token,这里会得到openId

通过code就可以换取access_token了,这里其实openId比access_token更有用

换取的结果

{'access_token':'0W71gcY7yvLBBL0JzxQC-sGJnBBOHcx95sBZqpWOTJpNm5C1Tm00UnE1MsNXaFb0JQmDwWHFtGi7vkuHT0ohdf5a8w2FI-JXKYtOKe5ehSs','expires_in':7200,'refresh_token':'QhEl0tbQERkdD-7-JKFZfYh68wqx-Frrs1OnHv5Wv7CarYhDhtk2nATc_x2q5liPMs0Pdlh-FOgJgcIDy0d57wqa431BJ2NVjZKWyWA-hpQ','openid':'oJhxHv8xKWX6ZYo4aeqBhTko94jk','scope':'snsapi_base'}
  • 1

我写了一个方法

ExchangeCode2OpenId.java

package com.airport.util;import org.json.JSONException;import org.json.JSONObject;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.airport.context.WechatConst;/** * 通过code换取openId * * @author 程高伟 * * @date 2016年10月17日 下午7:05:34 */public class ExchangeCode2OpenId { private static Logger logger = LoggerFactory.getLogger(ExchangeCode2OpenId.class); public static String exchange(String code) { String openid = ''; String appId = WechatConst.appId; String appSecret = WechatConst.appSecret; // 换取access_token 其中包含了openid // 这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。 String URL = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code' .replace('APPID', appId).replace('SECRET', appSecret).replace('CODE', code); String jsonStr = HttpUtil.sendGet(URL); logger.info('----------换取openid返回的结果:{}----------', jsonStr); JSONObject jsonObj = new JSONObject(jsonStr); try { openid = jsonObj.getString('openid'); } catch (JSONException e) { logger.info('----------换取openid发生了异常:{}----------', e.getMessage()); } return openid; }}
  • 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
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

好了,有了openid,我们就可以调用基础接口(用户管理)中的获取用户信息方法了。

这里获取用户信息需要access_token,注意,这里的access_token不是上面通过code换取到的,而是要自己去获取。

获取地址

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

这样就可以获取用户信息了。

整个流程就是这个样子。

自定义菜单获取用户信息

将上一步我们拼接的url作为view型按钮的url

这里如果生成自定义菜单

如果报40033错误,请参考

自定义菜单创建好之后,就可以当用户点击自定义菜单的时候获取用户信息了。

具体的获取用户信息接口地址

@RequestMapping(value = '/user', method = RequestMethod.GET)public String user(String code, Model model, HttpSession session) { String openid = ExchangeCode2OpenId.exchange(code); WechatUser wechatUser = WechatUserUtil.getWechatUser(openid); if (null == wechatUser) { model.addAttribute('title', '请从微信公众号进入'); return 'notInWechat'; } System.out.println('wechatUser:' + wechatUser); session.setAttribute('wechatUser', wechatUser); model.addAttribute('wechatUser', wechatUser); model.addAttribute('title', '用户信息'); return 'user';}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

我们看一下效果

自定义菜单

点击后进入

点击最下面的按钮

确定后跳转到另一个页面

然后返回,仍然回到了用户信息页面

一切都很顺利

看一下打印输出

如果你也很正常,那恭喜你,你用的安卓设备

我们换成苹果的

再走一遍,先清空打印内容,再看一下iPhone操作的打印输出内容

iPhone会在点击返回的时候再请求一次,而上面我们说过code只能用一次,第二次已经不能用了,所以获取不到用户信息,结果导致出错

如果你用iPad,效果和安卓手机一样。

搞不清楚为什么苹果iPhone和iPad居然不一样。

好了,言归正传,如何解决这个问题,其实很简单,在第一次获取到用户信息后保存起来,具体存哪里根据你的喜好(session也好,缓存也好)

这里我将它放在session里。

献上关键代码

@RequestMapping(value = '/user', method = RequestMethod.GET)public String user(String code, Model model, HttpSession session) { WechatUser wechatUser = getWechatUser(code, session); if (null == wechatUser) { model.addAttribute('title', '请从微信公众号进入'); return 'notInWechat'; } System.out.println('wechatUser:' + wechatUser); session.setAttribute('wechatUser', wechatUser); model.addAttribute('wechatUser', wechatUser); model.addAttribute('title', '用户信息'); return 'user';}private WechatUser getWechatUser(String code, HttpSession session) { String openid = ''; WechatUser wechatUser = null; WechatUser wechatUserInSession = (WechatUser) session.getAttribute('wechatUser'); // 先看session if (null != wechatUserInSession) { wechatUser = wechatUserInSession; System.out.println('session中有用户信息'); } else {// session中没有 去获取 System.out.println('得到的code:' + code); if (StringUtils.isBlank(code)) { return null; }else{ openid = ExchangeCode2OpenId.exchange(code); if (StringUtils.isBlank(openid)) { return null; } } System.out.println('得到的openid:' + openid); // 这里使用的是普通接口(用户管理,获取用户基本信息) wechatUser = WechatUserUtil.getWechatUser(openid); String headImgurl = wechatUser.getHeadimgurl(); // 132*132的头像 if (StringUtils.isNotBlank(wechatUser.getHeadimgurl())) { headImgurl = headImgurl.substring(0, headImgurl.length() - 1); headImgurl += '132'; wechatUser.setHeadimgurl(headImgurl); } else { headImgurl = '/assets/img/default_head.png'; } wechatUser.setHeadimgurl(headImgurl); System.out.println('得到的用户信息:' + wechatUser); } return wechatUser;}
  • 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
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

还有一种就是需要用户点击同意后再获取用户信息,就不写了,用到了再说,思路都是一样的。

WechatUserUtil.java

import java.io.UnsupportedEncodingException;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import com.google.gson.Gson;import com.google.gson.JsonSyntaxException;@Componentpublic class WechatUserUtil { @Autowired private AccessTokenUtil accessToken; private final Logger logger = LoggerFactory.getLogger(this.getClass()); public WechatUser getWechatUser(String openid) { String token = accessToken.getAccessToken(); String URL = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN'; String jsonResult = HttpUtil.sendGet(URL.replace('OPENID', openid).replace('ACCESS_TOKEN', token)); logger.info('----------获取到的用户信息,{}----------', jsonResult); Gson gson = new Gson(); WechatUser wechatUser = null; try { wechatUser = gson.fromJson(new String(jsonResult.getBytes('ISO-8859-1'), 'UTF-8'), WechatUser.class); // 错误的openId if (StringUtils.isBlank(wechatUser.getOpenid())) { wechatUser = null; } } catch (JsonSyntaxException e) { logger.info('----------解析json出错----------'); e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return wechatUser; }}
  • 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
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
微信公众号支付功能开发
微信支付之openid获取
微信网页第三方登录原理
微信公众平台开发(71)OAuth2.0网页授权
微信获取用户信息的两个接口和两个ACCESS_TOKEN
微信用户授权
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服