充值改造

This commit is contained in:
张松 2025-09-25 14:32:17 +08:00
parent 6bcf58aafc
commit 657eef3b8a
8 changed files with 224 additions and 34 deletions

View File

@ -0,0 +1,37 @@
package com.czg.controller.user;
import com.czg.market.service.MkShopRechargeService;
import com.czg.market.vo.MemberDetailVO;
import com.czg.market.vo.MemberListVO;
import com.czg.market.vo.MkShopRechargeVO;
import com.czg.resp.CzgResult;
import com.czg.sa.StpKit;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 会员相关
*
* @author Administrator
*/
@RestController
@RequestMapping("/user/recharge")
public class URechargeController {
@Resource
private MkShopRechargeService shopRechargeService;
/**
* 获取充值配置
* @param shopId 店铺id
*/
@GetMapping("/config")
public CzgResult<MkShopRechargeVO> getConfig(@RequestParam Long shopId) {
return CzgResult.success(shopRechargeService.detail(shopId));
}
}

View File

@ -5,6 +5,8 @@ import com.czg.annotation.SaStaffCheckPermission;
import com.czg.entity.resp.CzgBaseResp;
import com.czg.order.entity.OrderInfo;
import com.czg.resp.CzgResult;
import com.czg.sa.StpKit;
import com.czg.service.order.dto.RechargeDTO;
import com.czg.service.order.dto.VipMemberPayParamDTO;
import com.czg.service.order.dto.VipPayParamDTO;
import com.czg.service.order.dto.VipRefundDTO;
@ -70,6 +72,22 @@ public class VipPayController {
return payService.ltPayVip(ServletUtil.getClientIP(request), payParam);
}
/**
* 充值
* @param request
* @param rechargeDTO
* @return
*/
@PostMapping("/recharge")
@Debounce(value = "#payParam.shopUserId")
public CzgResult<Map<String, Object>> recharge(HttpServletRequest request, @Validated @RequestBody RechargeDTO rechargeDTO) {
if (rechargeDTO.getRechargeDetailId() == null && rechargeDTO.getMoney() == null) {
return CzgResult.failure("充值失败 未指定充值金额");
}
rechargeDTO.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
return payService.recharge(ServletUtil.getClientIP(request), rechargeDTO, StpKit.USER.getLoginIdAsLong());
}
/**
* 会员购买支付
* @param request

View File

@ -1,9 +1,14 @@
package com.czg.market.service;
import com.czg.enums.ShopUserFlowBizEnum;
import com.czg.market.dto.MkShopRechargeDTO;
import com.czg.market.vo.MkShopRechargeVO;
import com.mybatisflex.core.service.IService;
import com.czg.market.entity.MkShopRecharge;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* 充值配置表 服务层
@ -17,4 +22,7 @@ public interface MkShopRechargeService extends IService<MkShopRecharge> {
Boolean edit(Long shopId, MkShopRechargeDTO shopRechargeDTO);
BigDecimal checkRecharge(Long mainShopId, @NotNull(message = "店铺不能为空") Long shopId, Long userId, Long rechargeDetailId, @DecimalMin("0.01") BigDecimal money);
void recharge(Long shopId, Long shopUserId, Long relatedId, BigDecimal amount, Long paymentId, String payType, ShopUserFlowBizEnum bizEnum);
}

View File

@ -3,23 +3,39 @@ package com.czg.service.market.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.czg.account.dto.shopuser.ShopUserMoneyEditDTO;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.MemberPointsService;
import com.czg.account.service.ShopUserService;
import com.czg.enums.ShopUserFlowBizEnum;
import com.czg.exception.CzgException;
import com.czg.market.dto.CouponInfoDTO;
import com.czg.market.dto.MkRewardCouponDTO;
import com.czg.market.dto.MkShopRechargeDTO;
import com.czg.market.dto.MkShopRechargeDetailDTO;
import com.czg.market.entity.MkShopRechargeDetail;
import com.czg.market.entity.ShopCoupon;
import com.czg.market.service.MkShopCouponRecordService;
import com.czg.market.service.MkShopRechargeDetailService;
import com.czg.market.service.ShopCouponService;
import com.czg.market.vo.CouponInfoVO;
import com.czg.market.vo.MkShopRechargeDetailVO;
import com.czg.market.vo.MkShopRechargeVO;
import com.czg.order.entity.OrderInfo;
import com.czg.service.market.enums.OrderStatusEnums;
import com.czg.utils.AssertUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkShopRecharge;
import com.czg.market.service.MkShopRechargeService;
import com.czg.service.market.mapper.MkShopRechargeMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -32,12 +48,19 @@ import java.util.stream.Collectors;
* @author zs
* @since 2025-09-16
*/
@Slf4j
@Service
public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper, MkShopRecharge> implements MkShopRechargeService{
@Resource
private MkShopRechargeDetailService shopRechargeDetailService;
@Resource
private ShopCouponService shopCouponService;
@DubboReference
private ShopUserService shopUserService;
@DubboReference
private MemberPointsService memberPointsService;
@Resource
private MkShopCouponRecordService shopCouponRecordService;
@Override
public MkShopRechargeVO detail(Long shopId) {
@ -95,4 +118,64 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
}
return updateById(shopRecharge);
}
@Override
public BigDecimal checkRecharge(Long mainShopId, Long shopId, Long userId, Long rechargeDetailId, BigDecimal money) {
MkShopRechargeVO rechargeVO = detail(mainShopId);
if ("part".equals(rechargeVO.getUseType()) && !rechargeVO.getShopIdList().contains(shopId)) {
throw new CzgException("充值失败 该店铺不在充值店铺列表");
}
if (rechargeDetailId == null) {
if (rechargeVO.getIsCustom() == 0) {
throw new CzgException("未开启自定义充值金额");
}
return money;
}else {
MkShopRechargeDetail rechargeDetail = shopRechargeDetailService.getOne(new QueryWrapper().eq(MkShopRechargeDetail::getShopRechargeId, rechargeVO.getId()).eq(MkShopRechargeDetail::getId, rechargeDetailId));
AssertUtil.isNull(rechargeDetail, "充值金额不存在");
return rechargeDetail.getAmount();
}
}
@Override
public void recharge(Long shopId, Long shopUserId, Long relatedId, BigDecimal amount, Long paymentId, String payType, ShopUserFlowBizEnum bizEnum) {
log.info("充值回调, 用户id: {}, 金额: {}, 关联id: {}", shopUserId, amount, relatedId);
ShopUser shopUser = shopUserService.getById(shopUserId);
ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
.setId(shopUserId)
.setType(1)
.setBizEnum(bizEnum)
.setRelationId(paymentId);
// 标准充值
if (relatedId != null) {
MkShopRechargeDetail rechargeDetail = shopRechargeDetailService.getById(relatedId);
shopUserMoneyEditDTO.setMoney(rechargeDetail.getAmount().add(rechargeDetail.getRewardAmount()));
// 发放积分
if (rechargeDetail.getRewardPoints() != null) {
memberPointsService.addPoints(shopUserId, rechargeDetail.getRewardPoints(), "会员消费送积分", null);
}
// 发放优惠券
if (StrUtil.isNotBlank(rechargeDetail.getCouponInfoList())) {
JSONArray.parseArray(rechargeDetail.getCouponInfoList()).toJavaList(CouponInfoDTO.class).forEach(item -> {
shopCouponRecordService.grant(shopId, new MkRewardCouponDTO().setCouponId(item.getId())
.setNum(item.getNum())
.setUserId(shopUser.getUserId())
.setShopId(shopId));
});
}
// 自定义金额
}else {
shopUserMoneyEditDTO.setMoney(amount.divide(new BigDecimal(100), 2, RoundingMode.DOWN));
}
//TODO 以前的会员活动
// activateService.giveActivate(shopUser, new BigDecimal(czgCallBackDto.getAmount()).divide(new BigDecimal(100), 2, RoundingMode.DOWN),
// payment.getRelatedId(), flowId);
//更新会员余额 并生成流水
shopUserService.updateMoney(shopUserMoneyEditDTO);
}
}

