接入微信公众平台开发之用户关注(取消)事件触发后台自定义消息体通知给用户的实现过程

1.需求:用户关注公众号后回复给用户一个字符串,字符串不能重复使用即如果a用户关注公众号后商户后台回复给用户字符串str1后,b用户关注就是其他字符串,且a用户取消关注再次关注不回复消息体

2.实现过程:

  ①首先配置服务器url并开启,再次过程中需要微信后台与商户后台进行通信,所以,微信后台会发送请求,商户平台自定义接口回复相关内容即可完成通信。

接入微信公众平台开发之用户关注(取消)事件触发后台自定义消息体通知给用户的实现过程

    ②原理图:

接入微信公众平台开发之用户关注(取消)事件触发后台自定义消息体通知给用户的实现过程

  ③代码实现:

    a.pcodecontroller:定义的一个接口类,用来处理微信服务器发送的请求

接入微信公众平台开发之用户关注(取消)事件触发后台自定义消息体通知给用户的实现过程
  1 package com.java.zxf.controller;
  2 
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.io.OutputStream;
  6 import java.io.PrintWriter;
  7 import java.io.UnsupportedEncodingException;
  8 import java.util.HashMap;
  9 import java.util.List;
 10 import java.util.Map;
 11 import javax.servlet.ServletInputStream;
 12 import javax.servlet.ServletOutputStream;
 13 import javax.servlet.http.HttpServletRequest;
 14 import javax.servlet.http.HttpServletResponse;
 15 import org.apache.log4j.Logger;
 16 import org.dom4j.Document;
 17 import org.dom4j.Element;
 18 import org.dom4j.io.SAXReader;
 19 import org.springframework.beans.factory.annotation.Autowired;
 20 import org.springframework.stereotype.Controller;
 21 import org.springframework.web.bind.annotation.RequestMapping;
 22 import org.springframework.web.bind.annotation.ResponseBody;
 23 import weixin.popular.bean.xmlmessage.XMLMessage;
 24 import weixin.popular.bean.xmlmessage.XMLTextMessage;
 25 import weixin.popular.support.ExpireKey;
 26 import weixin.popular.support.expirekey.DefaultExpireKey;
 27 import com.easytouch.util.MyCheck;
 28 import com.java.zxf.dao.Pcodedao;
 29 import com.java.zxf.domain.pcode;
 30 
 31 @Controller
 32 public class PcodeController {
 33 
 34     @Autowired
 35     private Pcodedao pcodedao;
 36     private Logger log = Logger.getLogger(getClass());
 37     
 38     @RequestMapping("/getbyid")
 39     @ResponseBody
 40     public Map<String, Object> getbyid(HttpServletRequest request,int id){
 41         pcode code = pcodedao.getcodebyid(id);
 42         Map<String, Object> map = new HashMap<String, Object>();
 43         map.put("code", code);
 44         return map;
 45     }
 46     
 47     //重复通知过滤
 48     private static ExpireKey expireKey = new DefaultExpireKey();
 49 
 50 
 51     //微信推送事件 url
 52     @RequestMapping("/openwx/getticket")
 53     public void getTicket(HttpServletRequest request, HttpServletResponse response)
 54             throws Exception {
 55         ServletInputStream inputStream = request.getInputStream();
 56         ServletOutputStream outputStream = response.getOutputStream(); String signature = request.getParameter("signature");
 57         String timestamp = request.getParameter("timestamp");
 58         String nonce = request.getParameter("nonce");
 59         String echostr = request.getParameter("echostr");
 60 
 61         //首次请求申请验证,返回echostr
 62         if(echostr!=null){
 63             outputStreamWrite(outputStream,echostr);
 64             return;
 65         }
 66 
 67         //验证请求签名
 68         if(!MyCheck.checkSignature(signature, timestamp, nonce)){
 69             System.out.println("The request signature is invalid");
 70             return;
 71         }
 72 
 73         boolean isreturn= false;
 74         //loger.info("1.收到微信服务器消息");
 75         Map<String, String> wxdata=parseXml(request);
 76         if(wxdata.get("MsgType")!=null){
 77             if("event".equals(wxdata.get("MsgType"))){
 78                 //loger.info("2.1解析消息内容为:事件推送");
 79                 if( "subscribe".equals(wxdata.get("Event"))){
 80                     //loger.info("2.2用户第一次关注 返回true哦");
 81                     isreturn=true;
 82                 }
 83             }
 84         }
 85 
 86         if(isreturn == true){
 87             String openid = wxdata.get("FromUserName");
 88             String tosend = "抱歉,提货码已用完";
 89             String key = wxdata.get("FromUserName")+ "__"
 90                     + wxdata.get("ToUserName")+ "__"
 91                     + wxdata.get("MsgId") + "__"
 92                     + wxdata.get("CreateTime");
 93             if(expireKey.exists(key)){
 94                 //重复通知不作处理
 95                 //loger.info("3.1  重复通知了");
 96                 return;
 97             }else{
 98                 //loger.info("3.1  第一次通知");
 99                  //转换XML
100                 //loger.info("3.0 进入回复 转换对象:"+key);
101                 pcode temp = pcodedao.getbyopenid(openid);
102                 if (temp==null){
103                     List<pcode> pcodelist = pcodedao.getAllcode();
104                     try{
105                         pcode code = pcodelist.get(0);
106                         tosend = "您的提货码为:"+code.getPickupcode();
107                         int flag = pcodedao.update(code.getId(),openid);
108                         if(flag==1){
109                             System.out.println("更新成功,取货码已使用");
110                         }else{
111                             log.error("更新用户openid失败,取货码未能使用");
112                         }
113                     }catch(Exception e){
114                         System.out.println("取货码已经用完");
115                         log.info("取货码已经用完");
116                     }
117                   //loger.info("3.2  回复你好");
118                     //创建回复
119                     XMLMessage xmlTextMessage = new XMLTextMessage(
120                             wxdata.get("FromUserName"),
121                             wxdata.get("ToUserName"),
122                             tosend);
123                     expireKey.add(key);
124                     //回复
125                     xmlTextMessage.outputStreamWrite(outputStream);
126                     return;
127                 }
128                 }
129         }
130         //loger.info("3.2  回复空");
131         outputStreamWrite(outputStream,"");
132     }
133 
134     /**
135      * 数据流输出
136      * @param outputStream
137      * @param text
138      * @return
139      */
140     private boolean outputStreamWrite(OutputStream outputStream, String text){
141         try {
142             outputStream.write(text.getBytes("utf-8"));
143         } catch (UnsupportedEncodingException e) {
144             // TODO Auto-generated catch block
145             e.printStackTrace();
146             return false;
147         } catch (IOException e) {
148             // TODO Auto-generated catch block
149             e.printStackTrace();
150             return false;
151         }
152         return true;
153     }
154 
155     /**
156      * dom4j 解析 xml 转换为 map
157      * @param request
158      * @return
159      * @throws Exception
160      */
161     public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
162         // 将解析结果存储在HashMap中
163         Map<String, String> map = new HashMap<String, String>();
164         // 从request中取得输入流
165         InputStream inputStream = request.getInputStream();
166         // 读取输入流
167         SAXReader reader = new SAXReader();
168         Document document = reader.read(inputStream);
169         // 得到xml根元素
170         Element root = document.getRootElement();
171         // 得到根元素的所有子节点
172         List<Element> elementList = root.elements();
173 
174         // 遍历所有子节点
175         for (Element e : elementList)
176             map.put(e.getName(), e.getText());
177 
178         // 释放资源
179         inputStream.close();
180         inputStream = null;
181         return map;
182     }
183 
184     /**
185      * 回复微信服务器"文本消息"
186      * @param response
187      * @param returnvaleue
188      */
189     public void output(HttpServletResponse response, String returnvaleue) {
190         try {
191             PrintWriter pw = response.getWriter();
192             pw.write(returnvaleue);
193             pw.flush();
194         } catch (IOException e) {
195             e.printStackTrace();
196         }
197     }
198 }
View Code

    b.pcodedao:商户后台应用-数据层;定义的读写数据的类

