Переглянути джерело

Merge remote-tracking branch 'origin/master'

xgb 1 тиждень тому
батько
коміт
c092026b0c

+ 1 - 1
fs-doctor-app/src/main/resources/application.yml

@@ -6,4 +6,4 @@ server:
 spring:
   profiles:
 #    active: dev
-    active: druid-jnmy
+    active: dev-yjb

+ 4 - 0
fs-service/src/main/java/com/fs/his/service/IFsStorePaymentService.java

@@ -97,6 +97,10 @@ public interface IFsStorePaymentService
 
     R sendRedPacketV3(WxSendRedPacketParam param);
 
+    R sendRedPacketLimit(WxSendRedPacketParam param);
+
+    R sendRedPacketDeduction(WxSendRedPacketParam param);
+
     String transferNotify(String notifyData, HttpServletRequest request);
 
     Boolean isEntityNull(FsStorePaymentParam fsStorePayment);

+ 4 - 4
fs-service/src/main/java/com/fs/his/service/impl/FsInquiryOrderServiceImpl.java

@@ -121,8 +121,8 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
     private JpushService jpushService;
     @Autowired
     IPayService payService;
-    @Autowired
-    SmsServiceImpl smsService;
+//    @Autowired
+//    SmsServiceImpl smsService;
     @Autowired
     private FsInquiryOrderMapper fsInquiryOrderMapper;
     @Autowired
@@ -908,7 +908,7 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
                 FsUser fsUser = fsUserService.selectFsUserByUserId(order.getUserId());
                 if (fsUser!=null&&fsUser.getPhone()!=null){
                     logger.info("医生接单发送短信:"+fsUser.getPhone()+patientDTO.getPatientName());
-                    smsService.sendUserSms(fsUser.getPhone(), patientDTO.getPatientName(), "3");
+//                    smsService.sendUserSms(fsUser.getPhone(), patientDTO.getPatientName(), "3");
                 }
 
             }
@@ -1044,7 +1044,7 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
                 FsUser fsUser = fsUserService.selectFsUserByUserId(order.getUserId());
                 if (fsUser!=null&&fsUser.getPhone()!=null){
                     logger.info("医生接单发送短信:"+fsUser.getPhone()+patientDTO.getPatientName());
-                    smsService.sendUserSms(fsUser.getPhone(), patientDTO.getPatientName(), "3");
+//                    smsService.sendUserSms(fsUser.getPhone(), patientDTO.getPatientName(), "3");
                 }
 
             }

+ 152 - 67
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -3,9 +3,10 @@ package com.fs.his.service.impl;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
-import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
@@ -17,8 +18,6 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.annotation.DataScope;
-import com.fs.common.annotation.Log;
-import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.CustomException;
@@ -26,7 +25,6 @@ import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.ip.IpUtils;
-import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.mapper.CompanyConfigMapper;
@@ -39,19 +37,14 @@ import com.fs.config.cloud.CloudHostProper;
 import com.fs.core.config.WxMaConfiguration;
 import com.fs.core.config.WxPayProperties;
 import com.fs.core.utils.OrderCodeUtils;
-import com.fs.course.config.CourseConfig;
 import com.fs.course.config.RedPacketConfig;
-import com.fs.course.domain.FsCourseRedPacketLog;
-import com.fs.course.mapper.FsCourseRedPacketLogMapper;
 import com.fs.course.service.IFsCourseRedPacketLogService;
 import com.fs.course.service.IFsUserCourseOrderService;
 import com.fs.course.service.IFsUserVipOrderService;
-import com.fs.erp.dto.ErpRefundUpdateRequest;
 import com.fs.his.domain.*;
 import com.fs.his.dto.PayConfigDTO;
 import com.fs.his.enums.PaymentMethodEnum;
 import com.fs.his.mapper.*;
-import com.fs.his.param.FsStoreOrderParam;
 import com.fs.his.param.FsStorePaymentParam;
 import com.fs.his.param.PayOrderParam;
 import com.fs.his.param.WxSendRedPacketParam;
