会员积分代码提交

This commit is contained in:
Tankaikai
2025-02-26 14:14:45 +08:00
parent 6488a55355
commit 9b1961c77a
11 changed files with 508 additions and 46 deletions

View File

@@ -219,8 +219,8 @@ public class MemberPointsServiceImpl extends ServiceImpl<MemberPointsMapper, Mem
@Override
@Transactional(rollbackFor = Exception.class)
public boolean addPoints(Long memberId, int points, String content, Long orderId) {
MemberPoints entity = initMemberPoints(memberId);
public boolean addPoints(Long userId, int points, String content, Long orderId) {
MemberPoints entity = initMemberPoints(userId);
// 增加账户积分
entity.setAccountPoints(entity.getAccountPoints() + points);
entity.setLastPointsChangeTime(LocalDateTime.now());
@@ -246,7 +246,7 @@ public class MemberPointsServiceImpl extends ServiceImpl<MemberPointsMapper, Mem
@Override
@Transactional(rollbackFor = Exception.class)
public void consumeAwardPoints(Long memberId, Long orderId) {
public void consumeAwardPoints(Long userId, Long orderId) {
OrderInfo orderInfo = orderInfoService.getById(orderId);
if (orderInfo == null) {
throw new CzgException("订单不存在");
@@ -266,7 +266,7 @@ public class MemberPointsServiceImpl extends ServiceImpl<MemberPointsMapper, Mem
String rewardsGroup = basicSetting.getRewardsGroup();
MemberPoints entity;
try {
entity = initMemberPoints(memberId);
entity = initMemberPoints(userId);
} catch (Exception e) {
return;
}
@@ -282,6 +282,6 @@ public class MemberPointsServiceImpl extends ServiceImpl<MemberPointsMapper, Mem
return;
}
BigDecimal awardPoints = NumberUtil.roundDown(NumberUtil.div(payAmount, consumeAmount), 0);
addPoints(memberId, awardPoints.intValue(), StrUtil.format("消费¥{}送{}积分", payAmount, awardPoints.intValue()), orderId);
addPoints(userId, awardPoints.intValue(), StrUtil.format("消费¥{}送{}积分", payAmount, awardPoints.intValue()), orderId);
}
}

View File

@@ -1,24 +1,37 @@
package com.czg.service.account.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import com.czg.account.dto.points.PointsExchangeRecordDTO;
import com.czg.account.entity.*;
import com.czg.account.enums.PointsExchangeStatusEnum;
import com.czg.account.enums.PointsOrderPayTypeEnum;
import com.czg.account.param.PointsExchangeCfParam;
import com.czg.account.param.PointsExchangeRecordParam;
import com.czg.account.param.PointsOrderCreateParam;
import com.czg.account.param.PointsOrderPayParam;
import com.czg.account.service.PointsExchangeRecordService;
import com.czg.account.vo.PointsExchangeSummaryVo;
import com.czg.exception.CzgException;
import com.czg.sa.StpKit;
import com.czg.service.account.mapper.*;
import com.czg.utils.HttpContextUtil;
import com.czg.utils.PageUtil;
import com.czg.validator.ValidatorUtil;
import com.czg.validator.group.DefaultGroup;
import com.czg.validator.group.InsertGroup;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -42,6 +55,7 @@ public class PointsExchangeRecordServiceImpl extends ServiceImpl<PointsExchangeR
private final MemberPointsLogMapper memberPointsLogMapper;
private final ShopInfoMapper shopInfoMapper;
private final ShopMerchantMapper shopMerchantMapper;
private final PointsBasicSettingMapper pointsBasicSettingMapper;
private QueryWrapper buildQueryWrapper(PointsExchangeRecordParam param) {
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
@@ -107,6 +121,221 @@ public class PointsExchangeRecordServiceImpl extends ServiceImpl<PointsExchangeR
pointsGoodsSettingMapper.update(goods);
}
private Object[] verify(PointsOrderCreateParam param) {
ValidatorUtil.validateEntity(param, InsertGroup.class);
PointsBasicSetting basic = pointsBasicSettingMapper.selectOneByQuery(query().eq(PointsBasicSetting::getShopId, param.getShopId()));
if (basic == null) {
throw new CzgException("商家未配置积分锁客基本设置");
}
if (basic.getEnablePointsMall() != 1) {
throw new CzgException("积分商城未开启");
}
PointsGoodsSetting goods = pointsGoodsSettingMapper.selectOneById(param.getPointsGoodsId());
if (goods == null) {
throw new CzgException("兑换的商品信息不存在");
}
if (goods.getDelFlag() == 1) {
throw new CzgException("兑换的商品信息不存在");
}
param.setPointsGoodsName(goods.getGoodsName());
param.setGoodsImageUrl(goods.getGoodsImageUrl());
Integer status = goods.getStatus();
if (status != 1) {
throw new CzgException("兑换的商品已下架");
}
Integer quantity = goods.getQuantity();
if (quantity <= 0) {
throw new CzgException("兑换的商品库存不足");
}
MemberPoints memberPoints = memberPointsMapper.selectOneByQuery(query().eq(MemberPoints::getUserId, param.getUserId()));
if (memberPoints == null) {
throw new CzgException("会员积分不足无法兑换此商品");
}
Integer accountPoints = memberPoints.getAccountPoints();
Integer requiredPoints = goods.getRequiredPoints();
if (accountPoints < requiredPoints) {
throw new CzgException("会员积分不足无法兑换此商品");
}
return new Object[]{basic, goods, memberPoints};
}
@Override
public PointsExchangeRecordDTO create(PointsOrderCreateParam param) {
Long shopId = StpKit.USER.getShopId(0L);
param.setShopId(shopId);
Object[] verify = verify(param);
PointsBasicSetting basic = (PointsBasicSetting) verify[0];
PointsGoodsSetting goods = (PointsGoodsSetting) verify[1];
MemberPoints memberPoints = (MemberPoints) verify[2];
PointsExchangeRecord entity = BeanUtil.copyProperties(param, PointsExchangeRecord.class);
entity.setExtraPaymentAmount(goods.getExtraPrice());
entity.setSpendPoints(goods.getRequiredPoints());
Snowflake seqNo = IdUtil.getSnowflake(0, 0);
String orderNo = DateUtil.format(new Date(), "yyyyMMddHH") + StrUtil.subSuf(seqNo.nextIdStr(), -12);
entity.setOrderNo(orderNo);
entity.setStatus(PointsExchangeStatusEnum.UNPAID.value());
// 生成订单
super.save(entity);
return BeanUtil.copyProperties(entity, PointsExchangeRecordDTO.class);
}
@Override
@Transactional(rollbackFor = Exception.class)
public PointsExchangeRecordDTO pay(PointsOrderPayParam param) {
ValidatorUtil.validateEntity(param, DefaultGroup.class);
PointsExchangeRecord entity = super.getById(param.getId());
if (entity == null) {
throw new CzgException("订单不存在");
}
try {
PointsOrderCreateParam pointsOrderCreateParam = BeanUtil.copyProperties(entity, PointsOrderCreateParam.class);
verify(pointsOrderCreateParam);
} catch (Exception e) {
throw new CzgException(e.getMessage().concat(",请您取消订单"));
}
if (!PointsExchangeStatusEnum.UNPAID.value().equals(entity.getStatus())) {
throw new CzgException("订单状态异常,请刷新后重试");
}
entity.setPayType(param.getPayType().toUpperCase());
if (!PointsOrderPayTypeEnum.getValues().contains(param.getPayType().toUpperCase())) {
throw new CzgException("支付方式不合法");
}
// 设置支付方式
entity.setPayMethod(PointsOrderPayTypeEnum.getText(param.getPayType().toUpperCase()));
// 纯积分支付并且商品需要额外支付金额,需要抛出异常
if (PointsOrderPayTypeEnum.POINTS.getValue().equals(entity.getPayType()) && NumberUtil.isGreater(entity.getExtraPaymentAmount(), BigDecimal.ZERO)) {
throw new CzgException("此商品需要额外支付金额");
}
if (!PointsOrderPayTypeEnum.POINTS.getValue().equals(entity.getPayType()) && NumberUtil.equals(entity.getExtraPaymentAmount(), BigDecimal.ZERO)) {
throw new CzgException("此商品不需要额外支付金额");
}
// 如果不需要额外支付
if (NumberUtil.equals(entity.getExtraPaymentAmount(), BigDecimal.ZERO)) {
// 设置核销券码
entity.setCouponCode(IdUtil.getSnowflakeNextIdStr());
entity.setStatus("waiting");
entity.setPayTime(LocalDateTime.now());
entity.setPayType(param.getPayType().toUpperCase());
super.updateById(entity);
waitingAfter(entity);
return BeanUtil.copyProperties(entity, PointsExchangeRecordDTO.class);
}
if (StrUtil.isBlank(param.getOpenId())) {
throw new CzgException("openId/userId不能为空");
}
HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
String ip = null;
if (request != null) {
ip = JakartaServletUtil.getClientIP(request);
}
if (StrUtil.isBlank(ip)) {
throw new CzgException("无法获取用户ip地址");
}
// 需要额外支付
ShopInfo shopInfo = shopInfoMapper.selectOneById(entity.getShopId());
if (shopInfo == null) {
throw new CzgException("店铺信息不存在");
}
ShopMerchant shopMerchant = shopMerchantMapper.selectOneById(shopInfo.getId());
if (shopMerchant == null) {
throw new CzgException("支付通道不存在");
}
if ("alipay".equalsIgnoreCase(entity.getPayType()) && StrUtil.isBlank(shopMerchant.getAlipaySmallAppid())) {
throw new CzgException("店铺未配置支付宝小程序appId");
}
if (1 == 1) {
// TODO 对接支付接口
throw new CzgException("TODO暂未对接支付接口");
}
return null;
/*// 准备支付参数
// 应用ID
String appId = thirdApply.getAppId();
String appToken = thirdApply.getAppToken();
String storeId = thirdApply.getStoreId();
// 订单标题(商品名称)
String subject = entity.getPointsGoodsName();
// 商品描述
String body = StrUtil.format("兑换商品:{} * {}", entity.getPointsGoodsName(), "1");
// 交易金额 单位分 100 表示1元
long amount = NumberUtil.mul(entity.getExtraPaymentAmount(), new BigDecimal("100")).longValue();
// 支付方式
String payType = entity.getPayType().toUpperCase();
// 子商户APPID
String subAppid = thirdApply.getSmallAppid();
if ("alipay".equalsIgnoreCase(entity.getPayType())) {
subAppid = thirdApply.getAlipaySmallAppid();
}
// 用户唯一标识 微信支付时传入用户的openId支付宝支付和银联支付时传入用户的userId
String openId = record.getOpenId();
// 用户IP
String clientIp = record.getIp();
// 商户订单号 mchOrderNo
String mchOrderNo = IdUtil.getSnowflakeNextIdStr();
// 回调地址
String notifyUrl = pointsGoodsOrderCallBack;
// 支付成功后的跳转页面
String returnUrl = null;
PublicResp<WxScanPayResp> publicResp;
try {
publicResp = thirdPayService.scanpay(thirdUrl, appId, subject, body, amount, payType, subAppid, openId, clientIp, mchOrderNo, storeId, notifyUrl, returnUrl, appToken);
} catch (Exception e) {
log.error("拉起支付失败:", e);
throw new MsgException(StrUtil.format("拉起支付失败:{}", e.getMessage()));
}
if (publicResp == null) {
throw new MsgException("拉起支付失败:无响应");
}
if (!"000000".equals(publicResp.getCode())) {
throw new MsgException(publicResp.getMsg());
}
WxScanPayResp payResp = publicResp.getObjData();
if (!"TRADE_AWAIT".equals(payResp.getState())) {
throw new MsgException(StrUtil.format("拉起支付失败:{}", payResp.getState()));
}
entity.setPayOrderId(payResp.getPayOrderId());
super.updateById(entity);
entity.setPayInfo(payResp.getPayInfo());
return entity;*/
}
/**
* 支付完成的后续操作
*
* @param entity 积分兑换实体
*/
private void waitingAfter(PointsExchangeRecord entity) {
PointsGoodsSetting goods = pointsGoodsSettingMapper.selectOneById(entity.getPointsGoodsId());
if (goods == null) {
throw new CzgException("积分商品不存在");
}
MemberPoints memberPoints = memberPointsMapper.selectOneById(entity.getUserId());
if (memberPoints == null) {
throw new CzgException("会员积分不足无法兑换此商品");
}
Integer quantity = goods.getQuantity();
Integer accountPoints = memberPoints.getAccountPoints();
Integer requiredPoints = goods.getRequiredPoints();
// 扣减积分
memberPoints.setAccountPoints(accountPoints - requiredPoints);
memberPoints.setLastPointsChangeTime(LocalDateTime.now());
memberPoints.setLastFloatPoints(-requiredPoints);
memberPointsMapper.update(memberPoints);
// 扣减库存
goods.setQuantity(quantity - 1);
pointsGoodsSettingMapper.update(goods);
// 记录积分浮动流水
MemberPointsLog log = new MemberPointsLog();
log.setShopId(entity.getShopId());
log.setUserId(entity.getUserId());
log.setContent(StrUtil.format("兑换商品:{} * {}", entity.getPointsGoodsName(), "1"));
log.setFloatType("subtract");
log.setFloatPoints(-requiredPoints);
memberPointsLogMapper.insert(log);
}
@Override
public void cancel(PointsExchangeCfParam param) {
if (param.getId() == null) {
@@ -171,7 +400,7 @@ public class PointsExchangeRecordServiceImpl extends ServiceImpl<PointsExchangeR
if (NumberUtil.equals(entity.getExtraPaymentAmount(), BigDecimal.ZERO)) {
return;
}
// 需要额外支付
// 需要额外退款
ShopInfo shopInfo = shopInfoMapper.selectOneById(entity.getShopId());
if (shopInfo == null) {
throw new CzgException("店铺信息不存在");