最近业务经常需要针对微信公众号开发,比如处理关注公众号事件,微信网页扫码登录及绑定帐号等。在开发过程中遇到许多问题,谷歌上看了许多前人的文章,特此来做个总结。
- 首先我们需要申请一个公众号,具体怎么申请这里就不说了。申请成功后进入开发/基本配置页面
AppID和AppSecret:用来获取accessToken,accessToken是调用微信一切接口的凭证
IP白名单:当服务端在调试时想调用微信接口时,需把ip地址加入白名单中
URL:服务器上暴露的接口地址
- tip:必须是域名形式,不能是IP
令牌:任意值,后续解析加密消息用
密钥:随机生成值,后续解析加密消息用
- tip:如果要使用weixin-mp-java依赖开发,不能直接使用公众号网页上生成的随机key,解决办法是使用
Base64.encodeBase64String(UUID.randomUUID().toString().replaceAll("-","").getBytes());
生成44位的字符串,然后去除末尾=号作为key
消息加密方式:是否加密传输的消息,可选择明文,明文密文,仅密文
然后我们就可以开发了
-
在springboot初始化项目生成页生成一个项目,然后加入以下依赖
1 2 3 4 5 6 7 8 9 10
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-mp</artifactId> <version>3.8.0</version> </dependency>
公众号接入指南中提到微信会往上一步填写的URL上发送校验签名请求,服务器必须对请求作出响应,才能完成接入。新建WechatController,编写以下接口
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
// 此接口的作用是接收微信校验签名以及消息请求 // msgSignature:加密的消息参数,当加密方式设置为密文时,微信会在请求里带上此参数 // 其余参数请参考https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html接入指南 @RequestMapping("/wechat") @ResponseBody public String wechat(HttpServletRequest request, @RequestParam(value = "msg_signature", required = false) String msgSignature, @RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce, @RequestParam(value = "echostr", required = false) String echostr) throws IOException { if (wxMpService.checkSignature(timestamp, nonce, signature)) { // GET请求味校验签名接口 if (request.getMethod().equals("GET")) { System.out.println("success"); return echostr; } else { // 接收微信消息请求根据WxMpXmlMessage的msgType判断消息类型,然后根据类型处理相应业务逻辑 WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), wxMpConfigStorage, timestamp, nonce, msgSignature); System.out.println(inMessage.toString()); return ""; } } else { System.out.println("failed"); return ""; } }
-
接下来是网页授权和扫码功能的开发,场景一般是微信内访问网页以及网页上提供微信扫码服务
根据网页授权里的说明,需要以下几个接口
-
生成提示用户授权的链接
1 2 3 4 5 6 7 8
// redirectUrl:用户同意授权后重定向的链接,可以为html地址或者服务端处理后续业务接口,重定向链接中会携带code,作为获取accessToken的凭据 // state:随机数,可以用来存储用户状态,扫码登录的时候会用到 @RequestMapping("/authorization-url") @ResponseBody public String getAuthorizationUrl(@RequestParam("redirectUrl") String redirectUrl, @RequestParam("state") String state) { return wxMpService.oauth2buildAuthorizationUrl(redirectUrl, "snsapi_userinfo", state); }
-
获取用户信息
1 2 3 4 5 6 7 8 9 10 11
@RequestMapping(value = "", method = RequestMethod.GET) @ResponseBody public String xxx(@RequestParam("code") String code) throws WxErrorException { WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code); WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(accessToken, "zh_CN"); String openId = wxMpUser.getOpenId(); String unionId = wxMpUser.getUnionId(); // 拿到openId和unionId之后,可以做相应的业务逻辑,比如绑定微信帐号,用微信登录等等 return "success"; }
-
-
扫码功能。关于扫码具体代码就不贴了,说下思路,结合上述代码实现也很简单
- 前端调用生成提示用户授权的链接,然后把链接变成二维码,展示给用户,同时生成一个随机数,存入map中
- 服务端提供一个检查扫码状态接口,检查随机数对应的微信unionId是否为空,并返回相应的状态给前端
- 如果用户确认授权,微信会调用服务端确认授权的回调接口,把随机数对应的微信unionId设置好
- 前端轮询扫码状态接口,并在网页上作出相应的提示
-