掌握公众号消息接收与回复机制
公众号可以接收和发送多种类型的消息,实现与用户的互动。
微信服务器将消息以XML格式POST到开发者服务器。
| 参数 | 说明 |
|---|---|
| ToUserName | 开发者微信号(公众号原始ID) |
| FromUserName | 发送方OpenID |
| CreateTime | 消息创建时间(整型) |
| MsgType | 消息类型(text/image/voice等) |
| MsgId | 消息ID(64位整型) |
<xml>
<ToUserName><![CDATA[gh_1234567890ab]]></ToUserName>
<FromUserName><![CDATA[oABCDEFGHIJKLMNOPQRSTUVWXYZ]]></FromUserName>
<CreateTime>1648800000</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>@RestController
@RequestMapping("/wechat")
public class WechatMessageController {
@PostMapping
public String handleMessage(@RequestBody String xml) {
// 这里可以使用 JAXB / XStream / 自己解析 XML
// 为了示例,省略解析细节,只演示返回一个固定文本
String toUser = "用户OpenID"; // 从 XML 中解析
String fromUser = "公众号原始ID"; // 从 XML 中解析
return buildTextMessage(toUser, fromUser, "你好,我收到了你的消息!");
}
private String buildTextMessage(String toUser, String fromUser, String content) {
long now = System.currentTimeMillis() / 1000;
return "<xml>" +
"<ToUserName><![CDATA[" + toUser + "]]></ToUserName>" +
"<FromUserName><![CDATA[" + fromUser + "]]></FromUserName>" +
"<CreateTime>" + now + "</CreateTime>" +
"<MsgType><![CDATA[text]]></MsgType>" +
"<Content><![CDATA[" + content + "]]></Content>" +
"</xml>";
}
}<xml>
<ToUserName><![CDATA[openid]]></ToUserName>
<FromUserName><![CDATA[gh_id]]></FromUserName>
<CreateTime>1648800000</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>2</ArticleCount>
<Articles>
<item>
<Title><![CDATA[标题1]]></Title>
<Description><![CDATA[描述1]]></Description>
<PicUrl><![CDATA[https://example.com/pic1.jpg]]></PicUrl>
<Url><![CDATA[https://example.com/article1]]></Url>
</item>
</Articles>
</xml>public String buildNewsMessage(String toUser, String fromUser, List<Article> articles) {
long now = System.currentTimeMillis() / 1000;
StringBuilder items = new StringBuilder();
for (Article a : articles) {
items.append(" <item>")
.append("<Title><![CDATA[").append(a.getTitle()).append("]]></Title>")
.append("<Description><![CDATA[").append(a.getDescription()).append("]]></Description>")
.append("<PicUrl><![CDATA[").append(a.getPicUrl()).append("]]></PicUrl>")
.append("<Url><![CDATA[").append(a.getUrl()).append("]]></Url>")
.append("</item>");
}
return "<xml>" +
"<ToUserName><![CDATA[" + toUser + "]]></ToUserName>" +
"<FromUserName><![CDATA[" + fromUser + "]]></FromUserName>" +
"<CreateTime>" + now + "</CreateTime>" +
"<MsgType><![CDATA[news]]></MsgType>" +
"<ArticleCount>" + articles.size() + "</ArticleCount>" +
"<Articles>" + items + "</Articles>" +
"</xml>";
}<xml>
<ToUserName><![CDATA[gh_1234567890ab]]></ToUserName>
<FromUserName><![CDATA[openid]]></FromUserName>
<CreateTime>1648800000</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
</xml>// 伪代码示例,省略 XML 解析细节
if ("event".equals(msgType) && "subscribe".equals(event)) {
String replyXml = buildTextMessage(fromUser, toUser, "欢迎关注!回复\"帮助\"查看功能。");
// 返回 replyXml 即可
}public Map<String, Object> sendCustomMessage(String accessToken,
String openId,
String content) {
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + accessToken;
Map<String, Object> text = new HashMap<>();
text.put("content", content);
Map<String, Object> body = new HashMap<>();
body.put("touser", openId);
body.put("msgtype", "text");
body.put("text", text);
return restTemplate.postForObject(url, body, Map.class);
}