I. Introduction
Hello friends, everyone. The topic of this article is use Java开发微信公众号之被动回复用户消息-回复图文消息
. For those who don’t know the WeChat official account passively responding to user messages (文本消息、图片消息)
, please take a look at the article I wrote earlier: Java Development of WeChat Official Account Passive Reply to user message-reply to text message , don't talk nonsense, start to enter the topic below.
WeChat development document: WeChat official document-passively respond to user messages
Two, version description
- spring boot.version: v2.1.7.RELEASE
- java.version: 1.8
- weixin-java-mp.version: 3.5.0
Three, passively reply to messages
When a user sends a message to the official account (or when an event triggered by a specific user operation is pushed), a POST
request is generated . The developer can Get
return a specific XML structure in the response package ( ) to respond to the message (now support Response 文本
, 图片
, 图文
, 语音
, 视频
, 音乐
). Strictly speaking, sending a passive response message is not actually an interface, but a reply to the message sent by the WeChat server.
Four, message re-weighting
After the WeChat server sends the user's message to the developer server URL
address of the official account (configured in the Developer Center), the WeChat server will disconnect the connection if it does not receive a response within five seconds, and re-initiate the request, a total of three retries. If you Debug
find that the user cannot receive the response message during debugging, you can check whether the message processing has timed out. In general debug
debugging, the response will not be received after more than 5 seconds. Regarding retry message duplication, every message should retain its idempotent, pushed in xml
the data structure, there are msgid
messages recommended msgid
duplication. If it is an event type message, it is recommended to use it FromUserName + CreateTime
for re-resetting.
5. How to guarantee processing and reply within five seconds
If the server cannot guarantee to process and reply within five seconds, it must make the following reply, so that the WeChat server will not do anything about it and will not initiate a retry (in this case, you can use the customer service message interface for asynchronous Reply), otherwise, a serious error message will appear. See the description below for details:
- 1. Reply directly
success
(recommended method) - 2. Reply to an empty string directly (refers to an empty string with a byte length of 0, not the content of the field in the
XML
structurecontent
is empty)
Once it encounters the server without processing within five seconds and responds to the reply or the developer responds with abnormal data, such as JSON
data, etc.; WeChat will send a system prompt to the user in the official account session “该公众号暂时无法提供服务,请稍后再试”
;
6. How to reply to graphic messages
When replying to multimedia messages with pictures (GIF is not supported), temporary materials need to be uploaded to the WeChat server through the material management interface in advance; you can also upload permanent materials in the material management interface to the WeChat WeChat server, but the temporary materials are stored on the WeChat server The validity period of is only 3 days, and the permanent material is always valid. Since the number of WeChat permanent materials is limited, if your project environment has a large demand for media material files, use permanent materials to upload with caution and use temporary materials; but also It does not matter, the WeChat developer documentation also provides an interface for deleting permanent materials and deleting temporary materials, which can be used reasonably according to the scene.
After uploading temporary or permanent materials through the material management interface, the interface will return a key field called mediaId
. After this is mediaId
returned to us, we need to store it ourselves. When we need to use the multimedia file material, it is passed mediaId
to the interface parameter , the micro-channel will be based on the server mediaId
to find the corresponding source file, and then do the corresponding return processing, such as image info reply, reply graphic information, and so on.
Seven, upload picture materials in advance
Please note : As previously emphasized, when replying to (不支持gif动图)
multimedia messages such as pictures , you need to upload temporary materials to the WeChat server through the material management interface in advance. You can use temporary materials in material management or permanent materials.
Therefore, before we realize the function of passively replying to the message-replying to the graphic message, we need to upload the temporary image material or the permanent image material to the WeChat platform first, and then we first observe the requirements xml格式
and parameter descriptions of the graphic message .
1. Reply to graphic message in xml format
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>1</ArticleCount>
<Articles>
<item>
<Title><![CDATA[title1]]></Title>
<Description><![CDATA[description1]]></Description>
<PicUrl><![CDATA[picurl]]></PicUrl>
<Url><![CDATA[url]]></Url>
</item>
</Articles>
</xml>
2. Description of parameters for replying to graphic messages
parameter | Do you have to | Description |
---|---|---|
ToUserName | Yes | Recipient account (OpenID received) |
FromUserName | Yes | Developer Wechat |
CreateTime | Yes | Message creation time (integer) |
MsgType | Yes | Message type, picture and text are news |
ArticleCount | Yes | The number of graphic messages; when the user sends six types of messages: text, picture, voice, video, graphic, text, and geographic location, the developer can only reply to 1 graphic message; the rest of the scenes can reply up to 8 graphic messages |
Articles | Yes | Picture and text message information, note that if the number of pictures and text exceeds the limit, only the number within the limit will be sent |
Title | Yes | Graphic message title |
Description | Yes | Graphic message description |
PicUrl | Yes | Image links, support JPG, PNG formats, better results for the big picture 360 200 Small chart 200 200 |
Url | Yes | Click the link of the graphic message |
3. Upload permanent image material
/**
* @desc:
* @author: cao_wencao
* @date: 2020-05-21 13:47
*/
@Slf4j
@RestController
@RequestMapping("/wx/material")
public class WxMaterialController {
private static final SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS" );
@Autowired
private WeChatMaterialUtils materialUtils;
/**
* 上传单个图片文件
*/
@PostMapping("/uploadImg")
public ApiResult uploadImg(@RequestParam("imgFile") MultipartFile imgFile) throws IOException {
log.info("multipartFile = " + imgFile);
log.info("ContentType = " + imgFile.getContentType());
log.info("OriginalFilename = " + imgFile.getOriginalFilename());
log.info("Name = " + imgFile.getName());
log.info("Size = " + imgFile.getSize());
String fileExt = imgFile.getOriginalFilename().substring(imgFile.getOriginalFilename().lastIndexOf(".") + 1);
log.info("fileExt = " + fileExt);
WxMpMaterialUploadResult wxMpMaterialUploadResult
= materialUtils.uploadFilesToWeChat("image", fileExt ,imgFile.getName(), imgFile.getInputStream());
if(null == wxMpMaterialUploadResult){
return ApiResult.error("上传图片失败");
}
log.info("wxMpMaterialUploadResult = : " + JSON.toJSONString(wxMpMaterialUploadResult));
return ApiResult.succee(wxMpMaterialUploadResult,"上传图片成功");
}
}
4. PostMan test image upload
4.1 The parameters are as follows
- headers
“key”:“Content-Type”, “value”:“multipart/form-data”
- body
- Response result
{
"code": 200,
"message": "上传图片成功",
"data": {
"mediaId": "1C72rnlYrj7ZqBiRGdKCoUUudPCjA5qMkJZeODvTN9U",
"url": "http://mmbiz.qpic.cn/mmbiz_jpg/DwMlrmia5oVQrbNsb6GJ64xlUtfTXspTcyuV1m6ykgiaGJQYR374WWfGGrgibJOibYc1df7Wyicw4u9f5CV3u7oAzow/0?wx_fmt=jpeg"
}
}
- Access url
Eight, package graphic message Handler
- TextMsgHandler.java
package com.thinkingcao.weixin.handler;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @desc: 文本类型消息处理-TEXT
* @link: XmlMsgType.TEXT
* @author: cao_wencao
* @date: 2020-05-20 15:15
*/
@Component
public class TextMsgHandler extends AbstractHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> map, WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException {
//判断传递过来的消息,类型是否为TEXT
if (wxMessage.getMsgType().equals(WxConsts.XmlMsgType.TEXT)) {
//TODO: 如果需要做微信消息日志存储,可以在这里进行日志存储到数据库,这里省略不写。
}
// 获取微信用户基本信息
WxMpUser userWxInfo = wxMpService.getUserService().userInfo(wxMessage.getFromUser(), "zh_CN");
if (null == userWxInfo){
return null;
}
String content = wxMessage.getContent();
if ("文本".equals(content)){
//下面两种响应方式都可以
//return new TextBuilder().build("您的一互动,泛起了我内心的涟漪。",wxMessage,wxMpService);
return WxMpXmlOutMessage
.TEXT()
.content("您的一互动,就激起了我内心的无限可能")
.fromUser(wxMessage.getToUser())
.toUser(wxMessage.getFromUser())
.build();
}
if ("图片".equals(content)){
return WxMpXmlOutMessage
.IMAGE()
.mediaId("1C72rnlYrj7ZqBiRGdKCoS54AXQwSo4iULd9qRhOC-U")
.fromUser(wxMessage.getToUser())
.toUser(wxMessage.getFromUser())
.build();
}
if ("图文".equals(content)){
List<WxMpXmlOutNewsMessage.Item> articles = new ArrayList<>();
WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item();
item.setDescription("使用Java语言进行开发微信公众号发送图文消息");
item.setPicUrl("http://mmbiz.qpic.cn/mmbiz_jpg/DwMlrmia5oVQrbNsb6GJ64xlUtfTXspTcgAU6Jvbt3uL72LqN3ToB4ibiaWkTZT7SD0IUD56uGiaFRXpI8vBYtYrAQ/0?wx_fmt=jpeg");
item.setTitle("SpringBoot开发微信公众号");
item.setUrl("https://blog.csdn.net/thinkingcao/category_9277860.html");
articles.add(item);
return WxMpXmlOutMessage
.NEWS()
.addArticle(item)
.articles(articles)
.fromUser(wxMessage.getToUser())
.toUser(wxMessage.getFromUser())
.build();
}
return null;
}
}
Nine, test passive response to graphic messages
Enter in the official account dialog box: After the graphic keyword, the background will match the message type MsgType = text through routing, and then find the specific text message processor, that is, TextMsgHandler, and then further match the keyword "graphic", and then Assemble the reply graphic message field and reply the graphic message to the user interactor, so here is a simple sentence. In actual project development, constructing a passive message reply must achieve dynamic content, so the data generated by all fields must be To record through the database table, when constructing the passive message reply, it can be fetched from the database, so that the dynamic passive reply to the user message is realized.
- Background request response console log
2020-06-10 23:51:23.334 DEBUG 4812 --- [nio-8080-exec-3] m.c.w.mp.api.impl.BaseWxMpServiceImpl :
【请求地址】: https://api.weixin.qq.com/cgi-bin/user/info?access_token=34_Gsg49pv1E8sqzyc7DeHUXSVtUQZSxxTXkXp3h_S_MCOXYwIuqqH41B4a6eF3HpokFucpJVjJIPpPvKwQYCXFMWdAJc45Yd8BmEk-PPHWDg_iJ5INbTuWn9m3gQdHQV-zcbtFN2V8-DGDZo6WSHXfAAAWLB
【请求参数】:openid=oGjQdw2EyT7CBNfN84Te6IpmflCM&lang=zh_CN
【响应数据】:{
"subscribe":1,"openid":"oGjQdw2EyT7CBNfN84Te6IpmflCM","nickname":"曹","sex":1,"language":"zh_CN","city":"墨尔本","province":"维多利亚","country":"澳大利亚","headimgurl":"http:\/\/thirdwx.qlogo.cn\/mmopen\/1ZMUBCDTp8ZAsxH99cX3icFXXDSstNaIR1FDpibnmfNPEn1J7Hf9yLXicSHJiciaEgtwgTXRicib9X2mua4bpeEg2sWNics6rXnIKKq7\/132","subscribe_time":1589956861,"remark":"","groupid":0,"tagid_list":[],"subscribe_scene":"ADD_SCENE_QR_CODE","qr_scene":0,"qr_scene_str":""}
2020-06-10 23:51:23.335 DEBUG 4812 --- [nio-8080-exec-3] m.c.weixin.mp.api.WxMpMessageRouter : End session access: async=false, sessionId=oGjQdw2EyT7CBNfN84Te6IpmflCM
2020-06-10 23:51:23.335 DEBUG 4812 --- [pool-1-thread-4] m.c.weixin.mp.api.WxMpMessageRouter : End session access: async=true, sessionId=oGjQdw2EyT7CBNfN84Te6IpmflCM
2020-06-10 23:51:23.336 DEBUG 4812 --- [nio-8080-exec-3] c.t.w.controller.WxPortalController :
组装回复信息:<xml>
<ToUserName><![CDATA[oGjQdw2EyT7CBNfN84Te6IpmflCM]]></ToUserName>
<FromUserName><![CDATA[gh_833ac613acf7]]></FromUserName>
<CreateTime>1591804283</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Articles>
<item>
<Title><![CDATA[SpringBoot开发微信公众号]]></Title>
<Description><![CDATA[使用Java语言进行开发微信公众号发送图文消息]]></Description>
<PicUrl><![CDATA[http://mmbiz.qpic.cn/mmbiz_jpg/DwMlrmia5oVQrbNsb6GJ64xlUtfTXspTcyuV1m6ykgiaGJQYR374WWfGGrgibJOibYc1df7Wyicw4u9f5CV3u7oAzow/0?wx_fmt=jpeg]]></PicUrl>
<Url><![CDATA[https://blog.csdn.net/thinkingcao/category_9277860.html]]></Url>
</item>
</Articles>
<ArticleCount>1</ArticleCount>
</xml>
- Dialog interaction
Ten, source code
Source code: https://github.com/Thinkingcao/SpringBootLearning/tree/master/springboot-wechat