Browse Source

支付模块:添加appId字段

wangPH 2 years ago
parent
commit
73e93f422c
14 changed files with 161 additions and 72 deletions
  1. 4 2
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatSubscriptionDTO.java
  2. 2 1
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/dto/CreatSubscriptionManualDTO.java
  3. 6 6
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/feign/SubscriptionApi.java
  4. 4 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/OrderUpdateVO.java
  5. 2 0
      pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/vo/SubscriptionsVO.java
  6. 8 8
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/controller/SubscriptionController.java
  7. 2 0
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/entity/Subscription.java
  8. 47 1
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/listener/PaymentListener.java
  9. 11 0
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/mapper/SubscriptionsMapper.java
  10. 12 4
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/SubscriptionsService.java
  11. 3 1
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/OrdersServiceImpl.java
  12. 4 1
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/PaddleWebhookServiceImpl.java
  13. 21 23
      pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/SubscriptionsServiceImpl.java
  14. 35 25
      pdf-office-payment/src/main/resources/mapper/SubscriptionsMapper.xml

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

@@ -24,10 +24,12 @@ public class CreatSubscriptionDTO implements Serializable {
     /**
      * productId
      */
-    @NotNull(message = "productId 不能为空")
     private String productId;
 
-    private String subscriptionId;
+    @NotNull(message = "appId 不能为空")
+    private String appId;
+
+    private String thirdSubscriptionId;
 
     @NotNull(message = "orderId 不能为空")
     private String orderId;

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

@@ -23,8 +23,9 @@ public class CreatSubscriptionManualDTO implements Serializable {
     /**
      * productId
      */
-    @NotNull(message = "productId 不能为空")
     private String productId;
+    @NotNull(message = "appId 不能为空")
+    private String appId;
 
     private String thirdSubscriptionId;
 

+ 6 - 6
pdf-office-api/pdf-office-api-payment/src/main/java/cn/kdan/cloud/pdf/office/api/payment/feign/SubscriptionApi.java

@@ -33,13 +33,13 @@ public interface SubscriptionApi {
     /**
      * 通过用户id和产品id 获取最新的订阅信息
      *
-     * @param userId    userId
-     * @param productId productId
+     * @param userId userId
+     * @param appId  appId
      * @return Subscriptions
      */
     @GetMapping("/getSubscriptions")
     ResultMap<SubscriptionsVO> getSubscriptions(@Validated @NotNull(message = "userId 不能为空") @RequestParam("userId") String userId,
-                                                @NotNull(message = "productId 不能为空") @RequestParam("productId") String productId);
+                                                @NotNull(message = "appId 不能为空") @RequestParam("appId") String appId);
 
     /**
      * 手动创建订阅信息
@@ -54,12 +54,12 @@ public interface SubscriptionApi {
     /**
      * 查询当前用户的订阅计划和支付订单
      *
-     * @param userId    userId
-     * @param productId productId
+     * @param userId userId
+     * @param appId  appId
      * @return SubscriptionSchemeVO
      */
     @GetMapping("/getSubscriptionSchemeInfo")
     ResultMap<SubscriptionSchemeVO> getSubscriptionSchemeInfo(@NotNull(message = "用户id不能为空") String userId,
-                                                              @NotNull(message = "productId不能为空") String productId);
+                                                              @NotNull(message = "appId不能为空") String appId);
 
 }

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

@@ -18,4 +18,8 @@ public class OrderUpdateVO {
 
     private String userId;
 
+    private String productId;
+
+    private String appId;
+
 }

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

@@ -121,4 +121,6 @@ public class SubscriptionsVO implements Serializable {
     private String subscriptionId;
 
     private String orderId;
+
+    private String appId;
 }

+ 8 - 8
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/controller/SubscriptionController.java

