>  기사  >  위챗 애플릿  >  메시지 획득 및 회신을 위한 Java WeChat 개발 API의 두 번째 단계를 분석합니다.

메시지 획득 및 회신을 위한 Java WeChat 개발 API의 두 번째 단계를 분석합니다.

高洛峰
高洛峰원래의
2017-03-13 13:06:362407검색

이 기사는 주로 Java WeChat 개발 API두 번째 단계는 메시지를 얻고 응답하는 것입니다. 관심 있는 친구는

WeChat 개발 API를 얻고 응답하는 방법을 참조할 수 있습니다. 소식, 아래에서 소개해드리겠습니다

1. 설명
* 위챗 개발문서를 바탕으로 한 예시입니다: http://mp.weixin.qq .com/wiki /home/index.html개발 시연을 위한 최신 버전(2016년 4월 3일 오후 5:34:36).
* 편집 플랫폼: myeclipse10.7+win32+jdk1.7+tomcat7.0
* 서버: Alibaba Cloud Windows Server 2008 64bits
* 플랫폼 요구 사항: servlet주석 방법을 사용하세요. 플랫폼 요구 사항: j2ee6.0+, jdk6.0+, tomcat7.0+
* 데모에서는 API 분석에 더 중점을 둡니다.
* 테스트 설명을 용이하게 하기 위해 각 테스트 케이스는 독립적이며 다른 방법에 의존하지 않습니다. 포장에 대해 많이 생각하지 마십시오.
* 시연은 최대한 API 요구사항에 맞춰 진행되어야 하며, 문서의 사용법을 이해하고 하나의 예시를 통해 추론하는 효과를 얻는 것이 목적입니다.
* 지식 요구사항: 탄탄한 Java 기초, http 네트워크 통신 지식에 대한 이해, javaweb에 대한 충분한 이해, json파싱
* 각 기사 마지막에는 이 부분의 데모 소스 코드가 제공됩니다. 주어지다. API 분석 후 모든 데모 소스코드는 소스코드 패키지 형태로 제공됩니다.
* 현재 시간: 2016년 4월 3일 오후 5:32:57, 이 시간에 따라 달라질 수 있습니다.

2. 원본 문서 - 메시지 관리(요약)
•문서 주소 : http://mp.weixin.qq .com/wiki/17/f298879f8fb29ab98b2f2971d42552fd.html

•메시지 관리
◦ 메시지 수신 - 일반 메시지 수신
◦ 메시지 수신 - 이벤트 수신 푸시
◦ 메시지 보내기 - 수동 답장 메시지
◦ 메시지 보내기 - 수동 답장 중 암호화 및 복호화
◦ 메시지 보내기 - 고객 서비스 메시지
◦ 메시지 보내기 - 그룹 전송 인터페이스
◦ 메시지 보내기 - 템플릿 메시지 인터페이스
◦ 메시지 보내기 - 템플릿 메시지 동작 사양
◦ 공개 계정 자동 회신 설정 받기

3. 문서 이해
• 메시지 수신
◦ 문서에서는 다음과 같이 설명합니다. 일반 WeChat 사용자가 공개 계정에 메시지를 보내면 WeChat 서버는 해당 메시지의 XML 데이터 패키지를 게시합니다. 개발자가 입력한 URL입니다.
◦이해: WeChat 서버는 사용자가 req에 보낸 메시지를 Post 스트림 형식으로 반환합니다. 사용자가 보낸 메시지를 얻으려면 req.getInputStream()을 통해 얻을 수 있습니다. 물론, 문서에서 반환된 메시지의 xml 형식을 기반으로 필요한 구문 분석을 수행할 수 있습니다.

구현:

/*
 * 该部分我们获取用户发送的信息,并且解析成<K,V>的形式进行显示
 */
// 解析用户发送过来的信息
InputStream is = req.getInputStream();// 拿取请求流
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>();
// 解析xml,将获取到的返回结果xml进行解析成我们习惯的文字信息
SAXReader reader = new SAXReader();// 第三方jar:dom4j【百度:saxreader解析xml】
Document document = null;
try {
 document = reader.read(is);
} catch (DocumentException e1) {
 // TODO Auto-generated catch block
 e1.printStackTrace();
}
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements();

// 遍历所有子节点
for (Element e : elementList)
 map.put(e.getName(), e.getText());

// 测试输出
Set<String> keySet = map.keySet();
// 测试输出解析后用户发过来的信息
System.out.println(TAG + ":解析用户发送过来的信息开始");
for (String key : keySet) {
 System.out.println(key + ":" + map.get(key));
}
System.out.println(TAG + ":解析用户发送过来的信息结束");