View File

@ -0,0 +1,42 @@
package com.czg.service.order.dto;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
/**
* 支付接收参数 实体类
*
* @author ww
* @description
*/
@Data
public class RechargeDTO {
@NotNull(message = "店铺不能为空")
private Long shopId;
/**
* 充值金额id
*/
private Long rechargeDetailId;
@DecimalMin("0.01")
private BigDecimal money;
/**
* 跳转地址
*/
private String returnUrl;
/**
* 平台类型 pc 收银机客户端 wechat 微信小程序 alipay 支付宝小程序 admin-pc PC管理端 admin-app APP管理端
*/
private String platformType;
private String openId;
private String buyerRemark;
private String payType;
}

View File

@ -4,10 +4,7 @@ import com.czg.entity.resp.CzgBaseResp;
import com.czg.entity.resp.CzgRefundResp;
import com.czg.order.dto.OrderInfoRefundDTO;
import com.czg.resp.CzgResult;
import com.czg.service.order.dto.OrderPayParamDTO;
import com.czg.service.order.dto.VipMemberPayParamDTO;
import com.czg.service.order.dto.VipPayParamDTO;
import com.czg.service.order.dto.VipRefundDTO;
import com.czg.service.order.dto.*;
import lombok.NonNull;
import java.math.BigDecimal;
@ -122,4 +119,6 @@ public interface PayService {
CzgResult<CzgRefundResp> queryRefund(Long shopId, String mchRefundNo, String refundOrderId);
CzgResult<Map<String, Object>> ltPayMember(String clientIP, VipMemberPayParamDTO payParam);
CzgResult<Map<String, Object>> recharge(String clientIP, RechargeDTO rechargeDTO, Long userId);
}

