zwhui před 2 roky
rodič
revize
f6108fa3f9
34 změnil soubory, kde provedl 1849 přidání a 0 odebrání
  1. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyAccountMapper.java
  2. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyUserConversationMapper.java
  3. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyUserMapper.java
  4. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/UpgradeOrderDonMapper.java
  5. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/UpgradePackageMapper.java
  6. 21 0
      netflix-dao/src/main/java/com/cyksj/model/dto/BlendDimensions.java
  7. 18 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitActionDTO.java
  8. 23 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitBlendDTO.java
  9. 16 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitDescribeDTO.java
  10. 24 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitImagineDTO.java
  11. 27 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitModalDTO.java
  12. 16 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitShortenDTO.java
  13. 10 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSku.java
  14. 54 0
      netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyAccount.java
  15. 60 0
      netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUser.java
  16. 90 0
      netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUserConversation.java
  17. 121 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UpgradeOrderDon.java
  18. 53 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UpgradePackage.java
  19. 5 0
      netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java
  20. 76 0
      netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyAccountView.java
  21. 71 0
      netflix-dao/src/main/java/com/cyksj/model/views/UpgradePackageView.java
  22. 11 0
      netflix-service/src/main/java/com/cyksj/service/mange/upgrade/UpgradePackageService.java
  23. 19 0
      netflix-service/src/main/java/com/cyksj/service/mange/upgrade/impl/UpgradePackageServiceImpl.java
  24. 27 0
      netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyAccountService.java
  25. 29 0
      netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyService.java
  26. 267 0
      netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidJourneyAccountServiceImpl.java
  27. 265 0
      netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyServiceImpl.java
  28. 4 0
      netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java
  29. 67 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  30. 106 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/mj/MidJourneyController.java
  31. 121 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/upgrade/UpgradePackageController.java
  32. 161 0
      netflix-web/src/main/java/com/cyksj/web/controller/mirror/MidjourneyController.java
  33. 13 0
      netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java
  34. 19 0
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyAccountMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.MidjourneyAccount;
+
+/**
+ * @author zwhui
+ * @date 2024/4/12 15:51
+ */
+public interface MidjourneyAccountMapper extends BaseMapper<MidjourneyAccount> {
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyUserConversationMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.MidjourneyUserConversation;
+
+/**
+ * @author zwhui
+ * @date 2024/4/23 16:03
+ */
+public interface MidjourneyUserConversationMapper extends BaseMapper<MidjourneyUserConversation> {
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyUserMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.MidjourneyUser;
+
+/**
+ * @author zwhui
+ * @date 2024/4/16 17:46
+ */
+public interface MidjourneyUserMapper extends BaseMapper<MidjourneyUser> {
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/UpgradeOrderDonMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UpgradeOrderDon;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 17:29
+ */
+public interface UpgradeOrderDonMapper extends BaseMapper<UpgradeOrderDon> {
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/UpgradePackageMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UpgradePackage;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 15:03
+ */
+public interface UpgradePackageMapper extends BaseMapper<UpgradePackage> {
+}

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/BlendDimensions.java

@@ -0,0 +1,21 @@
+package com.cyksj.model.dto;
+
+
+import lombok.Getter;
+
+@Getter
+public enum BlendDimensions {
+
+	PORTRAIT("2:3"),
+
+	SQUARE("1:1"),
+
+	LANDSCAPE("3:2");
+
+	private final String value;
+
+	BlendDimensions(String value) {
+		this.value = value;
+	}
+
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitActionDTO.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.dto;
+
+import lombok.Data;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 10:56
+ */
+@Data
+public class SubmitActionDTO {
+
+    private Long taskId;
+
+    /**
+     * 动作标识,示例值(MJ::JOB::upsample::2::3dbbd469-36af-4a0f-8f02-df6c579e7011)
+     */
+    private String customId;
+}

+ 23 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitBlendDTO.java

@@ -0,0 +1,23 @@
+package com.cyksj.model.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author zwhui
+ * @date 2024/4/23 13:49
+ */
+@Data
+public class SubmitBlendDTO {
+
+	/**
+	 * base64
+	 */
+	private List<String> base64Array;
+
+	/**
+	 * 比例: PORTRAIT(2:3); SQUARE(1:1); LANDSCAPE(3:2)
+	 */
+	private BlendDimensions dimensions = BlendDimensions.SQUARE;
+}

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitDescribeDTO.java

@@ -0,0 +1,16 @@
+package com.cyksj.model.dto;
+
+import lombok.Data;
+
+/**
+ * @author zwhui
+ * @date 2024/4/23 13:49
+ */
+@Data
+public class SubmitDescribeDTO {
+
+	/**
+	 * base64
+	 */
+	private String base64;
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitImagineDTO.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author zwhui
+ * @date 2024/4/23 13:49
+ */
+@Data
+public class SubmitImagineDTO {
+
+    /**
+     * 提示词
+     */
+    private String prompt;
+
+    /**
+     * 垫图base64数组
+     */
+    private List<String> base64Array;
+
+}

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitModalDTO.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.dto;
+
+import lombok.Data;
+
+/**
+ * @author zwhui
+ * @date 2024/4/23 18:04
+ */
+@Data
+public class SubmitModalDTO {
+
+    /**
+     * 局部重绘base64
+     */
+    private String maskBase64;
+
+    /**
+     * 提示词
+     */
+    private String prompt;
+
+    /**
+     * 任务id
+     */
+    private Long taskId;
+
+}

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitShortenDTO.java

@@ -0,0 +1,16 @@
+package com.cyksj.model.dto;
+
+import lombok.Data;
+
+/**
+ * @author zwhui
+ * @date 2024/4/23 18:07
+ */
+@Data
+public class SubmitShortenDTO {
+
+    /**
+     * 提示词
+     */
+    private String prompt;
+}

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

@@ -178,6 +178,16 @@ public class GoodsDonSku extends BaseEntity {
      */
     private Long gptLimitTime;
 
+    /**
+     * mj fast次数
+     */
+    private Integer mjFastNum;
+
+    /**
+     * mj relax次数
+     */
+    private Integer mjRelaxNum;
+
     /**
      * 特定价格
      */

+ 54 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyAccount.java

@@ -0,0 +1,54 @@
+package com.cyksj.model.entity;
+
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Data;
+
+/**
+ * @author zwhui
+ * @date 2024/4/12 10:52
+ */
+@Data
+@SearchBean(tables = "midjourney_account")
+public class MidjourneyAccount extends BaseEntity{
+
+    /**
+     * 账号id
+     */
+    private Long accountId;
+
+    /**
+     * 状态 true有效 false无效
+     */
+    private Boolean status;
+
+    /**
+     * 服务器id
+     */
+    private Long guildId;
+
+    /**
+     * 频道id
+     */
+    private Long channelId;
+
+    /**
+     * user_token
+     */
+    private String userToken;
+
+    /**
+     * plus服务实例id
+     */
+    private Long instanceId;
+
+    /**
+     * fast剩余时间
+     */
+    private String fastRemainTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 60 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUser.java

@@ -0,0 +1,60 @@
+package com.cyksj.model.entity;
+
+/**
+ * @author zwhui
+ * @date 2024/4/16 17:01
+ */
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@SearchBean(tables = "midjourney_user")
+public class MidjourneyUser extends BaseEntity{
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 头像
+     */
+    private String img;
+
+    /**
+     * 用户凭证
+     */
+    @TableField("userToken")
+    private String userToken;
+
+    /**
+     * 过期时间
+     */
+    @TableField("expireTime")
+    private Date expireTime;
+
+    /**
+     * 车票id
+     */
+    @TableField("relationId")
+    private Long relationId;
+
+    /**
+     * mj fast次数
+     */
+    private Integer mjFastNum;
+
+    /**
+     * mj relax次数
+     */
+    private Integer mjRelaxNum;
+
+    /**
+     * 当前模式 1:fast 2:relax
+     */
+    private Integer mode;
+}

+ 90 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUserConversation.java

@@ -0,0 +1,90 @@
+package com.cyksj.model.entity;
+
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @author zwhui
+ * @date 2024/4/23 11:10
+ */
+@Data
+@Accessors(chain = true)
+@SearchBean(tables = "midjourney_user_conversation")
+public class MidjourneyUserConversation extends BaseEntity implements Serializable {
+
+    private Long userId;
+
+    /**
+     * plus服务任务id
+     */
+    private Long taskId;
+
+    /**
+     * IMAGINE,UPSCALE,VARIATION,ZOOM,PAN,DESCRIBE,BLEND,SHORTEN
+     */
+    private String action;
+
+    /**
+     * 频道id
+     */
+    private Long channelId;
+
+    /**
+     * plus服务实例id
+     */
+    private Long instanceId;
+
+    /**
+     * 模式 1:fast 2:relax
+     */
+    private Integer mode;
+
+    /**
+     * 开始时间
+     */
+    private Long startTime;
+
+    /**
+     * 完成时间
+     */
+    private Long finishTime;
+
+    /**
+     * 提示词
+     */
+    private String prompt;
+
+    /**
+     * 描述
+     */
+    private String description;
+
+    /**
+     * 任务状态,可用值:IN_PROGRESS,FAILURE,SUCCESS,CANCEL
+     */
+    private String status;
+
+    /**
+     * 失败原因
+     */
+    private String failReason;
+
+    /**
+     * 进度
+     */
+    private String progress;
+
+    /**
+     * 图片地址
+     */
+    private String imageUrl;
+
+    /**
+     * 按钮
+     */
+    private String buttons;
+
+}

+ 121 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UpgradeOrderDon.java

@@ -0,0 +1,121 @@
+package com.cyksj.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Date;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 17:08
+ */
+@Data
+public class UpgradeOrderDon extends BaseEntity {
+    /**
+     * 订单编号
+     */
+    private String orderNo;
+
+    /**
+     * 商品id
+     */
+    private Long goodsId;
+
+    /**
+     * 套餐id
+     */
+    private Long packageId;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+
+    /**
+     * 原订单号
+     */
+    private Long originalOrderId;
+
+    /**
+     * 金额
+     */
+    private BigDecimal money;
+
+
+    /**
+     * 余额支付
+     */
+    private BigDecimal balance;
+
+    /**
+     * 退款金额
+     */
+    private BigDecimal refundMoney;
+
+    /**
+     * 退款余额
+     */
+    private BigDecimal refundBalance;
+
+    /**
+     * 退款原因
+     */
+    private String refundDesc;
+
+    /**
+     * 支付时间
+     */
+    private Date payTime;
+
+    private Status status;
+
+    private Type type;
+
+    public enum Status {
+        /**
+         * 订单状态
+         */
+        close("已关闭"),
+        noPayment("待付款"),
+        hasPayment("已付款"),
+        transport("已发货"),
+        received("已签收"),
+        complete("已完成"),
+        refund("已退款"),
+        ;
+
+        private String desc;
+
+        Status(String desc) {
+            this.desc = desc;
+        }
+
+        public String getDesc() {
+            return desc;
+        }
+    }
+
+    @Getter
+    @AllArgsConstructor
+    public enum Type{
+        WeChat("wechat","微信"),
+        ALI_PAY("zfb","支付宝"),
+        EX_CODE("exchange_code","兑换码"),
+        LOTTERY("lottery","抽奖"),
+        EQUIPMENT("equipment", "实物设备分销"),
+        PAY_EQUIPMENT("pay_equipment", "自购设备"),
+        BALANCE("balance", "余额支付"),
+        PAYPAL("paypal","paypal支付"),
+        STRIPE("stripe","stripe支付")
+        ;
+        String type;
+        String desc;
+
+        public static UpgradeOrderDon.Type getType(String type) {
+            return Arrays.stream(UpgradeOrderDon.Type.values()).filter(tp -> tp.getType().equals(type)).findFirst().orElse(ALI_PAY);
+        }
+    }
+}

+ 53 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UpgradePackage.java

@@ -0,0 +1,53 @@
+package com.cyksj.model.entity;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 14:54
+ */
+@Data
+public class UpgradePackage extends BaseEntity{
+
+    /**
+     * 套餐名称
+     */
+    private String name;
+
+    /**
+     * 商品id
+     */
+    private Long goodsId;
+
+    /**
+     * 商品规格id
+     */
+    private Long skuId;
+
+    /**
+     * 套餐价格
+     */
+    private BigDecimal price;
+
+    /**
+     * 数量
+     */
+    private Integer num;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * true 上架 / false 下架
+     */
+    private Boolean status;
+
+    /**
+     * true 存在 / false 删除
+     */
+    private Boolean deleted;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java

@@ -165,4 +165,9 @@ public class OrderPayRequest {
      * 百亿补贴规格id
      */
     private Long subsidyId;
+
+    /**
+     * 套餐id
+     */
+    private Long packageId;
 }

+ 76 - 0
netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyAccountView.java

@@ -0,0 +1,76 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GroupsTrips;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author zwhui
+ * @date 2024/4/16 16:04
+ */
+@Getter
+@Setter
+@SearchBean(tables = "midjourney_account ma left join account a on ma.account_id = a.id",
+        where = ":extra_sql:")
+public class MidjourneyAccountView {
+    @DbField("ma.id")
+    private Long id;
+
+    @DbField("a.account")
+    private String account;
+
+    @DbField("a.password")
+    private String password;
+
+    @DbField("a.start_time")
+    private Date startTime;
+
+    @DbField("a.expiry_time")
+    private Date expiryTime;
+
+    /**
+     * 状态 true有效 false无效
+     */
+    @DbField("ma.status")
+    private Boolean status;
+
+    /**
+     * 服务器id
+     */
+    @DbField("ma.guild_id")
+    private Long guildId;
+
+    /**
+     * 频道id
+     */
+    @DbField("ma.channel_id")
+    private Long channelId;
+
+    /**
+     * user_token
+     */
+    @DbField("ma.user_token")
+    private String userToken;
+
+    /**
+     * fast剩余时间
+     */
+    @DbField("ma.fast_remain_time")
+    private String fastRemainTime;
+
+    /**
+     * 账号备注
+     */
+    @DbField("ma.remark")
+    private String remark;
+
+    @DbField("ma.created_time")
+    private Date createdTime;
+
+}

+ 71 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UpgradePackageView.java

@@ -0,0 +1,71 @@
+package com.cyksj.model.views;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 15:20
+ */
+@Data
+@SearchBean(tables = "upgrade_package up left join goods g on up.goods_id = g.id", where = "deleted = true")
+public class UpgradePackageView {
+
+    /**
+     * 套餐名称
+     */
+    @DbField("up.name")
+    private String name;
+
+    /**
+     * 商品id
+     */
+    @DbField("up.goods_id")
+    private Long goodsId;
+
+    /**
+     * 商品名称
+     */
+    @DbField("g.title")
+    private String goodsName;
+
+    /**
+     * 商品规格id
+     */
+    @DbField("up.sku_id")
+    private Long skuId;
+
+    /**
+     * 套餐价格
+     */
+    @DbField("up.price")
+    private BigDecimal price;
+
+    /**
+     * 数量
+     */
+    @DbField("up.num")
+    private Integer num;
+
+    /**
+     * 备注
+     */
+    @DbField("up.remark")
+    private String remark;
+
+    /**
+     * true 上架 / false 下架
+     */
+    @DbField("up.status")
+    private Boolean status;
+
+    /**
+     * true 存在 / false 删除
+     */
+    @DbField("up.deleted")
+    private Boolean deleted;
+}

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/mange/upgrade/UpgradePackageService.java

@@ -0,0 +1,11 @@
+package com.cyksj.service.mange.upgrade;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.UpgradePackage;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 15:04
+ */
+public interface UpgradePackageService extends IService<UpgradePackage> {
+}

+ 19 - 0
netflix-service/src/main/java/com/cyksj/service/mange/upgrade/impl/UpgradePackageServiceImpl.java

@@ -0,0 +1,19 @@
+package com.cyksj.service.mange.upgrade.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.UpgradePackageMapper;
+import com.cyksj.model.entity.UpgradePackage;
+import com.cyksj.service.mange.upgrade.UpgradePackageService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 15:05
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class UpgradePackageServiceImpl extends ServiceImpl<UpgradePackageMapper, UpgradePackage> implements UpgradePackageService {
+}

+ 27 - 0
netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyAccountService.java

@@ -0,0 +1,27 @@
+package com.cyksj.service.midjourney;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.Account;
+import com.cyksj.model.entity.MidjourneyAccount;
+import com.cyksj.model.entity.MidjourneyUser;
+
+import java.util.List;
+
+/**
+ * @author zwhui
+ * @date 2024/4/12 15:54
+ */
+public interface MidjourneyAccountService extends IService<MidjourneyAccount> {
+    void addAccount(MidjourneyAccount midjourneyAccount);
+
+    void removeAccount(Long id);
+
+    void updateAccount(MidjourneyAccount midjourneyAccount);
+
+    void updateStatus(Long id);
+
+    void syncAccount(Long id);
+
+    String getLoginUrl(Long userId, Long relationId);
+
+}

+ 29 - 0
netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyService.java

@@ -0,0 +1,29 @@
+package com.cyksj.service.midjourney;
+
+import com.cyksj.model.dto.BlendDimensions;
+import com.cyksj.model.entity.MidjourneyUser;
+import com.cyksj.model.entity.MidjourneyUserConversation;
+
+import java.util.List;
+
+/**
+ * @author zwhui
+ * @date 2024/4/23 15:44
+ */
+public interface MidjourneyService {
+    MidjourneyUserConversation submitImagine(MidjourneyUser user, String prompt, List<String> base64Array);
+
+    MidjourneyUserConversation submitDescribe(MidjourneyUser user, String base64);
+
+    MidjourneyUserConversation submitBlend(MidjourneyUser user, BlendDimensions dimensions, List<String> base64Array);
+
+    MidjourneyUserConversation submitModal(MidjourneyUser user, Long taskId, String prompt, String maskBase64);
+
+    MidjourneyUserConversation submitShorten(MidjourneyUser user, String prompt);
+
+    List<MidjourneyUserConversation> listConversationByIds(List<Long> ids);
+
+    MidjourneyUserConversation submitAction(MidjourneyUser user, Long taskId, String customId);
+
+    MidjourneyUserConversation cancelConversation(MidjourneyUser user, Long id);
+}

+ 267 - 0
netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidJourneyAccountServiceImpl.java

@@ -0,0 +1,267 @@
+package com.cyksj.service.midjourney.impl;
+
+import cn.hutool.core.lang.UUID;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.*;
+import com.cyksj.model.entity.*;
+import com.cyksj.service.midjourney.MidjourneyAccountService;
+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 javax.imageio.stream.FileImageOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author zwhui
+ * @date 2024/4/12 15:54
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountMapper, MidjourneyAccount> implements MidjourneyAccountService {
+
+    private static final String HOST = "http://43.154.230.104:8080";
+
+    private final GroupsRelationMapper groupsRelationMapper;
+
+    private final GroupsMapper groupsMapper;
+
+    private final GoodsDonSkuMapper skuMapper;
+
+    private final UserMapper userMapper;
+
+    private final UserBindRelationService userBindRelationService;
+
+    private final MidjourneyUserMapper midjourneyUserMapper;
+
+    @Override
+    public void addAccount(MidjourneyAccount midjourneyAccount) {
+        baseMapper.insert(midjourneyAccount);
+        addAcount(midjourneyAccount);
+        //拉取plus服务账号实例id
+        Long instanceId = getAccount(midjourneyAccount.getId());
+        midjourneyAccount.setInstanceId(instanceId);
+        baseMapper.updateById(midjourneyAccount);
+    }
+
+    @Override
+    public void removeAccount(Long id) {
+        MidjourneyAccount midjourneyAccount = baseMapper.selectById(id);
+        if (midjourneyAccount == null) {
+            throw BusinessRuntimeException.getInstance("账号不存在");
+        }
+        baseMapper.deleteById(id);
+        //删除plus服务账号信息
+        delAcount(midjourneyAccount.getInstanceId());
+    }
+
+    @Override
+    public void updateAccount(MidjourneyAccount midjourneyAccount) {
+        baseMapper.updateById(midjourneyAccount);
+        updAccount(midjourneyAccount);
+    }
+
+    @Override
+    public void updateStatus(Long id) {
+        MidjourneyAccount midjourneyAccount = baseMapper.selectById(id);
+        if (midjourneyAccount == null) {
+            throw BusinessRuntimeException.getInstance("账号不存在");
+        }
+        midjourneyAccount.setStatus(!midjourneyAccount.getStatus());
+        updAccount(midjourneyAccount);
+    }
+
+    @Override
+    public void syncAccount(Long id) {
+        MidjourneyAccount midjourneyAccount = baseMapper.selectById(id);
+        if (midjourneyAccount == null) {
+            throw BusinessRuntimeException.getInstance("账号不存在");
+        }
+        String fastRemainTime = syncInfo(midjourneyAccount.getInstanceId());
+        midjourneyAccount.setFastRemainTime(fastRemainTime);
+        baseMapper.updateById(midjourneyAccount);
+    }
+
+    private void addAcount(MidjourneyAccount midjourneyAccount) {
+        Map<String, Object> accountParam = createAccountParam(midjourneyAccount);
+        String body = HttpUtil.post(HOST + "/mj/account/create", accountParam);
+        log.info("addAccount body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("addAccount error message:" + jsonObject.getStr("description"));
+        }
+    }
+
+    private Map<String, Object> createAccountParam(MidjourneyAccount midjourneyAccount) {
+        Map<String, Object> param = new HashMap<>();
+        param.put("channelId", midjourneyAccount.getChannelId());
+        param.put("guildId", midjourneyAccount.getGuildId());
+        param.put("userToken", midjourneyAccount.getUserToken());
+        param.put("remark", midjourneyAccount.getId());
+        return param;
+    }
+
+    private void delAcount(Long id) {
+        String body = HttpRequest.delete(HOST + "/mj/account/"+id+"/delete").execute().body();
+        log.info("delAcount body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("delAcount error message:" + jsonObject.getStr("description"));
+        }
+    }
+
+    private Long getAccount(Long id) {
+        String body = HttpRequest.post(HOST + "/mj/account/query").form("remark",id).execute().body();
+        log.info("getAccount body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("getAccount error message:" + jsonObject.getStr("description"));
+        }
+
+        return JSONUtil.parseObj(JSONUtil.parseArray(jsonObject.getStr("content")).get(0)).get("id", Long.class);
+    }
+
+    private void updAccount(MidjourneyAccount midjourneyAccount){
+        Map<String, Object> accountParam = createAccountParam(midjourneyAccount);
+        String body = HttpRequest.put(HOST + "/mj/account/"+midjourneyAccount.getInstanceId()+"/update-reconnect")
+                .body(JSONUtil.toJsonStr(accountParam)).execute().body();
+        log.info("updAccount body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("updAccount error message:" + jsonObject.getStr("description"));
+        }
+    }
+
+    private String syncInfo(Long id){
+        String body = HttpRequest.post(HOST + "/mj/account/"+id+"/sync-info").execute().body();
+        log.info("syncInfo body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("syncInfo error message:" + jsonObject.getStr("description"));
+        }
+        return JSONUtil.parseObj(jsonObject.getStr("result")).getStr("fastTimeRemaining");
+    }
+
+
+    @Override
+    public String getLoginUrl(Long userId, Long relationId) {
+        GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
+        GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
+        GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
+
+        if (goodsDonSku != null && goodsDonSku.getIsMirror()) {
+            MidjourneyUser midjourneyUser = getMidjourneyUser(userId, relationId, groupsRelation, groupsTrips, goodsDonSku);
+            return HOST + "/login_token?access_token=" + midjourneyUser.getUserToken();
+        } else {
+            throw BusinessRuntimeException.getInstance("服务器出了点问题");
+        }
+    }
+
+    /**
+     * 获取车位信息
+     *
+     * @param userId
+     * @param relationId
+     * @return
+     */
+    private GroupsRelation getGroupsRelation(Long userId, Long relationId) {
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        GroupsRelation groupsRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).in(GroupsRelation::getUserId, userIdList).eq(GroupsRelation::getId, relationId));
+        if (groupsRelation == null) {
+            throw BusinessRuntimeException.getInstance("车票不存在");
+        }
+        return groupsRelation;
+    }
+
+    /**
+     * 获取车队信息
+     *
+     * @param groupsRelation
+     * @return
+     */
+    private GroupsTrips getGroupsTrips(GroupsRelation groupsRelation) {
+        GroupsTrips groupsTrips = groupsMapper.selectById(groupsRelation.getGroupsId());
+        if (groupsTrips == null) {
+            throw BusinessRuntimeException.getInstance("车队异常");
+        }
+        return groupsTrips;
+    }
+
+    private MidjourneyUser getMidjourneyUser(Long userId, Long relationId, GroupsRelation groupsRelation, GroupsTrips groupsTrips, GoodsDonSku goodsDonSku) {
+        MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class).eq(MidjourneyUser::getRelationId, relationId));
+        User user = userMapper.selectById(userId);
+        if (midjourneyUser == null) {
+            midjourneyUser = createMidjourneyUser(groupsRelation, groupsTrips, user, goodsDonSku);
+        } else {
+            updateMidjourneyUser(groupsRelation, user, midjourneyUser);
+        }
+        return midjourneyUser;
+    }
+
+    /**
+     * 创建MidjourneyUser
+     */
+    private synchronized MidjourneyUser createMidjourneyUser(GroupsRelation groupsRelation, GroupsTrips groupsTrips, User user, GoodsDonSku goodsDonSku) {
+        MidjourneyUser midjourneyUser = new MidjourneyUser();
+        midjourneyUser.setExpireTime(groupsRelation.getExpiryTime());
+        midjourneyUser.setName(user.getNickname());
+        midjourneyUser.setImg(getWxImg(user.getHeadimgurl(), user));
+        midjourneyUser.setRelationId(groupsRelation.getId());
+        midjourneyUser.setUserToken(UUID.randomUUID().toString());
+        midjourneyUser.setMjFastNum(goodsDonSku.getMjFastNum());
+        midjourneyUser.setMjRelaxNum(goodsDonSku.getMjRelaxNum());
+        midjourneyUserMapper.insert(midjourneyUser);
+        return midjourneyUser;
+    }
+
+    private void updateMidjourneyUser(GroupsRelation groupsRelation, User user, MidjourneyUser midjourneyUser) {
+        midjourneyUser.setName(user.getNickname());
+        midjourneyUser.setImg(getWxImg(user.getHeadimgurl(), user));
+        midjourneyUser.setExpireTime(groupsRelation.getExpiryTime());
+        midjourneyUserMapper.updateById(midjourneyUser);
+    }
+
+    /**
+     * 更换wx头像至oss
+     */
+    private String getWxImg(String headimgurl, User user) {
+        if (headimgurl.contains("thirdwx.qlogo.cn")) {
+            try {
+                return uploadPic(headimgurl, "wxheadimg-" + user.getId());
+            } catch (Exception ex) {
+                log.error("上传微信头像错误!msg:{}", StringUtil.getErrorText(ex));
+                return "./avatars.png";
+            }
+        } else {
+            return user.getHeadimgurl();
+        }
+    }
+
+    private static String uploadPic(String url, String prefix) throws IOException {
+        byte[] body = HttpUtil.downloadBytes(url);
+        Path tempFile = Files.createTempFile(prefix, ".jpeg");
+        try (FileImageOutputStream imageOutput = new FileImageOutputStream(tempFile.toFile())) {
+            imageOutput.write(body, 0, body.length);
+        }
+        Map<String, Object> paramMap = new HashMap<>();
+        paramMap.put("file", tempFile.toFile());
+        JSONObject result = JSONUtil.parseObj(HttpUtil.post("https://files.liuliangbang.vip/pic/ups", paramMap));
+        return result.getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl");
+    }
+
+}

+ 265 - 0
netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyServiceImpl.java

@@ -0,0 +1,265 @@
+package com.cyksj.service.midjourney.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
+import com.cyksj.mapper.MidjourneyUserConversationMapper;
+import com.cyksj.model.dto.BlendDimensions;
+import com.cyksj.model.entity.MidjourneyAccount;
+import com.cyksj.model.entity.MidjourneyUser;
+import com.cyksj.model.entity.MidjourneyUserConversation;
+import com.cyksj.service.midjourney.MidjourneyService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import javax.imageio.stream.FileImageOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author zwhui
+ * @date 2024/4/23 15:44
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class MidjourneyServiceImpl implements MidjourneyService {
+    private static final String HOST = "http://43.154.230.104:8080";
+
+    private final MidjourneyUserConversationMapper conversationMapper;
+
+    private static final List<String> progress = Arrays.asList("25%", "45%", "75%", "100%");
+
+    private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
+
+
+    @Override
+    public MidjourneyUserConversation submitImagine(MidjourneyUser user, String prompt, List<String> base64Array) {
+        JSONObject imagine = imagine(user.getId(), prompt, base64Array);
+        JSONObject properties = imagine.getJSONObject("properties");
+        return saveConversation(user.getId(), imagine.getLong("result"), properties,"IMAGINE", prompt);
+    }
+
+    public MidjourneyUserConversation saveConversation(Long userId,Long taskId,JSONObject properties, String action,String prompt) {
+        MidjourneyUserConversation conversation = new MidjourneyUserConversation()
+                .setUserId(userId).setTaskId(taskId).setAction(action).setPrompt(prompt)
+                .setMode(1).setStartTime(System.currentTimeMillis()).setProgress("0%")
+                .setStatus("IN_PROGRESS").setChannelId(properties.getLong("discordChannelId"))
+                .setInstanceId(properties.getLong("discordInstanceId")).setTaskId(taskId);
+        conversationMapper.insert(conversation);
+        return conversation;
+    }
+
+    private JSONObject imagine(Long userId,String prompt, List<String> base64Array) {
+        Map<String, Object> imagineParam = MapUtil.builder(new HashMap<String,Object>())
+                .put("prompt", prompt).put("state", userId).build();
+        if (CollectionUtil.isNotEmpty(base64Array)) {
+            imagineParam.put("base64Array", base64Array);
+        }
+        String body = HttpUtil.post(HOST + "/mj/submit/imagine", imagineParam);
+        log.info("imagine body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("imagine error message:" + jsonObject.getStr("description"));
+        }
+        return jsonObject;
+    }
+
+
+    @Override
+    public MidjourneyUserConversation submitDescribe(MidjourneyUser user, String base64) {
+        JSONObject describe = describe(user.getId(), base64);
+        JSONObject properties = describe.getJSONObject("properties");
+        return saveConversation(user.getId(), describe.getLong("result"), properties,"DESCRIBE", StringUtils.EMPTY);
+    }
+
+    private JSONObject describe(Long userId,String base64) {
+        Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>()).put("state", userId).put("base64", base64).build();
+        String body = HttpUtil.post(HOST + "/mj/submit/describe", param);
+        log.info("describe body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("describe error message:" + jsonObject.getStr("description"));
+        }
+        return jsonObject;
+    }
+
+
+
+    @Override
+    public MidjourneyUserConversation submitBlend(MidjourneyUser user, BlendDimensions dimensions, List<String> base64Array) {
+        JSONObject blend = blend(user.getId(), dimensions, base64Array);
+        JSONObject properties = blend.getJSONObject("properties");
+        return saveConversation(user.getId(), blend.getLong("result"), properties,"BLEND", StringUtils.EMPTY);
+    }
+
+    private JSONObject blend(Long userId,BlendDimensions dimensions, List<String> base64Array) {
+        Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>())
+                .put("base64Array", base64Array).put("state", userId).build();
+        if (dimensions != null) {
+            param.put("dimensions", dimensions);
+        }
+        String body = HttpUtil.post(HOST + "/mj/submit/blend", param);
+        log.info("blend body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("blend error message:" + jsonObject.getStr("description"));
+        }
+        return jsonObject;
+    }
+    @Override
+    public MidjourneyUserConversation submitModal(MidjourneyUser user, Long taskId, String prompt, String maskBase64) {
+        JSONObject modal = modal(user.getId(),taskId, prompt, maskBase64);
+        JSONObject properties = modal.getJSONObject("properties");
+        return saveConversation(user.getId(), modal.getLong("result"), properties,"MODAL", prompt);
+    }
+
+    private JSONObject modal(Long userId,Long taskId,String prompt, String maskBase64) {
+        Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>())
+                .put("taskId", taskId).put("state", userId).build();
+        if (StringUtils.isNotBlank(prompt)) {
+            param.put("prompt", prompt);
+        }
+        if (StringUtils.isNotBlank(maskBase64)) {
+            param.put("maskBase64", maskBase64);
+        }
+        String body = HttpUtil.post(HOST + "/mj/submit/modal", param);
+        log.info("shorten body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("shorten error message:" + jsonObject.getStr("description"));
+        }
+        return jsonObject;
+    }
+
+    @Override
+    public MidjourneyUserConversation submitShorten(MidjourneyUser user, String prompt) {
+        JSONObject shorten = shorten(user.getId(), prompt);
+        JSONObject properties = shorten.getJSONObject("properties");
+        return saveConversation(user.getId(), shorten.getLong("result"), properties,"SHORTEN", prompt);
+    }
+
+    private JSONObject shorten(Long userId,String prompt) {
+        Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>())
+                .put("prompt", prompt).put("state", userId).build();
+        String body = HttpUtil.post(HOST + "/mj/submit/shorten", param);
+        log.info("shorten body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("shorten error message:" + jsonObject.getStr("description"));
+        }
+        return jsonObject;
+    }
+
+
+    @Override
+    public MidjourneyUserConversation submitAction(MidjourneyUser user, Long taskId, String customId) {
+        JSONObject action = action(user.getId(), taskId, customId);
+        JSONObject properties = action.getJSONObject("properties");
+        return saveConversation(user.getId(), action.getLong("result"), properties,"ACTION", StringUtils.EMPTY);
+    }
+
+    public JSONObject action(Long userId, Long taskId, String customId) {
+        Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>())
+                .put("taskId", taskId).put("state", userId).put("customId", customId).build();
+        String body = HttpUtil.post(HOST + "/mj/submit/action", param);
+        log.info("action body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("action error message:" + jsonObject.getStr("description"));
+        }
+        return jsonObject;
+    }
+    @Override
+    public List<MidjourneyUserConversation> listConversationByIds(List<Long> ids) {
+        List<MidjourneyUserConversation> list = new ArrayList<>();
+        listByIds(ids).forEach(json -> {
+            JSONObject jsons = JSONUtil.parseObj(json);
+            MidjourneyUserConversation conversation = JSONUtil.toBean(jsons, MidjourneyUserConversation.class);
+            conversation.setUserId(jsons.getLong("state"));
+            conversation.setTaskId(jsons.getLong("id"));
+            list.add(conversation);
+            TASK_EXECUTOR.execute(() -> {
+                try {
+                    sync(conversation);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            });
+        });
+        return list;
+    }
+
+
+    public void sync(MidjourneyUserConversation conversation) throws IOException {
+        if (progress.contains(conversation.getProgress())){
+            log.info("同步任务:{},进度:{}",conversation.getTaskId(),conversation.getProgress());
+            MidjourneyUserConversation dbConversation = conversationMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUserConversation.class).eq(MidjourneyUserConversation::getTaskId, conversation.getTaskId())
+                    .eq(MidjourneyUserConversation::getUserId, conversation.getUserId()).last("limit 1"));
+            if (dbConversation != null) {
+                if (StringUtils.isNotBlank(conversation.getImageUrl())) {
+                    dbConversation.setImageUrl(uploadPic(conversation.getImageUrl(), "conversation"+dbConversation.getId()));
+                }
+                conversation.setId(dbConversation.getId());
+                conversationMapper.updateById(conversation);
+            }
+        }
+    }
+
+
+    private static String uploadPic(String url, String prefix) throws IOException {
+        byte[] body = HttpUtil.downloadBytes(url);
+        Path tempFile = Files.createTempFile(prefix, ".png");
+        try (FileImageOutputStream imageOutput = new FileImageOutputStream(tempFile.toFile())) {
+            imageOutput.write(body, 0, body.length);
+        }
+        Map<String, Object> paramMap = new HashMap<>();
+        paramMap.put("file", tempFile.toFile());
+        JSONObject result = JSONUtil.parseObj(HttpUtil.post("https://files.liuliangbang.vip/pic/ups", paramMap));
+        return result.getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl");
+    }
+    public JSONArray listByIds(List<Long> ids) {
+        Map<String, Object> param = MapUtil.builder(new HashMap<String, Object>()).put("ids", ids).build();
+        String body = HttpUtil.post(HOST + "/mj/task/list-by-ids", param);
+        log.info("listByIds body:{}", body);
+        return JSONUtil.parseArray(body);
+    }
+
+    @Override
+    public MidjourneyUserConversation cancelConversation(MidjourneyUser user, Long id) {
+        MidjourneyUserConversation conversation = conversationMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUserConversation.class).eq(MidjourneyUserConversation::getId, id));
+        if (conversation == null) {
+            throw BusinessRuntimeException.getInstance("会话不存在");
+        }
+        if (!Objects.equals(conversation.getUserId(), user.getId())) {
+            throw BusinessRuntimeException.getInstance("不是您的会话");
+        }
+        conversation.setStatus("CANCEL");
+        conversationMapper.updateById(conversation);
+        cancel(conversation.getTaskId());
+        return conversation;
+    }
+
+    public void cancel(Long taskId) {
+        String body = HttpUtil.post(HOST + "/mj/task/"+taskId+"/cancel",MapUtil.empty());
+        log.info("cancel body:{}", body);
+        JSONObject jsonObject = JSONUtil.parseObj(body);
+        if (jsonObject.getInt("code") != 1) {
+            throw BusinessRuntimeException.getInstance("cancel error message:" + jsonObject.getStr("description"));
+        }
+    }
+
+}

