我是靠谱客的博主 粗暴冬日,这篇文章主要介绍基于springboot的微信公众号开发,现在分享给大家,希望可以做个参考。

基于springboot的微信公众号开发

    • 导入依赖
    • Controller层
    • service层
    • ServiceImpl
    • 相关工具类

导入依赖

复制代码
1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/dom4j/dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency>

Controller层

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@RestController public class WeChatController { @Autowired private WeChatService weChatService; @ApiOperation("微信服务器签名验证") @GetMapping("/wechat") public String validate(String signature, String timestamp, String nonce, String echostr) { return weChatService.validate(signature, timestamp, nonce, echostr); } @ApiOperation("公众号事件回调") @PostMapping(value = "/wechat",produces = {"application/xml;charset=utf-8"}) public String processMsg(HttpServletRequest request){ return weChatService.doprocessMsg(request); } @ApiOperation("公众号access_token获取") @GetMapping("/getAccessToken") public String getAccessToken(){ return weChatService.getAccessToken(); } @ApiOperation("公众号创建菜单") @GetMapping("/createMenu") public boolean createMenu(){ return weChatService.createMenu(); } }

service层

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public interface WeChatService { //公众号获取access_token String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token"; //公众号获取菜单 String MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token="; //公众号获取微信用户 String USER_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="; /** * 微信服务器签名验证 * @param signature * @param timestamp * @param nonce * @param echostr * @return */ String validate(String signature, String timestamp, String nonce, String echostr); /** * 公众号事件回调 * @param request * @return */ String doprocessMsg(HttpServletRequest request); /** * 公众号,获取access_token * @return */ String getAccessToken(); /** * 创建菜单功能 */ boolean createMenu(); /** * 根据用户的openId获取用户信息 * @param openId * @return */ JSONObject getwxUserInfo(String openId); }

ServiceImpl

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import com.alibaba.fastjson.JSONObject; import com.example.config.TestConfig; import com.example.config.util.RedisUtil; import com.example.wechat.service.WeChatService; import com.example.wechat.util.DequeUtil; import com.example.wechat.util.MessageUtil; import com.example.wechat.util.WxValidateUtil; import com.example.wechat.util.XMLUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map; @Service @Slf4j public class WeChatServiceImpl implements WeChatService { @Autowired private TestConfig config; @Autowired private RestTemplate restTemplate; @Autowired private WxValidateUtil wxValidateUtil; @Autowired private RedisUtil redisUtil; @Override public String validate(String signature, String timestamp, String nonce, String echostr) { log.info("signature:" + signature + ",timestamp:" + timestamp + ",nonce:" + nonce + ",echostr:" + echostr); // 公众号接入要求若校验成功,则原样返回echostr return wxValidateUtil.checkSignature(signature, timestamp, nonce) ? echostr : null; } @Override public String doprocessMsg(HttpServletRequest request) { //解析XML文档,判断消息类型,判断事件类型,实现沟通逻辑 //解析XML文档,转换为Map,可读性更高,获取数据方便 Map<String , String> map = null; try { map = XMLUtil.getMap(request.getInputStream()); } catch (IOException e) { e.printStackTrace(); } //获取消息类型 String msgType = map.get("MsgType"); //获取消息是谁发的,用户的openid String fromUser = map.get("FromUserName"); //发送给谁,我们的公众号的账号 String toUser = map.get("ToUserName"); //要回复的内容 String reply = ""; //如果是事件类型的消息 if (msgType.equals("event")) { //获取事件类型 String event = map.get("Event"); //如果是关注事件 if (event.equals("subscribe")) { reply = "欢迎您关注微租房平台!"; //在这里实现,获取用户信息,并且信息入库 log.info("openid{}",fromUser); try { //放入阻塞队列 DequeUtil.DEQUE.put(fromUser); } catch (InterruptedException e) { log.error("阻塞队列插入报错{}",e); } // redisUtil.hset("微信用户",fromUser,getwxUserInfo(fromUser)); }else if (event.equals("CLICK")) { //如果是点击事件,获取菜单的key值,实现我们自己的业务逻辑 String key = map.get("EventKey"); if (key.equals("get-post")) { reply = "功能正在建设中,请期待..."; } } }else if (msgType.equals("text")) { //用户发送给我们的消息 String content = map.get("Content"); if (content.equals("1")) { reply = "请在官网领取优惠券"; }else if (content.equals("2")) { reply = "在房源详情,可直接联系经纪人"; }else if (content.equals("3")) { reply = "更多帮助,请联系客服电话:8956-531"; }else { reply = "请回复您要解决的问题编号:n" + "1、在哪里可以领取优惠券n" + "2、怎样联系房源的经纪人n" + "3、其他帮助"; } } int createTime = (int) (new Date().getTime() / 1000); return MessageUtil.formatMsg(fromUser , toUser , createTime , "text" , reply); } @Override public String getAccessToken() { HashMap accessToken = restTemplate.getForObject(ACCESS_TOKEN_URL + "?grant_type=client_credential&appid=" + config.getObs().getAppId() + "&secret=" + config.getObs().getAppsecret(), HashMap.class); if (!accessToken.containsKey("access_token")){ log.error("公众号配置参数不正确"); return null; } return (String) accessToken.get("access_token"); } @Override public boolean createMenu() { String paramStr = "{n" + " "button":[n" + " {n" + " "type":"click",n" + " "name":"我的海报",n" + " "key":"get-post"n" + " },n" + " {n" + " "name":"智慧服务",n" + " "sub_button":[n" + " {n" + " "type":"view",n" + " "name":"平台公告",n" + " "url":"https://news.qq.com/"n" + " },n" + " {n" + " "type":"view",n" + " "name":"言情小说",n" + " "url":"https://news.163.com/"n" + " },n" + " {n" + " "type":"view",n" + " "name":"智享搜搜乐",n" + " "url":"https://www.baidu.com/index.php?tn=monline_3_dg"n" + " }]n" + " },n" + " {n" + " "name":"海量房源",n" + " "type":"view",n" + " "url":" http://7r2mmb.natappfree.cc//index.html"n" + " }]n" + "}n"; JSONObject jsonObject = JSONObject.parseObject(paramStr); HashMap menuMap = restTemplate.postForEntity(MENU_URL + getAccessToken(),jsonObject,HashMap.class).getBody(); if ("40018".equals(menuMap.get("errcode").toString())){ log.error("创建菜单失败"); return false; } return true; } @Override public JSONObject getwxUserInfo(String openId){ return restTemplate.getForEntity(USER_URL+getAccessToken()+"&openid="+ openId +"&lang=zh_CN",JSONObject.class).getBody(); } }

相关工具类

XML解析工具类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; public class XMLUtil { /** * 将XML转换成Map * @param inputStream 请求体中的输入流 * @return Map * */ public static Map<String,String> getMap(InputStream inputStream){ //返回的Map Map<String,String> map = new HashMap<>(); //初始化解析器 SAXReader reader = new SAXReader(); //读取XML文档 Document document = null; try { document = reader.read(inputStream); } catch (DocumentException e) { e.printStackTrace(); } //获取XML文档的根节点 Element element = document.getRootElement(); //遍历所有节点,把键和值存入Map List<Element> elementList = element.elements(); for (Element e : elementList) { map.put(e.getName(),e.getText()); } return map; } }

MessageUtil 工具类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/** * 格式化XML消息 */ public class MessageUtil { /** * 格式化消息 * @param toUser 消息接收者 * @param fromUser 消息发送者 * @param createTime 消息创建时间 * @param msgType 消息类型 * @param content 消息内容 * */ public static String formatMsg (String toUser , String fromUser , int createTime , String msgType , String content) { String str = "<xml>n" + " <ToUserName><![CDATA[%s]]></ToUserName>n" + " <FromUserName><![CDATA[%s]]></FromUserName>n" + " <CreateTime>%d</CreateTime>n" + " <MsgType><![CDATA[%s]]></MsgType>n" + " <Content><![CDATA[%s]]></Content>n" + "</xml>n" + "n"; return String.format(str , toUser , fromUser , createTime , msgType , content); } }

WxValidateUtil 工具类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import com.example.config.TestConfig; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; @Slf4j @Component public class WxValidateUtil { @Autowired TestConfig testConfig; /** * 检验signature * * @param signature * @param timestamp * @param nonce * @return */ public boolean checkSignature(String signature, String timestamp, String nonce) { // 1)将token、timestamp、nonce三个参数进行字典序排序 String token = testConfig.getMp().getToken(); String[] str = {token, timestamp, nonce}; Arrays.sort(str); // 2)将三个参数字符串拼接成一个字符串进行sha1加密 StringBuilder sb = new StringBuilder(); for (String s : str) { sb.append(s); } MessageDigest messageDigest = null; String tmpStr = null; try { messageDigest = MessageDigest.getInstance("sha1"); byte[] digest = messageDigest.digest(sb.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { log.error("异常:", e); } // 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信 return signature.toUpperCase().equals(tmpStr); } /** * 将字节数组转换为十六进制字符串 * * @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]; return new String(tempArr); } }

参考文章

最后

以上就是粗暴冬日最近收集整理的关于基于springboot的微信公众号开发的全部内容,更多相关基于springboot内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(74)

评论列表共有 0 条评论

立即
投稿
返回
顶部