•메시지 보내기
◦ 문서에서는 다음과 같이 설명합니다. 사용자가 공무원에게 메시지를 보낼 때 계정(또는 누군가) 특정 사용자 작업에 의해 트리거된 이벤트가 푸시되면 POST 요청이 생성됩니다. 개발자는 응답 패키지(Get)에서 특정 XML 구조를 반환하여 메시지에 응답할 수 있습니다. 이제 텍스트가 지원됩니다), 사진, 그래픽, 텍스트, 음성, 비디오, 음악). 엄밀히 말하면 수동 응답 메시지를 보내는 것은 실제로 인터페이스가 아니라 WeChat 서버에서 보낸 메시지에 대한 응답입니다.
◦이해: 사용자가 요청을 보내면 POST 요청이 생성되고 Respone을 통해 해당 메시지에 응답할 수 있습니다. 그러나 응답 내용에는 엄격한 형식 요구 사항이 있습니다. 형식 요구 사항이 충족되는 경우에만 WeChat 서버가 이를 처리하여 사용자에게 반환합니다. 문서의 "메시지 관리" 모듈을 살펴보면 WeChat에 다양한 메시지가 있음을 알 수 있습니다. 각 메시지 유형에는 고유한 특정 형식 요구 사항이 있으며 특정 정보를 사용자에게 정상적으로 반환해야 합니다. 우리는 문서에서 요구하는 형식으로 사용자의 문자 메시지와 그래픽 메시지에 응답하려고 노력합니다. 요점: 문서 요구사항에 따라 필수 매개변수를 구성합니다. 특별 참고 사항: 매개변수는 대소문자를 구분합니다.
◦구현 1-일반 문자 메시지에 대한 응답:

//实例1:发送普通文本消息,请查看文档关于“回复文本消息”的xml格式

// 第一步:按照回复文本信息构造需要的参数
TextMsg textMsg = new TextMsg();
textMsg.setToUserName(map.get("FromUserName"));// 发送和接收信息“User”刚好相反
textMsg.setFromUserName(map.get("ToUserName"));
textMsg.setCreateTime(new Date().getTime());// 消息创建时间 (整型)
textMsg.setMsgType("text");// 文本类型消息
textMsg.setContent("我是服务器回复给用户的信息");

// // 第二步,将构造的信息转化为微信识别的xml格式【百度:xstream bean转xml】
XStream xStream = new XStream();
xStream.alias("xml", textMsg.getClass());
String textMsg2Xml = xStream.toXML(textMsg);
System.out.println(textMsg2Xml);

// // 第三步,发送xml的格式信息给微信服务器,服务器转发给用户
PrintWriter printWriter = resp.getWriter();
printWriter.print(textMsg2Xml);

◦구현 2-그래픽 메시지에 대한 응답:

//实例2,发送图文消息。请查看文档关于“回复图文消息”的xml格式

// 第一步:按照回复图文信息构造需要的参数
List<Article> articles = new ArrayList<Article>();
Article a = new Article();
a.setTitle("我是图片标题");
a.setUrl("www.baidu.com");// 该地址是点击图片跳转后
a.setPicUrl("http://b.hiphotos.baidu.com/image/pic/item/08f790529822720ea5d058ba7ccb0a46f21fab50.jpg");// 该地址是一个有效的图片地址
a.setDescription("我是图片的描述");
articles.add(a);
PicAndTextMsg picAndTextMsg = new PicAndTextMsg();
picAndTextMsg.setToUserName(map.get("FromUserName"));// 发送和接收信息“User”刚好相反
picAndTextMsg.setFromUserName(map.get("ToUserName"));
picAndTextMsg.setCreateTime(new Date().getTime());// 消息创建时间 (整型)
picAndTextMsg.setMsgType("news");// 图文类型消息
picAndTextMsg.setArticleCount(1);
picAndTextMsg.setArticles(articles);
// 第二步,将构造的信息转化为微信识别的xml格式【百度:xstream bean转xml】
XStream xStream = new XStream();
xStream.alias("xml", picAndTextMsg.getClass());
xStream.alias("item", a.getClass());
String picAndTextMsg2Xml = xStream.toXML(picAndTextMsg);
System.out.println(picAndTextMsg2Xml);
// 第三步,发送xml的格式信息给微信服务器,服务器转发给用户
PrintWriter printWriter = resp.getWriter();
printWriter.print(picAndTextMsg2Xml);

