1. 编写接入代码有一个这样简单的需求,用户发送消息到公众号,经过Java后台的逻辑处理后,返回处理结果给用户。
编写代码之前我们需要引入两个依赖。
commons-codec commons-codec 1.10 org.dom4j dom4j 2.0.0
我们需要向微信后台暴露一个接口,以供微信调用。这里采用get请求方式,请求路径自己定义。
微信会给我们传signature 、timestamp 、nonce 和echostr 四个参数,我们需要做的是用前三个参数做校验,校验成功之后原封不动的返回echostr 。
这里需要自定义设置一个TOKEN的值,后续配置用得到。
@RestController
public class WxController {
public static final String TOKEN = "123456";
@GetMapping("/wx/echo")
public String echo(HttpServletRequest req, HttpServletResponse resp) {
// 1.获取微信传入的4个参数
String signature = req.getParameter("signature");
String timestamp = req.getParameter("timestamp");
String nonce = req.getParameter("nonce");
String echostr = req.getParameter("echostr");
// 2.用timestamp, nonce, signature进行校验
boolean result = check(timestamp, nonce, signature);
if (result) {
// 3.校验成功返回echostr
return echostr;
}
return "error!";
}
public static boolean check(String timestamp, String nonce, String signature) {
// 1.按字典序对TOKEN, timestamp和nonce排序
String[] arr = new String[]{TOKEN,timestamp,nonce};
Arrays.sort(arr);
// 2.将3个参数拼成一个字符串进行sha1加密
String str = arr[0]+arr[1]+arr[2];
// 3.用commons-codec包中的工具类进行sha1加密
str = DigestUtils.sha1Hex(str);
// 4.将加密后的字符串和signature比较
System.out.println(signature);
return str.equalsIgnoreCase(signature);
}
}
2.公众号配置
登陆公众号后台,选择基本配置。URL填入你的接口地址,Token与步骤1中定义的TOKEN保持一致。简单起见,EncodingAESKey随机生成,消息加密方式选择明文模式。
点击提交,提示提交成功。
由于URL使用的是80端口,而后台服务不一定是80端口,所以这里需要用nginx做一些反向代理。
location ~ / {
proxy_pass http://127.0.0.1:8080;
}
3.接收用户消息
上述操作已经成功连接微信与Java后台,接下来接受用户发送的消息。
当普通微信用户向公众账号发消息时,微信服务器将 POST 消息的 XML 数据包到开发者填写的 URL 上。数据包格式如下。
1348831860 1234567890123456 xxxx xxxx
我们写一个post接口,用来解析消息、逻辑处理以及回复消息。路径与步骤二中的URL一致。
@PostMapping("/wx/echo")
public String echoPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1.解析消息
Map param = parseRequest(req.getInputStream());
// 2.逻辑处理(可以根据自身逻辑进行处理,这里略)
// ...........
// 3.回复消息
String textMsg = "" +
" " +
" " +
"12345678 " +
" " +
" " +
" ";
return textMsg;
}
// 利用dom4j中的类进行解析
public static Map parseRequest(InputStream is) {
Map map = new HashMap();
// 1. 通过io流得到文档对象
SAXReader saxReader = new SAXReader();
Document document = null;
try {
document = saxReader.read(is);
} catch (DocumentException e) {
e.printStackTrace();
}
// 2.通过文档对象得到根节点对象
Element root = document.getRootElement();
// 3.通过根节点对象获取所有子节点对象
List elements = root.elements();
// 4.将所有节点放入map
for (Element element : elements) {
map.put(element.getName(), element.getStringValue());
}
return map;
}
上述代码,无论我们发送什么消息给公众号,公众号都将回复你好。
由于微信会进行超时重试,因此需要进行排重。建议使用redis进行排重,这里不做演示。