+ 4 - 0
netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java

@@ -10,6 +10,7 @@ import com.cyksj.model.dto.H5JsPayParams;
 import com.cyksj.model.entity.OrderDetailView;
 import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.entity.RealGoodsInterestUser;
+import com.cyksj.model.entity.UpgradeOrderDon;
 import com.cyksj.model.request.AlipayOrderDonReq;
 import com.cyksj.model.request.OrderPayRequest;
 
@@ -90,4 +91,7 @@ public interface OrderDonService extends IService<OrderDon> {
     void zeroOrderConfirm(Long orderId);
 
     void orderNotify(OrderDon orderDon);
+
+    UpgradeOrderDon submitUpgrade(OrderPayRequest payRequest);
+
 }

+ 67 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -286,6 +286,12 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final OrderDonSubsidyRelateMapper orderDonSubsidyRelateMapper;
 
+	private final UpgradePackageMapper upgradePackageMapper;
+
+	private final UpgradeOrderDonMapper upgradeOrderDonMapper;
+
+	private final MidjourneyUserMapper midjourneyUserMapper;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -3079,4 +3085,65 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		orderDon.setMoney(price);
 	}
+
+
+	@Override
+	public UpgradeOrderDon submitUpgrade(OrderPayRequest payRequest) {
+		GroupsRelation groupsRelation = getGroupsRelation(payRequest.getUserId(), payRequest.getRelationId());
+		GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
+		GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(groupsTrips.getSkuId());
+
+		if (goodsDonSku != null && goodsDonSku.getIsMirror()) {
+			UpgradePackage upgradePackage = upgradePackageMapper.selectById(payRequest.getPackageId());
+			if (upgradePackage == null) {
+				throw BusinessRuntimeException.getInstance("套餐包不存在");
+			}
+			MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class).eq(MidjourneyUser::getRelationId, payRequest.getRelationId()));
+			if (midjourneyUser != null){
+				String donNo = SEQUENCE.nextId().toString();
+				UpgradeOrderDon upgradeOrderDon = new UpgradeOrderDon();
+				upgradeOrderDon.setOrderNo(donNo);
+				upgradeOrderDon.setUserId(payRequest.getUserId());
+				upgradeOrderDon.setOriginalOrderId(groupsRelation.getOrderId());
+				upgradeOrderDon.setPackageId(payRequest.getPackageId());
+				upgradeOrderDon.setGoodsId(groupsTrips.getGoodsId());
+				upgradeOrderDon.setMoney(payRequest.getDonMoney());
+				upgradeOrderDon.setStatus(UpgradeOrderDon.Status.noPayment);
+				upgradeOrderDon.setType(UpgradeOrderDon.Type.ALI_PAY);
+				upgradeOrderDonMapper.insert(upgradeOrderDon);
+				return upgradeOrderDon;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * 获取车位信息
+	 *
+	 * @param userId
+	 * @param relationId
+	 * @return
+	 */
+	private GroupsRelation getGroupsRelation(Long userId, Long relationId) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		GroupsRelation groupsRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).in(GroupsRelation::getUserId, userIdList).eq(GroupsRelation::getId, relationId));
+		if (groupsRelation == null) {
+			throw BusinessRuntimeException.getInstance("车票不存在");
+		}
+		return groupsRelation;
+	}
+
+	/**
+	 * 获取车队信息
+	 *
+	 * @param groupsRelation
+	 * @return
+	 */
+	private GroupsTrips getGroupsTrips(GroupsRelation groupsRelation) {
+		GroupsTrips groupsTrips = groupsMapper.selectById(groupsRelation.getGroupsId());
+		if (groupsTrips == null) {
+			throw BusinessRuntimeException.getInstance("车队异常");
+		}
+		return groupsTrips;
+	}
 }