이 부분의 모든 작업 소스 코드를 직접 사용할 수 있습니다.
•CoreServlet.java(서버 액세스, 사용자가 보낸 메시지 수신, 일반 문자 메시지에 대한 응답, 그래픽 메시지에 대한 응답 포함. 타사 jar 필요: dom4j, xstream)

package com.gist.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.gist.bean.Article;
import com.gist.bean.PicAndTextMsg;
import com.thoughtworks.xstream.XStream;

/**
 * @author 高远</n> 邮箱:wgyscsf@163.com</n> 博客 http://www.php.cn/;/n>
 *  编写时期 2016-4-3 下午4:34:05
 */
@WebServlet("/CoreServlet")
public class CoreServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;
 String TAG = "CoreServlet";

 /*
 * 第二步:验证服务器地址的有效性 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,
 * GET请求携带四个参数:signature、timestamp、nonce、echostr
 * 开发者通过检验signature对请求进行校验(下面有校验方式)。 若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,
 * 则接入生效, 成为开发者成功,否则接入失败。
 * 
 * 加密/校验流程如下: 1. 将token、timestamp、nonce三个参数进行字典序排序 2.
 * 将三个参数字符串拼接成一个字符串进行sha1加密 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
 */
 /*
 * 字典排序(lexicographical
 * order)是一种对于随机变量形成序列的排序方法。其方法是,按照字母顺序,或者数字小大顺序,由小到大的形成序列。
 */
 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  throws ServletException, IOException {

 // 设置编码
 req.setCharacterEncoding("utf-8");
 resp.setContentType("html/text;charset=utf-8");
 resp.setCharacterEncoding("utf-8");
 // 获取输出流
 PrintWriter printWriter = resp.getWriter();

 // 设置一个全局的token,开发者自己设置。api这样解释:Token可由开发者可以任意填写,
 // 用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
 String token = "wgyscsf";
 // 根据api说明,获取上述四个参数
 String signature = req.getParameter("signature");
 String timestamp = req.getParameter("timestamp");
 String nonce = req.getParameter("nonce");
 String echostr = req.getParameter("echostr");
 // // temp:临时打印,观看返回参数情况
 // System.out.println(TAG + ":signature:" + signature + ",timestamp:"
 // + timestamp + ",nonce:" + nonce + ",echostr:" + echostr);
 // 根据api所说的“加密/校验流程”进行接入。共计三步

 // 第一步:将token、timestamp、nonce三个参数进行字典序排序
 String[] parms = new String[] { token, timestamp, nonce };// 将需要字典序排列的字符串放到数组中
 Arrays.sort(parms);// 按照api要求进行字典序排序
 // 第二步:将三个参数字符串拼接成一个字符串进行sha1加密
 // 拼接字符串
 String parmsString = "";// 注意,此处不能=null。
 for (int i = 0; i < parms.length; i++) {
  parmsString += parms[i];
 }
 // sha1加密
 String mParms = null;// 加密后的结果
 MessageDigest digest = null;
 try {
  digest = java.security.MessageDigest.getInstance("SHA");
 } catch (NoSuchAlgorithmException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
 digest.update(parmsString.getBytes());
 byte messageDigest[] = digest.digest();
 // Create Hex String
 StringBuffer hexString = new StringBuffer();
 // 字节数组转换为 十六进制 数
 for (int i = 0; i < messageDigest.length; i++) {
  String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
  if (shaHex.length() < 2) {
  hexString.append(0);
  }
  hexString.append(shaHex);
 }
 mParms = hexString.toString();// 加密结果

 /*
  * api要求: 若确认此次GET请求来自微信服务器,请原样返回echostr参数内容, 则接入生效, 成为开发者成功,否则接入失败。
  */
 // 第三步: 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信接入成功。
 // System.out.println(TAG + ":" + mParms + "---->" + signature);
 if (mParms.equals(signature)) {
  // System.out.println(TAG + ":" + mParms + "---->" + signature);
  printWriter.write(echostr);
 } else {
  // 接入失败,不用回写
  // System.out.println(TAG + "接入失败");
 }
 }

 /*
 * 查看api文档关于收发消息推送的消息格式基本一致。 如以下格式: <xml>
 * <ToUserName><![CDATA[toUser]]></ToUserName>
 * <FromUserName><![CDATA[fromUser]]></FromUserName>
 * <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[text]]></MsgType>
 * <Content><![CDATA[this is a test]]></Content>
 * <MsgId>1234567890123456</MsgId> </xml> 那么,我们就可以进行统一处理。
 */
 /*
 * 我们先获取输入流,看输入流里面的信息。通过测试打印输出流,我们可以看到每次用户请求,都会收到req请求,请求格式是xml格式,该信息在文档中有说明。
 */
 /*
 * 特别注意,req.getInputStream()只能获取一次,并且只能读取一次。如果想要多次读取,需要另外想办法。为了简单起见,
 * 我们只获取一次req.getInputStream(),不再打印输出流信息。直接打印解析后的信息。
 */
 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
  throws ServletException, IOException {
 // 设置编码
 req.setCharacterEncoding("utf-8");
 resp.setContentType("html/text;charset=utf-8");
 resp.setCharacterEncoding("utf-8");

 /*
  * 该部分我们获取用户发送的信息,并且解析成<K,V>的形式进行显示
  */
 // 解析用户发送过来的信息
 InputStream is = req.getInputStream();// 拿取请求流
 // 将解析结果存储在HashMap中
 Map<String, String> map = new HashMap<String, String>();
 // 解析xml,将获取到的返回结果xml进行解析成我们习惯的文字信息
 SAXReader reader = new SAXReader();// 第三方jar:dom4j【百度:saxreader解析xml】
 Document document = null;
 try {
  document = reader.read(is);
 } catch (DocumentException e1) {
  // TODO Auto-generated catch block
  e1.printStackTrace();
 }
 // 得到xml根元素
 Element root = document.getRootElement();
 // 得到根元素的所有子节点
 List<Element> elementList = root.elements();

 // 遍历所有子节点
 for (Element e : elementList)
  map.put(e.getName(), e.getText());

 // 测试输出
 Set<String> keySet = map.keySet();
 // 测试输出解析后用户发过来的信息
 System.out.println(TAG + ":解析用户发送过来的信息开始");
 for (String key : keySet) {
  System.out.println(key + ":" + map.get(key));
 }
 System.out.println(TAG + ":解析用户发送过来的信息结束");

 /*
  * 该部分我们尝试按照文档的要求格式给用户回复文本信息、图文消息。重点:按照文档要求构造需要的参数。特别注意:参数区分大小写。
  */

 // //实例1:发送普通文本消息,请查看文档关于“回复文本消息”的xml格式
 //
 // // 第一步:按照回复文本信息构造需要的参数
 // TextMsg textMsg = new TextMsg();
 // textMsg.setToUserName(map.get("FromUserName"));// 发送和接收信息“User”刚好相反
 // textMsg.setFromUserName(map.get("ToUserName"));
 // textMsg.setCreateTime(new Date().getTime());// 消息创建时间 (整型)
 // textMsg.setMsgType("text");// 文本类型消息
 // textMsg.setContent("我是服务器回复给用户的信息");
 //
 // // // 第二步,将构造的信息转化为微信识别的xml格式【百度:xstream bean转xml】
 // XStream xStream = new XStream();
 // xStream.alias("xml", textMsg.getClass());
 // String textMsg2Xml = xStream.toXML(textMsg);
 // System.out.println(textMsg2Xml);
 //
 // // // 第三步,发送xml的格式信息给微信服务器,服务器转发给用户
 // PrintWriter printWriter = resp.getWriter();
 // printWriter.print(textMsg2Xml);

 // //实例2,发送图文消息。请查看文档关于“回复图文消息”的xml格式

 // 第一步:按照回复图文信息构造需要的参数
 List<Article> articles = new ArrayList<Article>();
 Article a = new Article();
 a.setTitle("我是图片标题");
 a.setUrl("www.baidu.com");// 该地址是点击图片跳转后
 a.setPicUrl("http://b.hiphotos.baidu.com/image/pic/item/08f790529822720ea5d058ba7ccb0a46f21fab50.jpg");// 该地址是一个有效的图片地址
 a.setDescription("我是图片的描述");
 articles.add(a);
 PicAndTextMsg picAndTextMsg = new PicAndTextMsg();
 picAndTextMsg.setToUserName(map.get("FromUserName"));// 发送和接收信息“User”刚好相反
 picAndTextMsg.setFromUserName(map.get("ToUserName"));
 picAndTextMsg.setCreateTime(new Date().getTime());// 消息创建时间 (整型)
 picAndTextMsg.setMsgType("news");// 图文类型消息
 picAndTextMsg.setArticleCount(1);
 picAndTextMsg.setArticles(articles);
 // 第二步,将构造的信息转化为微信识别的xml格式【百度:xstream bean转xml】
 XStream xStream = new XStream();
 xStream.alias("xml", picAndTextMsg.getClass());
 xStream.alias("item", a.getClass());
 String picAndTextMsg2Xml = xStream.toXML(picAndTextMsg);
 System.out.println(picAndTextMsg2Xml);
 // 第三步,发送xml的格式信息给微信服务器,服务器转发给用户
 PrintWriter printWriter = resp.getWriter();
 printWriter.print(picAndTextMsg2Xml);
 }
}

