|
@@ -561,143 +561,39 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
|
|
|
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
|
|
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
|
|
|
public R sendRedPacket(WxSendRedPacketParam param) {
|
|
public R sendRedPacket(WxSendRedPacketParam param) {
|
|
|
|
|
|
|
|
- //---------------发红包前先判断润天账户余额是否足够---------
|
|
|
|
|
- RLock lock = redissonClient.getLock(REDPACKET_POOL_LOCK);
|
|
|
|
|
- RedPacketLog redPacketLog = null;
|
|
|
|
|
-
|
|
|
|
|
- try{
|
|
|
|
|
- boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS);
|
|
|
|
|
-
|
|
|
|
|
- if (!locked) {
|
|
|
|
|
- logger.error("获取锁失败");
|
|
|
|
|
- return R.error("[红包领取] 系统繁忙,请重试!");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- FsUser user = param.getUser();
|
|
|
|
|
- BigDecimal amount = param.getAmount();
|
|
|
|
|
-
|
|
|
|
|
- if(user == null) {
|
|
|
|
|
- throw new IllegalArgumentException("[发送红包] 用户id为必传参数!");
|
|
|
|
|
- }
|
|
|
|
|
- Long userId = user.getUserId();
|
|
|
|
|
-
|
|
|
|
|
- // 判断当前用户是否限流
|
|
|
|
|
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
|
|
|
|
|
- String today = sdf.format(new Date());
|
|
|
|
|
- String userLimitKey = String.format(REDPACKET_USER_LIMIT, today, userId);
|
|
|
|
|
- Integer userCount = redisTemplateInteger.opsForValue().get(userLimitKey);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // 首次领取
|
|
|
|
|
- if(userCount == null) {
|
|
|
|
|
- userCount = 0;
|
|
|
|
|
- long expireSeconds = getExpireSeconds();
|
|
|
|
|
- redisTemplateInteger.opsForValue().set(userLimitKey, userCount, expireSeconds, TimeUnit.SECONDS);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if(userCount >= RED_PACKET_LIMIT_COUNT){
|
|
|
|
|
- logger.info("[红包领取] 用户{} 领取红包已经达到最大限制!",userId);
|
|
|
|
|
- return R.error("[红包领取] 当前用户当前已经领取红包已经达到限制!");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- BigDecimal companyMoney = null;
|
|
|
|
|
-
|
|
|
|
|
- if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
|
|
|
|
|
- companyMoney = redisTemplate.opsForValue().get(REDPACKET_COMPANY_MONEY);
|
|
|
|
|
-
|
|
|
|
|
- if(ObjectUtils.isNull(companyMoney)){
|
|
|
|
|
- SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("company.money");
|
|
|
|
|
- if(ObjectUtils.isNull(sysConfig)){
|
|
|
|
|
- throw new IllegalArgumentException("润天公司账户余额不能为空!请检查配置!");
|
|
|
|
|
- }
|
|
|
|
|
- String configValue = sysConfig.getConfigValue();
|
|
|
|
|
- companyMoney = new BigDecimal(configValue);
|
|
|
|
|
- logger.info("缓存公司余额为空,从数据库读取 companyMoney: {}",companyMoney);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (companyMoney.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
|
|
- logger.info("润天账户余额: {} 不足!", companyMoney);
|
|
|
|
|
- return R.error("[红包领取] 账户余额不足,请联系管理员!");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- redPacketLog = new RedPacketLog();
|
|
|
|
|
- redPacketLog.setRedPacketMode(param.getRedPacketMode());
|
|
|
|
|
- redPacketLog.setAmount(param.getAmount());
|
|
|
|
|
- redPacketLog.setAppId(param.getAppId());
|
|
|
|
|
- redPacketLog.setCompanyId(param.getCompanyId());
|
|
|
|
|
- redPacketLog.setCreateTime(LocalDateTime.now());
|
|
|
|
|
- redPacketLog.setUserId(userId);
|
|
|
|
|
- redPacketLog.setAccBalanceBefore(companyMoney);
|
|
|
|
|
- redPacketLog.setSource(param.getSource());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- String json;
|
|
|
|
|
- RedPacketConfig config = new RedPacketConfig();
|
|
|
|
|
- // 根据红包模式获取配置
|
|
|
|
|
- switch (param.getRedPacketMode()){
|
|
|
|
|
- case 1:
|
|
|
|
|
- json = configService.selectConfigByKey("redPacket.config");
|
|
|
|
|
- config = JSONUtil.toBean(json, RedPacketConfig.class);
|
|
|
|
|
- break;
|
|
|
|
|
- case 2:
|
|
|
|
|
- json = companyConfigService.selectRedPacketConfigByKey(param.getCompanyId());
|
|
|
|
|
- config = JSONUtil.toBean(json, RedPacketConfig.class);
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- //H5的用公众号的appid发,小程序的用小程序的appid来发
|
|
|
|
|
- if (param.getSource()==2){
|
|
|
|
|
- // 传参appId为空时,仍然使用配置里面的
|
|
|
|
|
- String appId = StringUtils.isBlank(param.getAppId()) ? config.getMiniappId() : param.getAppId();
|
|
|
|
|
- config.setAppId(appId);
|
|
|
|
|
- }
|
|
|
|
|
- logger.info("最终传参 {}",config);
|
|
|
|
|
- //组合返回参数
|
|
|
|
|
- R result = new R();
|
|
|
|
|
- // 根据 isNew 判断使用哪种发红包方式
|
|
|
|
|
- if (config.getIsNew() != null && config.getIsNew() == 1) {
|
|
|
|
|
- result = sendRedPacketV3Internal(param, config);
|
|
|
|
|
- } else {
|
|
|
|
|
- result= sendRedPacketLegacyInternal(param, config);
|
|
|
|
|
- }
|
|
|
|
|
- result.put("mchId",config.getMchId()+"");
|
|
|
|
|
- result.put("isNew",config.getIsNew());
|
|
|
|
|
- logger.info("红包返回:{}",result);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
|
|
|
|
|
- // 更新账户余额
|
|
|
|
|
- logger.info("[更新账户余额] 当前余额{} 更新后余额{}",companyMoney.toPlainString(),companyMoney.subtract(amount).toPlainString());
|
|
|
|
|
-
|
|
|
|
|
- companyMoney = companyMoney.subtract(amount);
|
|
|
|
|
- redisTemplate.opsForValue().set(REDPACKET_COMPANY_MONEY,companyMoney);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- redPacketLog.setAccBalanceAfter(companyMoney);
|
|
|
|
|
- redPacketLog.setUpdateTime(LocalDateTime.now());
|
|
|
|
|
- redPacketLog.setStatus(1);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 用户领取红包次数+1
|
|
|
|
|
- redisTemplateInteger.opsForValue().increment(userLimitKey, 1);
|
|
|
|
|
- return result;
|
|
|
|
|
- }catch (Exception e){
|
|
|
|
|
- logger.error("领取红包失败原因:{}", ExceptionUtils.getFullStackTrace(e),e);
|
|
|
|
|
- if(redPacketLog != null) {
|
|
|
|
|
- redPacketLog.setStatus(2);
|
|
|
|
|
- redPacketLog.setErrorMsg(ExceptionUtils.getFullStackTrace(e));
|
|
|
|
|
- }
|
|
|
|
|
- throw new RuntimeException(e);
|
|
|
|
|
- }finally {
|
|
|
|
|
- if (lock.isHeldByCurrentThread()) {
|
|
|
|
|
- lock.unlock();
|
|
|
|
|
- }
|
|
|
|
|
- if(redPacketLog != null) {
|
|
|
|
|
- redPacketLogMapper.insert(redPacketLog);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ String json;
|
|
|
|
|
+ RedPacketConfig config = new RedPacketConfig();
|
|
|
|
|
+ // 根据红包模式获取配置
|
|
|
|
|
+ switch (param.getRedPacketMode()){
|
|
|
|
|
+ case 1:
|
|
|
|
|
+ json = configService.selectConfigByKey("redPacket.config");
|
|
|
|
|
+ config = JSONUtil.toBean(json, RedPacketConfig.class);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 2:
|
|
|
|
|
+ json = companyConfigService.selectRedPacketConfigByKey(param.getCompanyId());
|
|
|
|
|
+ config = JSONUtil.toBean(json, RedPacketConfig.class);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ //H5的用公众号的appid发,小程序的用小程序的appid来发
|
|
|
|
|
+ if (param.getSource()==2){
|
|
|
|
|
+ // 传参appId为空时,仍然使用配置里面的
|
|
|
|
|
+ String appId = StringUtils.isBlank(param.getAppId()) ? config.getMiniappId() : param.getAppId();
|
|
|
|
|
+ config.setAppId(appId);
|
|
|
}
|
|
}
|
|
|
|
|
+ logger.info("最终传参 {}",config);
|
|
|
|
|
+ //组合返回参数
|
|
|
|
|
+ R result = new R();
|
|
|
|
|
+ // 根据 isNew 判断使用哪种发红包方式
|
|
|
|
|
+ if (config.getIsNew() != null && config.getIsNew() == 1) {
|
|
|
|
|
+ result = sendRedPacketV3Internal(param, config);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ result= sendRedPacketLegacyInternal(param, config);
|
|
|
|
|
+ }
|
|
|
|
|
+ result.put("mchId",config.getMchId()+"");
|
|
|
|
|
+ result.put("isNew",config.getIsNew());
|
|
|
|
|
+ logger.info("红包返回:{}",result);
|
|
|
|
|
+ return result;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
private static long getExpireSeconds() {
|
|
private static long getExpireSeconds() {
|
|
|
Calendar calendar = Calendar.getInstance();
|
|
Calendar calendar = Calendar.getInstance();
|
|
|
calendar.add(Calendar.DAY_OF_YEAR, 1);
|
|
calendar.add(Calendar.DAY_OF_YEAR, 1);
|