在上一篇《微信公众号开发(一)——环境搭建》中咱们已经准备好了微信公众号开发环境,那么接下来咱们要真正的开始进行公众号的实际开发之旅。html
在真正的开发公众号以前咱们必需要接入微信公众平台,那为何要接入、如何接入本文就这些问题一一解答;java
首先咱们来了解一下接入平台的原理,而后再贴出代码上手实践测试。web
微信服务器就至关于一个转发服务器,终端(手机、Pad等)发起请求至微信服务器,微信服务器而后将请求转发给咱们的应用服务器。应用服务器处理完毕后,将响应数据回发给微信服务器,微信服务器再将具体响应信息回复到微信App终端。spring
通讯协议为:HTTPjson
数据传输格式为:XML数组
具体的流程以下图所示:安全
来一张更加直观的图吧:springboot
咱们须要作的事情,就是对微信服务器转发的HTTP请求作出响应。具体的请求内容,咱们按照特定的XML格式去解析,处理完毕后,也要按照特定的XML格式返回。服务器
在微信公众平台开发者文档上,关于公众号接入这一节内容在接入指南上写的比较详细的,文档中说接入公众号须要3个步骤,分别是:微信
一、填写服务器配置
二、验证服务器地址的有效性
三、依据接口文档实现业务逻辑
其实,第3步已经不能算作公众号接入的步骤,而是接入以后,开发人员能够根据微信公众号提供的接口所能作的一些开发。
第1步中服务器配置包含服务器地址(URL)、Token和EncodingAESKey。
服务器地址即公众号后台提供业务逻辑的入口地址,目前只支持80端口,以后包括接入验证以及任何其它的操做的请求(例如消息的发送、菜单管理、素材管理等)都要从这个地址进入。接入验证和其它请求的区别就是,接入验证时是get请求,其它时候是post请求;
Token可由开发者能够任意填写,用做生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性);
EncodingAESKey由开发者手动填写或随机生成,将用做消息体加解密密钥。本例中所有以未加密的明文消息方式,不涉及此配置项。
以测试帐号为例:
第1步 配置咱们的服务器参数
咱们点击修改按钮输入url和token点击提交;
第2步,验证服务器地址的有效性,当点击“提交”按钮后,微信服务器将发送一个http的get请求到刚刚填写的服务器地址,而且携带四个参数:
接到请求后,咱们须要作以下三步,若确认这次GET请求来自微信服务器,原样返回echostr参数内容,则接入生效,不然接入失败。
1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 开发者得到加密后的字符串可与signature对比,标识该请求来源于微信
第3步 依据接口文档实现业务逻辑
验证URL有效性成功后即接入生效,成为开发者。你能够在公众平台网站中申请微信认证,认证成功后,将得到更多接口权限,知足更多业务需求。
成为开发者后,用户每次向公众号发送消息、或者产生自定义菜单、或产生微信支付订单等状况时,开发者填写的服务器配置URL将获得微信服务器推送过来的消息和事件,开
发者能够依据自身业务逻辑进行响应,如回复消息。
公众号调用各接口时,通常会得到正确的结果,具体结果可见对应接口的说明。返回错误时,可根据返回码来查询错误缘由。全局返回码说明
用户向公众号发送消息时,公众号方收到的消息发送者是一个OpenID,是使用用户微信号加密后的结果,每一个用户对每一个公众号有一个惟一的OpenID
一、首先咱们要建立一个java web 工程
二、建立一个controller 来进行服务器的验证
package com.quanlian.controller; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import util.NetWorkHelper; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.quanlian.entity.AccessToken; import com.quanlian.entity.AccessTokenInfo; import com.quanlian.runner.MyApplicationRunner; @RestController public class WxController { private final String TOKEN = "super"; @RequestMapping(value="/hello") public String hello(){ return "hello"; } @RequestMapping(value = "wx") public String wxcheck(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException { String method = request.getMethod(); System.out.println(method); if(method.equals("POST")){ return wxMessage(request,response); }else{ String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); System.out.println(echostr); //排序 String sortString = sort(TOKEN, timestamp, nonce); //加密 String mySignature = sha1(sortString); if(signature!=null&&signature!=""&&signature.equals(mySignature)){ System.out.println("签名校验经过。"); return echostr; }else{ System.out.println("签名校验失败."); return "xxxx"; } } } @RequestMapping(value="wxMessage",method=RequestMethod.POST) public String wxMessage(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException{ request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); System.out.println("请求进入"); String result = ""; try { Map<String,String> map = MessageHandlerUtil.parseXml(request); System.out.println("开始构造消息"); result = MessageHandlerUtil.buildXml(map); System.out.println(result); if(result.equals("")){ result = "未正确响应"; } } catch (Exception e) { e.printStackTrace(); System.out.println("发生异常:"+ e.getMessage()); } return result; } /** * 排序 */ public String sort(String token, String timestamp, String nonce){ String[] strArray = {token,timestamp,nonce}; Arrays.sort(strArray); StringBuilder sb = new StringBuilder(); for(String str : strArray){ sb.append(str); } return sb.toString(); } /** * 进行sha1加密 */ public String sha1(String str){ try { MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(str.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); // 字节数组转换为 十六进制 数 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } }
三、启动咱们的服务,这里直接运行SpringbootApplication.java就能够了 我使用的是springboot 有关springboot 的知识请自行百度
四、运行咱们的natapp.exe 将咱们的服务映射到外网
五、将映射的http地址配置到测试帐号中
这里的 URL必定要保证和natapp中映射的外网地址相匹配;
六、咱们的服务后台是打印出以下信息表示咱们的本地服务器配置成功
Ok到这里本文关于接入服务器的演示完毕!