上一章:java微信公众开发(原始篇-消息管理)
既然是公众号开发,当然会涉及到咱们的web端,学了前面几章之后的小伙伴一定发现了,公众号上发消息都可以轻易的获取到发送消息者的微信openid,那么我们在公众号上通过菜单或者图文消息中跳转网页的时候该如何获取到微信用户的信息呢?
在开始之前先来讲讲公众号的两种授权方式:
文档的解释很明了,也就是说
以snsapi_base为scope发起的网页授权,不需要用户手动点击授权,只获取微信用户的openid;
以snsapi_userinfo为scope发起的网页授权,需要用户手动点击授权,并且获取用户的基本信息
还有一点需要注意,网页授权中的access_token与我们前两节说到的access_token为不同的两个寓意
经过简单了解后,咱们来实战一番:(本次代码继上一节内容基础上进行)
这是本次项目用到的依赖:
<!-- jackson依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.3.1</version>
</dependency>
<!-- JSONObject对象依赖的jar包 -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.2.3</version>
<classifier>jdk15</classifier><!-- 指定jdk版本 -->
</dependency>
<!-- 微信httpclient 获取用户 openId-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.1</version>
</dependency>
第一步:用户同意授权,获取code
授权接口:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
这是接口所需要的参数说明:
封装了一下接口URL,WechatConstants.java:
//网页授权
public static final String WEB_AUTHORIZE_URL= "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
/**
* 将所需要的参数填入后得到的网页授权url
* @param redirect_uri 授权后重定向的回调链接地址
* @param isSilence 是否为静默方式
* @param state 可选
* @return
*/
public static String getWeb_authorize_url(String redirect_uri,boolean isSilence,String state){
return WEB_AUTHORIZE_URL.replace("APPID", APPID)
.replace("REDIRECT_URI",redirect_uri)
.replace("SCOPE",isSilence?"snsapi_base":"snsapi_userinfo")
.replace("STATE",state);
}
定义咱们的控制器,创建TestController.java
/**
* 测试公众号
* @author mage on 2019/9/5
*/
@Controller
@RequestMapping("test")
public class TestController {
private Logger log = LoggerFactory.getLogger(TestController.class);
/**
* 用户点击授权之后跳转的url
* @param code 授权成功后得到的code (code作为换取access_token的票据,
* 每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。)
* @param state (可选参数)
* @return
*/
@GetMapping("/authorizeInfo")
@ResponseBody
public String authorizeInfo(String code,@RequestParam(value = "state",required = false) String state){
log.info("[code]:--[{}]",code);
log.info("[state]:--[{}]",state);
return "SUCCESS";
}
}
打开我们的natapp,外网穿透一下,把测试号的对接url修改成natapp生成的url
然后将我们的接口url放到自定义菜单其中一个菜单选项里(如果是插章观看的小伙伴请参考java微信公众开发(原始篇-自定义菜单)
并运行main方法重新创建新的菜单。
别忘了最重要的一步:打开我们的测试号往下拉找到网页服务的网页账号这里点击修改
将我们的natapp上的url放上去,注意:不要带 http://
万事具备,只欠东风,将我们能的测试公众号重新关注,点击包含我们授权url的菜单,日志结果:
但是这里呢有一个问题,理想中的授权确认页面并没有出现,而是直接跳转到了原先定义好的控制器中,难道是太久没有做微信公众号开发,官方更新了?冲头在看了一遍文档,发现:
原来api对已经关注了公众号的用户也是静默授权,不过呢也是可以正常的获取到code这个参数的,如果想要体验一下用户点击授权的页面可以使用HttpServletResponse重定向到授权URL,做法:在公众号上的菜单或图文消息等添加的url为普通的Controller,Controller再使用HttpServletResponse重定向到授权URL就可以看懂手动授权页了,具体代码实现就不做了,这不是重点。
网页授权的目的是为了拿到微信用户的基本信息,怎么拿不是拿,达到目的就可以。
第二步:通过code换取网页授权access_token
拿到code之后我们还需要通过code来获取access_token,一步一步来,获取access_token的api接口:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
不光只是能获取access_token,还包含微信用户的openid,这才是最关键的
封装URL
//网页授权code获取access_token的url
public static final String WEB_AUTHORIZE_CODE_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
/**
* 网页授权获取code后将code填入后的url
* @param code
* @return
*/
public static String getWeb_authorize_code_url(String code){
return WEB_AUTHORIZE_CODE_URL.replace("APPID", APPID)
.replace("SECRET",APPSECRET)
.replace("CODE",code);
}
控制器 TestController.java 加上代码
JSONObject get = WeixinUtil.httpRequest(WechatConstants.getWeb_authorize_code_url(code), "GET", null);
String access_token = get.getString("access_token");
String openid = get.getString("openid");
log.info("[网页授权access_token]:--[{}]",access_token);
log.info("[微信用户openid]:--[{}]",openid);
测试测试,看日志
第四步:拉取用户信息
现在access_token和openid都有了,下一步就可以获取我们需要的用户信息了,但是这个接口的前提是需要授权URL中的scope为 snsapi_userinfo,
拉取用户信息api接口:
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
参数说明没有截图完,有需要的可以去官网查看
封装URL
//网页授权access_token用户基本信息
public static final String WEB_AUTHORIZE_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
/**
* 网页授权获取access_token与openid后填入得url
* @param access_token 网页授权access_token(与基本的access_token不同)
* @param openid (用户唯一标识openid)
* @return
*/
public static String getWeb_authorize_access_token_url(String access_token,String openid){
return WEB_AUTHORIZE_ACCESS_TOKEN_URL.replace("ACCESS_TOKEN",access_token)
.replace("OPENID",openid);
}
TestController.java完整代码
/**
* 测试公众号
* @author mage on 2019/9/5
*/
@Controller
@RequestMapping("test")
public class TestController {
private Logger log = LoggerFactory.getLogger(TestController.class);
/**
* 用户点击授权之后跳转的url
* @param code 授权成功后得到的code (code作为换取access_token的票据,
* 每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。)
* @param state (可选参数)
* @return
*/
@GetMapping("/authorizeInfo")
@ResponseBody
public String authorizeInfo(String code,@RequestParam(value = "state",required = false) String state){
log.info("[code]:--[{}]",code);
log.info("[state]:--[{}]",state);
JSONObject get = WeixinUtil.httpRequest(WechatConstants.getWeb_authorize_code_url(code), "GET", null);
String access_token = get.getString("access_token");
String openid = get.getString("openid");
log.info("[网页授权access_token]:--[{}]",access_token);
log.info("[微信用户openid]:--[{}]",openid);
JSONObject userInfo = WeixinUtil.httpRequest(WechatConstants.getWeb_authorize_access_token_url(access_token,openid), "GET", null);
log.info("[用户基本信息]:--[{}]",userInfo);
return "SUCCESS";
}
}
测试测试,看日志
大功告成。
总结:微信网页授权的目的很明显,就是为了让我们的javaWeb轻松的获取到微信用户的基本信息,也就是说平时大家常说的业务系统与微信公众号绑定,其实就是使用项目中的业务数据与微信用户的openid(因为openid是用户唯一标识)进行数据绑定,这样就可以做到用户进入公众号网页里的时候获取到用户信息进行数据库业务数据匹配,获取出该用户的业务数据。当然也不仅仅是这些作用而已,更多用途由大家去慢慢发掘把(可能说的不够好,希望大家能指出不足)
本章结束,有疑问或者有建议的小伙伴可以在下方评论区留言。
git源码分享:----》》》戳这里