@@ -38,14 +38,14 @@ public class SubscriptionController {
     /**
      * 通过用户id和产品id 获取最新的订阅信息
      *
-     * @param userId    userId
-     * @param productId productId
+     * @param userId userId
+     * @param appId  appId
      * @return Subscriptions
      */
     @GetMapping("/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));
+                                                       @NotNull(message = "appId 不能为空") @RequestParam("appId") String appId) {
+        return ResultMap.success(subscriptionsService.getSubscriptions(userId, appId));
     }
 
     /**
@@ -62,14 +62,14 @@ public class SubscriptionController {
     /**
      * 查询当前用户的订阅计划和支付订单
      *
-     * @param userId    userId
-     * @param productId productId
+     * @param userId userId
+     * @param appId  appId
      * @return SubscriptionSchemeVO
      */
     @GetMapping("/getSubscriptionSchemeInfo")
     public ResultMap<SubscriptionSchemeVO> getSubscriptionSchemeInfo(@Validated @NotNull(message = "用户id不能为空") String userId,
-                                                                     @Validated @NotNull(message = "productId不能为空") String productId) {
-        return ResultMap.success(subscriptionsService.getSubscriptionSchemeInfo(userId, productId));
+                                                                     @Validated @NotNull(message = "appId不能为空") String appId) {
+        return ResultMap.success(subscriptionsService.getSubscriptionSchemeInfo(userId, appId));
     }
 
 }

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

@@ -125,4 +125,6 @@ public class Subscription extends BaseEntity{
 
     private String orderId;
 
+    private String appId;
+
 }

+ 47 - 1
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/listener/PaymentListener.java

@@ -1,7 +1,13 @@
 package cn.kdan.cloud.pdf.office.payment.listener;
 
+import cn.kdan.cloud.pdf.office.api.account.feign.UserApi;
+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.common.constant.RabbitMqConstant;
+import cn.kdan.cloud.pdf.office.common.utils.MyDateUtils;
+import cn.kdan.cloud.pdf.office.common.vo.UserInfoVO;
 import cn.kdan.cloud.pdf.office.payment.service.OrdersService;
+import cn.kdan.cloud.pdf.office.payment.service.SubscriptionsService;
 import com.rabbitmq.client.Channel;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -9,6 +15,8 @@ import org.springframework.amqp.core.Message;
 import org.springframework.amqp.rabbit.annotation.RabbitListener;
 import org.springframework.stereotype.Component;
 
+import java.time.LocalDateTime;
+
 /**
  * @author ComPDFKit-WPH 2023/1/11
  */
@@ -19,8 +27,13 @@ public class PaymentListener {
 
     private final OrdersService ordersService;
 
+    private final SubscriptionsService subscriptionsService;
+
+    private final UserApi userApi;
+
+
     /**
-     * 发送邮件 监听
+     * 关闭订单 监听
      *
      * @param message message
      * @param channel channel
@@ -38,4 +51,37 @@ public class PaymentListener {
             log.error("消息消费失败:" + e.getMessage(), e);
         }
     }
+
+    /**
+     * 订阅过期 监听
+     *
+     * @param message        message
+     * @param channel        channel
+     * @param subscriptionId subscriptionId
+     */
+    @RabbitListener(queues = RabbitMqConstant.PAYMENT_SUBSCRIPTION_EXPIRED_DELAY_QUEUE)
+    public void paymentSubscriptionExpiredDelayQueue(Message message, Channel channel, String subscriptionId) {
+        try {
+            log.info("订阅过期 监听内容:{}", subscriptionId);
+            // 判断当前用户是否有有效的订阅模式
+            SubscriptionsVO subscriptionsVO = subscriptionsService.getSubscriptionBySubscriptionId(subscriptionId);
+            SubscriptionsVO subscription = subscriptionsService.getSubscriptions(subscriptionsVO.getUserId(), subscriptionsVO.getAppId());
+            LocalDateTime now = LocalDateTime.now();
+            LocalDateTime endDate = MyDateUtils.dateToLocalDateTime(subscription.getEndDate());
+            if (now.compareTo(endDate) > 0){
+                // 修改用户状态
+                // 获取当前用户的订阅状态
+                String validFlag = userApi.getById(subscription.getUserId()).getResult().getValidFlag();
+                // TODO 修改用户状态
+
+            }
+            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+            log.info("订阅过期 处理成功 :{}", subscriptionId);
+        } catch (Exception e) {
+            // TODO 补救策略
+            log.error("消息消费失败:" + e.getMessage(), e);
+        }
+    }
+
+
 }

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

@@ -1,11 +1,22 @@
 package cn.kdan.cloud.pdf.office.payment.mapper;
 
