25 changed files with 897 additions and 27 deletions
@ -0,0 +1,140 @@ |
|||||
|
package com.bnyer.common.core.utils; |
||||
|
|
||||
|
import org.apache.commons.codec.digest.DigestUtils; |
||||
|
|
||||
|
import java.io.File; |
||||
|
import java.io.FileInputStream; |
||||
|
import java.io.IOException; |
||||
|
import java.io.InputStream; |
||||
|
import java.security.MessageDigest; |
||||
|
import java.security.NoSuchAlgorithmException; |
||||
|
|
||||
|
/** |
||||
|
* @author :WXC |
||||
|
* @Date :2023/05/12 |
||||
|
* @description : |
||||
|
*/ |
||||
|
public class MD5Util { |
||||
|
|
||||
|
/** |
||||
|
* 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合 |
||||
|
*/ |
||||
|
protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', |
||||
|
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; |
||||
|
|
||||
|
protected static MessageDigest messagedigest = null; |
||||
|
static { |
||||
|
try { |
||||
|
messagedigest = MessageDigest.getInstance("MD5"); |
||||
|
} catch (NoSuchAlgorithmException nsaex) { |
||||
|
System.err.println(MD5Util.class.getName() |
||||
|
+ "初始化失败,MessageDigest不支持MD5Util。"); |
||||
|
nsaex.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成字符串的md5校验值 |
||||
|
* |
||||
|
* @param s |
||||
|
* @return |
||||
|
*/ |
||||
|
public static String getMD5String(String s) { |
||||
|
return getMD5String(s.getBytes()); |
||||
|
} |
||||
|
public static String getStaffMD5String(String staffId,String s) { |
||||
|
|
||||
|
return getMD5String((staffId+s).getBytes()); |
||||
|
} |
||||
|
public static String getUserMD5String(String userId,String s) { |
||||
|
return getMD5String(s.getBytes()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 判断字符串的md5校验码是否与一个已知的md5码相匹配 |
||||
|
* |
||||
|
* @param password 要校验的字符串 |
||||
|
* @param md5PwdStr 已知的md5校验码 |
||||
|
* @return |
||||
|
*/ |
||||
|
public static boolean checkPassword(String password, String md5PwdStr) { |
||||
|
String s = getMD5String(password); |
||||
|
return s.equals(md5PwdStr); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成文件的md5校验值 |
||||
|
* |
||||
|
* @param file |
||||
|
* @return |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public static String getFileMD5String(File file) throws IOException { |
||||
|
InputStream fis; |
||||
|
fis = new FileInputStream(file); |
||||
|
byte[] buffer = new byte[1024]; |
||||
|
int numRead = 0; |
||||
|
while ((numRead = fis.read(buffer)) > 0) { |
||||
|
messagedigest.update(buffer, 0, numRead); |
||||
|
} |
||||
|
fis.close(); |
||||
|
return bufferToHex(messagedigest.digest()); |
||||
|
} |
||||
|
public static String getFileMD5String(InputStream fis) throws IOException { |
||||
|
byte[] buffer = new byte[1024]; |
||||
|
int numRead = 0; |
||||
|
while ((numRead = fis.read(buffer)) > 0) { |
||||
|
messagedigest.update(buffer, 0, numRead); |
||||
|
} |
||||
|
fis.close(); |
||||
|
return bufferToHex(messagedigest.digest()); |
||||
|
} |
||||
|
|
||||
|
public static String getMD5String(byte[] bytes) { |
||||
|
messagedigest.update(bytes); |
||||
|
return bufferToHex(messagedigest.digest()); |
||||
|
} |
||||
|
|
||||
|
private static String bufferToHex(byte bytes[]) { |
||||
|
return bufferToHex(bytes, 0, bytes.length); |
||||
|
} |
||||
|
|
||||
|
private static String bufferToHex(byte bytes[], int m, int n) { |
||||
|
StringBuffer stringbuffer = new StringBuffer(2 * n); |
||||
|
int k = m + n; |
||||
|
for (int l = m; l < k; l++) { |
||||
|
appendHexPair(bytes[l], stringbuffer); |
||||
|
} |
||||
|
return stringbuffer.toString(); |
||||
|
} |
||||
|
|
||||
|
private static void appendHexPair(byte bt, StringBuffer stringbuffer) { |
||||
|
char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字节中高 4 位的数字转换, >>> 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同
|
||||
|
char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换
|
||||
|
stringbuffer.append(c0); |
||||
|
stringbuffer.append(c1); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* MD5方法 |
||||
|
* |
||||
|
* @param text 明文 |
||||
|
* @param key 密钥 |
||||
|
* @return 密文 |
||||
|
* @throws Exception |
||||
|
*/ |
||||
|
public static String md5(String text, String key) throws Exception { |
||||
|
//加密后的字符串
|
||||
|
System.out.println("text + key "+text + key); |
||||
|
String encodeStr= DigestUtils.md5Hex(text + key); |
||||
|
System.out.println("MD5加密后的字符串为:encodeStr="+encodeStr); |
||||
|
return encodeStr; |
||||
|
} |
||||
|
|
||||
|
public static void main(String[] args) throws IOException { |
||||
|
System.out.println(MD5Util.getMD5String("RVWU202305121022211042vip")); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
package com.bnyer.img.controller; |
||||
|
|
||||
|
import com.bnyer.common.core.domain.R; |
||||
|
import com.bnyer.img.query.UserVipQuery; |
||||
|
import com.bnyer.img.query.UserVipRecordQuery; |
||||
|
import com.bnyer.img.service.UserVipRecordService; |
||||
|
import com.bnyer.img.service.UserVipService; |
||||
|
import com.bnyer.img.vo.UserVipRecordVo; |
||||
|
import com.bnyer.img.vo.UserVipVo; |
||||
|
import io.swagger.annotations.Api; |
||||
|
import io.swagger.v3.oas.annotations.Operation; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* @author :WXC |
||||
|
* @Date :2023/05/10 |
||||
|
* @description : |
||||
|
*/ |
||||
|
@Api(value = "用户会员记录相关接口",tags = "用户会员记录相关接口") |
||||
|
@RestController |
||||
|
@RequestMapping("/img/mini/vipRecord") |
||||
|
@Slf4j |
||||
|
public class UserVipRecordController { |
||||
|
|
||||
|
@Resource |
||||
|
private UserVipRecordService userVipRecordService; |
||||
|
|
||||
|
@Operation(summary="获取用户会员记录",description = "获取用户会员记录") |
||||
|
@GetMapping(value = "/queryUserVipRecord") |
||||
|
public R<UserVipRecordVo> queryUserVipRecord(UserVipRecordQuery query){ |
||||
|
return R.ok(userVipRecordService.queryUserVipRecord(query)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
package com.bnyer.img.query; |
||||
|
|
||||
|
import io.swagger.annotations.ApiModel; |
||||
|
import io.swagger.annotations.ApiModelProperty; |
||||
|
import lombok.Getter; |
||||
|
import lombok.Setter; |
||||
|
|
||||
|
/** |
||||
|
* @author :WXC |
||||
|
* @Date :2023/03/31 |
||||
|
* @description : |
||||
|
*/ |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@ApiModel("用户会员记录查询请求对象") |
||||
|
public class UserVipRecordQuery { |
||||
|
@ApiModelProperty(value = "id") |
||||
|
private Long id; |
||||
|
|
||||
|
@ApiModelProperty(value = "用户id") |
||||
|
private Long userId; |
||||
|
/** |
||||
|
* 用户客户端类型 |
||||
|
*/ |
||||
|
private Integer userClientType; |
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
package com.bnyer.img.vo; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
|
import io.swagger.annotations.ApiModel; |
||||
|
import io.swagger.annotations.ApiModelProperty; |
||||
|
import lombok.Getter; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
import lombok.Setter; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
|
||||
|
@Getter |
||||
|
@Setter |
||||
|
@NoArgsConstructor |
||||
|
@ApiModel(value = "用户会员记录查询响应对象") |
||||
|
public class UserVipRecordVo { |
||||
|
|
||||
|
@ApiModelProperty(value="id") |
||||
|
private Long id; |
||||
|
|
||||
|
@ApiModelProperty(value="订单号") |
||||
|
private String orderNo; |
||||
|
|
||||
|
@ApiModelProperty(value="用户id") |
||||
|
private Long userId; |
||||
|
|
||||
|
@ApiModelProperty(value="用户手机号") |
||||
|
private String phone; |
||||
|
|
||||
|
@ApiModelProperty(value="vip表id") |
||||
|
private Long vipId; |
||||
|
|
||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
||||
|
@ApiModelProperty(value="开始时间") |
||||
|
private Date startTime; |
||||
|
|
||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
||||
|
@ApiModelProperty(value="到期时间") |
||||
|
private Date endTime; |
||||
|
|
||||
|
@ApiModelProperty(value="状态(0->已到期;1->已生效;)") |
||||
|
private Integer status; |
||||
|
|
||||
|
@ApiModelProperty(value="vip名称") |
||||
|
private String vipName; |
||||
|
|
||||
|
@ApiModelProperty(value = "vip类型名称") |
||||
|
private String vipTypeName; |
||||
|
|
||||
|
@ApiModelProperty(value = "用户客户端类型:10用户-抖音 20用户-快手 30用户-微信 40艺术家-微信") |
||||
|
private Integer userClientType; |
||||
|
|
||||
|
@ApiModelProperty(value = "是否开通会员:0 未开通 1已开通") |
||||
|
private String isVip; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
package com.bnyer.order.annotation; |
||||
|
|
||||
|
import java.lang.annotation.Documented; |
||||
|
import java.lang.annotation.Retention; |
||||
|
import java.lang.annotation.RetentionPolicy; |
||||
|
import java.lang.annotation.Target; |
||||
|
|
||||
|
import static java.lang.annotation.ElementType.METHOD; |
||||
|
|
||||
|
/** |
||||
|
* @author :WXC |
||||
|
* @Date :2023/05/12 |
||||
|
* @description : 防重复提交 |
||||
|
*/ |
||||
|
@Target({ METHOD}) |
||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||
|
@Documented |
||||
|
public @interface LimitRepeatRequest { |
||||
|
|
||||
|
/** |
||||
|
* 限制当前用户同一个api 不能重复提交 |
||||
|
*/ |
||||
|
String SELF="self"; |
||||
|
|
||||
|
/** |
||||
|
* 限制所有用户同一个参数不能重复提交,如我新增了用户 张三, 那么其他人不能再并发情况下重复添加张三 |
||||
|
*/ |
||||
|
String ALL_USER="all"; |
||||
|
|
||||
|
/** |
||||
|
* 当前时间内 api 只能请求一次,单位秒 |
||||
|
* @return |
||||
|
*/ |
||||
|
int time() default 5; |
||||
|
|
||||
|
/** |
||||
|
* 对部分参数做重复请求限制 |
||||
|
* @return |
||||
|
*/ |
||||
|
String[] bodyParam() default {}; |
||||
|
|
||||
|
/** |
||||
|
* 是否对全部参数做重复请求限制 |
||||
|
* @return |
||||
|
*/ |
||||
|
boolean bodyAllParam() default false; |
||||
|
|
||||
|
/** |
||||
|
* 重复请求限制的用户范围 |
||||
|
* LimitRepeatRequest.SELF:针对当前登录用户 |
||||
|
* LimitRepeatRequest.ALL_USER:针对所有用户 |
||||
|
* |
||||
|
* @return |
||||
|
*/ |
||||
|
String userRange() default SELF; |
||||
|
|
||||
|
/** |
||||
|
* 错误提示信息 |
||||
|
* @return |
||||
|
*/ |
||||
|
String message() default ""; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,150 @@ |
|||||
|
package com.bnyer.order.aop; |
||||
|
|
||||
|
import cn.hutool.core.collection.CollUtil; |
||||
|
import com.alibaba.fastjson.JSON; |
||||
|
import com.alibaba.fastjson.JSONArray; |
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.bnyer.common.core.domain.R; |
||||
|
import com.bnyer.common.core.utils.MD5Util; |
||||
|
import com.bnyer.common.core.utils.StringUtils; |
||||
|
import com.bnyer.common.core.vo.UserInfoVo; |
||||
|
import com.bnyer.common.redis.service.RedisService; |
||||
|
import com.bnyer.common.security.utils.SecurityUtils; |
||||
|
import com.bnyer.order.annotation.LimitRepeatRequest; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.aspectj.lang.ProceedingJoinPoint; |
||||
|
import org.aspectj.lang.Signature; |
||||
|
import org.aspectj.lang.annotation.Around; |
||||
|
import org.aspectj.lang.annotation.Aspect; |
||||
|
import org.aspectj.lang.reflect.MethodSignature; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import java.lang.reflect.Method; |
||||
|
import java.util.Objects; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
/** |
||||
|
* @author :WXC |
||||
|
* @Date :2023/05/12 |
||||
|
* @description :重复提交限制aop |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Aspect |
||||
|
@Component |
||||
|
public class LimitRepeatRequestAspect { |
||||
|
|
||||
|
@Autowired |
||||
|
private RedisService redisService; |
||||
|
|
||||
|
@Around("@annotation(limitRepeatRequest)") |
||||
|
public Object around(ProceedingJoinPoint joinPoint, LimitRepeatRequest limitRepeatRequest) throws Throwable{ |
||||
|
String key = getKey(joinPoint,limitRepeatRequest); |
||||
|
Object cacheObject = redisService.getCacheObject(key); |
||||
|
Object message; |
||||
|
if (Objects.nonNull(cacheObject)){ |
||||
|
if (StringUtils.isNotBlank(limitRepeatRequest.message())){ |
||||
|
message = limitRepeatRequest.message(); |
||||
|
}else { |
||||
|
message = new R().buildRepeatRequest(limitRepeatRequest.time()); |
||||
|
} |
||||
|
}else { |
||||
|
redisService.setCacheObject(key,"1",(long)limitRepeatRequest.time(), TimeUnit.SECONDS); |
||||
|
message = joinPoint.proceed(); |
||||
|
} |
||||
|
return message; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取rediskey |
||||
|
* |
||||
|
* @param joinPoint |
||||
|
* @param limitRepeatRequest |
||||
|
* @return |
||||
|
*/ |
||||
|
private String getKey(ProceedingJoinPoint joinPoint, LimitRepeatRequest limitRepeatRequest) { |
||||
|
UserInfoVo userInfo = SecurityUtils.getUserInfo(); |
||||
|
Method currentMethod = getCurrentMethod(joinPoint); |
||||
|
//最后拼接好的key
|
||||
|
StringBuilder key = new StringBuilder("LimitRepeatRequestAspect#" + currentMethod.getName()); |
||||
|
//限制范围
|
||||
|
String userRange = limitRepeatRequest.userRange(); |
||||
|
if (LimitRepeatRequest.SELF.equals(userRange)){ |
||||
|
key.append("#"); |
||||
|
key.append(userInfo.getUserClientType()); |
||||
|
key.append("#"); |
||||
|
key.append(userInfo.getId()); |
||||
|
} |
||||
|
//获取请求参数
|
||||
|
JSONObject requestParams = getRequestParams(joinPoint); |
||||
|
//部分参数做重复请求限制
|
||||
|
if (Objects.nonNull(requestParams)){ |
||||
|
String[] bodyParam = limitRepeatRequest.bodyParam(); |
||||
|
if (bodyParam != null){ |
||||
|
for (String param : bodyParam) { |
||||
|
key.append("#"); |
||||
|
Object obj = requestParams.get(param); |
||||
|
if (obj instanceof JSONArray){ |
||||
|
JSONArray jsonArray = requestParams.getJSONArray(param); |
||||
|
if (CollUtil.isNotEmpty(jsonArray)){ |
||||
|
for (Object o : jsonArray) { |
||||
|
if (o instanceof String){ |
||||
|
key.append(o); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}else if(obj instanceof String){ |
||||
|
String value = requestParams.containsKey(param)?requestParams.getString(param):""; |
||||
|
key.append(value); |
||||
|
}else if(obj instanceof Integer){ |
||||
|
String value = requestParams.containsKey(param)?requestParams.getString(param):""; |
||||
|
key.append(value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
//全部参数做重复请求限制
|
||||
|
if (limitRepeatRequest.bodyAllParam()){ |
||||
|
String jsonStr = JSON.toJSONString(requestParams); |
||||
|
key.append("#"); |
||||
|
key.append(jsonStr); |
||||
|
} |
||||
|
return MD5Util.getMD5String(key.toString()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取请求参数 |
||||
|
* @param joinPoint |
||||
|
* @return |
||||
|
*/ |
||||
|
private JSONObject getRequestParams(ProceedingJoinPoint joinPoint) { |
||||
|
Object[] args = joinPoint.getArgs(); |
||||
|
if (args != null && args.length != 0){ |
||||
|
String jsonString = JSON.toJSONString(args); |
||||
|
JSONArray parseArray = JSON.parseArray(jsonString); |
||||
|
return parseArray.getJSONObject(0); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取当前方法 |
||||
|
* @param joinPoint |
||||
|
* @return |
||||
|
*/ |
||||
|
private Method getCurrentMethod(ProceedingJoinPoint joinPoint) { |
||||
|
Signature signature = joinPoint.getSignature(); |
||||
|
if (!(signature instanceof MethodSignature)){ |
||||
|
throw new IllegalArgumentException("该注解只能作用于方法上面"); |
||||
|
} |
||||
|
MethodSignature methodSignature = (MethodSignature)signature; |
||||
|
Object target = joinPoint.getTarget(); |
||||
|
try { |
||||
|
Method method = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes()); |
||||
|
return method; |
||||
|
} catch (NoSuchMethodException e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
package com.bnyer.pay.annotation; |
||||
|
|
||||
|
import java.lang.annotation.Documented; |
||||
|
import java.lang.annotation.Retention; |
||||
|
import java.lang.annotation.RetentionPolicy; |
||||
|
import java.lang.annotation.Target; |
||||
|
|
||||
|
import static java.lang.annotation.ElementType.METHOD; |
||||
|
|
||||
|
/** |
||||
|
* @author :WXC |
||||
|
* @Date :2023/05/12 |
||||
|
* @description : 防重复提交 |
||||
|
*/ |
||||
|
@Target({ METHOD}) |
||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||
|
@Documented |
||||
|
public @interface LimitRepeatRequest { |
||||
|
|
||||
|
/** |
||||
|
* 限制当前用户同一个api 不能重复提交 |
||||
|
*/ |
||||
|
String SELF="self"; |
||||
|
|
||||
|
/** |
||||
|
* 限制所有用户同一个参数不能重复提交,如我新增了用户 张三, 那么其他人不能再并发情况下重复添加张三 |
||||
|
*/ |
||||
|
String ALL_USER="all"; |
||||
|
|
||||
|
/** |
||||
|
* 当前时间内 api 只能请求一次,单位秒 |
||||
|
* @return |
||||
|
*/ |
||||
|
int time() default 5; |
||||
|
|
||||
|
/** |
||||
|
* 对部分参数做重复请求限制 |
||||
|
* @return |
||||
|
*/ |
||||
|
String[] bodyParam() default {}; |
||||
|
|
||||
|
/** |
||||
|
* 是否对全部参数做重复请求限制 |
||||
|
* @return |
||||
|
*/ |
||||
|
boolean bodyAllParam() default false; |
||||
|
|
||||
|
/** |
||||
|
* 重复请求限制的用户范围 |
||||
|
* LimitRepeatRequest.SELF:针对当前登录用户 |
||||
|
* LimitRepeatRequest.ALL_USER:针对所有用户 |
||||
|
* |
||||
|
* @return |
||||
|
*/ |
||||
|
String userRange() default SELF; |
||||
|
|
||||
|
/** |
||||
|
* 错误提示信息 |
||||
|
* @return |
||||
|
*/ |
||||
|
String message() default ""; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,150 @@ |
|||||
|
package com.bnyer.pay.aop; |
||||
|
|
||||
|
import cn.hutool.core.collection.CollUtil; |
||||
|
import com.alibaba.fastjson.JSON; |
||||
|
import com.alibaba.fastjson.JSONArray; |
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.bnyer.common.core.domain.R; |
||||
|
import com.bnyer.common.core.utils.MD5Util; |
||||
|
import com.bnyer.common.core.utils.StringUtils; |
||||
|
import com.bnyer.common.core.vo.UserInfoVo; |
||||
|
import com.bnyer.common.redis.service.RedisService; |
||||
|
import com.bnyer.common.security.utils.SecurityUtils; |
||||
|
import com.bnyer.pay.annotation.LimitRepeatRequest; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.aspectj.lang.ProceedingJoinPoint; |
||||
|
import org.aspectj.lang.Signature; |
||||
|
import org.aspectj.lang.annotation.Around; |
||||
|
import org.aspectj.lang.annotation.Aspect; |
||||
|
import org.aspectj.lang.reflect.MethodSignature; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import java.lang.reflect.Method; |
||||
|
import java.util.Objects; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
/** |
||||
|
* @author :WXC |
||||
|
* @Date :2023/05/12 |
||||
|
* @description :重复提交限制aop |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Aspect |
||||
|
@Component |
||||
|
public class LimitRepeatRequestAspect { |
||||
|
|
||||
|
@Autowired |
||||
|
private RedisService redisService; |
||||
|
|
||||
|
@Around("@annotation(limitRepeatRequest)") |
||||
|
public Object around(ProceedingJoinPoint joinPoint, LimitRepeatRequest limitRepeatRequest) throws Throwable{ |
||||
|
String key = getKey(joinPoint,limitRepeatRequest); |
||||
|
Object cacheObject = redisService.getCacheObject(key); |
||||
|
Object message; |
||||
|
if (Objects.nonNull(cacheObject)){ |
||||
|
if (StringUtils.isNotBlank(limitRepeatRequest.message())){ |
||||
|
message = limitRepeatRequest.message(); |
||||
|
}else { |
||||
|
message = new R().buildRepeatRequest(limitRepeatRequest.time()); |
||||
|
} |
||||
|
}else { |
||||
|
redisService.setCacheObject(key,"1",(long)limitRepeatRequest.time(), TimeUnit.SECONDS); |
||||
|
message = joinPoint.proceed(); |
||||
|
} |
||||
|
return message; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取rediskey |
||||
|
* |
||||
|
* @param joinPoint |
||||
|
* @param limitRepeatRequest |
||||
|
* @return |
||||
|
*/ |
||||
|
private String getKey(ProceedingJoinPoint joinPoint, LimitRepeatRequest limitRepeatRequest) { |
||||
|
UserInfoVo userInfo = SecurityUtils.getUserInfo(); |
||||
|
Method currentMethod = getCurrentMethod(joinPoint); |
||||
|
//最后拼接好的key
|
||||
|
StringBuilder key = new StringBuilder("LimitRepeatRequestAspect#" + currentMethod.getName()); |
||||
|
//限制范围
|
||||
|
String userRange = limitRepeatRequest.userRange(); |
||||
|
if (LimitRepeatRequest.SELF.equals(userRange)){ |
||||
|
key.append("#"); |
||||
|
key.append(userInfo.getUserClientType()); |
||||
|
key.append("#"); |
||||
|
key.append(userInfo.getId()); |
||||
|
} |
||||
|
//获取请求参数
|
||||
|
JSONObject requestParams = getRequestParams(joinPoint); |
||||
|
//部分参数做重复请求限制
|
||||
|
if (Objects.nonNull(requestParams)){ |
||||
|
String[] bodyParam = limitRepeatRequest.bodyParam(); |
||||
|
if (bodyParam != null){ |
||||
|
for (String param : bodyParam) { |
||||
|
key.append("#"); |
||||
|
Object obj = requestParams.get(param); |
||||
|
if (obj instanceof JSONArray){ |
||||
|
JSONArray jsonArray = requestParams.getJSONArray(param); |
||||
|
if (CollUtil.isNotEmpty(jsonArray)){ |
||||
|
for (Object o : jsonArray) { |
||||
|
if (o instanceof String){ |
||||
|
key.append(o); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}else if(obj instanceof String){ |
||||
|
String value = requestParams.containsKey(param)?requestParams.getString(param):""; |
||||
|
key.append(value); |
||||
|
}else if(obj instanceof Integer){ |
||||
|
String value = requestParams.containsKey(param)?requestParams.getString(param):""; |
||||
|
key.append(value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
//全部参数做重复请求限制
|
||||
|
if (limitRepeatRequest.bodyAllParam()){ |
||||
|
String jsonStr = JSON.toJSONString(requestParams); |
||||
|
key.append("#"); |
||||
|
key.append(jsonStr); |
||||
|
} |
||||
|
return MD5Util.getMD5String(key.toString()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取请求参数 |
||||
|
* @param joinPoint |
||||
|
* @return |
||||
|
*/ |
||||
|
private JSONObject getRequestParams(ProceedingJoinPoint joinPoint) { |
||||
|
Object[] args = joinPoint.getArgs(); |
||||
|
if (args != null && args.length != 0){ |
||||
|
String jsonString = JSON.toJSONString(args); |
||||
|
JSONArray parseArray = JSON.parseArray(jsonString); |
||||
|
return parseArray.getJSONObject(0); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取当前方法 |
||||
|
* @param joinPoint |
||||
|
* @return |
||||
|
*/ |
||||
|
private Method getCurrentMethod(ProceedingJoinPoint joinPoint) { |
||||
|
Signature signature = joinPoint.getSignature(); |
||||
|
if (!(signature instanceof MethodSignature)){ |
||||
|
throw new IllegalArgumentException("该注解只能作用于方法上面"); |
||||
|
} |
||||
|
MethodSignature methodSignature = (MethodSignature)signature; |
||||
|
Object target = joinPoint.getTarget(); |
||||
|
try { |
||||
|
Method method = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes()); |
||||
|
return method; |
||||
|
} catch (NoSuchMethodException e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
package com.bnyer.pay.enums; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Getter; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
/** |
||||
|
* @author :WXC |
||||
|
* @Date :2023/05/12 |
||||
|
* @description : |
||||
|
*/ |
||||
|
@Getter |
||||
|
@NoArgsConstructor |
||||
|
@AllArgsConstructor |
||||
|
public enum EnumVerificationKey { |
||||
|
VIP("vip", "VipInOrder20230512Key"), |
||||
|
; |
||||
|
private String key; |
||||
|
private String value; |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
package com.bnyer.pay.utils; |
||||
|
|
||||
|
import com.bnyer.common.core.utils.MD5Util; |
||||
|
import com.bnyer.pay.bean.dto.RefundDto; |
||||
|
import com.bnyer.pay.enums.EnumVerificationKey; |
||||
|
|
||||
|
/** |
||||
|
* @author :WXC |
||||
|
* @Date :2023/05/12 |
||||
|
* @description : 退款工具类 |
||||
|
*/ |
||||
|
public class PaymentRefundUtil { |
||||
|
|
||||
|
/** |
||||
|
* 获取签名 |
||||
|
* @param dto |
||||
|
* @return |
||||
|
*/ |
||||
|
public static String getSign(RefundDto dto) { |
||||
|
return MD5Util.getMD5String(dto.getPayId() + EnumVerificationKey.VIP.getValue()); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 校验签名 |
||||
|
* @param dto |
||||
|
* @return |
||||
|
*/ |
||||
|
public static boolean checkSign(RefundDto dto) { |
||||
|
|
||||
|
return MD5Util.getMD5String(dto.getPayId() + EnumVerificationKey.VIP.getValue()).equals(dto.getSign()); |
||||
|
} |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
String sign = MD5Util.getMD5String("RVWU202305121022211042" + EnumVerificationKey.VIP.getValue()); |
||||
|
System.out.println(sign); |
||||
|
System.out.println(MD5Util.getMD5String("RVWU202305121022211042" + EnumVerificationKey.VIP.getValue()).equals(sign)); |
||||
|
} |
||||
|
|
||||
|
} |
||||
Loading…
Reference in new issue