Преглед на файлове

支付模块: paddle 取消订阅,更新订阅

wangPH преди 2 години
родител
ревизия
a289f44f21
променени са 54 файла, в които са добавени 1424 реда и са изтрити 136 реда
  1. 2 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/constant/OrderConstant.java
  2. 3 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/constant/PaddleAPIConstant.java
  3. 2 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/constant/SubscriptionConstant.java
  4. 20 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/ChargebackOrderDTO.java
  5. 5 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatOrderDTO.java
  6. 13 3
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatOrderManualDTO.java
  7. 4 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatSubscriptionDTO.java
  8. 39 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatSubscriptionManualDTO.java
  9. 1 1
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/PaddleWebhookDTO.java
  10. 86 1
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/feign/PaymentApi.java
  11. 51 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/feign/hystrix/PaymentHystrix.java
  12. 26 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/paddle/NextPayment.java
  13. 58 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/paddle/UpdateSubscription.java
  14. 26 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/paddle/UpdateSubscriptionResult.java
  15. 93 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/OrdersVO.java
  16. 122 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/SubscriptionsVO.java
  17. 27 0
      pdf-office-api/pdf-office-api-product/pom.xml
  18. 15 0
      pdf-office-api/pdf-office-api-product/src/main/java/cn/kdan/cloud/pdf/office/api/product/annotation/EnableProductApiClient.java
  19. 11 0
      pdf-office-api/pdf-office-api-product/src/main/java/cn/kdan/cloud/pdf/office/api/product/config/PdfOfficeApiProductConfig.java
  20. 1 1
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/ProductListDTO.java
  21. 28 0
      pdf-office-api/pdf-office-api-product/src/main/java/cn/kdan/cloud/pdf/office/api/product/feign/ProductApi.java
  22. 25 0
      pdf-office-api/pdf-office-api-product/src/main/java/cn/kdan/cloud/pdf/office/api/product/feign/hystrix/ProductHystrix.java
  23. 1 1
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/ProductPriceVo.java
  24. 1 1
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/ProductVO.java
  25. 1 0
      pdf-office-api/pom.xml
  26. 2 2
      pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/config/RabbitMqConfig.java
  27. 4 0
      pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/constant/CommonConstant.java
  28. 12 0
      pdf-office-payment/pom.xml
  29. 2 0
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/PDFOfficePaymentApplication.java
  30. 74 10
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/client/PaddleClient.java
  31. 128 0
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/controller/PaymentController.java
  32. 4 2
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/entity/Orders.java
  33. 3 3
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/entity/Subscriptions.java
  34. 2 2
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/mapper/OrdersMapper.java
  35. 2 2
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/mapper/SubscriptionsMapper.java
  36. 13 6
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/OrdersService.java
  37. 26 6
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/SubscriptionsService.java
  38. 54 27
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/OrdersServiceImpl.java
  39. 19 5
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/PaddleWebhookServiceImpl.java
  40. 89 35
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/SubscriptionsServiceImpl.java
  41. 1 1
      pdf-office-payment/src/main/resources/mapper/OrdersMapper.xml
  42. 1 1
      pdf-office-payment/src/main/resources/mapper/SubscriptionsMapper.xml
  43. 2 2
      pdf-office-payment/src/test/java/cn/kdan/cloud/pdf/office/payment/PaddleTest.java
  44. 154 0
      pdf-office-product/pom.xml
  45. 25 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/PDFOfficeProductApplication.java
  46. 37 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/controller/ProductController.java
  47. 2 1
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/entity/Product.java
  48. 2 2
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/mapper/ProductMapper.java
  49. 7 9
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/ProductService.java
  50. 11 11
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/ProductServiceImpl.java
  51. 12 0
      pdf-office-product/src/main/resources/bootstrap.properties
  52. 73 0
      pdf-office-product/src/main/resources/logback-spring.xml
  53. 1 1
      pdf-office-payment/src/main/resources/mapper/ProductMapper.xml
  54. 1 0
      pom.xml

+ 2 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/constant/OrderConstant.java

@@ -15,4 +15,6 @@ public interface OrderConstant {
 
     Integer CLOSED = 3;
 
+    Integer REFUND = 4;
+
 }

+ 3 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/constant/PaddleAPIConstant.java

@@ -8,6 +8,9 @@ package cn.kdan.cloud.pdf.office.api.payment.constant;
 public interface PaddleAPIConstant {
 
     String CREAT_PAY_LINK = "/product/generate_pay_link";
+    String CANCEL_SUBSCRIPTION = "/subscription/users_cancel";
+    String UPDATE_SUBSCRIPTION = "/subscription/users/update";
+
     String VENDORID = "vendor_id";
     String VENDORAUTHCODE = "vendor_auth_code";
     /**

+ 2 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/constant/SubscriptionConstant.java

@@ -12,5 +12,7 @@ public interface SubscriptionConstant {
     int actived = 3;
     int expired = 4;
     int refunded = 5;
+//    // 试用
+//    int trial = 6;
 
 }

+ 20 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/ChargebackOrderDTO.java

@@ -0,0 +1,20 @@
+package cn.kdan.cloud.pdf.office.api.payment.dto;
+
+import lombok.Data;
+import lombok.ToString;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/1
+ */
+@Data
+@ToString
+public class ChargebackOrderDTO implements Serializable {
+    @NotNull(message = "orderId 不能为空")
+    private String orderId;
+    @NotNull(message = "subscriptionId 不能为空")
+    private String subscriptionId;
+
+}

+ 5 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatOrderDTO.java

@@ -3,6 +3,7 @@ package cn.kdan.cloud.pdf.office.api.payment.dto;
 import cn.kdan.cloud.pdf.office.api.payment.enums.PaymentMethodEnum;
 import lombok.*;
 
+import javax.validation.constraints.NotNull;
 import java.math.BigDecimal;
 
 /**
@@ -19,14 +20,17 @@ public class CreatOrderDTO {
     /**
      * app ID
      */
+    @NotNull(message = "appId 不能为空")
     private String appId;
     /**
      * 产品ID
      */
+    @NotNull(message = "产品id 不能为空")
     private String productId;
     /**
      * 支付方式
      */
+    @NotNull(message = "paymentMethod 不能为空")
     private PaymentMethodEnum paymentMethod;
     /**
      * 邮箱
@@ -35,6 +39,7 @@ public class CreatOrderDTO {
     /**
      * userId
      */
+    @NotNull(message = "用户id 不能为空")
     private String userId;
     /**
      * 客户地区

+ 13 - 3
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatOrderManualDTO.java

@@ -1,7 +1,9 @@
 package cn.kdan.cloud.pdf.office.api.payment.dto;
 
+import cn.kdan.cloud.pdf.office.api.payment.enums.PaymentMethodEnum;
 import lombok.*;
 
+import javax.validation.constraints.NotNull;
 import java.math.BigDecimal;
 
 /**
@@ -13,17 +15,25 @@ import java.math.BigDecimal;
 @NoArgsConstructor
 @AllArgsConstructor
 public class CreatOrderManualDTO {
-
+    @NotNull(message = "appId 不能为空")
     private String appId;
 
+    @NotNull(message = "productId 不能为空")
     private String productId;
-
+    /**
+     * 手动生成的
+     */
     private String tradeNo;
 
     private BigDecimal price;
-
+    @NotNull(message = "userId 不能为空")
     private String userId;
 
+    /**
+     * 第三方编号,没有可不填
+     */
     private String thirdTradeNo;
+    @NotNull(message = "paymentMethod 不能为空")
+    private PaymentMethodEnum paymentMethod;
 
 }

+ 4 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatSubscriptionDTO.java

@@ -3,6 +3,7 @@ package cn.kdan.cloud.pdf.office.api.payment.dto;
 import lombok.Data;
 import lombok.ToString;
 
+import javax.validation.constraints.NotNull;
 import java.io.Serializable;
 
 /**
@@ -17,15 +18,18 @@ public class CreatSubscriptionDTO implements Serializable {
     /**
      * userId
      */
+    @NotNull(message = "userId 不能为空")
     private String userId;
 
     /**
      * productId
      */
+    @NotNull(message = "productId 不能为空")
     private String productId;
 
     private String subscriptionId;
 
+    @NotNull(message = "orderId 不能为空")
     private String orderId;
 
 

+ 39 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatSubscriptionManualDTO.java

@@ -0,0 +1,39 @@
+package cn.kdan.cloud.pdf.office.api.payment.dto;
+
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/1
+ */
+@Data
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class CreatSubscriptionManualDTO implements Serializable {
+    /**
+     * userId
+     */
+    @NotNull(message = "userId 不能为空")
+    private String userId;
+
+    /**
+     * productId
+     */
+    @NotNull(message = "productId 不能为空")
+    private String productId;
+
+    private String thirdSubscriptionId;
+
+    @NotNull(message = "orderId 不能为空")
+    private String orderId;
+
+    /**
+     * SubscriptionConstant.actived
+     */
+    private Integer status;
+
+}

+ 1 - 1
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/PaddleWebhookDTO.java

