|
|
@@ -1,98 +1,150 @@
|
|
|
package com.fs.his.service.impl;
|
|
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
import com.fs.common.core.domain.R;
|
|
|
+import com.fs.common.exception.CustomException;
|
|
|
+import com.fs.common.utils.DateUtils;
|
|
|
+import com.fs.common.utils.StringUtils;
|
|
|
+import com.fs.company.domain.Company;
|
|
|
+import com.fs.company.domain.CompanyUser;
|
|
|
+import com.fs.company.mapper.CompanyMapper;
|
|
|
+import com.fs.company.mapper.CompanyUserMapper;
|
|
|
+import com.fs.core.config.WxOpenProperties;
|
|
|
+import com.fs.his.domain.FsSignArticle;
|
|
|
import com.fs.his.domain.FsSignArticleReadDetail;
|
|
|
+import com.fs.his.domain.FsUser;
|
|
|
+import com.fs.his.domain.FsUserWx;
|
|
|
+import com.fs.his.mapper.FsSignArticleMapper;
|
|
|
import com.fs.his.mapper.FsSignArticleReadDetailMapper;
|
|
|
+import com.fs.his.mapper.FsUserMapper;
|
|
|
+import com.fs.his.param.ClaimArticleRedPacketParam;
|
|
|
+import com.fs.his.param.WxSendRedPacketParam;
|
|
|
import com.fs.his.param.APPSignArticleReadDetailParam;
|
|
|
import com.fs.his.service.IFsSignArticleReadDetailService;
|
|
|
+import com.fs.his.service.IFsStorePaymentService;
|
|
|
+import com.fs.his.service.IFsUserWxService;
|
|
|
+import com.fs.qw.domain.QwUser;
|
|
|
+import com.fs.qw.domain.SignRedPacketRecord;
|
|
|
+import com.fs.qw.mapper.QwUserMapper;
|
|
|
+import com.fs.qw.mapper.SignRedPacketRecordMapper;
|
|
|
+import com.fs.system.service.ISysConfigService;
|
|
|
+import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.util.Date;
|
|
|
+
|
|
|
import java.util.List;
|
|
|
|
|
|
/**
|
|
|
* 用户阅读文章明细Service业务层处理
|
|
|
- *
|
|
|
+ *
|
|
|
* @author fs
|
|
|
* @date 2024-01-01
|
|
|
*/
|
|
|
+@Slf4j
|
|
|
@Service
|
|
|
-public class FsSignArticleReadDetailServiceImpl implements IFsSignArticleReadDetailService
|
|
|
-{
|
|
|
+public class FsSignArticleReadDetailServiceImpl implements IFsSignArticleReadDetailService {
|
|
|
@Autowired
|
|
|
private FsSignArticleReadDetailMapper fsSignArticleReadDetailMapper;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private IFsStorePaymentService fsStorePaymentService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ISysConfigService configService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WxOpenProperties openProperties;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IFsUserWxService fsUserWxService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SignRedPacketRecordMapper signRedPacketRecordMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FsSignArticleMapper signArticleMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FsUserMapper userMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CompanyUserMapper companyUserMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CompanyMapper companyMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private QwUserMapper qwUserMapper;
|
|
|
+
|
|
|
/**
|
|
|
* 查询用户阅读文章明细
|
|
|
- *
|
|
|
+ *
|
|
|
* @param id 用户阅读文章明细主键
|
|
|
* @return 用户阅读文章明细
|
|
|
*/
|
|
|
@Override
|
|
|
- public FsSignArticleReadDetail selectFsSignArticleReadDetailById(Long id)
|
|
|
- {
|
|
|
+ public FsSignArticleReadDetail selectFsSignArticleReadDetailById(Long id) {
|
|
|
return fsSignArticleReadDetailMapper.selectFsSignArticleReadDetailById(id);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 查询用户阅读文章明细列表
|
|
|
- *
|
|
|
+ *
|
|
|
* @param fsSignArticleReadDetail 用户阅读文章明细
|
|
|
* @return 用户阅读文章明细
|
|
|
*/
|
|
|
@Override
|
|
|
- public List<FsSignArticleReadDetail> selectFsSignArticleReadDetailList(FsSignArticleReadDetail fsSignArticleReadDetail)
|
|
|
- {
|
|
|
+ public List<FsSignArticleReadDetail> selectFsSignArticleReadDetailList(FsSignArticleReadDetail fsSignArticleReadDetail) {
|
|
|
return fsSignArticleReadDetailMapper.selectFsSignArticleReadDetailList(fsSignArticleReadDetail);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 新增用户阅读文章明细
|
|
|
- *
|
|
|
+ *
|
|
|
* @param fsSignArticleReadDetail 用户阅读文章明细
|
|
|
* @return 结果
|
|
|
*/
|
|
|
@Override
|
|
|
- public int insertFsSignArticleReadDetail(FsSignArticleReadDetail fsSignArticleReadDetail)
|
|
|
- {
|
|
|
+ public int insertFsSignArticleReadDetail(FsSignArticleReadDetail fsSignArticleReadDetail) {
|
|
|
fsSignArticleReadDetail.setCreateTime(new java.util.Date());
|
|
|
return fsSignArticleReadDetailMapper.insertFsSignArticleReadDetail(fsSignArticleReadDetail);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 修改用户阅读文章明细
|
|
|
- *
|
|
|
+ *
|
|
|
* @param fsSignArticleReadDetail 用户阅读文章明细
|
|
|
* @return 结果
|
|
|
*/
|
|
|
@Override
|
|
|
- public int updateFsSignArticleReadDetail(FsSignArticleReadDetail fsSignArticleReadDetail)
|
|
|
- {
|
|
|
+ public int updateFsSignArticleReadDetail(FsSignArticleReadDetail fsSignArticleReadDetail) {
|
|
|
return fsSignArticleReadDetailMapper.updateFsSignArticleReadDetail(fsSignArticleReadDetail);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 批量删除用户阅读文章明细
|
|
|
- *
|
|
|
+ *
|
|
|
* @param ids 需要删除的用户阅读文章明细主键
|
|
|
* @return 结果
|
|
|
*/
|
|
|
@Override
|
|
|
- public int deleteFsSignArticleReadDetailByIds(Long[] ids)
|
|
|
- {
|
|
|
+ public int deleteFsSignArticleReadDetailByIds(Long[] ids) {
|
|
|
return fsSignArticleReadDetailMapper.deleteFsSignArticleReadDetailByIds(ids);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 删除用户阅读文章明细信息
|
|
|
- *
|
|
|
+ *
|
|
|
* @param id 用户阅读文章明细主键
|
|
|
* @return 结果
|
|
|
*/
|
|
|
@Override
|
|
|
- public int deleteFsSignArticleReadDetailById(Long id)
|
|
|
- {
|
|
|
+ public int deleteFsSignArticleReadDetailById(Long id) {
|
|
|
return fsSignArticleReadDetailMapper.deleteFsSignArticleReadDetailById(id);
|
|
|
}
|
|
|
|
|
|
@@ -127,4 +179,177 @@ public class FsSignArticleReadDetailServiceImpl implements IFsSignArticleReadDet
|
|
|
return R.error();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 发送文章红包
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public R sendArticleRedPack(ClaimArticleRedPacketParam param) {
|
|
|
+
|
|
|
+ // ******************** 阶段一:业务校验 ********************
|
|
|
+ // 1. 是否已有红包记录?
|
|
|
+ SignRedPacketRecord existing = signRedPacketRecordMapper
|
|
|
+ .selectByUserIdAndArticleId(param.getUserId(), param.getArticleId());
|
|
|
+ if (existing != null) {
|
|
|
+ return handleExistingRecord(existing); // 私有方法1:处理已存在记录
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 今日领取次数是否超限?
|
|
|
+ Integer maxNum = getArticleRedPacketConfig();
|
|
|
+ if (maxNum == null || maxNum <= 0) {
|
|
|
+ throw new CustomException("今日领取红包次数已达上限!");
|
|
|
+ }
|
|
|
+ int todayCount = signRedPacketRecordMapper.countTodayCollectedByUserId(param.getUserId());
|
|
|
+ if (todayCount >= maxNum) {
|
|
|
+ throw new CustomException("今日领取红包次数已达上限");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 文章、用户、销售、公司、企微信息是否完整?
|
|
|
+ FsSignArticle article = signArticleMapper.selectFsSignArticleById(param.getArticleId());
|
|
|
+ if (article == null || !Integer.valueOf(1).equals(article.getSignFlag())) {
|
|
|
+ throw new CustomException("文章不可领取红包");
|
|
|
+ }
|
|
|
+ if (article.getAmount() == null || article.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ throw new CustomException("红包金额异常");
|
|
|
+ }
|
|
|
+
|
|
|
+ FsUser user = userMapper.selectFsUserById(param.getUserId());
|
|
|
+ if (user == null) throw new CustomException("用户信息缺失");
|
|
|
+
|
|
|
+ CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
|
|
|
+ if (companyUser == null) throw new CustomException("销售信息缺失");
|
|
|
+
|
|
|
+ Company company = companyMapper.selectCompanyById(companyUser.getCompanyId());
|
|
|
+ if (company == null) throw new CustomException("公司信息缺失");
|
|
|
+
|
|
|
+ QwUser qwUser = qwUserMapper.selectQwUserById(Long.valueOf(param.getQwUserId()));
|
|
|
+ if (qwUser == null) throw new CustomException("企微用户信息缺失");
|
|
|
+
|
|
|
+ // 4. 获取用户在该小程序的 openId(若不存在则尝试补救一次)
|
|
|
+ FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(), user.getUserId(), 1);
|
|
|
+ if (fsUserWx == null) {
|
|
|
+ handleFsUserWx(user, param.getAppId()); // 补救逻辑(已存在的老方法)
|
|
|
+ fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(), user.getUserId(), 1);
|
|
|
+ }
|
|
|
+ if (fsUserWx == null || StringUtils.isEmpty(fsUserWx.getOpenId())) {
|
|
|
+ throw new CustomException("用户openId获取失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ // ******************** 阶段二:组装微信参数并发送 ********************
|
|
|
+ WxSendRedPacketParam wxParam = new WxSendRedPacketParam();
|
|
|
+ wxParam.setOpenId(fsUserWx.getOpenId());
|
|
|
+ wxParam.setAmount(article.getAmount());
|
|
|
+ wxParam.setRedPacketMode(1);
|
|
|
+ wxParam.setAppId(param.getAppId());
|
|
|
+ wxParam.setMpAppId(param.getAppId());
|
|
|
+ wxParam.setUser(user);
|
|
|
+ wxParam.setPhoneTag(true);
|
|
|
+ wxParam.setSource(2);
|
|
|
+ wxParam.setCompanyId(companyUser.getCompanyId());
|
|
|
+ wxParam.setSourceType(1L); // 文章红包标识
|
|
|
+
|
|
|
+ R sendResult = fsStorePaymentService.sendArticleRedPack(wxParam);
|
|
|
+
|
|
|
+ // ******************** 阶段三:处理结果并落库 ********************
|
|
|
+ return saveRecordAndReturn(sendResult, param, user, companyUser, company, qwUser, article);
|
|
|
+ }
|
|
|
+
|
|
|
+// ==================== 私有方法1:处理已存在的红包记录 ====================
|
|
|
+ /**
|
|
|
+ * 根据已有记录的状态返回对应的前端提示
|
|
|
+ */
|
|
|
+ private R handleExistingRecord(SignRedPacketRecord record) {
|
|
|
+ if (record.getCollectType() == 1) {
|
|
|
+ return R.error("您已领取过该文章红包");
|
|
|
+ } else if (record.getCollectType() == 0) {
|
|
|
+ return R.ok(record.getResult());
|
|
|
+ }
|
|
|
+ return R.error("红包状态异常");
|
|
|
+ }
|
|
|
+
|
|
|
+// ==================== 私有方法2:保存红包发放记录 ====================
|
|
|
+ /**
|
|
|
+ * 解析微信返回结果,构建 SignRedPacketRecord 并入库
|
|
|
+ */
|
|
|
+ private R saveRecordAndReturn(R sendResult,
|
|
|
+ ClaimArticleRedPacketParam param,
|
|
|
+ FsUser user,
|
|
|
+ CompanyUser companyUser,
|
|
|
+ Company company,
|
|
|
+ QwUser qwUser,
|
|
|
+ FsSignArticle article) {
|
|
|
+
|
|
|
+ // 修正:code 是 Integer,必须用 equals 比较
|
|
|
+ if (!Integer.valueOf(200).equals(sendResult.get("code"))) {
|
|
|
+ log.error("打卡文章红包-领取失败: {}", sendResult);
|
|
|
+ throw new CustomException("领取失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ SignRedPacketRecord record = new SignRedPacketRecord();
|
|
|
+ record.setResult(JSON.toJSONString(sendResult));
|
|
|
+
|
|
|
+ Object isNew = sendResult.get("isNew");
|
|
|
+ if (Integer.valueOf(1).equals(isNew)) {
|
|
|
+ TransferBillsResult data = (TransferBillsResult) sendResult.get("data");
|
|
|
+ record.setOutBatchNo(data.getOutBillNo());
|
|
|
+ record.setBatchId(data.getTransferBillNo());
|
|
|
+ } else {
|
|
|
+ record.setOutBatchNo(sendResult.get("orderCode").toString());
|
|
|
+ record.setBatchId(sendResult.get("batchId").toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ Date now = DateUtils.getNowDate();
|
|
|
+ record.setSignUrl(param.getSignUrl());
|
|
|
+ record.setCollectTag(0);
|
|
|
+ record.setCollectType(0);
|
|
|
+ record.setSignType(1); // 1-直接打卡
|
|
|
+ record.setSendTime(now);
|
|
|
+ record.setUpdateTime(now);
|
|
|
+ record.setCreateTime(now);
|
|
|
+ record.setUserId(param.getUserId());
|
|
|
+ record.setUserName(user.getRealName());
|
|
|
+ record.setCompanyId(companyUser.getCompanyId());
|
|
|
+ record.setCompanyUserId(param.getCompanyUserId());
|
|
|
+ record.setCompanyName(company.getCompanyName());
|
|
|
+ record.setArticleId(param.getArticleId());
|
|
|
+ record.setAmount(article.getAmount());
|
|
|
+ record.setQwUserId(param.getQwUserId());
|
|
|
+ record.setQwUserName(qwUser.getQwUserName());
|
|
|
+
|
|
|
+ signRedPacketRecordMapper.insertSignRedPacketRecord(record);
|
|
|
+ return sendResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取文章红包配置
|
|
|
+ *
|
|
|
+ * @return 领取次数
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Integer getArticleRedPacketConfig() {
|
|
|
+ String json = configService.selectConfigByKey("articleRedPacket.config");
|
|
|
+ if (StringUtils.isNotEmpty(json)) {
|
|
|
+ try {
|
|
|
+ JSONObject jsonObject = JSON.parseObject(json);
|
|
|
+ return jsonObject.getInteger("redPacketNum");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("解析文章红包配置失败, json={}", json, e);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0; // 默认返回 0次
|
|
|
+ }
|
|
|
+
|
|
|
+ private void handleFsUserWx(FsUser user, String appId) {
|
|
|
+ FsUserWx fsUserWx = new FsUserWx();
|
|
|
+ fsUserWx.setType(1);
|
|
|
+ fsUserWx.setFsUserId(user.getUserId());
|
|
|
+ fsUserWx.setAppId(appId);
|
|
|
+ fsUserWx.setOpenId(user.getCourseMaOpenId());
|
|
|
+ fsUserWx.setUnionId(user.getUnionId());
|
|
|
+ fsUserWx.setCreateTime(new Date());
|
|
|
+ fsUserWx.setUpdateTime(new Date());
|
|
|
+ fsUserWxService.saveOrUpdateByUniqueKey(fsUserWx);
|
|
|
+
|
|
|
+ log.info("【更新或插入用户与小程序{}的绑定关系】:{}", appId, user.getUserId());
|
|
|
+ }
|
|
|
}
|