From 29715bda7859579d4c60f4a782dba68936f147b2 Mon Sep 17 00:00:00 2001
From: Jerry Yan <792602257@qq.com>
Date: Tue, 21 Jan 2025 14:48:58 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../java/com/ycwl/basic/biz/OrderBiz.java     | 87 ++++++++++++++++++-
 .../java/com/ycwl/basic/biz/TemplateBiz.java  |  8 +-
 .../controller/mobile/AppTaskController.java  |  1 -
 .../basic/controller/wvp/WvpController.java   |  7 +-
 .../operator/WvpPassiveStorageOperator.java   |  2 +-
 .../com/ycwl/basic/mapper/OrderMapper.java    |  6 ++
 .../basic/repository/OrderRepository.java     | 73 ++++++++++++++--
 .../basic/repository/SourceRepository.java    | 55 ++++++++++++
 .../basic/repository/VideoRepository.java     | 27 ++++++
 .../service/impl/mobile/WxPayServiceImpl.java | 73 +++++-----------
 .../service/impl/pc/OrderServiceImpl.java     | 36 --------
 .../basic/service/mobile/WxPayService.java    |  1 -
 .../task/impl/TaskTaskServiceImpl.java        | 34 +++++---
 .../com/ycwl/basic/utils/JwtTokenUtil.java    |  7 ++
 src/main/resources/mapper/OrderMapper.xml     | 33 +++++++
 src/main/resources/mapper/SourceMapper.xml    |  2 +-
 16 files changed, 336 insertions(+), 116 deletions(-)
 create mode 100644 src/main/java/com/ycwl/basic/repository/SourceRepository.java

diff --git a/src/main/java/com/ycwl/basic/biz/OrderBiz.java b/src/main/java/com/ycwl/basic/biz/OrderBiz.java
index 6f1164f..c8c82c9 100644
--- a/src/main/java/com/ycwl/basic/biz/OrderBiz.java
+++ b/src/main/java/com/ycwl/basic/biz/OrderBiz.java
@@ -1,11 +1,12 @@
 package com.ycwl.basic.biz;
 
-import com.ycwl.basic.mapper.FaceMapper;
 import com.ycwl.basic.mapper.VideoMapper;
 import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
 import com.ycwl.basic.model.mobile.order.PriceObj;
 import com.ycwl.basic.model.pc.face.entity.FaceEntity;
-import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
+import com.ycwl.basic.model.pc.order.entity.OrderEntity;
+import com.ycwl.basic.model.pc.order.entity.OrderItemEntity;
+import com.ycwl.basic.model.pc.order.req.OrderUpdateReq;
 import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
 import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
 import com.ycwl.basic.model.pc.template.resp.TemplateRespVO;
@@ -13,11 +14,15 @@ import com.ycwl.basic.model.pc.video.resp.VideoRespVO;
 import com.ycwl.basic.repository.FaceRepository;
 import com.ycwl.basic.repository.OrderRepository;
 import com.ycwl.basic.repository.ScenicRepository;
+import com.ycwl.basic.repository.SourceRepository;
 import com.ycwl.basic.repository.TemplateRepository;
