技术开发文档:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432
前面我们处理的知识text文本消息的处理,但是接受的消息类型并不是只有这一种,
型以及对应的事件关键字:
1、可接收消息类型:
文本消息——text,语音消息——voice,图片消息——image,
视频消息——video,链接消息——link,位置消息——location,
消息视频消息——shortvideo,
2、支持的事件推送——event
关注——subscribe,取消关注——unsubscribe,上传地理位置——location
菜单点击——点击菜单获取消息时触发click/点击菜单跳转链接时触发view
扫描带参数二维码——未关注时触发subscribe/已关注时触发scan
那我们可以清楚的看到,微信可接收的消息类型以及可触发的事件类型有很多种,而每种类型都对应着详细的XML包,在微信公众平台开发文档中有详细解析,此处不做赘述,详情可参考开发文档内容:
根据消息的类型不同,我们可以自定义一个实体类来封装(在前面的MessageUtils)
public static final String MESSAGE_TEXT = "text";
public static final String MESSAGE_IMAGE = "image";
public static final String MESSAGE_VOICE = "voice";
public static final String MESSAGE_VIDEO = "video";
public static final String MESSAGE_SHORTVIDEO = "shortvideo";
public static final String MESSAGE_LINK = "link";
public static final String MESSAGE_LOCATION = "location";
public static final String MESSAGE_EVENT = "event";
public static final String MESSAGE_SUBSCRIBE = "subscribe";
public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe";
public static final String MESSAGE_CLICK = "CLICK";
public static final String MESSAGE_VIEW = "VIEW";
public static final String MESSAGE_SCAN = "SCAN";
撰写拼接主菜单方法&初始化消息方法
//关注初始化消息内容
public static String menuText(){
StringBuffer b=new StringBuffer();
b.append("欢饮来到我的微信公众号,请选择\n\n");
b.append("1、我很帅。\n\n");
b.append("2、我贼鸡儿帅。\n\n");
b.append("回复、主菜单。\n\n");
return b.toString();
}
public static String initText(String toUserName,String fromUserName,String content){
Message message=new Message();
message.setToUserName(fromUserName);
message.setFromUserName(toUserName);
message.setMsgType(MESSAGE_TEXT);
message.setContent(content);
message.setCreateTime(new Date().getTime());
return objectToXml(message);
}
Servlet事件处理
}else if (MsgType.equalsIgnoreCase(MessgaeUtils.MESSAGE_EVENT)){
//这里处理事件如关注、取消关注、点击菜单等多种功能
String eventType=map.get("Event");
//订阅事件
if (eventType.equalsIgnoreCase(MessgaeUtils.MESSAGE_SUBSCRIBE)){
str= MessgaeUtils.initText(ToUserName,FromUserName,MessgaeUtils.menuText());
}
url和token如下:
关键字回复:
if (MsgType.equalsIgnoreCase(MessgaeUtils.MESSAGE_TEXT)){
;
//用户发来1
if ("1".equalsIgnoreCase(Content)){
//微信公众号回复
str=MessgaeUtils.initText(ToUserName,FromUserName,"哦");
}else if ("2".equalsIgnoreCase(Content)){
str=MessgaeUtils.initText(ToUserName,FromUserName,"哦哦哦");
}
}
代码如下:
pom.xml:
<dependencies>
<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<!--创建Servlet-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<!--//<scope>provided</scope>-->
</dependency>
</dependencies>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<servlet>
<servlet-name>bb</servlet-name>
<servlet-class>yiche.com.servlet.WeiXinServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>bb</servlet-name>
<url-pattern>/ok.do</url-pattern>
</servlet-mapping>
</web-app>
Servlet
public class WeiXinServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
String str = null;
//将request请求,传到Message工具类的转换方法中,返回接收到的Map对象
try {
Map<String, String> map = MessgaeUtils.xmlToMap(request);
//从集合中,获取XML各个节点的内容
String ToUserName = map.get("ToUserName");
String FromUserName = map.get("FromUserName");
String CreateTime = map.get("CreateTime");
String MsgType = map.get("MsgType");
String Content = map.get("Content");
String MsgId = map.get("MsgId");
//这里处理文本消息
if (MsgType.equalsIgnoreCase(MessgaeUtils.MESSAGE_TEXT)){
;
//用户发来1
if ("1".equalsIgnoreCase(Content)){
//微信公众号回复
str=MessgaeUtils.initText(ToUserName,FromUserName,"哦");
}else if ("2".equalsIgnoreCase(Content)){
str=MessgaeUtils.initText(ToUserName,FromUserName,"哦哦哦");
}
}else if (MsgType.equalsIgnoreCase(MessgaeUtils.MESSAGE_EVENT)){
//这里处理事件如关注、取消关注、点击菜单等多种功能
String eventType=map.get("Event");
//订阅事件
if (eventType.equalsIgnoreCase(MessgaeUtils.MESSAGE_SUBSCRIBE)){
str= MessgaeUtils.initText(ToUserName,FromUserName,MessgaeUtils.menuText());
}
}
}catch (Exception e){
e.printStackTrace();
}
out.print(str);
out.close();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
System.out.println(request.getMethod().toString());
while (request.getAttributeNames().hasMoreElements()){
System.out.println("1");
request.getAttributeNames().nextElement();
}
// 微信加密签名
String signature = request.getParameter("signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串 由于我使用的是申请的测试账号,并没有随机字符串随意这里的ech是null
String ech = request.getParameter("echostr");
PrintWriter out = response.getWriter();
if (CheckUtil.checkSignature(signature,timestamp,nonce))
System.out.println("校验成功");
out.print(ech);
}
}
文本消息实体类
public class Message {
private String ToUserName;
private String FromUserName;
private Long CreateTime;
private String MsgType;
private String Content;
private String MsgId;
}
MessgaeUtils
public class MessgaeUtils {
public static final String MESSAGE_TEXT = "text";
public static final String MESSAGE_IMAGE = "image";
public static final String MESSAGE_VOICE = "voice";
public static final String MESSAGE_VIDEO = "video";
public static final String MESSAGE_SHORTVIDEO = "shortvideo";
public static final String MESSAGE_LINK = "link";
public static final String MESSAGE_LOCATION = "location";
public static final String MESSAGE_EVENT = "event";
public static final String MESSAGE_SUBSCRIBE = "subscribe";
public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe";
public static final String MESSAGE_CLICK = "CLICK";
public static final String MESSAGE_VIEW = "VIEW";
public static final String MESSAGE_SCAN = "SCAN";
//关注初始化消息内容
public static String menuText(){
StringBuffer b=new StringBuffer();
b.append("欢饮来到我的微信公众号,请选择\n\n");
b.append("1、我很帅。\n\n");
b.append("2、我贼鸡儿帅。\n\n");
b.append("回复、主菜单。\n\n");
return b.toString();
}
public static String initText(String toUserName,String fromUserName,String content){
Message message=new Message();
message.setToUserName(fromUserName);
message.setFromUserName(toUserName);
message.setMsgType(MESSAGE_TEXT);
message.setContent(content);
message.setCreateTime(new Date().getTime());
return objectToXml(message);
}
/*将xml格式转化为map*/
public static Map<String,String> xmlToMap(HttpServletRequest request) throws Exception{
Map<String,String> map=new HashMap<>();
SAXReader reader=new SAXReader();
InputStream inputStream=request.getInputStream();
Document doc=reader.read(inputStream);
Element root=doc.getRootElement();//得到根节点
List<Element> list=root.elements();//根节点下的所有的节点
for(Element e:list){
map.put(e.getName(),e.getText());
}
inputStream.close();
return map;
}
/*将我们的消息内容转变为xml*/
public static String objectToXml(Message message){
XStream xStream=new XStream();
//xml根节点替换成<xml> 默认是Message的包名
xStream.alias("xml", message.getClass());
return xStream.toXML(message);
}
}
CheckUtil
public class CheckUtil {
public static final String tooken = "jkjkjkhk"; //开发者自行定义Tooken
//signatrue微信公众平台传过来的的经过加密的签名
public static boolean checkSignature(String signature, String timestamp, String nonce) {
//1.定义数组存放tooken,timestamp,nonce
String[] arr = {tooken, timestamp, nonce};
//2.对数组进行排序
Arrays.sort(arr);
//3.生成字符串
StringBuffer sb = new StringBuffer();
for (String s : arr) {
sb.append(s);
}
//4.sha1加密,网上均有现成代码
String temp = getSha1(sb.toString());
//5.将加密后的字符串,与微信传来的加密签名比较,返回结果
return temp.equals(signature);
}
public static String getSha1(String str){
if(str==null||str.length()==0){
return null;
}
char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9',
'a','b','c','d','e','f'};
try {
MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
mdTemp.update(str.getBytes("UTF-8"));
byte[] md = mdTemp.digest();
int j = md.length;
char buf[] = new char[j*2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
buf[k++] = hexDigits[byte0 & 0xf];
}
return new String(buf);
} catch (Exception e) {
// TODO: handle exception
return null;
}
}
}