公众号后台开发(SpingMVC接收与响应公众号消息)
<h2>1.准备</h2><h3>1.准备服务</h3>
<p>与微信对接的url要具备以下条件:</p>
<p>(1)在公网上能够访问</p>
<p>(2)端口只支持80端口</p>
<p> 在这里如果是公网能够访问的服务最好,也可以通过花生壳或者其他外网映射工具进行映射,比如ngrok。</p>
<h3>2.数据交互原理</h3>
<p> 开发模式与编辑模式是互斥的,打开开发模式的时候,编辑模式的自动回复与自定义菜单失效;打开编辑模式的自动回复或者自定义菜单的时候开发模式会失效。</p>
<p><img src="https://img2018.cnblogs.com/blog/1196212/201910/1196212-20191016222120769-2060530279.png" alt=""></p>
<p> </p>
<p> </p>
<p>开发模式的数据交互原理如下:</p>
<p><img src="https://img2018.cnblogs.com/blog/1196212/201910/1196212-20191016222342715-381802745.png" alt=""></p>
<p> </p>
<p> 我们需要开发的任务就是维信公众号服务器,包括业务逻辑、身份验证等操作。</p>
<h2>2.接入后台</h2>
<p> 参考公众号开发文档: 开发->开发者工具-》开发者文档,里面有类似于对接钉钉的文档,有接入指南以及其他接口文档。</p>
<p> https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html</p>
<h3>1. 第一步:填写服务器配置</h3>
<p> 到公众号后台: https://mp.weixin.qq.com/</p>
<p> </p>
<p><img src="https://img2018.cnblogs.com/blog/1196212/201910/1196212-20191021224800601-2006796541.png" alt=""></p>
<p> </p>
<h3 id="第二步:验证消息的确来自微信服务器">2 第二步:验证消息的确来自微信服务器(在自己的微信服务器进行验证)</h3>
<p> 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下表所示:</p>
<p><img src="https://img2018.cnblogs.com/blog/1196212/201910/1196212-20191021224854921-663902077.png" alt=""></p>
<p> </p>
<p>开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:</p>
<p>1)将token、timestamp、nonce三个参数进行字典序排序 2)将三个参数字符串拼接成一个字符串进行sha1加密 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信</p>
<p>SpringMVC接收代码如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.controller.weixin;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.commons.lang3.StringUtils;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.Logger;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.LoggerFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.stereotype.Controller;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.web.bind.annotation.RequestMapping;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.web.bind.annotation.RequestParam;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.web.bind.annotation.ResponseBody;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.controller.UserController;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.weixin.WeixinCheckUtils;
@Controller
@RequestMapping(</span>"weixin"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> WeixinController {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> Logger logger = LoggerFactory.getLogger(UserController.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
@ResponseBody
@RequestMapping(</span>"index"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span> String index(@RequestParam(required = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">) String signature,
@RequestParam(required </span>= <span style="color: rgba(0, 0, 255, 1)">false</span>) String timestamp, @RequestParam(required = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">) String nonce,
@RequestParam(required </span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">) String echostr) {
logger.debug(</span>"signature: {}, timestamp: {}, nonce: {}, echostr: {}"<span style="color: rgba(0, 0, 0, 1)">, signature, timestamp, nonce, echostr);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNoneBlank(signature, timestamp, nonce)
</span>&&<span style="color: rgba(0, 0, 0, 1)"> WeixinCheckUtils.checkSignature(signature, timestamp, nonce)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> echostr;
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> "error"<span style="color: rgba(0, 0, 0, 1)">;
}
}</span></pre>
</div>
<p> </p>
<p>验证工具如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.weixin;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.security.MessageDigest;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Arrays;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> WeixinCheckUtils {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> token,与微信公众号后台的一致</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String token = "devqiaolq"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> checkSignature(String signature, String timestamp, String nonce) {
String[] arr </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> String[] { token, timestamp, nonce };
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 排序</span>
<span style="color: rgba(0, 0, 0, 1)"> Arrays.sort(arr);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 生成字符串</span>
StringBuffer content = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringBuffer();
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i < arr.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
content.append(arr);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> sha1加密</span>
String temp =<span style="color: rgba(0, 0, 0, 1)"> getSha1(content.toString());
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> temp.equals(signature);
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String getSha1(String str) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (str == <span style="color: rgba(0, 0, 255, 1)">null</span> || str.length() == 0<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">char</span> hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'<span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
MessageDigest mdTemp </span>= MessageDigest.getInstance("SHA1"<span style="color: rgba(0, 0, 0, 1)">);
mdTemp.update(str.getBytes(</span>"UTF-8"<span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 0, 255, 1)">byte</span>[] md =<span style="color: rgba(0, 0, 0, 1)"> mdTemp.digest();
</span><span style="color: rgba(0, 0, 255, 1)">int</span> j =<span style="color: rgba(0, 0, 0, 1)"> md.length;
</span><span style="color: rgba(0, 0, 255, 1)">char</span> buf[] = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">char</span>;
</span><span style="color: rgba(0, 0, 255, 1)">int</span> k = 0<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i < j; i++<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">byte</span> byte0 =<span style="color: rgba(0, 0, 0, 1)"> md;
buf = hexDigits;
buf = hexDigits;
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> String(buf);
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
}</span></pre>
</div>
<h3> </h3>
<p><span style="color: rgba(255, 0, 0, 1)"><strong> 注意:如果有登录过滤器,记得在过滤器中放行微信请求.</strong></span></p>
<p> </p>
<h2 id="第三步:依据接口文档实现业务逻辑">3. 第三步:依据接口文档实现业务逻辑</h2>
<h3>1. 首先需要启用开发者模式:(启用开发者模式之后自己的自定义菜单就不会生效)</h3>
<p><img src="https://img2018.cnblogs.com/blog/1196212/201910/1196212-20191023214701145-1911482809.png" alt=""></p>
<h3>2. 接收与响应文字消息</h3>
<p><strong> 当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。</strong></p>
<p>文本消息的xml数据格式如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">xml</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">ToUserName</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">ToUserName</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">FromUserName</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">FromUserName</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">CreateTime</span><span style="color: rgba(0, 0, 255, 1)">></span>1348831860<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">CreateTime</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">MsgType</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">MsgType</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">Content</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">Content</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">MsgId</span><span style="color: rgba(0, 0, 255, 1)">></span>1234567890123456<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">MsgId</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">xml</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p> </p>
<p>参数解释:</p>
<div class="table-wrp">
<table>
<thead>
<tr><th>参数</th><th>描述</th></tr>
</thead>
<tbody>
<tr>
<td>ToUserName</td>
<td>开发者微信号</td>
</tr>
<tr>
<td>FromUserName</td>
<td>发送方帐号(一个OpenID)</td>
</tr>
<tr>
<td>CreateTime</td>
<td>消息创建时间 (整型)</td>
</tr>
<tr>
<td>MsgType</td>
<td>消息类型,文本为text</td>
</tr>
<tr>
<td>Content</td>
<td>文本消息内容</td>
</tr>
<tr>
<td>MsgId</td>
<td>消息id,64位整型</td>
</tr>
</tbody>
</table>
</div>
<p> </p>
<p>(1)建立后台对应的TextMessage实体类:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> TextMessage {
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 开发者微信号
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String ToUserName;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 发送方帐号(一个OpenID)
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String FromUserName;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 消息创建时间 (整型)
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)"> CreateTime;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* text
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String MsgType;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 文本消息内容
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String Content;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 消息id,64位整型
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String MsgId;
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String toString() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> "TextMessage{" + "ToUserName='" + ToUserName + '\'' + ", FromUserName='" + FromUserName + '\''
+ ", CreateTime=" + CreateTime + ", MsgType='" + MsgType + '\'' + ", Content='" + Content + '\''
+ ", MsgId='" + MsgId + '\'' + '}'<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getToUserName() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ToUserName;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setToUserName(String toUserName) {
ToUserName </span>=<span style="color: rgba(0, 0, 0, 1)"> toUserName;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getFromUserName() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> FromUserName;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setFromUserName(String fromUserName) {
FromUserName </span>=<span style="color: rgba(0, 0, 0, 1)"> fromUserName;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)"> getCreateTime() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> CreateTime;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> setCreateTime(<span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)"> createTime) {
CreateTime </span>=<span style="color: rgba(0, 0, 0, 1)"> createTime;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getMsgType() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> MsgType;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setMsgType(String msgType) {
MsgType </span>=<span style="color: rgba(0, 0, 0, 1)"> msgType;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getContent() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Content;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setContent(String content) {
Content </span>=<span style="color: rgba(0, 0, 0, 1)"> content;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getMsgId() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> MsgId;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setMsgId(String msgId) {
MsgId </span>=<span style="color: rgba(0, 0, 0, 1)"> msgId;
}
}</span></pre>
</div>
<p> </p>
<p>(2)编写工具类实现xml(接收的是xml格式的数据)转map和TextMessage对象转换成xml(响应数据格式为xml)</p>
<p>pom加入:</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">微信转换XML所需包 </span><span style="color: rgba(0, 128, 0, 1)">--></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>dom4j<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>dom4j<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">></span>1.6.1<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream </span><span style="color: rgba(0, 128, 0, 1)">--></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>com.thoughtworks.xstream<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>xstream<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">></span>1.4.10<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p> </p>
<p>工具类:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.weixin;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.io.IOException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.io.InputStream;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.HashMap;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.List;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Map;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.servlet.http.HttpServletRequest;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.dom4j.Document;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.dom4j.DocumentException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.dom4j.Element;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.dom4j.io.SAXReader;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> com.thoughtworks.xstream.XStream;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.TextMessage;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MessageUtils {
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* xml数据转map
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> request
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span><span style="color: rgba(0, 128, 0, 1)">
* </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> IOException
* </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> DocumentException
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Map<String, String> xmlToMap(HttpServletRequest request) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException, DocumentException {
Map</span><String, String> map = <span style="color: rgba(0, 0, 255, 1)">new</span> HashMap<><span style="color: rgba(0, 0, 0, 1)">();
SAXReader reader </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SAXReader();
InputStream inputStream </span>=<span style="color: rgba(0, 0, 0, 1)"> request.getInputStream();
Document document </span>=<span style="color: rgba(0, 0, 0, 1)"> reader.read(inputStream);
Element root </span>=<span style="color: rgba(0, 0, 0, 1)"> document.getRootElement();
List</span><Element> list =<span style="color: rgba(0, 0, 0, 1)"> root.elements();
</span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (Element element : list) {
map.put(element.getName(), element.getText());
}
inputStream.close();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> map;
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 将文本消息对象转换成xml
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> textMessage
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
<span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String textMessageToXml(TextMessage textMessage) {
XStream xStream </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> XStream();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将xml的根元素替换成xml</span>
xStream.alias("xml"<span style="color: rgba(0, 0, 0, 1)">, textMessage.getClass());
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> xStream.toXML(textMessage);
}
}</span></pre>
</div>
<p> </p>
<p>(3)重写Controller接收消息和响应消息</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.controller.weixin;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.io.IOException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.io.PrintWriter;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Date;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Map;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.servlet.http.HttpServletRequest;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.servlet.http.HttpServletResponse;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.commons.lang3.StringUtils;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.dom4j.DocumentException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.Logger;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.LoggerFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.stereotype.Controller;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.web.bind.annotation.RequestMapping;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.web.bind.annotation.RequestMethod;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.TextMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.controller.UserController;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.weixin.MessageUtils;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.weixin.WeixinCheckUtils;
@Controller
@RequestMapping(</span>"weixin"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> WeixinController {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> Logger logger = LoggerFactory.getLogger(UserController.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
@RequestMapping(value </span>= "index", method =<span style="color: rgba(0, 0, 0, 1)"> { RequestMethod.GET, RequestMethod.POST })
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> index(HttpServletRequest request, HttpServletResponse response) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将请求、响应的编码均设置为UTF-8(防止中文乱码)</span>
request.setCharacterEncoding("UTF-8"); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码;</span>
response.setCharacterEncoding("UTF-8"); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上;</span>
<span style="color: rgba(0, 0, 0, 1)">
String method </span>=<span style="color: rgba(0, 0, 0, 1)"> request.getMethod().toLowerCase();
logger.info(</span>"method: {}"<span style="color: rgba(0, 0, 0, 1)">, method);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 验证是否是微信请求</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> ("get"<span style="color: rgba(0, 0, 0, 1)">.equals(method)) {
doGet(request, response);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> POST请求接收消息,且给客户响应消息</span>
<span style="color: rgba(0, 0, 0, 1)"> doPost(request, response);
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* Post请求用于接收消息且处理消息之后回传消息
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> request
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> response
* </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> IOException
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doPost(HttpServletRequest request, HttpServletResponse response) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException {
PrintWriter out </span>=<span style="color: rgba(0, 0, 0, 1)"> response.getWriter();
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
Map</span><String, String> map =<span style="color: rgba(0, 0, 0, 1)"> MessageUtils.xmlToMap(request);
String fromUserName </span>= map.get("FromUserName"<span style="color: rgba(0, 0, 0, 1)">);
String toUserName </span>= map.get("ToUserName"<span style="color: rgba(0, 0, 0, 1)">);
String msgType </span>= map.get("MsgType"<span style="color: rgba(0, 0, 0, 1)">);
String content </span>= map.get("Content"<span style="color: rgba(0, 0, 0, 1)">);
logger.info(</span>"map: {}"<span style="color: rgba(0, 0, 0, 1)">, map);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotBlank(content)) {
System.out.println(</span>"接收的的消息为:" + content + ",你可以根据关键字进行搜索或者做其他"<span style="color: rgba(0, 0, 0, 1)">);
}
String message </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> ("text"<span style="color: rgba(0, 0, 0, 1)">.equals(msgType)) {
TextMessage textMessage </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TextMessage();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 回传消息,所以讲fromuser和toUser交换</span>
<span style="color: rgba(0, 0, 0, 1)"> textMessage.setFromUserName(toUserName);
textMessage.setToUserName(fromUserName);
textMessage.setMsgType(msgType);
textMessage.setCreateTime(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date().getTime());
textMessage.setContent(</span>"您发送的消息为: " +<span style="color: rgba(0, 0, 0, 1)"> content);
logger.info(</span>"textMessage: {}"<span style="color: rgba(0, 0, 0, 1)">, textMessage);
message </span>=<span style="color: rgba(0, 0, 0, 1)"> MessageUtils.textMessageToXml(textMessage);
}
out.print(message);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 把消息发送到客户端</span>
} <span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (DocumentException e) {
logger.error(</span>"dispose post request error"<span style="color: rgba(0, 0, 0, 1)">, e);
} </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
out.close();
}
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* Get请求用于微信配置验证
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> request
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> response
* </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> IOException
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doGet(HttpServletRequest request, HttpServletResponse response) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException {
String signature </span>= request.getParameter("signature");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 微信加密签名</span>
String timestamp = request.getParameter("timestamp");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 时间戳</span>
String nonce = request.getParameter("nonce");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 随机数</span>
String echostr = request.getParameter("echostr");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 随机字符串</span>
logger.info("signature: {}, timestamp: {}, nonce: {}, echostr: {}"<span style="color: rgba(0, 0, 0, 1)">, signature, timestamp, nonce, echostr);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNoneBlank(signature, timestamp, nonce)
</span>&&<span style="color: rgba(0, 0, 0, 1)"> WeixinCheckUtils.checkSignature(signature, timestamp, nonce)) {
response.getWriter().write(echostr);
}
}
}</span></pre>
</div>
<p> </p>
<p>测试:</p>
<p><img src="https://img2018.cnblogs.com/blog/1196212/201910/1196212-20191023233117105-1989552956.png" alt=""></p>
<p> </p>
<p><strong>Java服务器日志如下:</strong></p>
<p>2019-10-23 23:34:15.625 INFO 244500 --- cn.qlq.controller.UserController : method: post<br>2019-10-23 23:34:15.633INFO 244500 --- cn.qlq.controller.UserController : map: {MsgId=22503405793257008, FromUserName=o_qAo0u6Snhoc7Z45RfSxYatMWpo, CreateTime=1571844638, Content=怎么了, ToUserName=gh_fc4bd5c2fda8, MsgType=text}<br>接收的的消息为:怎么了,你可以根据关键字进行搜索或者做其他<br>2019-10-23 23:34:15.635INFO 244500 --- cn.qlq.controller.UserController : textMessage: TextMessage{ToUserName='o_qAo0u6Snhoc7Z45RfSxYatMWpo', FromUserName='gh_fc4bd5c2fda8', CreateTime=1571844855635, MsgType='text', Content='您发送的消息为: 怎么了', MsgId='null'}<br>2019-10-23 23:34:20.288INFO 244500 --- cn.qlq.controller.UserController : method: post<br>2019-10-23 23:34:20.295INFO 244500 --- cn.qlq.controller.UserController : map: {MsgId=22503406289173072, FromUserName=o_qAo0u6Snhoc7Z45RfSxYatMWpo, CreateTime=1571844642, Content=什么意思, ToUserName=gh_fc4bd5c2fda8, MsgType=text}<br>接收的的消息为:什么意思,你可以根据关键字进行搜索或者做其他<br>2019-10-23 23:34:20.296INFO 244500 --- cn.qlq.controller.UserController : textMessage: TextMessage{ToUserName='o_qAo0u6Snhoc7Z45RfSxYatMWpo', FromUserName='gh_fc4bd5c2fda8', CreateTime=1571844860296, MsgType='text', Content='您发送的消息为: 什么意思', MsgId='null'}</p>
<p> </p>
<h2>4. 接收其他类型的消息以及返回文本消息、图文消息</h2>
<p> 公众号可以接受的消息大概有文本消息(在上面已经接收)、图片(image)消息、语音(voice,在后台接口开启语音识别可以自动识别文字)消息、视频(video)消息、短视频(shortvideo)消息、地理位置(location)消息、链接(link)消息、事件(event,事件类型:subscribe(订阅)、unsubscribe(取消订阅))消息。</p>
<p> 公众号可以回复的消息有: 文本(text)消息、图片消息(image)、语音消息(voice)、视频消息(video)、音乐消息(music)、图文(news)消息。</p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)"><strong>注意:这里需要注意接收的消息和发送的消息数据数据格式不一样。如下是回复的图片消息和图文消息的数据格式:</strong></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><strong>回传图片消息数据格式:</strong></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">xml</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">ToUserName</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">ToUserName</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">FromUserName</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">FromUserName</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">CreateTime</span><span style="color: rgba(0, 0, 255, 1)">></span>12345678<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">CreateTime</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">MsgType</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">MsgType</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">Image</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">MediaId</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">MediaId</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">Image</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">xml</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p> </p>
<p><span style="color: rgba(0, 0, 0, 1)">回传图文消息数据格式:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">xml</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">ToUserName</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">ToUserName</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">FromUserName</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">FromUserName</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">CreateTime</span><span style="color: rgba(0, 0, 255, 1)">></span>12345678<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">CreateTime</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">MsgType</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">MsgType</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">ArticleCount</span><span style="color: rgba(0, 0, 255, 1)">></span>1<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">ArticleCount</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">Articles</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">item</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">Title</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">Title</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">Description</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">Description</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">PicUrl</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">PicUrl</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">Url</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">Url</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">item</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">Articles</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">xml</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p> </p>
<p>自己封装的controller接收数据和消息处理的工具类如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.controller.weixin;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.io.IOException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.io.PrintWriter;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Map;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.servlet.http.HttpServletRequest;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.servlet.http.HttpServletResponse;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.commons.lang3.StringUtils;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.dom4j.DocumentException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.Logger;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.LoggerFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.stereotype.Controller;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.web.bind.annotation.RequestMapping;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.web.bind.annotation.RequestMethod;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.response.AbstractResponseMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.controller.UserController;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.weixin.MessageHandler;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.weixin.MessageUtils;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.weixin.WeixinCheckUtils;
@Controller
@RequestMapping(</span>"weixin"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> WeixinController {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> Logger logger = LoggerFactory.getLogger(UserController.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
@RequestMapping(value </span>= "index", method =<span style="color: rgba(0, 0, 0, 1)"> { RequestMethod.GET, RequestMethod.POST })
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> index(HttpServletRequest request, HttpServletResponse response) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将请求、响应的编码均设置为UTF-8(防止中文乱码)</span>
request.setCharacterEncoding("UTF-8"); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码;</span>
response.setCharacterEncoding("UTF-8"); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上;</span>
<span style="color: rgba(0, 0, 0, 1)">
String method </span>=<span style="color: rgba(0, 0, 0, 1)"> request.getMethod().toLowerCase();
logger.info(</span>"method: {}"<span style="color: rgba(0, 0, 0, 1)">, method);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 验证是否是微信请求</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> ("get"<span style="color: rgba(0, 0, 0, 1)">.equals(method)) {
doGet(request, response);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> POST请求接收消息,且给客户响应消息</span>
<span style="color: rgba(0, 0, 0, 1)"> doPost(request, response);
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* Post请求用于接收消息且处理消息之后回传消息
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> request
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> response
* </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> IOException
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doPost(HttpServletRequest request, HttpServletResponse response) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException {
PrintWriter out </span>=<span style="color: rgba(0, 0, 0, 1)"> response.getWriter();
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 消息转map</span>
Map<String, Object> map =<span style="color: rgba(0, 0, 0, 1)"> MessageUtils.xmlToMap(request);
logger.info(</span>"接收到的消息map: {}"<span style="color: rgba(0, 0, 0, 1)">, map);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 调用工具类处理完之后显示回传消息</span>
AbstractResponseMessage responseMessage =<span style="color: rgba(0, 0, 0, 1)"> MessageHandler.handlMessage(map);
logger.info(</span>"回传的消息responseMessage: {}"<span style="color: rgba(0, 0, 0, 1)">, responseMessage);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (responseMessage == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
String messageToXml </span>=<span style="color: rgba(0, 0, 0, 1)"> MessageUtils.messageToXml(responseMessage);
logger.info(</span>"回传的消息responseMessage messageToXml: {}"<span style="color: rgba(0, 0, 0, 1)">, messageToXml);
out.print(messageToXml);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 把消息发送到客户端</span>
} <span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (DocumentException e) {
logger.error(</span>"dispose post request error"<span style="color: rgba(0, 0, 0, 1)">, e);
} </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
out.close();
}
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* Get请求用于微信配置验证
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> request
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> response
* </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> IOException
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doGet(HttpServletRequest request, HttpServletResponse response) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException {
String signature </span>= request.getParameter("signature");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 微信加密签名</span>
String timestamp = request.getParameter("timestamp");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 时间戳</span>
String nonce = request.getParameter("nonce");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 随机数</span>
String echostr = request.getParameter("echostr");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 随机字符串</span>
logger.info("signature: {}, timestamp: {}, nonce: {}, echostr: {}"<span style="color: rgba(0, 0, 0, 1)">, signature, timestamp, nonce, echostr);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNoneBlank(signature, timestamp, nonce)
</span>&&<span style="color: rgba(0, 0, 0, 1)"> WeixinCheckUtils.checkSignature(signature, timestamp, nonce)) {
response.getWriter().write(echostr);
}
}
}</span></pre>
</div>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.weixin;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Date;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Map;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.commons.collections.MapUtils;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.apache.commons.lang3.StringUtils;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.Logger;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.LoggerFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.EventMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.ImageMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.LinkMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.LocationMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.TextMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.VideoMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.VoiceMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.response.AbstractResponseMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.response.ImageResponseMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.response.NewsResponseMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.response.NewsResponseMessageArticle;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.response.NewsResponseMessageArticleItem;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.response.TextResponseMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.BeanUtils;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MessageHandler {
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_TEXT = "text"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_IMAGE = "image"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_VOICE = "voice"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_VIDEO = "video"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_LINK = "link"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_LOCATION = "location"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_EVENT = "event";<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 事件</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_SUBSCRIBE = "subscribe";<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 关注</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_UNSUBSCRIBE = "unsubscribe";<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 取消关注</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_CLICK = "CLICK"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String MESSAGE_VIEW = "VIEW"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> Logger logger = LoggerFactory.getLogger(MessageHandler.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AbstractResponseMessage handlMessage(Map<String, Object><span style="color: rgba(0, 0, 0, 1)"> messageMap) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MapUtils.isEmpty(messageMap)) {
logger.error(</span>"message is empty"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}
String msgType </span>= (String) messageMap.get("MsgType"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_TEXT.equals(msgType)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> handleTextMessage(messageMap);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_IMAGE.equals(msgType)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> handleImageMessage(messageMap);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_LOCATION.equals(msgType)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> handleLocationMessage(messageMap);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_EVENT.equals(msgType)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> handleEventMessage(messageMap);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_LINK.equals(msgType)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> handleLinkMessage(messageMap);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_VOICE.equals(msgType)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> handleVoiceMessage(messageMap);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_VIDEO.equals(msgType)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> handleVideoMessage(messageMap);
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AbstractResponseMessage handleVideoMessage(Map<String, Object><span style="color: rgba(0, 0, 0, 1)"> messageMap) {
VideoMessage message </span>= BeanUtils.map2Bean(messageMap, VideoMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String thumbMediaId </span>=<span style="color: rgba(0, 0, 0, 1)"> message.getThumbMediaId();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可以用图片路径做其他操作</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotBlank(thumbMediaId)) {
System.out.println(</span>"您接收到视频消息, thumbMediaId为: " +<span style="color: rgba(0, 0, 0, 1)"> thumbMediaId);
}
String responseMsg </span>= "您发送了一条视频消息,thumbMediaId为: " +<span style="color: rgba(0, 0, 0, 1)"> thumbMediaId;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> MessageUtils.initTextMessage(message.getToUserName(), message.getFromUserName(), responseMsg);
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AbstractResponseMessage handleVoiceMessage(Map<String, Object><span style="color: rgba(0, 0, 0, 1)"> messageMap) {
VoiceMessage message </span>= BeanUtils.map2Bean(messageMap, VoiceMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String recognition </span>=<span style="color: rgba(0, 0, 0, 1)"> message.getRecognition();
String format </span>=<span style="color: rgba(0, 0, 0, 1)"> message.getFormat();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可以用图片路径做其他操作</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotBlank(recognition)) {
System.out.println(</span>"您接收到语音消息, 格式为: " + format + ", 转换后的文字为: " +<span style="color: rgba(0, 0, 0, 1)"> recognition);
}
String responseMsg </span>= "您发送了一条语音消息,格式为: " + format + ", 转换后的文字为: " +<span style="color: rgba(0, 0, 0, 1)"> recognition;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> MessageUtils.initTextMessage(message.getToUserName(), message.getFromUserName(), responseMsg);
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 处理链接消息(回复一条图文消息)
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> message
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
<span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AbstractResponseMessage handleLinkMessage(Map<String, Object><span style="color: rgba(0, 0, 0, 1)"> messageMap) {
LinkMessage message </span>= BeanUtils.map2Bean(messageMap, LinkMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String desc </span>=<span style="color: rgba(0, 0, 0, 1)"> message.getDescription();
String title </span>=<span style="color: rgba(0, 0, 0, 1)"> message.getTitle();
String url </span>=<span style="color: rgba(0, 0, 0, 1)"> message.getUrl();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可以用图片路径做其他操作</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotBlank(url)) {
System.out.println(</span>"您接收到链接消息, title: " + title + ", desc: " + desc + ", url: " +<span style="color: rgba(0, 0, 0, 1)"> url);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 回复一条图文消息</span>
NewsResponseMessage news = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> NewsResponseMessage();
news.setCreateTime(System.currentTimeMillis());
news.setFromUserName(message.getToUserName());
news.setToUserName(message.getFromUserName());
news.setArticleCount(</span>"1"<span style="color: rgba(0, 0, 0, 1)">);
news.setMsgType(</span>"news"<span style="color: rgba(0, 0, 0, 1)">);
NewsResponseMessageArticle article </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> NewsResponseMessageArticle();
news.setArticles(article);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建多条图文消息</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i < 1; i++<span style="color: rgba(0, 0, 0, 1)">) {
NewsResponseMessageArticleItem item </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> NewsResponseMessageArticleItem();
item.setTitle(</span>"18年写的面试心得"<span style="color: rgba(0, 0, 0, 1)">);
item.setPicUrl(</span>"https://images.cnblogs.com/cnblogs_com/qlqwjy/1031659/o_9.bmp"<span style="color: rgba(0, 0, 0, 1)">);
item.setUrl(</span>"https://www.cnblogs.com/qlqwjy/p/9194434.html"<span style="color: rgba(0, 0, 0, 1)">);
item.setDescription(</span>"18年毕设心血来潮写的毕设心得,1年后再看有点东西。"<span style="color: rgba(0, 0, 0, 1)">);
article.addNewsResponseMessageArticleItem(item);
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> news;
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 处理事件消息(订阅和取消订阅)
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> messageMap
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
<span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AbstractResponseMessage handleEventMessage(Map<String, Object><span style="color: rgba(0, 0, 0, 1)"> messageMap) {
EventMessage message </span>= BeanUtils.map2Bean(messageMap, EventMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String event </span>=<span style="color: rgba(0, 0, 0, 1)"> message.getEvent();
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotBlank(event)) {
System.out.println(</span>"您接收到事件消息, 事件类型为: " +<span style="color: rgba(0, 0, 0, 1)"> event);
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_SUBSCRIBE.equals(event)) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 关注的时候</span>
System.out.println("这里可以向数据库插入数据"<span style="color: rgba(0, 0, 0, 1)">);
String responseMsg </span>=<span style="color: rgba(0, 0, 0, 1)"> MessageUtils.subscribeWelcomeText();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> MessageUtils.initTextMessage(message.getToUserName(), message.getFromUserName(), responseMsg);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 取消关注(不用回传消息.需要将用户产生的数据删除)</span>
System.out.println("这时需要从数据删除" + message.getFromUserName() + " 用户产生的相关数据"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AbstractResponseMessage handleLocationMessage(Map<String, Object><span style="color: rgba(0, 0, 0, 1)"> messageMap) {
LocationMessage message </span>= BeanUtils.map2Bean(messageMap, LocationMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String label </span>=<span style="color: rgba(0, 0, 0, 1)"> message.getLabel();
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotBlank(label)) {
System.out.println(</span>"您接收到位置消息, 地理位置信息为: " +<span style="color: rgba(0, 0, 0, 1)"> message);
}
String responseMsg </span>= "您发送了一条位置消息, 您的地理位置信息为:" +<span style="color: rgba(0, 0, 0, 1)"> label;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> MessageUtils.initTextMessage(message.getToUserName(), message.getFromUserName(), responseMsg);
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 处理图片消息(回复一条图片消息)
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> message
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
<span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AbstractResponseMessage handleImageMessage(Map<String, Object><span style="color: rgba(0, 0, 0, 1)"> message) {
ImageMessage imageMessage </span>= BeanUtils.map2Bean(message, ImageMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String url </span>=<span style="color: rgba(0, 0, 0, 1)"> imageMessage.getPicUrl();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可以用图片路径做其他操作</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotBlank(url)) {
System.out.println(</span>"您接收到的图片消息url为: " +<span style="color: rgba(0, 0, 0, 1)"> url);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 回传一条图片消息</span>
ImageResponseMessage responseMessage = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ImageResponseMessage();
responseMessage.setCreateTime(System.currentTimeMillis());
responseMessage.setFromUserName(imageMessage.getToUserName());
responseMessage.setToUserName(imageMessage.getFromUserName());
responseMessage.setMediaId(imageMessage.getMediaId());
responseMessage.setMsgType(MESSAGE_IMAGE);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> responseMessage;
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 处理文本消息
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> message
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
<span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AbstractResponseMessage handleTextMessage(Map<String, Object><span style="color: rgba(0, 0, 0, 1)"> message) {
TextMessage textMessage </span>= BeanUtils.map2Bean(message, TextMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String content </span>=<span style="color: rgba(0, 0, 0, 1)"> textMessage.getContent();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可以根据文本消息去查库或者进行其他操作</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotBlank(content)) {
System.out.println(</span>"您接收到的文本消息内容为: " +<span style="color: rgba(0, 0, 0, 1)"> content);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置回传的消息内容</span>
TextResponseMessage responseMessage = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TextResponseMessage();
responseMessage.setContent(</span>"服务器已接收到您的消息,内容为: " +<span style="color: rgba(0, 0, 0, 1)"> content);
responseMessage.setCreateTime(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date().getTime());
responseMessage.setFromUserName(textMessage.getToUserName());
responseMessage.setToUserName(textMessage.getFromUserName());
responseMessage.setMsgType(MESSAGE_TEXT);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> responseMessage;
}
}</span></pre>
</div>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.utils.weixin;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.io.IOException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.io.InputStream;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.HashMap;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.List;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Map;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.servlet.http.HttpServletRequest;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.dom4j.Document;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.dom4j.DocumentException;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.dom4j.Element;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.dom4j.io.SAXReader;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> com.thoughtworks.xstream.XStream;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.response.AbstractResponseMessage;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin.response.TextResponseMessage;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MessageUtils {
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* xml数据转map
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> request
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span><span style="color: rgba(0, 128, 0, 1)">
* </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> IOException
* </span><span style="color: rgba(128, 128, 128, 1)">@throws</span><span style="color: rgba(0, 128, 0, 1)"> DocumentException
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Map<String, Object> xmlToMap(HttpServletRequest request) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException, DocumentException {
Map</span><String, Object> map = <span style="color: rgba(0, 0, 255, 1)">new</span> HashMap<><span style="color: rgba(0, 0, 0, 1)">();
SAXReader reader </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SAXReader();
InputStream inputStream </span>=<span style="color: rgba(0, 0, 0, 1)"> request.getInputStream();
Document document </span>=<span style="color: rgba(0, 0, 0, 1)"> reader.read(inputStream);
Element root </span>=<span style="color: rgba(0, 0, 0, 1)"> document.getRootElement();
List</span><Element> list =<span style="color: rgba(0, 0, 0, 1)"> root.elements();
</span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (Element element : list) {
map.put(element.getName(), element.getText());
}
inputStream.close();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> map;
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 将文本消息对象转换成xml
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> message
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
<span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String messageToXml(AbstractResponseMessage message) {
XStream xStream </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> XStream();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将xml的根元素替换成xml</span>
xStream.alias("xml"<span style="color: rgba(0, 0, 0, 1)">, message.getClass());
xStream.alias(</span>"item", cn.qlq.bean.weixin.response.NewsResponseMessageArticleItem.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
xStream.addImplicitArray(cn.qlq.bean.weixin.response.NewsResponseMessageArticle.</span><span style="color: rgba(0, 0, 255, 1)">class</span>, "items"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> xStream.toXML(message);
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 将文本消息对象转换成xml
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> message
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
<span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String messageToXml2(AbstractResponseMessage message) {
XStream xStream </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> XStream();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将xml的根元素替换成xml</span>
xStream.alias("xml"<span style="color: rgba(0, 0, 0, 1)">, message.getClass());
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> xStream.toXML(message);
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 订阅后的欢迎信息
*
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
<span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String subscribeWelcomeText() {
StringBuffer sb </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringBuffer();
sb.append(</span>"欢迎您的关注,这里是乔治个人平台:\n\n"<span style="color: rgba(0, 0, 0, 1)">);
sb.append(</span>"1.推荐一些优秀的文章\n");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> \n代表换行</span>
sb.append("2.记录一些美好时刻\n\n"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sb.toString();
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 生成文本消息
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> fromUserName
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> toUserName
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> content
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
<span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> TextResponseMessage initTextMessage(String fromUserName, String toUserName, String content) {
TextResponseMessage textResponseMessage </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TextResponseMessage();
textResponseMessage.setFromUserName(fromUserName);
textResponseMessage.setToUserName(toUserName);
textResponseMessage.setMsgType(MessageHandler.MESSAGE_TEXT);
textResponseMessage.setCreateTime(System.currentTimeMillis());
textResponseMessage.setContent(content);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> textResponseMessage;
}
}</span></pre>
</div>
<p> 结果如下:</p>
<p><img src="https://img2018.cnblogs.com/blog/1196212/201910/1196212-20191025233514731-2118207046.png" alt=""></p>
<p> </p>
<h2>5. 获取用户的精度纬度信息 </h2>
<p>1.首先在接口设置开启经纬度事件(开启之后在用户进入公众号之后会主动拉取用户的位置信息)</p>
<p><img src="https://img2018.cnblogs.com/blog/1196212/201910/1196212-20191030115528891-1226577947.png" alt=""></p>
<p> </p>
<h3>2. 处理上报地理位置事件</h3>
<p> 用户同意上报地理位置后,每次进入公众号会话时,都会在进入时上报地理位置,或在进入会话后每5秒上报一次地理位置,公众号可以在公众平台网站中修改以上设置。上报地理位置时,微信会将上报地理位置事件推送到开发者填写的URL。 </p>
<p>推送的XML数据包格式如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">xml</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">ToUserName</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">ToUserName</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">FromUserName</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">FromUserName</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">CreateTime</span><span style="color: rgba(0, 0, 255, 1)">></span>123456789<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">CreateTime</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">MsgType</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">MsgType</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">Event</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 255, 1)"><!]></span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">Event</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">Latitude</span><span style="color: rgba(0, 0, 255, 1)">></span>23.137466<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">Latitude</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">Longitude</span><span style="color: rgba(0, 0, 255, 1)">></span>113.352425<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">Longitude</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">Precision</span><span style="color: rgba(0, 0, 255, 1)">></span>119.385040<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">Precision</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">xml</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p> </p>
<p>java处理:</p>
<p>封装工具类:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> cn.qlq.bean.weixin;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 上报地理位置事件
*
* </span><span style="color: rgba(128, 128, 128, 1)">@author</span><span style="color: rgba(0, 128, 0, 1)"> Administrator
*
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> LocationEventMessage <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> EventMessage {
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 地理位置纬度
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String Latitude;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 地理位置经度
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String Longitude;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 地理位置精度
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String Precision;
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getLatitude() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Latitude;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setLatitude(String latitude) {
Latitude </span>=<span style="color: rgba(0, 0, 0, 1)"> latitude;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getLongitude() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Longitude;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setLongitude(String longitude) {
Longitude </span>=<span style="color: rgba(0, 0, 0, 1)"> longitude;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getPrecision() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Precision;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setPrecision(String precision) {
Precision </span>=<span style="color: rgba(0, 0, 0, 1)"> precision;
}
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String toString() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> "LocationEventMessage [Latitude=" + Latitude + ", Longitude=" + Longitude + ", Precision=" +<span style="color: rgba(0, 0, 0, 1)"> Precision
</span>+ ", ToUserName=" + ToUserName + ", FromUserName=" + FromUserName + ", CreateTime=" +<span style="color: rgba(0, 0, 0, 1)"> CreateTime
</span>+ ", MsgType=" + MsgType + ", Event=" + Event + "]"<span style="color: rgba(0, 0, 0, 1)">;
}
}</span></pre>
</div>
<p> </p>
<p>修改处理事件消息的代码:(CLICK和VIEW是用于处理自定义菜单事件)</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* 处理事件消息(订阅和取消订阅)
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> messageMap
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
<span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> AbstractResponseMessage handleEventMessage(Map<String, Object><span style="color: rgba(0, 0, 0, 1)"> messageMap) {
EventMessage message </span>= BeanUtils.map2Bean(messageMap, EventMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String event </span>=<span style="color: rgba(0, 0, 0, 1)"> message.getEvent();
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotBlank(event)) {
System.out.println(</span>"您接收到事件消息, 事件类型为: " +<span style="color: rgba(0, 0, 0, 1)"> event);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 关注的时候</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_SUBSCRIBE.equals(event)) {
System.out.println(</span>"这里可以向数据库插入数据"<span style="color: rgba(0, 0, 0, 1)">);
String responseMsg </span>=<span style="color: rgba(0, 0, 0, 1)"> MessageUtils.subscribeWelcomeText();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> MessageUtils.initTextMessage(message.getToUserName(), message.getFromUserName(), responseMsg);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 取消关注(不用回传消息.需要将用户产生的数据删除)</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_SUBSCRIBE.equals(event)) {
System.out.println(</span>"这时需要从数据删除" + message.getFromUserName() + " 用户产生的相关数据"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 点击自定义的点击菜单事件</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_EVENT_CLICK.equals(event)) {
ClickViewEventMessage map2Bean </span>= BeanUtils.map2Bean(messageMap, ClickViewEventMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String eventKey </span>=<span style="color: rgba(0, 0, 0, 1)"> map2Bean.getEventKey();
String content </span>= "您点击的按钮的key为: " +<span style="color: rgba(0, 0, 0, 1)"> eventKey;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> MessageUtils.initTextMessage(map2Bean.getToUserName(), map2Bean.getFromUserName(), content);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> VIEW菜单的事件</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_EVENT_VIEW.equals(event)) {
ClickViewEventMessage map2Bean </span>= BeanUtils.map2Bean(messageMap, ClickViewEventMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String eventKey </span>=<span style="color: rgba(0, 0, 0, 1)"> map2Bean.getEventKey();
String content </span>= "您点击的按钮跳转的URL为: " +<span style="color: rgba(0, 0, 0, 1)"> eventKey;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> MessageUtils.initTextMessage(map2Bean.getToUserName(), map2Bean.getFromUserName(), content);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> LOCATION菜单的事件</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (MESSAGE_EVENT_LOCATION.equals(event)) {
LocationEventMessage map2Bean </span>= BeanUtils.map2Bean(messageMap, LocationEventMessage.<span style="color: rgba(0, 0, 255, 1)">class</span>, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
String latitude </span>=<span style="color: rgba(0, 0, 0, 1)"> map2Bean.getLatitude();
String longitude </span>=<span style="color: rgba(0, 0, 0, 1)"> map2Bean.getLongitude();
String precision </span>=<span style="color: rgba(0, 0, 0, 1)"> map2Bean.getPrecision();
String content </span>= "您的经度:" + latitude + ", 您的维度:" + longitude + ", 您的精度: " +<span style="color: rgba(0, 0, 0, 1)"> precision;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> MessageUtils.initTextMessage(map2Bean.getToUserName(), map2Bean.getFromUserName(), content);
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p>测试结果:(需要开启GPS才可以触发该事件消息发送)</p>
<p><img src="https://img2018.cnblogs.com/blog/1196212/201910/1196212-20191030120141606-622033290.png" alt=""></p>
<p> </p>
<h3>总结:</h3>
<p>(1)回传xml数据格式的数据时,可以用字符串进行拼接,不一定用XStream进行转换</p>
<p>(2)微信回传的消息支持换行,换行符为\n</p>
<p>(3)图文消息是最常见的消息,回传消息的时候注意回传的xml数据格式</p>
<p> </p>
<p>完整的代码接收消息与回传消息代码参考:https://github.com/qiao-zhi/springboot-ssm.git</p>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
<span style="font-size: 16px; color: #ff0000">
<strong>【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】</strong>
</span><br><br>
来源:https://www.cnblogs.com/qlqwjy/p/11688870.html
頁:
[1]