BAT一直以来是许多程序猿的奋斗目标,但若是有幸可以进入其中学习却连自家的平台API都没办法调用,那就有点说不过去了。所以,我这段时间一直在学习JAVA微信之间的对接开发,也从中看到了BAT的严谨之处。php
最好的参考工具(官方文档):公众平台开发者文档
参考博客:souvc的博客
测试接口:微信公众号平台接口测试
jdk:1.8
IDE:IDEA
服务器:腾讯云(对学生有较大优惠)html
经过阅读官方文档,能够得知若要接入微信公众号平台开发,开发者须要按照如下三步流程:
1. 填写服务器配置
2. 验证服务器地址的有效性
3. 依据接口文档来实现业务逻辑java
咱们的应用服务器要接受微信服务器的get请求,其中包括四个参数(signature、timestamp、nonce、echostr),开发者经过检验signature对请求进行校验(下面有校验方式)。若确认这次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,不然接入失败。
注意:具体内容含义能够经过阅读官方文档得知!
由官方文档,咱们可知加密/校验流程以下:
- 将token、timestamp、nonce三个参数进行字典序排序
- 将三个参数字符串拼接成一个字符串进行SHA1加密(SHA1加密在接下来的开发,有兴趣的话能够去了解一下)
- 开发者得到加密后的字符串可与signature对比,标识该请求来源于微信git
ps:微信提供了一份php示例代码,有兴趣的能够了解一下spring
接下来,我将前两个步骤合为一个工具类去实现。废话很少说,咱们直接上代码。数组
/** * SignUtil * 验证 signature 工具类 * Created by zggdczfr on 2016/10/21. */ public class SignUtil { //与接口配置信息中的ToKen一致 private static String token = ""; //该Token值为本身定义 public static boolean checkSignature(String signature, String timestamp,String nonce){ // 1. 将token、timestamp、nonce三个参数进行字典序排序 String[] arr = new String[] { token, timestamp, nonce }; Arrays.sort(arr); // 2. 将三个参数字符串拼接成一个字符串进行sha1加密 StringBuilder content = new StringBuilder(); for(int i=0; i<arr.length; i++){ content.append(arr[i]); } MessageDigest messageDigest = null; String tmpStr = null; try { // 将三个参数字符串拼接成一个字符串进行sha1加密 messageDigest = MessageDigest.getInstance("SHA-1"); byte[] digest = messageDigest.digest(content.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } content = null; // 3. 将sha1加密后的字符串可与signature对比,标识该请求来源于微信 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; } /** * 将字节数组转换为十六进制字符串 * @param byteArray * @return */ private static String byteToStr(byte[] byteArray){ String strDigest = ""; for(int i=0; i < byteArray.length; i++){ strDigest += byteToHexStr(byteArray[i]); } return strDigest; } /** * 将字节转换为十六进制字符串 * @param mByte * @return */ private static String byteToHexStr(byte mByte){ char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A','B', 'C', 'D', 'E', 'F'};; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; } }
接下来是实现第三步,这里须要注意的一点是:微信提过get方法来验证身份,经过post方法来实现信息的传递,也就是说之后的业务逻辑实现都将经过这里配置的连接来对接。服务器
/** * Created by zggdczfr on 2016/10/21. */ @Controller @RequestMapping(value = "/wechat") public class SecurityController { private static final long serialVersionUID = 4323197796926899691L; private static final Logger LOGGER = Logger.getLogger(SecurityController.class); @RequestMapping("test") public String test(){ System.out.println("test"); return "/index.jsp"; } @RequestMapping(value = "security", method = RequestMethod.GET) public void WetChatGet(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "signature", required = true) String signature, @RequestParam(value = "timestamp", required = true) String timestamp, @RequestParam(value = "nonce", required = true) String nonce, @RequestParam(value = "echostr", required = true) String echostr) throws IOException { try { // 经过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,不然接入失败 if (SignUtil.checkSignature(signature, timestamp, nonce)) { PrintWriter out = response.getWriter(); out.print(echostr); out.close(); } } catch (Exception e){ LOGGER.log(Level.ERROR, "链接微信公众号平台测试失败!"); } System.out.println("链接微信公众号平台测试成功!"); } @RequestMapping(value = "security", method = RequestMethod.POST) public void WetChatPost(HttpServletRequest request, HttpServletResponse response){ //业务逻辑处理 } }
接下来就是将咱们的代码打包部署到服务器上来,经过测试接口来进行对接。
测试结果:
微信