+ 106 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/mj/MidJourneyController.java

@@ -0,0 +1,106 @@
+package com.cyksj.web.controller.manage.mj;
+
+import cn.hutool.core.util.StrUtil;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.MidjourneyAccount;
+import com.cyksj.model.manage.views.AccountView;
+import com.cyksj.model.views.MidjourneyAccountView;
+import com.cyksj.service.midjourney.MidjourneyAccountService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author zwhui
+ * @date 2024/4/15 14:38
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/manage/mj")
+public class MidJourneyController {
+
+    private final BeanSearcher beanSearcher;
+
+    private final HttpServletRequest request;
+
+    private final MidjourneyAccountService midjourneyAccountService;
+
+
+    /**
+     * 移入MJ账号池
+     */
+    @PostMapping("/addAccount")
+    public Result<Void> addAccount(@RequestBody MidjourneyAccount midjourneyAccount) {
+        log.info("移入MJ账号池 midjourneyAccount:{}", midjourneyAccount);
+        midjourneyAccountService.addAccount(midjourneyAccount);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 移除MJ账号池
+     */
+    @DeleteMapping("/removeAccount/{id}")
+    public Result<Void> removeAccount(@PathVariable Long id) {
+        log.info("移除MJ账号池 id:{}", id);
+        midjourneyAccountService.removeAccount(id);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 修改MJ账号池
+     */
+    @PutMapping("/updateAccount")
+    public Result<Void> updateAccount(@RequestBody MidjourneyAccount midjourneyAccount) {
+        log.info("修改MJ账号池 midjourneyAccount:{}", midjourneyAccount);
+        midjourneyAccountService.updateAccount(midjourneyAccount);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 上下架MJ账号
+     */
+    @PutMapping("/updateStatus/{id}")
+    public Result<Void> updateStatus(@PathVariable Long id) {
+        log.info("上下架MJ账号 id:{}", id);
+        midjourneyAccountService.updateStatus(id);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 同步账号信息
+     */
+    @PutMapping("/syncAccount/{id}")
+    public Result<Void> syncAccount(@PathVariable Long id) {
+        log.info("同步账号信息 id:{}", id);
+        midjourneyAccountService.syncAccount(id);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+
+    /**
+     * 查询账号池列表
+     */
+    @GetMapping("/getAccount")
+    public Result<SearchResult<MidjourneyAccountView>> getAccount(String expiryStartTime, String expiryEndTime) {
+        log.info("查询账号池列表");
+        MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
+        if (StrUtil.isNotEmpty(expiryStartTime) || StrUtil.isNotEmpty(expiryEndTime)) {
+            mapBuilder.field(AccountView::getExpiryTime, expiryStartTime, expiryEndTime)
+                    .op(Operator.Between);
+        }
+        SearchResult<MidjourneyAccountView> search = beanSearcher.search(MidjourneyAccountView.class, mapBuilder.build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
+
+
+
+}

+ 121 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/upgrade/UpgradePackageController.java

@@ -0,0 +1,121 @@
+package com.cyksj.web.controller.manage.upgrade;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.map.MapUtil;
+import com.cyksj.common.annotation.Log;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.UpgradePackage;
+import com.cyksj.model.views.UpgradePackageView;
+import com.cyksj.service.mange.upgrade.UpgradePackageService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapBuilder;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 15:06
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/manage/upgrade")
+public class UpgradePackageController {
+
+    private final UpgradePackageService upgradePackageService;
+
+    private final HttpServletRequest request;
+
+    private final BeanSearcher beanSearcher;
+
+    /**
+     * 新增套餐
+     */
+    @PostMapping
+    @SaCheckPermission("upgrade:add")
+    @Log(module = "套餐管理/新增套餐", businessType = BusinessType.POST, isSaveRequestData = true)
+    public Result<String> post(@RequestBody UpgradePackage upgradePackage){
+        log.info("新增套餐:{}", upgradePackage);
+        upgradePackageService.save(upgradePackage);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 修改套餐
+     */
+    @PutMapping
+    @SaCheckPermission("upgrade:edit")
+    @Log(module = "套餐管理/修改套餐", businessType = BusinessType.PUT, isSaveRequestData = true)
+    public Result<String> put(@RequestBody UpgradePackage upgradePackage){
+        log.info("修改套餐:{}", upgradePackage);
+        upgradePackageService.updateById(upgradePackage);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 删除套餐
+     */
+    @DeleteMapping("/{id}")
+    @SaCheckPermission("upgrade:delete")
+    @Log(module = "套餐管理/删除套餐", businessType = BusinessType.DELETE, isSaveRequestData = true)
+    public Result<String> delete(@PathVariable Long id){
+        log.info("删除套餐:{}", id);
+        UpgradePackage byId = upgradePackageService.getById(id);
+        if (byId == null){
+            throw BusinessRuntimeException.getInstance("套餐不存在");
+        }
+        byId.setDeleted(false);
+        upgradePackageService.updateById(byId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 上下架套餐
+     */
+    @PutMapping("/put/status/{id}")
+    @SaCheckPermission("upgrade:putStatus")
+    @Log(module = "套餐管理/上下架套餐", businessType = BusinessType.PUT, isSaveRequestData = true)
+    public Result<Boolean> putStatus(@PathVariable Long id){
+        log.info("上下架套餐:{}", id);
+        UpgradePackage byId = upgradePackageService.getById(id);
+        if (byId == null){
+            throw BusinessRuntimeException.getInstance("套餐不存在");
+        }
+        byId.setStatus(!byId.getStatus());
+        upgradePackageService.updateById(byId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(byId.getStatus());
+    }
+
+    /**
+     * 获取套餐
+     */
+    @GetMapping("/{id}")
+    public Result<UpgradePackage> get(@PathVariable Long id){
+        log.info("获取套餐:{}", id);
+        UpgradePackage byId = upgradePackageService.getById(id);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(byId);
+    }
+
+    /**
+     * 获取套餐列表
+     */
+    @GetMapping
+    public Result<SearchResult<UpgradePackageView>> list() {
+        log.info("获取套餐列表");
+        Map<String, Object> build = MapUtils.flatBuilder(request.getParameterMap()).build();
+        SearchResult<UpgradePackageView> search = beanSearcher.search(UpgradePackageView.class, build);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
+
+
+}

+ 161 - 0
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MidjourneyController.java

@@ -0,0 +1,161 @@
+package com.cyksj.web.controller.mirror;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.dto.Result;
+import com.cyksj.model.dto.*;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.MidjourneyUserMapper;
+import com.cyksj.model.entity.MidjourneyUser;
+import com.cyksj.model.entity.MidjourneyUserConversation;
+import com.cyksj.service.midjourney.MidjourneyAccountService;
+import com.cyksj.service.midjourney.MidjourneyService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapBuilder;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author zwhui
+ * @date 2024/4/23 10:31
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/applets/midjourney")
+public class MidjourneyController {
+
+    private final MidjourneyAccountService midjourneyAccountService;
+
+    private final MidjourneyUserMapper midjourneyUserMapper;
+
+    private final HttpServletRequest request;
+
+    private final MidjourneyService midjourneyService;
+
+    private final BeanSearcher beanSearcher;
+
+    public MidjourneyUser getUser(){
+        return midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
+                .eq(MidjourneyUser::getUserToken, request.getHeader("user-token")).last("limit 1"));
+    }
+
+
+    /**
+     * 检查用户fast次数
+     */
+    public void checkUserFast(MidjourneyUser user){
+       if (user.getMode() == 1){
+           if (user.getMjFastNum() < 0 || user.getExpireTime().before(new Date())) {
+               user.setMode(2);
+               midjourneyUserMapper.updateById(user);
+           }
+       }
+    }
+
+
+
+    /**
+     * 提交Imagine任务
+     */
+    @PostMapping("/submit/imagine")
+    public Result<MidjourneyUserConversation> submitImagine(SubmitImagineDTO submitImagineDTO){
+        log.info("提交Imagine任务,提示:{},base64数组长度:{}",submitImagineDTO.getPrompt(),submitImagineDTO.getBase64Array().size());
+        MidjourneyUser user = getUser();
+        checkUserFast(user);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyService.submitImagine(user,submitImagineDTO.getPrompt(),submitImagineDTO.getBase64Array()));
+    }
+
+    /**
+     * 提交Describe任务
+     */
+    @PostMapping("/submit/describe")
+    public Result<MidjourneyUserConversation> submitDescribe(SubmitDescribeDTO submitDescribeDTO){
+        log.info("提交Describe任务");
+        MidjourneyUser user = getUser();
+        checkUserFast(user);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyService.submitDescribe(user,submitDescribeDTO.getBase64()));
+    }
+
+    /**
+     * 提交Blend任务
+     */
+    @PostMapping("/submit/blend")
+    public Result<MidjourneyUserConversation> submitBlend(SubmitBlendDTO submitBlendDTO) {
+        log.info("提交Blend任务 dimensions:{},base64数组长度:{}", submitBlendDTO.getDimensions(), submitBlendDTO.getBase64Array().size());
+        MidjourneyUser user = getUser();
+        checkUserFast(user);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyService.submitBlend(user, submitBlendDTO.getDimensions(), submitBlendDTO.getBase64Array()));
+    }
+
+    /**
+     * 提交Modal任务
+     */
+    @PostMapping("/submit/modal")
+    public Result<MidjourneyUserConversation> submitModal(SubmitModalDTO submitModalDTO){
+        log.info("提交Modal任务,taskId:{},提示:{},base64数组长度:{}",submitModalDTO.getTaskId(),submitModalDTO.getPrompt(),submitModalDTO.getMaskBase64().length());
+        MidjourneyUser user = getUser();
+        checkUserFast(user);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyService.submitModal(user,submitModalDTO.getTaskId(),submitModalDTO.getPrompt(),submitModalDTO.getMaskBase64()));
+    }
+
+    /**
+     * 提交Shorten任务
+     */
+    @PostMapping("/submit/shorten")
+    public Result<MidjourneyUserConversation> submitShorten(SubmitShortenDTO submitShortenDTO){
+        log.info("提交Shorten任务 提示词:{}",submitShortenDTO.getPrompt());
+        MidjourneyUser user = getUser();
+        checkUserFast(user);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyService.submitShorten(user,submitShortenDTO.getPrompt()));
+    }
+
+    /**
+     * 执行动作
+     */
+    @PostMapping("/submit/action")
+    public Result<MidjourneyUserConversation> action(SubmitActionDTO actionDTO){
+        log.info("任务id:{},执行动作:{}",actionDTO.getTaskId(),actionDTO.getCustomId());
+        MidjourneyUser user = getUser();
+        checkUserFast(user);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyService.submitAction(user,actionDTO.getTaskId(), actionDTO.getCustomId()));
+    }
+
+
+    /**
+     * 查询会话列表
+     */
+    @GetMapping("/conversation/list")
+    public Result<SearchResult<MidjourneyUserConversation>> conversationList(){
+        MidjourneyUser user = getUser();
+        log.info("查询会话列表 userId:{}",user.getId());
+        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(beanSearcher.search(MidjourneyUserConversation.class,
+                builder.field(MidjourneyUserConversation::getUserId, user.getId()).build()));
+    }
+
+    /**
+     * 根据ids查询会话
+     */
+    @GetMapping("/conversation/listByIds")
+    public Result<List<MidjourneyUserConversation>> conversationListByIds(@RequestParam(value = "ids" ) List<Long> ids){
+        log.info("根据ids查询会话");
+        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyService.listConversationByIds(ids));
+    }
+
+    /**
+     * 取消任务
+     */
+    @PostMapping("/conversation/{id}/cancel")
+    public Result<MidjourneyUserConversation> conversationCancel(@PathVariable("id") Long id){
+        MidjourneyUser user = getUser();
+        log.info("取消任务 id:{}",id);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyService.cancelConversation(user,id));
+    }
+}

+ 13 - 0
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java

@@ -14,6 +14,7 @@ import com.cyksj.model.views.ChatGptUserConversationRecordHistoryView;
 import com.cyksj.model.views.ChatGptUserView;
 import com.cyksj.model.views.ChatgptCarInfoView;
 import com.cyksj.service.chatgpt.ChatGptAccountService;
+import com.cyksj.service.midjourney.MidjourneyAccountService;
 import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
@@ -53,6 +54,8 @@ public class MirrorController {
 
     private final BeanSearcher beanSearcher;
 
+    private final MidjourneyAccountService midjourneyAccountService;
+
 
     /**
      * GPT车票跳转登录
@@ -291,4 +294,14 @@ public class MirrorController {
 
 
 
+    /**
+     * MJ车票跳转登录
+     *
+     * @param relationId 车票id
+     */
+    @GetMapping("/midjourneyMirror/{relationId}")
+    public Result<String> midjourneyMirror(@PathVariable Long relationId) throws IOException {
+        Long userId = StpUserUtil.getLoginIdAsLong();
+        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyAccountService.getLoginUrl(userId, relationId));
+    }
 }

+ 19 - 0
netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

@@ -167,6 +167,25 @@ public class OrderController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon);
     }
 
+    /**
+     * 套餐提交支付
+     */
+    @PostMapping("/post/submit")
+    public Result<UpgradeOrderDon> submitUpgrade(@Validated @RequestBody OrderPayRequest payRequest) throws Exception {
+        final String methodName = "套餐吊起支付";
+        Long userId = StpUserUtil.getUserIdAfterLogin();
+        payRequest.setUserId(userId);
+        log.info("{}[start] params:{}", methodName, payRequest);
+
+        String ip = ServletUtil.getClientIP(request);
+
+        payRequest.setIp(ip);
+
+        UpgradeOrderDon orderDon = orderDonService.submitUpgrade(payRequest);
+
+        return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon);
+    }
+
     /**
      * 0元订单确认
      */