会员积分代码提交
This commit is contained in:
parent
6488a55355
commit
9b1961c77a
|
|
@ -33,7 +33,7 @@ public class PointsBasicSettingController {
|
|||
@GetMapping()
|
||||
@OperationLog("积分基本设置-详情")
|
||||
//@SaAdminCheckPermission("basicSetting:info")
|
||||
public CzgResult<PointsBasicSettingDTO> getPointsBasicSettingByShopId() {
|
||||
public CzgResult<PointsBasicSettingDTO> getPointsBasicSetting() {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
PointsBasicSetting entity = pointsBasicSettingService.getById(shopId);
|
||||
PointsBasicSettingDTO data = BeanUtil.copyProperties(entity, PointsBasicSettingDTO.class);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.czg.controller.admin;
|
||||
|
||||
import com.czg.account.dto.points.PointsExchangeRecordDTO;
|
||||
import com.czg.account.param.PointsExchangeCfParam;
|
||||
import com.czg.account.param.PointsExchangeRecordParam;
|
||||
import com.czg.account.service.PointsExchangeRecordService;
|
||||
import com.czg.account.vo.PointsExchangeSummaryVo;
|
||||
|
|
@ -13,7 +12,7 @@ import org.springframework.web.bind.annotation.*;
|
|||
|
||||
|
||||
/**
|
||||
* 积分兑换
|
||||
* 积分兑换记录
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-25
|
||||
|
|
@ -25,7 +24,6 @@ public class PointsExchangeRecordController {
|
|||
|
||||
private final PointsExchangeRecordService pointsExchangeRecordService;
|
||||
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
|
|
@ -63,28 +61,6 @@ public class PointsExchangeRecordController {
|
|||
return CzgResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
@PostMapping("cancel")
|
||||
@OperationLog("积分兑换-取消")
|
||||
//@SaAdminCheckPermission("pointsExchangeRecord:cancel")
|
||||
public CzgResult<Void> cancel(@RequestBody PointsExchangeCfParam param) {
|
||||
pointsExchangeRecordService.cancel(param);
|
||||
return CzgResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 退单
|
||||
*/
|
||||
@PostMapping("refund")
|
||||
@OperationLog("积分兑换-退单")
|
||||
//@SaAdminCheckPermission("pointsExchangeRecord:refund")
|
||||
public CzgResult<Void> refund(@RequestBody PointsExchangeCfParam param) {
|
||||
pointsExchangeRecordService.refund(param);
|
||||
return CzgResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.czg.account.entity.MemberPoints;
|
|||
import com.czg.account.param.ConsumeAwardPointsParam;
|
||||
import com.czg.account.param.PayedDeductPointsParam;
|
||||
import com.czg.account.service.MemberPointsService;
|
||||
import com.czg.log.annotation.OperationLog;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
|
@ -14,7 +13,7 @@ import org.springframework.web.bind.annotation.*;
|
|||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 会员积分
|
||||
* 支付相关积分接口
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-25
|
||||
|
|
@ -27,10 +26,9 @@ public class UMemberPointsController {
|
|||
private final MemberPointsService memberPointsService;
|
||||
|
||||
/**
|
||||
* 获取会员积分等信息
|
||||
* 001-会员积分账户信息
|
||||
*/
|
||||
@GetMapping("my-points")
|
||||
@OperationLog("会员积分-获取会员积分等信息")
|
||||
public CzgResult<MemberPoints> getMemberPoints() {
|
||||
long userId = StpKit.USER.getLoginIdAsLong();
|
||||
MemberPoints data = memberPointsService.getMemberPoints(userId);
|
||||
|
|
@ -38,57 +36,52 @@ public class UMemberPointsController {
|
|||
}
|
||||
|
||||
/**
|
||||
* 获取订单可用积分及抵扣金额
|
||||
* 002-获取订单可用积分及抵扣金额(支付页面使用)
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param orderAmount 订单金额
|
||||
*/
|
||||
@GetMapping("calc-usable-points")
|
||||
@OperationLog("获取订单可用积分及抵扣金额")
|
||||
public CzgResult<OrderDeductionPointsDTO> getMemberUsablePoints(@RequestParam Long userId, @RequestParam BigDecimal orderAmount) {
|
||||
OrderDeductionPointsDTO usablePoints = memberPointsService.getMemberUsablePoints(userId, orderAmount);
|
||||
return CzgResult.success(usablePoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据抵扣金额计算所需积分
|
||||
* 004-根据抵扣金额计算所需积分
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param orderAmount 订单金额
|
||||
* @param deductionAmount 抵扣金额
|
||||
*/
|
||||
@GetMapping("calc-used-points")
|
||||
@OperationLog("根据抵扣金额计算所需积分")
|
||||
public CzgResult<Integer> calcUsedPoints(@RequestParam Long userId, @RequestParam BigDecimal orderAmount, @RequestParam BigDecimal deductionAmount) {
|
||||
int points = memberPointsService.calcUsedPoints(userId, orderAmount, deductionAmount);
|
||||
return CzgResult.success(points);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据积分计算可抵扣金额
|
||||
* 003-根据积分计算可抵扣金额
|
||||
*/
|
||||
@GetMapping("calc-deduction-amount")
|
||||
@OperationLog("根据积分计算可抵扣金额")
|
||||
public CzgResult<BigDecimal> calcDeductionAmount(@RequestParam Long memberId, @RequestParam BigDecimal orderAmount, @RequestParam Integer points) {
|
||||
BigDecimal deductionAmount = memberPointsService.calcDeductionAmount(memberId, orderAmount, points);
|
||||
return CzgResult.success(deductionAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付完成扣减积分(支付成功回调中使用)
|
||||
* 005-支付完成扣减积分(支付成功回调中使用)
|
||||
*/
|
||||
@PostMapping("payed-deduct-points")
|
||||
@OperationLog("支付完成扣减积分(支付成功回调中使用)")
|
||||
public CzgResult<Boolean> deductPoints(@RequestBody PayedDeductPointsParam param) {
|
||||
boolean ret = memberPointsService.deductPoints(param.getUserId(), param.getPoints(), param.getContent(), param.getOrderId());
|
||||
return CzgResult.success(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消费赠送积分(支付成功回调中使用)
|
||||
* 006-消费赠送积分(支付成功回调中使用)
|
||||
*/
|
||||
@PostMapping("consume-award-points")
|
||||
@OperationLog("消费赠送积分(支付成功回调中使用)")
|
||||
public CzgResult<Void> consumeAwardPoints(@RequestBody ConsumeAwardPointsParam param) {
|
||||
memberPointsService.consumeAwardPoints(param.getUserId(), param.getOrderId());
|
||||
return CzgResult.success();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
package com.czg.controller.user;
|
||||
|
||||
import com.czg.account.dto.points.PointsExchangeRecordDTO;
|
||||
import com.czg.account.dto.points.PointsGoodsSettingDTO;
|
||||
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.service.PointsGoodsSettingService;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
/**
|
||||
* 积分商城
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-25
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/user/points/mall")
|
||||
public class UPointsMallController {
|
||||
|
||||
private final PointsGoodsSettingService pointsGoodsSettingService;
|
||||
private final PointsExchangeRecordService pointsExchangeRecordService;
|
||||
|
||||
/**
|
||||
* 商品列表
|
||||
*/
|
||||
@GetMapping("/goods/page")
|
||||
public CzgResult<Page<PointsGoodsSettingDTO>> getPointsGoodsSettingPage(PointsGoodsSettingDTO param) {
|
||||
Page<PointsGoodsSettingDTO> data = pointsGoodsSettingService.getPointsGoodsSettingPage(param);
|
||||
return CzgResult.success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成订单
|
||||
*/
|
||||
@PostMapping("/order/create")
|
||||
public CzgResult<PointsExchangeRecordDTO> create(@RequestBody PointsOrderCreateParam param) {
|
||||
PointsExchangeRecordDTO data = pointsExchangeRecordService.create(param);
|
||||
return CzgResult.success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单
|
||||
*/
|
||||
@PostMapping("/order/cancel")
|
||||
public CzgResult<Void> cancel(@RequestBody PointsExchangeCfParam param) {
|
||||
pointsExchangeRecordService.cancel(param);
|
||||
return CzgResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付订单
|
||||
*/
|
||||
@PostMapping("/order/pay")
|
||||
public CzgResult<PointsExchangeRecordDTO> pay(@RequestBody PointsOrderPayParam param) {
|
||||
PointsExchangeRecordDTO data = pointsExchangeRecordService.pay(param);
|
||||
return CzgResult.success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退单
|
||||
*/
|
||||
@PostMapping("/order/refund")
|
||||
public CzgResult<Void> refund(@RequestBody PointsExchangeCfParam param) {
|
||||
pointsExchangeRecordService.refund(param);
|
||||
return CzgResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 我的兑换记录
|
||||
*/
|
||||
@GetMapping("/order/page")
|
||||
public CzgResult<Page<PointsExchangeRecordDTO>> getPointsExchangeRecordPage(PointsExchangeRecordParam param) {
|
||||
param.setUserId(StpKit.USER.getLoginIdAsLong());
|
||||
Page<PointsExchangeRecordDTO> page = pointsExchangeRecordService.getPointsExchangeRecordPage(param);
|
||||
return CzgResult.success(page);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package com.czg.account.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 积分兑换订单支付类型枚举
|
||||
*
|
||||
* @author tankaikai
|
||||
* @since 2025-02-26 10:29
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum PointsOrderPayTypeEnum {
|
||||
/**
|
||||
* 积分
|
||||
*/
|
||||
POINTS("POINTS", "积分支付"),
|
||||
|
||||
/**
|
||||
* 积分+微信
|
||||
*/
|
||||
WECHAT("WECHAT", "积分+微信"),
|
||||
/**
|
||||
* 积分+支付宝
|
||||
*/
|
||||
ALIPAY("ALIPAY", "积分+支付宝"),
|
||||
|
||||
;
|
||||
|
||||
private final String value;
|
||||
private final String text;
|
||||
|
||||
|
||||
public static List<String> getValues() {
|
||||
return Arrays.stream(values()).map(PointsOrderPayTypeEnum::getValue).toList();
|
||||
}
|
||||
|
||||
public static String getText(String value) {
|
||||
PointsOrderPayTypeEnum item = Arrays.stream(values()).filter(obj -> value.equals(obj.getValue())).findFirst().orElse(null);
|
||||
if (item != null) {
|
||||
return item.getText();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.czg.account.param;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.czg.validator.group.InsertGroup;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 积分订单创建入参
|
||||
*
|
||||
* @author tankaikai
|
||||
* @since 2025-02-26 10:03
|
||||
*/
|
||||
@Data
|
||||
public class PointsOrderCreateParam implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 店铺id
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@NotNull(message = "店铺id不能为空", groups = InsertGroup.class)
|
||||
private Long shopId;
|
||||
/**
|
||||
* 积分商品id
|
||||
*/
|
||||
@NotNull(message = "积分商品id不能为空", groups = InsertGroup.class)
|
||||
private Long pointsGoodsId;
|
||||
/**
|
||||
* 领取方式 self-自取 post-邮寄
|
||||
*/
|
||||
@NotBlank(message = "领取方式不能为空", groups = InsertGroup.class)
|
||||
private String pickupMethod;
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@NotNull(message = "用户id不能为空", groups = InsertGroup.class)
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
@NotBlank(message = "用户昵称不能为空", groups = InsertGroup.class)
|
||||
private String nickName;
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 会员头像
|
||||
*/
|
||||
private String avatarUrl;
|
||||
/**
|
||||
* 积分商品名称
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
private String pointsGoodsName;
|
||||
/**
|
||||
* 商品图片URL
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
private String goodsImageUrl;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.czg.account.param;
|
||||
|
||||
import com.czg.validator.group.DefaultGroup;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 积分订单支付入参
|
||||
*
|
||||
* @author tankaikai
|
||||
* @since 2025-02-26 10:03
|
||||
*/
|
||||
@Data
|
||||
public class PointsOrderPayParam implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 订单id(积分兑换记录id)
|
||||
*/
|
||||
@NotNull(message = "订单id不能为空", groups = DefaultGroup.class)
|
||||
private Long id;
|
||||
/**
|
||||
* 支付类型 POINTS-积分 WECHAT-微信 ALIPAY-支付宝 UNIONPAY-银联云闪付
|
||||
*/
|
||||
@NotBlank(message = "支付类型不能为空", groups = DefaultGroup.class)
|
||||
private String payType;
|
||||
/**
|
||||
* 微信openId/支付完userId
|
||||
*/
|
||||
@NotBlank(message = "openId不能为空", groups = DefaultGroup.class)
|
||||
private String openId;
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@ import com.czg.account.dto.points.PointsExchangeRecordDTO;
|
|||
import com.czg.account.entity.PointsExchangeRecord;
|
||||
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.vo.PointsExchangeSummaryVo;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
|
@ -39,6 +41,22 @@ public interface PointsExchangeRecordService extends IService<PointsExchangeReco
|
|||
*/
|
||||
void checkout(String couponCode);
|
||||
|
||||
/**
|
||||
* 创建兑换订单
|
||||
*
|
||||
* @param param 兑换入参
|
||||
* @return 兑换详情
|
||||
*/
|
||||
PointsExchangeRecordDTO create(PointsOrderCreateParam param);
|
||||
|
||||
/**
|
||||
* 支付兑换订单
|
||||
*
|
||||
* @param param 支付入参
|
||||
* @return 支付结果
|
||||
*/
|
||||
PointsExchangeRecordDTO pay(PointsOrderPayParam param);
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@ package com.czg.product.vo;
|
|||
import cn.hutool.core.convert.Convert;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.czg.product.dto.ProdSkuDTO;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品规格详情
|
||||
|
|
@ -105,6 +107,10 @@ public class ShopProductInfoVo implements Serializable {
|
|||
*/
|
||||
@JSONField(serialize = false)
|
||||
private LocalTime endTime;
|
||||
/**
|
||||
* 商品规格列表
|
||||
*/
|
||||
private List<ProdSkuDTO> skuList;
|
||||
|
||||
public Object getImages() {
|
||||
return JSON.parseArray(Convert.toStr(images, "[]"));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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("店铺信息不存在");
|
||||
|
|
|
|||
Loading…
Reference in New Issue