diff --git a/src/main/java/com/sqx/common/utils/ApiAccessLimitUtil.java b/src/main/java/com/sqx/common/utils/ApiAccessLimitUtil.java index 894eeeb2..7c385c57 100644 --- a/src/main/java/com/sqx/common/utils/ApiAccessLimitUtil.java +++ b/src/main/java/com/sqx/common/utils/ApiAccessLimitUtil.java @@ -1,15 +1,21 @@ package com.sqx.common.utils; import cn.hutool.core.date.DateUtil; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + import java.util.Date; +import java.util.UUID; +import java.util.function.Supplier; /** * 接口访问次数 月为单位 */ @Component +@Slf4j public class ApiAccessLimitUtil { private static final String ACCESS_COUNT_KEY_PREFIX = "sys:limit:"; @@ -122,6 +128,48 @@ public class ApiAccessLimitUtil { } + public static T runFunAndCheckKey(Supplier supplier, String lockKey, Integer seconds) { + try{ + // 创建线程id, 用作判断 + String clientId = UUID.randomUUID().toString(); + // 设置分布式锁 + boolean lock = Boolean.TRUE.equals(redisUtils.setIfAbsent(lockKey, clientId, seconds)); + int count = 0; + while (!lock) { + if (count++ > 100) { + throw new RuntimeException("系统繁忙, 稍后再试"); + } + Thread.sleep(20); + lock = Boolean.TRUE.equals(redisUtils.setIfAbsent(lockKey, clientId, seconds)); + } + return supplier.get(); + } catch (RuntimeException e){ + log.info("执行出错:{}", e.getMessage()); + throw e; + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally{ + redisUtils.delete(lockKey); + } + } + + public static boolean isAccessAllowed(String id, String key, Integer count, Integer seconds) { + String redisKey = generateRedisKey(key, id); + Object countObj = redisUtils.get(redisKey); + if (countObj == null) { + // 根据不同时间周期设置过期时间并初始化访问次数为1 + redisUtils.set(redisKey, 1, seconds); + return true; + } + if (Integer.parseInt(countObj.toString()) < count) { + // 访问次数未达上限,次数加1 + redisUtils.incr(redisKey); + return true; + } + return false; + } + + private static String generateRedisKey(String key, String id) { return ACCESS_COUNT_KEY_PREFIX + key + ":" + id; } @@ -142,4 +190,4 @@ public class ApiAccessLimitUtil { long currentTimeStamp = DateUtil.currentSeconds(); return endTimeStamp - currentTimeStamp; } -} \ No newline at end of file +} diff --git a/src/main/java/com/sqx/common/utils/RedisKeys.java b/src/main/java/com/sqx/common/utils/RedisKeys.java index 54ae6475..0f736498 100644 --- a/src/main/java/com/sqx/common/utils/RedisKeys.java +++ b/src/main/java/com/sqx/common/utils/RedisKeys.java @@ -9,6 +9,8 @@ import cn.hutool.core.date.DateUtil; public class RedisKeys { public static final String FREE_WATCH_KEY = "free:watch:"; + public static final String LOCK_KEY = "SYS:LOCK:"; + public static String getSysConfigKey(String key){ return "sys:config:" + key; @@ -28,4 +30,15 @@ public class RedisKeys { public static void main(String[] args) { System.out.println(DateUtil.today()); } + + + public static String getLockKey(String sign, Object... args) { + StringBuilder key = new StringBuilder(LOCK_KEY + ":" + sign + ":"); + for (Object arg : args) { + if (arg != null) { + key.append(":").append(arg); + } + } + return key.toString(); + } } diff --git a/src/main/java/com/sqx/config/SwaggerConfig.java b/src/main/java/com/sqx/config/SwaggerConfig.java index a9043dce..8cf4bfee 100644 --- a/src/main/java/com/sqx/config/SwaggerConfig.java +++ b/src/main/java/com/sqx/config/SwaggerConfig.java @@ -1,6 +1,7 @@ package com.sqx.config; import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -21,9 +22,13 @@ import static com.google.common.collect.Lists.newArrayList; @EnableSwagger2 public class SwaggerConfig implements WebMvcConfigurer { + @Value("${swagger.enabled}") + private boolean enabled; + @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) + .enable(enabled) .apiInfo(apiInfo()) .select() //加了ApiOperation注解的类,才生成接口文档 diff --git a/src/main/java/com/sqx/modules/app/controller/app/AppLoginController.java b/src/main/java/com/sqx/modules/app/controller/app/AppLoginController.java index 96895f23..19ff76ea 100644 --- a/src/main/java/com/sqx/modules/app/controller/app/AppLoginController.java +++ b/src/main/java/com/sqx/modules/app/controller/app/AppLoginController.java @@ -144,7 +144,7 @@ public class AppLoginController { @RequestMapping(value = "/registerCode", method = RequestMethod.POST) @ApiOperation("app或h5注册或登录") @ResponseBody -// @Debounce(interval = 2500, value = "phone") + @Debounce(interval = 2500, value = "#phone") public Result registerCode(@RequestParam String phone,String msg,String platform,Integer sysPhone, String password,String inviterCode,String wxId,String qdCode) { return userService.registerCode(phone,msg,platform,sysPhone,password,inviterCode,wxId,qdCode); diff --git a/src/main/java/com/sqx/modules/app/service/impl/UserServiceImpl.java b/src/main/java/com/sqx/modules/app/service/impl/UserServiceImpl.java index 13bd79fb..ba435901 100644 --- a/src/main/java/com/sqx/modules/app/service/impl/UserServiceImpl.java +++ b/src/main/java/com/sqx/modules/app/service/impl/UserServiceImpl.java @@ -50,6 +50,8 @@ import com.sqx.modules.file.utils.Md5Utils; import com.sqx.modules.invite.service.InviteService; import com.sqx.modules.message.entity.MessageInfo; import com.sqx.modules.message.service.MessageService; +import com.sqx.modules.sys.entity.SysUserEntity; +import com.sqx.modules.sys.service.SysUserService; import com.sqx.modules.utils.HttpClientUtil; import com.sqx.modules.utils.InvitationCodeUtil; import com.sqx.modules.utils.MD5Util; @@ -110,6 +112,8 @@ public class UserServiceImpl extends ServiceImpl implements private CommonInfoService commonRepository; @Autowired private DiscSpinningService discSpinningService; + @Autowired + private SysUserService sysUserService; private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(true); @Override @@ -896,12 +900,9 @@ public class UserServiceImpl extends ServiceImpl implements if (StringUtils.isEmpty(msg)) { return Result.error("验证码不能为空!"); } - Msg msg1 = null; - if (!"147258".equals(msg)) { - msg1 = msgDao.findByPhoneAndCode(phone, msg); - if (msg1 == null) { - return Result.error("验证码不正确!"); - } + Msg msg1 = msgDao.findByPhoneAndCode(phone, msg); + if (msg1 == null) { + return Result.error("验证码不正确!"); } userInfo = new UserEntity(); UserEntity userEntity = null; @@ -921,6 +922,11 @@ public class UserServiceImpl extends ServiceImpl implements } if (StringUtils.isEmpty(qdCode)) { qdCode = userEntity.getQdCode(); + } else { + SysUserEntity sysUserEntity = sysUserService.selectSysUserByQdCode(qdCode); + if (sysUserEntity == null) { + return Result.error("请使用正确的渠道码!"); + } } userInfo.setQdCode(qdCode); userInfo.setPhone(phone); diff --git a/src/main/java/com/sqx/modules/discSpinning/controller/DiscSpinningController.java b/src/main/java/com/sqx/modules/discSpinning/controller/DiscSpinningController.java index b93c0087..f9a9b980 100644 --- a/src/main/java/com/sqx/modules/discSpinning/controller/DiscSpinningController.java +++ b/src/main/java/com/sqx/modules/discSpinning/controller/DiscSpinningController.java @@ -1,6 +1,5 @@ package com.sqx.modules.discSpinning.controller; -import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -28,7 +27,6 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; -import reactor.util.annotation.Nullable; import springfox.documentation.annotations.ApiIgnore; import java.math.BigDecimal; @@ -49,7 +47,6 @@ public class DiscSpinningController { private final TaskCenterRecordService taskRecordService; private final UserService userService; private final RedisUtils redisUtils; - @Autowired public DiscSpinningController(CommonInfoService commonRepository, DiscSpinningService discSpinningService, OrdersService ordersService, DiscSpinningRecordService recordService, diff --git a/src/main/java/com/sqx/modules/discSpinning/service/impl/DiscSpinningServiceImpl.java b/src/main/java/com/sqx/modules/discSpinning/service/impl/DiscSpinningServiceImpl.java index 436b2016..5b4d0c92 100644 --- a/src/main/java/com/sqx/modules/discSpinning/service/impl/DiscSpinningServiceImpl.java +++ b/src/main/java/com/sqx/modules/discSpinning/service/impl/DiscSpinningServiceImpl.java @@ -124,28 +124,38 @@ public class DiscSpinningServiceImpl extends ServiceImpl cashOuts = cashOutDao.selectYesterday(); for (CashOut cashOut : cashOuts) { - String outOrderNo = AliPayOrderUtil.createOrderId(); - cashOut.setOrderNumber(outOrderNo); - BaseResp baseResp = WuyouPay.extractOrder(cashOut.getUserId(), outOrderNo, cashOut.getMoney(), cashOut.getZhifubao(), cashOut.getZhifubaoName()); - if (baseResp.getStatus() != null && baseResp.getStatus().equals(2)) { - cashOut.setState(1); - } else { - cashOut.setState(2); - cashOut.setRefund(StringUtils.isNotBlank(baseResp.getMsg()) ? baseResp.getMsg() : baseResp.getErrorMsg()); - if (cashOut.getRefund().contains("收款人账户号出款属性不匹配")||cashOut.getRefund().contains("已驳回")) { - cashOut.setRefund("提现失败,请检查支付宝账号与收款人姓名后,重试。"); - }else { - cashOut.setRefund(baseResp.getErrorMsg()); - } - UserMoneyDetails userMoneyDetails = new UserMoneyDetails( - cashOut.getUserId(),null,null,"提现失败",4,1,1, - new BigDecimal(cashOut.getMoney()),"提现失败存入余额" + cashOut.getMoney() + "元", 1); + if (WuyouPay.checkCanCash(cashOut.getUserId())) { + String outOrderNo = AliPayOrderUtil.createOrderId(); + cashOut.setOrderNumber(outOrderNo); - //存入余额 钱 - userMoneyService.updateAmount(1, cashOut.getUserId(), Double.parseDouble(cashOut.getMoney())); - userMoneyDetailsService.save(userMoneyDetails); + BaseResp baseResp = WuyouPay.extractOrder(outOrderNo, cashOut.getMoney(), cashOut.getZhifubao(), cashOut.getZhifubaoName()); + if (baseResp.getStatus() != null && baseResp.getStatus().equals(2)) { + cashOut.setState(1); + } else { + cashOut.setState(2); + cashOut.setRefund(StringUtils.isNotBlank(baseResp.getMsg()) ? baseResp.getMsg() : baseResp.getErrorMsg()); + if (cashOut.getRefund().contains("收款人账户号出款属性不匹配") || cashOut.getRefund().contains("已驳回")) { + cashOut.setRefund("提现失败,请检查支付宝账号与收款人姓名后,重试。"); + } else { + cashOut.setRefund(baseResp.getErrorMsg()); + } + UserMoneyDetails userMoneyDetails = new UserMoneyDetails( + cashOut.getUserId(), null, null, "提现失败", 4, 1, 1, + new BigDecimal(cashOut.getMoney()), "提现失败存入余额" + cashOut.getMoney() + "元", 1); + + //存入余额 钱 + userMoneyService.updateAmount(1, cashOut.getUserId(), Double.parseDouble(cashOut.getMoney())); + userMoneyDetailsService.save(userMoneyDetails); + } + }else { + cashOut.setState(3); } cashOutDao.updateById(cashOut); } diff --git a/src/main/java/com/sqx/modules/job/task/CashOutTask2.java b/src/main/java/com/sqx/modules/job/task/CashOutTask2.java new file mode 100644 index 00000000..781d1f3f --- /dev/null +++ b/src/main/java/com/sqx/modules/job/task/CashOutTask2.java @@ -0,0 +1,74 @@ +package com.sqx.modules.job.task; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.sqx.modules.app.entity.UserMoneyDetails; +import com.sqx.modules.app.service.UserMoneyDetailsService; +import com.sqx.modules.app.service.UserMoneyService; +import com.sqx.modules.banner.entity.Activity; +import com.sqx.modules.pay.dao.CashOutDao; +import com.sqx.modules.pay.entity.CashOut; +import com.sqx.modules.pay.wuyou.BaseResp; +import com.sqx.modules.pay.wuyou.WuyouPay; +import com.sqx.modules.utils.AliPayOrderUtil; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.List; + +@Component("CashOutTask2") +public class CashOutTask2 implements ITask { + + @Resource + private CashOutDao cashOutDao; + @Resource + private UserMoneyService userMoneyService; + @Resource + private UserMoneyDetailsService userMoneyDetailsService; + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public void run(String params) { + logger.info("提现开始"); + List cashOuts = cashOutDao.selectList(new QueryWrapper() + .eq("state", 0) + .gt("create_at", DateUtil.today()+" 00:00:00") + .lt("create_at",DateUtil.today()+" 23:59:59")); + System.out.println(cashOuts.size()); + for (CashOut cashOut : cashOuts) { + if (WuyouPay.checkCanCash(cashOut.getUserId())) { + String outOrderNo = AliPayOrderUtil.createOrderId(); + cashOut.setOrderNumber(outOrderNo); + BaseResp baseResp = WuyouPay.extractOrder(outOrderNo, cashOut.getMoney(), cashOut.getZhifubao(), cashOut.getZhifubaoName()); + if (baseResp.getStatus() != null && baseResp.getStatus().equals(2)) { + cashOut.setState(1); + } else { + cashOut.setState(2); + cashOut.setRefund(StringUtils.isNotBlank(baseResp.getMsg()) ? baseResp.getMsg() : baseResp.getErrorMsg()); + if (cashOut.getRefund().contains("收款人账户号出款属性不匹配")||cashOut.getRefund().contains("已驳回")) { + cashOut.setRefund("提现失败,请检查支付宝账号与收款人姓名后,重试。"); + }else { + cashOut.setRefund(baseResp.getErrorMsg()); + } + UserMoneyDetails userMoneyDetails = new UserMoneyDetails( + cashOut.getUserId(),null,null,"提现失败",4,1,1, + new BigDecimal(cashOut.getMoney()),"提现失败存入余额" + cashOut.getMoney() + "元", 1); + + //存入余额 钱 + userMoneyService.updateAmount(1, cashOut.getUserId(), Double.parseDouble(cashOut.getMoney())); + userMoneyDetailsService.save(userMoneyDetails); + } + }else { + cashOut.setState(3); + } + + cashOutDao.updateById(cashOut); + } + logger.info("提现结束"); + } +} diff --git a/src/main/java/com/sqx/modules/pay/controller/app/WuyouController.java b/src/main/java/com/sqx/modules/pay/controller/app/WuyouController.java index 6cb90a89..c918ddc7 100644 --- a/src/main/java/com/sqx/modules/pay/controller/app/WuyouController.java +++ b/src/main/java/com/sqx/modules/pay/controller/app/WuyouController.java @@ -4,7 +4,9 @@ import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.sqx.common.annotation.Debounce; +import com.sqx.common.utils.ApiAccessLimitUtil; import com.sqx.common.utils.DateUtils; +import com.sqx.common.utils.RedisKeys; import com.sqx.common.utils.Result; import com.sqx.modules.app.entity.UserEntity; import com.sqx.modules.app.entity.UserMoneyDetails; @@ -34,6 +36,7 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.springframework.context.ApplicationContext; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; @@ -68,12 +71,13 @@ public class WuyouController { private final CashOutDao cashOutDao; private final CompletAwardService completAwardService; private final SysUserService sysUserService; + private final ApplicationContext applicationContext; ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5); private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); WuyouController(OrdersService ordersService, PayDetailsDao payDetailsDao, UserService userService, InviteService inviteService, CashOutDao cashOutDao, UserMoneyService userMoneyService, UserMoneyDetailsService userMoneyDetailsService, CommonInfoService commonRepository, - InviteDao inviteDao,CompletAwardService completAwardService, SysUserService sysUserService) { + InviteDao inviteDao, CompletAwardService completAwardService, SysUserService sysUserService, ApplicationContext applicationContext) { this.ordersService = ordersService; this.payDetailsDao = payDetailsDao; this.userService = userService; @@ -85,6 +89,7 @@ public class WuyouController { this.inviteDao = inviteDao; this.completAwardService = completAwardService; this.sysUserService = sysUserService; + this.applicationContext = applicationContext; } @Debounce(interval = 1000, value = "#orderId") @@ -335,7 +340,11 @@ public class WuyouController { ordersService.updateById(order); ordersService.insertOrders(order); CompletableFuture.runAsync(() -> { - activities(user, byUser); + ApiAccessLimitUtil.runFunAndCheckKey(() -> { + WuyouController proxy = applicationContext.getBean(WuyouController.class); + proxy.activities(user, byUser); + return null; + }, RedisKeys.getLockKey("activaties", user.getUserId(), byUser.getUserId()), 15); }); } diff --git a/src/main/java/com/sqx/modules/pay/service/impl/CashOutServiceImpl.java b/src/main/java/com/sqx/modules/pay/service/impl/CashOutServiceImpl.java index 33968598..e65d3980 100644 --- a/src/main/java/com/sqx/modules/pay/service/impl/CashOutServiceImpl.java +++ b/src/main/java/com/sqx/modules/pay/service/impl/CashOutServiceImpl.java @@ -486,15 +486,20 @@ public class CashOutServiceImpl extends ServiceImpl impleme return Result.success("可提现余额不足!"); } -// BaseResp baseResp = WuyouPay.extractOrder(outOrderNo, cashOut.getMoney(), cashOut.getZhifubao(), cashOut.getZhifubaoName()); -// if (baseResp.getStatus() != null && (baseResp.getStatus().equals(2) || baseResp.getStatus().equals(10000))){ -// userMoneyDetails.setContent("成功提现:" + money); -// cashOut.setState(1); -// } -// -// if (baseResp.getErrorMsg() != null) { -// return Result.error(baseResp.getErrorMsg()); -// } + if (WuyouPay.checkCanCash(userId)) { + BaseResp baseResp = WuyouPay.extractOrder(outOrderNo, cashOut.getMoney(), cashOut.getZhifubao(), cashOut.getZhifubaoName()); + if (baseResp.getStatus() != null && (baseResp.getStatus().equals(2) || baseResp.getStatus().equals(10000))){ + userMoneyDetails.setContent("成功提现:" + money); + cashOut.setState(1); + } + + if (baseResp.getErrorMsg() != null) { + return Result.error(baseResp.getErrorMsg()); + } + }else { + userMoneyDetails.setContent("成功提现:" + money); + cashOut.setState(3); + } userMoneyDetailsService.save(userMoneyDetails); baseMapper.insert(cashOut); diff --git a/src/main/java/com/sqx/modules/pay/wuyou/WuyouPay.java b/src/main/java/com/sqx/modules/pay/wuyou/WuyouPay.java index 3ce633f2..efd60c3b 100644 --- a/src/main/java/com/sqx/modules/pay/wuyou/WuyouPay.java +++ b/src/main/java/com/sqx/modules/pay/wuyou/WuyouPay.java @@ -82,30 +82,30 @@ public class WuyouPay { return JSONObject.parseObject(body, BaseResp.class); } + public static boolean checkCanCash(long userId) { + // 查询当日体现次数 + Integer successCashCount = cashOutDao.selectTodayCashCount(userId, 1); + CommonInfo cashLimit = commonInfoService.findOne(922); + if (cashLimit == null || StrUtil.isBlank(cashLimit.getValue())) { + logger.warn("提现必要参数未配置,请联系管理员"); + return false; + } + + if (successCashCount >= Integer.parseInt(cashLimit.getValue())) { + logger.warn("提现必要参数未配置,请联系管理员"); + return false; + + } + return true; + } + /** * 提现 * @param account 支付宝账号 * @param userName 支付宝名称 * @return */ - public static BaseResp extractOrder(long userId, String outOrderNo, String amount, String account, String userName) { - - // 查询当日体现次数 - Integer successCashCount = cashOutDao.selectTodayCashCount(userId, 1); - CommonInfo cashLimit = commonInfoService.findOne(922); - if (cashLimit == null || StrUtil.isBlank(cashLimit.getValue())) { - BaseResp baseResp = new BaseResp(); - baseResp.setStatus(0); - baseResp.setErrorMsg("提现必要参数未配置,请联系管理员"); - return baseResp; - } - - if (successCashCount >= Integer.parseInt(cashLimit.getValue())) { - BaseResp baseResp = new BaseResp(); - baseResp.setStatus(0); - baseResp.setErrorMsg("每日提现次数限制" + cashLimit.getValue() + "次, 您已超过上限"); - return baseResp; - } + public static BaseResp extractOrder(String outOrderNo, String amount, String account, String userName) { Map params = getBaseParams(); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 7338d3e6..1cc256d7 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -33,7 +33,8 @@ spring: config: multi-statement-allow: true - +swagger: + enabled: true pay: h5BaseUrl: https://video-h5.hnsiyao.cn/me/detail/detail?allId= orderNotifyUrl: https://video.hnsiyao.cn/sqx_fast/app/wuyou/notify diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 56c0e79a..2d219bc9 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -32,7 +32,8 @@ spring: wall: config: multi-statement-allow: true - +swagger: + enabled: false pay: h5BaseUrl: https://dj-h5.hnsiyao.cn/me/detail/detail?allId= orderNotifyUrl: https://dj-api.hnsiyao.cn/sqx_fast/app/wuyou/notify