|
|
@@ -4967,7 +4967,7 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
|
|
|
packetParam.setAmount(fsCourseRedPacketLog.getAmount());
|
|
|
packetParam.setSource(param.getSource());
|
|
|
packetParam.setAppId(param.getAppId());
|
|
|
- return paymentService.sendAppRedPacket(packetParam);
|
|
|
+ return sendAppRedPacket(packetParam, log,video, config);
|
|
|
// 积分奖励
|
|
|
case 2:
|
|
|
return sendIntegralReward(param, user, log, config);
|
|
|
@@ -4983,6 +4983,242 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ private R sendAppRedPacket(WxSendRedPacketParam packetParam,FsCourseWatchLog log,FsUserCourseVideo video,CourseConfig config) {
|
|
|
+ FsUserCoursePeriodDays periodDays = new FsUserCoursePeriodDays();
|
|
|
+ periodDays.setVideoId(log.getVideoId());
|
|
|
+ periodDays.setPeriodId(log.getPeriodId());
|
|
|
+ //正常情况是只能查询到一条,之前可能存在重复的脏数据,暂使用查询list的方式
|
|
|
+ List<FsUserCoursePeriodDays> fsUserCoursePeriodDays = fsUserCoursePeriodDaysMapper.selectFsUserCoursePeriodDaysList(periodDays);
|
|
|
+ if (fsUserCoursePeriodDays != null && !fsUserCoursePeriodDays.isEmpty()) {
|
|
|
+ periodDays = fsUserCoursePeriodDays.get(0);
|
|
|
+ }
|
|
|
+ if (periodDays != null && periodDays.getLastJoinTime() != null && LocalDateTime.now().isAfter(periodDays.getLastJoinTime())) {
|
|
|
+ return R.error(403, "已超过领取红包时间");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 确定红包金额
|
|
|
+ BigDecimal amount = BigDecimal.ZERO;
|
|
|
+ FsUserCourseVideoRedPackage redPackage = fsUserCourseVideoRedPackageMapper.selectRedPacketByCompanyId(log.getVideoId(), log.getCompanyId(), log.getPeriodId());
|
|
|
+
|
|
|
+ if (redPackage != null && redPackage.getRedPacketMoney() != null) {
|
|
|
+ amount = redPackage.getRedPacketMoney();
|
|
|
+ } else if (video != null && video.getRedPacketMoney() != null) {
|
|
|
+ amount = video.getRedPacketMoney();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (amount.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+
|
|
|
+ // 打开红包扣减功能
|
|
|
+ if ("1".equals(config.getIsRedPackageBalanceDeduction())) {
|
|
|
+ // 先注释 20251024 redis 余额 充值没有考虑 其余扣减没有考虑
|
|
|
+ // ===================== 20251022 xgb 修改 本次修改目的为了实时扣减公司余额=====================
|
|
|
+ // 1 使用redis缓存加锁 预扣减余额 红包发送失败 恢复redis缓存余额,如果回滚失败登记异常记录表 定时任务重新回滚余额
|
|
|
+ // 2 另起定时任务 同步缓存余额到redis中
|
|
|
+ // 3 注意!!!!! 启动系统时查询公司账户余额(这个时候要保证余额正确)启动会自动保存到redis缓存中
|
|
|
+ // 注意!!!!! 打开这个开关前记得检测redis缓存余额是否正确 若不正确 修改数据库字段red_package_money,删除redis缓存,重启系统,
|
|
|
+
|
|
|
+
|
|
|
+ // 预设值异常对象
|
|
|
+
|
|
|
+ BalanceRollbackError balanceRollbackError = new BalanceRollbackError();
|
|
|
+ balanceRollbackError.setCompanyId(packetParam.getCompanyId());
|
|
|
+ balanceRollbackError.setUserId(log.getUserId());
|
|
|
+ balanceRollbackError.setLogId(log.getLogId());
|
|
|
+ balanceRollbackError.setVideoId(log.getVideoId());
|
|
|
+ balanceRollbackError.setStatus(0);
|
|
|
+ balanceRollbackError.setMoney(amount);
|
|
|
+
|
|
|
+ if (packetParam.getCompanyId() == null) {
|
|
|
+ logger.error("发送红包参数错误,公司不能为空,异常请求参数{}", packetParam);
|
|
|
+ return R.error("发送红包失败,请联系管理员");
|
|
|
+ }
|
|
|
+ String companyMoneyKey = FsConstants.COMPANY_MONEY_KEY + packetParam.getCompanyId();
|
|
|
+
|
|
|
+ // 第一次加锁:预扣减余额
|
|
|
+ RLock lock1 = redissonClient.getLock(FsConstants.COMPANY_MONEY_LOCK + packetParam.getCompanyId());
|
|
|
+ boolean lockAcquired = false;
|
|
|
+ BigDecimal newMoney;
|
|
|
+ try {
|
|
|
+ if (lock1.tryLock(3, 10, TimeUnit.SECONDS)) {
|
|
|
+ lockAcquired = true;
|
|
|
+ BigDecimal originalMoney;
|
|
|
+ // 获取当前余额
|
|
|
+ String moneyStr = redisCache.getCacheObject(companyMoneyKey);
|
|
|
+ if (StringUtils.isNotEmpty(moneyStr)) {
|
|
|
+ originalMoney = new BigDecimal(moneyStr);
|
|
|
+ } else {
|
|
|
+ // 缓存没有值,重启系统恢复redis数据 保证数据正确性
|
|
|
+ logger.error("发送红包获取redis余额缓存异常,异常请求参数{}", packetParam);
|
|
|
+ return R.error("系统异常,请稍后重试");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (originalMoney.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ logger.error("服务商余额不足,异常请求参数{}", packetParam);
|
|
|
+ return R.error("服务商余额不足,请联系群主服务器充值!");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 预扣减金额
|
|
|
+ newMoney = originalMoney.subtract(amount);
|
|
|
+ redisCache.setCacheObject(companyMoneyKey, newMoney.toString());
|
|
|
+ } else {
|
|
|
+ logger.error("获取redis锁失败,异常请求参数{}", packetParam);
|
|
|
+ return R.error("系统繁忙,请稍后重试");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("预扣减余额失败: 异常请求参数{},异常信息{}", packetParam, e.getMessage(), e);
|
|
|
+ return R.error("系统异常,请稍后重试");
|
|
|
+ } finally {
|
|
|
+ // 只有在成功获取锁的情况下才释放锁
|
|
|
+ if (lockAcquired && lock1.isHeldByCurrentThread()) {
|
|
|
+ try {
|
|
|
+ lock1.unlock();
|
|
|
+ } catch (IllegalMonitorStateException e) {
|
|
|
+ logger.warn("尝试释放非当前线程持有的锁: companyId={}", packetParam.getCompanyId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 调用第三方接口(锁外操作)
|
|
|
+ R sendRedPacket;
|
|
|
+ try {
|
|
|
+ sendRedPacket = paymentService.sendAppRedPacket(packetParam);
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("红包发送异常: 异常请求参数{}", packetParam, e);
|
|
|
+ // 异常时回滚余额
|
|
|
+
|
|
|
+ rollbackBalance(balanceRollbackError);
|
|
|
+ return R.error("奖励发送失败,请联系客服");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 红包发送成功处理
|
|
|
+ if (sendRedPacket.get("code").equals(200)) {
|
|
|
+ FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
|
|
|
+ TransferBillsResult transferBillsResult;
|
|
|
+ if (sendRedPacket.get("isNew").equals(1)) {
|
|
|
+ transferBillsResult = (TransferBillsResult) sendRedPacket.get("data");
|
|
|
+ redPacketLog.setResult(JSON.toJSONString(sendRedPacket));
|
|
|
+ redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
|
|
|
+ redPacketLog.setBatchId(transferBillsResult.getTransferBillNo());
|
|
|
+ } else {
|
|
|
+ redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
|
|
|
+ redPacketLog.setBatchId(sendRedPacket.get("batchId").toString());
|
|
|
+ }
|
|
|
+ // 添加红包记录
|
|
|
+ redPacketLog.setCourseId(log.getCourseId());
|
|
|
+ redPacketLog.setCompanyId(log.getCompanyId());
|
|
|
+ redPacketLog.setUserId(log.getUserId());
|
|
|
+ redPacketLog.setVideoId(log.getVideoId());
|
|
|
+ redPacketLog.setStatus(0);
|
|
|
+ redPacketLog.setQwUserId(log.getQwUserId() != null ? log.getQwUserId().toString() : null);
|
|
|
+ redPacketLog.setCompanyUserId(log.getCompanyUserId());
|
|
|
+ redPacketLog.setCreateTime(new Date());
|
|
|
+ redPacketLog.setAmount(amount);
|
|
|
+ redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
|
|
|
+ redPacketLog.setPeriodId(log.getPeriodId());
|
|
|
+ redPacketLog.setAppId(packetParam.getAppId());
|
|
|
+
|
|
|
+ redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
|
|
|
+
|
|
|
+ // 更新观看记录的奖励类型
|
|
|
+ log.setRewardType(config.getRewardType());
|
|
|
+ courseWatchLogMapper.updateFsCourseWatchLog(log);
|
|
|
+
|
|
|
+ // 异步登记余额扣减日志
|
|
|
+ BigDecimal money = amount.multiply(BigDecimal.valueOf(-1));
|
|
|
+ companyService.asyncRecordBalanceLog(log.getCompanyId(), money, 15, newMoney, "发放红包", redPacketLog.getLogId());
|
|
|
+
|
|
|
+ return sendRedPacket;
|
|
|
+
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // 发送失败,回滚余额
|
|
|
+ rollbackBalance(balanceRollbackError);
|
|
|
+ return R.error("奖励发送失败,请联系客服");
|
|
|
+ }
|
|
|
+
|
|
|
+ // ===================== 本次修改目的为了实时扣减公司余额=====================
|
|
|
+ } else {
|
|
|
+ Company company = companyMapper.selectCompanyById(log.getCompanyId());
|
|
|
+ BigDecimal money = company.getMoney();
|
|
|
+ if (money.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ return R.error("服务商余额不足,请联系群主服务器充值!");
|
|
|
+ }
|
|
|
+
|
|
|
+ try{
|
|
|
+ // 发送红包
|
|
|
+ R sendRedPacket = paymentService.sendAppRedPacket(packetParam);
|
|
|
+ if (sendRedPacket.get("code").equals(200)) {
|
|
|
+ FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
|
|
|
+ TransferBillsResult transferBillsResult;
|
|
|
+ if (sendRedPacket.get("isNew").equals(1)) {
|
|
|
+ transferBillsResult = (TransferBillsResult) sendRedPacket.get("data");
|
|
|
+ redPacketLog.setResult(JSON.toJSONString(sendRedPacket));
|
|
|
+ redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
|
|
|
+ redPacketLog.setBatchId(transferBillsResult.getTransferBillNo());
|
|
|
+ } else {
|
|
|
+ redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
|
|
|
+ redPacketLog.setBatchId(sendRedPacket.get("batchId").toString());
|
|
|
+ }
|
|
|
+ // 添加红包记录
|
|
|
+ redPacketLog.setCourseId(log.getCourseId());
|
|
|
+ redPacketLog.setCompanyId(log.getCompanyId());
|
|
|
+ redPacketLog.setUserId(log.getUserId());
|
|
|
+ redPacketLog.setVideoId(log.getVideoId());
|
|
|
+ redPacketLog.setStatus(0);
|
|
|
+ redPacketLog.setQwUserId(log.getQwUserId() != null ? log.getQwUserId().toString() : null);
|
|
|
+ redPacketLog.setCompanyUserId(log.getCompanyUserId());
|
|
|
+ redPacketLog.setCreateTime(new Date());
|
|
|
+ redPacketLog.setAmount(amount);
|
|
|
+ redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
|
|
|
+ redPacketLog.setPeriodId(log.getPeriodId());
|
|
|
+ redPacketLog.setAppId( packetParam.getAppId());
|
|
|
+
|
|
|
+ redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
|
|
|
+
|
|
|
+ // 更新观看记录的奖励类型
|
|
|
+ log.setRewardType(config.getRewardType());
|
|
|
+ courseWatchLogMapper.updateFsCourseWatchLog(log);
|
|
|
+
|
|
|
+ return sendRedPacket;
|
|
|
+ } else {
|
|
|
+ return R.error("奖励发送失败,请联系客服");
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ return R.error(e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
|
|
|
+ // 添加红包记录
|
|
|
+ redPacketLog.setCourseId(log.getCourseId());
|
|
|
+// redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
|
|
|
+ redPacketLog.setCompanyId(log.getCompanyId());
|
|
|
+ redPacketLog.setUserId(log.getUserId());
|
|
|
+ redPacketLog.setVideoId(log.getVideoId());
|
|
|
+ redPacketLog.setStatus(1);
|
|
|
+ redPacketLog.setQwUserId(log.getQwUserId() != null ? log.getQwUserId().toString() : null);
|
|
|
+ redPacketLog.setCompanyUserId(log.getCompanyUserId());
|
|
|
+ redPacketLog.setCreateTime(new Date());
|
|
|
+ redPacketLog.setAmount(BigDecimal.ZERO);
|
|
|
+ redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
|
|
|
+ redPacketLog.setPeriodId(log.getPeriodId());
|
|
|
+ redPacketLog.setAppId( packetParam.getAppId());
|
|
|
+ redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
|
|
|
+
|
|
|
+ // 更新观看记录的奖励类
|
|
|
+ log.setRewardType(config.getRewardType());
|
|
|
+ courseWatchLogMapper.updateFsCourseWatchLog(log);
|
|
|
+ return R.ok("答题成功!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 获取用户openId
|
|
|
*/
|