+import com.ycwl.basic.repository.VideoRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
 
 @Component
 public class OrderBiz {
@@ -32,6 +37,10 @@ public class OrderBiz {
     private OrderRepository orderRepository;
     @Autowired
     private FaceRepository faceRepository;
+    @Autowired
+    private SourceRepository sourceRepository;
+    @Autowired
+    private VideoRepository videoRepository;
 
     public PriceObj queryPrice(Long scenicId, int goodsType, Long goodsId) {
         PriceObj priceObj = new PriceObj();
@@ -99,6 +108,19 @@ public class OrderBiz {
     public IsBuyRespVO isBuy(Long userId, Long scenicId, int goodsType, Long goodsId) {
         IsBuyRespVO respVO = new IsBuyRespVO();
         boolean isBuy = orderRepository.checkUserBuyItem(userId, goodsType, goodsId);
+        // 免费送逻辑,之前已经赠送了的
+        if (!isBuy) {
+            switch (goodsType) {
+                case 0:
+                    isBuy = videoRepository.getUserIsBuy(userId, goodsId);
+                    break;
+                case 1:
+                case 2:
+                    isBuy = sourceRepository.getUserIsBuy(userId, goodsType, goodsId);
+                    break;
+            }
+        }
+        // 还是没买
         respVO.setBuy(isBuy);
         if (!isBuy) {
             PriceObj priceObj = queryPrice(scenicId, goodsType, goodsId);
@@ -113,4 +135,65 @@ public class OrderBiz {
         }
         return respVO;
     }
+
+    public void paidOrder(Long orderId) {
+        orderRepository.clearOrderCache(orderId); // 检查支付呢,还缓存
+        OrderEntity order = orderRepository.getOrder(orderId);
+        List<OrderItemEntity> orderItems = orderRepository.getOrderItems(orderId);
+        OrderEntity orderUpdate = new OrderEntity();
+        orderUpdate.setPayAt(new Date());
+        orderUpdate.setStatus(1);
+        orderRepository.updateOrder(orderId, orderUpdate);
+        orderItems.forEach(item -> {
+            switch (item.getGoodsType()) {
+                case 0: // vlog视频
+                    videoRepository.setUserIsBuyItem(order.getMemberId(), item.getGoodsId(), order.getId());
+                case 1: // 视频原素材
+                case 2: // 照片原素材
+                    sourceRepository.setUserIsBuyItem(order.getMemberId(), item.getGoodsType(), item.getGoodsId(), order.getId());
+            }
+        });
+        orderRepository.clearOrderCache(orderId); // 更新完了,清理下
+    }
+
+    public void cancelOrder(Long orderId) {
+        orderRepository.clearOrderCache(orderId); // 检查支付呢,还缓存
+        OrderEntity order = orderRepository.getOrder(orderId);
+        List<OrderItemEntity> orderItems = orderRepository.getOrderItems(orderId);
+        OrderEntity orderUpdate = new OrderEntity();
+        orderUpdate.setCancelAt(new Date());
+        orderUpdate.setStatus(9);
+        orderRepository.updateOrder(orderId, orderUpdate);
+        orderItems.forEach(item -> {
+            switch (item.getGoodsType()) {
+                case 0: // vlog视频
+                    videoRepository.setUserNotBuyItem(order.getMemberId(), item.getGoodsId());
+                case 1: // 视频原素材
+                case 2: // 照片原素材
+                    sourceRepository.setUserNotBuyItem(order.getMemberId(), item.getGoodsType(), item.getGoodsId());
+            }
+        });
+        orderRepository.clearOrderCache(orderId); // 更新完了,清理下
+    }
+
+    public void refundOrder(Long orderId) {
+        orderRepository.clearOrderCache(orderId);
+        OrderEntity order = orderRepository.getOrder(orderId);
+        List<OrderItemEntity> orderItems = orderRepository.getOrderItems(orderId);
+        OrderEntity orderUpdate = new OrderEntity();
+        orderUpdate.setRefundAt(new Date());
+        orderUpdate.setStatus(2);
+        orderUpdate.setRefundStatus(1);
+        orderRepository.updateOrder(orderId, orderUpdate);
+        orderItems.forEach(item -> {
+            switch (item.getGoodsType()) {
+                case 0: // vlog视频
+                    videoRepository.setUserNotBuyItem(order.getMemberId(), item.getGoodsId());
+                case 1: // 视频原素材
+                case 2: // 照片原素材
+                    sourceRepository.setUserNotBuyItem(order.getMemberId(), item.getGoodsType(), item.getGoodsId());
+            }
+        });
+        orderRepository.clearOrderCache(orderId); // 更新完了,清理下
+    }
 }
diff --git a/src/main/java/com/ycwl/basic/biz/TemplateBiz.java b/src/main/java/com/ycwl/basic/biz/TemplateBiz.java
index 62a97df..277294e 100644
--- a/src/main/java/com/ycwl/basic/biz/TemplateBiz.java
+++ b/src/main/java/com/ycwl/basic/biz/TemplateBiz.java
@@ -1,12 +1,14 @@
 package com.ycwl.basic.biz;
 
 import com.ycwl.basic.mapper.SourceMapper;
+import com.ycwl.basic.model.pc.face.entity.FaceEntity;
 import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
 import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
 import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
 import com.ycwl.basic.model.pc.source.entity.SourceEntity;
 import com.ycwl.basic.model.pc.template.entity.TemplateConfigEntity;
 import com.ycwl.basic.repository.FaceRepository;
+import com.ycwl.basic.repository.SourceRepository;
 import com.ycwl.basic.repository.TemplateRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -24,6 +26,8 @@ public class TemplateBiz {
     private FaceRepository faceRepository;
     @Autowired
     private SourceMapper sourceMapper;
+    @Autowired
+    private SourceRepository sourceRepository;
 
 
     public boolean determineTemplateCanGenerate(Long templateId, Long faceId) {
@@ -38,12 +42,12 @@ public class TemplateBiz {
         if (minimalPlaceholderFill <= 0) {
             return true;
         }
+        FaceEntity face = faceRepository.getFace(faceId);
         List<FaceSampleEntity> faceSampleList = faceRepository.getFaceSampleList(faceId);
         if (faceSampleList.isEmpty()) {
             return false;
         }
-        // todo fix me
-        List<SourceEntity> sourceEntities = sourceMapper.listVideoBySampleIds(faceSampleList.stream().map(FaceSampleEntity::getId).collect(Collectors.toList()));
+        List<SourceEntity> sourceEntities = sourceMapper.listVideoByScenicFaceRelation(face.getScenicId(), faceId);
         long count = sourceEntities.stream().map(SourceEntity::getDeviceId).filter(deviceId -> placeholderList.contains(deviceId.toString())).count();
         return count >= minimalPlaceholderFill;
     }
diff --git a/src/main/java/com/ycwl/basic/controller/mobile/AppTaskController.java b/src/main/java/com/ycwl/basic/controller/mobile/AppTaskController.java
index 9d1c255..31085eb 100644
--- a/src/main/java/com/ycwl/basic/controller/mobile/AppTaskController.java
+++ b/src/main/java/com/ycwl/basic/controller/mobile/AppTaskController.java
@@ -54,7 +54,6 @@ public class AppTaskController {
 
     @PostMapping("/submit")
     public ApiResponse<String> submitVideoTask(@RequestBody VideoTaskReq videoTaskReq) {
-        JwtInfo worker = JwtTokenUtil.getWorker();
         taskService.createTaskByFaceIdAndTempalteId(videoTaskReq.getFaceId(),videoTaskReq.getTemplateId(),0);
         return ApiResponse.success("成功");
     }
diff --git a/src/main/java/com/ycwl/basic/controller/wvp/WvpController.java b/src/main/java/com/ycwl/basic/controller/wvp/WvpController.java
index fc4e313..354e41c 100644
--- a/src/main/java/com/ycwl/basic/controller/wvp/WvpController.java
+++ b/src/main/java/com/ycwl/basic/controller/wvp/WvpController.java
@@ -11,6 +11,7 @@ import com.ycwl.basic.storage.adapters.IStorageAdapter;
 import com.ycwl.basic.utils.ApiResponse;
 import io.swagger.annotations.Api;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -47,11 +48,13 @@ public class WvpController {
     @PostMapping("/scenic/{scenicId}/{taskId}/success")
     public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
         IStorageAdapter adapter = StorageFactory.use("assets-ext");
-        fileObject.setUrl(adapter.getUrl(WvpPassiveStorageOperator.getUrlForTask(taskId)));
+        if (StringUtils.isBlank(fileObject.getUrl())) {
+            fileObject.setUrl(adapter.getUrl(WvpPassiveStorageOperator.getUrlForTask(taskId)));
+        }
         WvpPassiveStorageOperator.onReceiveResult(taskId, fileObject);
         return ApiResponse.success("success");
     }
-    @PostMapping("/scenic/{scenicId}/{taskId}/fail")
+    @PostMapping("/scenic/{scenicId}/{taskId}/failure")
     public ApiResponse<String> fail(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
         WvpPassiveStorageOperator.onReceiveResult(taskId, null);
         return ApiResponse.success("success");
diff --git a/src/main/java/com/ycwl/basic/device/operator/WvpPassiveStorageOperator.java b/src/main/java/com/ycwl/basic/device/operator/WvpPassiveStorageOperator.java
index 8be6995..7fc2d76 100644
--- a/src/main/java/com/ycwl/basic/device/operator/WvpPassiveStorageOperator.java
+++ b/src/main/java/com/ycwl/basic/device/operator/WvpPassiveStorageOperator.java
@@ -78,7 +78,7 @@ public class WvpPassiveStorageOperator extends ADeviceStorageOperator {
         taskList.add(task);
         Date taskStartTime = new Date();
         while (true) {
-            if (new Date().getTime() - taskStartTime.getTime() > 120000L) {
+            if (new Date().getTime() - taskStartTime.getTime() > 80000L) {
                 log.info("任务{}获取视频超时!", task.taskId);
                 return Collections.emptyList();
             }
diff --git a/src/main/java/com/ycwl/basic/mapper/OrderMapper.java b/src/main/java/com/ycwl/basic/mapper/OrderMapper.java
index 5330e4c..53a5ba0 100644
--- a/src/main/java/com/ycwl/basic/mapper/OrderMapper.java
+++ b/src/main/java/com/ycwl/basic/mapper/OrderMapper.java
@@ -43,4 +43,10 @@ public interface OrderMapper {
     List<OrderItemEntity> listOrderItemByOrderId(Long orderId);
 
     OrderEntity getUserBuyItem(Long userId, int goodsType, Long goodsId);
+
+    OrderEntity get(Long orderId);
+
+    OrderItemEntity getOrderItem(Long orderItemId);
+
+    int updateOrder(OrderEntity updateEntity);
 }
diff --git a/src/main/java/com/ycwl/basic/repository/OrderRepository.java b/src/main/java/com/ycwl/basic/repository/OrderRepository.java
index 83dc675..e8fd92d 100644
--- a/src/main/java/com/ycwl/basic/repository/OrderRepository.java
+++ b/src/main/java/com/ycwl/basic/repository/OrderRepository.java
@@ -1,12 +1,17 @@
 package com.ycwl.basic.repository;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.ycwl.basic.mapper.OrderMapper;
 import com.ycwl.basic.model.pc.order.entity.OrderEntity;
+import com.ycwl.basic.model.pc.order.entity.OrderItemEntity;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
+import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 @Component
 public class OrderRepository {
@@ -15,19 +20,59 @@ public class OrderRepository {
     @Autowired
     private RedisTemplate<String, String> redisTemplate;
 
-    public static final String ORDER_ITEM_CACHE_KEY = "order:user:%s:type:%s:id:%s";
+    public static final String ORDER_CACHE_KEY = "order:%s";
+    public static final String ORDER_ITEMS_CACHE_KEY = "order:%s:items";
+    public static final String ORDER_ITEM_CACHE_KEY = "order:item:%s";
+    public static final String ORDER_USER_TYPE_BUY_ITEM_CACHE_KEY = "order:user:%s:type:%s:id:%s";
+
+    public OrderEntity getOrder(Long orderId) {
+        if (redisTemplate.hasKey(String.format(ORDER_CACHE_KEY, orderId))) {
+            return JSON.parseObject(redisTemplate.opsForValue().get(String.format(ORDER_CACHE_KEY, orderId)), OrderEntity.class);
+        }
+        OrderEntity orderEntity = orderMapper.get(orderId);
+        if (orderEntity != null) {
+            redisTemplate.opsForValue().set(String.format(ORDER_CACHE_KEY, orderId), JSON.toJSONString(orderEntity), 60, TimeUnit.SECONDS);
+        }
+        return orderEntity;
+    }
+
+    public List<OrderItemEntity> getOrderItems(Long orderId) {
+        if (redisTemplate.hasKey(String.format(ORDER_ITEMS_CACHE_KEY, orderId))) {
+            return JSON.parseArray(redisTemplate.opsForValue().get(String.format(ORDER_ITEMS_CACHE_KEY, orderId)), Long.class)
+                    .stream().map(this::getOrderItemByOrderItemId).collect(Collectors.toList());
+        }
+        List<OrderItemEntity> orderItemEntities = orderMapper.listOrderItemByOrderId(orderId);
+        if (orderItemEntities != null) {
+            redisTemplate.opsForValue().set(
+                    String.format(ORDER_ITEMS_CACHE_KEY, orderId),
+                    JSONArray.toJSONString(orderItemEntities.stream().map(OrderItemEntity::getId).collect(Collectors.toList()))
+            );
+        }
+        return orderItemEntities;
+    }
+
+    public OrderItemEntity getOrderItemByOrderItemId(Long orderItemId) {
+        if (redisTemplate.hasKey(String.format(ORDER_ITEM_CACHE_KEY, orderItemId))) {
+            return JSON.parseObject(redisTemplate.opsForValue().get(String.format(ORDER_ITEM_CACHE_KEY, orderItemId)), OrderItemEntity.class);
+        }
+        OrderItemEntity orderItemEntity = orderMapper.getOrderItem(orderItemId);
+        if (orderItemEntity != null) {
+            redisTemplate.opsForValue().set(String.format(ORDER_ITEM_CACHE_KEY, orderItemId), JSON.toJSONString(orderItemEntity));
+        }
+        return orderItemEntity;
+    }
 
     public boolean checkUserBuyItem(Long userId, int goodsType, Long goodsId) {
         synchronized (this) {
-            if (redisTemplate.hasKey(String.format(ORDER_ITEM_CACHE_KEY, userId, goodsType, goodsId))) {
-                return "1".equals(redisTemplate.opsForValue().get(String.format(ORDER_ITEM_CACHE_KEY, userId, goodsType, goodsId)));
+            if (redisTemplate.hasKey(String.format(ORDER_USER_TYPE_BUY_ITEM_CACHE_KEY, userId, goodsType, goodsId))) {
+                return "1".equals(redisTemplate.opsForValue().get(String.format(ORDER_USER_TYPE_BUY_ITEM_CACHE_KEY, userId, goodsType, goodsId)));
             }
             OrderEntity orderEntity = orderMapper.getUserBuyItem(userId, goodsType, goodsId);
             if (orderEntity == null) {
-                redisTemplate.opsForValue().set(String.format(ORDER_ITEM_CACHE_KEY, userId, goodsType, goodsId), "0", 60, TimeUnit.SECONDS);
+                redisTemplate.opsForValue().set(String.format(ORDER_USER_TYPE_BUY_ITEM_CACHE_KEY, userId, goodsType, goodsId), "0", 60, TimeUnit.SECONDS);
                 return false;
             }
-            redisTemplate.opsForValue().set(String.format(ORDER_ITEM_CACHE_KEY, userId, goodsType, goodsId), "1");
+            redisTemplate.opsForValue().set(String.format(ORDER_USER_TYPE_BUY_ITEM_CACHE_KEY, userId, goodsType, goodsId), "1");
             return true;
         }
     }
@@ -45,6 +90,22 @@ public class OrderRepository {
     }
 
     public void clearUserBuyItemCache(Long userId, int goodsType, Long goodsId) {
-        redisTemplate.delete(String.format(ORDER_ITEM_CACHE_KEY, userId, goodsType, goodsId));
+        redisTemplate.delete(String.format(ORDER_USER_TYPE_BUY_ITEM_CACHE_KEY, userId, goodsType, goodsId));
+    }
+
+    public void clearOrderCache(Long orderId) {
+        OrderEntity order = getOrder(orderId);
+        redisTemplate.delete(String.format(ORDER_CACHE_KEY, orderId));
+        getOrderItems(orderId).forEach(orderItem -> {
+            redisTemplate.delete(String.format(ORDER_ITEM_CACHE_KEY, orderItem.getId()));
+            clearUserBuyItemCache(order.getMemberId(), orderItem.getGoodsType(), orderItem.getGoodsId());
+        });
+        redisTemplate.delete(String.format(ORDER_ITEMS_CACHE_KEY, orderId));
+    }
+
+    public void updateOrder(Long orderId, OrderEntity updateEntity) {
+        updateEntity.setId(orderId);
+        orderMapper.updateOrder(updateEntity);
+        clearOrderCache(orderId);
     }
 }
diff --git a/src/main/java/com/ycwl/basic/repository/SourceRepository.java b/src/main/java/com/ycwl/basic/repository/SourceRepository.java
new file mode 100644
index 0000000..477aed3
--- /dev/null
+++ b/src/main/java/com/ycwl/basic/repository/SourceRepository.java
@@ -0,0 +1,55 @@
+package com.ycwl.basic.repository;
+
+import com.ycwl.basic.mapper.SourceMapper;
+import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
+import com.ycwl.basic.model.pc.source.entity.SourceEntity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+public class SourceRepository {
+    @Autowired
+    private SourceMapper sourceMapper;
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
+
+    public void addSource(SourceEntity source) {
+        sourceMapper.add(source);
+    }
+
+    public void setUserIsBuyItem(Long memberId, int type, Long faceId, Long orderId) {
+        MemberSourceEntity memberSource = new MemberSourceEntity();
+        memberSource.setMemberId(memberId);
+        memberSource.setFaceId(faceId);
+        memberSource.setType(type);
+        memberSource.setOrderId(orderId);
+        memberSource.setIsBuy(1);
+        sourceMapper.updateRelation(memberSource);
+    }
+
+    public void setUserNotBuyItem(Long memberId, int type, Long faceId) {
+        MemberSourceEntity memberSource = new MemberSourceEntity();
+        memberSource.setMemberId(memberId);
+        memberSource.setFaceId(faceId);
+        memberSource.setType(type);
+        memberSource.setOrderId(null);
+        memberSource.setIsBuy(0);
+        sourceMapper.updateRelation(memberSource);
+    }
+
+    public boolean getUserIsBuy(Long userId, int type, Long faceId) {
+        switch (type) {
+            case 1:
+                List<SourceEntity> videoSourceList = sourceMapper.listVideoByFaceRelation(userId, faceId);
+                return videoSourceList.stream().anyMatch(item -> Integer.valueOf(1).equals(item.getIsBuy()));
+            case 2:
+                List<SourceEntity> imageSourceList = sourceMapper.listImageByFaceRelation(userId, faceId);
+                return imageSourceList.stream().anyMatch(item -> Integer.valueOf(1).equals(item.getIsBuy()));
+            default:
+                return false;
+        }
+    }
+}
diff --git a/src/main/java/com/ycwl/basic/repository/VideoRepository.java b/src/main/java/com/ycwl/basic/repository/VideoRepository.java
index 3da72b9..de4e09c 100644
--- a/src/main/java/com/ycwl/basic/repository/VideoRepository.java
+++ b/src/main/java/com/ycwl/basic/repository/VideoRepository.java
@@ -1,6 +1,7 @@
 package com.ycwl.basic.repository;
 
 import com.ycwl.basic.mapper.VideoMapper;
+import com.ycwl.basic.model.pc.video.entity.MemberVideoEntity;
 import com.ycwl.basic.model.pc.video.entity.VideoEntity;
 import com.ycwl.basic.model.pc.video.resp.VideoRespVO;
 import com.ycwl.basic.model.task.req.VideoInfoReq;
@@ -31,4 +32,30 @@ public class VideoRepository {
         update.setDuration(req.getDuration());
         videoMapper.updateMeta(update);
     }
+
+    public void setUserIsBuyItem(Long memberId, Long videoId, Long orderId) {
+        MemberVideoEntity memberVideo = new MemberVideoEntity();
+        memberVideo.setVideoId(videoId);
+        memberVideo.setMemberId(memberId);
+        memberVideo.setIsBuy(1);
+        memberVideo.setOrderId(orderId);
+        videoMapper.updateRelation(memberVideo);
+    }
+
+    public void setUserNotBuyItem(Long memberId, Long videoId) {
+        MemberVideoEntity memberVideo = new MemberVideoEntity();
+        memberVideo.setVideoId(videoId);
+        memberVideo.setMemberId(memberId);
+        memberVideo.setIsBuy(0);
+        memberVideo.setOrderId(null);
+        videoMapper.updateRelation(memberVideo);
+    }
+
+    public boolean getUserIsBuy(Long userId, Long videoId) {
+        MemberVideoEntity memberVideo = videoMapper.queryUserVideo(userId, videoId);
+        if (memberVideo == null) {
+            return false;
+        }
+        return Integer.valueOf(1).equals(memberVideo.getIsBuy());
+    }
 }
diff --git a/src/main/java/com/ycwl/basic/service/impl/mobile/WxPayServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/mobile/WxPayServiceImpl.java
index 5e40611..afb6f64 100644
--- a/src/main/java/com/ycwl/basic/service/impl/mobile/WxPayServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/impl/mobile/WxPayServiceImpl.java
@@ -18,6 +18,7 @@ import com.wechat.pay.java.service.refund.RefundService;
 import com.wechat.pay.java.service.refund.model.AmountReq;
 import com.wechat.pay.java.service.refund.model.CreateRequest;
 import com.wechat.pay.java.service.refund.model.Refund;
+import com.ycwl.basic.biz.OrderBiz;
 import com.ycwl.basic.config.WechatConfig;
 import com.ycwl.basic.constant.HttpConstant;
 import com.ycwl.basic.constant.NumberConstant;
@@ -32,6 +33,7 @@ import com.ycwl.basic.mapper.SourceMapper;
 import com.ycwl.basic.mapper.StatisticsMapper;
 import com.ycwl.basic.mapper.VideoMapper;
 import com.ycwl.basic.model.mobile.statistic.req.StatisticsRecordAddReq;
+import com.ycwl.basic.model.pc.order.entity.OrderEntity;
 import com.ycwl.basic.model.pc.order.entity.OrderItemEntity;
 import com.ycwl.basic.model.pc.order.resp.OrderRespVO;
 import com.ycwl.basic.model.pc.payment.entity.PaymentEntity;
@@ -101,6 +103,8 @@ public class WxPayServiceImpl implements WxPayService {
     private VideoMapper videoMapper;
     @Autowired
     private OrderRepository orderRepository;
+    @Autowired
+    private OrderBiz orderBiz;
 
     @Override
     public WxPayRespVO createOrder(WXPayOrderReqVO req) {
@@ -198,14 +202,19 @@ public class WxPayServiceImpl implements WxPayService {
 
             // 更新订单信息
             new Thread(() -> {
-                Transaction.TradeStateEnum tradeState = parse.getTradeState();
-                OrderStateEnum OrderStateEnum = null;
-                if (Transaction.TradeStateEnum.SUCCESS == tradeState) {
-                    OrderStateEnum = OrderStateEnum.PAID;
-                }
-                if (Objects.nonNull(OrderStateEnum)) {
-                    long orderId = Long.parseLong(parse.getOutTradeNo());
-                    notifyOrderSuccess(orderId);
+                long orderId = Long.parseLong(parse.getOutTradeNo());
+                switch (parse.getTradeState()) {
+                    case SUCCESS:
+                        orderBiz.paidOrder(orderId);
+                        break;
+                    case NOTPAY:
+                    case CLOSED:
+                    case REVOKED:
+                        orderBiz.cancelOrder(orderId);
+                        break;
+                    case REFUND:
+                        orderBiz.refundOrder(orderId);
+                        break;
                 }
             }).start();
         } catch (Exception e) {
@@ -213,45 +222,6 @@ public class WxPayServiceImpl implements WxPayService {
         }
     }
 
-    @Override
-    public void notifyOrderSuccess(Long orderId) {
-        try {
-            orderService.updateOrderState(orderId, OrderStateEnum.PAID, null);
-            // 添加统计数据
-            statisticsHandler(orderId);
-        }catch (Exception e) {
-            log.error("[微信支付回调]更新订单状态失败", e);
-        }
-        OrderRespVO byId = orderMapper.getById(orderId);
-        List<OrderItemEntity> orderItemList = orderMapper.listOrderItemByOrderId(orderId);
-        orderItemList.forEach(orderItemVO -> {
-            orderRepository.clearUserBuyItemCache(byId.getMemberId(), orderItemVO.getGoodsType(), orderItemVO.getGoodsId());
-            switch (orderItemVO.getGoodsType()) {
-                case 0: // 成片
-                    MemberVideoEntity memberVideoEntity = new MemberVideoEntity();
-                    memberVideoEntity.setMemberId(byId.getMemberId());
-                    memberVideoEntity.setVideoId(orderItemVO.getGoodsId());
-                    memberVideoEntity.setIsBuy(1);
-                    memberVideoEntity.setOrderId(orderId);
-                    videoMapper.updateRelation(memberVideoEntity);
-                    break;
-                case 1: // 源视频
-                case 2: // 源素材
-                    MemberSourceEntity memberSourceEntity = new MemberSourceEntity();
-                    memberSourceEntity.setMemberId(byId.getMemberId());
-                    // 源素材的goodsId是人脸ID
-                    memberSourceEntity.setFaceId(orderItemVO.getGoodsId());
-                    memberSourceEntity.setType(orderItemVO.getGoodsType());
-                    memberSourceEntity.setIsBuy(1);
-                    memberSourceEntity.setOrderId(orderId);
-                    sourceMapper.updateRelation(memberSourceEntity);
-                    break;
-                default:
-                    break;
-            }
-        });
-    }
-
     //
     private void statisticsHandler(Long orderId) {
         ApiResponse<OrderRespVO> orderDetail = orderService.detail(orderId);
@@ -362,14 +332,13 @@ public class WxPayServiceImpl implements WxPayService {
 
         if (!StringUtils.isEmpty(refund_status) && WECHATPAY_SUCCESS.equals(refund_status)) {
             long orderId = Long.parseLong(out_trade_no);
-            orderService.updateOrderState(orderId, OrderStateEnum.REFUNDED, null);
+            orderBiz.refundOrder(orderId);
 
-            ApiResponse<OrderRespVO> detail = orderService.detail(orderId);
-            OrderRespVO orderData = detail.getData();
+            OrderEntity order = orderRepository.getOrder(orderId);
             StatisticsRecordAddReq statisticsRecordAddReq = new StatisticsRecordAddReq();
-            statisticsRecordAddReq.setMemberId(orderData.getMemberId());
+            statisticsRecordAddReq.setMemberId(order.getMemberId());
             statisticsRecordAddReq.setType(StatisticEnum.REFUND.code);
-            statisticsRecordAddReq.setScenicId(orderData.getScenicId());
+            statisticsRecordAddReq.setScenicId(order.getScenicId());
             statisticsRecordAddReq.setMorphId(orderId);
             statisticsMapper.addStatisticsRecord(statisticsRecordAddReq);
 
diff --git a/src/main/java/com/ycwl/basic/service/impl/pc/OrderServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/pc/OrderServiceImpl.java
index a1a9396..3ad639d 100644
--- a/src/main/java/com/ycwl/basic/service/impl/pc/OrderServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/impl/pc/OrderServiceImpl.java
@@ -189,48 +189,12 @@ public class OrderServiceImpl implements OrderService {
             if (state == OrderStateEnum.CANCELED.getState()) {//取消支付
                 orderUpdateReq.setCancelAt(new Date());
 
-                //如果订单未支付就把商品状态更改成未购买
-                OrderRespVO orderRespVO = orderMapper.getById(orderSn);
-                Integer goodsType = orderRespVO.getGoodsType();
-                List<OrderItemVO> orderItemList = orderRespVO.getOrderItemList();
-                orderItemList.forEach(orderItemVO -> {
-                    Long goodsId = orderItemVO.getGoodsId();
-                    if (Objects.equals(goodsType, GoodsTypeEnum.VIDEO.code)) {
-                        VideoEntity videoEntity = new VideoEntity();
-                        videoEntity.setId(goodsId);
-                        videoEntity.setIsBuy(0);
-                        videoMapper.update(videoEntity);
-                    } else if (Objects.equals(goodsType, GoodsTypeEnum.SOURCE.code)) {
-                        SourceEntity sourceEntity = new SourceEntity();
-                        sourceEntity.setId(goodsId);
-                        sourceEntity.setIsBuy(0);
-                        sourceMapper.update(sourceEntity);
-                    }
-                });
             } else if (state== OrderStateEnum.PAID.getState()) {//支付成功
                 orderUpdateReq.setPayAt(new Date());
 
             }else if (state == OrderStateEnum.REFUNDED.getState()) {//退款成功
                 orderUpdateReq.setRefundAt(new Date());
 
-                //订单退款成功就把商品状态更改成未购买
-                OrderRespVO orderRespVO = orderMapper.getById(orderSn);
-                Integer goodsType = orderRespVO.getGoodsType();
-                List<OrderItemVO> orderItemList = orderRespVO.getOrderItemList();
-                orderItemList.forEach(orderItemVO -> {
-                    Long goodsId = orderItemVO.getGoodsId();
-                    if (Objects.equals(goodsType, GoodsTypeEnum.VIDEO.code)) {
-                        VideoEntity videoEntity = new VideoEntity();
-                        videoEntity.setId(goodsId);
-                        videoEntity.setIsBuy(0);
-                        videoMapper.update(videoEntity);
-                    } else if (Objects.equals(goodsType, GoodsTypeEnum.SOURCE.code)) {
-                        SourceEntity sourceEntity = new SourceEntity();
-                        sourceEntity.setId(goodsId);
-                        sourceEntity.setIsBuy(0);
-                        sourceMapper.update(sourceEntity);
-                    }
-                });
             }
         }
         orderMapper.update(orderUpdateReq);
diff --git a/src/main/java/com/ycwl/basic/service/mobile/WxPayService.java b/src/main/java/com/ycwl/basic/service/mobile/WxPayService.java
index 56ca11a..2a58862 100644
--- a/src/main/java/com/ycwl/basic/service/mobile/WxPayService.java
+++ b/src/main/java/com/ycwl/basic/service/mobile/WxPayService.java
@@ -20,7 +20,6 @@ public interface WxPayService {
      */
     void payNotify(HttpServletRequest xml);
 
-    void notifyOrderSuccess(Long orderId);
 
     /**
      * 微信支付结果查询
diff --git a/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java b/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java
index 7cbcf1c..b0d77d7 100644
--- a/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java
+++ b/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java
@@ -263,20 +263,22 @@ public class TaskTaskServiceImpl implements TaskService {
 
     @Override
     public void createTaskByFaceIdAndTempalteId(Long faceId, Long templateId, int automatic) {
-        FaceRespVO faceRespVO = faceMapper.getById(faceId);
-        if (faceRespVO == null) {
+        FaceEntity face = faceRepository.getFace(faceId);
+        if (face == null) {
+            log.info("faceId:{} is not exist", faceId);
             return;
         }
-        ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(faceRespVO.getScenicId());
         List<FaceSampleEntity> faceSampleList = faceRepository.getFaceSampleList(faceId);
         if (faceSampleList.isEmpty()) {
-            return;
+            log.info("faceId:{} sample list not exist", faceId);
         }
         List<Long> faceSampleIds = faceSampleList.stream().map(FaceSampleEntity::getId).collect(Collectors.toList());
-        List<SourceEntity> sourceList = sourceMapper.listBySampleIds(faceSampleIds);
+        List<SourceEntity> sourceList = sourceMapper.listVideoByScenicFaceRelation(face.getScenicId(), faceId);
         if (sourceList.isEmpty()) {
+            log.info("faceId:{} source list not exist", faceId);
             return;
         }
+//        ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(face.getScenicId());
 //        if (automatic > 0) {
 //            TaskReqQuery taskReqQuery = new TaskReqQuery();
 //            taskReqQuery.setFaceId(faceId);
@@ -314,7 +316,7 @@ public class TaskTaskServiceImpl implements TaskService {
         task.faceId = faceId;
         task.faceSampleIds = faceSampleIds;
         task.templateId = templateId;
-        task.memberId = faceRespVO.getMemberId();
+        task.memberId = face.getMemberId();
         task.callback = () -> {
             log.info("task callback");
             boolean canGenerate = templateBiz.determineTemplateCanGenerate(templateId, faceId);
@@ -322,7 +324,7 @@ public class TaskTaskServiceImpl implements TaskService {
                 log.info("task callback: 不能生成");
                 return;
             }
-            List<SourceEntity> videoSourceList = sourceMapper.listVideoByScenicFaceRelation(faceRespVO.getScenicId(), faceId);
+            List<SourceEntity> videoSourceList = sourceMapper.listVideoByScenicFaceRelation(face.getScenicId(), faceId);
             Map<String, List<SourceEntity>> sourcesMap = videoSourceList.stream()
                     .peek(item -> item.setUrl(item.getVideoUrl()))
                     .collect(Collectors.groupingBy(item -> item.getDeviceId().toString()));
@@ -337,8 +339,8 @@ public class TaskTaskServiceImpl implements TaskService {
             List<TaskRespVO> list = taskMapper.list(taskReqQuery);
 
             MemberVideoEntity memberVideoEntity = new MemberVideoEntity();
-            memberVideoEntity.setMemberId(faceRespVO.getMemberId());
-            memberVideoEntity.setScenicId(faceRespVO.getScenicId());
+            memberVideoEntity.setMemberId(face.getMemberId());
+            memberVideoEntity.setScenicId(face.getScenicId());
             memberVideoEntity.setFaceId(faceId);
             memberVideoEntity.setTemplateId(templateId);
             memberVideoEntity.setIsBuy(0);
@@ -346,7 +348,7 @@ public class TaskTaskServiceImpl implements TaskService {
                 log.info("创建任务! faceId:{},templateId:{},taskParams:{}", faceId, templateId, sourcesMap);
                 TaskEntity taskEntity = new TaskEntity();
                 taskEntity.setId(SnowFlakeUtil.getLongId());
-                taskEntity.setScenicId(faceRespVO.getScenicId());
+                taskEntity.setScenicId(face.getScenicId());
                 taskEntity.setFaceId(faceId);
                 taskEntity.setTemplateId(templateId);
                 taskEntity.setStatus(0);
@@ -366,13 +368,21 @@ public class TaskTaskServiceImpl implements TaskService {
                     memberVideoEntity.setVideoId(video.getId());
                     // 已经生成了
                     new Thread(() -> {
-                        sendVideoGeneratedServiceNotification(list.get(0).getId(), faceRespVO.getMemberId());
+                        sendVideoGeneratedServiceNotification(list.get(0).getId(), face.getMemberId());
                     }).start();
                 }
             }
             videoMapper.addRelation(memberVideoEntity);
         };
-        VideoPieceGetter.addTask(task);
+        if (faceSampleIds.isEmpty()) {
+            // 没有人脸样本
+            if (!sourceList.isEmpty()) {
+                // 但是有原片
+                task.callback.onInvoke();
+            }
+        } else {
+            VideoPieceGetter.addTask(task);
+        }
     }
 
     @Override
diff --git a/src/main/java/com/ycwl/basic/utils/JwtTokenUtil.java b/src/main/java/com/ycwl/basic/utils/JwtTokenUtil.java
index 63eb087..b644770 100644
--- a/src/main/java/com/ycwl/basic/utils/JwtTokenUtil.java
+++ b/src/main/java/com/ycwl/basic/utils/JwtTokenUtil.java
@@ -93,4 +93,11 @@ public class JwtTokenUtil {
         }
         return parsingToken(token);
     }
+
+    public static void main(String[] args) throws Exception {
+        JwtInfo jwtInfo = new JwtInfo();
+        jwtInfo.setUserId(3936121342868459520L);
+        jwtInfo.setName("微信用户");
+        System.out.println(generateToken(jwtInfo, 86400));
+    }
 }
diff --git a/src/main/resources/mapper/OrderMapper.xml b/src/main/resources/mapper/OrderMapper.xml
index 1ff0cc9..0564bc9 100644
--- a/src/main/resources/mapper/OrderMapper.xml
+++ b/src/main/resources/mapper/OrderMapper.xml
@@ -153,6 +153,33 @@
         </set>
         where id = #{id}
     </update>
+    <update id="updateOrder">
+        update `order`
+        <set>
+            <if test="remark!= null and remark!= ''">
+                remark = #{remark},
+            </if>
+            <if test="refundReason!= null and refundReason!= ''">
+                refund_reason = #{refundReason},
+            </if>
+            <if test="refundStatus!= null ">
+                refund_status = #{refundStatus},
+            </if>
+            <if test="status!= null ">
+                `status` = #{status},
+            </if>
+            <if test="refundAt!= null ">
+                refund_at = #{refundAt},
+            </if>
+            <if test="payAt!= null ">
+                pay_at = #{payAt},
+            </if>
+            <if test="cancelAt!= null ">
+                cancel_at = #{cancelAt},
+            </if>
+        </set>
+        where id = #{id}
+    </update>
     <delete id="deleteById">
         delete from `order` where id = #{id}
     </delete>
@@ -345,4 +372,10 @@
           and o.status = 1
         limit 1
     </select>
+    <select id="get" resultType="com.ycwl.basic.model.pc.order.entity.OrderEntity">
+        select * from `order` where id = #{id}
+    </select>
+    <select id="getOrderItem" resultType="com.ycwl.basic.model.pc.order.entity.OrderItemEntity">
+        select * from order_item where id = #{id}
+    </select>
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/SourceMapper.xml b/src/main/resources/mapper/SourceMapper.xml
index 7f2b91d..380468f 100644
--- a/src/main/resources/mapper/SourceMapper.xml
+++ b/src/main/resources/mapper/SourceMapper.xml
@@ -36,7 +36,7 @@
             <if test="isBuy!=null">is_buy = #{isBuy}, </if>
             <if test="orderId!=null">order_id = #{orderId}, </if>
         </set>
-        where member_id = #{memberId} and face_id = #{faceId} and type = #{type}
+        where member_id = #{memberId} and face_id = #{faceId} and `type` = #{type}
     </update>
     <delete id="deleteById">
         delete from source where id = #{id}