View File

@ -118,6 +118,8 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
private MkShopConsumeDiscountRecordService newConsumerDiscountRecordService;
@Resource
private MemberOrderService memberOrderService;
@Resource
private MkShopRechargeService shopRechargeService;
// 延迟 5
private static final long DELAY = 5;
//重试次数
@ -842,43 +844,24 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
if (shopUser == null) {
log.error("会员充值失败会员不存在会员id{}", payment.getSourceId());
} else {
if (shopUser.getIsVip().equals(0)) {
ShopUser shopUser1 = new ShopUser();
shopUser1.setId(shopUser.getId());
shopUser1.setIsVip(1);
shopUser1.setJoinTime(LocalDateTime.now());
shopUserService.updateById(shopUser1);
}
ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
.setId(payment.getSourceId())
.setMoney(new BigDecimal(czgCallBackDto.getAmount()).divide(new BigDecimal(100), 2, RoundingMode.DOWN))
.setType(1)
.setRelationId(payment.getId());
ShopUserFlowBizEnum bizEnum;
if ("WECHAT".equals(czgCallBackDto.getPayType())) {
shopUserMoneyEditDTO.setBizEnum(ShopUserFlowBizEnum.WECHAT_IN);
bizEnum = ShopUserFlowBizEnum.WECHAT_IN;
} else if ("ALIPAY".equals(czgCallBackDto.getPayType())) {
shopUserMoneyEditDTO.setBizEnum(ShopUserFlowBizEnum.ALIPAY_IN);
bizEnum = ShopUserFlowBizEnum.ALIPAY_IN;
} else {
shopUserMoneyEditDTO.setBizEnum(ShopUserFlowBizEnum.CASH_IN);
}
//更新会员余额 并生成流水
Long flowId = shopUserService.updateMoney(shopUserMoneyEditDTO);
if (payment.getRelatedId() == null) {
return;
bizEnum = ShopUserFlowBizEnum.CASH_IN;
}
if (isFree) {
shopUserMoneyEditDTO.setBizEnum(ShopUserFlowBizEnum.FREE_IN);
bizEnum = ShopUserFlowBizEnum.CASH_IN;
updateChain().eq(OrderInfo::getId, payment.getRelatedId())
.set(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode())
.set(OrderInfo::getIsFreeDine, 1)
.set(OrderInfo::getPayAmount, 0)
.update();
} else {
//TODO 以前的会员活动
// activateService.giveActivate(shopUser, new BigDecimal(czgCallBackDto.getAmount()).divide(new BigDecimal(100), 2, RoundingMode.DOWN),
// payment.getRelatedId(), flowId);
}
shopRechargeService.recharge(payment.getShopId(), payment.getSourceId(), payment.getRelatedId(),
BigDecimal.valueOf(czgCallBackDto.getAmount() / 100), payment.getId(), payment.getPayType(), bizEnum);
}
} else if ("memberPay".equals(payment.getPayType())) {
memberConfigService.joinMember(payment.getShopId(), payment.getSourceId(), payment.getRelatedId());

View File

@ -20,6 +20,8 @@ import com.czg.exception.PaySuccessException;
import com.czg.market.entity.MkShopCouponRecord;
import com.czg.market.service.MemberOrderService;
import com.czg.market.service.MkShopCouponRecordService;
import com.czg.market.service.MkShopRechargeService;
import com.czg.market.vo.MkShopRechargeVO;
import com.czg.order.dto.BigDecimalDTO;
import com.czg.order.dto.CheckOrderPay;
import com.czg.order.dto.OrderInfoRefundDTO;
@ -31,12 +33,10 @@ import com.czg.order.enums.PayEnums;
import com.czg.order.service.*;
import com.czg.resp.CzgRespCode;
import com.czg.resp.CzgResult;
import com.czg.sa.StpKit;
import com.czg.service.CzgPayService;
import com.czg.service.RedisService;
import com.czg.service.order.dto.OrderPayParamDTO;
import com.czg.service.order.dto.VipMemberPayParamDTO;
import com.czg.service.order.dto.VipPayParamDTO;
import com.czg.service.order.dto.VipRefundDTO;
import com.czg.service.order.dto.*;
import com.czg.service.order.enums.OrderStatusEnums;
import com.czg.service.order.service.PayService;
import com.czg.system.enums.SysParamCodeEnum;
@ -101,6 +101,8 @@ public class PayServiceImpl implements PayService {
private RabbitPublisher rabbitPublisher;
@DubboReference
private MemberOrderService memberOrderService;
@Resource
private MkShopRechargeService shopRechargeService;
private final BigDecimal MONEY_RATE = new BigDecimal("100");
@ -421,6 +423,24 @@ public class PayServiceImpl implements PayService {
payParam.getPayType(), "会员充值", payParam.getOpenId(), clintIp, payParam.getReturnUrl(), payParam.getBuyerRemark(), ""));
}
@Override
public CzgResult<Map<String, Object>> recharge(String clientIP, RechargeDTO rechargeDTO, Long userId) {
ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getSourceShopId, rechargeDTO.getShopId())
.eq(ShopUser::getUserId, userId));
AssertUtil.isNull(shopUser, "充值失败 该店铺用户不存在");
MkShopRechargeVO rechargeVO = shopRechargeService.detail(rechargeDTO.getShopId());
if (rechargeDTO.getRechargeDetailId() == null && rechargeVO.getIsCustom() == 0) {
throw new CzgException("未开启自定义充值金额");
}
BigDecimal amount = shopRechargeService.checkRecharge(StpKit.USER.getHeadId(), rechargeDTO.getShopId(), userId, rechargeDTO.getRechargeDetailId(), rechargeDTO.getMoney());
String payOrderNo = rechargeDTO.getPlatformType() + IdUtil.getSnowflakeNextId();
initOrderPayment(new OrderPayment(rechargeDTO.getShopId(), shopUser.getId(), "memberIn", payOrderNo,
"", amount, rechargeDTO.getRechargeDetailId()));
return ltPay(rechargeDTO.getShopId(), rechargeDTO.getPayType(), new CzgLtPayReq(payOrderNo, amount.multiply(MONEY_RATE).longValue(),
rechargeDTO.getPayType(), "会员充值", rechargeDTO.getOpenId(), clientIP, rechargeDTO.getReturnUrl(), rechargeDTO.getBuyerRemark(), ""));
}
@Override
@Transactional
public CzgResult<Map<String, Object>> scanPayVip(String clintIp, VipPayParamDTO payParam) {