Przeglądaj źródła

下单后绑定gptTeam账号

zoujiajian 9 miesięcy temu
rodzic
commit
4f68ccfad7

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GptTeamUserBindRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GptTeamUserBindRecord;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * GPT Team用户绑定记录Mapper接口
+ */
+@Mapper
+public interface GptTeamUserBindRecordMapper extends BaseMapper<GptTeamUserBindRecord> {
+
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSku.java

@@ -354,4 +354,9 @@ public class GoodsDonSku extends BaseEntity {
      */
     @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String payDesc;
+
+    /**
+     * got team规格 默认false
+     */
+    private Boolean isGptTeam;
 }

+ 47 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GptTeamUserBindRecord.java

@@ -0,0 +1,47 @@
+package com.cyksj.model.entity;
+
+import com.cyksj.model.BaseEntity;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * GPT Team用户绑定记录
+ */
+@Getter
+@Setter
+public class GptTeamUserBindRecord extends BaseEntity {
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    private Long orderId;
+
+    /**
+     * GPT Team邮箱
+     */
+    private String bindEmail;
+
+    /**
+     * team token
+     */
+    private String token;
+
+    /**
+     * 换绑前的 token
+     */
+    private String bfToken;
+
+    /**
+     * 绑定时间
+     */
+    private Date bindTime;
+
+    /**
+     * 换绑次数
+     */
+    private Integer changeNum;
+}

+ 4 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuInsert.java

@@ -258,6 +258,10 @@ public class ReqGoodsSkuInsert {
          */
         private String payDesc;
 
+        /**
+         * got team规格 默认false
+         */
+        private Boolean isGptTeam;
     }
 
 }

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonView.java