•TestMsg.java(일반 문자 메시지 Bean)

package com.gist.bean;

/**
 * @author 高远</n> 邮箱:wgyscsf@163.com</n> 博客 http://www.php.cn/;/n>
 *  编写时期 2016-4-4 下午2:09:27
 */
public class TextMsg {
 private String ToUserName;
 private String FromUserName;
 private long CreateTime;
 private String MsgType;

 @Override
 public String toString() {
 return "TextMsg [ToUserName=" + ToUserName + ", FromUserName="
  + FromUserName + ", CreateTime=" + CreateTime + ", MsgType="
  + MsgType + ", Content=" + Content + "]";
 }

 private String Content;

 public TextMsg(String toUserName, String fromUserName, long createTime,
  String msgType, String content) {
 super();
 ToUserName = toUserName;
 FromUserName = fromUserName;
 CreateTime = createTime;
 MsgType = msgType;
 Content = content;
 }

 public TextMsg() {
 super();
 }

 public String getToUserName() {
 return ToUserName;
 }

 public void setToUserName(String toUserName) {
 ToUserName = toUserName;
 }

 public String getFromUserName() {
 return FromUserName;
 }

 public void setFromUserName(String fromUserName) {
 FromUserName = fromUserName;
 }

 public long getCreateTime() {
 return CreateTime;
 }