@@ -77,7 +70,6 @@ import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
 import com.fs.system.service.ISysConfigService;
 import com.fs.tzBankPay.TzBankService.TzBankService;
-import com.fs.tzBankPay.TzBankService.TzBankServiceImpl.TzBankServiceImpl;
 import com.fs.tzBankPay.doman.*;
 import com.fs.ybPay.domain.CreateWxOrderResult;
 import com.fs.ybPay.domain.OrderResult;
@@ -85,45 +77,35 @@ import com.fs.ybPay.dto.OrderQueryDTO;
 import com.fs.ybPay.dto.RefundDTO;
 import com.fs.ybPay.dto.WxJspayDTO;
 import com.fs.ybPay.service.IPayService;
-import com.github.binarywang.wxpay.bean.merchanttransfer.TransferCreateRequest;
-import com.github.binarywang.wxpay.bean.merchanttransfer.TransferCreateResult;
 import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
 import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
 import com.github.binarywang.wxpay.bean.notify.WxPayTransferBatchesNotifyV3Result;
 import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
 import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
-import com.github.binarywang.wxpay.bean.request.WxPaySendRedpackRequest;
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
 import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
 import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
 import com.github.binarywang.wxpay.bean.transfer.*;
 import com.github.binarywang.wxpay.config.WxPayConfig;
 import com.github.binarywang.wxpay.exception.WxPayException;
-import com.github.binarywang.wxpay.service.MerchantTransferService;
-import com.github.binarywang.wxpay.service.RedpackService;
 import com.github.binarywang.wxpay.service.TransferService;
 import com.github.binarywang.wxpay.service.WxPayService;
-import com.github.binarywang.wxpay.service.impl.RedpackServiceImpl;
 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
 import com.google.gson.Gson;
 import com.hc.openapi.tool.fastjson.JSON;
-import com.wechat.pay.java.service.transferbatch.TransferBatchService;
-import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferRequest;
-import me.chanjar.weixin.common.bean.WxJsapiSignature;
 import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.mp.api.WxMpService;
 import org.apache.commons.lang.exception.ExceptionUtils;
-import org.apache.hc.core5.concurrent.CompletedFuture;
 import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.aop.framework.AopContext;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
 import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
@@ -137,6 +119,7 @@ import javax.servlet.http.HttpServletRequest;
  * @date 2023-08-11
  */
 @Service
+@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
 public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     Logger logger = LoggerFactory.getLogger(getClass());
     @Autowired
@@ -207,10 +190,23 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     @Value("${enableRedPackAccount:0}")
     private String ENABLE_RED_PACK_ACCOUNT;
 
+    @Autowired
+    private ICompanyConfigService companyConfigService;
+
+    @Autowired
+    private RedissonClient redissonClient;
+
+    @Autowired
+    private RedPacketLogMapper redPacketLogMapper;
+
     /**
      * 红包账户锁
      */
     private static final String REDPACKET_POOL_LOCK = "redpacket_pool_lock";
+    /**
+     * 红包锁
+     */
+    private static final String REDPACKET_LOCK = "redpacket_lock:%d";
 
     /**
      * 公司红包金额
@@ -222,6 +218,8 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
      */
     private static final String REDPACKET_USER_LIMIT = "redpacket_user_limit:%s:%d";
 