@@ -74,6 +74,12 @@ public class OrderDonView {
     @DbField("sku.months")
     private Integer months;
 
+    /**
+     * 是否是got team规格
+     */
+    @DbField("sku.is_gpt_team")
+    private Boolean isGptTeam;
+
     @DbField("o.user_id")
     @JsonIgnore
     private Long userId;

+ 33 - 0
netflix-dao/src/main/java/com/cyksj/model/request/GptTeamBindRequest.java

@@ -0,0 +1,33 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotNull;
+
+/**
+ * GPT Team绑定请求
+ */
+@Getter
+@Setter
+public class GptTeamBindRequest {
+
+    /**
+     * 订单ID
+     */
+    @NotNull(message = "订单ID不能为空")
+    private Long orderId;
+
+    /**
+     * 邮箱
+     */
+    @NotNull(message = "邮箱不能为空")
+    @Email(message = "邮箱格式不正确")
+    private String email;
+
+    /**
+     * 用户ID(由系统设置)
+     */
+    private Long userId;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuFrontView.java

@@ -296,4 +296,9 @@ public class GoodsDonSkuFrontView {
 	 * 每月预算上限
 	 */
 	private Integer openaiQuota;
+
+	/**
+	 * got team规格 默认false
+	 */
+	private Boolean isGptTeam;
 }

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/views/YhShopGoodsSkuFrontView.java

@@ -262,4 +262,10 @@ public class YhShopGoodsSkuFrontView {
 	 */
 	@DbField("sku.openai_quota")
 	private Integer openaiQuota;
+
+	/**
+	 * got team规格 默认false
+	 */
+	@DbField("sku.is_gpt_team")
+	private Boolean isGptTeam;
 }

+ 5 - 0
netflix-dao/src/main/resources/mapper/GptTeamUserBindRecordMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.cyksj.mapper.GptTeamUserBindRecordMapper">
+
+</mapper>

+ 35 - 0
netflix-service/src/main/java/com/cyksj/service/gpt/GptTeamUserBindRecordService.java

@@ -0,0 +1,35 @@
+package com.cyksj.service.gpt;
+
+import com.cyksj.model.entity.GptTeamUserBindRecord;
+import com.cyksj.model.request.GptTeamBindRequest;
+
+/**
+ * GPT Team用户绑定记录服务接口
+ */
+public interface GptTeamUserBindRecordService {
+
+    /**
+     * 通过订单ID绑定邮箱
+     *
+     * @param request 绑定请求
+     * @return 绑定响应
+     */
+    void bindByOrderId(GptTeamBindRequest request);
+
+    /**
+     * 获取绑定记录
+     *
+     * @param orderId 订单ID
+     * @param userId 用户ID
+     * @return 绑定记录
+     */
+    GptTeamUserBindRecord getBindRecord(Long orderId, Long userId);
+
+    /**
+     * 换绑邮箱
+     *
+     * @param request 换绑请求
+     * @return 换绑响应
+     */
+    void changeBind(GptTeamBindRequest request);
+}

+ 143 - 0
netflix-service/src/main/java/com/cyksj/service/gpt/impl/GptTeamUserBindRecordServiceImpl.java

@@ -0,0 +1,143 @@
+package com.cyksj.service.gpt.impl;
+
+import cn.hutool.core.date.DateTime;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.mapper.GptTeamAccountMapper;
+import com.cyksj.mapper.GptTeamUserBindRecordMapper;
+import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.entity.GptTeamAccount;
+import com.cyksj.model.entity.GptTeamUserBindRecord;
+import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.request.GptTeamBindRequest;
+import com.cyksj.service.gpt.GptTeamUserBindRecordService;
+import com.cyksj.service.user.UserBindRelationService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * GPT Team用户绑定记录服务实现
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class GptTeamUserBindRecordServiceImpl implements GptTeamUserBindRecordService {
+
+    private final GptTeamUserBindRecordMapper bindRecordMapper;
+
+    private final GptTeamAccountMapper gptTeamAccountMapper;
+
+    private final OrderDonMapper orderDonMapper;
+
+    private final UserBindRelationService userBindRelationService;
+
+    private final GoodsDonSkuMapper goodsDonSkuMapper;
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public void bindByOrderId(GptTeamBindRequest request) {
+        Long orderId = request.getOrderId();
+        Long userId = request.getUserId();
+        String email = request.getEmail();
+
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        // 1. 验证订单
+        OrderDon order = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getId, orderId).in(OrderDon::getUserId, userIdList).notIn(OrderDon::getStatus, Constant.noOrderAllStatus).last("limit 1"));
+        if (order == null) {
+            throw new BusinessRuntimeException("订单不存在");
+        }
+
+        GoodsDonSku sku = goodsDonSkuMapper.selectById(order.getSkuId());
+        //校验是否是gptTeam规格
+        if (sku == null || !sku.getIsGptTeam()) {
+            throw new BusinessRuntimeException("错误订单规格");
+        }
+
+        // 2. 检查是否已经绑定
+        Integer selectCount = bindRecordMapper.selectCount(Wrappers.lambdaQuery(GptTeamUserBindRecord.class).eq(GptTeamUserBindRecord::getOrderId, orderId));
+        if (selectCount > 0) {
+            throw BusinessRuntimeException.getInstance("已有绑定的Team");
+        }
+        // 4. 创建绑定记录
+        GptTeamUserBindRecord bindRecord = new GptTeamUserBindRecord();
+        //订单用户id
+        bindRecord.setUserId(order.getUserId());
+        bindRecord.setBindTime(DateTime.now());
+        bindRecord.setBindEmail(email);
+        try {
+            bindRecordMapper.insert(bindRecord);
+        } catch (DuplicateKeyException e) {
+            throw BusinessRuntimeException.getInstance("已有绑定的Team");
+        }
+
+        // 3. 查找可用的GPT Team账号
+        LambdaQueryWrapper<GptTeamAccount> accountWrapper = new LambdaQueryWrapper<>();
+        accountWrapper.eq(GptTeamAccount::getStatus, true)
+                     .notExists("SELECT 1 FROM gpt_team_user_bind_record WHERE gpt_team_account_id = gpt_team_account.id AND bind_status = 1");
+        
+        List<GptTeamAccount> availableAccounts = gptTeamAccountMapper.selectList(accountWrapper);
+        if (availableAccounts.isEmpty()) {
+            throw new BusinessRuntimeException("暂无可用的GPT Team账号,请稍后再试");
+        }
+
+        GptTeamAccount selectedAccount = availableAccounts.get(0);
+
+        //绑定 Team API
+        bindRecord.setToken("");
+        bindRecordMapper.updateById(bindRecord);
+    }
+
+    @Override
+    public GptTeamUserBindRecord getBindRecord(Long orderId, Long userId) {
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        GptTeamUserBindRecord bindRecord = bindRecordMapper.selectOne(Wrappers.lambdaQuery(GptTeamUserBindRecord.class).eq(GptTeamUserBindRecord::getOrderId, orderId).in(GptTeamUserBindRecord::getUserId, userIdList).last("limit 1"));
+        return bindRecord;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void changeBind(GptTeamBindRequest request) {
+        Long orderId = request.getOrderId();
+        Long userId = request.getUserId();
+
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        GptTeamUserBindRecord bindRecord = bindRecordMapper.selectOne(Wrappers.lambdaQuery(GptTeamUserBindRecord.class).eq(GptTeamUserBindRecord::getOrderId, orderId).in(GptTeamUserBindRecord::getUserId, userIdList).last("limit 1"));
+        if (bindRecord == null) {
+            throw BusinessRuntimeException.getInstance("您还未假如Team");
+        }
+
+        // 1. 验证换绑次数
+        Integer changeNum = bindRecord.getChangeNum();
+        if (changeNum == 0) {
+            throw new BusinessRuntimeException("仅可换绑一次");
+        }
+
+        int update = bindRecordMapper.update(null, Wrappers.lambdaUpdate(GptTeamUserBindRecord.class)
+                .set(GptTeamUserBindRecord::getChangeNum, 0)
+                .eq(GptTeamUserBindRecord::getId, bindRecord.getId())
+                .eq(GptTeamUserBindRecord::getChangeNum, changeNum));
+        if (update == 0) {
+            throw new BusinessRuntimeException("仅可换绑一次");
+        }
+        //换绑前的token
+        String bfToken = bindRecord.getToken();
+        // 4. 查找新的可用账号
+        LambdaQueryWrapper<GptTeamAccount> accountWrapper = new LambdaQueryWrapper<>();
+        accountWrapper.eq(GptTeamAccount::getStatus, true)
+                     .ne(GptTeamAccount::getToken, bfToken)
+                     .notExists("SELECT 1 FROM gpt_team_user_bind_record WHERE gpt_team_account_id = gpt_team_account.id AND bind_status = 1");
+        //换绑其他Team API
+        bindRecord.setToken("");
+        bindRecord.setBfToken(bfToken);
+        bindRecordMapper.updateById(bindRecord);
+    }
+}

+ 6 - 2
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -475,7 +475,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		User user = null;
 		String payOpenId = null;
 		Long relationId = 0L;
-		Boolean isNeedTicket = checkIsNeedGroupsRelation(goodsDon);
+		Boolean isNeedTicket = checkIsNeedGroupsRelation(goodsDon, sku);
 		Long userId = payRequest.getUserId();
 		if (userId != null && payRequest.getCmt() == 1) {
 			int noPayCount = count(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, userId).eq(OrderDon::getGoodsId, goodsId)
@@ -942,7 +942,11 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 	}
 
-	private Boolean checkIsNeedGroupsRelation(GoodsDon goodsDon) {
+	private Boolean checkIsNeedGroupsRelation(GoodsDon goodsDon, GoodsDonSku sku) {
+		//gpt team规格不需要车票
+		if (sku.getIsGptTeam()) {
+			return false;
+		}
 		if (goodsDon.getType() == 1) {
 			//礼品卡特殊类型不需要车票
 			if (goodsDon.getSpecialType() != null && goodsDon.getSpecialType() == GoodsDon.SpecialType.giftCard) {

+ 59 - 0
netflix-web/src/main/java/com/cyksj/web/controller/gpt/GptTeamUserBindRecordController.java

@@ -0,0 +1,59 @@
+package com.cyksj.web.controller.gpt;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.GptTeamUserBindRecord;
+import com.cyksj.model.request.GptTeamBindRequest;
+import com.cyksj.service.gpt.GptTeamUserBindRecordService;
+import com.cyksj.web.util.StpUserUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * GPT Team用户绑定记录控制器
+ */
+@Slf4j
+@RestController
+@RequestMapping("/gpt/team/bind")
+@RequiredArgsConstructor
+public class GptTeamUserBindRecordController {
+
+    private final GptTeamUserBindRecordService gptTeamUserBindRecordService;
+
+    /**
+     * 通过订单ID绑定邮箱
+     */
+    @PostMapping("/bindByOrderId")
+    public Result<String> bindByOrderId(@RequestBody @Validated GptTeamBindRequest request) {
+        Long userId = StpUserUtil.getLoginIdAsLong();
+        request.setUserId(userId);
+        gptTeamUserBindRecordService.bindByOrderId(request);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 查询用户绑定记录
+     * 
+     * @param orderId 订单ID
+     * @return 绑定记录
+     */
+    @GetMapping("/getBindRecord/{orderId}")
+    public Result<GptTeamUserBindRecord> getBindRecord(@PathVariable Long orderId) {
+        Long userId = StpUserUtil.getLoginIdAsLong();
+        GptTeamUserBindRecord response = gptTeamUserBindRecordService.getBindRecord(orderId, userId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(response);
+    }
+
+    /**
+     * Team失效换绑
+     */
+    @PostMapping("/changeBind")
+    public Result<String> changeBind(@RequestBody @Validated GptTeamBindRequest request) {
+        Long userId = StpUserUtil.getLoginIdAsLong();
+        request.setUserId(userId);
+        gptTeamUserBindRecordService.changeBind(request);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+}