|
@@ -1,21 +1,60 @@
|
|
|
package com.fs.recharge.service.impl;
|
|
|
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.fs.common.core.domain.R;
|
|
|
+import com.fs.common.exception.CustomException;
|
|
|
+import com.fs.common.utils.DateUtils;
|
|
|
+import com.fs.common.utils.ServletUtils;
|
|
|
+import com.fs.common.utils.ip.IpUtils;
|
|
|
+import com.fs.core.utils.OrderCodeUtils;
|
|
|
+import com.fs.his.domain.FsPayConfig;
|
|
|
+import com.fs.his.domain.FsStoreOrder;
|
|
|
+import com.fs.his.domain.FsStorePayment;
|
|
|
+import com.fs.his.domain.FsUser;
|
|
|
+import com.fs.his.dto.PayConfigDTO;
|
|
|
+import com.fs.his.enums.FsStoreOrderStatusEnum;
|
|
|
+import com.fs.his.param.FsCouponReceiveParam;
|
|
|
+import com.fs.his.param.FsStoreOrderDoPayParam;
|
|
|
+import com.fs.his.service.IFsCouponService;
|
|
|
+import com.fs.his.service.IFsUserService;
|
|
|
+import com.fs.his.utils.PhoneUtil;
|
|
|
+import com.fs.huifuPay.domain.HuiFuCreateOrder;
|
|
|
+import com.fs.huifuPay.domain.HuifuCreateOrderResult;
|
|
|
+import com.fs.huifuPay.service.HuiFuService;
|
|
|
+import com.fs.recharge.domain.FsUserRechargeRecord;
|
|
|
import com.fs.recharge.domain.RechargeTemplate;
|
|
|
import com.fs.recharge.mapper.RechargeTemplateMapper;
|
|
|
+import com.fs.recharge.param.RechargeParam;
|
|
|
+import com.fs.recharge.service.FsUserRechargeRecordService;
|
|
|
import com.fs.recharge.service.RechargeTemplateService;
|
|
|
import com.fs.recharge.vo.RechargeTemplateVO;
|
|
|
+import com.fs.system.domain.SysConfig;
|
|
|
+import com.fs.system.service.ISysConfigService;
|
|
|
+import com.fs.tzBankPay.doman.PayCreateOrder;
|
|
|
+import com.fs.tzBankPay.doman.PayCreateOrderResult;
|
|
|
+import com.fs.tzBankPay.doman.TzBankResult;
|
|
|
+import com.fs.ybPay.domain.CreateWxOrderResult;
|
|
|
+import com.fs.ybPay.dto.WxJspayDTO;
|
|
|
+import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
|
|
|
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
|
|
|
+import com.github.binarywang.wxpay.config.WxPayConfig;
|
|
|
+import com.github.binarywang.wxpay.exception.WxPayException;
|
|
|
+import com.google.gson.Gson;
|
|
|
+import jodd.util.StringUtil;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Propagation;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.time.LocalDateTime;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.Arrays;
|
|
|
-import java.util.List;
|
|
|
+import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
@@ -82,6 +121,207 @@ public class RechargeTemplateServiceImpl extends ServiceImpl<RechargeTemplateMap
|
|
|
return convertToVO(template);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ISysConfigService configService;
|
|
|
+ @Autowired
|
|
|
+ private IFsUserService fsUserService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RechargeTemplateService rechargeTemplateService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private HuiFuService huiFuService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FsUserRechargeRecordService fsUserRechargeRecordService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public R payment(RechargeParam param) {
|
|
|
+
|
|
|
+ // 1. 验证充值参数
|
|
|
+ if (param.getTemplateId() == null) {
|
|
|
+ return R.error("请选择充值模板");
|
|
|
+ }
|
|
|
+ if (param.getUserId() == null) {
|
|
|
+ return R.error("用户ID不能为空");
|
|
|
+ }
|
|
|
+ // 2. 获取充值模板
|
|
|
+ RechargeTemplate template = this.getById(param.getTemplateId());
|
|
|
+ if (template == null) {
|
|
|
+ return R.error("充值模板不存在");
|
|
|
+ }
|
|
|
+ // 3. 验证模板状态
|
|
|
+ if (template.getStatus() != 1) {
|
|
|
+ return R.error("充值模板已下线");
|
|
|
+ }
|
|
|
+ // 4. 验证模板有效期
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
+ if (template.getStartTime() != null && now.isBefore(template.getStartTime())) {
|
|
|
+ return R.error("充值模板未生效");
|
|
|
+ }
|
|
|
+ if (template.getEndTime() != null && now.isAfter(template.getEndTime())) {
|
|
|
+ return R.error("充值模板已过期");
|
|
|
+ }
|
|
|
+ // 5. 验证用户类型限制
|
|
|
+ FsUser user = fsUserService.selectFsUserByUserId(param.getUserId());
|
|
|
+ if (user == null) {
|
|
|
+ return R.error("用户不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 6. 验证购买次数限制
|
|
|
+ if (template.getPurchaseLimit() > 0) {
|
|
|
+ Long purchaseCount = this.countUserPurchaseByTemplateId(user.getUserId(), template.getId());
|
|
|
+ if (purchaseCount >= template.getPurchaseLimit()) {
|
|
|
+ return R.error("您已达到该充值模板的购买次数上限");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 7. 生成充值订单
|
|
|
+ String rechargeCode = OrderCodeUtils.getOrderSn();
|
|
|
+ if (StringUtils.isEmpty(rechargeCode)) {
|
|
|
+ return R.error("订单生成失败,请重试");
|
|
|
+ }
|
|
|
+ // 8. 创建充值记录
|
|
|
+ FsUserRechargeRecord rechargeRecord = new FsUserRechargeRecord();
|
|
|
+ rechargeRecord.setRechargeCode(rechargeCode);
|
|
|
+ rechargeRecord.setUserId(user.getUserId());
|
|
|
+ rechargeRecord.setTemplateId(template.getId());
|
|
|
+ rechargeRecord.setRechargeAmount(template.getRechargeAmount());
|
|
|
+ rechargeRecord.setBonusAmount(template.getBonusAmount());
|
|
|
+ rechargeRecord.setTotalAmount(template.getRechargeAmount().add(template.getBonusAmount()));
|
|
|
+ rechargeRecord.setStatus(0); // 0-待支付
|
|
|
+ rechargeRecord.setCouponIds(template.getCouponIds());
|
|
|
+ rechargeRecord.setCreateTime(new Date());
|
|
|
+ rechargeRecord.setCompanyId(user.getCompanyId());
|
|
|
+
|
|
|
+ // 9. 判断是否需要支付
|
|
|
+ if (template.getRechargeAmount().compareTo(new BigDecimal(0)) == 0) {
|
|
|
+ // 免费充值,直接完成
|
|
|
+ rechargeRecord.setStatus(1);
|
|
|
+ rechargeRecord.setPayTime(new Date());
|
|
|
+ rechargeRecord.setPayMode("free");
|
|
|
+ rechargeRecord.setRemark("免费充值");
|
|
|
+
|
|
|
+ if (fsUserRechargeRecordService.insertRechargeRecord(rechargeRecord) <= 0) {
|
|
|
+ return R.error("充值订单创建失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理充值完成逻辑
|
|
|
+ this.processRechargeSuccess(rechargeRecord);
|
|
|
+
|
|
|
+ return R.ok().put("data", rechargeRecord.getRechargeId()).put("isPay", "1");
|
|
|
+ } else {
|
|
|
+ // 10. 在线支付
|
|
|
+ if (StringUtil.isNotBlank(user.getMaOpenId())) {
|
|
|
+ String json = configService.selectConfigByKey("his.pay");
|
|
|
+ PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
|
|
|
+
|
|
|
+ rechargeRecord.setOpenId(user.getMaOpenId());
|
|
|
+ rechargeRecord.setPayMode(payConfigDTO.getType());
|
|
|
+
|
|
|
+ if (fsUserRechargeRecordService.insertRechargeRecord(rechargeRecord) <= 0) {
|
|
|
+ return R.error("充值订单创建失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 11. 根据支付方式创建支付订单
|
|
|
+ if ("hf".equals(payConfigDTO.getType())) {
|
|
|
+ // 汇付支付
|
|
|
+ return createHuifuPayOrder(rechargeRecord, user);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return R.error("用户未绑定微信,无法完成支付");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return R.error("支付创建失败");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IFsCouponService fsCouponService;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理充值成功逻辑
|
|
|
+ */
|
|
|
+ @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
|
|
+ public void processRechargeSuccess(FsUserRechargeRecord rechargeRecord) {
|
|
|
+ try {
|
|
|
+ // 1. 查询充值模板
|
|
|
+ RechargeTemplate template = rechargeTemplateService.getById(rechargeRecord.getTemplateId());
|
|
|
+ if (template == null) {
|
|
|
+ log.error("充值模板不存在,templateId={}", rechargeRecord.getTemplateId());
|
|
|
+ throw new RuntimeException("充值模板不存在");
|
|
|
+ }
|
|
|
+ // 2. 增加用户余额
|
|
|
+ FsUser user = fsUserService.selectFsUserByUserIdForUpdate(rechargeRecord.getUserId());
|
|
|
+ BigDecimal totalAmount = rechargeRecord.getRechargeAmount().add(rechargeRecord.getBonusAmount());
|
|
|
+ BigDecimal money = user.getMoney();
|
|
|
+ if(ObjectUtils.isNull(money)) {
|
|
|
+ money = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ user.setMoney(money.add(totalAmount));
|
|
|
+
|
|
|
+ // 3. 发放优惠券
|
|
|
+ if (StringUtil.isNotEmpty(template.getCouponIds())) {
|
|
|
+ String[] couponIds = template.getCouponIds().split(",");
|
|
|
+ for (String couponId : couponIds) {
|
|
|
+ try {
|
|
|
+ Long cId = Long.parseLong(couponId);
|
|
|
+
|
|
|
+ FsCouponReceiveParam param = new FsCouponReceiveParam();
|
|
|
+ param.setCouponId(cId);
|
|
|
+ param.setUserId(rechargeRecord.getUserId());
|
|
|
+ param.setCompanyId(user.getCompanyId());
|
|
|
+ param.setCompanyUserId(user.getCompanyUserId());
|
|
|
+ fsCouponService.receive(param);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("发放优惠券失败,couponId={}, userId={}", couponId, rechargeRecord.getUserId(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("处理充值成功逻辑失败", e);
|
|
|
+ throw new RuntimeException("处理充值成功逻辑失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建汇付支付订单
|
|
|
+ */
|
|
|
+ private R createHuifuPayOrder(FsUserRechargeRecord rechargeRecord, FsUser user) {
|
|
|
+ try {
|
|
|
+ HuiFuCreateOrder order = new HuiFuCreateOrder();
|
|
|
+ order.setTradeType("T_MINIAPP");
|
|
|
+ order.setOpenid(user.getMaOpenId());
|
|
|
+ order.setReqSeqId("recharge-" + rechargeRecord.getRechargeCode());
|
|
|
+ order.setTransAmt(rechargeRecord.getRechargeAmount().toString());
|
|
|
+ order.setGoodsDesc("账户充值");
|
|
|
+
|
|
|
+ HuifuCreateOrderResult result = huiFuService.createOrder(order);
|
|
|
+ if (result != null && StringUtil.isNotEmpty(result.getHf_seq_id())) {
|
|
|
+ // 更新充值记录
|
|
|
+ FsUserRechargeRecord updateRecord = new FsUserRechargeRecord();
|
|
|
+ updateRecord.setRechargeId(rechargeRecord.getRechargeId());
|
|
|
+ updateRecord.setTradeNo(result.getHf_seq_id());
|
|
|
+ updateRecord.setPayParams(JSONUtil.toJsonStr(result));
|
|
|
+ updateRecord.setUpdateTime(new Date());
|
|
|
+ fsUserRechargeRecordService.updateRechargeRecord(updateRecord);
|
|
|
+
|
|
|
+ return R.ok().put("isPay", 0).put("data", result).put("type", "hf");
|
|
|
+ } else {
|
|
|
+ return R.error("支付创建失败");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("创建汇付支付订单失败", e);
|
|
|
+ return R.error("支付创建失败:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Long countUserPurchaseByTemplateId(Long userId, Long id) {
|
|
|
+ return 0L;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 将实体对象转换为VO对象
|
|
|
*/
|