+import cn.kdan.cloud.pdf.office.api.payment.vo.SubscriptionsVO;
 import cn.kdan.cloud.pdf.office.payment.entity.Subscription;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * @author ComPDFKit-WPH 2023-01-28
  */
 public interface SubscriptionsMapper extends BaseMapper<Subscription> {
 
+    /**
+     * 通过用户id和产品id 获取最新的订阅信息
+     *
+     * @param userId userId
+     * @param appId  appId
+     * @return Subscriptions
+     */
+    SubscriptionsVO selectNewestSubscription(@Param("userId") String userId,
+                                             @Param("appId") String appId);
 }

+ 12 - 4
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/SubscriptionsService.java

@@ -35,11 +35,11 @@ public interface SubscriptionsService extends IService<Subscription> {
     /**
      * 通过用户id和产品id 获取最新的订阅信息
      *
-     * @param userId    userId
-     * @param productId productId
+     * @param userId userId
+     * @param appId  appId
      * @return Subscriptions
      */
-    SubscriptionsVO getSubscriptions(String userId, String productId);
+    SubscriptionsVO getSubscriptions(String userId, String appId);
 
     /**
      * 创建订阅信息 自动续订
@@ -58,7 +58,7 @@ public interface SubscriptionsService extends IService<Subscription> {
     String giveSubscriptionManual(CreatSubscriptionManualDTO subscriptionManual);
 
     /**
-     * 退单
+     * 取消订阅 退单
      *
      * @param chargebackOrderDTO chargebackOrderDTO
      */
@@ -72,4 +72,12 @@ public interface SubscriptionsService extends IService<Subscription> {
      * @return SubscriptionSchemeVO
      */
     SubscriptionSchemeVO getSubscriptionSchemeInfo(String userId, String productId);
+
+    /**
+     * 根据主键id获取
+     *
+     * @param subscriptionId subscriptionId
+     * @return SubscriptionsVO
+     */
+    SubscriptionsVO getSubscriptionBySubscriptionId(String subscriptionId);
 }

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

@@ -139,11 +139,13 @@ public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Order> implemen
         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)
+                .select(Order::getId, Order::getUserId,Order::getProductId,Order::getAppId)
                 .eq(Order::getTradeNo, orderSucceeded.getTradeNo()));
         return OrderUpdateVO.builder()
                 .orderId(orderTradeNo.getId())
                 .userId(orderTradeNo.getUserId())
+                .productId(orders.getProductId())
+                .appId(orders.getAppId())
                 .build();
     }
 

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