@@ -21,7 +21,7 @@ public class PaddleWebhookDTO implements Serializable {
     @JsonProperty("balance_currency")
     private String balanceCurrency;
     @JsonProperty("balance_earnings")
-    private String balanceEarnings;
+    private BigDecimal balanceEarnings;
     @JsonProperty("balance_fee")
     private BigDecimal balanceFee;
     @JsonProperty("balance_gross")

+ 86 - 1
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/feign/PaymentApi.java

@@ -1,14 +1,99 @@
 package cn.kdan.cloud.pdf.office.api.payment.feign;
 
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatOrderDTO;
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatOrderManualDTO;
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatSubscriptionDTO;
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatSubscriptionManualDTO;
 import cn.kdan.cloud.pdf.office.api.payment.feign.hystrix.PaymentHystrix;
+import cn.kdan.cloud.pdf.office.api.payment.vo.CreatOrderResultVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.OrderUpdateVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.OrdersVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.SubscriptionsVO;
 import cn.kdan.cloud.pdf.office.common.constant.CommonConstant;
+import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.stereotype.Component;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.validation.constraints.NotNull;
 
 
 @Component
-@FeignClient(value = CommonConstant.EMAIL_PROVIDER_NAME + "/pay" , fallback = PaymentHystrix.class)
+@FeignClient(value = CommonConstant.PAYMENT_PROVIDER_NAME + "/pay" , fallback = PaymentHystrix.class)
 public interface PaymentApi {
 
+    /**
+     * 创建支付订单
+     *
+     * @param creatOrderDTO creatOrderDTO
+     * @return CreatOrderResultVO
+     */
+    @PostMapping("/order/creatOrder")
+    ResultMap<CreatOrderResultVO> creatOrder(@Validated @RequestBody CreatOrderDTO creatOrderDTO);
+
+    /**
+     * 手动创建虚拟订单
+     *
+     * @param creatOrderManual creatOrderManual
+     * @return OrderUpdateVO
+     */
+    @PostMapping("/order/creatOrderManual")
+    ResultMap<OrderUpdateVO> creatOrderManual(@Validated @RequestBody CreatOrderManualDTO creatOrderManual);
+
+    /**
+     * 通过id获取订单信息
+     *
+     * @param orderId orderId
+     * @return Orders
+     */
+    @GetMapping("/order/getOrderById")
+    ResultMap<OrdersVO> getOrderById(@Validated @NotNull(message = "orderId不能为空")
+                                            @RequestParam("orderId") String orderId);
+
+    /**
+     * 通过自定义订单id获取订单信息
+     *
+     * @param tradeNo tradeNo
+     * @return Orders
+     */
+    @GetMapping("/order/getOrderByTradeNo")
+    ResultMap<OrdersVO> getOrderByTradeNo(@Validated @NotNull(message = "tradeNo不能为空")
+                                                 @RequestParam("tradeNo") String tradeNo);
+
+    @PostMapping("/order/chargebackOrder")
+    ResultMap<Void> chargebackOrder();
+
+
+    /**
+     * 创建订阅信息
+     *
+     * @param subscriptionInfo subscriptionInfo
+     * @return 订阅id
+     */
+    @PostMapping("/subscription/creatSubscription")
+    ResultMap<String> creatSubscription(@Validated @RequestBody CreatSubscriptionDTO subscriptionInfo);
+
+    /**
+     * 通过用户id和产品id 获取最新的订阅信息
+     *
+     * @param userId    userId
+     * @param productId productId
+     * @return Subscriptions
+     */
+    @GetMapping("/subscription/getSubscriptions")
+    ResultMap<SubscriptionsVO> getSubscriptions(@Validated @NotNull(message = "userId 不能为空") @RequestParam("userId") String userId,
+                                                       @NotNull(message = "productId 不能为空") @RequestParam("productId") String productId);
 
+    /**
+     * 手动创建订阅信息
+     *
+     * @param subscriptionManual subscriptionManual
+     * @return 订阅id
+     */
+    @PostMapping("/subscription/creatSubscriptionManual")
+    ResultMap<String> creatSubscriptionManual(@Validated @RequestBody CreatSubscriptionManualDTO subscriptionManual);
 }

+ 51 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/feign/hystrix/PaymentHystrix.java

@@ -1,10 +1,61 @@
 package cn.kdan.cloud.pdf.office.api.payment.feign.hystrix;
 
 
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatOrderDTO;
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatOrderManualDTO;
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatSubscriptionDTO;
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatSubscriptionManualDTO;
 import cn.kdan.cloud.pdf.office.api.payment.feign.PaymentApi;
+import cn.kdan.cloud.pdf.office.api.payment.vo.CreatOrderResultVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.OrderUpdateVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.OrdersVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.SubscriptionsVO;
+import cn.kdan.cloud.pdf.office.common.constant.CommonConstant;
+import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
 import org.springframework.stereotype.Service;
 
+import javax.validation.constraints.NotNull;
+
 @Service
 public class PaymentHystrix implements PaymentApi {
 
+    @Override
+    public ResultMap<CreatOrderResultVO> creatOrder(CreatOrderDTO creatOrderDTO) {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
+
+    @Override
+    public ResultMap<OrderUpdateVO> creatOrderManual(CreatOrderManualDTO creatOrderManual) {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
+
+    @Override
+    public ResultMap<OrdersVO> getOrderById(@NotNull(message = "orderId不能为空") String orderId) {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
+
+    @Override
+    public ResultMap<OrdersVO> getOrderByTradeNo(@NotNull(message = "tradeNo不能为空") String tradeNo) {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
+
+    @Override
+    public ResultMap<Void> chargebackOrder() {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
+
+    @Override
+    public ResultMap<String> creatSubscription(CreatSubscriptionDTO subscriptionInfo) {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
+
+    @Override
+    public ResultMap<SubscriptionsVO> getSubscriptions(@NotNull(message = "userId 不能为空") String userId, @NotNull(message = "productId 不能为空") String productId) {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
+
+    @Override
+    public ResultMap<String> creatSubscriptionManual(CreatSubscriptionManualDTO subscriptionManual) {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
 }

+ 26 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/paddle/NextPayment.java

@@ -0,0 +1,26 @@
+package cn.kdan.cloud.pdf.office.api.payment.paddle;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/2
+ */
+@Data
+@ToString
+public class NextPayment implements Serializable {
+    private BigDecimal amount;
+    private String currency;
+
+    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+    @JsonSerialize(using = LocalDateTimeSerializer.class)
+    private LocalDateTime date;
+}

+ 58 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/paddle/UpdateSubscription.java

@@ -0,0 +1,58 @@
+package cn.kdan.cloud.pdf.office.api.payment.paddle;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/2
+ */
+@Data
+@ToString
+public class UpdateSubscription implements Serializable {
+
+    @JsonProperty("subscription_id")
+    private String thirdSubscriptionId;
+    private Integer quantity;
+    /***
+     * 可选,但如果设置 .应用于收取重复价格的货币。例如、、、等。
+     * 这必须与现有订阅的货币相同。recurring_priceUSD GBP EUR
+     */
+    private String currency;
+    /**
+     * 要应用于订阅的每数量单位的新定期价格。请注意,这是一个单一的价格,即。11.00
+     */
+    @JsonProperty("recurring_price")
+    private String recurringPrice;
+    /**
+     * 要将订阅移动到的新计划 ID。
+     */
+    @JsonProperty("plan_id")
+    private String planId;
+    /**
+     * 订阅中的更改是否应按比例分配。
+     */
+    private Boolean prorate;
+    /**
+     * 如果订阅应立即按修订后的数字计费下一个间隔。
+     */
+    @JsonProperty("bill_immediately")
+    private Boolean billImmediately;
+    /**
+     * 保留用户订阅上的现有修饰符。
+     */
+    @JsonProperty("keep_modifiers")
+    private Boolean keepModifiers;
+    private String passthrough;
+    /**
+     * 暂停或重启订阅。如果订阅未暂停,并且设置为 ,则在达到订阅的下一个计划付款日期时,将更改为“已暂停”。true
+     *
+     * 如果指定了此选项,则不能同时包含以下修改:、、、
+     * bill_immediatelykeep_modifiersproratequantityrecurring_pricepassthroughplan_id
+     */
+    private Boolean pause;
+
+
+}

+ 26 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/paddle/UpdateSubscriptionResult.java

@@ -0,0 +1,26 @@
+package cn.kdan.cloud.pdf.office.api.payment.paddle;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/2
+ */
+@Data
+@ToString
+public class UpdateSubscriptionResult implements Serializable {
+
+
+    @JsonProperty("subscription_id")
+    private int subscriptionId;
+    @JsonProperty("user_id")
+    private int userId;
+    @JsonProperty("plan_id")
+    private int planId;
+    @JsonProperty("next_payment")
+    private NextPayment nextPayment;
+
+}

+ 93 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/OrdersVO.java

@@ -0,0 +1,93 @@
+package cn.kdan.cloud.pdf.office.api.payment.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/1
+ */
+@Data
+@ToString
+public class OrdersVO implements Serializable {
+
+    /**
+     * id
+     */
+    private String id;
+    /**
+     * app ID
+     */
+    private String appId;
+    /**
+     * 订阅ID
+     */
+    private String subscriptionId;
+    /**
+     * 订单编号,不知道什么东西
+     */
+    private String tradeNo;
+    /**
+     * paypal 支付id
+     */
+    private String thirdOrderNo;
+    /**
+     * 价格
+     */
+    private BigDecimal price;
+    /**
+     * 支付方式  [paypal = 0, alipay = 1, wxpay = 2, paddle = 3, no need to pay = 4];
+     */
+    private Integer payment;
+    /**
+     * 订单状态, [created = 0, approved = 1, completed = 2, closed = 3]
+     */
+    private Integer status;
+    /**
+     * 结果
+     */
+    private String result;
+    /**
+     * 支付链接
+     */
+    private String pagePayUrl;
+    /**
+     * 发票编号 时间戳
+     */
+    private String invoiceNo;
+    /**
+     * 第三方订单id
+     */
+    private String thirdTradeNo;
+    /**
+     * 产品/计划id
+     */
+    private String productId;
+    /**
+     * 折扣
+     */
+    private BigDecimal discount;
+    /**
+     * 减免的金额
+     */
+    private BigDecimal reducedPrice;
+    /**
+     * 是否是Vpp[No=1, Yes = 2];
+     */
+    private Integer isVpp;
+    /**
+     * [website_purchase=1, background_creation = 2];
+     */
+    private Integer type;
+    /**
+     * [trial = 1, formal = 2]
+     */
+    private Integer detailType;
+
+    private String userId;
+
+}

+ 122 - 0
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/SubscriptionsVO.java

@@ -0,0 +1,122 @@
+package cn.kdan.cloud.pdf.office.api.payment.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/1
+ */
+@Data
+@ToString
+public class SubscriptionsVO implements Serializable {
+    /**
+     *
+     */
+    private String id;
+    /**
+     *
+     */
+    private String productId;
+    /**
+     *
+     */
+    private Integer status;
+    /**
+     *
+     */
+    private BigDecimal price;
+    /**
+     *
+     */
+    private Integer buyerType;
+    /**
+     *
+     */
+    private String cdkey;
+    /**
+     *
+     */
+    private String email;
+    /**
+     *
+     */
+    private String phone;
+    /**
+     *
+     */
+    private String contactName;
+    /**
+     *
+     */
+    private String companyName;
+    /**
+     *
+     */
+    private Date startDate;
+    /**
+     *
+     */
+    private Date endDate;
+    /**
+     *
+     */
+    private Integer maxDeviceAmount;
+    /**
+     *
+     */
+    private BigDecimal cnyPrice;
+    /**
+     *
+     */
+    private String couponId;
+    /**
+     *
+     */
+    private String cdkeyType;
+    /**
+     *
+     */
+    private String upgradeCdkey;
+    /**
+     *
+     */
+    private String forReason;
+    /**
+     *
+     */
+    private String lastSubId;
+    /**
+     *
+     */
+    private Integer payment;
+    /**
+     *
+     */
+    private BigDecimal originalPrice;
+    /**
+     *
+     */
+    private BigDecimal cnyOriginalPrice;
+    /**
+     *
+     */
+    private Integer isVpp;
+    /**
+     *
+     */
+    private String vppMemberId;
+    /**
+     *
+     */
+    private String companyId;
+
+    private String userId;
+
+    private String subscriptionId;
+}

+ 27 - 0
pdf-office-api/pdf-office-api-product/pom.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>pdf-office-api</artifactId>
+        <groupId>cn.kdan.pdf.office</groupId>
+        <version>0.0.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>pdf-office-api-product</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>cn.kdan.pdf.office</groupId>
+            <artifactId>pdf-office-common</artifactId>
+            <version>0.0.1</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 15 - 0
pdf-office-api/pdf-office-api-product/src/main/java/cn/kdan/cloud/pdf/office/api/product/annotation/EnableProductApiClient.java

@@ -0,0 +1,15 @@
+package cn.kdan.cloud.pdf.office.api.product.annotation;
+
+import cn.kdan.cloud.pdf.office.api.product.config.PdfOfficeApiProductConfig;
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(value = ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Import(PdfOfficeApiProductConfig.class)
+public @interface EnableProductApiClient {
+}

+ 11 - 0
pdf-office-api/pdf-office-api-product/src/main/java/cn/kdan/cloud/pdf/office/api/product/config/PdfOfficeApiProductConfig.java

@@ -0,0 +1,11 @@
+package cn.kdan.cloud.pdf.office.api.product.config;
+
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan(basePackages = {"cn.kdan.cloud.pdf.office.api.product.feign"})
+@EnableFeignClients(basePackages = {"cn.kdan.cloud.pdf.office.api.product.feign"})
+public class PdfOfficeApiProductConfig {
+}

+ 1 - 1
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/ProductListDTO.java

@@ -1,4 +1,4 @@
-package cn.kdan.cloud.pdf.office.api.payment.dto;
+package cn.kdan.cloud.pdf.office.api.product.dto;
 
 import cn.kdan.cloud.pdf.office.common.base.BaseEntity;
 import lombok.Data;

+ 28 - 0
pdf-office-api/pdf-office-api-product/src/main/java/cn/kdan/cloud/pdf/office/api/product/feign/ProductApi.java

@@ -0,0 +1,28 @@
+package cn.kdan.cloud.pdf.office.api.product.feign;
+
+import cn.kdan.cloud.pdf.office.api.product.feign.hystrix.ProductHystrix;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductPriceVo;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
+import cn.kdan.cloud.pdf.office.common.constant.CommonConstant;
+import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.validation.constraints.NotNull;
+
+
+@Component
+@FeignClient(value = CommonConstant.PRODUCT_PROVIDER_NAME + "/product" , fallback = ProductHystrix.class)
+public interface ProductApi {
+
+
+    @GetMapping("/getProductPrice")
+    ResultMap<ProductPriceVo> getProductPrice(@NotNull(message = "产品id不能为空") @RequestParam("productId") String productId);
+
+
+    @GetMapping("/getProduct")
+    ResultMap<ProductVO> getProduct(@NotNull(message = "产品id不能为空") @RequestParam("productId") String productId);
+
+}

+ 25 - 0
pdf-office-api/pdf-office-api-product/src/main/java/cn/kdan/cloud/pdf/office/api/product/feign/hystrix/ProductHystrix.java

@@ -0,0 +1,25 @@
+package cn.kdan.cloud.pdf.office.api.product.feign.hystrix;
+
+
+import cn.kdan.cloud.pdf.office.api.product.feign.ProductApi;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductPriceVo;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
+import cn.kdan.cloud.pdf.office.common.constant.CommonConstant;
+import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
+import org.springframework.stereotype.Service;
+
+import javax.validation.constraints.NotNull;
+
+@Service
+public class ProductHystrix implements ProductApi {
+
+    @Override
+    public ResultMap<ProductPriceVo> getProductPrice(@NotNull(message = "产品id不能为空") String productId) {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
+
+    @Override
+    public ResultMap<ProductVO> getProduct(@NotNull(message = "产品id不能为空") String productId) {
+        return new ResultMap<>(CommonConstant.ERROR, CommonConstant.RESULT_ERROR_SERVICE_NOT_AVAILABLE);
+    }
+}

+ 1 - 1
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/ProductPriceVo.java

@@ -1,4 +1,4 @@
-package cn.kdan.cloud.pdf.office.api.payment.vo;
+package cn.kdan.cloud.pdf.office.api.product.vo;
 
 import lombok.Data;
 import lombok.ToString;

+ 1 - 1
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/ProductVO.java

@@ -1,4 +1,4 @@
-package cn.kdan.cloud.pdf.office.api.payment.vo;
+package cn.kdan.cloud.pdf.office.api.product.vo;
 
 import lombok.Data;
 import lombok.ToString;

+ 1 - 0
pdf-office-api/pom.xml

@@ -18,6 +18,7 @@
         <module>pdf-office-api-app</module>
         <module>pdf-office-api-email</module>
         <module>pdf-office-api-payment</module>
+        <module>pdf-office-api-product</module>
     </modules>
 
 </project>

+ 2 - 2
pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/config/RabbitMqConfig.java

@@ -55,7 +55,7 @@ public class RabbitMqConfig {
     }
 
     @Bean
-    public Exchange paymentExchange() {
+    public TopicExchange paymentExchange() {
         return new TopicExchange(RabbitMqConstant.PAYMENT_EXCHANGE, true, false);
     }
 
@@ -86,7 +86,7 @@ public class RabbitMqConfig {
     }
 
     @Bean
-    public BindingBuilder.GenericArgumentsConfigurer paymentOrderBinding() {
+    public Binding paymentOrderBinding() {
         // 如果要让延迟队列之间有关联,这里的 routingKey 和 绑定的交换机很关键
         return BindingBuilder.bind(paymentOrderQueue())
                 .to(paymentExchange())

+ 4 - 0
pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/constant/CommonConstant.java

@@ -101,6 +101,10 @@ public interface CommonConstant {
 
     String EMAIL_PROVIDER_NAME = "pdf-office-email";
 
+    String PAYMENT_PROVIDER_NAME = "pdf-office-payment";
+
+    String PRODUCT_PROVIDER_NAME = "pdf-office-product";
+
     String APP_PROVIDER_NAME = "pdf-office-app";
 
     String EMAIL_VERIFY_CODE_KEY = "verifyCode_email";

+ 12 - 0
pdf-office-payment/pom.xml

@@ -82,6 +82,18 @@
             </exclusions>
         </dependency>
 
+        <dependency>
+            <groupId>cn.kdan.pdf.office</groupId>
+            <artifactId>pdf-office-api-product</artifactId>
+            <version>0.0.1</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>cn.kdan.pdf.office</groupId>
+                    <artifactId>pdf-office-common</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>

+ 2 - 0
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/PDFOfficePaymentApplication.java

@@ -1,5 +1,6 @@
 package cn.kdan.cloud.pdf.office.payment;
 
+import cn.kdan.cloud.pdf.office.api.product.annotation.EnableProductApiClient;
 import cn.kdan.cloud.pdf.office.common.annotation.EnableCommonTools;
 import cn.kdan.cloud.pdf.office.common.annotation.EnableMyRabbitMqHandler;
 import cn.kdan.cloud.pdf.office.common.annotation.EnableMybatisPlusConfig;
@@ -31,6 +32,7 @@ import org.springframework.data.redis.repository.configuration.EnableRedisReposi
 @RequiredArgsConstructor
 @EnableCaching
 @EnableCommonTools
+@EnableProductApiClient
 public class PDFOfficePaymentApplication {
 
     public static void main(String[] args) {

+ 74 - 10
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/client/PaddleClient.java

@@ -5,6 +5,8 @@ import cn.kdan.cloud.pdf.office.api.payment.bo.GeneratePayLinkPaddleBO;
 import cn.kdan.cloud.pdf.office.api.payment.bo.GeneratePayLinkResultPaddleBO;
 import cn.kdan.cloud.pdf.office.api.payment.constant.PaddleAPIConstant;
 import cn.kdan.cloud.pdf.office.api.payment.paddle.PaddleResult;
+import cn.kdan.cloud.pdf.office.api.payment.paddle.UpdateSubscription;
+import cn.kdan.cloud.pdf.office.api.payment.paddle.UpdateSubscriptionResult;
 import cn.kdan.cloud.pdf.office.common.exception.BackendRuntimeException;
 import cn.kdan.cloud.pdf.office.common.utils.JsonUtils;
 import cn.kdan.cloud.pdf.office.payment.interceptor.PaddleClientHttpRequestInterceptor;
@@ -72,16 +74,12 @@ public class PaddleClient {
      * @return CreatSubscriptionsResultBO
      */
     public GeneratePayLinkResultPaddleBO creatSubscriptions(GeneratePayLinkPaddleBO creatSubscriptions) {
-        MultiValueMap<String, Object> requestParamMap = new LinkedMultiValueMap<>();
-
+        MultiValueMap<String, Object> requestParamMap = getValueMap(creatSubscriptions);
         Map<String, Object> stringObjectMap = JSON.parseObject(JsonUtils.getJsonString(creatSubscriptions),
-                new TypeReference<Map<String, Object>>() {});
-
+                new TypeReference<Map<String, Object>>() {
+                });
         Iterables.removeIf(stringObjectMap.values(), Objects::isNull);
-
         requestParamMap.setAll(stringObjectMap);
-        requestParamMap.set(PaddleAPIConstant.VENDORID,properties.getVendorId());
-        requestParamMap.set(PaddleAPIConstant.VENDORAUTHCODE,properties.getVendorAuthCode());
         String[] prices = creatSubscriptions.getPrices();
         if (!ObjectUtils.isEmpty(prices)) {
             requestParamMap.remove("prices");
@@ -89,23 +87,88 @@ public class PaddleClient {
                 requestParamMap.set("prices[" + i + "]:", prices[i]);
             }
         }
-        log.info("prama:{}",requestParamMap);
+        log.info("prama:{}", requestParamMap);
         String resultJson = restTemplate.exchange(
                 PADDLE_VENDORS_HOST + PaddleAPIConstant.CREAT_PAY_LINK,
                 HttpMethod.POST,
                 new HttpEntity<>(requestParamMap, getWwwFormHttpHeaders()),
                 String.class).getBody();
         PaddleResult<GeneratePayLinkResultPaddleBO> paddleResult = JSON.parseObject(resultJson,
-                new TypeReference<PaddleResult<GeneratePayLinkResultPaddleBO>>() {});
+                new TypeReference<PaddleResult<GeneratePayLinkResultPaddleBO>>() {
+                });
 
         if (!paddleResult.isSuccess()) {
-            log.info("paddle 生成支付链接调用失败\n:{},\n参数:{}", paddleResult.getError(), creatSubscriptions);
+            log.error("paddle 生成支付链接调用失败\n:{},\n参数:{}", paddleResult.getError(), creatSubscriptions);
             throw new BackendRuntimeException(paddleResult.getError().getMessage());
         }
         // TODO 返回信息再调整
         return paddleResult.getResponse();
     }
 
+    /**
+     * paddle 取消续订
+     *
+     * @param thirdSubscriptionId paddle subscriptionId
+     * @return paddle subscriptionId
+     */
+    public String cancelSubscription(String thirdSubscriptionId) {
+        log.info("paddle 取消续订:{}", thirdSubscriptionId);
+        MultiValueMap<String, Object> requestParamMap = getValueMap(null);
+        requestParamMap.set("subscription_id", thirdSubscriptionId);
+        String resultJson = restTemplate.exchange(
+                PADDLE_VENDORS_HOST + PaddleAPIConstant.CANCEL_SUBSCRIPTION,
+                HttpMethod.POST,
+                new HttpEntity<>(requestParamMap, getWwwFormHttpHeaders()),
+                String.class).getBody();
+        PaddleResult<Void> paddleResult = JSON.parseObject(resultJson,
+                new TypeReference<PaddleResult<Void>>() {
+                });
+
+        if (!paddleResult.isSuccess()) {
+            log.error("paddle 生成支付链接调用失败\n:{},\n参数:{}", paddleResult.getError(), thirdSubscriptionId);
+            throw new BackendRuntimeException(paddleResult.getError().getMessage());
+        }
+        return thirdSubscriptionId;
+    }
+
+    /**
+     * 更新订阅
+     *
+     * @param updateSubscription updateSubscription
+     * @return UpdateSubscriptionResult
+     */
+    public UpdateSubscriptionResult updateSubscription(UpdateSubscription updateSubscription) {
+        log.info("paddle 更新订阅:{}", updateSubscription);
+        MultiValueMap<String, Object> requestParamMap = getValueMap(updateSubscription);
+        String resultJson = restTemplate.exchange(
+                PADDLE_VENDORS_HOST + PaddleAPIConstant.UPDATE_SUBSCRIPTION,
+                HttpMethod.POST,
+                new HttpEntity<>(requestParamMap, getWwwFormHttpHeaders()),
+                String.class).getBody();
+        PaddleResult<UpdateSubscriptionResult> paddleResult = JSON.parseObject(resultJson,
+                new TypeReference<PaddleResult<UpdateSubscriptionResult>>() {
+                });
+        if (!paddleResult.isSuccess()) {
+            log.error("paddle 生成支付链接调用失败\n:{},\n参数:{}", paddleResult.getError(), updateSubscription);
+            throw new BackendRuntimeException(paddleResult.getError().getMessage());
+        }
+        return paddleResult.getResponse();
+    }
+
+
+    @NotNull
+    private MultiValueMap<String, Object> getValueMap(Object o) {
+        MultiValueMap<String, Object> requestParamMap = new LinkedMultiValueMap<>();
+        requestParamMap.set(PaddleAPIConstant.VENDORID, properties.getVendorId());
+        requestParamMap.set(PaddleAPIConstant.VENDORAUTHCODE, properties.getVendorAuthCode());
+        Map<String, Object> stringObjectMap = JSON.parseObject(JsonUtils.getJsonString(o),
+                new TypeReference<Map<String, Object>>() {
+                });
+        Iterables.removeIf(stringObjectMap.values(), Objects::isNull);
+        requestParamMap.setAll(stringObjectMap);
+        return requestParamMap;
+    }
+
 
     /**
      * 获取订阅信息
@@ -122,6 +185,7 @@ public class PaddleClient {
         return null;
     }
 
+
     @NotNull
     private HttpHeaders getWwwFormHttpHeaders() {
         HttpHeaders httpHeaders = new HttpHeaders();

+ 128 - 0
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/controller/PaymentController.java

@@ -0,0 +1,128 @@
+package cn.kdan.cloud.pdf.office.payment.controller;
+
+import cn.kdan.cloud.pdf.office.api.payment.dto.*;
+import cn.kdan.cloud.pdf.office.api.payment.vo.CreatOrderResultVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.OrderUpdateVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.OrdersVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.SubscriptionsVO;
+import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
+import cn.kdan.cloud.pdf.office.payment.service.OrdersService;
+import cn.kdan.cloud.pdf.office.payment.service.SubscriptionsService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/1
+ */
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/pay")
+public class PaymentController {
+
+    private final OrdersService ordersService;
+
+    private final SubscriptionsService subscriptionsService;
+
+    /**
+     * 创建支付订单
+     *
+     * @param creatOrderDTO creatOrderDTO
+     * @return CreatOrderResultVO
+     */
+    @PostMapping("/order/creatOrder")
+    public ResultMap<CreatOrderResultVO> creatOrder(@Validated @RequestBody CreatOrderDTO creatOrderDTO){
+        return ResultMap.success(ordersService.creatOrder(creatOrderDTO));
+    }
+
+    /**
+     * 手动创建虚拟订单
+     *
+     * @param creatOrderManual creatOrderManual
+     * @return OrderUpdateVO
+     */
+    @PostMapping("/order/creatOrderManual")
+    public ResultMap<OrderUpdateVO> creatOrderManual(@Validated @RequestBody CreatOrderManualDTO creatOrderManual){
+        return ResultMap.success(ordersService.creatOrderManual(creatOrderManual));
+    }
+
+    /**
+     * 通过id获取订单信息
+     *
+     * @param orderId orderId
+     * @return Orders
+     */
+    @GetMapping("/order/getOrderById")
+    public ResultMap<OrdersVO> getOrderById(@Validated @NotNull(message = "orderId不能为空")
+                                                @RequestParam("orderId") String orderId){
+        return ResultMap.success(ordersService.getOrderById(orderId));
+    }
+
+    /**
+     * 通过自定义订单id获取订单信息
+     *
+     * @param tradeNo tradeNo
+     * @return Orders
+     */
+    @GetMapping("/order/getOrderByTradeNo")
+    public ResultMap<OrdersVO> getOrderByTradeNo(@Validated @NotNull(message = "tradeNo不能为空")
+                                                     @RequestParam("tradeNo") String tradeNo){
+        return ResultMap.success(ordersService.getOrderByTradeNo(tradeNo));
+    }
+
+    /**
+     * 手动推单
+     *
+     * @param chargebackOrderDTO chargebackOrderDTO
+     * @return Void
+     */
+    @PostMapping("/order/chargebackOrder")
+    public ResultMap<Void> chargebackOrder(@Validated @RequestBody ChargebackOrderDTO chargebackOrderDTO){
+        // 修改 订单状态
+        ordersService.chargebackOrder(chargebackOrderDTO);
+        // 修改 订阅状态
+        subscriptionsService.chargebackSubscription(chargebackOrderDTO);
+        return ResultMap.success();
+    }
+
+
+    /**
+     * 创建订阅信息
+     *
+     * @param subscriptionInfo subscriptionInfo
+     * @return 订阅id
+     */
+    @PostMapping("/subscription/creatSubscription")
+    public ResultMap<String> creatSubscription(@Validated @RequestBody CreatSubscriptionDTO subscriptionInfo){
+        return ResultMap.success(subscriptionsService.creatSubscription(subscriptionInfo));
+    }
+
+    /**
+     * 通过用户id和产品id 获取最新的订阅信息
+     *
+     * @param userId    userId
+     * @param productId productId
+     * @return Subscriptions
+     */
+    @GetMapping("/subscription/getSubscriptions")
+    public ResultMap<SubscriptionsVO> getSubscriptions(@Validated @NotNull(message = "userId 不能为空") @RequestParam("userId") String userId,
+                                                       @NotNull(message = "productId 不能为空") @RequestParam("productId") String productId){
+        return ResultMap.success(subscriptionsService.getSubscriptions(userId,productId));
+    }
+
+    /**
+     * 手动创建订阅信息
+     *
+     * @param subscriptionManual subscriptionManual
+     * @return 订阅id
+     */
+    @PostMapping("/subscription/creatSubscriptionManual")
+    public ResultMap<String> creatSubscriptionManual(@Validated @RequestBody CreatSubscriptionManualDTO subscriptionManual){
+        return ResultMap.success(subscriptionsService.creatSubscriptionManual(subscriptionManual));
+    }
+
+
+
+}

+ 4 - 2
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/entity/Orders.java

@@ -13,8 +13,8 @@ import java.math.BigDecimal;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("orders")
-public class Orders extends BaseEntity{
+@TableName("order")
+public class Order extends BaseEntity{
 
     /**
      * id
@@ -47,6 +47,8 @@ public class Orders extends BaseEntity{
     private Integer payment;
     /**
      * 订单状态, [created = 0, approved = 1, completed = 2, closed = 3]
+     *
+     * OrderConstant
      */
     private Integer status;
     /**

+ 3 - 3
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/entity/Subscriptions.java

@@ -14,8 +14,8 @@ import java.math.BigDecimal;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("subscriptions")
-public class Subscriptions extends BaseEntity{
+@TableName("subscription")
+public class Subscription extends BaseEntity{
 
     /**
      * 
@@ -121,6 +121,6 @@ public class Subscriptions extends BaseEntity{
 
     private String userId;
 
-    private String subscriptionId;
+    private String thirdSubscriptionId;
 
 }

+ 2 - 2
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/mapper/OrdersMapper.java

@@ -1,11 +1,11 @@
 package cn.kdan.cloud.pdf.office.payment.mapper;
 
-import cn.kdan.cloud.pdf.office.payment.entity.Orders;
+import cn.kdan.cloud.pdf.office.payment.entity.Order;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
 /**
  * @author ComPDFKit-WPH 2023-01-29
  */
-public interface OrdersMapper extends BaseMapper<Orders> {
+public interface OrdersMapper extends BaseMapper<Order> {
 
 }

+ 2 - 2
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/mapper/SubscriptionsMapper.java

@@ -1,11 +1,11 @@
 package cn.kdan.cloud.pdf.office.payment.mapper;
 
-import cn.kdan.cloud.pdf.office.payment.entity.Subscriptions;
+import cn.kdan.cloud.pdf.office.payment.entity.Subscription;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
 /**
  * @author ComPDFKit-WPH 2023-01-28
  */
-public interface SubscriptionsMapper extends BaseMapper<Subscriptions> {
+public interface SubscriptionsMapper extends BaseMapper<Subscription> {
 
 }

+ 13 - 6
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/OrdersService.java

@@ -1,19 +1,19 @@
 package cn.kdan.cloud.pdf.office.payment.service;
 
 import cn.kdan.cloud.pdf.office.api.payment.bo.OrderSucceededBO;
+import cn.kdan.cloud.pdf.office.api.payment.dto.ChargebackOrderDTO;
 import cn.kdan.cloud.pdf.office.api.payment.dto.CreatOrderDTO;
 import cn.kdan.cloud.pdf.office.api.payment.dto.CreatOrderManualDTO;
 import cn.kdan.cloud.pdf.office.api.payment.vo.CreatOrderResultVO;
 import cn.kdan.cloud.pdf.office.api.payment.vo.OrderUpdateVO;
-import cn.kdan.cloud.pdf.office.payment.entity.Orders;
+import cn.kdan.cloud.pdf.office.api.payment.vo.OrdersVO;
+import cn.kdan.cloud.pdf.office.payment.entity.Order;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 
 /**
  * @author ComPDFKit-WPH 2023-01-29
  */
-public interface OrdersService extends IService<Orders> {
-
+public interface OrdersService extends IService<Order> {
 
     /**
      * 创建订单
@@ -44,7 +44,7 @@ public interface OrdersService extends IService<Orders> {
      * @param orderId orderId
      * @return Orders
      */
-    Orders getOrderById(String orderId);
+    OrdersVO getOrderById(String orderId);
 
     /**
      * 通过自定义订单id获取订单信息
@@ -52,7 +52,7 @@ public interface OrdersService extends IService<Orders> {
      * @param tradeNo tradeNo
      * @return Orders
      */
-    Orders getOrderByTradeNo(String tradeNo);
+    OrdersVO getOrderByTradeNo(String tradeNo);
 
     /**
      * 手动创建虚拟订单
@@ -61,4 +61,11 @@ public interface OrdersService extends IService<Orders> {
      * @return OrderUpdateVO
      */
     OrderUpdateVO creatOrderManual(CreatOrderManualDTO creatOrderManual);
+
+    /**
+     * 手动推单
+     *
+     * @param chargebackOrderDTO chargebackOrderDTO
+     */
+    void chargebackOrder(ChargebackOrderDTO chargebackOrderDTO);
 }

+ 26 - 6
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/SubscriptionsService.java

@@ -1,7 +1,10 @@
 package cn.kdan.cloud.pdf.office.payment.service;
 
+import cn.kdan.cloud.pdf.office.api.payment.dto.ChargebackOrderDTO;
 import cn.kdan.cloud.pdf.office.api.payment.dto.CreatSubscriptionDTO;
-import cn.kdan.cloud.pdf.office.payment.entity.Subscriptions;
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatSubscriptionManualDTO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.SubscriptionsVO;
+import cn.kdan.cloud.pdf.office.payment.entity.Subscription;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
@@ -10,7 +13,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
  * <p>
  * 生成支付订阅
  */
-public interface SubscriptionsService extends IService<Subscriptions> {
+public interface SubscriptionsService extends IService<Subscription> {
 
     /**
      * 列表查询
@@ -18,14 +21,15 @@ public interface SubscriptionsService extends IService<Subscriptions> {
      * @param query 查询参数
      * @return 列表数据
      */
-    IPage<Subscriptions> page(Subscriptions query);
+    IPage<Subscription> page(Subscription query);
 
     /**
      * 创建订阅信息
      *
-     * @param orderInfo orderInfo
+     * @param subscriptionInfo subscriptionInfo
+     * @return 订阅id
      */
-    void creatSubscription(CreatSubscriptionDTO orderInfo);
+    String creatSubscription(CreatSubscriptionDTO subscriptionInfo);
 
     /**
      * 通过用户id和产品id 获取最新的订阅信息
@@ -34,5 +38,21 @@ public interface SubscriptionsService extends IService<Subscriptions> {
      * @param productId productId
      * @return Subscriptions
      */
-    Subscriptions getSubscriptions(String userId, String productId);
+    SubscriptionsVO getSubscriptions(String userId, String productId);
+
+    /**
+     * 手动创建订阅信息
+     *
+     * @param subscriptionManual subscriptionManual
+     * @return 订阅id
+     */
+    String creatSubscriptionManual(CreatSubscriptionManualDTO subscriptionManual);
+
+    /**
+     * 退单
+     *
+     * @param chargebackOrderDTO chargebackOrderDTO
+     */
+    void chargebackSubscription(ChargebackOrderDTO chargebackOrderDTO);
+
 }

+ 54 - 27
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/OrdersServiceImpl.java

@@ -4,27 +4,32 @@ import cn.kdan.cloud.pdf.office.api.payment.bo.GeneratePayLinkPaddleBO;
 import cn.kdan.cloud.pdf.office.api.payment.bo.GeneratePayLinkResultPaddleBO;
 import cn.kdan.cloud.pdf.office.api.payment.bo.OrderSucceededBO;
 import cn.kdan.cloud.pdf.office.api.payment.constant.OrderConstant;
+import cn.kdan.cloud.pdf.office.api.payment.constant.SubscriptionConstant;
+import cn.kdan.cloud.pdf.office.api.payment.dto.ChargebackOrderDTO;
 import cn.kdan.cloud.pdf.office.api.payment.dto.CreatOrderDTO;
 import cn.kdan.cloud.pdf.office.api.payment.dto.CreatOrderManualDTO;
 import cn.kdan.cloud.pdf.office.api.payment.vo.CreatOrderResultVO;
 import cn.kdan.cloud.pdf.office.api.payment.vo.OrderUpdateVO;
-import cn.kdan.cloud.pdf.office.api.payment.vo.ProductPriceVo;
+import cn.kdan.cloud.pdf.office.api.payment.vo.OrdersVO;
+import cn.kdan.cloud.pdf.office.api.product.feign.ProductApi;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductPriceVo;
 import cn.kdan.cloud.pdf.office.common.constant.RabbitMqConstant;
 import cn.kdan.cloud.pdf.office.common.constant.RedisKeyConstant;
 import cn.kdan.cloud.pdf.office.common.exception.BackendRuntimeException;
-import cn.kdan.cloud.pdf.office.common.utils.JsonUtils;
 import cn.kdan.cloud.pdf.office.common.utils.MyDateUtils;
 import cn.kdan.cloud.pdf.office.payment.client.PaddleClient;
-import cn.kdan.cloud.pdf.office.payment.entity.Orders;
+import cn.kdan.cloud.pdf.office.payment.entity.Order;
+import cn.kdan.cloud.pdf.office.payment.entity.Subscription;
 import cn.kdan.cloud.pdf.office.payment.error.ErrorMessage;
 import cn.kdan.cloud.pdf.office.payment.mapper.OrdersMapper;
 import cn.kdan.cloud.pdf.office.payment.service.OrdersService;
-import cn.kdan.cloud.pdf.office.payment.service.ProductService;
+import cn.kdan.cloud.pdf.office.payment.service.SubscriptionsService;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
 import org.springframework.amqp.rabbit.core.RabbitTemplate;
 import org.springframework.beans.BeanUtils;
 import org.springframework.cache.annotation.Cacheable;
@@ -42,9 +47,9 @@ import java.util.UUID;
 @Service
 @Slf4j
 @RequiredArgsConstructor
-public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {
+public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Order> implements OrdersService {
 
-    private final ProductService productService;
+    private final ProductApi productApi;
 
     private final StringRedisTemplate redisTemplate;
 
@@ -52,6 +57,8 @@ public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> impleme
 
     private final RabbitTemplate rabbitTemplate;
 
+//    private final SubscriptionsService subscriptionsService;
+
     @Override
     @Cacheable(value = RedisKeyConstant.CACHE_PAYMENT_CREAT_ORDER + "#3#h",
             key = "T(String).valueOf(#creatOrderDTO.userId)" +
@@ -60,7 +67,7 @@ public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> impleme
             cacheManager = "myRedisCacheManager", unless = "#result == null")
     public CreatOrderResultVO creatOrder(CreatOrderDTO creatOrderDTO) {
         log.info("creatOrder:{}", creatOrderDTO);
-        Orders orders = new Orders();
+        Order orders = new Order();
         orders.setAppId(creatOrderDTO.getAppId());
         orders.setUserId(creatOrderDTO.getUserId());
         orders.setProductId(creatOrderDTO.getProductId());
@@ -72,7 +79,7 @@ public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> impleme
         String readeNo = MyDateUtils.getTimeStamp() + "-" + creatOrderDTO.getProductId() + "-" + (int) ((Math.random() * 9 + 1) * 1000);
         orders.setTradeNo(readeNo);
         // 查询当前产品多少钱
-        ProductPriceVo productPrice = productService.getProductPrice(creatOrderDTO.getProductId());
+        ProductPriceVo productPrice = productApi.getProductPrice(creatOrderDTO.getProductId()).getResult();
         switch (creatOrderDTO.getPaymentMethod()) {
             case WXPAY:
                 break;
@@ -101,35 +108,39 @@ public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> impleme
         CreatOrderResultVO creatOrderResultVO = new CreatOrderResultVO();
         BeanUtils.copyProperties(orders, creatOrderResultVO);
         // 订单关闭
+        log.info("rabbitMq 发送延时队列,关闭订单:{}", orders.getId());
         rabbitTemplate.convertAndSend(RabbitMqConstant.PAYMENT_EXCHANGE,
                 RabbitMqConstant.PAYMENT_ORDER_ROUTING_KEY,
                 orders.getId(),
-                (msg -> { msg.getMessageProperties().setExpiration((60 * 1000) + "");
-                    return msg; }));
+                (msg -> {
+                    msg.getMessageProperties().setExpiration((60 * 1000) + "");
+                    return msg;
+                }));
         return creatOrderResultVO;
     }
 
     @Override
     public void closeOrder(String orderId) {
-        Orders orders = getOrderById(orderId);
+        OrdersVO orders = getOrderById(orderId);
         log.info("当前订单信息:{}", orders);
-        if (orders.getStatus().equals(OrderConstant.CREATED)){
-            orders.setStatus(OrderConstant.CLOSED);
-            orders.setId(orderId);
-            this.baseMapper.updateById(orders);
+        if (orders.getStatus().equals(OrderConstant.CREATED)) {
+            Order order = new Order();
+            order.setStatus(OrderConstant.CLOSED);
+            order.setId(orderId);
+            this.baseMapper.updateById(order);
         }
     }
 
     @Override
     public OrderUpdateVO updateOrderSucceeded(OrderSucceededBO orderSucceeded) {
-        Orders orders = new Orders();
+        Order orders = new Order();
         orders.setThirdOrderNo(orderSucceeded.getThirdTradeNo());
         orders.setStatus(OrderConstant.COMPLETED);
-        this.baseMapper.update(orders,new LambdaQueryWrapper<Orders>()
-                .eq(Orders::getTradeNo,orderSucceeded.getTradeNo()));
-        Orders orderTradeNo = this.baseMapper.selectOne(new LambdaQueryWrapper<Orders>()
-                .select(Orders::getId, Orders::getUserId)
-                .eq(Orders::getTradeNo, orderSucceeded.getTradeNo()));
+        this.baseMapper.update(orders, new LambdaQueryWrapper<Order>()
+                .eq(Order::getTradeNo, orderSucceeded.getTradeNo()));
+        Order orderTradeNo = this.baseMapper.selectOne(new LambdaQueryWrapper<Order>()
+                .select(Order::getId, Order::getUserId)
+                .eq(Order::getTradeNo, orderSucceeded.getTradeNo()));
         return OrderUpdateVO.builder()
                 .orderId(orderTradeNo.getId())
                 .userId(orderTradeNo.getUserId())
@@ -137,24 +148,29 @@ public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> impleme
     }
 
     @Override
-    public Orders getOrderById(String orderId){
-        return this.baseMapper.selectOne(new LambdaQueryWrapper<Orders>().eq(Orders::getId,orderId));
+    public OrdersVO getOrderById(String orderId) {
+        OrdersVO ordersVO = new OrdersVO();
+        BeanUtils.copyProperties(this.baseMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getId, orderId)), ordersVO);
+        return ordersVO;
     }
 
     @Override
-    public Orders getOrderByTradeNo(String tradeNo){
-        return this.baseMapper.selectOne(new LambdaQueryWrapper<Orders>().eq(Orders::getTradeNo,tradeNo));
+    public OrdersVO getOrderByTradeNo(String tradeNo) {
+        OrdersVO ordersVO = new OrdersVO();
+        BeanUtils.copyProperties(this.baseMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getTradeNo, tradeNo)), ordersVO);
+        return ordersVO;
     }
 
     @Override
     public OrderUpdateVO creatOrderManual(CreatOrderManualDTO creatOrderManual) {
-        Orders orders = new Orders();
+        Order orders = new Order();
         orders.setAppId(creatOrderManual.getAppId());
         orders.setProductId(creatOrderManual.getProductId());
         orders.setUserId(creatOrderManual.getUserId());
         orders.setTradeNo(creatOrderManual.getTradeNo());
         orders.setThirdTradeNo(creatOrderManual.getThirdTradeNo());
         orders.setPrice(creatOrderManual.getPrice());
+        orders.setPayment(creatOrderManual.getPaymentMethod().getValue());
         this.baseMapper.insert(orders);
         return OrderUpdateVO.builder()
                 .userId(creatOrderManual.getUserId())
@@ -163,6 +179,17 @@ public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> impleme
     }
 
 
+    @Override
+    public void chargebackOrder(@NotNull ChargebackOrderDTO chargebackOrderDTO) {
+        log.info("手动退单修改状态:{}", chargebackOrderDTO);
+        // 修改订单状态
+        Order orders = new Order();
+        orders.setId(chargebackOrderDTO.getOrderId());
+        orders.setStatus(OrderConstant.REFUND);
+        this.baseMapper.updateById(orders);
+        log.info("手动退单修改状态成功:{}", chargebackOrderDTO);
+    }
+
     /**
      * 对价格进行处理
      *
@@ -171,7 +198,7 @@ public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> impleme
      * @param orders        orders
      * @return 新价格
      */
-    private BigDecimal priceHandle(CreatOrderDTO creatOrderDTO, BigDecimal price, Orders orders) {
+    private BigDecimal priceHandle(CreatOrderDTO creatOrderDTO, BigDecimal price, Order orders) {
         if (!ObjectUtils.isEmpty(creatOrderDTO.getDiscount())) {
             price = price.multiply(creatOrderDTO.getDiscount());
         }

+ 19 - 5
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/PaddleWebhookServiceImpl.java

@@ -1,14 +1,17 @@
 package cn.kdan.cloud.pdf.office.payment.service.impl;
 
 import cn.kdan.cloud.pdf.office.api.payment.bo.OrderSucceededBO;
+import cn.kdan.cloud.pdf.office.api.payment.constant.SubscriptionConstant;
 import cn.kdan.cloud.pdf.office.api.payment.dto.CreatSubscriptionDTO;
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatSubscriptionManualDTO;
 import cn.kdan.cloud.pdf.office.api.payment.dto.PaddleWebhookDTO;
 import cn.kdan.cloud.pdf.office.api.payment.dto.CreatOrderManualDTO;
+import cn.kdan.cloud.pdf.office.api.payment.enums.PaymentMethodEnum;
 import cn.kdan.cloud.pdf.office.api.payment.vo.OrderUpdateVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.OrdersVO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.SubscriptionsVO;
 import cn.kdan.cloud.pdf.office.common.exception.BackendRuntimeException;
 import cn.kdan.cloud.pdf.office.common.utils.MyDateUtils;
-import cn.kdan.cloud.pdf.office.payment.entity.Orders;
-import cn.kdan.cloud.pdf.office.payment.entity.Subscriptions;
 import cn.kdan.cloud.pdf.office.payment.error.ErrorMessage;
 import cn.kdan.cloud.pdf.office.payment.service.OrdersService;
 import cn.kdan.cloud.pdf.office.payment.service.PaddleWebhookService;
@@ -16,6 +19,7 @@ import cn.kdan.cloud.pdf.office.payment.service.SubscriptionsService;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
@@ -54,9 +58,9 @@ public class PaddleWebhookServiceImpl implements PaddleWebhookService {
     @Override
     public void subscriptionPaymentSucceeded(PaddleWebhookDTO paddleWebhookDTO) {
         log.info("paddle 订阅的支付订单已成功 paddle订单id:{}",paddleWebhookDTO.getCheckoutId());
-        Orders orderByTradeNo = ordersService.getOrderByTradeNo(paddleWebhookDTO.getPassthrough());
+        OrdersVO orderByTradeNo = ordersService.getOrderByTradeNo(paddleWebhookDTO.getPassthrough());
         // 判断当前是否存在订阅
-        Subscriptions subscriptions = subscriptionsService.getSubscriptions(orderByTradeNo.getUserId(), orderByTradeNo.getProductId());
+        SubscriptionsVO subscriptions = subscriptionsService.getSubscriptions(orderByTradeNo.getUserId(), orderByTradeNo.getProductId());
         if (ObjectUtils.isEmpty(subscriptions)){
             throw new BackendRuntimeException(ErrorMessage.SUBSCRIPTION_NON_EXISTENT);
         }
@@ -65,8 +69,18 @@ public class PaddleWebhookServiceImpl implements PaddleWebhookService {
         }
         // 创建新订单
         CreatOrderManualDTO creatOrderManual = new CreatOrderManualDTO();
+        BeanUtils.copyProperties(orderByTradeNo,creatOrderManual);
+        creatOrderManual.setPaymentMethod(PaymentMethodEnum.PADDLE);
+        // 设置实际扣费价格 有可能不对。。。
+        creatOrderManual.setPrice(paddleWebhookDTO.getBalanceGross());
+        creatOrderManual.setThirdTradeNo(paddleWebhookDTO.getCheckoutId());
         OrderUpdateVO orderManual = ordersService.creatOrderManual(creatOrderManual);
         // 创建新订阅
-        subscriptionsService.creatSubscriptionManual();
+        CreatSubscriptionManualDTO subscriptionManual = new CreatSubscriptionManualDTO();
+        BeanUtils.copyProperties(orderByTradeNo,orderManual);
+        subscriptionManual.setProductId(orderByTradeNo.getProductId());
+        subscriptionManual.setThirdSubscriptionId(paddleWebhookDTO.getSubscriptionId());
+        subscriptionManual.setStatus(SubscriptionConstant.actived);
+        subscriptionsService.creatSubscriptionManual(subscriptionManual);
     }
 }

+ 89 - 35
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/SubscriptionsServiceImpl.java

@@ -1,12 +1,16 @@
 package cn.kdan.cloud.pdf.office.payment.service.impl;
 
 import cn.kdan.cloud.pdf.office.api.payment.constant.SubscriptionConstant;
+import cn.kdan.cloud.pdf.office.api.payment.dto.ChargebackOrderDTO;
 import cn.kdan.cloud.pdf.office.api.payment.dto.CreatSubscriptionDTO;
+import cn.kdan.cloud.pdf.office.api.payment.dto.CreatSubscriptionManualDTO;
+import cn.kdan.cloud.pdf.office.api.payment.vo.SubscriptionsVO;
+import cn.kdan.cloud.pdf.office.api.product.feign.ProductApi;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
 import cn.kdan.cloud.pdf.office.common.utils.MyDateUtils;
-import cn.kdan.cloud.pdf.office.payment.entity.Product;
-import cn.kdan.cloud.pdf.office.payment.entity.Subscriptions;
+import cn.kdan.cloud.pdf.office.payment.client.PaddleClient;
+import cn.kdan.cloud.pdf.office.payment.entity.Subscription;
 import cn.kdan.cloud.pdf.office.payment.mapper.SubscriptionsMapper;
-import cn.kdan.cloud.pdf.office.payment.service.ProductService;
 import cn.kdan.cloud.pdf.office.payment.service.SubscriptionsService;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -16,6 +20,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
@@ -26,26 +31,97 @@ import java.time.LocalDateTime;
 @Service
 @Slf4j
 @RequiredArgsConstructor
-public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, Subscriptions> implements SubscriptionsService {
+public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, Subscription> implements SubscriptionsService {
 
-    private final ProductService productService;
+    private final ProductApi productApi;
+
+    private final PaddleClient paddleClient;
 
     @Override
-    public IPage<Subscriptions> page(Subscriptions query) {
+    public IPage<Subscription> page(Subscription query) {
         return this.page(new Page<>(query.getPage(), query.getSize()), Wrappers.query(query));
     }
 
 
     @Override
-    public void creatSubscription(CreatSubscriptionDTO orderInfo) {
-        log.info("creatSubscription Info :{}", orderInfo);
-        // 通过用户id和产品id获取最新订阅信息
-        Subscriptions newestSubscriptions = getSubscriptions(orderInfo.getUserId(), orderInfo.getProductId());
+    public String creatSubscription(CreatSubscriptionDTO subscriptionInfo) {
+        log.info("creatSubscription Info :{}", subscriptionInfo);
         /* 获取产品的订阅周期时长 */
-        // 初始时间
-        LocalDateTime originalTime;
         // 当前时间
         LocalDateTime now = LocalDateTime.now();
+        // 初始时间
+        LocalDateTime originalTime = getOriginalTime(subscriptionInfo, now);
+        // 获取结束时间
+        LocalDateTime endTime = getEndTime(subscriptionInfo, originalTime);
+        // 产生一条最新的订阅信息
+        Subscription subscription = new Subscription();
+        subscription.setProductId(subscriptionInfo.getUserId());
+        subscription.setStatus(SubscriptionConstant.actived);
+        subscription.setUserId(subscriptionInfo.getUserId());
+        subscription.setStartDate(MyDateUtils.localDateTimeToDate(now));
+        subscription.setEndDate(MyDateUtils.localDateTimeToDate(endTime));
+        subscription.setThirdSubscriptionId(subscriptionInfo.getSubscriptionId());
+        this.baseMapper.insert(subscription);
+        return subscription.getId();
+    }
+
+    @Override
+    public SubscriptionsVO getSubscriptions(String userId, String productId) {
+        SubscriptionsVO subscriptionsVO = new SubscriptionsVO();
+        // 可优化查询字段 添加 <.select>
+        BeanUtils.copyProperties(this.baseMapper.selectOne(new LambdaQueryWrapper<Subscription>()
+                .eq(Subscription::getUserId, userId)
+                .eq(Subscription::getProductId, productId)
+                .eq(Subscription::getStatus,SubscriptionConstant.actived)
+                .orderByDesc(Subscription::getEndDate)
+                .last("LIMIT 1")), subscriptionsVO);
+        return subscriptionsVO;
+    }
+
+    @Override
+    public String creatSubscriptionManual(CreatSubscriptionManualDTO subscriptionManual) {
+        CreatSubscriptionDTO creatSubscriptionDTO = new CreatSubscriptionDTO();
+        BeanUtils.copyProperties(subscriptionManual,creatSubscriptionDTO);
+        return this.creatSubscription(creatSubscriptionDTO);
+    }
+
+    @Override
+    public void chargebackSubscription(ChargebackOrderDTO chargebackOrderDTO) {
+        Subscription subscription = this.baseMapper.selectById(chargebackOrderDTO.getSubscriptionId());
+        String thirdSubscriptionId = subscription.getThirdSubscriptionId();
+        // 更新paddle的订阅信息
+        paddleClient.cancelSubscription(thirdSubscriptionId);
+        // 修改订阅状态
+        Subscription subscriptions = new Subscription();
+        subscriptions.setId(chargebackOrderDTO.getSubscriptionId());
+        subscriptions.setStatus(SubscriptionConstant.refunded);
+        this.baseMapper.updateById(subscriptions);
+    }
+
+    /**
+     * 获取订阅结束时间
+     *
+     * @param subscriptionInfo subscriptionInfo
+     * @param originalTime    开始时间
+     * @return 结束时间
+     */
+    private LocalDateTime getEndTime(CreatSubscriptionDTO subscriptionInfo, LocalDateTime originalTime) {
+        ProductVO product = productApi.getProduct(subscriptionInfo.getProductId()).getResult();
+        String forPeriod = product.getForPeriod();
+        return MyDateUtils.TimeAddition(originalTime, forPeriod);
+    }
+
+    /**
+     * 获取初始开始时间
+     *
+     * @param subscriptionInfo subscriptionInfo
+     * @param now now
+     * @return LocalDateTime
+     */
+    private LocalDateTime getOriginalTime(CreatSubscriptionDTO subscriptionInfo, LocalDateTime now) {
+        // 通过用户id和产品id获取最新订阅信息
+        SubscriptionsVO newestSubscriptions = getSubscriptions(subscriptionInfo.getUserId(), subscriptionInfo.getProductId());
+        LocalDateTime originalTime;
         // 没有订阅数据
         if (ObjectUtils.isEmpty(newestSubscriptions)) {
             originalTime = now;
@@ -58,28 +134,6 @@ public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, S
                 originalTime = localDateTime;
             }
         }
-        //
-        Product product = productService.getProduct(orderInfo.getProductId());
-        String forPeriod = product.getForPeriod();
-        LocalDateTime endTime = MyDateUtils.TimeAddition(originalTime, forPeriod);
-        // 产生一条最新的订阅信息
-        Subscriptions subscription = new Subscriptions();
-        subscription.setProductId(orderInfo.getUserId());
-        subscription.setStatus(SubscriptionConstant.actived);
-        subscription.setUserId(orderInfo.getUserId());
-        subscription.setStartDate(MyDateUtils.localDateTimeToDate(now));
-        subscription.setEndDate(MyDateUtils.localDateTimeToDate(endTime));
-        subscription.setSubscriptionId(orderInfo.getSubscriptionId());
-    }
-
-    @Override
-    public Subscriptions getSubscriptions(String userId, String productId) {
-        return this.baseMapper.selectOne(new LambdaQueryWrapper<Subscriptions>()
-                .eq(Subscriptions::getUserId, userId)
-                .eq(Subscriptions::getProductId, productId)
-                .orderByDesc(Subscriptions::getEndDate)
-                .last("LIMIT 1"));
+        return originalTime;
     }
-
-
 }

+ 1 - 1
pdf-office-payment/src/main/resources/mapper/OrdersMapper.xml

@@ -4,7 +4,7 @@
 <mapper namespace="cn.kdan.cloud.pdf.office.payment.mapper.OrdersMapper">
 
     <!-- 可根据自己的需求,是否要使用 -->
-    <resultMap id="OrdersResultMap" type="cn.kdan.cloud.pdf.office.payment.entity.Orders">
+    <resultMap id="OrdersResultMap" type="cn.kdan.cloud.pdf.office.payment.entity.Order">
         <result property="id" column="id" />
         <result property="appId" column="app_id" />
         <result property="subscriptionId" column="subscription_id" />

+ 1 - 1
pdf-office-payment/src/main/resources/mapper/SubscriptionsMapper.xml

@@ -4,7 +4,7 @@
 <mapper namespace="cn.kdan.cloud.pdf.office.payment.mapper.SubscriptionsMapper">
 
     <!-- 可根据自己的需求,是否要使用 -->
-    <resultMap id="SubscriptionsResultMap" type="cn.kdan.cloud.pdf.office.payment.entity.Subscriptions">
+    <resultMap id="SubscriptionsResultMap" type="cn.kdan.cloud.pdf.office.payment.entity.Subscription">
         <result property="id" column="id" />
         <result property="productId" column="product_id" />
         <result property="status" column="status" />

+ 2 - 2
pdf-office-payment/src/test/java/cn/kdan/cloud/pdf/office/payment/PaddleTest.java

@@ -38,9 +38,9 @@ public class PaddleTest {
     @Test
     public void creatOrder() {
         CreatOrderDTO creatOrderDTO = CreatOrderDTO.builder()
-                .appId("12312312312")
+                .appId("1231233123")
                 .productId("1")
-                .userId("2312321")
+                .userId("231232221")
                 .paymentMethod(PaymentMethodEnum.PADDLE)
                 .build();
         System.out.println(ordersService.creatOrder(creatOrderDTO));

+ 154 - 0
pdf-office-product/pom.xml

@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>backend</artifactId>
+        <groupId>cn.kdan.pdf.office</groupId>
+        <version>0.0.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>pdf-office-product</artifactId>
+    <description>产品/app/活动 中心</description>
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>cn.kdan.pdf.office</groupId>
+            <artifactId>pdf-office-common</artifactId>
+            <version>0.0.1</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-amqp</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.kdan.pdf.office</groupId>
+            <artifactId>pdf-office-api-product</artifactId>
+            <version>0.0.1</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>cn.kdan.pdf.office</groupId>
+                    <artifactId>pdf-office-common</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+    </dependencies>
+
+
+    <build>
+        <finalName>pdf-office-product</finalName>
+
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+
+
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.22.2</version>
+                <configuration>
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <version>${docker.version}</version>
+                <configuration>
+                    <!-- Docker 远程管理地址-->
+                    <dockerHost>http://${docker.host}</dockerHost>
+                    <!--镜像名称-->
+                    <imageName>${project.artifactId}</imageName>
+                    <!--Dockerfile-->
+                    <dockerDirectory>${project.basedir}/docker</dockerDirectory>
+                    <!--插件会将需要的资源拷贝到docker目录下,供Dockerfile里构建镜像使用-->
+                    <resources>
+                        <resource>
+                            <targetPath>/</targetPath>
+                            <directory>${project.build.directory}</directory>
+                            <include>${project.build.finalName}.jar</include>
+                        </resource>
+                    </resources>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 25 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/PDFOfficeProductApplication.java

@@ -0,0 +1,25 @@
+package cn.kdan.cloud.pdf.office.product;
+
+import cn.kdan.cloud.pdf.office.common.annotation.EnableMybatisPlusConfig;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.netflix.hystrix.EnableHystrix;
+
+/**
+ * @author ComPDFKit-WPH 2023/1/12
+ */
+
+@SpringBootApplication
+@EnableDiscoveryClient
+@EnableHystrix
+@EnableMybatisPlusConfig
+@MapperScan("cn.kdan.cloud.pdf.office.product.mapper")
+public class PDFOfficeProductApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(PDFOfficeProductApplication.class, args);
+    }
+
+}

+ 37 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/controller/ProductController.java

@@ -0,0 +1,37 @@
+package cn.kdan.cloud.pdf.office.product.controller;
+
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductPriceVo;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
+import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
+import cn.kdan.cloud.pdf.office.product.service.ProductService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/1
+ */
+@RestController
+@RequestMapping("/product")
+@RequiredArgsConstructor
+public class ProductController {
+
+    private final ProductService productService;
+
+    @GetMapping("/getProductPrice")
+    public ResultMap<ProductPriceVo> getProductPrice(@Validated @NotNull(message = "产品id不能为空") @RequestParam("productId") String productId){
+        return ResultMap.success(productService.getProductPrice(productId));
+    }
+
+
+    @GetMapping("/getProduct")
+    public ResultMap<ProductVO> getProduct(@Validated @NotNull(message = "产品id不能为空") @RequestParam("productId") String productId){
+        return ResultMap.success(productService.getProduct(productId));
+    }
+
+}

+ 2 - 1
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/entity/Product.java

@@ -1,4 +1,4 @@
-package cn.kdan.cloud.pdf.office.payment.entity;
+package cn.kdan.cloud.pdf.office.product.entity;
 
 import cn.kdan.cloud.pdf.office.common.base.BaseEntity;
 import com.baomidou.mybatisplus.annotation.IdType;
@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+
 import java.math.BigDecimal;
 
 /**

+ 2 - 2
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/mapper/ProductMapper.java

@@ -1,6 +1,6 @@
-package cn.kdan.cloud.pdf.office.payment.mapper;
+package cn.kdan.cloud.pdf.office.product.mapper;
 
-import cn.kdan.cloud.pdf.office.payment.entity.Product;
+import cn.kdan.cloud.pdf.office.product.entity.Product;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
 /**

+ 7 - 9
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/ProductService.java

@@ -1,13 +1,11 @@
-package cn.kdan.cloud.pdf.office.payment.service;
+package cn.kdan.cloud.pdf.office.product.service;
 
-import cn.kdan.cloud.pdf.office.api.payment.dto.ProductListDTO;
-import cn.kdan.cloud.pdf.office.api.payment.vo.ProductPriceVo;
-import cn.kdan.cloud.pdf.office.api.payment.vo.ProductVO;
-import cn.kdan.cloud.pdf.office.payment.entity.Product;
-import com.baomidou.mybatisplus.extension.service.IService;
+import cn.kdan.cloud.pdf.office.api.product.dto.ProductListDTO;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductPriceVo;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
+import cn.kdan.cloud.pdf.office.product.entity.Product;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-
-import java.math.BigDecimal;
+import com.baomidou.mybatisplus.extension.service.IService;
 
 /**
  * @author ComPDFKit-WPH 2023-01-28
@@ -35,5 +33,5 @@ public interface ProductService extends IService<Product> {
      * @param productId id
      * @return Product
      */
-    Product getProduct(String productId);
+    ProductVO getProduct(String productId);
 }

+ 11 - 11
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/ProductServiceImpl.java

@@ -1,21 +1,19 @@
-package cn.kdan.cloud.pdf.office.payment.service.impl;
+package cn.kdan.cloud.pdf.office.product.service.impl;
 
-import cn.kdan.cloud.pdf.office.api.payment.dto.ProductListDTO;
-import cn.kdan.cloud.pdf.office.api.payment.vo.ProductPriceVo;
-import cn.kdan.cloud.pdf.office.api.payment.vo.ProductVO;
+import cn.kdan.cloud.pdf.office.api.product.dto.ProductListDTO;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductPriceVo;
+import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
 import cn.kdan.cloud.pdf.office.common.utils.JsonUtils;
-import cn.kdan.cloud.pdf.office.payment.entity.Product;
-import cn.kdan.cloud.pdf.office.payment.mapper.ProductMapper;
-import cn.kdan.cloud.pdf.office.payment.service.ProductService;
+import cn.kdan.cloud.pdf.office.product.entity.Product;
+import cn.kdan.cloud.pdf.office.product.mapper.ProductMapper;
+import cn.kdan.cloud.pdf.office.product.service.ProductService;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
-import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -43,8 +41,10 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
     }
 
     @Override
-    public Product getProduct(String productId) {
-        return this.baseMapper.selectOne(new LambdaQueryWrapper<Product>().eq(Product::getId,productId));
+    public ProductVO getProduct(String productId) {
+        ProductVO productVO = new ProductVO();
+        BeanUtils.copyProperties(this.baseMapper.selectOne(new LambdaQueryWrapper<Product>().eq(Product::getId,productId)),productVO);
+        return productVO;
     }
 
 

+ 12 - 0
pdf-office-product/src/main/resources/bootstrap.properties

@@ -0,0 +1,12 @@
+spring.profiles.active=@spring.profiles.active@
+server.servlet.context-path=/
+spring.application.name=pdf-office-product
+spring.cloud.nacos.config.server-addr=http://106.55.99.175:8848
+spring.cloud.nacos.config.username=nacos
+spring.cloud.nacos.config.password=Nacos@123!
+spring.cloud.nacos.config.file-extension=yml
+spring.cloud.nacos.config.refresh-enabled=true
+
+spring.cloud.nacos.discovery.server-addr=http://localhost:8848
+spring.cloud.nacos.discovery.username=nacos
+spring.cloud.nacos.discovery.password=nacos

+ 73 - 0
pdf-office-product/src/main/resources/logback-spring.xml

@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration debug="false">
+    <!-- 引入spirng boot默认的logback配置文件 -->
+    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+    <springProperty scope="context" name="logPath" source="log.path" />
+    <springProperty scope="context" name="logLevel" source="log.level" />
+    <!-- 控制台输出 -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <!-- 按照每天生成日志文件 info输出 -->
+    <appender name="FileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!--只输出INFO-->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!--过滤 INFO-->
+            <level>INFO</level>
+            <!--匹配到就禁止-->
+            <onMatch>ACCEPT</onMatch>
+            <!--没有匹配到就允许-->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <!--滚动策略-->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <!--日志文件输出的文件名-->
+            <FileNamePattern>${logPath}/account-provider/account-provider_%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+            <!--日志文件保留天数-->
+            <MaxHistory>30</MaxHistory>
+            <!--日志文件最大的大小-->
+            <MaxFileSize>300MB</MaxFileSize>
+        </rollingPolicy>
+        <!--格式化输出-->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <!--warn文件输出-->
+    <!-- 按照每天和固定大小(10MB)生成日志文件【最新的日志,是日期最大数字最大的】 -->
+    <appender name="FileWarnLog"  class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <!--设置日志级别,过滤掉info日志,只输入warn日志-->
+            <level>WARN</level>
+        </filter>
+        <!--滚动策略-->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <!--日志文件输出的文件名-->
+            <FileNamePattern>${logPath}/account-provider/account-provider_warn_%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+            <!--日志文件保留天数-->
+            <MaxHistory>30</MaxHistory>
+            <!--日志文件最大的大小-->
+            <MaxFileSize>300MB</MaxFileSize>
+        </rollingPolicy>
+        <!--格式化输出-->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+
+    <!-- 日志输出级别 -->
+    <root level="${logLevel}">
+        <appender-ref ref="STDOUT" />
+        <appender-ref ref="FileWarnLog" />
+        <appender-ref ref="FileInfoLog" />
+    </root>
+</configuration>

+ 1 - 1
pdf-office-payment/src/main/resources/mapper/ProductMapper.xml

@@ -4,7 +4,7 @@
 <mapper namespace="cn.kdan.cloud.pdf.office.payment.mapper.ProductMapper">
 
     <!-- 可根据自己的需求,是否要使用 -->
-    <resultMap id="ProductResultMap" type="cn.kdan.cloud.pdf.office.payment.entity.Product">
+    <resultMap id="ProductResultMap" type="cn.kdan.cloud.pdf.office.product.entity.Product">
         <result property="id" column="id" />
         <result property="productName" column="product_name" />
         <result property="appId" column="app_id" />

+ 1 - 0
pom.xml

@@ -342,6 +342,7 @@
         <module>pdf-office-app</module>
         <module>pdf-office-pdf-website</module>
         <module>pdf-office-system</module>
+        <module>pdf-office-product</module>
 
     </modules>