Browse Source

余额支付封装完成

mac 2 năm trước cách đây
mục cha
commit
dc1a8e9fd4
27 tập tin đã thay đổi với 752 bổ sung45 xóa
  1. 19 0
      kxs-common/kxs-common-core/src/main/java/com/kxs/common/core/util/SysUtils.java
  2. 21 0
      kxs-common/kxs-common-pay/src/main/java/com/kxs/common/pay/model/YuePayMessage.java
  3. 9 5
      kxs-common/kxs-common-pay/src/main/java/com/kxs/common/pay/service/yue/YuePayService.java
  4. 52 0
      kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/dto/kxsapp/shop/PayOrderDTO.java
  5. 1 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/constant/enums/ProductErrorTypeEnum.java
  6. 2 1
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/controller/kxsapp/ShopController.java
  7. 2 1
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/KxsShopOrderService.java
  8. 36 17
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/impl/KxsShopOrderServiceImpl.java
  9. 1 5
      kxs-user/kxs-user-api/pom.xml
  10. 39 0
      kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/dto/kxsapp/userAccount/PayRequestDTO.java
  11. 8 0
      kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/feign/RemoteKxsUserService.java
  12. 5 4
      kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/feign/RemoteYuePayService.java
  13. 94 0
      kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/model/KxsChangeType.java
  14. 101 0
      kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/model/KxsChangeTypeKind.java
  15. 121 0
      kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/model/KxsUserYuepay.java
  16. 30 0
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/constant/enums/YuePayStatusEnum.java
  17. 13 1
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/controller/kxsapp/UserAccountController.java
  18. 17 0
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/mapper/KxsChangeTypeKindMapper.java
  19. 17 0
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/mapper/KxsChangeTypeMapper.java
  20. 17 0
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/mapper/KxsUserYuepayMapper.java
  21. 5 1
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/service/KxsUserAmountService.java
  22. 15 0
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/service/KxsUserYuepayService.java
  23. 52 10
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/service/impl/KxsUserAmountServiceImpl.java
  24. 19 0
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/service/impl/KxsUserYuepayServiceImpl.java
  25. 18 0
      kxs-user/kxs-user-biz/src/main/resources/mapper/KxsChangeTypeKindMapper.xml
  26. 17 0
      kxs-user/kxs-user-biz/src/main/resources/mapper/KxsChangeTypeMapper.xml
  27. 21 0
      kxs-user/kxs-user-biz/src/main/resources/mapper/KxsUserYuepayMapper.xml

+ 19 - 0
kxs-common/kxs-common-core/src/main/java/com/kxs/common/core/util/SysUtils.java

@@ -3,7 +3,9 @@ package com.kxs.common.core.util;
 import cn.hutool.core.date.DatePattern;
 import cn.hutool.core.date.LocalDateTimeUtil;
 
+import java.text.SimpleDateFormat;
 import java.time.LocalDate;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -31,4 +33,21 @@ public class SysUtils {
         }
         return null;
     }
+
+    /**
+     * 交易流水号 ID
+     *
+     * @param id ID
+     * @return {@link String}
+     */
+    public static String generatePaymentId(Long id) {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+        String timestamp = sdf.format(new Date());
+
+        // 生成一个6位随机数作为流水号的后缀
+        int randomNum = (int) (Math.random() * 1000000);
+        String paymentId = timestamp + String.format("%06d", randomNum);
+
+        return paymentId + id;
+    }
 }

+ 21 - 0
kxs-common/kxs-common-pay/src/main/java/com/kxs/common/pay/model/YuePayMessage.java

@@ -4,6 +4,8 @@ import lombok.Builder;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
+import java.math.BigDecimal;
+
 /**
  * 余额同步回调消息
  *
@@ -26,4 +28,23 @@ public class YuePayMessage extends PayMessage {
      */
     private String outTradeNo;
 
+    /**
+     * 交易状态
+     */
+    private Integer tradeStatus;
+
+    /**
+     * 交易金额
+     */
+    private BigDecimal tradeAmount;
+
+    /**
+     * 订单标题
+     */
+    private String subject;
+
+    /**
+     * 回传参数
+     */
+    private String passbackParams;
 }

+ 9 - 5
kxs-common/kxs-common-pay/src/main/java/com/kxs/common/pay/service/yue/YuePayService.java

@@ -1,5 +1,6 @@
 package com.kxs.common.pay.service.yue;
 
+import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.extra.spring.SpringUtil;
 import com.alibaba.fastjson.JSON;
 import com.kxs.common.core.constant.enums.ErrorTypeEnum;
