基于springboot微信公众号开发(微信自动回复)

网友投稿 342 2022-12-22


基于springboot微信公众号开发(微信自动回复)

效果图

1.准备工作

申请微信订阅号(个人只能申请订阅号,而且没什么功能,也无法认证),申请完毕,点击 开发=>基本配置,如下图:

服务器配置需要有 域名 80端口,我猜你没有,这里推荐个实用工具,pagekite,下载链接,

这个工具需要 python2.7以上环境,还有邮箱一个,一个邮箱一个月,邮箱这东西大家懂得,

用pagekite申请完域名,就可以用自己的电脑做订阅号服务器了.

2.服务器代码

创建个springboot工程

pom.xml

UTF-8

UTF-8

1.8

org.springframework.boot

spring-boot-starter-parent

1.5.9.RELEASE

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-thymeleaf

net.sourceforge.nekohtml

nekohtml

1.9.22

    

      dom4j

      dom4j

      1.6.1

    

org.springframework.boot

spring-boot-maven-plugin

入口类

@SpringBootApplication

public class WeChatApplication {

public static void main(String[] args) {

SpringApplication.run(WeChatApplication.class, args);

System.out.println("====启动成功====");

}

}

application.properties,配置server.port=80

Controller,这个是处理微信请求,get方法就是微信公众平台 服务器配置url请求的路径,post是处理用户事件

@RestController

public class WeChatController {

@Autowired

private WeChatService weChatService;

/**

* 处理微信服务器发来的get请求,进行签名的验证

*

* signature 微信端发来的签名

* timestamp 微信端发来的时间戳

* nonce 微信端发来的随机字符串

* echostr 微信端发来的验证字符串

*/

@GetMapping(value = "wechat")

public String validate(@RequestParam(value = "signature") String signature,

@RequestParam(value = "timestamp") String timestamp,

@RequestParam(value = "nonce") String nonce,

@RequestParam(value = "echostr") String echostr) {

return WeChatUtil.checkSignature(signature, timestamp, nonce) ? echostr : null;

}

/**

* 此处是处理微信服务器的消息转发的

*/

@PostMapping(value = "wechat")

public String processMsg(HttpServletRequest request) {

// 调用核心服务类接收处理请求

return weChatService.processRequest(request);

}

}

Service,处理post请求

/**

* 核心服务类

*/

@Service

public class WeChatServiceImpl implements WeChatService{

@Autowired

private FeignUtil feignUtil;

@Autowired

private RedisUtils redisUtils;

public String processRequest(HttpServletRequest request) {

// xml格式的消息数据

String respXml = null;

// 默认返回的文本消息内容

String respContent;

try {

// 调用parseXml方法解析请求消息

Map requestMap = WeChatUtil.parseXml(request);

// 消息类型

String msgType = (String) requestMap.get(WeChatContant.MsgType);

String mes = null;

// 文本消息

if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_TEXT)) {

mes =requestMap.get(WeChatContant.Content).toString();

if(mes!=null&&mes.length()<2){

List items = new ArrayList<>();

ArticleItem item = new ArticleItem();

item.setTitle("照片墙");

item.setDescription("阿狸照片墙");

item.setPicUrl("http://changhaiwx.pagekite.me/photo-wall/a/iali11.jpg");

item.setUrl("http://changhaiwx.pagekite.me/page/photowall");

items.add(item);

item = new ArticleItem();

item.setTitle("哈哈");

item.setDescription("一张照片");

item.setPicUrl("http://changhaiwx.pagekite.me/images/me.jpg");

item.setUrl("http://changhaiwx.pagekite.me/page/index");

items.add(item);

item = new ArticleItem();

item.setTitle("小游戏2048");

item.setDescription("小游戏2048");

item.setPicUrl("http://changhaiwx.pagekite.me/images/2048.jpg");

item.setUrl("http://changhaiwx.pagekite.me/page/game2048");

items.add(item);

item = new ArticleItem();

item.setTitle("百度");

item.setDescription("百度一下");

item.setPicUrl("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1505100912368&di=69c2ba796aa2afd9a4608e213bf695fb&imgtype=0&src=http%3A%2F%2Ftx.haiqq.com%2Fuploads%2Fallimg%2F170510%2F0634355517-9.jpg");

item.setUrl("http://baidu.com");

items.add(item);

respXml = WeChatUtil.sendArticleMsg(requestMap, items);

}else if("我的信息".equals(mes)){

Map userInfo = getUserInfo(requestMap.get(WeChatContant.FromUserName));

System.out.println(userInfo.toString());

String nickname = userInfo.get("nickname");

String city = userInfo.get("city");

String province = userInfo.get("province");

String country = userInfo.get("country");

String headimgurl = userInfo.get("headimgurl");

List items = new ArrayList<>();

ArticleItem item = new ArticleItem();

item.setTitle("你的信息");

item.setDescription("昵称:"+nickname+" 地址:"+country+" "+province+" "+city);

item.setPicUrl(headimgurl);

item.setUrl("http://baidu.com");

items.add(item);

respXml = WeChatUtil.sendArticleMsg(requestMap, items);

}

}

// 图片消息

else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_IMAGE)) {

respContent = "您发送的是图片消息!";

respXml = WeChatUtil.sendTextMsg(requestMap, respContent);

}

// 语音消息

else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_VOICE)) {

respContent = "您发送的是语音消息!";

respXml = WeChatUtil.sendTextMsg(requestMap, respContent);

}

// 视频消息

else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_VIDEO)) {

respContent = "您发送的是视频消息!";

respXml = WeChatUtil.sendTextMsg(requestMap, respContent);

}

// 地理位置消息

else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_LOCATION)) {

respContent = "您发送的是地理位置消息!";

respXml = WeChatUtil.sendTextMsg(requestMap, respContent);

}

// 链接消息

else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_LINK)) {

respContent = "您发送的是链接消息!";

respXml = WeChatUtil.sendTextMsg(requestMap, respContent);

}

// 事件推送

else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_EVENT)) {

// 事件类型

String eventType = (String) requestMap.get(WeChatContant.Event);

// 关注

if (eventType.equals(WeChatContant.EVENT_TYPE_SUBSCRIBE)) {

respContent = "谢谢您的关注!";

respXml = WeChatUtil.sendTextMsg(requestMap, respContent);

}

// 取消关注

else if (eventType.equals(WeChatContant.EVENT_TYPE_UNSUBSCRIBE)) {

// TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复

}

// 扫描带参数二维码

else if (eventType.equals(WeChatContant.EVENT_TYPE_SCAN)) {

// TODO 处理扫描带参数二维码事件

}

// 上报地理位置

else if (eventType.equals(WeChatContant.EVENT_TYPE_LOCATION)) {

// TODO 处理上报地理位置事件

}

// 自定义菜单

else if (eventType.equals(WeChatContant.EVENT_TYPE_CLICK)) {

// TODO 处理菜单点击事件

}

}

mes = mes == null ? "不知道你在干嘛" : mes;

if(respXml == null)

respXml = WeChatUtil.sendTextMsg(requestMap, mes);

System.out.println(respXml);

return respXml;

} catch (Exception e) {

e.printStackTrace();

}

return "";

}

}

微信工具类(只写了回复文本消息,和图文消息,其他的都是大同小异)

package com.wechat.util;

import java.io.InputStream;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

import java.util.ArrayList;

import java.util.Date;

import java.util.HashMap;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;

import org.dom4j.Element;

import org.dom4j.io.SAXReader;

import com.wechat.bean.ArticleItem;

/**

* 请求校验工具类

*

* @author 32950745

*

*/

public class WeChatUtil {

/**

* 验证签名

*

* @param signature

* @param timestamp

* @param nonce

* @return

*/

public static boolean checkSignature(String signature, String timestamp, String nonce) {

String[] arr = new String[] { WeChatContant.TOKEN, timestamp, nonce };

// 将token、timestamp、nonce三个参数进行字典序排序

// Arrays.sort(arr);

sort(arr);

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;

// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信

return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;

}

/**

* 将字节数组转换为十六进制字符串

*

* @param byteArray

* @return

*/

private static String byteToStr(byte[] byteArray) {

String strDigest = "";

for (int i = 0; i < byteArray.length; i++) {

strDigest += byteToHexStr(byteArray[i]);

}

return strDigest;

}

/**

* 将字节转换为十六进制字符串

*

* @param mByte

* @return

*/

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;

}

private static void sort(String a[]) {

for (int i = 0; i < a.length - 1; i++) {

for (int j = i + 1; j < a.length; j++) {

if (a[j].compareTo(a[i]) < 0) {

String temp = a[i];

a[i] = a[j];

a[j] = temp;

}

}

}

}

/**

* 解析微信发来的请求(xml)

*

* @param request

* @return

* @throws Exception

*/

@SuppressWarnings({ "unchecked"})

public static Map parseXml(HttpServletRequest request) throws Exception {

// 将解析结果存储在HashMap中

Map map = new HashMap();

// 从request中取得输入流

InputStream inputStream = request.getInputStream();

// 读取输入流

SAXReader reader = new SAXReader();

Document document = reader.read(inputStream);

// 得到xml根元素

Element root = document.getRootElement();

// 得到根元素的所有子节点

List elementList = root.elements();

// 遍历所有子节点

for (Element e : elementList)

map.put(e.getName(), e.getText());

// 释放资源

inputStream.close();

inputStream = null;

return map;

}