@@ -65,6 +65,9 @@ public class PaddleWebhookServiceImpl implements PaddleWebhookService {
         CreatSubscriptionDTO creatSubscription = new CreatSubscriptionDTO();
         creatSubscription.setUserId(orderUpdate.getUserId());
         creatSubscription.setOrderId(orderUpdate.getOrderId());
+        creatSubscription.setAppId(orderUpdate.getAppId());
+        creatSubscription.setProductId(orderUpdate.getProductId());
+        creatSubscription.setThirdSubscriptionId(paddleWebhookDTO.getSubscriptionId());
         subscriptionsService.creatSubscription(creatSubscription);
         // 用户信息
         UserInfoVO userInfo = userApi.getById(orderUpdate.getUserId()).getResult();
@@ -98,7 +101,7 @@ public class PaddleWebhookServiceImpl implements PaddleWebhookService {
         log.info("paddle 订阅的支付订单已成功 paddle订单id:{}",paddleWebhookDTO.getCheckoutId());
         OrdersVO orderByTradeNo = ordersService.getOrderByTradeNo(paddleWebhookDTO.getPassthrough()).get(0);
         // 判断当前是否存在订阅
-        SubscriptionsVO subscriptions = subscriptionsService.getSubscriptions(orderByTradeNo.getUserId(), orderByTradeNo.getProductId());
+        SubscriptionsVO subscriptions = subscriptionsService.getSubscriptions(orderByTradeNo.getUserId(), orderByTradeNo.getAppId());
         if (ObjectUtils.isEmpty(subscriptions)){
             throw new BackendRuntimeException(ErrorMessage.SUBSCRIPTION_NON_EXISTENT);
         }

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

@@ -1,6 +1,5 @@
 package cn.kdan.cloud.pdf.office.payment.service.impl;
 
-import cn.kdan.cloud.pdf.office.api.account.dto.UpdateUserForPaySuccessDTO;
 import cn.kdan.cloud.pdf.office.api.account.feign.UserApi;
 import cn.kdan.cloud.pdf.office.api.payment.constant.SubscriptionConstant;
 import cn.kdan.cloud.pdf.office.api.payment.dto.ChargebackOrderDTO;
@@ -11,7 +10,6 @@ import cn.kdan.cloud.pdf.office.api.payment.vo.SubscriptionSchemeVO;
 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.enums.status.UserStatusEnum;
 import cn.kdan.cloud.pdf.office.common.utils.MyDateUtils;
 import cn.kdan.cloud.pdf.office.common.vo.UserInfoVO;
 import cn.kdan.cloud.pdf.office.payment.client.PaddleClient;
@@ -20,7 +18,6 @@ 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;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -76,26 +73,19 @@ public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, S
         subscription.setUserId(subscriptionInfo.getUserId());
         subscription.setStartDate(MyDateUtils.localDateTimeToDate(now));
         subscription.setEndDate(MyDateUtils.localDateTimeToDate(endTime));
-        subscription.setThirdSubscriptionId(subscriptionInfo.getSubscriptionId());
+        subscription.setThirdSubscriptionId(subscriptionInfo.getThirdSubscriptionId());
         subscription.setOrderId(subscriptionInfo.getOrderId());
+        subscription.setAppId(subscriptionInfo.getAppId());
         this.baseMapper.insert(subscription);
         String subscriptionId = subscription.getId();
         // 发送消息
-        SubscriptionUtil.subscriptionExpiredSendNews(rabbitTemplate,subscriptionId,endTime);
+        SubscriptionUtil.subscriptionExpiredSendNews(rabbitTemplate, subscriptionId, endTime);
         return subscriptionId;
     }
 
     @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;
+    public SubscriptionsVO getSubscriptions(String userId, String appId) {
+        return this.baseMapper.selectNewestSubscription(userId, appId);
     }
 
     @Override
@@ -125,16 +115,16 @@ public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, S
         // 更新paddle的订阅信息
         paddleClient.cancelSubscription(thirdSubscriptionId);
         // 修改订阅状态
-        Subscription subscriptions = new Subscription();
-        subscriptions.setId(chargebackOrderDTO.getSubscriptionId());
-        subscriptions.setStatus(SubscriptionConstant.refunded);
-        this.baseMapper.updateById(subscriptions);
+//        Subscription subscriptions = new Subscription();
+//        subscriptions.setId(chargebackOrderDTO.getSubscriptionId());
+//        subscriptions.setStatus(SubscriptionConstant.refunded);
+//        this.baseMapper.updateById(subscriptions);
     }
 
     @Override
