From 9b1961c77ab91e78e19d072bea74bc678710e6fb Mon Sep 17 00:00:00 2001 From: Tankaikai Date: Wed, 26 Feb 2025 14:14:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=9A=E5=91=98=E7=A7=AF=E5=88=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/PointsBasicSettingController.java | 2 +- .../admin/PointsExchangeRecordController.java | 26 +- .../user/UMemberPointsController.java | 21 +- .../user/UPointsMallController.java | 86 +++++++ .../account/enums/PointsOrderPayTypeEnum.java | 50 ++++ .../account/param/PointsOrderCreateParam.java | 67 +++++ .../account/param/PointsOrderPayParam.java | 37 +++ .../service/PointsExchangeRecordService.java | 18 ++ .../com/czg/product/vo/ShopProductInfoVo.java | 6 + .../service/impl/MemberPointsServiceImpl.java | 10 +- .../impl/PointsExchangeRecordServiceImpl.java | 231 +++++++++++++++++- 11 files changed, 508 insertions(+), 46 deletions(-) create mode 100644 cash-api/account-server/src/main/java/com/czg/controller/user/UPointsMallController.java create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/account/enums/PointsOrderPayTypeEnum.java create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/account/param/PointsOrderCreateParam.java create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/account/param/PointsOrderPayParam.java diff --git a/cash-api/account-server/src/main/java/com/czg/controller/admin/PointsBasicSettingController.java b/cash-api/account-server/src/main/java/com/czg/controller/admin/PointsBasicSettingController.java index 48f9352d..5e06ed72 100644 --- a/cash-api/account-server/src/main/java/com/czg/controller/admin/PointsBasicSettingController.java +++ b/cash-api/account-server/src/main/java/com/czg/controller/admin/PointsBasicSettingController.java @@ -33,7 +33,7 @@ public class PointsBasicSettingController { @GetMapping() @OperationLog("积分基本设置-详情") //@SaAdminCheckPermission("basicSetting:info") - public CzgResult getPointsBasicSettingByShopId() { + public CzgResult getPointsBasicSetting() { Long shopId = StpKit.USER.getShopId(0L); PointsBasicSetting entity = pointsBasicSettingService.getById(shopId); PointsBasicSettingDTO data = BeanUtil.copyProperties(entity, PointsBasicSettingDTO.class); diff --git a/cash-api/account-server/src/main/java/com/czg/controller/admin/PointsExchangeRecordController.java b/cash-api/account-server/src/main/java/com/czg/controller/admin/PointsExchangeRecordController.java index efca0861..1bf623b4 100644 --- a/cash-api/account-server/src/main/java/com/czg/controller/admin/PointsExchangeRecordController.java +++ b/cash-api/account-server/src/main/java/com/czg/controller/admin/PointsExchangeRecordController.java @@ -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 cancel(@RequestBody PointsExchangeCfParam param) { - pointsExchangeRecordService.cancel(param); - return CzgResult.success(); - } - - /** - * 退单 - */ - @PostMapping("refund") - @OperationLog("积分兑换-退单") - //@SaAdminCheckPermission("pointsExchangeRecord:refund") - public CzgResult refund(@RequestBody PointsExchangeCfParam param) { - pointsExchangeRecordService.refund(param); - return CzgResult.success(); - } - /** * 统计 */ diff --git a/cash-api/account-server/src/main/java/com/czg/controller/user/UMemberPointsController.java b/cash-api/account-server/src/main/java/com/czg/controller/user/UMemberPointsController.java index 995d9905..cae03b18 100644 --- a/cash-api/account-server/src/main/java/com/czg/controller/user/UMemberPointsController.java +++ b/cash-api/account-server/src/main/java/com/czg/controller/user/UMemberPointsController.java @@ -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 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 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 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 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 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 consumeAwardPoints(@RequestBody ConsumeAwardPointsParam param) { memberPointsService.consumeAwardPoints(param.getUserId(), param.getOrderId()); return CzgResult.success(); diff --git a/cash-api/account-server/src/main/java/com/czg/controller/user/UPointsMallController.java b/cash-api/account-server/src/main/java/com/czg/controller/user/UPointsMallController.java new file mode 100644 index 00000000..59484f31 --- /dev/null +++ b/cash-api/account-server/src/main/java/com/czg/controller/user/UPointsMallController.java @@ -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> getPointsGoodsSettingPage(PointsGoodsSettingDTO param) { + Page data = pointsGoodsSettingService.getPointsGoodsSettingPage(param); + return CzgResult.success(data); + } + + /** + * 生成订单 + */ + @PostMapping("/order/create") + public CzgResult create(@RequestBody PointsOrderCreateParam param) { + PointsExchangeRecordDTO data = pointsExchangeRecordService.create(param); + return CzgResult.success(data); + } + + /** + * 取消订单 + */ + @PostMapping("/order/cancel") + public CzgResult cancel(@RequestBody PointsExchangeCfParam param) { + pointsExchangeRecordService.cancel(param); + return CzgResult.success(); + } + + /** + * 支付订单 + */ + @PostMapping("/order/pay") + public CzgResult pay(@RequestBody PointsOrderPayParam param) { + PointsExchangeRecordDTO data = pointsExchangeRecordService.pay(param); + return CzgResult.success(data); + } + + /** + * 申请退单 + */ + @PostMapping("/order/refund") + public CzgResult refund(@RequestBody PointsExchangeCfParam param) { + pointsExchangeRecordService.refund(param); + return CzgResult.success(); + } + + /** + * 我的兑换记录 + */ + @GetMapping("/order/page") + public CzgResult> getPointsExchangeRecordPage(PointsExchangeRecordParam param) { + param.setUserId(StpKit.USER.getLoginIdAsLong()); + Page page = pointsExchangeRecordService.getPointsExchangeRecordPage(param); + return CzgResult.success(page); + } +} \ No newline at end of file diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/enums/PointsOrderPayTypeEnum.java b/cash-common/cash-common-service/src/main/java/com/czg/account/enums/PointsOrderPayTypeEnum.java new file mode 100644 index 00000000..4efa0591 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/enums/PointsOrderPayTypeEnum.java @@ -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 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; + } + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/param/PointsOrderCreateParam.java b/cash-common/cash-common-service/src/main/java/com/czg/account/param/PointsOrderCreateParam.java new file mode 100644 index 00000000..4c0d22c2 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/param/PointsOrderCreateParam.java @@ -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; +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/param/PointsOrderPayParam.java b/cash-common/cash-common-service/src/main/java/com/czg/account/param/PointsOrderPayParam.java new file mode 100644 index 00000000..813b170e --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/param/PointsOrderPayParam.java @@ -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; +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/service/PointsExchangeRecordService.java b/cash-common/cash-common-service/src/main/java/com/czg/account/service/PointsExchangeRecordService.java index 92f9ec6c..05b28e03 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/account/service/PointsExchangeRecordService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/service/PointsExchangeRecordService.java @@ -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 skuList; public Object getImages() { return JSON.parseArray(Convert.toStr(images, "[]")); diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/MemberPointsServiceImpl.java b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/MemberPointsServiceImpl.java index 0a55a387..7fe8e701 100644 --- a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/MemberPointsServiceImpl.java +++ b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/MemberPointsServiceImpl.java @@ -219,8 +219,8 @@ public class MemberPointsServiceImpl extends ServiceImpl 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