public static String mapToXML(Map map) {

StringBuffer sb = new StringBuffer();

sb.append("");

mapToXML2(map, sb);

sb.append("");

try {

return sb.toString();

} catch (Exception e) {

}

return null;

}

private static void mapToXML2(Map map, StringBuffer sb) {

Set set = map.keySet();

for (Iterator it = set.iterator(); it.hasNext();) {

String key = (String) it.next();

Object value = map.get(key);

if (null == value)

value = "";

if (value.getClass().getName().equals("java.util.ArrayList")) {

ArrayList list = (ArrayList) map.get(key);

sb.append("<" + key + ">");

for (int i = 0; i < list.size(); i++) {

HashMap hm = (HashMap) list.get(i);

mapToXML2(hm, sb);

}

sb.append("" + key + ">");

} else {

if (value instanceof HashMap) {

sb.append("<" + key + ">");

mapToXML2((HashMap) value, sb);

sb.append("" + key + ">");

} else {

sb.append("<" + key + "><![CDATA[" + value + "]]>" + key + ">");

}

}

}

}

/**

* 回复文本消息

* @param requestMap

* @param content

* @return

*/

public static String sendTextMsg(Map requestMap,String content){

Map map=new HashMap();

map.put("ToUserName", requestMap.get(WeChatContant.FromUserName));

map.put("FromUserName", requestMap.get(WeChatContant.ToUserName));

map.put("MsgType", WeChatContant.RESP_MESSAGE_TYPE_TEXT);

map.put("CreateTime", new Date().getTime());

map.put("Content", content);

return mapToXML(map);

}

/**

* 回复图文消息

* @param requestMap

* @param items

* @return

*/

public static String sendArticleMsg(Map requestMap,List items){

if(items == null || items.size()<1){

return "";

}

Map map=new HashMap();

map.put("ToUserName", requestMap.get(WeChatContant.FromUserName));

map.put("FromUserName", requestMap.get(WeChatContant.ToUserName));

map.put("MsgType", "news");

map.put("CreateTime", new Date().getTime());

List> Articles=new ArrayList>();

for(ArticleItem itembean : items){

Map item=new HashMap();

Map itemContent=new HashMap();

itemContent.put("Title", itembean.getTitle());

itemContent.put("Description", itembean.getDescription());

itemContent.put("PicUrl", itembean.getPicUrl());

itemContent.put("Url", itembean.getUrl());

item.put("item",itemContent);

Articles.add(item);

}

map.put("Articles", Articles);

map.put("ArticleCount", Articles.size());

return mapToXML(map);

}

}

微信常量

public class WeChatContant {

//APPID

public static final String appID = "appid";

//appsecret

public static final String appsecret = "appsecret";

// Token

public static final String TOKEN = "zch";

public static final String RESP_MESSAGE_TYPE_TEXT = "text";

public static final Object REQ_MESSAGE_TYPE_TEXT = "text";

public static final Object REQ_MESSAGE_TYPE_IMAGE = "image";

public static final Object REQ_MESSAGE_TYPE_VOICE = "voice";

public static final Object REQ_MESSAGE_TYPE_VIDEO = "video";

public static final Object REQ_MESSAGE_TYPE_LOCATION = "location";

public static final Object REQ_MESSAGE_TYPE_LINK = "link";

public static final Object REQ_MESSAGE_TYPE_EVENT = "event";

public static final Object EVENT_TYPE_SUBSCRIBE = "SUBSCRIBE";

public static final Object EVENT_TYPE_UNSUBSCRIBE = "UNSUBSCRIBE";

public static final Object EVENT_TYPE_SCAN = "SCAN";

public static final Object EVENT_TYPE_LOCATION = "LOCATION";

public static final Object EVENT_TYPE_CLICK = "CLICK";

public static final String FromUserName = "FromUserName";

public static final String ToUserName = "ToUserName";

public static final String MsgType = "MsgType";

public static final String Content = "Content";

public static final String Event = "Event";

}

图文消息实体bean

public class ArticleItem {

private String Title;

private String Description;

private String PicUrl;

private String Url;

public String getTitle() {

return Title;

}

public void setTitle(String title) {

Title = title;

}

public String getDescription() {

return Description;

}

public void setDescription(String description) {

Description = description;

}

public String getPicUrl() {

return PicUrl;

}

public void setPicUrl(String picUrl) {

PicUrl = picUrl;

}

public String getUrl() {

return Url;

}

public void setUrl(String url) {

Url = url;

}

}

好了运行项目,在公众平台配置好url,个人订阅号完成.


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:基于javamelody监控springboot项目过程详解
下一篇:Java方法重载Overload原理及使用解析
相关文章

 发表评论

暂时没有评论,来抢沙发吧~