Compare commits
23 Commits
3ce24c98b4
...
a62681e3f7
| Author | SHA1 | Date |
|---|---|---|
|
|
a62681e3f7 | |
|
|
f27abbd081 | |
|
|
fa1c872897 | |
|
|
9462f5caab | |
|
|
7020497109 | |
|
|
07be57d5cf | |
|
|
7a8fdc2f4e | |
|
|
bbb7bedc94 | |
|
|
f9c47e25e4 | |
|
|
3d01fffebe | |
|
|
2f424e837d | |
|
|
f89bbbc551 | |
|
|
03e6decd71 | |
|
|
919e75f2b1 | |
|
|
e8e7d397d5 | |
|
|
7fef7a0b1d | |
|
|
8ac1e83691 | |
|
|
a18a200a4b | |
|
|
5a7e05c6ca | |
|
|
ef38dc1413 | |
|
|
f5d120817d | |
|
|
c18e126dfd | |
|
|
69800cd27b |
|
|
@ -45,9 +45,10 @@ CREATE TABLE device_info (
|
|||
sn VARCHAR(255),
|
||||
device_model VARCHAR(255),
|
||||
last_online_time BIGINT,
|
||||
status INT
|
||||
status INT,
|
||||
remark VARCHAR(255)
|
||||
);
|
||||
|
||||
INSERT INTO device_info (is_monitored, time_out_period, device_brand, android_version, sn, device_model, last_online_time, status) VALUES
|
||||
(1, 600, 'google', 'Android 10', UNIX_TIMESTAMP(), 1),
|
||||
INSERT INTO device_info (is_monitored, time_out_period, device_brand, android_version, sn, device_model, last_online_time, status,remark) VALUES
|
||||
(1, 1800, 'google', 'Android 10',,'Pixel 3', UNIX_TIMESTAMP(), 1,'转发设备'),
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# 基础镜像使用OpenJDK官方镜像,标签为17-jdk-slim,这是Java 17的精简版环境
|
||||
FROM openjdk:17-jdk-slim
|
||||
|
||||
# 设置容器内的工作目录。如果该目录不存在,Docker将自动为你创建它。
|
||||
WORKDIR /app
|
||||
|
||||
# 将构建生成的可执行jar包复制到容器内。假设jar包位于target/目录下,并命名为wePush-1.0.0.jar。
|
||||
COPY target/wePush-1.0.0.jar ./app.jar
|
||||
|
||||
# 配置容器启动时运行的命令,这里用来启动Spring Boot应用。
|
||||
# 使用非root用户运行Java应用是一个好的安全实践。
|
||||
# 这里可以根据需要添加其他JVM参数,比如内存限制等。
|
||||
CMD ["java", "-jar", "/app/app.jar"]
|
||||
|
||||
# 暴露8080端口,这是Spring Boot应用默认的端口。
|
||||
# 注意,实际部署时可能需要根据应用的具体配置来调整端口号。
|
||||
EXPOSE 8080
|
||||
|
|
@ -22,18 +22,28 @@ public class WeChatMsgForwarderController {
|
|||
this.handleWeChatMsgService = handleWeChatMsgService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收微信消息。
|
||||
*
|
||||
* @param accessToken 访问令牌,用于验证请求的合法性。该参数通过请求头传递。
|
||||
* @param weChatMsg 微信消息体,包含消息的各种内容。该参数通过请求体传递,并需通过验证。
|
||||
* @return 返回处理结果,如果处理成功,返回成功状态和处理信息;如果失败,返回失败状态和错误信息。
|
||||
*/
|
||||
@PostMapping("/wechat")
|
||||
public ServerResponseEntity receiveMsg(@RequestHeader("accessToken") String accessToken,
|
||||
@RequestBody @Valid WeChatMsg weChatMsg){
|
||||
logger.info("CallInfoO: {}",weChatMsg.toString());
|
||||
@RequestBody @Valid WeChatMsg weChatMsg){
|
||||
logger.info("weChatMsg: {}",weChatMsg.toString());
|
||||
// 检查accessToken是否为空,为空则返回错误信息
|
||||
if(accessToken == null){
|
||||
logger.warn("Access token is missing or empty");
|
||||
return ServerResponseEntity.fail("accessToken cannot be empty.");
|
||||
}
|
||||
// 检查weChatMsg消息体是否有效,无效则返回错误信息
|
||||
if (weChatMsg.isInvalid()) {
|
||||
logger.debug("CallInfo has invalid fields.");
|
||||
return ServerResponseEntity.fail("json body value error.");
|
||||
}
|
||||
// 调用服务处理微信消息
|
||||
return handleWeChatMsgService.handleMsg(accessToken,weChatMsg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,4 +21,5 @@ public class DeviceInfoDAO {
|
|||
private String deviceModel;
|
||||
private long lastOnlineTime;
|
||||
private int status;
|
||||
private String remark;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,5 @@ public class TextMessage {
|
|||
public static class Text {
|
||||
private String content;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,35 +12,51 @@ import java.io.IOException;
|
|||
|
||||
public class WeChatAPI {
|
||||
private final Logger logger = LoggerFactory.getLogger(WeChatAPI.class);
|
||||
/**
|
||||
* 获取企业微信访问令牌
|
||||
* @param corpid 企业ID
|
||||
* @param corpsecret 企业密钥
|
||||
* @return 返回获取到的访问令牌,如果获取失败则返回null
|
||||
*/
|
||||
public String getAccessToken(String corpid,String corpsecret){
|
||||
// 创建OkHttpClient实例
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
|
||||
// 设置请求URL并添加查询参数
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
|
||||
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
|
||||
urlBuilder.addQueryParameter("corpid", corpid);
|
||||
urlBuilder.addQueryParameter("corpsecret", corpsecret);
|
||||
|
||||
// 构建请求
|
||||
Request request = new Request.Builder()
|
||||
.url(urlBuilder.build())
|
||||
.build();
|
||||
|
||||
try (Response response = client.newCall(request).execute()) {
|
||||
// 从响应中读取body内容
|
||||
String responseBody = response.body().string();
|
||||
logger.info("get qyWeChat AccessToken responseBody: {}", responseBody);
|
||||
|
||||
// 对响应内容进行JSON解析
|
||||
ObjectMapper objectMapper1 = new ObjectMapper();
|
||||
QyWeChatGetAccessTokenApiResponse qyWeChatGetAccessTokenApiResponse = objectMapper1.readValue(responseBody, QyWeChatGetAccessTokenApiResponse.class);
|
||||
// 检查是否获取令牌成功
|
||||
if (qyWeChatGetAccessTokenApiResponse.getErrcode() == 0){
|
||||
logger.debug("get qyWeChat AccessToken Success");
|
||||
// 返回访问令牌
|
||||
return qyWeChatGetAccessTokenApiResponse.getAccess_token();
|
||||
} else {
|
||||
// 记录获取令牌失败的日志
|
||||
logger.error("getAccessToken error: {}",qyWeChatGetAccessTokenApiResponse.getErrmsg());
|
||||
return null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// 记录异常信息
|
||||
logger.error("getAccessToken error:",e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,17 +27,42 @@ public class ApiSettingService {
|
|||
}
|
||||
return apiSetting;
|
||||
}
|
||||
private void queryApiSetting(){
|
||||
|
||||
/**
|
||||
* 查询API设置信息。
|
||||
* 该方法不接受参数,也不返回值,但会根据用户配置的电话号码查询数据库中的API设置信息,并更新相关的成员变量。
|
||||
* 主要步骤包括:
|
||||
* 1. 从用户配置中获取电话号码。
|
||||
* 2. 构建查询条件。
|
||||
* 3. 根据查询条件从数据库中查询唯一的API设置信息。
|
||||
* 4. 记录查询结果的日志信息。
|
||||
* 5. 如果查询结果为空,则更新API设置为null,并记录错误日志。
|
||||
* 6. 最后,更新API设置成员变量为查询结果,并记录相应日志。
|
||||
*/
|
||||
private void queryApiSetting() {
|
||||
// 从用户配置中获取电话号码
|
||||
String phoneNumberToSearch = userConfig.getPhoneNumber();
|
||||
|
||||
// 构建查询条件
|
||||
QueryWrapper<ApiSetting> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("phone_number", phoneNumberToSearch);
|
||||
|
||||
// 根据查询条件查询API设置信息
|
||||
ApiSetting result = apiSettingMapper.selectOne(wrapper);
|
||||
logger.info("result: {}",result);
|
||||
if (result == null){
|
||||
// 记录查询结果
|
||||
logger.info("result: {}", result);
|
||||
|
||||
// 处理查询结果为空的情况
|
||||
if (result == null) {
|
||||
apiSetting = null;
|
||||
// 记录错误日志
|
||||
logger.error("updateAccessToken error");
|
||||
}
|
||||
|
||||
// 更新API设置成员变量
|
||||
apiSetting = result;
|
||||
logger.info("get apiSetting from mysql,accessToken: {}",apiSetting);
|
||||
// 记录更新日志
|
||||
logger.info("get apiSetting from mysql,accessToken: {}", apiSetting);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,37 +30,67 @@ public class CallService {
|
|||
this.tokenService = tokenService;
|
||||
}
|
||||
|
||||
public ServerResponseEntity getPhoneNumber(String accessToken, CallInfo callInfo){
|
||||
/**
|
||||
* 根据提供的accessToken和呼叫信息获取电话号码。
|
||||
* 首先验证提供的accessToken的有效性,然后通过调用信息(电话号码和呼叫时间)向企业微信发送消息,
|
||||
* 并根据企业微信的响应返回成功或失败的服务器响应。
|
||||
*
|
||||
* @param accessToken 用户提供的accessToken用于身份验证。
|
||||
* @param callInfo 呼叫信息,包含电话号码和呼叫时间。
|
||||
* @return 返回一个服务器响应实体,如果成功则包含消息ID,如果失败则包含错误信息。
|
||||
*/
|
||||
public ServerResponseEntity getPhoneNumber(String accessToken, CallInfo callInfo) {
|
||||
// 通过token服务获取正确的accessToken
|
||||
String correctAccessToken = tokenService.getApiAccessToken();
|
||||
logger.info("accessToken: {} correctAccessToken: {}",accessToken,correctAccessToken);
|
||||
if (!correctAccessToken.equals(accessToken)){
|
||||
logger.info("accessToken: {} correctAccessToken: {}", accessToken, correctAccessToken);
|
||||
// 验证提供的accessToken是否有效
|
||||
if (!correctAccessToken.equals(accessToken)) {
|
||||
return ServerResponseEntity.fail("Invalid accessToken");
|
||||
}
|
||||
// 从呼叫信息中获取电话号码和呼叫时间
|
||||
String phoneNumber = callInfo.getPhoneNumber();
|
||||
String callTime = callInfo.getCallTime();
|
||||
// 获取企业微信的访问令牌
|
||||
String qyAccessToken = tokenService.getAccessToken();
|
||||
QyWeChatSendMessageApiResponse qyWeChatSendMessageApiResponse = requestWithOkhttp(qyAccessToken,phoneNumber,callTime);
|
||||
// 使用企业微信的accessToken、电话号码和呼叫时间发送消息,并获取响应
|
||||
QyWeChatSendMessageApiResponse qyWeChatSendMessageApiResponse = requestWithOkhttp(qyAccessToken, phoneNumber, callTime);
|
||||
// 检查发送消息的响应代码
|
||||
int code = qyWeChatSendMessageApiResponse.getErrcode();
|
||||
if (code == 0){
|
||||
if (code == 0) {
|
||||
// 如果消息发送成功,构建并返回成功的服务器响应
|
||||
SendMessageResonse sendMessageResonse = new SendMessageResonse();
|
||||
sendMessageResonse.setMsgid(qyWeChatSendMessageApiResponse.getMsgid());
|
||||
return ServerResponseEntity.success(sendMessageResonse);
|
||||
} else {
|
||||
// 如果消息发送失败,返回失败的服务器响应
|
||||
return ServerResponseEntity.fail("request qyWeChat error,please check server error log.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置文本卡片消息的内容。
|
||||
*
|
||||
* @param phoneNumber 来电电话号码
|
||||
* @param callTime 来电时间
|
||||
* @return TextCardMessage 文本卡片消息对象,包含了设置好的内容
|
||||
*/
|
||||
public TextCardMessage setTextCardMessage(String phoneNumber, String callTime) {
|
||||
TextCardMessage textCardMessage = new TextCardMessage();
|
||||
// 从api设置中获取用户信息,并设置到textCardMessage中
|
||||
textCardMessage.setTouser(apiSettingService.getApiSetting().getTouser());
|
||||
textCardMessage.setMsgtype(apiSettingService.getApiSetting().getMsgtype());
|
||||
textCardMessage.setAgentid(apiSettingService.getApiSetting().getAgentid());
|
||||
textCardMessage.setEnable_duplicate_check(apiSettingService.getApiSetting().getEnableDuplicateCheck());
|
||||
textCardMessage.setDuplicate_check_interval(apiSettingService.getApiSetting().getDuplicateCheckInterval());
|
||||
|
||||
// 创建TextCard对象,并设置其内容
|
||||
TextCardMessage.TextCard textCard = new TextCardMessage.TextCard();
|
||||
textCard.setTitle("新来电通知");
|
||||
// 设置描述信息,包含来电号码和来电时间
|
||||
textCard.setDescription("<div class='gray'>您有一通新来电</div><div class='highlight'>来电号码: " + phoneNumber + "</div><div class='highlight'>来电时间: " + callTime + "</div>如果您认识这个号码,请及时回电。如果不认识,请注意可能是垃圾电话或诈骗电话。");
|
||||
textCard.setUrl("https://kimgo.cn");
|
||||
|
||||
// 将TextCard对象设置到TextCardMessage中
|
||||
textCardMessage.setTextcard(textCard);
|
||||
|
||||
|
|
@ -69,37 +99,53 @@ public class CallService {
|
|||
return textCardMessage;
|
||||
}
|
||||
|
||||
public QyWeChatSendMessageApiResponse requestWithOkhttp(String accessToken,String phoneNumber,String callTime){
|
||||
|
||||
/**
|
||||
* 使用OkHttp发送企业微信文本卡片消息。
|
||||
*
|
||||
* @param accessToken 访问令牌,用于授权访问企业微信API。
|
||||
* @param phoneNumber 接收消息的手机号码。
|
||||
* @param callTime 预约的呼叫时间。
|
||||
* @return 返回企业微信发送消息的API响应,如果失败则返回null。
|
||||
*/
|
||||
public QyWeChatSendMessageApiResponse requestWithOkhttp(String accessToken, String phoneNumber, String callTime) {
|
||||
// 构建发送文本卡片消息的URL
|
||||
String url = qyWeChatURLService.getSendTextCardMessageUrl() + "?access_token=" + accessToken;
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
|
||||
TextCardMessage textCardMessage = setTextCardMessage(phoneNumber,callTime);
|
||||
// 使用Jackson进行序列化
|
||||
// 设置文本卡片消息内容
|
||||
TextCardMessage textCardMessage = setTextCardMessage(phoneNumber, callTime);
|
||||
// 将消息对象序列化为JSON字符串
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String jsonBody;
|
||||
try {
|
||||
jsonBody = objectMapper.writeValueAsString(textCardMessage);
|
||||
logger.info("jsonBody: {}",jsonBody);
|
||||
logger.info("jsonBody: {}", jsonBody);
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.error("JSON processing error", e);
|
||||
return null;
|
||||
}
|
||||
// 构建请求体
|
||||
|
||||
// 构建HTTP请求体
|
||||
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonBody);
|
||||
Request request = new Request.Builder().url(url).post(body).build();
|
||||
try (Response response = client.newCall(request).execute()) {
|
||||
// 从响应中读取内容
|
||||
String responseBody = response.body().string();
|
||||
logger.info("request sendMessage api ResponseBody: {}", responseBody);
|
||||
|
||||
// 反序列化API响应
|
||||
ObjectMapper objectMapper1 = new ObjectMapper();
|
||||
QyWeChatSendMessageApiResponse apiResponse = objectMapper1.readValue(responseBody, QyWeChatSendMessageApiResponse.class);
|
||||
|
||||
// 处理不同的API响应结果
|
||||
if (apiResponse.getErrcode() == 0) {
|
||||
logger.debug("Request qyWeChat Success.");
|
||||
return apiResponse;
|
||||
} else if (apiResponse.getErrcode() == 42001 || apiResponse.getErrcode() == 40014) {
|
||||
// 处理访问令牌过期的情况,刷新令牌后重新发送消息
|
||||
logger.info("Access token expired. Refreshing token...");
|
||||
tokenService.setAccessToken(); // 一个方法来刷新accessToken
|
||||
tokenService.setAccessToken(); // 刷新accessToken的方法
|
||||
String newAccessToken = tokenService.getAccessToken();
|
||||
return requestWithOkhttp(newAccessToken, phoneNumber, callTime);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.kimgo.wepush.service;
|
||||
package com.kimgo.wepush.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
|
|
@ -102,7 +102,7 @@ public class HeartBeatService {
|
|||
try {
|
||||
DeviceInfoDAO deviceInfoDAO = deviceInfoDAOMapper.selectOne(queryWrapper);
|
||||
if (deviceInfoDAO != null) {
|
||||
logger.info("Data is queried in the database based on the SN");
|
||||
//logger.info("Data is queried in the database based on the SN");
|
||||
return deviceInfoDAO;
|
||||
}
|
||||
return null; // 数据不存在
|
||||
|
|
@ -120,9 +120,8 @@ public class HeartBeatService {
|
|||
* @return 转换后的 DeviceInfoDAO 对象。
|
||||
*/
|
||||
private DeviceInfoDAO convertToDeviceInfoDAO(DeviceInfo deviceInfo) {
|
||||
logger.info("start convert to device info dao");
|
||||
// 这里需要实现将 DeviceInfo 转换为 DeviceInfoDAO 的逻辑
|
||||
// 示例代码(根据实际字段调整):
|
||||
// logger.info("start convert to device info dao");
|
||||
|
||||
DeviceInfoDAO deviceInfoDAO = new DeviceInfoDAO();
|
||||
deviceInfoDAO.setIsMonitored(1);
|
||||
deviceInfoDAO.setDeviceBrand(deviceInfo.getDeviceBrand());
|
||||
|
|
|
|||
|
|
@ -33,50 +33,65 @@ public class MonitorService {
|
|||
this.deviceInfoDAOMapper = deviceInfoDAOMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 定时监控在线设备的状态。
|
||||
* 该方法每隔固定的时间间隔(480000毫秒)执行一次,用于检查数据库中的设备是否在线。
|
||||
* 对于每个设备,如果其最后上线时间与当前时间的差值超过了设备的超时周期,则认为该设备已离线,并更新设备状态及发送通知。
|
||||
*
|
||||
* @Scheduled 注解指定了方法的定时执行策略,fixedDelay属性表示执行完一次后,隔多长时间再执行下一次。
|
||||
*/
|
||||
@Scheduled(fixedDelay = 480000)
|
||||
public void monitorOnlineDevices() {
|
||||
|
||||
List<DeviceInfoDAO> devices;
|
||||
try {
|
||||
// 尝试从数据库获取所有设备信息
|
||||
devices = getAllDevices();
|
||||
} catch (DatabaseQueryException e) {
|
||||
// 查询设备信息出错时的处理逻辑
|
||||
logger.error("monitor online devices error.");
|
||||
return;
|
||||
}
|
||||
if (devices.isEmpty()) {
|
||||
// 没有找到数据的处理逻辑
|
||||
// 如果查询到的设备列表为空,记录日志并返回
|
||||
logger.info("no data was queried.");
|
||||
return;
|
||||
}
|
||||
for (DeviceInfoDAO device : devices) {
|
||||
try {
|
||||
if (device.getIsMonitored() != 1){
|
||||
logger.info("device is not monitored ,device SN: {}",device.getSN());
|
||||
// 如果设备不被监控,则跳过该设备的处理
|
||||
if (device.getIsMonitored() != 1) {
|
||||
logger.info("device is not monitored ,device SN: {}", device.getSN());
|
||||
continue;
|
||||
}
|
||||
// 计算设备最后上线时间与当前时间的差值
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
long timeDifferenceMillis = currentTimeMillis - device.getLastOnlineTime();
|
||||
long timeDifferenceSeconds = timeDifferenceMillis / 1000;
|
||||
// 如果设备超出设定的超时周期未上线,则认为设备离线,并进行相应处理
|
||||
if (timeDifferenceSeconds > device.getTimeOutPeriod()) {
|
||||
logger.info("Device offline. SN: {}, LastOnlineTime: {}, TimeDifference: {}, TimeoutPeriod: {}",
|
||||
device.getSN(), device.getLastOnlineTime(), timeDifferenceSeconds, device.getTimeOutPeriod());
|
||||
updateStatus(device, 0); // 设备离线
|
||||
//logger.info("Device offline. SN: {}, LastOnlineTime: {}, TimeDifference: {}, TimeoutPeriod: {}",
|
||||
//device.getSN(), device.getLastOnlineTime(), timeDifferenceSeconds, device.getTimeOutPeriod());
|
||||
updateStatus(device, 0); // 更新设备状态为离线
|
||||
logger.info("Update the device status to offline.");
|
||||
sendNotification(device);
|
||||
sendNotification(device); // 发送设备离线通知
|
||||
} else {
|
||||
updateStatus(device, 1); // 设备在线
|
||||
logger.info("update the device status to online.");
|
||||
// 如果设备仍在设定的超时周期内上线,则认为设备在线,并更新设备状态
|
||||
updateStatus(device, 1); // 更新设备状态为在线
|
||||
//logger.info("update the device status to online.");
|
||||
}
|
||||
} catch (DatabaseUpdateException dbe){
|
||||
} catch (DatabaseUpdateException dbe) {
|
||||
// 更新数据库出错时的处理逻辑
|
||||
logger.error("update to mysql error.");
|
||||
return;
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
// 处理设备信息处理过程中出现的其他异常
|
||||
logger.error("Error processing device with SN " + device.getSN(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取数据库中所有DeviceInfoDAO对象的id。
|
||||
*
|
||||
|
|
@ -90,65 +105,104 @@ public class MonitorService {
|
|||
return deviceInfoDAOs;
|
||||
} catch (Exception e) {
|
||||
logger.error("Error querying all device info IDs", e);
|
||||
throw new DatabaseQueryException("get all devices error.",e);
|
||||
throw new DatabaseQueryException("get all devices error.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void sendNotification(DeviceInfoDAO deviceInfoDAO){
|
||||
/**
|
||||
* 发送通知消息到企业微信。
|
||||
*
|
||||
* @param deviceInfoDAO 设备信息数据访问对象,用于获取发送通知所需的信息。
|
||||
* 本函数不返回任何值,但会通过日志记录发送成功或失败的信息。
|
||||
*/
|
||||
private void sendNotification(DeviceInfoDAO deviceInfoDAO) {
|
||||
// 创建发送企业微信消息的请求对象,并初始化它
|
||||
SendQyWeChatMsgRequest sendQyWeChatMsgRequest = new SendQyWeChatMsgRequest(tokenService);
|
||||
// 获取访问令牌
|
||||
String accessToken = tokenService.getAccessToken();
|
||||
// 获取发送文本卡片消息的URL
|
||||
String url = qyWeChatURLService.getSendTextCardMessageUrl();
|
||||
// 发送请求,并获取响应
|
||||
QyWeChatSendMessageApiResponse qyWeChatSendMessageApiResponse = sendQyWeChatMsgRequest.okhttpRequest(url,
|
||||
accessToken,setTextCardMessage(deviceInfoDAO));
|
||||
if (qyWeChatSendMessageApiResponse ==null){
|
||||
accessToken, setTextCardMessage(deviceInfoDAO));
|
||||
// 如果发送响应为空,则记录发送失败
|
||||
if (qyWeChatSendMessageApiResponse == null) {
|
||||
logger.info("Send Notification Fail");
|
||||
}
|
||||
// 如果发送响应不为空且错误码为0,记录发送成功
|
||||
if (qyWeChatSendMessageApiResponse != null && qyWeChatSendMessageApiResponse.getErrcode() == 0) {
|
||||
logger.info("Send Notification Success");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建并设置文本卡片消息的内容。
|
||||
*
|
||||
* @param deviceInfoDAO 设备信息数据访问对象,用于获取设备的详细信息。
|
||||
* @return TextCardMessage 返回构建完成的文本卡片消息对象。
|
||||
*/
|
||||
public TextCardMessage setTextCardMessage(DeviceInfoDAO deviceInfoDAO) {
|
||||
TextCardMessage textCardMessage = new TextCardMessage();
|
||||
|
||||
// 设置消息的基本信息,如接收用户、消息类型和企业ID
|
||||
textCardMessage.setTouser(apiSettingService.getApiSetting().getTouser());
|
||||
textCardMessage.setMsgtype(apiSettingService.getApiSetting().getMsgtype());
|
||||
textCardMessage.setAgentid(apiSettingService.getApiSetting().getAgentid());
|
||||
textCardMessage.setEnable_duplicate_check(0);
|
||||
|
||||
// 创建文本卡片对象,并设置其内容
|
||||
TextCardMessage.TextCard textCard = new TextCardMessage.TextCard();
|
||||
textCard.setTitle("设备掉线通知");
|
||||
// 使用当前时间格式化字符串
|
||||
String formattedCurrentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
// 设置卡片的描述信息,包含设备的详细掉线通知
|
||||
textCard.setDescription("<div class='gray'>设备信息</div>" +
|
||||
"<div class='highlight'>品牌: " + deviceInfoDAO.getDeviceBrand() + "</div>" +
|
||||
"<div class='highlight'>设备型号: " + deviceInfoDAO.getDeviceModel() + "</div>" +
|
||||
"<div class='highlight'>安卓版本: " + deviceInfoDAO.getAndroidVersion() + "</div>" +
|
||||
"<div class='highlight'>SN: " + deviceInfoDAO.getSN() + "</div>" +
|
||||
"<div class='highlight'>监测到掉线时间: " + formattedCurrentTime + "</div>" +
|
||||
"<div class='highlight'>备注: " + deviceInfoDAO.getRemark() + "</div>" +
|
||||
"检测到设备已掉线,请及时查看设备状态.");
|
||||
textCard.setUrl("https://kimgo.cn");
|
||||
// 将TextCard对象设置到TextCardMessage中
|
||||
// 将构建的TextCard对象设置到TextCardMessage中
|
||||
textCardMessage.setTextcard(textCard);
|
||||
|
||||
// 记录文本卡片消息的内容
|
||||
logger.info("TextCardMessage: {}", textCardMessage);
|
||||
|
||||
return textCardMessage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新设备的状态信息。
|
||||
*
|
||||
* @param device 设备信息对象,包含需要更新的设备的SN(序列号)。
|
||||
* @param status 需要更新到的新状态。
|
||||
* @throws DatabaseUpdateException 如果数据库更新过程中发生异常,则抛出此异常。
|
||||
*/
|
||||
private void updateStatus(DeviceInfoDAO device, int status) throws DatabaseUpdateException {
|
||||
try {
|
||||
// 构建更新条件,设置更新的状态值
|
||||
UpdateWrapper<DeviceInfoDAO> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("SN", device.getSN());
|
||||
updateWrapper.set("status", status);
|
||||
|
||||
// 执行更新操作
|
||||
int result = deviceInfoDAOMapper.update(null, updateWrapper);
|
||||
// 根据更新结果进行日志记录
|
||||
if (result > 0) {
|
||||
logger.debug("Update successful for SN: " + device.getSN());
|
||||
} else {
|
||||
logger.warn("Update failed: No rows affected for SN: " + device.getSN());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 捕获异常,记录错误日志,并抛出数据库更新异常
|
||||
logger.error("Error updating status for SN: " + device.getSN(), e);
|
||||
throw new DatabaseUpdateException("update to mysql error.",e);
|
||||
throw new DatabaseUpdateException("update to mysql error.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,11 +32,13 @@ public class QyWeChatURLService {
|
|||
QueryWrapper<QyWeChatURL> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("phone_number", phoneNumberToSearch);
|
||||
QyWeChatURL result = qyWeChatURLMapper.selectOne(wrapper);
|
||||
if (result == null){
|
||||
if (result != null){
|
||||
logger.error("queryURL error");
|
||||
logger.info("queryURL result: {}",result);
|
||||
sendTextCardMessageUrl = result.getSendTextCardMessageUrl();
|
||||
qyWechatGetTokenUrl = result.getQyWechatGetTokenUrl();
|
||||
} else {
|
||||
logger.error("queryURL error.");
|
||||
}
|
||||
logger.info("queryURL result: {}",result.toString());
|
||||
sendTextCardMessageUrl = result.getSendTextCardMessageUrl();
|
||||
qyWechatGetTokenUrl = result.getQyWechatGetTokenUrl();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="FILE"/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue