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

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 }

    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 }

    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

原文地址:https://www.cnblogs.com/g177w/p/10053121.html

时间: 2025-01-14 08:04:11

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

接入微信公众平台开发

第一步:填写服务器配置 URL是开发者用来接收微信消息和事件的接口URL.Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性).EncodingAESKey由开发者手动填写或随机生成,将用作消息体加解密密钥. 第二步:验证服务器地址的有效性 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带四个参数: 参数 描述 signature 微信加密签名,signature结合了开发者填写的token参

20160170002 微信公众平台开发接入指南

参考地址: http://mp.weixin.qq.com/wiki/17/2d4265491f12608cd170a95559800f2d.html 接入指南 目录 1 概述 2 第一步:填写服务器配置 3 第二步:验证服务器地址的有效性 4 第三步:依据接口文档实现业务逻辑 概述 接入微信公众平台开发,开发者需要按照如下步骤完成: 1.填写服务器配置 2.验证服务器地址的有效性 3.依据接口文档实现业务逻辑 下面详细介绍这3个步骤. 第一步:填写服务器配置 登录微信公众平台官网后,在公众平台

微信公众平台开发(106) 网页获取用户地理位置

关键字:微信公众平台 JSSDK 获取地理位置接口 网页获取用户地理位置 getLocation作者:方倍工作室 原文:http://www.cnblogs.com/txw1958/p/weixin-web-location.html 在这篇微信公众平台开发教程中,我们将介绍如何在网页中获取用户的地理位置信息. 本文分为以下二个部分: 生成JS-SDK权限验证签名 使用地理位置接口获取坐标 一.微信JS-SDK 1. 获得Access Token access token的获得方法在前面有介绍,

Spring Boot 2.X 微信公众平台开发之接入

声明 : 本系列纯属自己为了学习而编写,均已测试号为例,如果不正之处,恳请指正,谢谢! 接入微信公众平台开发,开发者需要按照如下步骤完成: 1.填写服务器配置 由于只是接入,只需要一个Controller的方法路径 和 定义一个token,可以写在配置文件里 2.验证服务器地址的有效性 /** * FileName: CoreController * Author: Phil * Date: 8/1/2018 15:52 * Description: 接入微信并处理消息事件 * History:

Java微信公众平台开发(一)--接入微信公众平台

转自:http://www.cuiyongzhi.com/post/38.html (一)接入流程解析 在我们的开发过程中无论如何最好的参考工具当然是我们的官方文档了:http://mp.weixin.qq.com/wiki/8/f9a0b8382e0b77d87b3bcc1ce6fbc104.html 通过文档我们可以看出其中接入微信公众平台开发,开发者需要按照如下步骤完成: 填写服务器配置 验证服务器地址的有效性 依据接口文档实现业务逻辑 按照上面的逻辑可能是填写服务器配置信息是在第一步,但

第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理

温馨提示: 这篇文章是依赖前几篇的文章的. 第一篇:微信公众平台开发实战之了解微信公众平台基础知识以及资料准备 第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发 第三篇 :微信公众平台开发实战之请求消息,响应消息以及事件消息类的封装 首先,我们看看原来写的dopost方法: /** * 处理微信服务器发来的消息 */ public void doPost(HttpServletRequest request, HttpServletResponse response) thr

微信公众平台开发(89) 高级群发接口

在这篇微信公众平台高级接口开发教程中,我们将介绍如何开发高级群发接口功能. 本文分为以下四个部分: 准备群发内容 选择群发对象 执行群发 接收群发结果 一.准备群发内容 群发内容可以是文本.图片.语音.视频.图文.群发文本只需要文本内容,其他内容需要获得相应的media_id. 1. 文本内容 文本内容就是一段文字,比如:"微信公众平台开发最佳实践" 2. 图片.语音.视频 要求如下: ? 图片(image): 128K,支持JPG格式 ? 语音(voice):256K,播放长度不超过

微信公众平台开发(101) 神经猫

一.神经猫 近日,微信朋友圈被一款名为“围住神经病猫”的小游戏刷屏.这只露着屁股.腰身细长的白猫,在手机屏幕中贱贱地扭动腰肢,一副欠扁的模样.这是一个类似五子棋的小游戏,不同的是,围堵的对象变成了一只“神经病猫”.当用户围堵住这只猫时,会出现一个分数值,显示你击败的全国人数比. 源文件下载地址:http://pan.baidu.com/s/1hqnAxIc 和微信公众平台开发(100) 2048游戏 一样,上传到服务器中,得到url地址,然后在图片消息中引用就行了 二.一些修改 修改分享到朋友圈

微信公众平台开发教程--方培工作室,PHP语言版本

准备工作 微信公众平台的注册 介绍如何注册一个微信公众账号. 入门教程 微信公众平台开发入门教程 内容:1.申请SAE作为服务器; 2.启用开发模式; 3.微信公众平台PHP SDK; 4.接收发送消息类型解析; 5.微信公众平台开发模式原理; 6.快速开发天气预报功能. 入门教程是下面所有教程的基础. 基础接口 微信公众平台开发(2) 天气预报 介绍了使用中国天气网气象数据,实现微信上的天气预报功能. 微信公众平台开发(3) 中英翻译 介绍了使用有道翻译的接口,在微信公众平台上,开发中英互译的