Commit da3ddf46 authored by renandong's avatar renandong 🇨🇳

1,增加根据别名和cid单推接口

2,增加回调接口
3,增加短信发送,验签等配置
parent 12d8ce20
package com.weface.code;
public class CommonResult<T> {
private long code;
private Integer code;
private String message;
private T data;
protected CommonResult() {
}
protected CommonResult(long code, String message) {
protected CommonResult(Integer code, String message) {
this.code = code;
this.message = message;
}
protected CommonResult(long code, String message, T data) {
protected CommonResult(Integer code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
......@@ -100,11 +100,11 @@ public class CommonResult<T> {
return new CommonResult<T>(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data);
}
public long getCode() {
public Integer getCode() {
return code;
}
public void setCode(long code) {
public void setCode(Integer code) {
this.code = code;
}
......
......@@ -5,7 +5,7 @@ package com.weface.code;
* Created by martin on 2019/7/16.
*/
public interface IErrorCode {
long getCode();
Integer getCode();
String getMessage();
}
......@@ -5,16 +5,21 @@ public enum ResultCode implements IErrorCode {
FAILED(500, "操作失败"),
VALIDATE_FAILED(404, "参数检验失败"),
UNAUTHORIZED(401, "暂未登录或token已经过期"),
PARAMS_ERROR(40001, "参数错误不能为空"),
NOT_SIGN_ERROR(50003, "签名信息不可为空"),
REQUEST_EXPIRE_ERROR(50004, "请求已过期"),
CANNOT_ANALYSIS_PARAM_ERROR(50005, "无法解析的请求参数"),
SIGN_VALID_FAIL_ERROR(50006, "签名校验失败"),
FORBIDDEN(403, "没有相关权限");
private long code;
private String message;
private final Integer code;
private final String message;
private ResultCode(long code, String message) {
private ResultCode(Integer code, String message) {
this.code = code;
this.message = message;
}
public long getCode() {
public Integer getCode() {
return code;
}
......
package com.weface.common.utils;
import org.apache.commons.codec.digest.DigestUtils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
......@@ -88,4 +90,13 @@ public class Base64Util {
encodeStr = byte2Hex(instance.digest());
return encodeStr;
}
/**
* md5加密
*
* @param str 字符串
* @return 加密后结果
*/
public static String md5Encode(String str) {
return DigestUtils.md5Hex(str);
}
}
package com.weface.common.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.distance.DistanceUtils;
import org.locationtech.spatial4j.shape.Rectangle;
import org.springframework.util.AntPathMatcher;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
/**
* @author Administrator
*/
public class CommonUtil {
private static final SpatialContext SPATIAL_CONTEXT = SpatialContext.GEO;
/**
* 判断字符串是否Base64字符串
*/
public static boolean isBase64(String str) {
if (str == null || "".equals(str)) {
return false;
}
String reg = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
return Pattern.matches(reg, str);
}
/**
* 将一个集合平均分成n组
*/
public static <T> List<List<T>> averageAssign(List<T> source, int n) {
List<List<T>> result = new ArrayList<>();
//(先计算出余数)
int remainder = source.size() % n;
//然后是商
int number = source.size() / n;
//偏移量
int offset = 0;
for (int i = 0; i < n; i++) {
List<T> value;
if (remainder > 0) {
value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
remainder--;
offset++;
} else {
value = source.subList(i * number + offset, (i + 1) * number + offset);
}
result.add(value);
}
return result;
}
/**
* 将一个集合分成若干组,每组n个元素
*/
public static <T> List<List<T>> fixedGrouping(List<T> source, int n) {
if (null == source || source.size() == 0 || n <= 0) {
return null;
}
List<List<T>> result = new ArrayList<>();
int remainder = source.size() % n;
int size = (source.size() / n);
for (int i = 0; i < size; i++) {
List<T> subset;
subset = source.subList(i * n, (i + 1) * n);
result.add(subset);
}
if (remainder > 0) {
List<T> subset = source.subList(size * n, size * n + remainder);
result.add(subset);
}
return result;
}
/**
* 对实体类的某些字段进行加密
*
* @param t 实体类
* @param encryptFun 加密的方法
* @param fieldNames 要加密的字段数组
* @param <T> TT
* @return T
*/
public static <T> T encryptEntity(T t, Function<String, String> encryptFun, String[] fieldNames) {
for (String name : fieldNames) {
Class<?> clazz = t.getClass();
try {
Field field = clazz.getDeclaredField(name);
Class<?> fileType = field.getType();
//加密的字段,数据类型 必须是String
if (fileType == String.class) {
//设置字段为可操作
field.setAccessible(true);
String value = (String) field.get(t);
if (value == null) {
continue;
}
String encryptValue = encryptFun.apply(value);
//赋值为加密后的字段
field.set(t, encryptValue);
field.setAccessible(false);
}
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
return t;
}
/**
* 对实体类的某些字段进行解码
*
* @param t 实体类对象
* @param decryptFun 解码的方法
* @param fieldNames 解码的字段数组
* @param <T> TT
* @return T
*/
public static <T> T decryptEntity(T t, Function<String, String> decryptFun, String[] fieldNames) {
for (String name : fieldNames) {
Class<?> clazz = t.getClass();
try {
Field field = clazz.getDeclaredField(name);
Class<?> fileType = field.getType();
//加密的字段,数据类型 必须是String
if (fileType == String.class) {
//设置字段为可操作
field.setAccessible(true);
String value = (String) field.get(t);
//如果是base64,(加密后的数据时base字符串),再进行解码
if (value != null && isBase64(value)) {
String decryptStr = decryptFun.apply(value);
//赋值为加密后的字段
field.set(t, decryptStr);
}
field.setAccessible(false);
}
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
return t;
}
/**
* 签名的规则:sk + 所有非空参数值拼接 + sk
*
* @param param 所有请求参数
* @return sign 签名
*/
public static String apiParamSign(Map<String, Object> param, String sk) {
TreeMap<String, Object> map = new TreeMap<>(param);
StringBuilder builder = new StringBuilder();
builder.append(sk);
map.forEach((k, v) -> {
if (v != null && !"null".equals(v) && !"".equals(v)) {
builder.append(v);
}
});
builder.append(sk);
return SecureUtil.md5(builder.toString());
}
/**
* 调用百度接口,获取地址信息的经纬度
*
* @param address 地址信息
* @return double[] 0经度 1纬度
*/
public static double[] getAxisByAddress(String address) {
String url = "http://api.map.baidu.com/geocoding/v3/?address=%s&ret_coordtype=wgs84ll&output=json&ak=b9kvzxPGvOxvcPllM9P7s81C85bKQPgE";
String request = String.format(url, address);
JSONObject jsonObject = JSONUtil.parseObj(HttpUtil.get(request));
if (jsonObject.getInt(Constant.STATUS) == 0) {
JSONObject location = jsonObject.getJSONObject("result").getJSONObject("location");
Double lng = location.getDouble("lng");
Double lat = location.getDouble("lat");
return new double[]{lng, lat};
}
return null;
}
/**
* 利用开源库计算外接正方形坐标
*
* @param distance 距离,单位千米
* @param userLng 当前经度
* @param userLat 当前纬度
* @return 返回正方形坐标
*/
public static Rectangle getRectangle(double distance, double userLng, double userLat) {
return SPATIAL_CONTEXT.getDistCalc()
.calcBoxByDistFromPt(SPATIAL_CONTEXT.getShapeFactory().pointXY(userLng, userLat),
distance * DistanceUtils.KM_TO_DEG, SPATIAL_CONTEXT, null);
}
/***
* 球面中,两点间的距离(第三方库方法)
*
* @param longitude 经度1
* @param latitude 纬度1
* @param userLng 经度2
* @param userLat 纬度2
* @return 返回距离,单位km
*/
public static double getDistance(Double longitude, Double latitude, double userLng, double userLat) {
return SPATIAL_CONTEXT.calcDistance(SPATIAL_CONTEXT.getShapeFactory().pointXY(userLng, userLat),
SPATIAL_CONTEXT.getShapeFactory().pointXY(longitude, latitude)) * DistanceUtils.DEG_TO_KM;
}
/**
* * 判断一个字符串是否为空串
*
* @param str String
* @return true:为空 false:非空
*/
public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
/**
* * 判断一个Collection是否为空, 包含List,Set,Queue
*
* @param coll 要判断的Collection
* @return true:为空 false:非空
*/
public static boolean isEmpty(Collection<?> coll) {
return coll == null || coll.isEmpty();
}
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs) {
if (isEmpty(str) || isEmpty(strs)) {
return false;
}
for (String pattern : strs) {
if (isMatch(pattern, str)) {
return true;
}
}
return false;
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串,不可跨层级;
* ** 表示任意层路径;
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return boolean 是否匹配
*/
public static boolean isMatch(String pattern, String url) {
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
/**
* 获取真实ip地址,避免获取代理ip
*/
public static String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || Constant.UN_KNOW.equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || Constant.UN_KNOW.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || Constant.UN_KNOW.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || Constant.UN_KNOW.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || Constant.UN_KNOW.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || Constant.UN_KNOW.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
/**
* 加密ID和手机号
*
* @param uid uid
* @param tel 手机号
* @return 密文
*/
public static String encryptIdAndTel(String uid, String tel) {
//kkv+id+ 手机号码后五位+手机号码第六位+手机号码前五位
try {
String prefix = "kkv";
String sub1 = StrUtil.sub(tel, 0, 5);
String sub2 = StrUtil.sub(tel, 5, 6);
String sub3 = StrUtil.sub(tel, 6, 11);
return prefix + uid + sub3 + sub2 + sub1;
} catch (Exception e) {
return null;
}
}
/**
* 解析ID和手机号
*
* @param encryptStr 密文
* @return 明文
*/
public static String[] decryptIdAndTel(String encryptStr) {
//kkv+id+ 手机号码后五位+手机号码第六位+手机号码前五位
try {
String prefix = "kkv";
int length = encryptStr.length();
String hexTel = encryptStr.substring(length - 11, length);
String sub1 = StrUtil.sub(hexTel, 0, 5);
String sub2 = StrUtil.sub(hexTel, 5, 6);
String sub3 = StrUtil.sub(hexTel, 6, 11);
String tel = sub3 + sub2 + sub1;
String suffix = StrUtil.subAfter(encryptStr, prefix, true);
String uid = StrUtil.sub(suffix, 0, suffix.length() - 11);
String[] arr = new String[2];
arr[0] = uid;
arr[1] = tel;
return arr;
} catch (Exception e) {
return null;
}
}
}
package com.weface.common.utils;
/**
* 系统参数相关Key
*
* @author Mark sunlightcs@gmail.com
*/
public class ConfigConstant {
/**
* 云存储配置KEY
*/
public final static String CLOUD_STORAGE_CONFIG_KEY = "CLOUD_STORAGE_CONFIG_KEY";
}
......@@ -28,90 +28,49 @@ public class Constant {
* 升序
*/
public static final String ASC = "asc";
/**
* 菜单类型
*
* @author chenshun
* @date 2016年11月15日 下午1:24:29
*/
public enum MenuType {
/**
* 目录
*/
CATALOG(0),
/**
* 菜单
*/
MENU(1),
/**
* 按钮
*/
BUTTON(2);
private int value;
MenuType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
* 定时任务状态
*
* @author chenshun
* @date 2016年12月3日 上午12:07:22
* DES密钥
*/
public enum ScheduleStatus {
/**
* 正常
*/
NORMAL(0),
/**
* 暂停
*/
PAUSE(1);
private int value;
ScheduleStatus(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public static final String DES_KEY = "Kkweface55389527";
/**
* 状态
*/
public static final String STATUS = "status";
/**
*unknown
*/
public static final String UN_KNOW = "unknown";
/**
*时间戳
*/
public static final String TIME_NAME = "timestamp";
/**
* redis缓存前缀
*/
public static final String PUSH_TASK_INFO = "push_task_info";
/**
* 云服务商
* http 请求
*/
public enum CloudService {
@SuppressWarnings("unused")
public enum MethodType {
/**
* 七牛云
* 请求类型
*/
QINIU(1),
/**
* 阿里云
*/
ALIYUN(2),
/**
* 腾讯云
*/
QCLOUD(3);
GET("GET"),
POST("POST"),
PUT("PUT"),
DELETE("DELETE"),
PATCH("PATCH");
private int value;
private final String value;
CloudService(int value) {
MethodType(String value) {
this.value = value;
}
public int getValue() {
public String getValue() {
return value;
}
}
}
package com.weface.common.utils;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ObjectUtil;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
/**
* @author Administrator
*/
public class DES {
private byte[] desKey;
public DES(String desKey) {
this.desKey = desKey.getBytes();
}
private static DES des;
private DES() {
}
public static DES getInstanceDes() {
if (ObjectUtil.isNull(des)) {
des = new DES(Constant.DES_KEY);
}
return des;
}
/**
* 加密
*
* @param plainText 原文
* @return 密文
* @throws Exception 异常
*/
public byte[] desEncrypt(byte[] plainText) throws Exception {
SecureRandom sr = new SecureRandom();
byte[] rawKeyData = desKey;
DESKeySpec dks = new DESKeySpec(rawKeyData);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
javax.crypto.SecretKey key = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(1, key, sr);
return cipher.doFinal(plainText);
}
/**
* 解密
*
* @param encryptText 密文
* @return 原文
* @throws Exception 异常
*/
public byte[] desDecrypt(byte[] encryptText) throws Exception {
SecureRandom sr = new SecureRandom();
byte[] rawKeyData = desKey;
DESKeySpec dks = new DESKeySpec(rawKeyData);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
javax.crypto.SecretKey key = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(2, key, sr);
return cipher.doFinal(encryptText);
}
/**
* 加密
*
* @param input 原文
* @return 加密后数据
* @throws Exception 异常
*/
public String encrypt(String input) throws Exception {
if (StringUtils.isEmpty(input)) {
return null;
}
return Base64.encode(desEncrypt(input.getBytes(StandardCharsets.UTF_8)));
}
/**
* 解密
*
* @param input 加密数据
* @return 原文
*/
public String decrypt(String input) {
if (StringUtils.isEmpty(input)) {
return null;
}
byte[] result = Base64.decode(input);
try {
if (CommonUtil.isBase64(input)) {
return new String(desDecrypt(result), StandardCharsets.UTF_8);
} else {
return input;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String encrypt2(String input) throws Exception {
return new String(desEncrypt(input.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
}
public String decrypt2(String input) throws Exception {
return new String(desDecrypt(input.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
}
public static void main(String[] args) {
DES des = new DES(Constant.DES_KEY);
String name = des.decrypt("mC8HL+gBKJs=");
String head = des.decrypt("JH2AUKTuP4k4065YeoNoDA==");
System.out.println(name);
System.out.println(head);
}
}
......@@ -5,9 +5,9 @@ import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
......@@ -82,4 +82,27 @@ public class HttpUtil {
}
return flag;
}
/**
* 从请求中拿到请求流数据
*
* @param request 请求
* @return 字节数组
* @throws IOException io异常
*/
public static byte[] getRequestInputStream(HttpServletRequest request) throws IOException {
ServletInputStream input = request.getInputStream();
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int position = 0;
while (true) {
position = input.read(buffer);
if (position == -1) {
break;
}
output.write(buffer, 0, position);
}
return output.toByteArray();
}
}
package com.weface.common.utils;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.weface.config.RedisExpireData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
......@@ -1053,6 +1055,50 @@ public class RedisUtil implements ApplicationContextAware {
log.info("hScan(...) => cursor -> {}", JSON.toJSONString(cursor));
return cursor;
}
/**
* @Description 获取redis hash 带过期时间的数据
* @Param [redisTemplate, redisKey, hashKey]
* @Return java.lang.String
*/
/**
* 获取redis hash 带过期时间的数据
*
* @param redisKey redisKey
* @param hashKey hashKey
* @return obj
*/
public static Object hGetEx(String redisKey, String hashKey) {
Object hashValue = hGet(redisKey, hashKey);
if (hashValue == null) {
return null;
}
RedisExpireData redisData = JSONUtil.toBean(hashValue.toString(), RedisExpireData.class);
if (redisData == null) {
return null;
} else {
Object obj = redisData.getStoreData();
if (obj == null) {
hDelete(redisKey, hashKey);
}
return obj;
}
}
/**
* 设置带过期时间的redis hash
*
* @param redisKey redis_key
* @param hashKey hash_key
* @param hashValue value
* @param expire 过期时间
* @param timeUnit 时间类型
*/
public static void hPutEx(String redisKey, String hashKey, Object hashValue, Long expire, TimeUnit timeUnit) {
RedisExpireData redisData = new RedisExpireData(hashValue, timeUnit.toMillis(expire));
hPut(redisKey, hashKey, JSONUtil.toJsonStr(redisData));
}
}
/**
......
package com.weface.common.utils;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 短信发送操作类
*/
@Slf4j
public class ShortMsgSend {
/**
* 看看社保
*/
//static String url = "http://114.55.5.4/hy/";
//static String uid = "90062";
//static String auth = "ec7fa119ecc34b385549e8e154e5bdd5";
/**
* 看看生活
*/
// private static final String url = "http://submit.10690221.com:9012/hy/";
// private static final String uid = "90063";
// private static final String auth = "c4daa5fe21eabe16a765eefe0573dbdf";
public static boolean sendMobileByRegister(String paramContent, String telPhone, Integer messageTemplate) throws IOException {
String url = null;
String uid = null;
String auth = null;
switch (messageTemplate) {
//看看生活
case 1:
url = "http://submit.10690221.com:9012/hy/";
uid = "90063";
auth = "c4daa5fe21eabe16a765eefe0573dbdf";
break;
//看看社保
case 2:
url = "http://114.55.5.4/hy/";
uid = "90062";
auth = "ec7fa119ecc34b385549e8e154e5bdd5";
break;
default:
break;
}
if (url == null) {
log.error("短信模板参数错误:{}", messageTemplate);
return false;
}
return sendMobileByRegister(paramContent, telPhone, url, uid, auth);
}
private static boolean sendMobileByRegister(String paramContent, String telPhone, String url, String uid, String auth) throws IOException {
String content = java.net.URLEncoder.encode(paramContent, "gbk");
Map<String, Object> map = new HashMap<>();
map.put("uid", uid);
map.put("auth", auth);
map.put("mobile", telPhone);
map.put("expid", "0");
map.put("msg", content);
HttpRequest post = HttpUtil.createPost(url);
HttpResponse execute = post.form(map).execute();
int status = execute.getStatus();
if (status == 200) {
String postResult = execute.body();
log.error("{}的短信发生结果:{}", telPhone, postResult);
System.out.println(postResult);
try {
return postResult.split(",")[0].equals("0");
} catch (Exception e) {
return false;
}
} else {
return false;
}
}
/*
* 功能描述:
* @auther: 信息
* @date: 2018/12/24 17:30
*/
public static String Mesresult = "请您于6月10日之前,通过“看看卫健”软件,完成高龄补贴资格认证,每年3月、6月、9月、12月的1-10日为认证时间,不认证将停发或终止补贴";
public static void main(String[] args) {
String telphone = "15538250098";
String msg = "尊敬的用户,请尽快完成社保认证,领取养老金。认证下载链接http://dwz.date/eHEH";
System.out.println(msg.length());
try {
boolean sabeResult = sendMobileByRegister(msg, telphone, 1);
if (sabeResult) {
System.out.println("短信发送成功");
} else {
System.out.println("短信发送失败");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
package com.weface.common.validator;
import com.weface.code.CommonResult;
import com.weface.code.ResultCode;
import com.weface.dto.InformForm;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
/**
* @author : Administrator
* @date : 2022/4/21 14:28
*/
public class ValidatorParam {
public static CommonResult validPushSingleAlias(InformForm informForm) {
Integer pushType = informForm.getPushType();
if (pushType != null && pushType == 1) {
String className = informForm.getClassName();
String classTitle = informForm.getClassTitle();
String needLogin = informForm.getNeedLogin();
if (StringUtils.isEmpty(className) || StringUtils.isEmpty(classTitle) || StringUtils.isEmpty(needLogin)) {
return CommonResult.failed(ResultCode.PARAMS_ERROR);
}
}
String[] cid = informForm.getCid();
String phone = informForm.getPhone();
Integer messageTemplate = informForm.getMessageTemplate();
if (ArrayUtils.isEmpty(cid) || StringUtils.isEmpty(phone) || messageTemplate == null) {
return CommonResult.failed(ResultCode.PARAMS_ERROR);
}
return null;
}
}
......@@ -321,7 +321,7 @@ public class GeTuiService {
JSONObject data = jsonObject.getJSONObject("data");
if (data != null) {
//保存单推结果
pushLogService.saveLog(data, null, null);
pushLogService.saveLog(data, informForm, appId);
}
return CommonResult.success(data);
}
......@@ -340,7 +340,7 @@ public class GeTuiService {
*/
public CommonResult pushSingleAlias(InformForm informForm) {
try {
log.error("单推参数:{}",informForm);
log.error("单推参数:{}", informForm);
String type = informForm.getEquipmentType();
String appId = getAppId(type);
String pushToken = getPushToken(type);
......@@ -355,7 +355,7 @@ public class GeTuiService {
String url = GE_TUI_BASE_URL + appId + "/push/single/alias";
log.info("执行别名单推");
String result = generalPost(url, pushToken, map);
log.error("推送结果:{}",result);
log.error("推送结果:{}", result);
if (StringUtils.isEmpty(result)) {
return CommonResult.failed();
}
......@@ -364,7 +364,7 @@ public class GeTuiService {
JSONObject data = jsonObject.getJSONObject("data");
if (data != null) {
//保存单推结果
pushLogService.saveLog(data, informForm.getPhone(), informForm.getMessageTemplate());
pushLogService.saveLog(data, informForm, appId);
}
return CommonResult.success();
}
......@@ -406,7 +406,7 @@ public class GeTuiService {
JSONObject data = jsonObject.getJSONObject("data");
if (data != null) {
//保存单推结果
pushLogService.saveLog(data, informForm.getPhone(), informForm.getMessageTemplate());
pushLogService.saveLog(data, informForm, appId);
}
return CommonResult.success();
}
......
......@@ -6,6 +6,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
import java.util.HashMap;
import java.util.Map;
/**
* Filter配置
......@@ -16,8 +18,8 @@ import javax.servlet.DispatcherType;
public class FilterConfig {
@Bean
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
public FilterRegistrationBean<XssFilter> xssFilterRegistration() {
FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
......@@ -25,4 +27,25 @@ public class FilterConfig {
registration.setOrder(Integer.MAX_VALUE);
return registration;
}
/**
* 注册 签名校验过滤器
*/
@Bean
public FilterRegistrationBean<SignValidateFilter> signValidateFilter() {
final String include = "/push/single/alias,/push/single/aliascid";
//不拦截的url列表
final String excludes = "";
//拦截url列表
FilterRegistrationBean<SignValidateFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new SignValidateFilter());
bean.setName("signValidateFilter");
//设置拦截的url
bean.addUrlPatterns(include.split(","));
//设置不拦截
Map<String, String> initParameters = new HashMap<>(1);
initParameters.put("excludes", excludes);
bean.setInitParameters(initParameters);
return bean;
}
}
package com.weface.config;
import cn.hutool.core.io.IoUtil;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
/**
* @author Aleyn
* 1.重复获取HttpServletRequest中的inputStream 用以获取json请求参数
* 2.请求参数为二进制数据,controller无法正常映射,需要重写参数
* @since 2021/11/19 16:00
*/
public class OnceRequestWrapper extends HttpServletRequestWrapper {
/**
* json请求参数
*/
private final String body;
/**
* Map参数
*/
private final Map<String, String[]> params = new HashMap<>();
public OnceRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
this.body = getJsonBody(request);
//将参数表,赋予给当前的Map以便于持有request中的参数
this.params.putAll(request.getParameterMap());
}
/**
* 重载构造方法
*/
public OnceRequestWrapper(HttpServletRequest request, Map<String, Object> extendParams) throws IOException {
this(request);
//这里将扩展参数写入参数表
addAllParameters(extendParams);
}
private String getJsonBody(HttpServletRequest request) throws IOException {
String body;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IoUtil.copy(request.getInputStream(), baos);
body = baos.toString();
return body;
}
/**
* @return ServletInputStream 重写getInputStream()
*/
@Override
public ServletInputStream getInputStream() {
//每次调用此方法时将数据流中的数据读取出来,然后再回填到InputStream之中
//解决通过@RequestBody和@RequestParam(POST方式)读取一次后控制器拿不到参数问题
final ByteArrayInputStream bais = new ByteArrayInputStream(this.body.getBytes());
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
@Override
public int read() {
return bais.read();
}
};
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
/**
* 在获取所有的参数名,必须重写此方法,否则对象中参数值映射不上
*/
@Override
public Enumeration<String> getParameterNames() {
return new Vector(params.keySet()).elements();
}
/**
* 重写getParameter方法
*
* @param name 参数名
* @return 返回参数值
*/
@Override
public String getParameter(String name) {
String[] values = params.get(name);
if (values == null || values.length == 0) {
return null;
}
return values[0];
}
@Override
public String[] getParameterValues(String name) {
String[] values = params.get(name);
if (values == null || values.length == 0) {
return null;
}
return values;
}
/**
* 增加多个参数
*
* @param otherParams 增加的多个参数
*/
public void addAllParameters(Map<String, Object> otherParams) {
for (Map.Entry<String, Object> entry : otherParams.entrySet()) {
addParameter(entry.getKey(), entry.getValue());
}
}
/**
* 增加参数
*
* @param name 参数名
* @param value 参数值
*/
public void addParameter(String name, Object value) {
if (value != null) {
if (value instanceof String[]) {
params.put(name, (String[]) value);
} else if (value instanceof String) {
params.put(name, new String[]{(String) value});
} else {
params.put(name, new String[]{String.valueOf(value)});
}
}
}
}
package com.weface.config;
import java.io.Serializable;
/**
* @author : Administrator
* @date : 2022/4/21 10:58
*/
public class RedisExpireData implements Serializable {
private static final long serialVersionUID = 1L;
private Object storeData;
private Long expire;
private Long dataTime;
public RedisExpireData(Object data, Long expire) {
this.storeData = data;
this.expire = expire;
this.dataTime = System.currentTimeMillis();
}
/**
* 获取对应的expire数据
*
* @return java.lang.String
*/
public Object getStoreData() {
Long curr = System.currentTimeMillis();
if (curr - this.dataTime > this.expire) {
return null;
} else {
return this.storeData;
}
}
public void setStoreData(Object storeData) {
this.storeData = storeData;
}
public Long getExpire() {
return expire;
}
public void setExpire(Long expire) {
this.expire = expire;
}
public Long getDataTime() {
return dataTime;
}
public void setDataTime(Long dataTime) {
this.dataTime = dataTime;
}
}
package com.weface.config;
import cn.hutool.json.JSONUtil;
import com.weface.code.CommonResult;
import com.weface.code.ResultCode;
import com.weface.common.utils.CommonUtil;
import com.weface.common.utils.Constant;
import com.weface.common.utils.IPUtils;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.FilterConfig;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
/**
* @author Aleyn
* @since 2021/11/20 13:00
*/
@Slf4j
public class SignValidateFilter implements Filter {
/**
* 参数签名过期时间 2分钟
*/
public static final long EXPIRE_TIME = 1000 * 60 * 2;
public static final String TIME_NAME = "timestamp";
public static final String SIGN_NAME = "sign";
public static final String SECRET_KEY = "KkweFace95271125";
/**
* 排除链接
*/
public List<String> excludes = new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) {
log.info("初始化filter");
//不拦截的部分
String tempExcludes = filterConfig.getInitParameter("excludes");
if (!CommonUtil.isEmpty(tempExcludes)) {
String[] url = tempExcludes.split(",");
excludes.addAll(Arrays.asList(url));
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
corsConfig(response);
String ipAddr = IPUtils.getIpAddr(request);
log.info("调用了{}", request.getServletPath() + "方法");
log.info("请求IP地址为:{}", ipAddr);
//不拦截的
if (handleExcludeUrl(request)) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
//进行签名校验
checkParamAndSign(request, response, filterChain);
}
}
/**
* 设置允许跨域
*
* @param response 响应头
*/
private void corsConfig(HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "*");
//这里“Access-Token”是我要传到后台的内容key
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Expose-Headers", "*");
}
/**
* 签名校验
*/
public void checkParamAndSign(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
String timestamp = request.getHeader(TIME_NAME);
String sign = request.getHeader(SIGN_NAME);
if (CommonUtil.isEmpty(timestamp) || CommonUtil.isEmpty(sign)) {
this.fail(response, ResultCode.NOT_SIGN_ERROR);
return;
}
long now = System.currentTimeMillis();
if (now - (Long.parseLong(timestamp)) > EXPIRE_TIME) {
this.fail(response, ResultCode.REQUEST_EXPIRE_ERROR);
return;
}
Map<String, Object> param = new HashMap<>();
param.put(TIME_NAME, timestamp);
//请求类型
String contentType = request.getContentType() == null ? "" : request.getContentType().trim().toLowerCase();
//json参数
boolean isJson = contentType.contains("application/json");
//iso中使用application/x-www-form-urlencoded请求时,参数会转为multipart/form-data模式
boolean isMultiPart = contentType.contains("multipart/form-data");
OnceRequestWrapper requestWrapper = null;
if (isJson) {
requestWrapper = new OnceRequestWrapper(request);
//获取参数
String body = requestWrapper.getBody();
if (!CommonUtil.isEmpty(body)) {
if (JSONUtil.isJson(body)) {
Map<String, Object> bodyMap = JSONUtil.toBean(body, Map.class);
param.putAll(bodyMap);
} else {
//请求参数不是json
fail(response, ResultCode.CANNOT_ANALYSIS_PARAM_ERROR);
}
}
} else if (isMultiPart) {
String data = request.getParameter("Data");
if (data != null && JSONUtil.isJson(data)) {
//参数转为map
Map map = JSONUtil.parseObj(data).toBean(Map.class);
param.putAll(map);
requestWrapper = new OnceRequestWrapper(request, param);
}
} else {
//其他参数
Enumeration<String> names = request.getParameterNames();
Map<String, Object> parameterMap = new HashMap<>();
while (names.hasMoreElements()) {
String element = names.nextElement();
String value = request.getParameter(element);
parameterMap.put(element, value);
}
param.putAll(parameterMap);
}
if (CommonUtil.apiParamSign(param, SECRET_KEY).equals(sign)) {
if (isJson | isMultiPart) {
filterChain.doFilter(requestWrapper, response);
} else {
filterChain.doFilter(request, response);
}
} else {
fail(response, ResultCode.SIGN_VALID_FAIL_ERROR);
}
}
private boolean handleExcludeUrl(HttpServletRequest request) {
String url = request.getServletPath();
String method = request.getMethod();
// GET DELETE 不过滤
if (method == null || method.matches(Constant.MethodType.GET.getValue()) || method.matches(Constant.MethodType.DELETE.getValue())) {
return true;
}
return CommonUtil.matches(url, excludes);
}
@Override
public void destroy() {
log.info("销毁filter");
}
public void fail(ServletResponse response, ResultCode code) {
response.setContentType("application/json;charset=UTF-8");
CommonResult<Object> failed = CommonResult.failed(code);
try {
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(JSONUtil.toJsonStr(failed).getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
log.error(e.getMessage());
}
}
}
......@@ -8,7 +8,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author : Administrator
......@@ -22,7 +21,7 @@ public class PushCallBackController {
private PushCallBackService pushCallBackService;
@PostMapping("/call/back/info")
public PushResultCode callBackForPush(HttpServletRequest request) throws IOException {
public PushResultCode callBackForPush(HttpServletRequest request) {
return pushCallBackService.saveCallBackInfo(request);
}
......
package com.weface.controller;
import com.weface.code.CommonResult;
import com.weface.common.validator.ValidatorParam;
import com.weface.component.GeTuiService;
import com.weface.dto.InformForm;
import com.weface.dto.MsgDTO;
......@@ -45,11 +46,19 @@ public class PushController {
@PostMapping("/single/alias")
public CommonResult pushSingleAlias(@Validated({Default.class}) InformForm informForm) {
CommonResult commonResult = ValidatorParam.validPushSingleAlias(informForm);
if (commonResult != null) {
return commonResult;
}
return geTuiService.pushSingleAlias(informForm);
}
@PostMapping("/single/cid")
public CommonResult pushSingleCid(@Validated({Default.class}) InformForm informForm) {
CommonResult commonResult = ValidatorParam.validPushSingleAlias(informForm);
if (commonResult != null) {
return commonResult;
}
return geTuiService.pushSingleCid(informForm);
}
}
......@@ -3,14 +3,22 @@ package com.weface.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.weface.entity.PushLogEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
*
*
* @author admin
* @date 2022-04-20 09:54:09
*/
@Mapper
public interface PushLogDao extends BaseMapper<PushLogEntity> {
/**
* 根据时间查询推送日志
*
* @param time 时间
* @return 推送日志
*/
List<PushLogEntity> getPushLogByTime(@Param("time") Integer time);
}
......@@ -45,7 +45,7 @@ public class PushCallBackEntity implements Serializable {
/**
* 推送结果描述
*/
private String desc;
private String descStr;
/**
* 签名
*/
......
......@@ -7,59 +7,69 @@ import java.io.Serializable;
import java.util.Date;
/**
*
*
* @author admin
* @date 2022-04-20 09:54:09
*/
@Data
@TableName("tb_push_log")
public class PushLogEntity implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String taskId;
/**
*
*/
private String cid;
/**
*
*/
private String cidStatus;
/**
*
*/
private String phone;
/**
*
*/
private Integer messageTemplate;
/**
*
*/
private Integer isArrive;
/**
*
*/
@TableLogic(value = "1", delval = "0")
@TableField(fill = FieldFill.INSERT)
private Integer isValid;
/**
*
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
*
*/
private Date updateTime;
/**
*
*/
@TableId
private Long id;
/**
* 应用名称
*/
private String appName;
/**
* 任务id
*/
private String taskId;
/**
* 推送内容
*/
private String result;
/**
* 目标手机号
*/
private String phone;
/**
* 推送的短信模板
*/
private Integer messageTemplate;
/**
* 推送目标(别名/cid)
*/
private String pushTarget;
/**
* 推送内容
*/
private String pushContent;
/**
* 到达状态 1001:已推送 1002:已到达 1003:已发送短信
*/
private Integer arriveStatus;
/**
* 备用字段
*/
private String bas1;
/**
* 逻辑删除 1:未删除 0:删除
*/
@TableLogic(value = "1", delval = "0")
@TableField(fill = FieldFill.INSERT)
private Integer isValid;
/**
*
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
*
*/
private Date updateTime;
}
......@@ -2,16 +2,40 @@ package com.weface.service;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.IService;
import com.weface.dto.InformForm;
import com.weface.entity.PushLogEntity;
import java.util.List;
/**
* @author admin
* @email admin@163.com
* @date 2022-04-20 09:54:09
*/
public interface PushLogService extends IService<PushLogEntity> {
public void saveLog(JSONObject data, String phone, Integer messageTemplate);
/**
* 保存日志
*
* @param data 返回数据
* @param informForm 推送数据
* @param appId 应用id
*/
public void saveLog(JSONObject data, InformForm informForm, String appId);
/**
* 查询日志
*
* @param taskId 任务id
* @return 日志信息
*/
public PushLogEntity getPushLog(String taskId);
/**
* 查询推送日志
*
* @param time 时间
* @return 推送日志
*/
public List<PushLogEntity> getPushLogByTime(Integer time);
}
......@@ -3,28 +3,28 @@ package com.weface.serviceimpl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weface.code.PushResultCode;
import com.weface.common.utils.SnowIdUtil;
import com.weface.common.utils.*;
import com.weface.config.GeTuiApp;
import com.weface.config.GeTuiConfig;
import com.weface.dao.PushCallBackDao;
import com.weface.entity.PushCallBackEntity;
import com.weface.entity.PushLogEntity;
import com.weface.service.PushCallBackService;
import com.weface.service.PushLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author : Administrator
......@@ -37,6 +37,8 @@ public class PushCallBackServiceImpl extends ServiceImpl<PushCallBackDao, PushCa
@Resource
private GeTuiApp geTuiApp;
@Autowired
private PushLogService pushLogService;
/**
* 保存推送回调
......@@ -46,24 +48,37 @@ public class PushCallBackServiceImpl extends ServiceImpl<PushCallBackDao, PushCa
*/
@Override
public PushResultCode saveCallBackInfo(HttpServletRequest request) {
JSONObject jsonObject = new JSONObject();
try {
byte[] bytes = getRequestInputStream(request);
String callInfo = new String(bytes);
PushCallBackEntity callBackInfo = JSONObject.parseObject(callInfo, PushCallBackEntity.class);
String appId = callBackInfo.getAppid();
String str = appId + callBackInfo.getCid() + callBackInfo.getTaskid() + callBackInfo.getMsgid() + getMasterSecret(appId);
String sign = md5Encode(str);
if (!callBackInfo.getSign().equals(sign)) {
List<PushCallBackEntity> list = getCallBackInfo(request);
if (list.isEmpty()) {
return PushResultCode.error();
}
String taskid = callBackInfo.getTaskid();
String cid = callBackInfo.getCid();
callBackInfo.setId(SnowIdUtil.nextId());
callBackInfo.setUpdateTime(new Date());
callBackInfo.setStatus(1);
this.save(callBackInfo);
for (PushCallBackEntity callBackInfo : list) {
String appId = callBackInfo.getAppid();
String taskId = callBackInfo.getTaskid();
String str = appId + callBackInfo.getCid() + taskId + callBackInfo.getMsgid() + getMasterSecret(appId);
String sign = Base64Util.md5Encode(str);
if (!callBackInfo.getSign().equals(sign)) {
return PushResultCode.error();
}
if (taskId.startsWith("RASS")) {
Object hashValue = RedisUtil.HashOps.hGet(Constant.PUSH_TASK_INFO, taskId);
if (hashValue != null) {
PushLogEntity pushLog = pushLogService.getPushLog(taskId);
if (pushLog != null) {
//更新推送日志
pushLog.setArriveStatus(1002);
pushLogService.updateById(pushLog);
log.error("推送回调消息:{}", taskId);
//持久化回调日志
callBackInfo.setId(SnowIdUtil.nextId());
callBackInfo.setUpdateTime(new Date());
callBackInfo.setStatus(1);
this.save(callBackInfo);
}
}
}
}
return PushResultCode.ok();
} catch (IOException e) {
log.error("处理回调函数异常:{}", e.getMessage());
......@@ -72,6 +87,13 @@ public class PushCallBackServiceImpl extends ServiceImpl<PushCallBackDao, PushCa
return PushResultCode.error();
}
/**
* 获取应用密钥
*
* @param appId 应用id
* @return 应用密钥
*/
private String getMasterSecret(String appId) {
String masterSecret = null;
Map<String, GeTuiConfig> apps = geTuiApp.getApps();
......@@ -81,28 +103,33 @@ public class PushCallBackServiceImpl extends ServiceImpl<PushCallBackDao, PushCa
break;
}
}
Assert.notNull(masterSecret, "密钥不能为空");
return masterSecret;
}
public static String md5Encode(String str) {
MessageDigest md = DigestUtils.getMd5Digest();
return Arrays.toString(md.digest(str.getBytes(StandardCharsets.UTF_8)));
}
public static byte[] getRequestInputStream(HttpServletRequest request) throws IOException {
ServletInputStream input = request.getInputStream();
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int position = 0;
while (true) {
position = input.read(buffer);
if (position == -1) {
break;
}
output.write(buffer, 0, position);
/**
* 解析请求数据
*
* @param request 请求
* @return 解析后回调对象
* @throws IOException 网络流异常
*/
public static List<PushCallBackEntity> getCallBackInfo(HttpServletRequest request) throws IOException {
byte[] bytes = HttpUtil.getRequestInputStream(request);
String callBackList = new String(bytes);
Pattern re = Pattern.compile("(\\{.*?})");
Matcher matcher = re.matcher(callBackList);
List<PushCallBackEntity> list = new ArrayList<>();
while (matcher.find()) {
String group = matcher.group(1);
log.info("回调信息:{}", group);
PushCallBackEntity callBackInfo = JSONObject.parseObject(group, PushCallBackEntity.class);
String desc = JSONObject.parseObject(group).getString("desc");
callBackInfo.setDescStr(desc);
list.add(callBackInfo);
}
return output.toByteArray();
return list;
}
}
package com.weface.serviceimpl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weface.common.utils.Constant;
import com.weface.common.utils.DES;
import com.weface.common.utils.RedisUtil;
import com.weface.common.utils.SnowIdUtil;
import com.weface.dao.PushLogDao;
import com.weface.dto.InformForm;
import com.weface.entity.PushLogEntity;
import com.weface.service.PushLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
......@@ -13,43 +19,73 @@ import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Slf4j
@Transactional(rollbackFor = {Exception.class})
@Service("pushLogService")
public class PushLogServiceImpl extends ServiceImpl<PushLogDao, PushLogEntity> implements PushLogService {
@Override
public void saveLog(JSONObject data, String phone, Integer messageTemplate) {
List<PushLogEntity> logList = new ArrayList<>();
for (Map.Entry<String, Object> stringObjectEntry : data.entrySet()) {
String key = stringObjectEntry.getKey();
Object value = stringObjectEntry.getValue();
if (value != null) {
JSONObject jsonObject1 = JSONObject.parseObject(value.toString());
for (Map.Entry<String, Object> objectEntry : jsonObject1.entrySet()) {
String key1 = objectEntry.getKey();
Object value1 = objectEntry.getValue();
PushLogEntity pushLogEntity = new PushLogEntity();
pushLogEntity.setId(SnowIdUtil.nextId());
pushLogEntity.setTaskId(key);
pushLogEntity.setCid(key1);
pushLogEntity.setCidStatus(value1.toString());
pushLogEntity.setPhone(phone);
pushLogEntity.setMessageTemplate(messageTemplate);
pushLogEntity.setIsArrive(0);
pushLogEntity.setIsValid(1);
Date date = new Date();
pushLogEntity.setCreateTime(date);
pushLogEntity.setUpdateTime(date);
logList.add(pushLogEntity);
public void saveLog(JSONObject data, InformForm informForm, String appId) {
try {
List<PushLogEntity> logList = new ArrayList<>();
for (String key : data.keySet()) {
PushLogEntity pushLogEntity = new PushLogEntity();
Long id = SnowIdUtil.nextId();
pushLogEntity.setId(id);
pushLogEntity.setAppName(informForm.getEquipmentType());
pushLogEntity.setTaskId(key);
pushLogEntity.setResult(data.toString());
DES des = DES.getInstanceDes();
pushLogEntity.setPhone(des.encrypt(informForm.getPhone()));
pushLogEntity.setMessageTemplate(informForm.getMessageTemplate());
StringBuilder sb = new StringBuilder();
for (String target : informForm.getCid()) {
sb.append(target).append(",");
}
pushLogEntity.setPushTarget(sb.toString());
pushLogEntity.setPushContent(informForm.getBody());
pushLogEntity.setArriveStatus(1001);
pushLogEntity.setUpdateTime(new Date());
logList.add(pushLogEntity);
RedisUtil.HashOps.hPutEx(Constant.PUSH_TASK_INFO, key, String.valueOf(id), 2L, TimeUnit.HOURS);
}
if (!CollectionUtils.isEmpty(logList)) {
this.saveBatch(logList);
}
} catch (Exception e) {
log.error("保存推送日志错误:{}", e.getMessage());
e.printStackTrace();
}
if (!CollectionUtils.isEmpty(logList)) {
this.saveBatch(logList);
}
/**
* 查询日志
*
* @param taskId 任务id
* @return 日志信息
*/
@Override
public PushLogEntity getPushLog(String taskId) {
List<PushLogEntity> list = this.list(new LambdaQueryWrapper<PushLogEntity>()
.eq(PushLogEntity::getTaskId, taskId));
if (!CollectionUtils.isEmpty(list)) {
return list.get(0);
} else {
return null;
}
}
/**
* 查询推送日志
*
* @param time 时间
* @return 推送日志
*/
@Override
public List<PushLogEntity> getPushLogByTime(Integer time) {
return this.baseMapper.getPushLogByTime(time);
}
}
\ No newline at end of file
package com.weface.task;
import cn.hutool.core.collection.CollUtil;
import com.weface.common.utils.RedisUtil;
import cn.hutool.json.JSONUtil;
import com.weface.common.utils.*;
import com.weface.component.MenuService;
import com.weface.config.RedisExpireData;
import com.weface.entity.MenuTagsEntity;
import com.weface.entity.PushLogEntity;
import com.weface.entity.UserMenusEntity;
import com.weface.entity.UserTagEntity;
import com.weface.service.MenuTagsService;
import com.weface.service.PushLogService;
import com.weface.service.UserMenusService;
import com.weface.service.UserTagService;
import lombok.extern.slf4j.Slf4j;
......@@ -17,16 +21,15 @@ import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
/**
* @author Administrator
* @CreateUser: Administrator
* @CreateTime: 2021/11/4
*/
@Component
......@@ -51,6 +54,73 @@ public class UserTagsTask {
@Autowired
private ThreadPoolTaskExecutor asyncServiceExecutor;
@Autowired
private PushLogService pushLogService;
/**
* 查询推送日志时间
*/
private static final Integer TIME = 2;
@Scheduled(cron = "0 0 0/1 * * ? ")
public void sendMessage() {
try {
log.info("开始执行短信发送任务");
List<PushLogEntity> list = pushLogService.getPushLogByTime(TIME);
List<PushLogEntity> updateBatch = null;
if (!CollectionUtils.isEmpty(list)) {
updateBatch = new ArrayList<>(list.size());
DES des = DES.getInstanceDes();
for (PushLogEntity pushLogEntity : list) {
String phone = pushLogEntity.getPhone();
if (CommonUtil.isBase64(phone)) {
phone = des.decrypt(phone);
}
String pushContent = pushLogEntity.getPushContent();
Integer messageTemplate = pushLogEntity.getMessageTemplate();
Integer arriveStatus = pushLogEntity.getArriveStatus();
if (1001 == arriveStatus) {
boolean b = ShortMsgSend.sendMobileByRegister(pushContent, phone, messageTemplate);
if (b) {
log.info("执行短信发送成功");
pushLogEntity.setArriveStatus(1003);
updateBatch.add(pushLogEntity);
}
}
}
}
if (updateBatch != null) {
pushLogService.updateBatchById(updateBatch);
}
} catch (IOException e) {
log.error("执行短信发送失败:{}", e.getMessage());
e.printStackTrace();
}
}
/**
* 更新推送任务id缓存
*/
@Scheduled(cron = "0 0 3 * * ?")
public void updateRedisHashKey() {
HashSet<Object> hashSet = new HashSet<>();
Set<Object> keys = RedisUtil.HashOps.hKeys(Constant.PUSH_TASK_INFO);
for (Object key : keys) {
Object hashValue = RedisUtil.HashOps.hGet(Constant.PUSH_TASK_INFO, key.toString());
if (hashValue != null) {
RedisExpireData redisData = JSONUtil.toBean(hashValue.toString(), RedisExpireData.class);
Object obj = redisData.getStoreData();
if (obj == null) {
hashSet.add(key);
}
}
}
if (!hashSet.isEmpty()) {
RedisUtil.HashOps.hDelete(Constant.PUSH_TASK_INFO, hashSet.toArray());
}
}
/**
* 更新用户标签
*/
......
......@@ -11,7 +11,7 @@
<result property="taskid" column="taskid"/>
<result property="msgid" column="msgid"/>
<result property="code" column="code"/>
<result property="desc" column="desc"/>
<result property="descStr" column="desc_str"/>
<result property="sign" column="sign"/>
<result property="actionid" column="actionId"/>
<result property="recvtime" column="recvtime"/>
......
......@@ -3,19 +3,31 @@
<mapper namespace="com.weface.dao.PushLogDao">
<!-- 可根据自己的需求,是否要使用 -->
<!-- 可根据自己的需求,是否要使用 -->
<resultMap type="com.weface.entity.PushLogEntity" id="pushLogMap">
<result property="id" column="id"/>
<result property="appName" column="app_name"/>
<result property="taskId" column="task_id"/>
<result property="cid" column="cid"/>
<result property="cidStatus" column="cid_status"/>
<result property="result" column="result"/>
<result property="phone" column="phone"/>
<result property="messageTemplate" column="message_template"/>
<result property="isArrive" column="is_arrive"/>
<result property="pushTarget" column="push_target"/>
<result property="pushContent" column="push_content"/>
<result property="arriveStatus" column="arrive_status"/>
<result property="bas1" column="bas1"/>
<result property="isValid" column="is_valid"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<select id="getPushLogByTime" resultMap="pushLogMap">
SELECT *
FROM tb_push_log
WHERE is_valid = 1
AND arrive_status = 1001
AND create_time > DATE_SUB(
NOW(),
INTERVAL #{time} HOUR)
</select>
</mapper>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment