1、公众号后台配置:点击基本配置-修改配置

URL:填写服务端建立的接口地址(接口要能接受get/post请求)

token:随便写

秘钥:自动生成

配好之后,点击提交,微信会往接口发送一条get请求的数据,服务端校验后,把微信发送的数据中的echoStr字段原样返回,微信接收到会提示修改成功。

2、配置服务端接口

/*** 接受微信发送的消息*  @param request 公参*  @return 返回结果*/@SneakyThrows@RequestMapping(value = "/getTencentMsg", method = {RequestMethod.POST, RequestMethod.GET})@ApiIgnorepublic void getTencentMsg(HttpServletRequest request, HttpServletResponse response) {String method = request.getMethod();if(RequestMethodEnum.GET.getDesc().equals(method)){String signature = request.getParameter("signature");String timestamp = request.getParameter("timestamp");String nonce = request.getParameter("nonce");String echoStr = request.getParameter("echostr");String token = "weiyouzz";boolean checkSignature = wxUtils.checkSignature(signature, timestamp, nonce, token);if (checkSignature) {response.getWriter().write(echoStr+"");}}else {//post请求跟消息相关,往下翻到第三点}}//校验微信请求/*** 验证微信签名*/public boolean checkSignature(String signature, String timestamp,String nonce, String token) {// 1.将token、timestamp、nonce三个参数进行字典序排序String[] arr = new String[]{token, timestamp, nonce};Arrays.sort(arr);// 2. 将三个参数字符串拼接成一个字符串进行sha1加密StringBuilder content = new StringBuilder();for (int i = 0; i < arr.length; i++) {content.append(arr[i]);}MessageDigest md = null;String tmpStr = null;try {md = MessageDigest.getInstance("SHA-1");// 将三个参数字符串拼接成一个字符串进行sha1加密byte[] digest = md.digest(content.toString().getBytes());tmpStr = byteToStr(digest);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}content = null;// 3.将sha1加密后的字符串可与signature对比,标识该请求来源于微信return tmpStr != null && tmpStr.equals(signature.toUpperCase());}private static String byteToStr(byte[] byteArray) {StringBuilder strDigest = new StringBuilder();for (int i = 0; i < byteArray.length; i++) {strDigest.append(byteToHexStr(byteArray[i]));}return strDigest.toString();}private static String byteToHexStr(byte mByte) {char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A','B', 'C', 'D', 'E', 'F'};char[] tempArr = new char[2];tempArr[0] = Digit[(mByte >>> 4) & 0X0F];tempArr[1] = Digit[mByte & 0X0F];String s = new String(tempArr);return s;}
//可能用到的包
import java.util.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import lombok.SneakyThrows;
import springfox.documentation.annotations.ApiIgnore;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

RequestMethodEnum枚举自己建或者复制下面的

public enum RequestMethodEnum {/** get*/GET(1,"GET"),/** post*/POST(2,"POST");private final Integer code;private final String desc;RequestMethodEnum(Integer id, String name){this.code = id;this.desc = name;}public Integer getCode() {return code;}public String getDesc() {return desc;}
}

3、获取消息并回应,还是走上面这个接口,但是请求方式是post

        else {// 预先设定返回的 response 类型为 xmltencentAdvertisingService.getMessage(request,response);}
    @Overridepublic void getMessage(HttpServletRequest request, HttpServletResponse response) {try {response.setHeader("Content-type", "application/xml");// 读取参数,解析Xml为mapMap<String, String> map = wxUtils.transferXmlToMap(wxUtils.readRequest(request));JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(map));if(ObjectUtils.isNotEmpty(jsonObject)){String msgType = jsonObject.getString("MsgType");String toUserName = jsonObject.getString("ToUserName");String fromUserName = jsonObject.getString("FromUserName");String createTime = jsonObject.getString("CreateTime");//回复,可以回复表情,蓝色可点击链接文字等String content ;if (TencentMsgTypeConstant.EVENT.equals(msgType)) {//关注自动回复content = "[Party]终于等到你!欢迎你的关注!\n" +"<a href=\"https://www.baidu.com\">百度</a>\n" +"\n" +"<a href=\"https://www.csdn.net\">CSDN</a>\n" +"\n" +"/:rose点击<a href=\"https://www.csdn.net\">【CSDN】</a>看更多优质博客\n" +"/:gift点击<a href=\"https://www.csdn.net\">【CSDN】</a>看更多优质博客";} else {//收到消息自动回复content = "/:sun已经收到您的消息~\n" +">> <a href=\"https://www.csdn.net\">【CSDN】</a>\n" +">> <a href=\"https://www.csdn.net\">【CSDN】</a>\n" +">> <a href=\"https://www.csdn.net\">【CSDN】</a>\n" +">> <a href=\"https://www.csdn.net\">【CSDN】</a>\n" +">> <a href=\"https://www.csdn.net\">【CSDN】</a>";}response.setCharacterEncoding("UTF-8");response.getWriter().write(getXmlReturnMsg(fromUserName,toUserName,System.currentTimeMillis() / 1000,content));}}catch (Exception e){log.info(e.getMessage());}}//工具类public Map transferXmlToMap(String strxml) throws IOException {strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");if (null == strxml || "".equals(strxml)) {return null;}Map m = new HashMap();InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));SAXBuilder builder = new SAXBuilder();Document doc = null;try {doc = builder.build(in);} catch (JDOMException e) {// 统一转化为 IO 异常输出throw new IOException(e.getMessage());}// 解析 DOMElement root = doc.getRootElement();List list = root.getChildren();Iterator it = list.iterator();while (it.hasNext()) {Element e = (Element) it.next();String k = e.getName();String v = "";List children = e.getChildren();if (children.isEmpty()) {v = e.getTextNormalize();} else {v = getChildrenText(children);}m.put(k, v);}//关闭流in.close();return m;}/*** 辅助 transferXmlToMap 方法递归提取子节点数据*/private String getChildrenText(List<Element> children) {StringBuffer sb = new StringBuffer();if (!children.isEmpty()) {Iterator<Element> it = children.iterator();while (it.hasNext()) {Element e = (Element) it.next();String name = e.getName();String value = e.getTextNormalize();List<Element> list = e.getChildren();sb.append("<" + name + ">");if (!list.isEmpty()) {sb.append(getChildrenText(list));}sb.append(value);sb.append("</" + name + ">");}}return sb.toString();}/*** 读取 request body 内容作为字符串** @param request* @return* @throws IOException*/public String readRequest(HttpServletRequest request) throws IOException {InputStream inputStream;StringBuffer sb = new StringBuffer();inputStream = request.getInputStream();String str;BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));while ((str = in.readLine()) != null) {sb.append(str);}in.close();inputStream.close();return sb.toString();}
    /*** 构建普通消息* @param toUser 接收方账号(openId)* @param fromUser 开发者账号* @param createTime 创建时间,整型* @param content 内容* @return 回复消息*/public String getXmlReturnMsg(String toUser,String fromUser,Long createTime,String content) {return "<xml>\n" +"  <ToUserName><![CDATA["+toUser+"]]></ToUserName>\n" +"  <FromUserName><![CDATA["+fromUser+"]]></FromUserName>\n" +"  <CreateTime>"+createTime+"</CreateTime>\n" +"  <MsgType><![CDATA[text]]></MsgType>\n" +"  <Content><![CDATA["+content+"]]></Content>\n" +"</xml>";}

java 对接微信公众号(二)获取关注取关事件/用户回复消息相关推荐

  1. java 对接微信公众号(一)获取token

    1.登录微信公众平台,在基本配置里获取AppId和AppSecret 2.获取token(token获取到存本地,后续API都要带token访问) 需要在基本配置里配置ip白名单才能获取到token ...

  2. JAVA对接微信公众号(服务号、订阅号)实现模板消息推送功能

    最近做了个需求要求对接微信公众号,使用模板进行消息推送,今天抽时间总结一下相关的逻辑. 大概逻辑分为四个步骤: 获取微信调用接口凭证access_token. 获取微信模板列表. 使用模板进行消息推送 ...

  3. 微信公众号PC端批量取关

    随着微信的使用,很多时候我们的微信会无缘无故关注了很多公众号,一个一个取关很麻烦,这款神器就可以帮助你啦!快速取关公众号. 下载点击原文 本文来自:关尓佟博客,原地址:https://guanerto ...

  4. Java 扫描微信公众号二维码,关注并自动登录网站

    场景:用户扫描微信公众号的二维码,关注后自动登录网站,若已关注则直接登录. 逻辑: 1.系统生成带参数(此参数自定义为唯一值)的临时二维码(微信公众平台有提供该接口,可查看一下开发文档): 2.用户使 ...

  5. Java对接微信公众号模板消息推送(架包WxJava)

    内容有点多,请耐心! 最近公司的有这个业务需求,又很凑巧让我来完成: 首先想要对接,先要一个公众号,再就是开发文档了:https://developers.weixin.qq.com/doc/offi ...

  6. 基于Java的微信公众号二次开发视频教程

    课程目录 微信二次开发基础部分.avi 01-18 Java微信二次开发微信验证.wmv 01-19 Java微信二次开发智能机器人.wmv 03-04-java微信二次开发公开课-微信公众号平台.w ...

  7. Java对接微信公众号模板消息推送

    最近公司的有这个业务需求,又很凑巧让我来完成: 首先想要对接,先要一个公众号,再就是开发文档了:https://developers.weixin.qq.com/doc/offiaccount/Get ...

  8. java对接微信公众号发布文章

    前言 在工作中遇到一个需求,需要向微信公众号发布文章,通过查询资料以及查阅微信的开发文档,最终实现. 微信开发文档:https://developers.weixin.qq.com/doc/offia ...

  9. 微信公众号接口之自动回复,根据接收文本回复消息(二)

    根据微信公众号设置的回调地址,设置的文件名字,把当前代码当进去,改成回调地址的文件名,即可完成,具体内容以下有注释. <?php header('content-type:text/html;c ...

  10. 手把手教你使用java对接微信公众号-获取地理位置信息

    公众号需要定位当前用户的地址位置,需要通过签名后返回的数据,前端将参数回调到微信服务器获取地理位置信息,官方文档说明(https://developers.weixin.qq.com/doc/offi ...

最新文章

  1. 预定义变量 - PHP手册笔记
  2. centos 6推荐使用epel源
  3. Types of intraclass correlation coefficience (ICC)
  4. 九度oj 题目1252:回文子串
  5. 关于设计模式--我有话说
  6. c#和WIN32 调用
  7. asp 调用java文件上传_用asp实现文件浏览、上传、下载的程序
  8. python操作redis集群_python 连接管理作redis集群
  9. 如果关闭一个窗体后激活另一个窗体的事件或方法
  10. matlab 课程设计循环码性能分析,matlab课程设计--循环码的性能分析
  11. Twitter开源软件项目列表
  12. Linux中网卡的命名规则
  13. 开篇之作,什么是云原生,云原生技术为什么这么火?
  14. WebRTC教程 - 使用SIPML5
  15. 数据中心设计方案 实例,数据中心网络设计方案
  16. workerman实现聊天室
  17. PE文件加节感染之Win32.Loader.bx.V病毒分析
  18. 华为荣耀启动“二级火箭”战略,加速向线下突进
  19. 【C++】C/C++面试之17道经典编程题目分析
  20. 三、数据需求与数据库设计

热门文章

  1. 怎么样关掉红米note开发者选项
  2. 开始混CSDN了,大器晚成……
  3. Gebru被辞退的背后真相:指出BERT的4大危害,威胁谷歌商业利益
  4. Python实现随机漫步
  5. 关于VISIO2013显示首要事项闪退问题
  6. 阿里技术专家甘盘:浅谈双十一背后的支付宝LDC架构和其CAP分析(含phil补充)
  7. 游戏项目开发的简单流程
  8. 百度脑图 “展开/收起节点“ 按钮隐藏
  9. ROS——发布摄像头节点并编写opencv图像处理节点(python)
  10. 十大推荐提交的安卓市场