一、说明

微信公众平台

https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN

测试平台

https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

本文demo

链接:https://pan.baidu.com/s/1syGGvdCJqcSPnZdJZpMkTA 提取码:y8y5

开发建议使用测试平台,测试平台拥有所有接口权限
微信公众平台个人只能申请订阅号,而且很多接口没有权限,如菜单,网页录授权

二、外网映射工具ngrok

微信接入必须能外网访问,其项目端口必须为80,需要进行路由映射
内网穿透工具 ngrok使用: https://blog.csdn.net/qq_41463655/article/details/92846613

代码写好后启动本地服务,输入内网穿透工具的地址进行接入

我这里使用内网穿透工具是花生壳

微信公众平台在 设置-基本资料 设置服务器配置,启动就ok了,花生壳的域名应该被微信认为是非法连接了,一直提示参数错误,使用 ngrok 工具连接是没有问题的

三、环境搭建

1、创建springboot 项目

2、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>springboot-weixin</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot-weixin</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><!-- web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- commons-lang3 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.4</version></dependency><!-- https://mvnrepository.com/artifact/org.dom4j/dom4j --><dependency><groupId>org.dom4j</groupId><artifactId>dom4j</artifactId><version>2.0.0</version></dependency><!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream --><dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.11.1</version></dependency><!-- httpclient --><dependency><groupId>commons-httpclient</groupId><artifactId>commons-httpclient</artifactId><version>3.1</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency><!-- json--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.30</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

3、XmlUtils

