微信公众号开发 (2) 消息处理
一、前言
微信公众号开发 (1) 微信接入认证成为开发者
本文将实现
- 接收消息
- 回复消息
二、消息接收
消息接收POST
和微信认证GET
是同一个接口(开发者填写的URL)
@Slf4j
@RestController
@RequestMapping("/api/weixin/index")
@Api(tags = "微信 - 接口")
public class IndexController extends BaseController {/*** 解析请求消息,post请求*/@PostMappingpublic void msgProcess(HttpServletRequest request, HttpServletResponse response) throws Exception {// 获取请求的字节流ServletInputStream inputStream = request.getInputStream();// 转换为字符流, 得到缓冲流InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);BufferedReader reader = new BufferedReader(inputStreamReader);String content = null;// 读取消息内容while ((content = reader.readLine()) != null) {System.out.println(content);}}}
接收到的文本消息
格式如下
其它消息格式可查看微信开放文档:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
<xml><ToUserName><![CDATA[gh_683c79d81f78]]></ToUserName><FromUserName><![CDATA[Wy5wvH9zSaQZSZcV7wZE18D]]></FromUserName><CreateTime>1578996487</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[测试]]></Content><MsgId>22605792697428179</MsgId>
</xml>
参数 | 描述 |
---|---|
ToUserName | 开发者微信号 |
FromUserName | 发送方帐号(一个OpenID) |
CreateTime | 消息创建时间 (整型) |
MsgType | 消息类型,文本为text |
Content | 文本消息内容 |
MsgId | 消息id,64位整型 |
三、消息处理
当用户发送消息给公众号时(或某些特定的用户操作引发的事件推送时),会产生一个POST请求,开发者可以在响应包(Get)中返回特定XML结构,来对该消息进行响应(现支持回复文本
、图片
、图文
、语音
、视频
、音乐
)。
温馨小提示:这里的消息封装可根据微信开放文档中给出的消息格式自行封装,完整代码可参考文末给出的源码哦~
1、封装消息类型枚举类
① 请求消息类型
public enum EnumRequestMessageType {// 请求消息类型TEXT("text", "文本"),IMAGE("image", "图片"),VOICE("voice", "语音"),VIDEO("video", "视频"),SHORTVIDEO("shortvideo", "小视频"),LOCATION("location", "地理位置"),LINK("link", "链接"),// 事件推送EVENT("event", "推送");
}
② 事件推送类型
public enum EnumEventMessageType {SUBSCRIBE("subscribe", "订阅"),UNSUBSCRIBE("unsubscribe", "取消订阅"),CLICK("CLICK", "自定义菜单点击事件"),SCAN("SCAN", "用户已关注时的事件推送");
}
③ 响应消息类型
public enum EnumResponseMessageType {TEXT("text", "文本"),IMAGE("image", "图片"),VOICE("voice", "语音"),VIDEO("video", "视频"),MUSIC("music", "音乐"),NEWS("news", "图文");
}
2、封装请求消息
① 请求消息基类
@Data
@ApiModel(description = "请求消息-基类")
public class BaseMessageDTO {@ApiModelProperty(value = "开发者微信号")private String ToUserName;@ApiModelProperty(value = "发送方帐号(一个OpenID)")private String FromUserName;@ApiModelProperty(value = "消息创建时间 (整型)")private long CreateTime;@ApiModelProperty(value = "消息id,64位整型")private long MsgId;}
② 事件推送
@Data
@ApiModel(description = "事件推送")
public class EventMessageDTO extends BaseMessageDTO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumRequestMessageType.EVENT.getType();@ApiModelProperty(value = "文本消息内容")private String Event;}
③ 图片消息
@Data
@ApiModel(description = "图片消息")
public class ImageMessageDTO extends BaseMessageDTO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumRequestMessageType.IMAGE.getType();@ApiModelProperty(value = "图片链接(由系统生成)")private String PicUrl;@ApiModelProperty(value = "图片消息媒体id,可以调用获取临时素材接口拉取数据")private String MediaId;}
④ 链接消息
@Data
@ApiModel(description = "链接消息")
public class LinkMessageDTO extends BaseMessageDTO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumRequestMessageType.LINK.getType();@ApiModelProperty(value = "消息标题")private String Title;@ApiModelProperty(value = "消息描述")private String Description;@ApiModelProperty(value = "消息链接")private String Url;}
⑤ 地理位置消息
@Data
@ApiModel(description = "地理位置消息")
public class LocationMessageDTO extends BaseMessageDTO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumRequestMessageType.LOCATION.getType();@ApiModelProperty(value = "地理位置维度")private String Location_X;@ApiModelProperty(value = "地理位置经度")private String Location_Y;@ApiModelProperty(value = "地图缩放大小")private String Scale;@ApiModelProperty(value = "地理位置信息")private String Label;}
⑥ 小视频消息
@Data
@ApiModel(description = "小视频消息")
public class ShortVideoMessageDTO extends BaseMessageDTO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumRequestMessageType.SHORTVIDEO.getType();@ApiModelProperty(value = "视频消息媒体id,可以调用获取临时素材接口拉取数据")private String MediaId;@ApiModelProperty(value = "视频消息缩略图的媒体id,可以调用获取临时素材接口拉取数据")private String ThumbMediaId;}
⑦ 文本消息
@Data
@ApiModel(description = "文本消息")
public class TextMessageDTO extends BaseMessageDTO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumRequestMessageType.TEXT.getType();@ApiModelProperty(value = "文本消息内容")private String Content;}
⑧ 视频消息
@Data
@ApiModel(description = "视频消息")
public class VideoMessageDTO extends BaseMessageDTO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumRequestMessageType.VIDEO.getType();@ApiModelProperty(value = "视频消息媒体id,可以调用获取临时素材接口拉取数据")private String MediaId;@ApiModelProperty(value = "视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据")private String ThumbMediaId;}
⑨ 语音消息
@Data
@ApiModel(description = "语音消息")
public class VoiceMessageDTO extends BaseMessageDTO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumRequestMessageType.VOICE.getType();@ApiModelProperty(value = "语音消息媒体id,可以调用获取临时素材接口拉取数据")private String MediaId;@ApiModelProperty(value = "语音格式,如amr,speex等")private String Format;/*** 请注意,开通语音识别后,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,* 增加一个Recognition字段(注:由于客户端缓存,开发者开启或者关闭语音识别功能,对新关注者立刻生效,对已关注用户需要24小时生效。开发者可以重新关注此帐号进行测试)*/@ApiModelProperty(value = "语音识别结果,UTF8编码")private String Recognition;}
3、封装响应消息
① 响应消息基类
@Data
@ApiModel(description = "响应消息-基类")
public class BaseMessageVO {@ApiModelProperty(value = "接收方帐号(收到的OpenID)")private String ToUserName;@ApiModelProperty(value = "开发者微信号")private String FromUserName;@ApiModelProperty(value = "消息创建时间 (整型)")private long CreateTime;@ApiModelProperty(value = "位0x0001被标志时,星标刚收到的消息")private int FuncFlag = 0;}
② 图片消息
@Data
@ApiModel(description = "图片消息")
public class ImageMessageVO extends BaseMessageVO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumResponseMessageType.IMAGE.getType();@ApiModelProperty(value = "图片")private Image Image;@Data@AllArgsConstructor@ApiModel(description = "图片消息中Image类的定义")public static class Image {@ApiModelProperty(value = "通过素材管理中的接口上传多媒体文件,得到的id")private String MediaId;}}
③ 音乐消息
@Data
@ApiModel(description = "音乐消息")
public class MusicMessageVO extends BaseMessageVO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumResponseMessageType.MUSIC.getType();@ApiModelProperty(value = "音乐")private Music Music;@Data@AllArgsConstructor@ApiModel(description = "音乐消息中Music类的定义")public static class Music {@ApiModelProperty(value = "音乐标题")private String Title;@ApiModelProperty(value = "音乐描述")private String Description;@ApiModelProperty(value = "音乐链接")private String MusicUrl;@ApiModelProperty(value = "高质量音乐链接,WIFI环境优先使用该链接播放音乐")private String HQMusicUrl;@ApiModelProperty(value = "缩略图的媒体id,通过素材管理中的接口上传多媒体文件,得到的id")private String ThumbMediaId;}}
④ 图文消息
@Data
@ApiModel(description = "图文消息")
public class NewsMessageVO extends BaseMessageVO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumResponseMessageType.NEWS.getType();@ApiModelProperty(value = "图文消息个数;当用户发送文本、图片、视频、图文、地理位置这五种消息时,开发者只能回复1条图文消息;其余场景最多可回复8条图文消息")private int ArticleCount = 0;@ApiModelProperty(value = "图文消息信息,注意,如果图文数超过限制,则将只发限制内的条数")private List<Article> Articles;@Data@ApiModel(description = "图文消息中Article类的定义")public static class Article {@ApiModelProperty(value = "图文消息标题")private String Title;@ApiModelProperty(value = "图文消息描述")private String Description = "";@ApiModelProperty(value = "图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200")private String PicUrl = "";@ApiModelProperty(value = "点击图文消息跳转链接")private String Url = "";}public void addArticle(Article article) {if (Articles == null) {Articles = Lists.newLinkedList();}Articles.add(article);ArticleCount++;}}
⑤ 文本消息
@Data
@ApiModel(description = "文本消息")
public class TextMessageVO extends BaseMessageVO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumResponseMessageType.TEXT.getType();@ApiModelProperty(value = "回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)")private String Content;}
⑥ 视频消息
@Data
@ApiModel(description = "视频消息")
public class VideoMessageVO extends BaseMessageVO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumResponseMessageType.VIDEO.getType();@ApiModelProperty(value = "视频")private Video Video;@Data@AllArgsConstructor@ApiModel(description = "视频消息中Voice类的定义")public static class Video {@ApiModelProperty(value = "通过素材管理中的接口上传多媒体文件,得到的id")private String MediaId;@ApiModelProperty(value = "视频消息的标题")private String Title;@ApiModelProperty(value = "视频消息的描述")private String Description;}}
⑦ 语音消息
@Data
@ApiModel(description = "语音消息")
public class VoiceMessageVO extends BaseMessageVO {@ApiModelProperty(value = "消息类型", hidden = true)private String MsgType = EnumResponseMessageType.VOICE.getType();@ApiModelProperty(value = "语音")private Voice Voice;@Data@AllArgsConstructor@ApiModel(description = "语音消息中Voice类的定义")public static class Voice {@ApiModelProperty(value = "通过素材管理中的接口上传多媒体文件,得到的id")private String MediaId;}}
4、消息处理工具类
① pom.xml
中引入所需依赖
<!-- dom4j: 解析微信发来的请求(XML) -->
<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<dependency><groupId>org.dom4j</groupId><artifactId>dom4j</artifactId><version>2.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jaxen/jaxen -->
<dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1.6</version>
</dependency><!-- xstream:将响应消息转换成xml返回 -->
<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
<dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.11.1</version>
</dependency>
② 工具类
- 解析微信发来的请求(xml)
- 将响应消息的Java对象转换成xml
public class MessageUtil {/*** 解析微信发来的请求(XML)** @param request* @return* @throws Exception*/@SuppressWarnings("unchecked")public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {// 将解析结果存储在HashMap中Map<String, String> map = new HashMap<>(10);// 从request中取得输入流InputStream inputStream = request.getInputStream();// 读取输入流SAXReader reader = new SAXReader();Document document = reader.read(inputStream);// 得到xml根元素Element root = document.getRootElement();// 得到根元素的所有子节点List<Element> elementList = root.elements();// 遍历所有子节点for (Element e : elementList) {map.put(e.getName(), e.getText());}// 释放资源inputStream.close();inputStream = null;return map;}/*** 文本消息对象转换成xml** @param textMessageVO 文本消息对象 XStream是一个Java对象和XML相互转换的工具* @return xml*/public static String textMessageToXml(TextMessageVO textMessageVO) {xstream.alias("xml", textMessageVO.getClass());return xstream.toXML(textMessageVO);}/*** 图片消息对象转换成xml** @param imageMessageVO 图片消息对象* @return xml*/public static String imageMessageToXml(ImageMessageVO imageMessageVO) {xstream.alias("xml", imageMessageVO.getClass());return xstream.toXML(imageMessageVO);}/*** 语音消息对象转换成xml** @param voiceMessageVO 语音消息对象* @return xml*/public static String voiceMessageToXml(VoiceMessageVO voiceMessageVO) {xstream.alias("xml", voiceMessageVO.getClass());return xstream.toXML(voiceMessageVO);}/*** 视频消息对象转换成xml** @param videoMessageVO 视频消息对象* @return xml*/public static String videoMessageToXml(VideoMessageVO videoMessageVO) {xstream.alias("xml", videoMessageVO.getClass());return xstream.toXML(videoMessageVO);}/*** 音乐消息对象转换成xml** @param musicMessage 音乐消息对象* @return xml*/public static String musicMessageToXml(MusicMessageVO musicMessage) {xstream.alias("xml", musicMessage.getClass());return xstream.toXML(musicMessage);}/*** 图文消息对象转换成xml** @param newsMessage 图文消息对象* @return xml*/public static String newsMessageToXml(NewsMessageVO newsMessage) {xstream.alias("xml", newsMessage.getClass());xstream.alias("item", NewsMessageVO.Article.class);return xstream.toXML(newsMessage);}/*** 扩展xstream,使其支持CDATA块*/private static XStream xstream = new XStream(new XppDriver() {@Overridepublic HierarchicalStreamWriter createWriter(Writer out) {return new PrettyPrintWriter(out) {// 对所有xml节点的转换都增加CDATA标记boolean cdata = true;@Override@SuppressWarnings("unchecked")public void startNode(String name, Class clazz) {super.startNode(name, clazz);}@Overrideprotected void writeText(QuickWriter writer, String text) {if (cdata) {writer.write("<![CDATA[");writer.write(text);writer.write("]]>");} else {writer.write(text);}}};}});}
四、回复消息
1、回复文本消息
@PostMapping
public void msgProcess(HttpServletRequest request, HttpServletResponse response) throws Exception {// 将请求、响应的编码均设置为UTF-8(防止中文乱码)request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");// 调用核心业务类接收消息、处理消息String respMessage = msgService.processRequest(request);// 响应消息PrintWriter out = response.getWriter();out.print(respMessage);out.close();}
其中的processRequest
消息处理方法逻辑如下
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class MsgServiceImpl implements IMsgService {@Overridepublic String processRequest(HttpServletRequest request) {String respMessage = null;try {// xml请求解析Map<String, String> requestMap = MessageUtil.parseXml(request);// 发送方帐号(open_id)String fromUserName = requestMap.get("FromUserName");// 公众帐号String toUserName = requestMap.get("ToUserName");// 消息类型String msgType = requestMap.get("MsgType");// 回复文本消息TextMessageVO textMessage = new TextMessageVO();textMessage.setToUserName(fromUserName);textMessage.setFromUserName(toUserName);textMessage.setCreateTime(System.currentTimeMillis());textMessage.setMsgType(EnumResponseMessageType.TEXT.getType());// 默认返回的文本消息内容String respContent = "请求处理异常,请稍候重试!";// 事件推送if (EnumRequestMessageType.getEnum(msgType) == EnumRequestMessageType.EVENT) {// 事件类型String eventType = requestMap.get("Event");switch (EnumEventMessageType.getEnum(eventType)) {// 订阅case SUBSCRIBE:respContent = "亲,感谢您的关注!";break;// 取消订阅case UNSUBSCRIBE:// TODO 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息break;// 自定义菜单点击事件case CLICK:// TODO 自定义菜单权没有开放,暂不处理该类消息break;default:break;}} else {respContent = EnumRequestMessageType.getEnum(msgType).getTypeValue();}textMessage.setContent(respContent);respMessage = MessageUtil.textMessageToXml(textMessage);} catch (Exception e) {e.printStackTrace();}return respMessage;}}
测试
2、 原样返回消息内容
原样返回消息内容,可调用IMsgService
中的processRequestReturnSameMsg
方法
public String processRequestReturnSameMsg(HttpServletRequest request) {String respMessage = null;try {// xml请求解析Map<String, String> requestMap = MessageUtil.parseXml(request);// 发送方帐号(open_id)String fromUserName = requestMap.get("FromUserName");// 公众帐号String toUserName = requestMap.get("ToUserName");// 消息类型String msgType = requestMap.get("MsgType");// 回复消息BaseMessageVO baseMessageVO = new BaseMessageVO();baseMessageVO.setToUserName(fromUserName);baseMessageVO.setFromUserName(toUserName);baseMessageVO.setCreateTime(System.currentTimeMillis());switch (EnumRequestMessageType.getEnum(msgType)) {// 文本消息case TEXT:TextMessageVO textMessageVO = BeanUtil.copyProperties(baseMessageVO, TextMessageVO.class);textMessageVO.setContent(requestMap.get("Content"));respMessage = MessageUtil.textMessageToXml(textMessageVO);break;// 图片消息case IMAGE:ImageMessageVO imageMessageVO = BeanUtil.copyProperties(baseMessageVO, ImageMessageVO.class);ImageMessageVO.Image image = new ImageMessageVO.Image(requestMap.get("MediaId"));imageMessageVO.setImage(image);respMessage = MessageUtil.imageMessageToXml(imageMessageVO);break;// 语音消息case VOICE:VoiceMessageVO voiceMessageVO = BeanUtil.copyProperties(baseMessageVO, VoiceMessageVO.class);VoiceMessageVO.Voice voice = new VoiceMessageVO.Voice(requestMap.get("MediaId"));voiceMessageVO.setVoice(voice);respMessage = MessageUtil.voiceMessageToXml(voiceMessageVO);break;// 事件推送case EVENT:// 事件类型String eventType = requestMap.get("Event");switch (EnumEventMessageType.getEnum(eventType)) {// 订阅case SUBSCRIBE:NewsMessageVO newsMessage = BeanUtil.copyProperties(baseMessageVO, NewsMessageVO.class);NewsMessageVO.Article article = new NewsMessageVO.Article();article.setTitle("感谢您的关注,这是一条图文消息!");article.setDescription("mysql转oracle笔记");article.setPicUrl("https://mmbiz.qpic.cn/mmbiz_png/iaUVVC0premhqE0TrtLzM6ABMIKKjnu81hraZvXia52byYMqADCyqXKwbs2wJ6jiadWc7MypLKL4EC5mUzXZKH2Rg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1");article.setUrl("https://mp.weixin.qq.com/s?__biz=Mzg2NzEwMjc3Ng==&mid=2247483813&idx=1&sn=7a18081426d014ddccd203d33011f526&chksm=ce41f8f2f93671e4fc5d93292360fd24da4cf1434415befc37f25be2d40780b4a485653861d8&mpshare=1&scene=1&srcid=&sharer_sharetime=1579140222251&sharer_shareid=936076bf8d5bee83e89fd7e769b5c6db&key=c62bc26d01d4cb91d588b8abdeaca0fbba6d713fbc52e3b4c4a9f0377e231e0fe6b4ce07f287f509e37cefa17a0346475f12d85e21bcdbb8e953d0685018a874fbd80005417e94836ad9b0ff7559b334&ascene=1&uin=MTg4MzA0MzMxNA%3D%3D&devicetype=Windows+7&version=62070158&lang=zh_CN&exportkey=AYq%2FJJZv5hRr7YLluyVInZk%3D&pass_ticket=vCPgwidZSOs1xBfcd5SrzkCdVlApSWF7Xc%2BOzjYf8GlJ9%2BLQco9XYzTHe9yWHqc1");newsMessage.addArticle(article);respMessage = MessageUtil.newsMessageToXml(newsMessage);break;// 取消订阅case UNSUBSCRIBE:// TODO 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息break;// 自定义菜单点击事件case CLICK:// TODO 自定义菜单权没有开放,暂不处理该类消息break;default:break;}break;default:break;}} catch (Exception e) {e.printStackTrace();}return respMessage;
}
测试
就这样一个简单的接受消息
与回复消息
就完成了,关于消息处理我们可以根据微信提供的官方文档去学习即可~
本文案例demo源码
https://gitee.com/zhengqingya/java-workspace
微信公众号开发 (2) 消息处理相关推荐
- 微信公众号开发 (3) 菜单处理
一.前言 微信公众号开发 (1) 微信接入认证成为开发者 微信公众号开发 (2) 消息处理 本文将实现 根据AppID和AppSecret获取access_token 自定义菜单(创建菜单.查询菜单. ...
- 实例:用C#.NET手把手教你做微信公众号开发(2)--普通消息处理之文本
上一篇文章我们完成了自己的web服务器与微信公众号服务器的对接,本篇开始处理微信用户和服务器之间的互动交流.一个用户与公众号之间,无外乎用户向公众号发送信息.点击公众号里的菜单和链接,或者公众号向用户 ...
- C#微信公众号开发系列教程二(新手接入指南)
此系列前面已经更新了两篇博文了,都是微信开发的前期准备工作,现在切入正题,本篇讲解新手接入的步骤与方法,大神可直接跳过,也欢迎大神吐槽. 微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教 ...
- 微信公众号自动回复html,[.NET] 简单接入微信公众号开发:实现自动回复
简单接入微信公众号开发:实现自动回复 一.前提 先申请微信公众号的授权,找到或配置几个关键的信息(开发者ID.开发者密码.IP白名单.令牌和消息加解密密钥等). 二.基本配置信息解读 开发者ID:固定 ...
- 手把手教你如何微信公众号开发
最近的话,发现微信开发其实也有很多挺有意思的地方,比如最近很火的一款游戏"跳一跳",也让我如此着迷..但是,今天我所要讲的并不是对于小程序的开发,而是要说一下,关于微信开发的另外一 ...
- 微信公众号开发 - 事件处理和回复消息
微信公众号开发文章目录 1.微信公众号开发 - 环境搭建 2.微信公众号开发 - 配置表设计以及接入公众号接口开发 3.微信公众号开发 - token获取(保证同一时间段内只请求一次) 4.微信公众号 ...
- 微信公众号开发-----实现模板、图文、文本、音乐、图片推送
本篇文章实现模板.图文.文本.音乐.图片推送,前提是已经搭建了微信开发环境.读完本文后,实现的主要效果如下 在测试账号中配置模板 登录测试公众号/正式公众号(认证后的服务号),测试公众号:模板消息接口 ...
- 实例:用C#.NET手把手教你做微信公众号开发(4)--获取普通access_token、jsapi的方法;用MediaId获取微信服务器图片
一.access_token概念 这里在后续几篇处理不同的普通消息文章前插播一个适用于整个微信公众号开发的公共类QinMingWeixinContainer,用于获取普通access_token和js ...
- 如何接入微信公众号开发?底层原理是什么?
要接入微信公众号开发,您需要完成以下几个步骤: 注册微信公众平台账号:首先,您需要在微信公众平台上注册一个账号,并创建一个公众号.在注册过程中,您需要提供相关的身份信息和认证材料,以便微信审核和认证您 ...
最新文章
- Linux Shell 脚本知识点
- 堆溢出DWORD SHOOT原理
- java控制台计算数字_java从控制台接收一个数字
- CorrTracker解读
- AdaBoost算法详解与python实现
- java json 修改字段_JSON文件-Java:编辑/更新字段值
- mysql 查看锁_别吵吵,分布式锁也是锁
- jquery获取和设置属性_jQuery获取属性,设置属性,删除属性
- ipv6文件服务器,在IPV6网络如何创建FTP服务器
- 复制文件并重命名到新的文件夹
- libcef-案例展示-将cef浏览器嵌入到mfc中作为子窗口运行
- VC++ MFC实现的优秀的开源项目
- 数据挖掘思维和实战20 Apriori 与 FP-Growth:不得不再说一遍啤酒与尿布的故事
- 小霸王其乐无穷~FC红白机游戏600合集(支持mac 12.x系统)
- 我的世界基岩JAVA附魔_我的世界1.2.5版本,基岩版的可以100级附魔吗,就是
- 神经网络基础之激活函数
- 机器学习 (十五) 关联分析之Apriori算法
- J2EE重要的技术架构图
- 无线安全[测试标准]
- 算法1—线性规划和非线性规划
热门文章
- Ubuntu安装显卡驱动,配置conda环境,安装pytorch
- mysql没有柔体约束吗_小学科学课标与教法研究-中国大学mooc-试题题目及答案
- 使用计算机时什么是死机,细说电脑死机是什么原因
- 本地的mqttbroker
- Linux搭建SMB服务
- mysql query cache 大小_MySQL查詢緩存:限制為128 MB的最大緩存大小?
- java异步调用外部接口
- ToneSpotVoice 效果器 简单功能讲解
- JavaWeb-过滤器Filter学习(四)敏感词过滤实例
- 17:00面试,17:04就出来了 ,问的实在是太...