@@ -11,6 +12,7 @@ import com.kxs.common.pay.enums.PayPlatformEnum;
 import com.kxs.common.pay.handlers.PayMessageHandler;
 import com.kxs.common.pay.model.*;
 import com.kxs.common.pay.service.PayService;
+import com.kxs.user.api.dto.kxsapp.userAccount.PayRequestDTO;
 import com.kxs.user.api.feign.RemoteKxsUserService;
 import com.kxs.user.api.feign.RemoteYuePayService;
 import com.kxs.user.api.model.KxsUser;
@@ -37,13 +39,15 @@ public class YuePayService implements PayService {
     @Override
     public PayResponse appPay(PayRequest payReq) {
 
-        R<PayMessage> result = remoteYuePayService.yuePay(payReq);
-        if(result.getStatus() != 1){
+        PayRequestDTO payRequestDTO = new PayRequestDTO();
+        BeanUtil.copyProperties(payReq, payRequestDTO);
+        R result = remoteYuePayService.yuePay(payRequestDTO);
+        if (result.getStatus() != 1) {
             throw new GlobalCustomerException(result.getMsg());
         }
-        PayMessage payMessage = RetOps.of(result)
-                .getData()
-                .orElseThrow(() -> new GlobalCustomerException("yue pay is empty"));
+        YuePayMessage payMessage = BeanUtil.toBean(result.getData(), YuePayMessage.class);
+
+        Optional.ofNullable(payMessage).orElseThrow(() -> new GlobalCustomerException("yue pay is empty"));
 
         return PayResponse.builder()
                 .payPlatformEnum(PayPlatformEnum.YUEPAY)

+ 52 - 0
kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/dto/kxsapp/shop/PayOrderDTO.java

@@ -0,0 +1,52 @@
+package com.kxs.product.api.dto.kxsapp.shop;
+
+import com.kxs.product.api.model.KxsShopOrder;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 订单提交
+ *
+ * @author Lxq
+ * @date 2023-12-20
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class PayOrderDTO extends KxsShopOrder {
+
+    /**
+     * 订单ID
+     */
+    @Schema(description = "订单ID")
+    @NotNull(message = "订单ID不能为空")
+    private Integer id;
+
+    /**
+     * 提货方式 0自提 1邮寄
+     */
+    @NotNull(message = "提货方式不能为空")
+    @Schema(description = "提货方式 0自提 1邮寄")
+    private Integer getMode;
+
+    /**
+     * 支付渠道 0余额 1支付宝 2微信 3盟主储蓄金
+     */
+    @NotNull(message = "支付渠道不能为空")
+    @Schema(description = "支付渠道 0余额 1支付宝 2微信 3盟主储蓄金")
+    private Integer payType;
+
+    /**
+     * 支付密码
+     */
+    @Schema(description = "支付密码")
+    private String payPwd;
+
+    /**
+     * 备注
+     */
+    @Schema(description = "备注")
+    private String remark;
+
+}

+ 1 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/constant/enums/ProductErrorTypeEnum.java

@@ -15,6 +15,7 @@ public enum ProductErrorTypeEnum {
 
 	ORDER_EMPTY(-1, "订单不存在"),
 	ORDER_NO_CANCEL(-1, "订单已不能取消"),
+	ORDER_STATUS_ERROR(-1, "订单状态错误"),
 	ORDER_NO_CONFIRM(-1, "订单已不能收货"),
 	USER_IS_NOT_FIND(-1, "划拨对象不在您的权限范围"),
 	USER_IS_NOT_AUTH(-1, "该创客未实名认证"),

+ 2 - 1
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/controller/kxsapp/ShopController.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.kxs.common.core.util.R;
 import com.kxs.common.security.annotation.Inner;
+import com.kxs.product.api.dto.kxsapp.shop.PayOrderDTO;
 import com.kxs.product.api.model.KxsShopOrder;
 import com.kxs.product.api.dto.kxsapp.shop.GoodsSubmitDTO;
 import com.kxs.product.api.vo.kxsapp.shop.ShopGoodsListVO;
@@ -138,7 +139,7 @@ public class ShopController {
      * @return 发起支付
      */
     @PostMapping("/orderPay")
-    public R orderPay(@RequestBody KxsShopOrder param) {
+    public R orderPay(@RequestBody PayOrderDTO param) {
 
         return kxsShopOrderService.payOrder(param);
     }

+ 2 - 1
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/KxsShopOrderService.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.kxs.common.core.util.R;
+import com.kxs.product.api.dto.kxsapp.shop.PayOrderDTO;
 import com.kxs.product.api.model.KxsShopOrder;
 import com.kxs.product.api.dto.kxsapp.shop.GoodsSubmitDTO;
 import com.kxs.product.api.vo.kxsapp.shop.ShopOrderCountVO;
@@ -43,7 +44,7 @@ public interface KxsShopOrderService extends IService<KxsShopOrder> {
      * @param param 参数
      * @return {@link R}
      */
-    R payOrder(KxsShopOrder param);
+    R payOrder(PayOrderDTO param);
 
     /**
      * kxs app 取消订单

+ 36 - 17
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/impl/KxsShopOrderServiceImpl.java

@@ -1,5 +1,6 @@
 package com.kxs.product.biz.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.IdUtil;
 import com.alipay.api.AlipayApiException;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -12,11 +13,14 @@ import com.kxs.common.core.exception.GlobalCustomerException;
 import com.kxs.common.core.util.R;
 import com.kxs.common.pay.enums.PayConstants;
 import com.kxs.common.pay.enums.PayPlatformEnum;
+import com.kxs.common.pay.enums.PayStatusCommEnum;
 import com.kxs.common.pay.factory.PaymentFactory;
 import com.kxs.common.pay.model.PayRequest;
 import com.kxs.common.pay.model.PayResponse;
+import com.kxs.common.pay.model.YuePayMessage;
 import com.kxs.common.security.util.SecurityUtils;
 import com.kxs.product.api.dto.kxsapp.shop.GoodsSubmitDTO;
+import com.kxs.product.api.dto.kxsapp.shop.PayOrderDTO;
 import com.kxs.product.api.model.KxsShopGoods;
 import com.kxs.product.api.model.KxsShopOrder;
 import com.kxs.product.api.model.KxsShopOrderInfo;
@@ -28,6 +32,7 @@ import com.kxs.product.biz.mapper.KxsShopOrderInfoMapper;
 import com.kxs.product.biz.mapper.KxsShopOrderMapper;
 import com.kxs.product.biz.service.KxsShopOrderService;
 import com.kxs.user.api.feign.RemoteKxsUserService;
+import com.lly835.bestpay.enums.OrderStatusEnum;
 import io.seata.spring.annotation.GlobalTransactional;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -35,7 +40,9 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -119,7 +126,7 @@ public class KxsShopOrderServiceImpl extends ServiceImpl<KxsShopOrderMapper, Kxs
 
     @Override
     @GlobalTransactional(rollbackFor = Exception.class)
-    public R payOrder(KxsShopOrder param) {
+    public R payOrder(PayOrderDTO param) {
 
         if(param.getId() == null){
             return R.failed(ProductErrorTypeEnum.ORDER_EMPTY.getDescription());
@@ -131,45 +138,57 @@ public class KxsShopOrderServiceImpl extends ServiceImpl<KxsShopOrderMapper, Kxs
         if(order == null){
             return R.failed(ProductErrorTypeEnum.ORDER_EMPTY.getDescription());
         }
+        if(!Objects.equals(order.getStatus(), KxsShopEnum.ORDER_NO_PAY.getType())){
+            return R.failed(ProductErrorTypeEnum.ORDER_STATUS_ERROR.getDescription());
+        }
         List<KxsShopOrderInfo> kxsShopOrderInfos = orderInfoMapper.selectList(Wrappers.<KxsShopOrderInfo>lambdaQuery().eq(KxsShopOrderInfo::getOrderId, order.getId()));
         String subject = kxsShopOrderInfos.stream().map(KxsShopOrderInfo::getGoodsName).collect(Collectors.joining(","));
 
-        LambdaUpdateWrapper<KxsShopOrder> lambdaUpdateWrapper = Wrappers.<KxsShopOrder>lambdaUpdate().eq(KxsShopOrder::getId, param.getId());
-        lambdaUpdateWrapper.set(KxsShopOrder::getPayType, param.getPayType())
-                .set(KxsShopOrder::getGetMode, param.getGetMode())
-                .set(KxsShopOrder::getRemark, param.getRemark());
+        //支付宝支付
+        if(param.getPayType().equals(KxsShopEnum.ALI_PAY.getType())){
+            return this.aliPay(order, subject);
+        }
 
         //余额支付
         if(param.getPayType().equals(KxsShopEnum.YUE_PAY.getType())){
+            Optional.ofNullable(param.getPayPwd()).orElseThrow(() -> new GlobalCustomerException("请输入支付密码"));
+            //校验支付密码
+            R<Boolean> booleanR = remoteKxsUserService.checkPayPwd(param.getPayPwd());
+            if(booleanR.getStatus() != 1 || !booleanR.getData()){
+                return R.failed("支付密码错误");
+            }
+
+            LambdaUpdateWrapper<KxsShopOrder> lambdaUpdateWrapper = Wrappers.<KxsShopOrder>lambdaUpdate().eq(KxsShopOrder::getId, param.getId());
+            lambdaUpdateWrapper.set(KxsShopOrder::getPayType, param.getPayType())
+                    .set(KxsShopOrder::getGetMode, param.getGetMode())
+                    .set(KxsShopOrder::getRemark, param.getRemark());
+
             PayRequest payReq = new PayRequest();
             payReq.setPayTypeEnum(PayPlatformEnum.ALIPAY);
             payReq.setOutTradeNo(order.getOrderSn());
             payReq.setSubject(subject);
-            payReq.setTotalAmount(param.getPayPrice().doubleValue());
+            payReq.setTotalAmount(order.getPayPrice().doubleValue());
             try {
                 PayResponse payResponse = paymentFactory.getPayService(PayPlatformEnum.YUEPAY.getType()).appPay(payReq);
-                if (PayConstants.YUE_PAY_SUCCESS.equals(payResponse.getResult())) {
+
+                YuePayMessage payMessage = BeanUtil.toBean(payResponse, YuePayMessage.class);
+                if (payMessage != null) {
                     //支付成功
                     lambdaUpdateWrapper.set(KxsShopOrder::getStatus, KxsShopEnum.ORDER_NO_SEND.getType());
-
-
-
+                    lambdaUpdateWrapper.set(KxsShopOrder::getPayTime, LocalDateTime.now());
                 }else{
                     return R.failed(payResponse.getResult());
                 }
             } catch (AlipayApiException e) {
                 throw new GlobalCustomerException("余额支付异常");
             }
+            //修改订单信息
+            this.update(lambdaUpdateWrapper);
+            //TODO 余额走支付接下来的逻辑
         }
-        //修改订单信息
-        this.update(lambdaUpdateWrapper);
 
-        //支付宝支付
-        if(param.getPayType().equals(KxsShopEnum.ALI_PAY.getType())){
-            return this.aliPay(order, subject);
-        }
 
-        return R.failed("未知的支付方式!");
+        return R.ok();
     }
 
 

+ 1 - 5
kxs-user/kxs-user-api/pom.xml

@@ -50,10 +50,6 @@
             <groupId>com.kxs</groupId>
             <artifactId>kxs-common-seata</artifactId>
         </dependency>
-        <!-- seata -->
-        <dependency>
-            <groupId>com.kxs</groupId>
-            <artifactId>kxs-common-pay</artifactId>
-        </dependency>
+
     </dependencies>
 </project>

+ 39 - 0
kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/dto/kxsapp/userAccount/PayRequestDTO.java

@@ -0,0 +1,39 @@
+package com.kxs.user.api.dto.kxsapp.userAccount;
+
+import lombok.Data;
+
+/**
+ * 付款请求
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-24
+ */
+@Data
+public class PayRequestDTO {
+
+
+    /**
+     * 商户网站唯一订单号
+     */
+    private String outTradeNo;
+
+    /**
+     * 订单总金额,单位为元,精确到小数点后两位
+     */
+    private Double totalAmount;
+
+    /**
+     * 订单标题
+     */
+    private String subject;
+
+    /**
+     * 订单包含的商品列表信息,json格式
+     */
+    private String goodsDetail;
+
+    /**
+     * 公用回传参数
+     */
+    private String passbackParams;
+}

+ 8 - 0
kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/feign/RemoteKxsUserService.java

@@ -147,4 +147,12 @@ public interface RemoteKxsUserService {
 	@GetExchange("/leader/getDateBetweenLeaders")
 	R<List<KxsLeader>> getDateBetweenLeaders(@RequestParam("startTime") String startTime, @RequestParam("endTime") String endTime, @RequestHeader(SecurityConstants.FROM) String from);
 
+	/**
+	 * 校验支付密码
+	 *
+	 * @param payPwd 支付 PWD
+	 * @return {@link R}
+	 */
+	@GetExchange("/app/checkPayPwd")
+	R<Boolean> checkPayPwd(@RequestParam("payPwd") String payPwd);
 }

+ 5 - 4
kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/feign/RemoteYuePayService.java

@@ -2,11 +2,12 @@
 package com.kxs.user.api.feign;
 
 import com.kxs.common.core.util.R;
-import com.kxs.common.pay.model.PayMessage;
-import com.kxs.common.pay.model.PayRequest;
-import com.kxs.common.pay.model.PayResponse;
+import com.kxs.user.api.dto.kxsapp.userAccount.PayRequestDTO;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.service.annotation.PostExchange;
 
+import java.util.Map;
+
 /**
  * @author Lxq
  * @date 2023/6/22
@@ -17,5 +18,5 @@ public interface RemoteYuePayService {
 	 * 余额支付
 	 */
 	@PostExchange("/userAccount/yuePay")
-	R<PayMessage> yuePay(PayRequest payReq);
+	R yuePay(@RequestBody PayRequestDTO payReq);
 }

+ 94 - 0
kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/model/KxsChangeType.java

@@ -0,0 +1,94 @@
+package com.kxs.user.api.model;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 收支明细分类表(KxsChangeType)表实体类
+ *
+ * @author 系统
+ * @since 2024-04-29 14:20:11
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class KxsChangeType extends Model<KxsChangeType> implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    
+    
+    /**
+     * 主键ID
+     */
+    @Schema(description = "主键ID")
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+
+    /**
+     * 新增时间
+     */
+    @TableField(fill = FieldFill.INSERT)
+    @Schema(description = "新增时间")
+    private LocalDateTime createTime;
+
+
+    /**
+     * 更新时间
+     */
+    @TableField(fill = FieldFill.UPDATE)
+    @Schema(description = "更新时间")
+    private LocalDateTime updateTime;
+
+
+    /**
+     * 删除标记,0未删除,1已删除
+     */
+    @Schema(description = "删除标记,0未删除,1已删除")
+    private Integer delFlag;
+
+
+    /**
+     * 版本
+     */
+    @Schema(description = "版本")
+    private Integer version;
+
+
+    /**
+     * 分类名称
+     */
+    @Schema(description = "分类名称")
+    private String name;
+
+
+    /**
+     * 收支类型 1新增 2减少
+     */
+    @Schema(description = "收支类型 1新增 2减少")
+    private String kind;
+
+
+    /**
+     * 排序
+     */
+    @Schema(description = "排序")
+    private Integer sort;
+
+
+
+
+}
+

+ 101 - 0
kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/model/KxsChangeTypeKind.java

@@ -0,0 +1,101 @@
+package com.kxs.user.api.model;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 收支明细分类明细表(KxsChangeTypeKind)表实体类
+ *
+ * @author 系统
+ * @since 2024-04-29 14:20:11
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class KxsChangeTypeKind extends Model<KxsChangeTypeKind> implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    
+    
+    /**
+     * 主键ID
+     */
+    @Schema(description = "主键ID")
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+
+    /**
+     * 新增时间
+     */
+    @TableField(fill = FieldFill.INSERT)
+    @Schema(description = "新增时间")
+    private LocalDateTime createTime;
+
+
+    /**
+     * 更新时间
+     */
+    @TableField(fill = FieldFill.UPDATE)
+    @Schema(description = "更新时间")
+    private LocalDateTime updateTime;
+
+
+    /**
+     * 删除标记,0未删除,1已删除
+     */
+    @Schema(description = "删除标记,0未删除,1已删除")
+    private Integer delFlag;
+
+
+    /**
+     * 版本
+     */
+    @Schema(description = "版本")
+    private Integer version;
+
+
+    /**
+     * 分类ID
+     */
+    @Schema(description = "分类ID")
+    private Integer changeTypeId;
+
+
+    /**
+     * 类型名称
+     */
+    @Schema(description = "类型名称")
+    private String name;
+
+
+    /**
+     * 排序
+     */
+    @Schema(description = "排序")
+    private Integer sort;
+
+
+    /**
+     * 收支类型 add新增 sub减少
+     */
+    @Schema(description = "收支类型 add新增 sub减少")
+    private String kind;
+
+
+
+
+}
+

+ 121 - 0
kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/model/KxsUserYuepay.java

@@ -0,0 +1,121 @@
+package com.kxs.user.api.model;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 余额支付交易账单表(KxsUserYuepay)表实体类
+ *
+ * @author 系统
+ * @since 2024-04-29 14:20:11
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class KxsUserYuepay extends Model<KxsUserYuepay> implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    
+    
+    /**
+     * 主键ID
+     */
+    @Schema(description = "主键ID")
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+
+    /**
+     * 新增时间
+     */
+    @TableField(fill = FieldFill.INSERT)
+    @Schema(description = "新增时间")
+    private LocalDateTime createTime;
+
+
+    /**
+     * 更新时间
+     */
+    @TableField(fill = FieldFill.UPDATE)
+    @Schema(description = "更新时间")
+    private LocalDateTime updateTime;
+
+
+    /**
+     * 删除标记,0未删除,1已删除
+     */
+    @Schema(description = "删除标记,0未删除,1已删除")
+    @TableLogic
+    @TableField(fill = FieldFill.INSERT)
+    private String delFlag;
+
+
+    /**
+     * 版本
+     */
+    @Schema(description = "版本")
+    private Integer version;
+
+
+    /**
+     * 交易编号
+     */
+    @Schema(description = "交易编号")
+    private String tradeNo;
+
+
+    /**
+     * 订单交易编号
+     */
+    @Schema(description = "订单交易编号")
+    private String outTradeNo;
+
+
+    /**
+     * 用户ID
+     */
+    @Schema(description = "用户ID")
+    private Long userId;
+
+
+    /**
+     * 订单标题
+     */
+    @Schema(description = "订单标题")
+    private String subject;
+
+
+    /**
+     * 公共参数 原路返回
+     */
+    @Schema(description = "公共参数 原路返回")
+    private String passbackParams;
+
+
+    /**
+     * 交易状态
+     */
+    @Schema(description = "交易状态")
+    private Integer tradeStatus;
+
+
+    /**
+     * 交易金额
+     */
+    @Schema(description = "交易金额")
+    private BigDecimal tradeAmount;
+
+
+
+
+}
+

+ 30 - 0
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/constant/enums/YuePayStatusEnum.java

@@ -0,0 +1,30 @@
+package com.kxs.user.biz.constant.enums;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+
+/**
+ * 余额支付状态类型枚举
+ *
+ * @author 没秃顶的码农
+ * @date 2024-01-02
+ */
+@Getter
+@RequiredArgsConstructor
+public enum YuePayStatusEnum {
+
+
+    SUCCESS(1, "支付成功"),
+    RETURN(-1, "退款");
+
+    /**
+     * 类型
+     */
+    private final Integer type;
+
+    /**
+     * 描述
+     */
+    private final String description;
+}

+ 13 - 1
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/controller/kxsapp/UserAccountController.java

@@ -3,6 +3,7 @@ package com.kxs.user.biz.controller.kxsapp;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.kxs.common.core.util.R;
+import com.kxs.user.api.dto.kxsapp.userAccount.PayRequestDTO;
 import com.kxs.user.api.dto.kxsapp.userAccount.UserAmountVariationListDTO;
 import com.kxs.user.api.dto.kxsapp.userAccount.WithdrawDepositDTO;
 import com.kxs.user.api.model.KxsUserAdvance;
@@ -165,6 +166,7 @@ public class UserAccountController {
 
         return R.ok(kxsUserAmountLogService.variationList(changeTypeId));
     }
+
     /**
      * 余额变动
      *
@@ -178,8 +180,18 @@ public class UserAccountController {
         return R.ok(kxsUserAmountService.userAmountChange(userAmountLog));
     }
 
+    /**
+     * 内部调用
+     * 余额支付
+     *
+     * @param payReq 支付参数
+     * @return {@link R}
+     */
+    @PostMapping("/yuePay")
+    public R yuePay(@RequestBody PayRequestDTO payReq){
 
-
+        return kxsUserAmountService.yuePay(payReq);
+    }
 
 
 }

+ 17 - 0
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/mapper/KxsChangeTypeKindMapper.java

@@ -0,0 +1,17 @@
+package com.kxs.user.biz.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.kxs.user.api.model.KxsChangeTypeKind;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 收支明细分类明细表(KxsChangeTypeKind)表数据库访问层
+ *
+ * @author 系统
+ * @since 2024-04-29 14:20:11
+ */
+@Mapper
+public interface KxsChangeTypeKindMapper extends BaseMapper<KxsChangeTypeKind> {
+
+}
+

+ 17 - 0
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/mapper/KxsChangeTypeMapper.java

@@ -0,0 +1,17 @@
+package com.kxs.user.biz.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.kxs.user.api.model.KxsChangeType;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 收支明细分类表(KxsChangeType)表数据库访问层
+ *
+ * @author 系统
+ * @since 2024-04-29 14:20:11
+ */
+@Mapper
+public interface KxsChangeTypeMapper extends BaseMapper<KxsChangeType> {
+
+}
+

+ 17 - 0
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/mapper/KxsUserYuepayMapper.java

@@ -0,0 +1,17 @@
+package com.kxs.user.biz.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.kxs.user.api.model.KxsUserYuepay;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 余额支付交易账单表(KxsUserYuepay)表数据库访问层
+ *
+ * @author 系统
+ * @since 2024-04-29 14:20:11
+ */
+@Mapper
+public interface KxsUserYuepayMapper extends BaseMapper<KxsUserYuepay> {
+
+}
+

+ 5 - 1
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/service/KxsUserAmountService.java

@@ -2,7 +2,7 @@ package com.kxs.user.biz.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.kxs.common.core.util.R;
-import com.kxs.user.api.dto.kxsapp.userAccount.WithdrawDepositDTO;
+import com.kxs.user.api.dto.kxsapp.userAccount.PayRequestDTO;
 import com.kxs.user.api.model.KxsUserAmount;
 import com.kxs.user.api.model.KxsUserAmountLog;
 import com.kxs.user.api.vo.kxsapp.userAccount.MyAccountVO;
@@ -30,5 +30,9 @@ public interface KxsUserAmountService extends IService<KxsUserAmount> {
      */
     R userAmountChange(KxsUserAmountLog userAmountLog);
 
+    /**
+     * 余额支付
+     */
+    R yuePay(PayRequestDTO payReq);
 }
 

+ 15 - 0
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/service/KxsUserYuepayService.java

@@ -0,0 +1,15 @@
+package com.kxs.user.biz.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.kxs.user.api.model.KxsUserYuepay;
+
+/**
+ * 余额支付交易账单表(KxsUserYuepay)表服务接口
+ *
+ * @author 系统
+ * @since 2024-04-29 14:20:11
+ */
+public interface KxsUserYuepayService extends IService<KxsUserYuepay> {
+
+}
+

+ 52 - 10
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/service/impl/KxsUserAmountServiceImpl.java

@@ -5,20 +5,27 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.kxs.common.core.constant.enums.KindTypeEnum;
 import com.kxs.common.core.util.R;
+import com.kxs.common.core.util.SysUtils;
+import com.kxs.common.mybatis.handler.MonthTableNameHandler;
 import com.kxs.common.security.util.SecurityUtils;
-import com.kxs.user.api.dto.kxsapp.userAccount.WithdrawDepositDTO;
+import com.kxs.user.api.dto.kxsapp.userAccount.PayRequestDTO;
+import com.kxs.user.api.model.KxsUserAmount;
 import com.kxs.user.api.model.KxsUserAmountLog;
+import com.kxs.user.api.model.KxsUserYuepay;
 import com.kxs.user.api.vo.kxsapp.userAccount.MyAccountVO;
+import com.kxs.user.biz.constant.enums.YuePayStatusEnum;
 import com.kxs.user.biz.mapper.KxsUserAmountMapper;
-import com.kxs.user.api.model.KxsUserAmount;
 import com.kxs.user.biz.service.KxsUserAmountLogService;
 import com.kxs.user.biz.service.KxsUserAmountService;
+import com.kxs.user.biz.service.KxsUserYuepayService;
 import lombok.RequiredArgsConstructor;
+import lombok.Synchronized;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
 import java.util.Objects;
+import java.util.UUID;
 
 /**
  * 用户账户表(KxsUserAmount)表服务实现类
@@ -31,6 +38,9 @@ import java.util.Objects;
 public class KxsUserAmountServiceImpl extends ServiceImpl<KxsUserAmountMapper, KxsUserAmount> implements KxsUserAmountService {
 
     private final KxsUserAmountLogService kxsUserAmountLogService;
+
+    private final KxsUserYuepayService kxsUserYuepayService;
+
     @Override
     public MyAccountVO myAccount() {
 
@@ -61,8 +71,12 @@ public class KxsUserAmountServiceImpl extends ServiceImpl<KxsUserAmountMapper, K
             afterAmount = NumberUtil.sub(userAmount.getAmount(), userAmountLog.getAmount());
         }
         userAmountLog.setAfterAmount(afterAmount);
-        userAmount.setAmount(NumberUtil.add(afterAmount));
+        userAmount.setAmount(afterAmount);
+
+        MonthTableNameHandler.setData(MonthTableNameHandler.getThisMoth());
         kxsUserAmountLogService.save(userAmountLog);
+        //删除线程,避免线程污染
+        MonthTableNameHandler.removeData();
 
         this.updateById(userAmount);
 
@@ -70,15 +84,43 @@ public class KxsUserAmountServiceImpl extends ServiceImpl<KxsUserAmountMapper, K
         return R.ok(Boolean.FALSE);
     }
 
+    @Override
+    @Synchronized
+    public R yuePay(PayRequestDTO payReq) {
 
+        Long userId = SecurityUtils.getUser().getId();
+        KxsUserAmount userAmount = this.getOne(Wrappers.<KxsUserAmount>lambdaQuery()
+                .eq(KxsUserAmount::getUserId, userId));
+        if(BigDecimal.valueOf(payReq.getTotalAmount()).compareTo(userAmount.getAmount()) > 0){
+            return R.failed("余额不足");
+        }
+        long count = kxsUserYuepayService.count(Wrappers.<KxsUserYuepay>lambdaQuery().eq(KxsUserYuepay::getOutTradeNo, payReq.getOutTradeNo()));
+        if(count > 1){
+            return R.failed("该订单号已支付");
+        }
 
-
-
-
-
-
-
-
+        KxsUserAmountLog kxsUserAmountLog = new KxsUserAmountLog();
+        kxsUserAmountLog.setAmount(BigDecimal.valueOf(payReq.getTotalAmount()));
+        kxsUserAmountLog.setUserId(userId.intValue());
+        //余额支付
+        kxsUserAmountLog.setVariationType(20);
+        kxsUserAmountLog.setRemark("购买" + payReq.getSubject());
+        kxsUserAmountLog.setKind(KindTypeEnum.SUB.getType());
+        this.userAmountChange(kxsUserAmountLog);
+        //余额支付账单
+        String tradeNo = SysUtils.generatePaymentId(userId);
+        KxsUserYuepay kxsUserYuepay = new KxsUserYuepay();
+        kxsUserYuepay.setSubject(payReq.getSubject());
+        kxsUserYuepay.setUserId(userId);
+        kxsUserYuepay.setTradeNo(tradeNo);
+        kxsUserYuepay.setPassbackParams(payReq.getPassbackParams());
+        kxsUserYuepay.setTradeStatus(YuePayStatusEnum.SUCCESS.getType());
+        kxsUserYuepay.setOutTradeNo(payReq.getOutTradeNo());
+        kxsUserYuepay.setTradeAmount(BigDecimal.valueOf(payReq.getTotalAmount()));
+        kxsUserYuepayService.save(kxsUserYuepay);
+
+        return R.ok(kxsUserYuepay);
+    }
 
 
 }

+ 19 - 0
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/service/impl/KxsUserYuepayServiceImpl.java

@@ -0,0 +1,19 @@
+package com.kxs.user.biz.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.kxs.user.biz.mapper.KxsUserYuepayMapper;
+import com.kxs.user.api.model.KxsUserYuepay;
+import com.kxs.user.biz.service.KxsUserYuepayService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 余额支付交易账单表(KxsUserYuepay)表服务实现类
+ *
+ * @author 系统
+ * @since 2024-04-29 14:20:11
+ */
+@Service("kxsUserYuepayService")
+public class KxsUserYuepayServiceImpl extends ServiceImpl<KxsUserYuepayMapper, KxsUserYuepay> implements KxsUserYuepayService {
+
+}
+

+ 18 - 0
kxs-user/kxs-user-biz/src/main/resources/mapper/KxsChangeTypeKindMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.kxs.user.biz.mapper.KxsChangeTypeKindMapper">
+
+    <resultMap type="com.kxs.user.api.model.KxsChangeTypeKind" id="KxsChangeTypeKindMap">
+        <result column="id" property="id" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="del_flag" property="delFlag" />
+        <result column="version" property="version" />
+        <result column="change_type_id" property="changeTypeId" />
+        <result column="name" property="name" />
+        <result column="sort" property="sort" />
+        <result column="kind" property="kind" />
+
+    </resultMap>
+
+</mapper>

+ 17 - 0
kxs-user/kxs-user-biz/src/main/resources/mapper/KxsChangeTypeMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.kxs.user.biz.mapper.KxsChangeTypeMapper">
+
+    <resultMap type="com.kxs.user.api.model.KxsChangeType" id="KxsChangeTypeMap">
+        <result column="id" property="id" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="del_flag" property="delFlag" />
+        <result column="version" property="version" />
+        <result column="name" property="name" />
+        <result column="kind" property="kind" />
+        <result column="sort" property="sort" />
+
+    </resultMap>
+
+</mapper>

+ 21 - 0
kxs-user/kxs-user-biz/src/main/resources/mapper/KxsUserYuepayMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.kxs.user.biz.mapper.KxsUserYuepayMapper">
+
+    <resultMap type="com.kxs.user.api.model.KxsUserYuepay" id="KxsUserYuepayMap">
+        <result column="id" property="id" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="del_flag" property="delFlag" />
+        <result column="version" property="version" />
+        <result column="trade_no" property="tradeNo" />
+        <result column="out_trade_no" property="outTradeNo" />
+        <result column="user_id" property="userId" />
+        <result column="subject" property="subject" />
+        <result column="passback_params" property="passbackParams" />
+        <result column="trade_status" property="tradeStatus" />
+        <result column="trade_amount" property="tradeAmount" />
+
+    </resultMap>
+
+</mapper>