-    public SubscriptionSchemeVO getSubscriptionSchemeInfo(String userId, String productId) {
+    public SubscriptionSchemeVO getSubscriptionSchemeInfo(String userId, String appId) {
         // 获取最新订阅信息
-        SubscriptionsVO subscriptions = this.getSubscriptions(userId, productId);
+        SubscriptionsVO subscriptions = this.getSubscriptions(userId, appId);
         // 获取该订阅关联的所有订单
         String orderId = subscriptions.getOrderId();
         String thirdTradeNo = ordersService.getOrderById(orderId).getThirdTradeNo();
@@ -145,6 +135,14 @@ public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, S
         return subscriptionSchemeVO;
     }
 
+    @Override
+    public SubscriptionsVO getSubscriptionBySubscriptionId(String subscriptionId) {
+        Subscription subscription = this.baseMapper.selectById(subscriptionId);
+        SubscriptionsVO subscriptionsVO = new SubscriptionsVO();
+        BeanUtils.copyProperties(subscription,subscriptionsVO);
+        return subscriptionsVO;
+    }
+
 
     /**
      * 获取订阅结束时间
@@ -154,7 +152,7 @@ public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, S
      * @return 结束时间
      */
     private LocalDateTime getEndTime(CreatSubscriptionDTO subscriptionInfo, LocalDateTime originalTime) {
-        if (!ObjectUtils.isEmpty(subscriptionInfo.getTermOfValidity())){
+        if (!ObjectUtils.isEmpty(subscriptionInfo.getTermOfValidity())) {
             return MyDateUtils.TimeAddition(originalTime, subscriptionInfo.getTermOfValidity());
         }
         ProductVO product = productApi.getProduct(subscriptionInfo.getProductId()).getResult();
@@ -171,7 +169,7 @@ public class SubscriptionsServiceImpl extends ServiceImpl<SubscriptionsMapper, S
      */
     private LocalDateTime getOriginalTime(CreatSubscriptionDTO subscriptionInfo, LocalDateTime now) {
         // 通过用户id和产品id获取最新订阅信息
-        SubscriptionsVO newestSubscriptions = getSubscriptions(subscriptionInfo.getUserId(), subscriptionInfo.getProductId());
+        SubscriptionsVO newestSubscriptions = getSubscriptions(subscriptionInfo.getUserId(), subscriptionInfo.getAppId());
         LocalDateTime originalTime;
         // 没有订阅数据
         if (ObjectUtils.isEmpty(newestSubscriptions)) {

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

@@ -5,31 +5,41 @@
 
     <!-- 可根据自己的需求,是否要使用 -->
     <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" />
-        <result property="price" column="price" />
-        <result property="buyerType" column="buyer_type" />
-        <result property="cdkey" column="cdkey" />
-        <result property="email" column="email" />
-        <result property="phone" column="phone" />
-        <result property="contactName" column="contact_name" />
-        <result property="companyName" column="company_name" />
-        <result property="startDate" column="start_date" />
-        <result property="endDate" column="end_date" />
-        <result property="maxDeviceAmount" column="max_device_amount" />
-        <result property="cnyPrice" column="cny_price" />
-        <result property="couponId" column="coupon_id" />
-        <result property="cdkeyType" column="cdkey_type" />
-        <result property="upgradeCdkey" column="upgrade_cdkey" />
-        <result property="forReason" column="for_reason" />
-        <result property="lastSubId" column="last_sub_id" />
-        <result property="payment" column="payment" />
-        <result property="originalPrice" column="original_price" />
-        <result property="cnyOriginalPrice" column="cny_original_price" />
-        <result property="isVpp" column="is_vpp" />
-        <result property="vppMemberId" column="vpp_member_id" />
-        <result property="companyId" column="company_id" />
+        <result property="id" column="id"/>
+        <result property="productId" column="product_id"/>
+        <result property="status" column="status"/>
+        <result property="price" column="price"/>
+        <result property="buyerType" column="buyer_type"/>
+        <result property="cdkey" column="cdkey"/>
+        <result property="email" column="email"/>
+        <result property="phone" column="phone"/>
+        <result property="contactName" column="contact_name"/>
+        <result property="companyName" column="company_name"/>
+        <result property="startDate" column="start_date"/>
+        <result property="endDate" column="end_date"/>
+        <result property="maxDeviceAmount" column="max_device_amount"/>
+        <result property="cnyPrice" column="cny_price"/>
+        <result property="couponId" column="coupon_id"/>
+        <result property="cdkeyType" column="cdkey_type"/>
+        <result property="upgradeCdkey" column="upgrade_cdkey"/>
+        <result property="forReason" column="for_reason"/>
+        <result property="lastSubId" column="last_sub_id"/>
+        <result property="payment" column="payment"/>
+        <result property="originalPrice" column="original_price"/>
+        <result property="cnyOriginalPrice" column="cny_original_price"/>
+        <result property="isVpp" column="is_vpp"/>
+        <result property="vppMemberId" column="vpp_member_id"/>
+        <result property="companyId" column="company_id"/>
     </resultMap>
 
+    <select id="selectNewestSubscription" resultType="cn.kdan.cloud.pdf.office.api.payment.vo.SubscriptionsVO">
+        SELECT s.id,s.product_id,s.status,s.price,s.buyer_type,s.cdkey,s.email,s.phone,s.contact_name,s.company_name,s.start_date,s.end_date,s.max_device_amount,s.cny_price,s.coupon_id,s.cdkey_type,s.upgrade_cdkey,s.for_reason,s.last_sub_id,s.payment,s.original_price,s.cny_original_price,s.is_vpp,s.vpp_member_id,s.company_id,s.user_id,s.subscription_type,s.third_subscription_id,s.order_id,s.appId
+        FROM subscription s
+        where s.app_id = #{appId}
+          and s.user_id = #{userId}
+          AND s.`status` = 3
+        ORDER BY s.end_date desc
+        LIMIT 1
+    </select>
+
 </mapper>