package com.example.springbootweixin.utils;import com.example.springbootweixin.entity.TextMessage;
import com.thoughtworks.xstream.XStream;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class XmlUtils {/*** 解析微信发来的请求(XML)* * @param request* @return Map<String, String>* @throws Exception*/@SuppressWarnings("unchecked")public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {// 将解析结果存储在HashMap中Map<String, String> map = new HashMap<String, String>();// 从request中取得输入流InputStream inputStream = request.getInputStream();// 读取输入流SAXReader reader = new SAXReader();Document document = reader.read(inputStream);// 得到xml根元素Element root = document.getRootElement();// 得到根元素的所有子节点List<Element> elementList = root.elements();// 遍历所有子节点for (Element e : elementList)map.put(e.getName(), e.getText());// 释放资源inputStream.close();inputStream = null;return map;}/*** 文本消息对象转换成xml* * @param textMessage*            文本消息对象* @return xml*/public static String messageToXml(TextMessage textMessage) {xstream.alias("xml", textMessage.getClass());return xstream.toXML(textMessage);}/*** 扩展xstream使其支持CDATA*/private static XStream xstream = new XStream();
}

4、HttpClientUtil

package com.example.springbootweixin.utils;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;public class HttpClientUtil {public static String doGet(String url, Map<String, String> param) {// 创建Httpclient对象CloseableHttpClient httpclient = HttpClients.createDefault();String resultString = "";CloseableHttpResponse response = null;try {// 创建uriURIBuilder builder = new URIBuilder(url);if (param != null) {for (String key : param.keySet()) {builder.addParameter(key, param.get(key));}}URI uri = builder.build();// 创建http GET请求HttpGet httpGet = new HttpGet(uri);// 执行请求response = httpclient.execute(httpGet);// 判断返回状态是否为200if (response.getStatusLine().getStatusCode() == 200) {resultString = EntityUtils.toString(response.getEntity(), "UTF-8");}} catch (Exception e) {e.printStackTrace();} finally {try {if (response != null) {response.close();}httpclient.close();} catch (IOException e) {e.printStackTrace();}}return resultString;}public static String doGet(String url) {return doGet(url, null);}public static String doPost(String url, Map<String, String> param) {// 创建Httpclient对象CloseableHttpClient httpClient = HttpClients.createDefault();CloseableHttpResponse response = null;String resultString = "";try {// 创建Http Post请求HttpPost httpPost = new HttpPost(url);// 创建参数列表if (param != null) {List<NameValuePair> paramList = new ArrayList<>();for (String key : param.keySet()) {paramList.add(new BasicNameValuePair(key, param.get(key)));}// 模拟表单UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);httpPost.setEntity(entity);}// 执行http请求response = httpClient.execute(httpPost);resultString = EntityUtils.toString(response.getEntity(), "utf-8");} catch (Exception e) {e.printStackTrace();} finally {try {response.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return resultString;}public static String doPost(String url) {return doPost(url, null);}public static String doPostJson(String url, String json) {// 创建Httpclient对象CloseableHttpClient httpClient = HttpClients.createDefault();CloseableHttpResponse response = null;String resultString = "";try {// 创建Http Post请求HttpPost httpPost = new HttpPost(url);// 创建请求内容StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);httpPost.setEntity(entity);// 执行http请求response = httpClient.execute(httpPost);resultString = EntityUtils.toString(response.getEntity(), "utf-8");} catch (Exception e) {e.printStackTrace();} finally {try {response.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return resultString;}
}

5、CheckUtil 验签

package com.example.springbootweixin.utils;import java.security.MessageDigest;import java.util.Arrays;public class CheckUtil {public static final String tooken = "123456789"; // 开发者自行定义Tookenpublic static boolean checkSignature(String signature, String timestamp, String nonce) {// 1.定义数组存放tooken,timestamp,nonceString[] 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) {return null;}}}

6、BaseMessage

package com.example.springbootweixin.entity;import lombok.Data;@Data
public class BaseMessage {/*** 开发者微信*/private String ToUserName;/*** 发送方openid*/private String FromUserName;/*** 创建时间*/private long CreateTime;/*** 内容类型*/private String MsgType;
//  /**
//   * 消息id
//   */
//  private long MsgId ;
}

7、TextMessage

package com.example.springbootweixin.entity;import lombok.Data;@Data
public class TextMessage  extends BaseMessage {private String Content;
}

8、微信接入主类 DispatCherServlet

青云客智能聊天机器人API:http://api.qingyunke.com/

package com.example.springbootweixin.controller;import com.alibaba.fastjson.JSONObject;
import com.example.springbootweixin.entity.TextMessage;
import com.example.springbootweixin.utils.CheckUtil;
import com.example.springbootweixin.utils.HttpClientUtil;
import com.example.springbootweixin.utils.XmlUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Map;/*** 微信事件通知*/@RestController
@Slf4j
public class DispatCherServlet {/*** 微信验证** @param signature* @param timestamp* @param nonce* @param echostr* @return*/@RequestMapping(value = "/dispatCherServlet", method = RequestMethod.GET)public String getDispatCherServlet(String signature, String timestamp, String nonce, String echostr) {boolean checkSignature = CheckUtil.checkSignature(signature, timestamp, nonce);if (!checkSignature) {return null;}return echostr;}/*** 功能说明:微信事件通知(用户所有消息都会通过改接口接收)** @param request* @return* @throws Exception*/@RequestMapping(value = "/dispatCherServlet", method = RequestMethod.POST)public void postdispatCherServlet(HttpServletRequest request, HttpServletResponse response) throws Exception {request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");Map<String, String> mapResult = XmlUtils.parseXml(request);if (mapResult == null) {return;}String msgType = mapResult.get("MsgType");PrintWriter out = response.getWriter();if(msgType ==  "text") {//获取用户信息String content = mapResult.get("Content");String toUserName = mapResult.get("ToUserName");String fromUserName = mapResult.get("FromUserName");String textMessage = null;//判断回复if (content.equals("微信公众号")) {textMessage = setTextMessage("我是后台接口自动回复的哦", toUserName, fromUserName);} else {// 调用第三方智能接口(青云客智能聊天机器人API)String resultStr = HttpClientUtil.doGet("http://api.qingyunke.com/api.php?key=free&appid=0&msg=" + content);JSONObject jsonObject = new JSONObject().parseObject(resultStr);Integer integer = jsonObject.getInteger("result");if (integer == null || integer != 0) {textMessage = setTextMessage("亲,系统出错啦!", toUserName, fromUserName);} else {String result = jsonObject.getString("content");textMessage = setTextMessage(result, toUserName, fromUserName);}}log.info("postdispatCherServlet() info:{}", textMessage);out.print(textMessage);}out.close();}// 回复消息封装public String setTextMessage(String content, String toUserName, String fromUserName) {TextMessage textMessage = new TextMessage();textMessage.setCreateTime(System.currentTimeMillis());textMessage.setFromUserName(toUserName);textMessage.setToUserName(fromUserName);textMessage.setContent(content);textMessage.setMsgType("text");String messageToXml = XmlUtils.messageToXml(textMessage);return messageToXml;}
}

9、启动配置好后测试效果如下

别忘了看第二步微信公众号接入当前本地项目

微信公众号一、接入微信并实现机器人自动回复功能相关推荐

  1. wechat-0010,微信公众号,接入微信公众平台

    demo:https://github.com/wenrongyao/wechat-demo 接入准备: 1.有一个能在公网上访问的项目 可以用内网穿透(推荐使用natapp),微信接入必须使用80端 ...

  2. 如何让微信公众号快速接入智能客服机器人?

    工具: 1.一枚公众号. 2.一枚免费的第四范式智能客服机器人. STEP 1:登陆官网 https://www.4paradigm.com/solution/bot,注册一个属于自己的机器人. ST ...

  3. 微信公众号如何接入微信机器人

    微信对话开放平台文档 官方文档 平台简介 微信对话开放平台开放了微信在对话领域积累多年的的智能对话技术,开发者及非开发者可简单.快速地搭建智能对话机器人(智能客服), 并接入公众号.小程序等,为业务赋 ...

  4. 微信公众号之接入微信公众号服务器开发(一)

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 一丶概述 公众号与公众平台 1. 微信账号类型 个人号 公众号 订阅号 服务号 企业号 2. 公众号 微信公众号主要面向名人.政府 ...

  5. 公众号使用微信客户,微信公众号如何接入微信客服

    为什么要写这篇文章? 网上有很多资料都是说的怎么设置微信客服,但是没有说怎么使用,给初次接触者很多困惑,我就在一个很简单的问题上,浪费了一天的时间,为了使大家节约更多的时间所以写了. 微信公众号如何开 ...

  6. 微信公众号简单接入springboot集成weixin4j

    微信公众号简单接入springboot集成weixin4j 内网穿透 登录地址:https://natapp.cn/ 注册用户,购买免费渠道 进行配置端口号(我配置的是8802) 根据网址进行下一步操 ...

  7. 微信公众号HTML5接入腾讯云人脸核身

    微信公众号HTML5接入腾讯云人脸核身 概述 接入流程 原生H5对行业的要求 概述 针对微信公众号接入腾讯云,腾讯云提供了两种方案,一种是通用H5接入,另外一种是通过微信的原生H5来接入,但是一般都是 ...

  8. 网络架构、云平台和微信公众号开发接入--基于嵌入式工程师的视觉

    云与后端相关的技术似乎并不属于嵌入式和物联智能硬件开发工程师的范畴,但是嵌入式开发工程师有必要认识成熟的网络架构和相关的云技术,以拓展自己在系统架构方面的视野.大数据分析是物联网背后的核心价值,物联智 ...

  9. 微信公众号Java接入demo

    微信公众号Java接入demo 前不久买了一台服务,本来是用来当梯子用的,后来买了一个域名搭了一个博客网站,后来不怎么在上面写博客一直闲着,最近申请了一个微信公众号就想着弄点什么玩玩.周末没事就鼓捣了 ...

  10. 微信公众号如何实现视频列表播放视频的功能

    原创文章,2020-1-7,载转请说明来自CSDN 微信公众号如何实现视频列表播放视频的功能 使用场景要求: 在微信公众号中,添加多个视频,且可实现视频列表的连播功能. 要求观看视频时无广告.稳定流畅 ...

最新文章

  1. plsql 为空显示 0 的函数_记住这三个检测函数,彻底清除公式当中的0值
  2. 专访陈天桥:把钱投给甘坐冷板凳的AI研究员
  3. pandas使用replace函数和正则表达式移除dataframe字符串数据列中头部指定模式字符串(Removing leading substring in dataframe)
  4. Unity中制作游戏的快照游戏支持玩家拍快照
  5. 【Python】青少年蓝桥杯_每日一题_11.27_电梯用电量
  6. 超级任天堂游戏模拟器被曝安全漏洞
  7. 使用ajax预加载图片
  8. springBoot JunitTest的使用以及如何在junit启动前加载
  9. 360极速浏览器无法正确getHours
  10. 2018.5.28 PSOC第一枪:基于cypress的蓝牙开发
  11. 进程句柄和进程ID的区别和关系
  12. 从程序员到项目经理(24):慎于问敏于行 - 忠于工作不等于奴性
  13. nts包如何下周 php_【Composer】PHP开发者必须了解!(life)
  14. 51nod 1384
  15. 一个index.html怎么添加备案号,ICP备案号怎么添加到自己网页底部?
  16. 网易的java微专业_网易微专业Java高级架构师
  17. android *#06#_现在在Android#20中
  18. 【吴恩达深度学习】——NLP和Word Embedding
  19. Vue项目原本原本http请求变成了https
  20. 【threejs效果:模型炸开】以钢铁侠obj模型为例

热门文章

  1. globalmapper将高程数据转换模型导入3dmax
  2. vue监听字符串长度_vue中的计算属性和侦听器
  3. 经典的数据库查询语句大全
  4. tar: Cannot utime: Operation not permitted
  5. 小红书微服务框架及治理等云原生业务架构演进案例
  6. win11如何投屏到电视
  7. mac Hadoop安装
  8. Python网络爬虫之Python基本命令
  9. dellR720服务器设置光盘引导流程安装cenos7
  10. Windows网络基础