+
+
     /**
      * 查询支付明细
      *
@@ -525,18 +523,111 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         return fsStorePaymentMapper.selectFsStorePaymentByPaymentCode(payCode);
     }
 
-    @Autowired
-    private ICompanyConfigService companyConfigService;
-
-    @Autowired
-    private RedissonClient redissonClient;
 
-    @Autowired
-    private RedPacketLogMapper redPacketLogMapper;
     @Override
     @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
     public R sendRedPacket(WxSendRedPacketParam param) {
+        IFsStorePaymentService service = (IFsStorePaymentService) AopContext.currentProxy();
+
+        if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
+            return service.sendRedPacketDeduction(param);
+        } else {
+            return service.sendRedPacketLimit(param);
+        }
+    }
+
+
+    @Override
+    public R sendRedPacketLimit(WxSendRedPacketParam param){
+        FsUser user = param.getUser();
+
+        if(user == null) {
+            throw new IllegalArgumentException("[发送红包] 用户id为必传参数!");
+        }
+        Long userId = user.getUserId();
+
+        String key = String.format(REDPACKET_LOCK,userId);
+        RLock lock = redissonClient.getLock(key);
+
+        try{
+            boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS);
+
+            if (!locked) {
+                logger.error("获取锁失败");
+                return R.error("[红包领取] 系统繁忙,请重试!");
+            }
+
+
+            // 判断当前用户是否限流
+            String today = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_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("[红包领取] 当前用户当前已经领取红包已经达到限制!");
+            }
 
+            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;
+                default:
+                    throw new UnsupportedOperationException("当前红包模式不支持!");
+            }
+            //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);
+
+            // 用户领取红包次数+1
+            redisTemplateInteger.opsForValue().increment(userLimitKey, 1);
+            return result;
+        }catch (Exception e){
+            logger.error("领取红包失败原因:{}", ExceptionUtils.getFullStackTrace(e),e);
+            throw new RuntimeException(e);
+        }finally {
+            if (lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
+    }
+
+    /**
+     * 开启红包账户扣减-发红包
+     */
+    @Override
+    public R sendRedPacketDeduction(WxSendRedPacketParam param){
         //---------------发红包前先判断润天账户余额是否足够---------
         RLock lock = redissonClient.getLock(REDPACKET_POOL_LOCK);
         RedPacketLog redPacketLog = null;
@@ -558,8 +649,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
             Long userId = user.getUserId();
 
             // 判断当前用户是否限流
-            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
-            String today = sdf.format(new Date());
+            String today = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
             String userLimitKey = String.format(REDPACKET_USER_LIMIT, today, userId);
             Integer userCount =  redisTemplateInteger.opsForValue().get(userLimitKey);
 
@@ -577,37 +667,33 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
             }
 
 
-            BigDecimal companyMoney = null;
-
-            if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
-                companyMoney = redisTemplate.opsForValue().get(REDPACKET_COMPANY_MONEY);
+            BigDecimal 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("[红包领取] 账户余额不足,请联系管理员!");
+            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);
+            }
 
-                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());
+            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();
             // 根据红包模式获取配置
@@ -620,6 +706,8 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
                     json = companyConfigService.selectRedPacketConfigByKey(param.getCompanyId());
                     config = JSONUtil.toBean(json, RedPacketConfig.class);
                     break;
+                default:
+                    throw new UnsupportedOperationException("当前红包模式不支持!");
             }
             //H5的用公众号的appid发,小程序的用小程序的appid来发
             if (param.getSource()==2){
@@ -640,19 +728,16 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
             result.put("isNew",config.getIsNew());
             logger.info("红包返回:{}",result);
 
+            // 更新账户余额
+            logger.info("[更新账户余额] 当前余额{} 更新后余额{}",companyMoney.toPlainString(),companyMoney.subtract(amount).toPlainString());
 
-            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);
+            companyMoney = companyMoney.subtract(amount);
+            redisTemplate.opsForValue().set(REDPACKET_COMPANY_MONEY,companyMoney);
 
+            redPacketLog.setAccBalanceAfter(companyMoney);
+            redPacketLog.setUpdateTime(LocalDateTime.now());
+            redPacketLog.setStatus(1);
 
-                redPacketLog.setAccBalanceAfter(companyMoney);
-                redPacketLog.setUpdateTime(LocalDateTime.now());
-                redPacketLog.setStatus(1);
-            }
 
             // 用户领取红包次数+1
             redisTemplateInteger.opsForValue().increment(userLimitKey, 1);