上传微信公众号
commit
3a39e06292
|
@ -0,0 +1,38 @@
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
|
@ -0,0 +1,8 @@
|
||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="GitToolBoxBlameSettings">
|
||||||
|
<option name="version" value="2" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="MaterialThemeProjectNewConfig">
|
||||||
|
<option name="metadata">
|
||||||
|
<MTProjectMetadataState>
|
||||||
|
<option name="migrated" value="true" />
|
||||||
|
<option name="pristineConfig" value="false" />
|
||||||
|
<option name="userId" value="543722b8:191dbece87f:-7ffe" />
|
||||||
|
</MTProjectMetadataState>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="MavenProjectsManager">
|
||||||
|
<option name="originalFiles">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,68 @@
|
||||||
|
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.muyu</groupId>
|
||||||
|
<artifactId>cloud-common</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.muyu</groupId>
|
||||||
|
<artifactId>cloud-modules</artifactId>
|
||||||
|
<version>3.6.3</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>4.9.3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.thoughtworks.xstream</groupId>
|
||||||
|
<artifactId>xstream</artifactId>
|
||||||
|
<version>1.4.20</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.34</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
<version>3.3.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<version>3.3.2</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- DOM4J是 dom4j.org 出品的一个开源XML解析包-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dom4j</groupId>
|
||||||
|
<artifactId>dom4j</artifactId>
|
||||||
|
<version>2.1.3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
|
<artifactId>fastjson2</artifactId>
|
||||||
|
<version>2.0.43</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>com.muyu</groupId>-->
|
||||||
|
<!-- <artifactId>cloud-common-redis</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.muyu;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: WxApplication ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/16 20:39 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
public class WxApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(WxApplication.class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.muyu.button;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: AbstractButton ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/18 20:57 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
public abstract class AbstractButton {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractButton(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.muyu.button;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: Button ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/18 20:53 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Button {
|
||||||
|
private List<AbstractButton> button;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.muyu.button;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: ClickButton ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/18 21:00 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
public class ClickButton extends AbstractButton{
|
||||||
|
public ClickButton(String name) {
|
||||||
|
super(name);
|
||||||
|
this.type="click";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.muyu.button;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: PhotoOrAlbum ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/18 21:18 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
public class PhotoOrAlbumButton extends AbstractButton{
|
||||||
|
public PhotoOrAlbumButton(String name) {
|
||||||
|
super(name);
|
||||||
|
this.type="pic_photo_or_album";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
|
||||||
|
}
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.muyu.button;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: SubButton ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/18 21:24 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
public class SubButton extends AbstractButton{
|
||||||
|
public SubButton(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
private List<AbstractButton> sub_button;
|
||||||
|
|
||||||
|
public List<AbstractButton> getSub_button() {
|
||||||
|
return sub_button;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSub_button(List<AbstractButton> sub_button) {
|
||||||
|
this.sub_button = sub_button;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.muyu.button;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: TestButton ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/18 22:20 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
public class TestButton {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
//创建一级菜单
|
||||||
|
Button button = new Button();
|
||||||
|
ArrayList<AbstractButton> buttons = new ArrayList<>();
|
||||||
|
//一级菜单中的第一个按钮
|
||||||
|
ClickButton clickButton = new ClickButton("授权");
|
||||||
|
clickButton.setKey("1");
|
||||||
|
|
||||||
|
//一级菜单中的第二个按钮
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
button.setButton(buttons);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.muyu.button;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: ViewButton ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/18 21:14 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
public class ViewButton extends AbstractButton{
|
||||||
|
public ViewButton(String name,String url) {
|
||||||
|
super(name);
|
||||||
|
this.type="view";
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
private String type;
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,202 @@
|
||||||
|
package com.muyu.controller;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.muyu.domain.Message;
|
||||||
|
import com.muyu.service.WxService;
|
||||||
|
import com.muyu.util.OkHttpUtils;
|
||||||
|
import com.muyu.util.TokenUtil;
|
||||||
|
import com.muyu.util.WechatUtil;
|
||||||
|
import com.thoughtworks.xstream.XStream;
|
||||||
|
import io.micrometer.common.util.StringUtils;
|
||||||
|
import jakarta.servlet.ServletInputStream;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import okhttp3.*;
|
||||||
|
import org.dom4j.Document;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.dom4j.io.SAXReader;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: GetWxController ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/16 20:38 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class WxController {
|
||||||
|
|
||||||
|
// @Autowired
|
||||||
|
// private RedisService redisService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WxService wxService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息验证,验证是否是微信
|
||||||
|
* @param signature
|
||||||
|
* @param timestamp
|
||||||
|
* @param nonce
|
||||||
|
* @param echostr
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GetMapping("/")
|
||||||
|
public String check(@RequestParam("signature") String signature,@RequestParam("timestamp") String timestamp ,
|
||||||
|
@RequestParam("nonce") String nonce, @RequestParam("echostr") String echostr){
|
||||||
|
|
||||||
|
String token ="zzhdzt";
|
||||||
|
List<String> list = Arrays.asList(token, timestamp, nonce);
|
||||||
|
Collections.sort(list);
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
for (String s : list) {
|
||||||
|
stringBuilder.append(s);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
|
||||||
|
MessageDigest instance = MessageDigest.getInstance("sha1");
|
||||||
|
//使用sha1进行加密,获得byte数组
|
||||||
|
byte[] digest = instance.digest(stringBuilder.toString().getBytes());
|
||||||
|
StringBuilder sum = new StringBuilder();
|
||||||
|
for (byte b : digest) {
|
||||||
|
sum.append(Integer.toHexString((b>>4)&15));
|
||||||
|
sum.append(Integer.toHexString(b&15));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.isEmpty(signature) && signature.equals(sum.toString())){
|
||||||
|
return echostr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收消息并自动回复
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("/")
|
||||||
|
public String receiveMessage(HttpServletRequest request){
|
||||||
|
|
||||||
|
|
||||||
|
String message = wxService.handleMessage(request);
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/getSignUpUserInfo")
|
||||||
|
public String getSignUpUserInfo(HttpServletRequest request){
|
||||||
|
|
||||||
|
String code = request.getParameter("code");
|
||||||
|
|
||||||
|
return wxService.getSignUpUserInfo(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/send")
|
||||||
|
public void sendWxMsg(@RequestParam("toUser") String toUser,@RequestParam("content") String content) {
|
||||||
|
WechatUtil.send(toUser,content);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @GetMapping("/getWxUserList")
|
||||||
|
// public List getUserList(){
|
||||||
|
// String accessToken = TokenUtil.getAccessToken();
|
||||||
|
// String url="https://api.weixin.qq.com/cgi-bin/user/get?access_token="+accessToken;
|
||||||
|
// String request = OkHttpUtils.sendGetRequest(url);
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// ObjectMapper mapper = new ObjectMapper();
|
||||||
|
// JsonNode rootNode = mapper.readTree(request);
|
||||||
|
//
|
||||||
|
// int total = rootNode.get("total").asInt();
|
||||||
|
// int count = rootNode.get("count").asInt();
|
||||||
|
// JsonNode itemsNode = rootNode.get("data");
|
||||||
|
// JsonNode openIdNode = itemsNode.get("openid");
|
||||||
|
// List<String> openids = new ArrayList<>();
|
||||||
|
//
|
||||||
|
// // 遍历 JSON 数组中的每个元素
|
||||||
|
// for (JsonNode item : openIdNode) {
|
||||||
|
// // 添加到集合中
|
||||||
|
// openids.add(item.asText());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// String nextOpenid = openids.isEmpty() ? null : openids.get(openids.size() - 1);
|
||||||
|
//
|
||||||
|
// // 构建最终的JSON对象
|
||||||
|
// Map<String, Object> map = new HashMap<>();
|
||||||
|
// map.put("total", total);
|
||||||
|
// map.put("count", count);
|
||||||
|
// Map<String, List<String>> data = new HashMap<>();
|
||||||
|
// data.put("openid", openids);
|
||||||
|
// map.put("data", data);
|
||||||
|
// map.put("next_openid", nextOpenid);
|
||||||
|
//
|
||||||
|
// // 根据openid获取用户信息
|
||||||
|
// for (String openid : openids) {
|
||||||
|
// String getUserUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
|
||||||
|
// String userInfoRequest = OkHttpUtils.sendGetRequest(getUserUrl);
|
||||||
|
//
|
||||||
|
// // 解析用户信息
|
||||||
|
// JsonNode userInfoNode = mapper.readTree(userInfoRequest);
|
||||||
|
// System.out.println("用户信息: " + userInfoNode);
|
||||||
|
// }
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// // 处理解析错误
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// @PostMapping("/test")
|
||||||
|
// public void test(){
|
||||||
|
// String accessToken = TokenUtil.getAccessToken();
|
||||||
|
// System.out.println(accessToken);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// String message="<xml><ToUserName><![CDATA[gh_746d58eabb43]]></ToUserName><FromUserName><![CDATA[oUjOm6hQ2WPWn1d8YO2-ovVJpfdE]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[你好]]></Content></xml>";
|
||||||
|
// @PostMapping("/")
|
||||||
|
// public String receiveMessage(HttpServletRequest request){
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// ServletInputStream inputStream = null;
|
||||||
|
// inputStream = request.getInputStream();
|
||||||
|
//
|
||||||
|
// byte[] bytes = new byte[1024];
|
||||||
|
// int len = 0;
|
||||||
|
// while ((len=inputStream.read(bytes))!=-1){
|
||||||
|
// System.out.println(new String(bytes, 0, len));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// throw new RuntimeException(e);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return "";
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.muyu.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: AccessToken ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/17 16:49 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AccessToken {
|
||||||
|
|
||||||
|
|
||||||
|
private String access_token;
|
||||||
|
|
||||||
|
private Long expires_in;
|
||||||
|
|
||||||
|
public void setExpiresTime(Long expiresIn) {
|
||||||
|
this.expires_in = System.currentTimeMillis()+expiresIn*1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public boolean isExpired(Long expiresIn){
|
||||||
|
// long now = System.currentTimeMillis();
|
||||||
|
// return now>expiresIn;
|
||||||
|
// }
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.muyu.domain;
|
||||||
|
|
||||||
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: Message ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/17 16:49 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@XStreamAlias("xml")
|
||||||
|
public class Message {
|
||||||
|
@XStreamAlias("ToUserName")
|
||||||
|
private String toUserName;
|
||||||
|
|
||||||
|
@XStreamAlias("FromUserName")
|
||||||
|
private String fromUserName;
|
||||||
|
|
||||||
|
@XStreamAlias("CreateTime")
|
||||||
|
private Long createTime;
|
||||||
|
|
||||||
|
@XStreamAlias("MsgType")
|
||||||
|
private String msgType;
|
||||||
|
|
||||||
|
@XStreamAlias("Content")
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.muyu.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: SubscribedUser ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/18 15:11 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SubscribedUser {
|
||||||
|
private String openid;
|
||||||
|
private String nickname;
|
||||||
|
private Integer sex;
|
||||||
|
private String province;
|
||||||
|
private String city;
|
||||||
|
private String country;
|
||||||
|
private String headimgurl;
|
||||||
|
private Long subscribedTime;
|
||||||
|
// private String privilege;
|
||||||
|
// private String unionid;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
package com.muyu.service.Impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.muyu.domain.Message;
|
||||||
|
import com.muyu.domain.SubscribedUser;
|
||||||
|
import com.muyu.service.WxService;
|
||||||
|
import com.muyu.util.OkHttpUtils;
|
||||||
|
import com.muyu.util.TokenUtil;
|
||||||
|
import com.muyu.util.WechatUtil;
|
||||||
|
import com.thoughtworks.xstream.XStream;
|
||||||
|
import jakarta.servlet.ServletInputStream;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import org.dom4j.Document;
|
||||||
|
import org.dom4j.DocumentException;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.dom4j.io.SAXReader;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: WxServiceImpl ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/18 12:05 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class WxServiceImpl implements WxService {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理信息
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String handleMessage(HttpServletRequest request) {
|
||||||
|
ServletInputStream inputStream = null;
|
||||||
|
|
||||||
|
HashMap<String, String> map = new HashMap<>();
|
||||||
|
try {
|
||||||
|
inputStream = request.getInputStream();
|
||||||
|
|
||||||
|
|
||||||
|
SAXReader saxReader = new SAXReader();
|
||||||
|
|
||||||
|
Document document = saxReader.read(inputStream);
|
||||||
|
Element rootElement = document.getRootElement();
|
||||||
|
List<Element> elements = rootElement.elements();
|
||||||
|
|
||||||
|
for (Element element : elements) {
|
||||||
|
map.put(element.getName(),element.getStringValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (DocumentException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("接受消息:"+map);
|
||||||
|
|
||||||
|
String replyMessage = getReplyMessage(map);
|
||||||
|
|
||||||
|
System.out.println("返回消息:"+replyMessage);
|
||||||
|
return replyMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSignUpUserInfo(String code) {
|
||||||
|
String appId = TokenUtil.APP_ID;
|
||||||
|
String appSecret = TokenUtil.APP_SECRET;
|
||||||
|
String url= String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",appId,appSecret,code);
|
||||||
|
|
||||||
|
String request = OkHttpUtils.sendGetRequest(url);
|
||||||
|
String accessToken = JSONObject.parseObject(request).getString("access_token");
|
||||||
|
String openId = JSONObject.parseObject(request).getString("openid");
|
||||||
|
|
||||||
|
String userInfoUrl= String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN",accessToken,openId);
|
||||||
|
|
||||||
|
String userInfo = OkHttpUtils.sendGetRequest(userInfoUrl);
|
||||||
|
SubscribedUser subscribedUser = JSONObject.parseObject(userInfo, SubscribedUser.class);
|
||||||
|
System.out.println(subscribedUser);
|
||||||
|
//TODO
|
||||||
|
// 添加数据库
|
||||||
|
|
||||||
|
WechatUtil.send(openId,"授权成功");
|
||||||
|
|
||||||
|
return "恭喜你,信息被盗取了";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得回复的消息内容
|
||||||
|
* @param map
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getReplyMessage(HashMap<String, String> map) {
|
||||||
|
Message message = new Message();
|
||||||
|
message.setToUserName(map.get("FromUserName"));
|
||||||
|
message.setFromUserName(map.get("ToUserName"));
|
||||||
|
// message.setMsgType(map.get("MsgType"));
|
||||||
|
message.setMsgType("text");
|
||||||
|
message.setCreateTime(System.currentTimeMillis()/1000);
|
||||||
|
String appId = TokenUtil.APP_ID;
|
||||||
|
String appSecret = TokenUtil.APP_SECRET;
|
||||||
|
String redirectDomain = TokenUtil.REDIRECT_DOMAIN;
|
||||||
|
|
||||||
|
//获取用户授权的url
|
||||||
|
String url = String.format("https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=STATE#wechat_redirect",appId,
|
||||||
|
"http://"+redirectDomain+"/getSignUpUserInfo","snsapi_userinfo") ;
|
||||||
|
|
||||||
|
|
||||||
|
message.setContent("点击给公众号授权链接 <a href=\""+url+"\">授权</a>");
|
||||||
|
XStream xStream =new XStream();
|
||||||
|
xStream.processAnnotations(Message.class);
|
||||||
|
String xml = xStream.toXML(message);
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.muyu.service;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: WxService ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/18 12:05 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
public interface WxService {
|
||||||
|
String handleMessage(HttpServletRequest request);
|
||||||
|
|
||||||
|
String getSignUpUserInfo(String code);
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.muyu.util;
|
||||||
|
|
||||||
|
import okhttp3.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class OkHttpUtils {
|
||||||
|
|
||||||
|
private static final OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
|
public static String sendGetRequest(String urlString) {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(urlString)
|
||||||
|
.build();
|
||||||
|
try (Response response = client.newCall(request).execute()) {
|
||||||
|
return response.body().string();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sendPostRequest(String urlString, String params) {
|
||||||
|
RequestBody requestBody = RequestBody.create(params, MediaType.parse("application/json; charset=utf-8"));
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(urlString)
|
||||||
|
.post(requestBody)
|
||||||
|
.build();
|
||||||
|
try (Response response = client.newCall(request).execute()) {
|
||||||
|
return response.body().string();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.muyu.util;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.muyu.domain.AccessToken;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @className: TokenUtil ️✈️
|
||||||
|
* @author: Yang 鹏 🦅
|
||||||
|
* @date: 2024/9/17 20:26 ⏰
|
||||||
|
* @Version: 1.0
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class TokenUtil {
|
||||||
|
public final static String APP_ID = "wxa10c6f55da3c0553";
|
||||||
|
|
||||||
|
public final static String APP_SECRET ="72d285981f3f51274e79dcda5e498a81";
|
||||||
|
|
||||||
|
|
||||||
|
//域名
|
||||||
|
public final static String REDIRECT_DOMAIN ="3kknv4.natappfree.cc";
|
||||||
|
|
||||||
|
private static AccessToken accessToken = new AccessToken();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static void getToken(){
|
||||||
|
String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",APP_ID,APP_SECRET);
|
||||||
|
String request = OkHttpUtils.sendGetRequest(url);
|
||||||
|
AccessToken wechatToken = JSON.parseObject(request, AccessToken.class);
|
||||||
|
//redisService.setCacheObject("WECHAT_TOKEN",wechatToken.getAccessToken(),wechatToken.getExpiresIn(), TimeUnit.SECONDS);
|
||||||
|
if (wechatToken != null) {
|
||||||
|
accessToken.setExpiresTime(wechatToken.getExpires_in());
|
||||||
|
accessToken.setAccess_token(wechatToken.getAccess_token());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static String getAccessToken(){
|
||||||
|
getToken();
|
||||||
|
return accessToken.getAccess_token();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.muyu.util;
|
||||||
|
|
||||||
|
|
||||||
|
import io.micrometer.common.util.StringUtils;
|
||||||
|
import okhttp3.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class WechatUtil {
|
||||||
|
|
||||||
|
public static void send(String toUser,String content) {
|
||||||
|
String accessToken = TokenUtil.getAccessToken();
|
||||||
|
if (!StringUtils.isBlank(accessToken)) {
|
||||||
|
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + accessToken;
|
||||||
|
String jsonStr = "{\"touser\":\"" + toUser + "\",\"msgtype\":\"text\",\"text\":{\"content\":\"" + content + "\"}}";
|
||||||
|
OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
|
// 构建请求
|
||||||
|
RequestBody requestBody = RequestBody.create(jsonStr, MediaType.get("application/json; charset=utf-8"));
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.post(requestBody)
|
||||||
|
.addHeader("Content-Type", "application/json; charset=utf-8")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
try (Response response = client.newCall(request).execute()) {
|
||||||
|
if (!response.isSuccessful()) {
|
||||||
|
throw new IOException("Unexpected code " + response);
|
||||||
|
}
|
||||||
|
// 输出响应
|
||||||
|
System.out.println(response.body().string());
|
||||||
|
}catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Tomcat
|
||||||
|
server:
|
||||||
|
port: 8088
|
||||||
|
##用户授权的重定向域名
|
||||||
|
#redirect:
|
||||||
|
# domain:123
|
||||||
|
##公众号appId和secret
|
||||||
|
#wx:
|
||||||
|
# appId:123
|
||||||
|
# secret:123
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue