Forráskód Böngészése

Merge remote-tracking branch 'origin/master'

tangxiangan 2 éve
szülő
commit
d613750cb2
14 módosított fájl, 230 hozzáadás és 14 törlés
  1. 6 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatSubscriptionDTO.java
  2. 21 0
      pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/annotation/EnableCommonFeignExceptionHandle.java
  3. 10 1
      pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/aop/ControllerExceptionHandler.java
  4. 49 0
      pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/aop/FeignExceptionAspect.java
  5. 27 0
      pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/config/CloudServerConfiguration.java
  6. 26 4
      pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/config/RabbitMqConfig.java
  7. 7 4
      pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/constant/RabbitMqConstant.java
  8. 20 0
      pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/exception/FeignBackendRuntimeException.java
  9. 6 4
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/PDFOfficePaymentApplication.java
  10. 11 1
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/SubscriptionsServiceImpl.java
  11. 42 0
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/utils/SubscriptionUtil.java
  12. 2 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/PDFOfficeProductApplication.java
  13. 2 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/controller/ProductController.java
  14. 1 0
      pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/impl/ProductServiceImpl.java

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

@@ -32,5 +32,11 @@ public class CreatSubscriptionDTO implements Serializable {
     @NotNull(message = "orderId 不能为空")
     private String orderId;
 
+    /**
+     * 有效期 1.months ,1.years,1.days
+     * 不填以产品中的有效期为准
+     */
+    private String termOfValidity;
+
 
 }

+ 21 - 0
pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/annotation/EnableCommonFeignExceptionHandle.java

@@ -0,0 +1,21 @@
+package cn.kdan.cloud.pdf.office.common.annotation;
+
+import cn.kdan.cloud.pdf.office.common.aop.FeignExceptionAspect;
+import cn.kdan.cloud.pdf.office.common.config.CloudServerConfiguration;
+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({ CloudServerConfiguration.class, FeignExceptionAspect.class})
+public @interface EnableCommonFeignExceptionHandle {
+
+}

+ 10 - 1
pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/aop/ControllerExceptionHandler.java

@@ -1,8 +1,9 @@
 package cn.kdan.cloud.pdf.office.common.aop;
 
-import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
 import cn.kdan.cloud.pdf.office.common.constant.CommonConstant;
 import cn.kdan.cloud.pdf.office.common.exception.BackendRuntimeException;
+import cn.kdan.cloud.pdf.office.common.exception.FeignBackendRuntimeException;
+import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.validation.BindingResult;
@@ -40,9 +41,17 @@ public class ControllerExceptionHandler {
     @ExceptionHandler(BackendRuntimeException.class)
     @ResponseBody
     public ResultMap handlerRuntimeException(BackendRuntimeException e){
+        logger.error("业务异常:"+e.getMessage(),e);
         return new ResultMap(CommonConstant.EXCEPTION_CODE_RUNTIME_ERROR,e.getMessage());
     }
 
+    @ExceptionHandler(FeignBackendRuntimeException.class)
+    @ResponseBody
+    public ResultMap handlerFeignRuntimeException(FeignBackendRuntimeException e){
+        logger.error("feign 业务异常:"+e.getMessage(),e);
+        return new ResultMap(e.getCode(),e.getMessage());
+    }
+
     @ExceptionHandler(Exception.class)
     @ResponseBody
     public ResultMap handlerException(Exception e){

+ 49 - 0
pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/aop/FeignExceptionAspect.java

@@ -0,0 +1,49 @@
+package cn.kdan.cloud.pdf.office.common.aop;
+
+import cn.kdan.cloud.pdf.office.common.exception.BackendRuntimeException;
+import cn.kdan.cloud.pdf.office.common.exception.FeignBackendRuntimeException;
+import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+
+/**
+ * Title: FeignExceptionAspect
+ * Description: Feign统一异常处理
+ */
+@Aspect
+@Order(Ordered.LOWEST_PRECEDENCE - 100)
+public class FeignExceptionAspect {
+
+    /**
+     * Pointcut注解声明切点
+     * 配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
+     *
+     * @within 对类起作用,@annotation 对方法起作用
+     */
+    @Pointcut("@within(org.springframework.cloud.openfeign.FeignClient)")
+    public void feignClientPointCut() {
+    }
+
+    /**
+     * 配置前置通知,使用在方法aspect()上注册的切入点
+     * 同时接受JoinPoint切入点对象,可以没有该参数
+     *
+     * @param proceedingJoinPoint
+     * @throws ClassNotFoundException
+     */
+    @Around("feignClientPointCut()")
+    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
+        Object object = proceedingJoinPoint.proceed();
+        if (object instanceof ResultMap<?>) {
+            ResultMap<?> responseDTO = (ResultMap<?>) object;
+            if (responseDTO.getCode() != 200) {
+                throw new FeignBackendRuntimeException(responseDTO.getCode(),responseDTO.getMsg());
+            }
+        }
+        return object;
+    }
+}

+ 27 - 0
pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/config/CloudServerConfiguration.java

@@ -0,0 +1,27 @@
+package cn.kdan.cloud.pdf.office.common.config;
+
+import cn.kdan.cloud.pdf.office.common.aop.FeignExceptionAspect;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/8
+ */
+@Configuration
+public class CloudServerConfiguration {
+
+//    @Bean
+//    public HeaderInterceptor headerInterceptor() {
+//        //微服务权限拦截处理
+//        return new HeaderInterceptor();
+//    }
+
+    @Bean
+    @ConditionalOnProperty(name = "system.cloud.feign.exception.enabled", havingValue="true", matchIfMissing=true)
+    public FeignExceptionAspect feignExceptionAspect() {
+        //微服务权限拦截处理
+        return new FeignExceptionAspect();
+    }
+
+}

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

@@ -46,7 +46,6 @@ public class RabbitMqConfig {
         );
     }
 
-
     // 交换机配置
     /* email交换机 */
     @Bean
@@ -65,16 +64,15 @@ public class RabbitMqConfig {
         return new DirectExchange(RabbitMqConstant.DELAY_EXCHANGE,true,false);
     }
 
+    // 订单关闭
     @Bean
     public Queue paymentOrderDelayQueue(){
         return new Queue(RabbitMqConstant.PAYMENT_ORDER_DELAY_QUEUE, true, false, false);
     }
-
     @Bean
     public Binding paymentOrderDelayBinding() {
         return BindingBuilder.bind(paymentOrderDelayQueue()).to(delayExchange()).with(RabbitMqConstant.PAYMENT_ORDER_ROUTING_KEY);
     }
-
     @Bean
     public Queue paymentOrderQueue() {
         Map<String, Object> params = new HashMap<>();
@@ -84,7 +82,6 @@ public class RabbitMqConfig {
         params.put("x-dead-letter-routing-key", RabbitMqConstant.PAYMENT_ORDER_ROUTING_KEY);
         return new Queue(RabbitMqConstant.PAYMENT_ORDER_QUEUE,true,false,false,params);
     }
-
     @Bean
     public Binding paymentOrderBinding() {
         // 如果要让延迟队列之间有关联,这里的 routingKey 和 绑定的交换机很关键
@@ -93,6 +90,31 @@ public class RabbitMqConfig {
                 .with(RabbitMqConstant.PAYMENT_ORDER_ROUTING_KEY);
     }
 
+    // 订阅过期死信队列
+    @Bean
+    public Queue paymentSubscriptionExpireDelayQueue(){
+        return new Queue(RabbitMqConstant.PAYMENT_SUBSCRIPTION_EXPIRED_DELAY_QUEUE, true, false, false);
+    }
+    @Bean
+    public Binding paymentSubscriptionExpireDelayBinding() {
+        return BindingBuilder.bind(paymentSubscriptionExpireDelayQueue()).to(delayExchange()).with(RabbitMqConstant.PAYMENT_SUBSCRIPTION_EXPIRED_ROUTING_KEY);
+    }
+    @Bean
+    public Queue paymentSubscriptionExpireQueue() {
+        Map<String, Object> params = new HashMap<>();
+        // x-dead-letter-exchange 声明了队列里的死信转发到的DLX名称,
+        params.put("x-dead-letter-exchange", RabbitMqConstant.DELAY_EXCHANGE);
+        // x-dead-letter-routing-key 声明了这些死信在转发时携带的 routing-key 名称。
+        params.put("x-dead-letter-routing-key", RabbitMqConstant.PAYMENT_SUBSCRIPTION_EXPIRED_DELAY_QUEUE);
+        return new Queue(RabbitMqConstant.PAYMENT_SUBSCRIPTION_EXPIRED_QUEUE,true,false,false,params);
+    }
+    @Bean
+    public Binding paymentSubscriptionExpireBinding() {
+        // 如果要让延迟队列之间有关联,这里的 routingKey 和 绑定的交换机很关键
+        return BindingBuilder.bind(paymentSubscriptionExpireQueue())
+                .to(paymentExchange())
+                .with(RabbitMqConstant.PAYMENT_SUBSCRIPTION_EXPIRED_ROUTING_KEY);
+    }
 
     // 普通队列配置
     /* 发送email队列 */

+ 7 - 4
pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/constant/RabbitMqConstant.java

@@ -2,9 +2,8 @@ package cn.kdan.cloud.pdf.office.common.constant;
 
 /**
  * @author ComPDFKit-WPH 2023/1/11
- *
+ * <p>
  * RabbitMq 公共字段
- *
  */
 public interface RabbitMqConstant {
 
@@ -24,8 +23,12 @@ public interface RabbitMqConstant {
 
     /* 订单过期关单路由 */
     String PAYMENT_ORDER_ROUTING_KEY = "payment.order";
-
     String PAYMENT_ORDER_DELAY_QUEUE = "pdf_office_payment_order_delay_queue";
-
     String PAYMENT_ORDER_QUEUE = "pdf_office_payment_order_queue";
+
+    /* 订阅过期路由和队列 */
+    String PAYMENT_SUBSCRIPTION_EXPIRED_ROUTING_KEY = "payment.subscription.expired";
+    String PAYMENT_SUBSCRIPTION_EXPIRED_DELAY_QUEUE = "pdf_office_payment_subscription_expired_delay_queue";
+    String PAYMENT_SUBSCRIPTION_EXPIRED_QUEUE = "pdf_office_payment_subscription_expired_queue";
+
 }

+ 20 - 0
pdf-office-common/src/main/java/cn/kdan/cloud/pdf/office/common/exception/FeignBackendRuntimeException.java

@@ -0,0 +1,20 @@
+package cn.kdan.cloud.pdf.office.common.exception;
+
+import lombok.Getter;
+
+/**
+ * @author tangxiangan
+ */
+@Getter
+public class FeignBackendRuntimeException extends RuntimeException{
+    private final Integer code;
+
+    public FeignBackendRuntimeException(String message) {
+        super(message);
+        this.code = 500;
+    }
+    public FeignBackendRuntimeException(Integer code ,String message) {
+        super(message);
+        this.code = code;
+    }
+}

+ 6 - 4
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/PDFOfficePaymentApplication.java

@@ -1,9 +1,8 @@
 package cn.kdan.cloud.pdf.office.payment;
 
+import cn.kdan.cloud.pdf.office.api.account.annotation.EnableAccountApiClient;
 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;
+import cn.kdan.cloud.pdf.office.common.annotation.*;
 import cn.kdan.cloud.pdf.office.payment.properties.PaddleProperties;
 import cn.kdan.cloud.pdf.office.payment.properties.PaypalProperties;
 import cn.kdan.cloud.pdf.office.payment.verifier.Verifier;
@@ -16,7 +15,6 @@ import org.springframework.cache.annotation.EnableCaching;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.cloud.netflix.hystrix.EnableHystrix;
 import org.springframework.context.annotation.Bean;
-import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
 
 /**
  * @author ComPDFKit-WPH 2023/1/12
@@ -33,6 +31,9 @@ import org.springframework.data.redis.repository.configuration.EnableRedisReposi
 @EnableCaching
 @EnableCommonTools
 @EnableProductApiClient
+@EnableAccountApiClient
+@EnableCommonFeignExceptionHandle
+@EnableControllerExceptionHandler
 public class PDFOfficePaymentApplication {
 
     public static void main(String[] args) {
@@ -57,4 +58,5 @@ public class PDFOfficePaymentApplication {
                 "-----END PUBLIC KEY-----");
     }
 
+
 }

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

@@ -19,6 +19,7 @@ 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.OrdersService;
 import cn.kdan.cloud.pdf.office.payment.service.SubscriptionsService;
+import cn.kdan.cloud.pdf.office.payment.utils.SubscriptionUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
@@ -27,6 +28,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.amqp.rabbit.core.RabbitTemplate;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
@@ -49,6 +51,8 @@ public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, S
 
     private final OrdersService ordersService;
 
+    private final RabbitTemplate rabbitTemplate;
+
     @Override
     public IPage<Subscription> page(Subscription query) {
         return this.page(new Page<>(query.getPage(), query.getSize()), Wrappers.query(query));
@@ -75,7 +79,10 @@ public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, S
         subscription.setThirdSubscriptionId(subscriptionInfo.getSubscriptionId());
         subscription.setOrderId(subscriptionInfo.getOrderId());
         this.baseMapper.insert(subscription);
-        return subscription.getId();
+        String subscriptionId = subscription.getId();
+        // 发送消息
+        SubscriptionUtil.subscriptionExpiredSendNews(rabbitTemplate,subscriptionId,endTime);
+        return subscriptionId;
     }
 
     @Override
@@ -147,6 +154,9 @@ public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, S
      * @return 结束时间
      */
     private LocalDateTime getEndTime(CreatSubscriptionDTO subscriptionInfo, LocalDateTime originalTime) {
+        if (!ObjectUtils.isEmpty(subscriptionInfo.getTermOfValidity())){
+            return MyDateUtils.TimeAddition(originalTime, subscriptionInfo.getTermOfValidity());
+        }
         ProductVO product = productApi.getProduct(subscriptionInfo.getProductId()).getResult();
         String forPeriod = product.getForPeriod();
         return MyDateUtils.TimeAddition(originalTime, forPeriod);

+ 42 - 0
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/utils/SubscriptionUtil.java

@@ -0,0 +1,42 @@
+package cn.kdan.cloud.pdf.office.payment.utils;
+
+import cn.kdan.cloud.pdf.office.common.constant.RabbitMqConstant;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+
+import java.time.Duration;
+import java.time.LocalDateTime;
+
+/**
+ * @author ComPDFKit-WPH 2023/2/8
+ * <p>
+ * SubscriptionUtil
+ */
+@Slf4j
+public class SubscriptionUtil {
+
+    private SubscriptionUtil() {
+    }
+
+    /**
+     * 订阅过期消息发送
+     *
+     * @param rabbitTemplate rabbitTemplate
+     * @param subscriptionId subscriptionId
+     * @param endTime        ttl
+     */
+    public static void subscriptionExpiredSendNews(RabbitTemplate rabbitTemplate, String subscriptionId, LocalDateTime endTime) {
+        LocalDateTime now = LocalDateTime.now();
+        long ttl = Duration.between(now, endTime).toMillis() + 1000L;
+        // 订阅过期
+        log.info("rabbitMq 发送延时队列,订阅过期:{}", subscriptionId);
+        rabbitTemplate.convertAndSend(RabbitMqConstant.PAYMENT_EXCHANGE,
+                RabbitMqConstant.PAYMENT_SUBSCRIPTION_EXPIRED_ROUTING_KEY,
+                subscriptionId,
+                (msg -> {
+                    msg.getMessageProperties().setExpiration(ttl + "");
+                    return msg;
+                }));
+    }
+}

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

@@ -1,5 +1,6 @@
 package cn.kdan.cloud.pdf.office.product;
 
+import cn.kdan.cloud.pdf.office.common.annotation.EnableControllerExceptionHandler;
 import cn.kdan.cloud.pdf.office.common.annotation.EnableMybatisPlusConfig;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
@@ -16,6 +17,7 @@ import org.springframework.cloud.netflix.hystrix.EnableHystrix;
 @EnableHystrix
 @EnableMybatisPlusConfig
 @MapperScan("cn.kdan.cloud.pdf.office.product.mapper")
+@EnableControllerExceptionHandler
 public class PDFOfficeProductApplication {
 
     public static void main(String[] args) {

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

@@ -3,6 +3,7 @@ package cn.kdan.cloud.pdf.office.product.controller;
 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.exception.BackendRuntimeException;
 import cn.kdan.cloud.pdf.office.common.pojo.ResultMap;
 import cn.kdan.cloud.pdf.office.product.service.ProductService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -28,6 +29,7 @@ public class ProductController {
     @GetMapping("/getProductPrice")
     public ResultMap<ProductPriceVo> getProductPrice(@Validated @NotNull(message = "产品id不能为空") @RequestParam("productId") String productId,
                                                      @NotNull(message = "userId不能为空") @RequestParam("userId") String userId) {
+
         return ResultMap.success(productService.getProductPrice(productId, userId));
     }
 

+ 1 - 0
pdf-office-product/src/main/java/cn/kdan/cloud/pdf/office/product/service/impl/ProductServiceImpl.java

@@ -4,6 +4,7 @@ import cn.kdan.cloud.pdf.office.api.product.dto.ProductListDTO;
 import cn.kdan.cloud.pdf.office.api.product.vo.ActivityInfoVO;
 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.exception.BackendRuntimeException;
 import cn.kdan.cloud.pdf.office.common.utils.JsonUtils;
 import cn.kdan.cloud.pdf.office.product.entity.Product;
 import cn.kdan.cloud.pdf.office.product.mapper.ProductMapper;