接入微信公众平台开发之用户关注(取消)事件触发后台自定义消息体通知给用户的实现过程
 1 package com.java.zxf.dao;
 2 
 3 import java.util.List;
 4 import org.apache.ibatis.annotations.Param;
 5 import org.apache.ibatis.annotations.Select;
 6 import org.apache.ibatis.annotations.Update;
 7 import org.springframework.stereotype.Repository;
 8 
 9 import com.java.zxf.domain.pcode;
10 @Repository
11 public interface Pcodedao {
12     @Select("select * from pcode where id=#{id}")
13     public pcode getcodebyid(int id);
14     
15     @Select("select * from pcode where openid is null or openid=‘‘")
16     public List<pcode> getAllcode();
17     
18     @Select("select * from pcode where openid=#{openid}")
19     public pcode getbyopenid(String openid);
20     
21     @Update("update pcode set openid=#{openid} where id=#{id}")
22     public int update(@Param(value="id")int id,@Param(value="openid")String openid);
23 }
View Code

    c.pom.xml中添加的依赖包

		<dependency>
		    <groupId>dom4j</groupId>
		    <artifactId>dom4j</artifactId>
		    <version>1.6.1</version>
		</dependency>
		<dependency>
		  <groupId>com.github.liyiorg</groupId>
		  <artifactId>weixin-popular</artifactId>
		  <version>2.8.24</version>
		</dependency>

  三.总结:微信公众平台提供了包括关注动作,被动回复消息在内的一系列动作,具体见如下链接:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140454

接入微信公众平台开发之用户关注(取消)事件触发后台自定义消息体通知给用户的实现过程

上一篇:如何做一个自己的开源聊天项目?(仿微信)


下一篇:Java单体应用 - 架构模式 - 03.设计模式-19.备忘录模式