Java调用WeChat's API总结
微信公众号结合着内置浏览器,有着普通浏览器无法完成的服务,前者可以获取浏览页面的微信用户的信息,从而根据信息为用户提供基于微信的更多服务;而后者仅仅能够浏览页面,通过用户的输入信息与用户互动。
本人根据个人的经历总结从小白到入门的过程,是一种记录,也是对渴望入门者的一种指引。
- 注册微信公众平台并申请公众平台测试账号
- 填写接口配置信息
- 服务器与公众号验证Token
- 项目引入weixin-java-mp
一、注册微信公众号平台并申请公众平台测试账号
这方面没什么多言的,至于为何申请测试账号。因为私人只能申请订阅号,对应的开发者账号只能调用基本功能,无法使用高级功能;而测试账号可以使用任何功能以此来学习。
二、填写接口配置信息
在这里要特别注意,URL的一栏并不是要填一个公网服务器即可,要求的是必须为一个可以有Token验证行为的地址。
至于公网的问题,可以使用NATAPP将内网ip转换为公网随机域名,免费,可直接在本机调试项目,很方便。
三、服务器与公众号验证Token
至于Token验证问题,需要代码来验证,原理就是要保证你的Token一致,验证方法有很多种,在weixin-java-mp工具类中也有对应的验证方法,不过本人感觉这种方法更简单:
1 package xxx; 2 3 import xxx.CheckoutUtil; 4 import org.springframework.stereotype.Controller; 5 import org.springframework.ui.Model; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 import java.io.IOException; 11 import java.io.PrintWriter; 12 13 /** 14 * @author zuoyu 15 * @program xx 16 * @description 微信服务器验证Token 17 * @create 2018-07-31 17:55 18 **/ 19 @Controller 20 @RequestMapping("/hello/") 21 public class HelloWeChatController { 22 /** 23 * 微信消息接收和token验证 24 * 25 * @param model 26 * @param request 27 * @param response 28 * @throws IOException 29 */ 30 @RequestMapping("hello") 31 public void hello(Model model, HttpServletRequest request, HttpServletResponse response) throws IOException { 32 boolean isGet = request.getMethod().toLowerCase().equals("get"); 33 PrintWriter print; 34 if (isGet) { 35 // 微信加密签名 36 String signature = request.getParameter("signature"); 37 // 时间戳 38 String timestamp = request.getParameter("timestamp"); 39 // 随机数 40 String nonce = request.getParameter("nonce"); 41 // 随机字符串 42 String echostr = request.getParameter("echostr"); 43 // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 44 if (signature != null && CheckoutUtil.checkSignature(signature, timestamp, nonce)) { 45 try { 46 print = response.getWriter(); 47 print.write(echostr); 48 print.flush(); 49 } catch (IOException e) { 50 e.printStackTrace(); 51 } 52 } 53 } 54 } 55 }
下面是在Servlet验证时要用到的工具类:
1 package xxx; 2 3 import java.security.MessageDigest; 4 import java.security.NoSuchAlgorithmException; 5 6 /** 7 * @author zuoyu 8 * @program xx 9 * @description 微信验证工具 10 * @create 2018-07-31 17:53 11 **/ 12 public class CheckoutUtil { 13 // 与接口配置信息中的Token要一致 14 private static String token = ""; 15 16 /** 17 * 验证签名 18 * 19 * @param signature 20 * @param timestamp 21 * @param nonce 22 * @return 23 */ 24 public static boolean checkSignature(String signature, String timestamp, String nonce) { 25 String[] arr = new String[] { token, timestamp, nonce }; 26 // 将token、timestamp、nonce三个参数进行字典序排序 27 // Arrays.sort(arr); 28 sort(arr); 29 StringBuilder content = new StringBuilder(); 30 for (int i = 0; i < arr.length; i++) { 31 content.append(arr[i]); 32 } 33 MessageDigest md = null; 34 String tmpStr = null; 35 36 try { 37 md = MessageDigest.getInstance("SHA-1"); 38 // 将三个参数字符串拼接成一个字符串进行sha1加密 39 byte[] digest = md.digest(content.toString().getBytes()); 40 tmpStr = byteToStr(digest); 41 } catch (NoSuchAlgorithmException e) { 42 e.printStackTrace(); 43 } 44 content = null; 45 // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信 46 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; 47 } 48 49 /** 50 * 将字节数组转换为十六进制字符串 51 * 52 * @param byteArray 53 * @return 54 */ 55 private static String byteToStr(byte[] byteArray) { 56 String strDigest = ""; 57 for (int i = 0; i < byteArray.length; i++) { 58 strDigest += byteToHexStr(byteArray[i]); 59 } 60 return strDigest; 61 } 62 63 /** 64 * 将字节转换为十六进制字符串 65 * 66 * @param mByte 67 * @return 68 */ 69 private static String byteToHexStr(byte mByte) { 70 char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 71 char[] tempArr = new char[2]; 72 tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; 73 tempArr[1] = Digit[mByte & 0X0F]; 74 String s = new String(tempArr); 75 return s; 76 } 77 public static void sort(String a[]) { 78 for (int i = 0; i < a.length - 1; i++) { 79 for (int j = i + 1; j < a.length; j++) { 80 if (a[j].compareTo(a[i]) < 0) { 81 String temp = a[i]; 82 a[i] = a[j]; 83 a[j] = temp; 84 } 85 } 86 } 87 } 88 }
将代码中的Token填写与在微信测试号的接口配置Token填写一致,然后URL指向该方法即可完成验证。
四、引入wenxin-java-mp工具包
每次调用微信的API都是访问给定的请求URL、附带的参数、以及访问方式,完成后返回一个json数据包;例如获取微信用户的openID:
如果这样在我们开发过程中是很繁琐的,而weixin-java-mp工具包就是一个将这些包装解析的繁琐动作封装起来,对外只暴露接口的工具包。当然类似的工具包还有很多,但个人感觉wenxin-java-mp是最完整且最简洁的,其他类似工具包有很多是基于其他框架、或者依赖包的。我们看一下用这个工具包获取openID多么方便:
几乎所有的对微信API的操作在wenxin-java-mp里都是一个方法。当然,在我们开发过程中依然要一边看着官方文档一边使用,要知其原理。