1. 程式人生 > >接入微信公眾平臺開發之使用者關注(取消)事件觸發後臺自定義訊息體通知給使用者的實現過程

接入微信公眾平臺開發之使用者關注(取消)事件觸發後臺自定義訊息體通知給使用者的實現過程

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