微信公众号开通开发者之后,需要开发者开发后台代码对接微信公众平台。本篇文章程序猿小编将为大家介绍下微信公众平台的基本对接,包括微信发送到Token验证,接收普通消息,接收事件推送,被动回复用户消息。
成为微信公众号开发者后,我们需要获取几个重要的信息,如下图:
我们需要在我们的代码中配置开发者ID(AppID),开发者密码(AppSecret)以及令牌(Token),后续在开发过程中使用这些配置信息;
如果我们需要调用微信公众平台的接口,则需要在IP白名单中配置我们的服务器的IP地址,若未配置则在调用微信公众平台的接口时候,会报以下错误信息:
{“errcode”:40164,“errmsg”:“invalidip 61.141.254.90, not in whitelist hint: [JNpRaA0073sha6]”}
服务器地址(URL)就是我们后台服务器接收微信发送到Token验证,接收普通消息,接收事件推送的地址,此处要注意的是微信发送到Token验证是用的是Http+GET方法,接收普通消息和接收事件推送用的是Http+POST+XML;所以这个URL需要能同时支持GET和POST方法。
微信发送Token验证形式如下:
http://***/wx/receive?signature=23959cb9a87f0dea51ebc7f49a8ccdc7ae2b1598×tamp=20190619140400&nonce=***&echostr=true
接收普通消息和接收事件推送用消息我们抓包分析如下图所示:
综合以上分析,我们在接收微信公众平台发给我们信息的时候需要同时支持GET和POST方法,以下我们给出Struts2中Action和SpringMVC中Controller的写法。
1、Struts2中Action的写法:
public void receive() throws Exception {
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
//获取http请求的方法
String requestMethod=request.getMethod();
if (!CommonUtil.isEmpty(requestMethod) && requestMethod.equals("GET")) {
String echostr = request.getParameter("echostr");
// 签名校验,判断是否微信发送过来的消息
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
logger.info("token校验时直接返回echostr :"+echostr);
response.getOutputStream().println(echostr);
}
} else {
if (SignUtil.checkSignature(signature, timestamp, nonce)) {//判断是否微信发送过来的消息
// 接收事件及推送消息
String result = wechatService.processRequest(request);
logger.info("事件处理结果result[{}]返回!", result);
response.getOutputStream().println(result);
}
}
}
2、SpringMVC中Controller的写法
@RequestMapping(value = "/receive", method = RequestMethod.GET, produces = "text/plain;charset=UTF-8")
public @ResponseBody
String receiveWeixinMessageGet(HttpServletRequest request)
{
String result = "";
// 微信加密签名
String signature = request.getParameter("signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr");
if (SignUtil.checkSignature(signature, timestamp, nonce))
{
result = echostr;
}
return result;
}
@RequestMapping(value = "/receive", method = RequestMethod.POST, produces = "text/xml;charset=UTF-8")
public @ResponseBody
String receiveWeixinMessagePOST(HttpServletRequest request, HttpServletResponse response)
{
String result = "";
// 将请求、响应的编码均设置为UTF-8(防止中文乱码)
try
{
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
// 接收参数微信加密签名、 时间戳、随机数
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
// 请求校验
if (SignUtil.checkSignature(signature, timestamp, nonce))
{
// 调用核心服务类接收处理请求
result = this.weixinService.processRequest(request);
}
return result;
}
3、接收事件及推送消息
public String processRequest(HttpServletRequest request) {
// xml格式的消息数据
String respXml = null;
// 默认返回的文本消息内容
String respContent = "未知的消息类型!";
try {
// 调用parseXml方法解析请求消息(即读取POST的XML数据并解析)
Map<String, String> requestMap = WechatUtil.parseXml(request);
// 发送方帐号
String fromUserName = requestMap.get("FromUserName");
// 开发者微信号
String toUserName = requestMap.get("ToUserName");
// 消息类型
String msgType = requestMap.get("MsgType");
// 文本消息
if (msgType.equals(WechatUtil.REQ_MESSAGE_TYPE_TEXT)) {
// FIXME 处理文本消息
}
// 图片消息
else if (msgType.equals(WechatUtil.REQ_MESSAGE_TYPE_IMAGE)) {
// FIXME 处理图片消息
}
// 语音消息
else if (msgType.equals(WechatUtil.REQ_MESSAGE_TYPE_VOICE)) {
// FIXME 处理语音消息
}
// 视频消息
else if (msgType.equals(WechatUtil.REQ_MESSAGE_TYPE_VIDEO)) {
// FIXME 处理视频消息
}
// 地理位置消息
else if (msgType.equals(WechatUtil.REQ_MESSAGE_TYPE_LOCATION)) {
// FIXME 处理地理位置消息
}
// 链接消息
else if (msgType.equals(WechatUtil.REQ_MESSAGE_TYPE_LINK)) {
// FIXME 处理地理链接消息
}
// 事件推送
else if (msgType.equals(WechatUtil.REQ_MESSAGE_TYPE_EVENT)) {
// 事件类型
String eventType = requestMap.get("Event");
// 关注
if (eventType.equals(WechatUtil.EVENT_TYPE_SUBSCRIBE)) {
// FIXME 处理关注事件
String eventKey = requestMap.get("EventKey");
// 事件KEY值,qrscene_为前缀,后面为二维码的参数值
if (!CommonUtil.isEmpty(eventKey)) {
// FIXME 扫描带参数二维码事件
}
}
// 取消关注
else if (eventType.equals(WechatUtil.EVENT_TYPE_UNSUBSCRIBE)) {
// FIXME 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复
}
// 扫描带参数二维码
else if (eventType.equals(WechatUtil.EVENT_TYPE_SCAN)) {
// FIXME 处理扫描带参数二维码事件
}
// 上报地理位置
else if (eventType.equals(WechatUtil.EVENT_TYPE_LOCATION)) {
// FIXME 处理上报地理位置事件
}
// 自定义菜单
else if (eventType.equals(WechatUtil.EVENT_TYPE_CLICK)) {
// FIXME 处理菜单点击事件
}
}
} catch (Exception e) {
e.printStackTrace();
}
return respXml;
}
4、回复消息示例
// 回复默认文本消息
TextResp textResp = new TextResp();
textResp.setToUserName(fromUserName);
textResp.setFromUserName(toUserName);
textResp.setCreateTime(new Date().getTime());
textResp.setMsgType(WechatUtil.RESP_MESSAGE_TYPE_TEXT);
// 设置文本消息的内容
respContent = "欢迎进入***公众号!";
textResp.setContent(respContent);
// 将文本消息对象转换成xml
respXml = WechatUtil.beanToXml(textResp);
回复图文消息
NewsResp newsResp = new NewsResp();
newsResp.setToUserName(fromUserName);
newsResp.setFromUserName(toUserName);
newsResp.setCreateTime(new Date().getTime());
newsResp.setMsgType(WechatUtil.RESP_MESSAGE_TYPE_NEWS);
newsResp.setArticleCount(1);
Article article = new Article();
article.setTitle(YspConfig.getNewsTitle());
article.setDescription(YspConfig.getNewsDesp());
article.setUrl(YspConfig.NEWS_URL));
article.setPicUrl(YspConfig.IMAGE_URL);
List<Article> articleList = new ArrayList<Article>();
articleList.add(article);
newsResp.setArticles(articleList);
respXml = WechatUtil.beanToXml(newsResp);
以上为大家介绍了对接微信公众平台的基本,感兴趣的同学可以关注我们的微信公众号发送消息与小编一起交流探讨。另外要详细了解微信公众平台接口的同学可以查看微信公众平台技术文档(https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432)。