 public void setCreateTime(long createTime) {
 CreateTime = createTime;
 }

 public String getMsgType() {
 return MsgType;
 }

 public void setMsgType(String msgType) {
 MsgType = msgType;
 }

 public String getContent() {
 return Content;
 }

 public void setContent(String content) {
 Content = content;
 }
}

•Article.java(그림 및 문자 메시지 내부의 기사 Bean)


package com.gist.bean;

/**
 * @author 高远</n> 邮箱:wgyscsf@163.com</n> 博客 http://www.php.cn/;/n>
 *  编写时期 2016-4-4 下午2:47:08
 */
public class Article {
 private String Title;

 @Override
 public String toString() {
 return "item [Title=" + Title + ", Description=" + Description
  + ", PicUrl=" + PicUrl + ", Url=" + Url + "]";
 }

 public String getTitle() {
 return Title;
 }

 public void setTitle(String title) {
 Title = title;
 }

 public String getDescription() {
 return Description;
 }

 public void setDescription(String description) {
 Description = description;
 }

 public String getPicUrl() {
 return PicUrl;
 }

 public void setPicUrl(String picUrl) {
 PicUrl = picUrl;
 }

 public String getUrl() {
 return Url;
 }

 public void setUrl(String url) {
 Url = url;
 }

 private String Description;
 private String PicUrl;
 private String Url;

}

• PicAndTextMsg.java(사진 및 문자 메시지 Bean)


package com.gist.bean;

import java.util.List;

/**
 * @author 高远</n> 邮箱:wgyscsf@163.com</n> 博客 http://www.php.cn/;/n>
 *  编写时期 2016-4-4 下午2:47:08
 */
public class PicAndTextMsg {
 private String ToUserName;
 private String FromUserName;
 private long CreateTime;
 private String MsgType;
 private int ArticleCount;
 private List<Article> Articles;

 @Override
 public String toString() {
 return "PicAndTextMsg [ToUserName=" + ToUserName + ", FromUserName="
  + FromUserName + ", CreateTime=" + CreateTime + ", MsgType="
  + MsgType + ", ArticleCount=" + ArticleCount + ", Articles="
  + Articles + "]";
 }

 public String getToUserName() {
 return ToUserName;
 }

 public void setToUserName(String toUserName) {
 ToUserName = toUserName;
 }

 public String getFromUserName() {
 return FromUserName;
 }

 public void setFromUserName(String fromUserName) {
 FromUserName = fromUserName;
 }

 public long getCreateTime() {
 return CreateTime;
 }

 public void setCreateTime(long createTime) {
 CreateTime = createTime;
 }

 public String getMsgType() {
 return MsgType;
 }

 public void setMsgType(String msgType) {
 MsgType = msgType;
 }

 public int getArticleCount() {
 return ArticleCount;
 }

 public void setArticleCount(int articleCount) {
 ArticleCount = articleCount;
 }

 public List<Article> getArticles() {
 return Articles;
 }

 public void setArticles(List<Article> articles) {
 Articles = articles;
 }

}

위 내용은 메시지 획득 및 회신을 위한 Java WeChat 개발 API의 두 번째 단계를 분석합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.