服务器接受图片消息
继上一章节(【公众号-个人订阅号开发】接受文本消息&响应文本消息)实现了公众号后端收发文本消息以后,本章节将实现公众号后台收发文本消息的功能。
老规矩,假设如下场景。
- 用户A发送一张图片消息给到微信订阅号接入的服务器后台
- 微信后台自动回复图片消息给到用户A
开发代码
基于上一章的代码(【公众号-个人订阅号开发】接受文本消息&响应文本消息)继续开发。
接收图片消息实体类
官方文本数据说明如下
图片消息xml 样例
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<PicUrl><![CDATA[this is a url]]></PicUrl>
<MediaId><![CDATA[media_id]]></MediaId>
<MsgId>1234567890123456</MsgId>
<MsgDataId>xxxx</MsgDataId>
<Idx>xxxx</Idx>
</xml>
字段说明
参数 | 描述 |
---|---|
ToUserName | 开发者微信号 |
FromUserName | 发送方账号(一个OpenID) |
CreateTime | 消息创建时间 (整型) |
MsgType | 消息类型,图片为image |
PicUrl | 图片链接(由系统生成) |
MediaId | 图片消息媒体id,可以调用获取临时素材接口拉取数据。 |
MsgId | 消息id,64位整型 |
MsgDataId | 消息的数据ID(消息如果来自文章时才有) |
Idx | 多图文时第几篇文章,从1开始(消息如果来自文章时才有) |
ReceiveMessage实体类Java
通过比较发现,相对于文本消息无非就是多了PicUrl和MediaId, 所以把上一章中的实体类(ReceiveTextMessage.java)重命名为ReceiveMessage.java。这样一个实体类就可以接受两种消息。你也可以定义基类比如BaseMessage.java抽取公共部分,这边暂先不抽取。
package top.xyx0123.wx.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import lombok.Data;
/**
* ReceiveMessage.
*/
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
@Data
@Schema(example =
//Text
// "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
// "<xml>\n" +
// " <Content>你好</Content>\n" +
// " <CreateTime>0</CreateTime>\n" +
// " <ToUserName>B</ToUserName>\n" +
// " <FromUserName>A</FromUserName>\n" +
// " <MsgDataId>msgDataId</MsgDataId>\n" +
// " <MsgId>msgId</MsgId>\n" +
// " <MsgType>text</MsgType>\n" +
// "</xml>",
//Pic
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<xml>\n" +
" <ToUserName><![CDATA[toUser]]></ToUserName>\n" +
" <FromUserName><![CDATA[fromUser]]></FromUserName>\n" +
" <CreateTime>1348831860</CreateTime>\n" +
" <MsgType><![CDATA[image]]></MsgType>\n" +
" <PicUrl><![CDATA[this is a url]]></PicUrl>\n" +
" <MediaId><![CDATA[media_id]]></MediaId>\n" +
" <MsgId>1234567890123456</MsgId>\n" +
" <MsgDataId>xxxx</MsgDataId>\n" +
" <Idx>xxxx</Idx>\n" +
"</xml>")
public class ReceiveMessage {
private String ToUserName;
private String FromUserName;
private long CreateTime;
private String MsgType;
private long MsgId;
private String MsgDataId;
private String Content;
/** new fields as below. **/
// <PicUrl><![CDATA[this is a url]]></PicUrl>
// <MediaId><![CDATA[media_id]]></MediaId>
private String PicUrl;
private String MediaId;
}
响应图片消息实体类
响应xml 样例
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
<MediaId><![CDATA[media_id]]></MediaId>
</Image>
</xml>
字段说明
参数 | 是否必须 | 说明 |
---|---|---|
ToUserName | 是 | 接收方账号(收到的OpenID) |
FromUserName | 是 | 开发者微信号 |
CreateTime | 是 | 消息创建时间 (整型) |
MsgType | 是 | 消息类型,图片为image |
MediaId | 是 | 通过素材管理中的接口上传多媒体文件,得到的id。 |
ResponseMessage实体类Java
同样的我们把上一章提到的ResponseTextMessage实体类改成ResponseMessage并添加MediaId字段。这里要注意下,MediaId需要被Image标签包裹,并是一个数组类型。
package top.xyx0123.wx.entity;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElementWrapper;
import jakarta.xml.bind.annotation.XmlRootElement;
import lombok.Data;
/**
* ResponseMessage.
*/
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class ResponseMessage {
private String ToUserName;
private String FromUserName;
private long CreateTime;
private String MsgType;
private String Content;
@XmlElementWrapper(name = "Image")
private String[] MediaId;
}
Controller 接收逻辑修改
逻辑如下
- 解析MsgType字段,text类型回复文本消息“好的,正在为你转接中”
- 解析MgsType字段,image类型回复图片消息,我这边是把用户发送进来的图片又回复给用户。
@RequestMapping(value = "/wechat/validate", method = RequestMethod.POST,
produces = {"application/xml; charset=UTF-8",},
consumes = {"text/xml; charset=UTF-8"})
public ResponseMessage receiveMessage(@RequestBody ReceiveMessage receiveMessage) {
log.info("Receive message: {}", receiveMessage);
ResponseMessage responseMessage = new ResponseMessage();
if ("text".equals(receiveMessage.getMsgType())) {
responseMessage.setToUserName(receiveMessage.getFromUserName());
responseMessage.setFromUserName(receiveMessage.getToUserName());
responseMessage.setCreateTime(new Date().getTime());
responseMessage.setMsgType(receiveMessage.getMsgType());
responseMessage.setContent("好的,正在为你转接中");
} else if ("image".equals(receiveMessage.getMsgType())) {
responseMessage.setToUserName(receiveMessage.getFromUserName());
responseMessage.setFromUserName(receiveMessage.getToUserName());
responseMessage.setCreateTime(new Date().getTime());
responseMessage.setMsgType(receiveMessage.getMsgType());
responseMessage.setMediaId(new String[]{receiveMessage.getMediaId()});
}
return responseMessage;
}
测试
本地sawgger测试文本消息
回归测试下之前的文本消息是否正常
- 输入构建文本消息体
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<Content>你好</Content>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType>text</MsgType>
<MsgId>1234567890123456</MsgId>
<MsgDataId>xxxx</MsgDataId>
<Idx>xxxx</Idx>
</xml>
- 测试结果
本地sawgger测试图片消息
- 输入构建图片消息体
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<PicUrl><![CDATA[this is a url]]></PicUrl>
<MediaId><![CDATA[media_id]]></MediaId>
<MsgId>1234567890123456</MsgId>
<MsgDataId>xxxx</MsgDataId>
<Idx>xxxx</Idx>
</xml>
- 测试结果
公众号测试
部署代码,在“软件老许”公众号上测试下功能。
- 搜索“软件老许” 公众号
- 发送文本消息“你好”
- 发送图片信息
结果如下
写在最后
至此,微信公众号的接收图片消息以及回复图片消息的功能已经开发测试完成。大家可以关注我的公众号(软件老许)去验证实现的功能,后面开发的功能也都会集成到这个公众号上面。
目前实现的功能
- 公众号-订阅号服务器接入
- 接收/回复文本消息
- 接收回复图片消息
更多功能敬请期待
谢谢大家! 十一假期快乐!