diff --git a/src/main/java/com/ai/da/common/RabbitMQ/GenerateConsumer.java b/src/main/java/com/ai/da/common/RabbitMQ/GenerateConsumer.java index 58f9435a..f9edde27 100644 --- a/src/main/java/com/ai/da/common/RabbitMQ/GenerateConsumer.java +++ b/src/main/java/com/ai/da/common/RabbitMQ/GenerateConsumer.java @@ -1,11 +1,13 @@ package com.ai.da.common.RabbitMQ; import com.ai.da.common.config.exception.BusinessException; +import com.ai.da.common.constant.CommonConstant; import com.ai.da.common.utils.RedisUtil; import com.ai.da.model.dto.GenerateThroughImageTextDTO; -import com.ai.da.model.vo.GenerateCollectionVO; +import com.ai.da.model.vo.GenerateResultVO; import com.ai.da.service.GenerateService; import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; import com.rabbitmq.client.Channel; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.Message; @@ -17,7 +19,7 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.io.IOException; import java.util.HashMap; -import java.util.Objects; +import java.util.Map; @Slf4j @@ -42,6 +44,9 @@ public class GenerateConsumer { @Value("${redis.key.resultMap}") private String resultMapKey; + @Value("${redis.key.generateResult}") + private String generateResultKey; + public void generate(Message msg, Channel channel, String consumerName) { log.info("============start listening=========="); long start = System.currentTimeMillis(); @@ -63,20 +68,16 @@ public class GenerateConsumer { // 2.2 将该消息从取消列表中删除 // redisUtil.removeFromSet(cancelSetKey, uniqueId); } else { - /*try { - Thread.sleep(15000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - }*/ - GenerateCollectionVO generateCollectionVO = generateService.generateThroughImageText(generateThroughImageTextDTO); +// GenerateCollectionVO generateCollectionVO = generateService.generateThroughImageText(generateThroughImageTextDTO); + generateService.generateThroughImageText(generateThroughImageTextDTO); // 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除 redisUtil.removeFromZSet(consumptionOrderKey, uniqueId); - if (!Objects.isNull(generateCollectionVO)) { + /*if (!Objects.isNull(generateCollectionVO)) { HashMap generateResult = new HashMap<>(); generateResult.put(uniqueId, JSONObject.toJSONString(generateCollectionVO)); // 将结果存在redis中 ,为空时不要存 redisUtil.addToMap(resultMapKey, generateResult); - } + }*/ } } catch (BusinessException e) { @@ -87,6 +88,9 @@ public class GenerateConsumer { channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false); // 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除 redisUtil.removeFromZSet(consumptionOrderKey, uniqueId); + String key = generateResultKey + ":" + uniqueId; + GenerateResultVO generateResultVO = new GenerateResultVO(generateThroughImageTextDTO.getUniqueId(), null, null, "Fail"); + redisUtil.addToString(key, new Gson().toJson(generateResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); } catch (IOException exception) { log.error("手动确认,取消返回队列,不再重新消费"); } @@ -104,6 +108,54 @@ public class GenerateConsumer { log.info("=============end listening==========="); } + public void processGenerateResult(Message msg, Channel channel) { + log.info("============ProcessGenerateResult listening=========="); + long start = System.currentTimeMillis(); + + Map generateResult = JSONObject.parseObject(msg.getBody(), Map.class); + log.info("generate response : {}", generateResult); + + try { + log.info("tasks_id : {} start ", generateResult.get("tasks_id")); + if (generateResult.get("status").equals("SUCCESS")) { + String url = generateResult.get("image_url"); + String taskId = generateResult.get("tasks_id"); + String category = generateResult.get("category"); + generateService.processGenerateResult(taskId, url, category); + } else { + // 修改redis中的数据状态为exception + String key = generateResultKey + ":" + generateResult.get("tasks_id"); + redisUtil.addToString(key, new Gson().toJson(new GenerateResultVO(generateResult.get("tasks_id"), null, null, "Fail")), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); + // 将异常信息存到exception中 + HashMap exceptionInfo = new HashMap<>(); + exceptionInfo.put(generateResult.get("tasks_id"), generateResult.get("data")); + // 存redis + redisUtil.addToMap(exceptionMapKey, exceptionInfo); + } + } catch (Exception e) { + log.error(e.getMessage()); + try { + channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false); + // 将消息从redis排队队列中删除,需保证被消费的消息存储到db之后再从redis删除 + redisUtil.removeFromZSet(consumptionOrderKey, generateResult.get("tasks_id")); + } catch (IOException exception) { + log.error("手动确认,取消返回队列,不再重新消费"); + } + // 将入参和错误信息存入数据库 + String exceptionMessage = JSONObject.toJSONString(generateResult) + + " Exception message : " + e.getMessage(); + HashMap exceptionInfo = new HashMap<>(); + exceptionInfo.put(String.valueOf(generateResult.get("tasks_id")), exceptionMessage); + // 存redis + redisUtil.addToMap(exceptionMapKey, exceptionInfo); + } + + long end = System.currentTimeMillis(); + log.info("tasks_id : {}, end , message : {}, 执行时长: {} 毫秒", generateResult.get("tasks_id"), generateResult.get("message"), (end - start)); + log.info("============ProcessGenerateResult End listening=========="); + + } + @RabbitListener(queues = MQConfig.GENERATE_QUEUE) @RabbitHandler public void generateConsumer1(Message msg, Channel channel) { @@ -158,4 +210,9 @@ public class GenerateConsumer { generate(msg, channel, "consumer 9"); } + @RabbitListener(queues = MQConfig.GENERATE_RESULT_QUEUE) + @RabbitHandler + public void getGenerateResult(Message msg, Channel channel) { + processGenerateResult(msg, channel); + } } diff --git a/src/main/java/com/ai/da/common/RabbitMQ/MQConfig.java b/src/main/java/com/ai/da/common/RabbitMQ/MQConfig.java index 79ecda25..e9df0264 100644 --- a/src/main/java/com/ai/da/common/RabbitMQ/MQConfig.java +++ b/src/main/java/com/ai/da/common/RabbitMQ/MQConfig.java @@ -10,15 +10,18 @@ public class MQConfig { public static final String GENERATE_EXCHANGE_FANOUT = "generate-exchange"; // public static final String GENERATE_QUEUE = "generate-queue-prod"; // public static final String GENERATE_QUEUE = "generate-queue-test"; +// public static final String GENERATE_QUEUE = "generate-queue-local"; public static final String GENERATE_QUEUE = "generate-queue-dev"; -// public static final String GENERATE_QUEUE = "generate-queue"; - public static final String SR_QUEUE = "SR-queue-dev"; // public static final String SR_QUEUE = "SR-queue-local"; + public static final String SR_QUEUE = "SR-queue-dev"; - // public static final String SR_RESULT_QUEUE = "SuperResolution-local"; +// public static final String SR_RESULT_QUEUE = "SuperResolution-local"; public static final String SR_RESULT_QUEUE = "SuperResolution-dev"; +// public static final String GENERATE_RESULT_QUEUE = "GenerateImage-local"; + public static final String GENERATE_RESULT_QUEUE = "GenerateImage-dev"; + public MQConfig() { } diff --git a/src/main/java/com/ai/da/common/RabbitMQ/MQPublisher.java b/src/main/java/com/ai/da/common/RabbitMQ/MQPublisher.java index 8afffa29..5cffa019 100644 --- a/src/main/java/com/ai/da/common/RabbitMQ/MQPublisher.java +++ b/src/main/java/com/ai/da/common/RabbitMQ/MQPublisher.java @@ -10,7 +10,7 @@ import javax.annotation.Resource; @Component public class MQPublisher { - private final String url = "http://localhost:15672/api/queues/%2f/generate-queue"; +// private final String url = "http://localhost:15672/api/queues/%2f/generate-queue"; @Resource private AmqpTemplate amqpTemplate; diff --git a/src/main/java/com/ai/da/common/RabbitMQ/SRConsumer.java b/src/main/java/com/ai/da/common/RabbitMQ/SRConsumer.java index 059b4f81..6ad261bd 100644 --- a/src/main/java/com/ai/da/common/RabbitMQ/SRConsumer.java +++ b/src/main/java/com/ai/da/common/RabbitMQ/SRConsumer.java @@ -87,14 +87,31 @@ public class SRConsumer { superResolutionDTO = JSONObject.parseObject(msg.getBody(), SuperResolutionDTO.class); // channel.basicNack() 为不确认deliveryTag对应的消息,第二个参数是否应用于多消息,第三个参数是否requeue setErrorMessage(msg, channel, e.getMsg(), superResolutionDTO); + try { + // 2.1 手动确认该消息 + channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false); + } catch (IOException ex) { + log.error("手动确认,不返回队列重新消费, error message : " + e.getMessage()); + } } catch (JSONException e) { log.error(e.getMessage()); setErrorMessage(msg, channel, e.getMessage(), null); + try { + // 2.1 手动确认该消息 + channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false); + } catch (IOException ex) { + log.error("手动确认,不返回队列重新消费, error message : " + e.getMessage()); + } } catch (Exception e) { log.error(e.getMessage()); superResolutionDTO = JSONObject.parseObject(msg.getBody(), SuperResolutionDTO.class); setErrorMessage(msg, channel, e.getMessage(), superResolutionDTO); - + try { + // 2.1 手动确认该消息 + channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false); + } catch (IOException ex) { + log.error("手动确认,不返回队列重新消费, error message : " + e.getMessage()); + } } long end = System.currentTimeMillis(); @@ -115,17 +132,31 @@ public class SRConsumer { try { result = JSONObject.parseObject(msg.getBody(), JSONObject.class); + log.info("SR response : {}", result); taskId = result.get("tasks_id").toString(); } catch (JSONException e) { log.error("SRResult 返回数据格式不合规范"); log.error(e.getMessage()); setErrorMessage(msg, channel, e.getMessage(), null); + try { + // 第二个参数,是否批量确认消息,当传false时,只确认当前 deliveryTag对应的消息;当传true时,会确认当前及之前所有未确认的消息。 + channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false); + } catch (IOException exception) { + log.error("手动确认,取消返回队列,不再重新消费"); + } + } catch (Exception e){ + log.error(e.getMessage()); + setErrorMessage(msg, channel, e.getMessage(), null); + try { + // 第二个参数,是否批量确认消息,当传false时,只确认当前 deliveryTag对应的消息;当传true时,会确认当前及之前所有未确认的消息。 + channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false); + } catch (IOException exception) { + log.error("手动确认,取消返回队列,不再重新消费"); + } } try { -// channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false); - // 2、判断状态是否成功 if ("SUCCESS".equals(result.get("status").toString())) { String output = result.get("data").toString(); diff --git a/src/main/java/com/ai/da/common/config/PrimaryDataSourceConfig.java b/src/main/java/com/ai/da/common/config/PrimaryDataSourceConfig.java index c12182db..44a4540b 100644 --- a/src/main/java/com/ai/da/common/config/PrimaryDataSourceConfig.java +++ b/src/main/java/com/ai/da/common/config/PrimaryDataSourceConfig.java @@ -1,11 +1,14 @@ package com.ai.da.common.config; +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties; +import com.baomidou.mybatisplus.core.config.GlobalConfig; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; @@ -19,6 +22,8 @@ import javax.sql.DataSource; @Configuration @MapperScan(basePackages = "com.ai.da.mapper.primary", sqlSessionFactoryRef = "primarySqlSessionFactory") public class PrimaryDataSourceConfig { + @Autowired + private MybatisPlusProperties mybatisPlusProperties; @Primary @Bean(name = "primaryDataSource") @@ -36,6 +41,11 @@ public class PrimaryDataSourceConfig { MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(applicationContext.getResources("classpath:mapper/primary/*.xml")); + // 设置 MyBatis Plus 全局配置 + GlobalConfig globalConfig = this.mybatisPlusProperties.getGlobalConfig(); + if (globalConfig != null) { + bean.setGlobalConfig(globalConfig); + } bean.setPlugins(mybatisPlusInterceptor); return bean.getObject(); } diff --git a/src/main/java/com/ai/da/common/constant/CommonConstant.java b/src/main/java/com/ai/da/common/constant/CommonConstant.java new file mode 100644 index 00000000..ac139e98 --- /dev/null +++ b/src/main/java/com/ai/da/common/constant/CommonConstant.java @@ -0,0 +1,14 @@ +package com.ai.da.common.constant; + +public class CommonConstant { + // 单位 秒 10分钟过期 +// public static final Long TASK_EXPIRE_TIME = 24 * 60 * 60L; + public static final Long TASK_EXPIRE_TIME = 10 * 60L; + // 单位 秒 两天过期 + public static final Long CREDITS_EXPIRE_TIME = 2 * 24 * 60 * 60L; + // 单位 分钟 + public static final Integer MINIO_IMAGE_EXPIRE_TIME = 24 * 60; + // 单位 秒 一天过期 in redis + public static final Long GENERATE_RESULT_EXPIRE_TIME = 24 * 60 * 60L; + +} diff --git a/src/main/java/com/ai/da/common/constant/PayPalCheckoutConstant.java b/src/main/java/com/ai/da/common/constant/PayPalCheckoutConstant.java index 31cc4adf..21b3694b 100644 --- a/src/main/java/com/ai/da/common/constant/PayPalCheckoutConstant.java +++ b/src/main/java/com/ai/da/common/constant/PayPalCheckoutConstant.java @@ -2,9 +2,6 @@ package com.ai.da.common.constant; public class PayPalCheckoutConstant { -// public static String MODE = "sandbox"; - public static String MODE = "live"; - public static final String CAPTURE = "CAPTURE"; /** * 该标签将覆盖PayPal网站上PayPal帐户中的公司名称 @@ -168,12 +165,6 @@ public class PayPalCheckoutConstant { public final static String CMD_NOTIFY_VALIDATE = "_notify-validate"; -// public final static String WEBHOOK_ID = "31797347YC028794L"; - // kim-sandbox -// public final static String WEBHOOK_ID = "1WH327112B602422N"; - // kim-live - public final static String WEBHOOK_ID = "41L14847MC833625B"; - public final static String PAYPAL_TOKEN_KEY = "PayPalAccessToken"; diff --git a/src/main/java/com/ai/da/common/enums/CreditsEventsEnum.java b/src/main/java/com/ai/da/common/enums/CreditsEventsEnum.java index 23566466..8a63d880 100644 --- a/src/main/java/com/ai/da/common/enums/CreditsEventsEnum.java +++ b/src/main/java/com/ai/da/common/enums/CreditsEventsEnum.java @@ -7,18 +7,18 @@ import lombok.Getter; @Getter public enum CreditsEventsEnum { - PRICE("price","1"), - // 6USD -> 1000 points ==> 10HKD -> 215 points ==> 2HKD -> 43points - BUY_CREDITS("Buy Credits","43"), + PRICE("price","6"), - INIT("init", "1000"), + BUY_CREDITS("Buy Credits","600"), - DAILY_CHECKIN("Daily Check-In", "50"), + INIT("init", "500"), - SOCIAL_MEDIA_SHARING("Social Media Sharing","50"), + DAILY_CHECKIN("Daily Check-In", "20"), + + SOCIAL_MEDIA_SHARING("Social Media Sharing","20"), // SUPER_RESOLUTION("Super Resolution","300"), - SUPER_RESOLUTION("Super Resolution","30"), + SUPER_RESOLUTION("Super Resolution","5"), OTHER("Other","10"); diff --git a/src/main/java/com/ai/da/common/enums/GenerateModeEnum.java b/src/main/java/com/ai/da/common/enums/GenerateModeEnum.java index 44409731..f3cc14e9 100644 --- a/src/main/java/com/ai/da/common/enums/GenerateModeEnum.java +++ b/src/main/java/com/ai/da/common/enums/GenerateModeEnum.java @@ -12,26 +12,33 @@ public enum GenerateModeEnum { /** * 通过文本生成 */ - TEXT(1, "text"), + TEXT(1, "text","txt2img"), /** * 通过图片生成 */ - IMAGE(2, "image"), + IMAGE(2, "image", "img2img"), /** * 通过文本和图片生成 */ - TEXT_IMAGE(2, "text-image"); + TEXT_IMAGE(2, "text-image","img2img"); private Integer code; private String value; + private String type; GenerateModeEnum(int code, String value) { this.code = code; this.value = value; } + GenerateModeEnum(Integer code, String value, String type) { + this.code = code; + this.value = value; + this.type = type; + } + public static List getGenerateModeList(){ return Stream.of(TEXT,IMAGE,TEXT_IMAGE).map(GenerateModeEnum::getValue).collect(Collectors.toList()); } diff --git a/src/main/java/com/ai/da/common/enums/OrderStatusEnum.java b/src/main/java/com/ai/da/common/enums/OrderStatusEnum.java index 559ae38b..aac9719d 100644 --- a/src/main/java/com/ai/da/common/enums/OrderStatusEnum.java +++ b/src/main/java/com/ai/da/common/enums/OrderStatusEnum.java @@ -40,7 +40,12 @@ public enum OrderStatusEnum { /** * 退款异常 */ - REFUND_ABNORMAL("退款异常"); + REFUND_ABNORMAL("退款异常"), + + /** + * paypal订单状态为 APPROVED + */ + ORDER_PROCESSING("订单处理中"); /** * 类型 diff --git a/src/main/java/com/ai/da/common/enums/PayPalOrderStatusEnum.java b/src/main/java/com/ai/da/common/enums/PayPalOrderStatusEnum.java index f35fd8f8..f9735c05 100644 --- a/src/main/java/com/ai/da/common/enums/PayPalOrderStatusEnum.java +++ b/src/main/java/com/ai/da/common/enums/PayPalOrderStatusEnum.java @@ -7,18 +7,24 @@ import lombok.Getter; @AllArgsConstructor public enum PayPalOrderStatusEnum { + // The order was created with the specified context. + // 订单已创建并具有指定的上下文。 CREATED("CREATED"), - + // The order was saved and persisted. The order status continues to be in progress until a capture is made with final_capture = true for all purchase units within the order. + // 订单已保存并持久化。订单状态仍处于进行中,直到对订单中的所有购买单元进行了 final_capture = true 的捕获为止 SAVED("SAVED"), - + // The customer approved the payment through the PayPal wallet or another form of guest or unbranded payment. For example, a card, bank account, or so on. + // 客户通过PayPal钱包或其他形式的游客或非品牌支付批准了付款。例如,信用卡、银行账户等。 APPROVED("APPROVED"), - + // All purchase units in the order are voided. + // 订单中的所有购买单元都已作废。 VOIDED("VOIDED"), - + // The payment was authorized or the authorized payment was captured for the order. + // 订单的支付已被授权或已捕获授权的支付。 COMPLETED("COMPLETED"), - + // The order requires an action from the payer (e.g. 3DS authentication). Redirect the payer to the "rel":"payer-action" HATEOAS link returned as part of the response prior to authorizing or capturing the order. + // 订单需要支付者执行某项操作(例如3DS身份验证)。在授权或捕获订单之前,请将支付者重定向到响应中返回的"rel":"payer-action" HATEOAS链接。 PAYER_ACTION_REQUIRED("PAYER_ACTION_REQUIRED"); - private final String status; } diff --git a/src/main/java/com/ai/da/common/security/filter/AuthenticationFilter.java b/src/main/java/com/ai/da/common/security/filter/AuthenticationFilter.java index 8ae7a2a1..9e404107 100644 --- a/src/main/java/com/ai/da/common/security/filter/AuthenticationFilter.java +++ b/src/main/java/com/ai/da/common/security/filter/AuthenticationFilter.java @@ -7,6 +7,7 @@ import com.ai.da.common.security.jwt.JWTTokenHelper; import com.ai.da.common.utils.LocalCacheUtils; import com.ai.da.common.utils.MultiReadHttpServletRequest; import com.ai.da.common.utils.MultiReadHttpServletResponse; +import com.ai.da.common.utils.RequestInfoUtil; import com.ai.da.model.vo.AuthPrincipalVo; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Configuration; @@ -91,6 +92,8 @@ public class AuthenticationFilter extends OncePerRequestFilter { log.debug("后台检查令牌:{}", jwtToken); if (StrUtil.isBlank(jwtToken)) { + String ipAddress = RequestInfoUtil.getIpAddress(request); + log.info("本次请求的ip为 : " + ipAddress); throw new RuntimeException("请传入token!"); } if(jwtToken.equals("Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIyIiwic3ViIjoie1wiaWRcIjoyLFwidXNlcm5hbWVcIjpcImxpcnNcIn0iLCJpYXQiOjE2NjU3NDEwODcsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE2NzQzODEwODd9.ShM9R_NNFD7oo1OvxrEgg7PFeWinOuAKkuInUCMQupp66s64Hhv8tN0Wwr83nIN4rHPqtn95wmd4msWcvaFYJA")){ diff --git a/src/main/java/com/ai/da/common/task/AliPayTask.java b/src/main/java/com/ai/da/common/task/AliPayTask.java index 64b0e81c..fa9a9b3a 100644 --- a/src/main/java/com/ai/da/common/task/AliPayTask.java +++ b/src/main/java/com/ai/da/common/task/AliPayTask.java @@ -24,10 +24,10 @@ public class AliPayTask { /** * 从第0秒开始每隔30秒执行1次,查询创建超过5分钟,并且未支付的订单 */ - @Scheduled(cron = "0/30 * * * * ?") +// @Scheduled(cron = "0/30 * * * * ?") public void orderConfirm(){ - log.info("orderConfirm 被执行......"); + log.info("Alipay orderConfirm 被执行......"); List orderInfoList = orderInfoService.getNoPayOrderByDuration(5, PayTypeEnum.ALIPAY.getType()); diff --git a/src/main/java/com/ai/da/common/task/PaypalTask.java b/src/main/java/com/ai/da/common/task/PaypalTask.java new file mode 100644 index 00000000..bc0e24dd --- /dev/null +++ b/src/main/java/com/ai/da/common/task/PaypalTask.java @@ -0,0 +1,42 @@ +package com.ai.da.common.task; + +import com.ai.da.common.enums.PayTypeEnum; +import com.ai.da.mapper.primary.entity.OrderInfo; +import com.ai.da.service.OrderInfoService; +import com.ai.da.service.PayPalCheckoutService; +import com.paypal.http.exceptions.SerializeException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +@Slf4j +@Component +public class PaypalTask { + + @Resource + private OrderInfoService orderInfoService; + + @Resource + private PayPalCheckoutService payPalCheckoutService; + + @Scheduled(cron = "0/30 * * * * ?") + public void orderConfirm() throws SerializeException { + + log.info("PayPal orderConfirm 被执行......"); + + List orderInfoList = orderInfoService.getNoPayOrderByDuration(5, PayTypeEnum.PAYPAL.getType()); + + for (OrderInfo orderInfo : orderInfoList) { + String orderNo = orderInfo.getOrderNo(); + log.warn("超时订单 ===> {}", orderNo); + + //核实订单状态:调用支付宝查单接口 + payPalCheckoutService.checkOrderStatus(orderNo); + + } + } +} diff --git a/src/main/java/com/ai/da/common/utils/AsyncCallerUtil.java b/src/main/java/com/ai/da/common/utils/AsyncCallerUtil.java index 29801a6b..40ae25db 100644 --- a/src/main/java/com/ai/da/common/utils/AsyncCallerUtil.java +++ b/src/main/java/com/ai/da/common/utils/AsyncCallerUtil.java @@ -25,7 +25,8 @@ public class AsyncCallerUtil { } public CompletableFuture> callGenerateAsync(GenerateToPythonDTO generateToPython) { - return CompletableFuture.supplyAsync(() -> pythonService.generateSketchOrPrint(generateToPython)); +// return CompletableFuture.supplyAsync(() -> pythonService.generateSketchOrPrint(generateToPython)); + return null; } public List generate(GenerateToPythonDTO generateToPython) { diff --git a/src/main/java/com/ai/da/common/utils/RedisUtil.java b/src/main/java/com/ai/da/common/utils/RedisUtil.java index 9fa37738..ef67de8f 100644 --- a/src/main/java/com/ai/da/common/utils/RedisUtil.java +++ b/src/main/java/com/ai/da/common/utils/RedisUtil.java @@ -136,6 +136,10 @@ public class RedisUtil { } //- - - - - - - - - - - - - - - - - - - - - String类型 - - - - - - - - - - - - - - - - - - - - + public void addToString(String key, String value){ + redisTemplate.opsForValue().set(key,value); + } + public void addToString(String key, String value, Long expiresIn){ redisTemplate.opsForValue().set(key,value,expiresIn, TimeUnit.SECONDS); } @@ -156,4 +160,8 @@ public class RedisUtil { return redisTemplate.getExpire(key); } + public void removeFromString(String key){ + redisTemplate.delete(key); + } + } diff --git a/src/main/java/com/ai/da/controller/ConvenientInquiryController.java b/src/main/java/com/ai/da/controller/ConvenientInquiryController.java index 1cc2552a..4b4526bd 100644 --- a/src/main/java/com/ai/da/controller/ConvenientInquiryController.java +++ b/src/main/java/com/ai/da/controller/ConvenientInquiryController.java @@ -7,12 +7,15 @@ import com.ai.da.mapper.primary.DesignMapper; import com.ai.da.mapper.primary.TrialOrderMapper; import com.ai.da.mapper.primary.entity.TrialOrder; import com.ai.da.model.dto.UserDesignStatisticDTO; +import io.netty.util.internal.StringUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.List; @Api(tags = "便利查询") @@ -31,7 +34,7 @@ public class ConvenientInquiryController { @GetMapping("/getTrial") public Response> getTrial(){ Long accountId = UserContext.getUserHolder().getId(); - if (accountId.equals(31L) || accountId.equals(87L) || accountId.equals(83L)){ + if (accountId.equals(31L) || accountId.equals(87L) || accountId.equals(83L) || accountId.equals(6L) || accountId.equals(4L) || accountId.equals(73L)){ List trialOrders = trialOrderMapper.selectList(null); return Response.success(trialOrders); }else { @@ -43,7 +46,13 @@ public class ConvenientInquiryController { @GetMapping("/getDesignStatistic") public Response> getDesignStatistic(@RequestParam String startTime,@RequestParam String endTime){ Long accountId = UserContext.getUserHolder().getId(); - if (accountId.equals(31L) || accountId.equals(87L) || accountId.equals(83L)){ + if (accountId.equals(31L) || accountId.equals(87L) || accountId.equals(83L) || accountId.equals(6L) || accountId.equals(4L) || accountId.equals(73L)){ + if (StringUtil.isNullOrEmpty(startTime)) startTime = "2024-02-01 00:00:00"; + if (StringUtil.isNullOrEmpty(endTime)){ + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + Date date = new Date(); + endTime = simpleDateFormat.format(date); + } List designStatistic = designMapper.getDesignStatistic(startTime, endTime); return Response.success(designStatistic); }else { diff --git a/src/main/java/com/ai/da/controller/GenerateController.java b/src/main/java/com/ai/da/controller/GenerateController.java index c752fbc0..4e1566dd 100644 --- a/src/main/java/com/ai/da/controller/GenerateController.java +++ b/src/main/java/com/ai/da/controller/GenerateController.java @@ -3,10 +3,7 @@ package com.ai.da.controller; import com.ai.da.common.response.Response; import com.ai.da.model.dto.GenerateLikeDTO; import com.ai.da.model.dto.GenerateThroughImageTextDTO; -import com.ai.da.model.vo.GenerateCaptionVO; -import com.ai.da.model.vo.GenerateCollectionVO; -import com.ai.da.model.vo.GenerateLikeVO; -import com.ai.da.model.vo.PrepareForGenerateVO; +import com.ai.da.model.vo.*; import com.ai.da.service.GenerateService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -16,6 +13,7 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; +import java.util.List; /** * @author XP @@ -35,11 +33,12 @@ public class GenerateController { return Response.success(generateService.generateCaption(sketchElementId)); } - @ApiOperation("通过文字、图片生成图片") + /*@ApiOperation("通过文字、图片生成图片") @PostMapping("/sketchAndPrint") - public Response generateThroughImageText(@Valid @RequestBody GenerateThroughImageTextDTO generateThroughImageTextDTO) { - return Response.success(generateService.generateThroughImageText(generateThroughImageTextDTO)); - } + public void generateThroughImageText(@Valid @RequestBody GenerateThroughImageTextDTO generateThroughImageTextDTO) { +// return Response.success(generateService.generateThroughImageText(generateThroughImageTextDTO)); + generateService.generateThroughImageText(generateThroughImageTextDTO); + }*/ @ApiOperation("喜欢生成的图片") @PostMapping("/like") @@ -63,16 +62,25 @@ public class GenerateController { @ApiOperation(value = "取消继续生成") @GetMapping("/stopWaiting") public Response stopWaiting(@RequestParam("userId") Long userId, - @RequestParam("uniqueId") String uniqueId, + @RequestParam("uniqueId") List uniqueId, @RequestParam("timeZone") String timeZone) { generateService.cancelGenerate(userId, uniqueId, timeZone); return Response.success("stop waiting successfully"); } - @ApiOperation(value = "获取生成结果") + /*@ApiOperation(value = "获取生成结果") @GetMapping("/result") public Response getGenerateResult(@RequestParam("uniqueId") String uniqueId) { GenerateCollectionVO generateResult = generateService.getGenerateResult(uniqueId); return Response.success(generateResult); + }*/ + + @ApiOperation(value = "获取生成结果") + @PostMapping("/result") + public Response> getGenerateResults(@Valid @RequestBody List taskIdList) { + List generateResult = generateService.getGenerateResultList(taskIdList); + return Response.success(generateResult); } + + } diff --git a/src/main/java/com/ai/da/controller/PayPalCheckoutController.java b/src/main/java/com/ai/da/controller/PayPalCheckoutController.java index 2ed119a7..203da0e7 100644 --- a/src/main/java/com/ai/da/controller/PayPalCheckoutController.java +++ b/src/main/java/com/ai/da/controller/PayPalCheckoutController.java @@ -1,7 +1,6 @@ package com.ai.da.controller; import com.ai.da.common.response.Response; -import com.ai.da.service.CallBackService; import com.ai.da.service.PayPalCheckoutService; import com.paypal.http.HttpResponse; import com.paypal.http.exceptions.SerializeException; @@ -46,8 +45,8 @@ public class PayPalCheckoutController { @ApiOperation(value = "查询指定订单") @PostMapping(value = "/trade/query/{orderNo}") - public Response queryOrder(@PathVariable String orderNo) throws SerializeException { - String s = payPalCheckoutService.queryOrder(orderNo); + public Response queryOrder(@PathVariable String orderNo) throws SerializeException { + Order s = payPalCheckoutService.queryOrder(orderNo); return Response.success(s); } @@ -61,7 +60,6 @@ public class PayPalCheckoutController { }else { return Response.fail("Request for refund failed."); } - } @ApiOperation("执行扣款") @@ -70,8 +68,5 @@ public class PayPalCheckoutController { Order response = payPalCheckoutService.captureOrder(orderNo); return Response.success(response); } - - - } diff --git a/src/main/java/com/ai/da/controller/ThirdPartyController.java b/src/main/java/com/ai/da/controller/ThirdPartyController.java index 2572ed5b..7132d9b2 100644 --- a/src/main/java/com/ai/da/controller/ThirdPartyController.java +++ b/src/main/java/com/ai/da/controller/ThirdPartyController.java @@ -42,8 +42,8 @@ public class ThirdPartyController { @CrossOrigin @ApiOperation(value = "Add user information") @PostMapping("/addTrialUser") - public Response addTrialUser(@RequestBody AccountTrialDTO accountTrialDTO) { - return Response.success(accountService.addTrialUser(accountTrialDTO)); + public Response addTrialUser(@RequestBody AccountTrialDTO accountTrialDTO, HttpServletRequest request) { + return Response.success(accountService.addTrialUser(accountTrialDTO, request)); } @CrossOrigin diff --git a/src/main/java/com/ai/da/mapper/primary/entity/Generate.java b/src/main/java/com/ai/da/mapper/primary/entity/Generate.java index 8da4dbcb..d58d72ec 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/Generate.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/Generate.java @@ -37,10 +37,15 @@ public class Generate { */ private String level1Type; + /** + * 图片来源 collection | library + */ + private String elementSource; + /** * 关联collection element id */ - private Long collectionElementId; + private Long elementId; /** * caption的内容 diff --git a/src/main/java/com/ai/da/mapper/primary/entity/GenerateDetail.java b/src/main/java/com/ai/da/mapper/primary/entity/GenerateDetail.java index b016e7fa..6cf9f0b3 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/GenerateDetail.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/GenerateDetail.java @@ -8,6 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.time.LocalDateTime; import java.util.Date; @Data @@ -50,7 +51,7 @@ public class GenerateDetail { /** * 创建时间 */ - private Date createDate; + private LocalDateTime createDate; /** * 更新时间 diff --git a/src/main/java/com/ai/da/mapper/primary/entity/Product.java b/src/main/java/com/ai/da/mapper/primary/entity/Product.java index de2df0cf..ddea327e 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/Product.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/Product.java @@ -10,4 +10,6 @@ public class Product extends BaseEntity{ private String title; //商品名称 private Integer price; //价格(分) + + private Integer credits; // 积分 } diff --git a/src/main/java/com/ai/da/mapper/primary/entity/TrialOrder.java b/src/main/java/com/ai/da/mapper/primary/entity/TrialOrder.java index cf37aeee..0e908b59 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/TrialOrder.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/TrialOrder.java @@ -25,7 +25,7 @@ public class TrialOrder implements Serializable { @TableId(value = "id", type = IdType.AUTO) private Long id; - @ApiModelProperty("surname") + @ApiModelProperty("title") private String title; @ApiModelProperty("surname") @@ -64,4 +64,5 @@ public class TrialOrder implements Serializable { */ private Integer status; private Integer isDeleted; + private String ip; } diff --git a/src/main/java/com/ai/da/model/dto/DesignSingleIncludeLayersDTO.java b/src/main/java/com/ai/da/model/dto/DesignSingleIncludeLayersDTO.java index 76161990..b2b5828d 100644 --- a/src/main/java/com/ai/da/model/dto/DesignSingleIncludeLayersDTO.java +++ b/src/main/java/com/ai/da/model/dto/DesignSingleIncludeLayersDTO.java @@ -26,6 +26,9 @@ public class DesignSingleIncludeLayersDTO { @ApiModelProperty("进度") private String processId; + @ApiModelProperty("性别") + private String gender; + @NotBlank(message = "timeZone.cannot.be.empty") @ApiModelProperty("本地时区,比如 'Asia/Tokyo' 东京时间 , 'Asia/Shanghai' 北京时间 由js本地获取") private String timeZone; diff --git a/src/main/java/com/ai/da/model/dto/DesignSingleItemDTO.java b/src/main/java/com/ai/da/model/dto/DesignSingleItemDTO.java index a21cb699..77b8b431 100644 --- a/src/main/java/com/ai/da/model/dto/DesignSingleItemDTO.java +++ b/src/main/java/com/ai/da/model/dto/DesignSingleItemDTO.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; @@ -14,6 +15,14 @@ public class DesignSingleItemDTO { @ApiModelProperty("切换图片对应的id") private Long id; + @NotEmpty(message = "changed cannot be empty") + @ApiModelProperty("当前服装的id是否被添加随机数") + private Boolean changed; + + @NotBlank(message = "designType cannot be empty") + @ApiModelProperty("当前图片来源于用户上传还是从library选择 Collection/Library") + private String designType; + @NotBlank(message = "type.cannot.be.empty") @ApiModelProperty("生成item实际对应的类型 有:outwear,dress,blouse,skirt,trousers Shoes Hairstyle Earring") private String type; @@ -38,4 +47,10 @@ public class DesignSingleItemDTO { @NotNull(message = "priority.cannot.be.empty") @ApiModelProperty("图层优先级") private Integer priority; + + @ApiModelProperty("渐变 起始/目标 颜色") + private List> gradient; + + @ApiModelProperty("渐变角度") + private Float gradient_angle; } diff --git a/src/main/java/com/ai/da/model/dto/GenerateThroughImageTextDTO.java b/src/main/java/com/ai/da/model/dto/GenerateThroughImageTextDTO.java index 1adfdbef..602f1886 100644 --- a/src/main/java/com/ai/da/model/dto/GenerateThroughImageTextDTO.java +++ b/src/main/java/com/ai/da/model/dto/GenerateThroughImageTextDTO.java @@ -24,7 +24,6 @@ public class GenerateThroughImageTextDTO { @ApiModelProperty("text image text-image") String generateType; - /** 暂时没有用上 */ @ApiModelProperty("图片是update,还是从library中选择") String designType; @@ -48,6 +47,7 @@ public class GenerateThroughImageTextDTO { @ApiModelProperty("唯一id,用于保持消息唯一性") String uniqueId; + @NotNull(message = "Please check if the required fields are empty.(isTestUser)") @ApiModelProperty("是否是测试用户") Boolean isTestUser; } diff --git a/src/main/java/com/ai/da/model/dto/GenerateToPythonDTO.java b/src/main/java/com/ai/da/model/dto/GenerateToPythonDTO.java index 927fff70..c08a5f90 100644 --- a/src/main/java/com/ai/da/model/dto/GenerateToPythonDTO.java +++ b/src/main/java/com/ai/da/model/dto/GenerateToPythonDTO.java @@ -6,22 +6,32 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor -@AllArgsConstructor +//@AllArgsConstructor public class GenerateToPythonDTO { - - private Long user_id; + // 去掉 +// private Long user_id; private String image_url; private String category; + // 改为prompt +// private String content; + private String prompt; - private String content; - - private Integer mode; - - private String version; - + private String mode; + // 去除 +// private String version; + // 去掉 private String gender; - + // taskId的最后拼接用户id private String tasks_id; + + public GenerateToPythonDTO(String tasks_id, String prompt, String image_url, String mode, String category, String gender) { + this.image_url = image_url; + this.category = category; + this.prompt = prompt; + this.mode = mode; + this.tasks_id = tasks_id; + this.gender = gender; + } } diff --git a/src/main/java/com/ai/da/model/dto/UserDesignStatisticDTO.java b/src/main/java/com/ai/da/model/dto/UserDesignStatisticDTO.java index 25bd7038..b0713077 100644 --- a/src/main/java/com/ai/da/model/dto/UserDesignStatisticDTO.java +++ b/src/main/java/com/ai/da/model/dto/UserDesignStatisticDTO.java @@ -7,11 +7,25 @@ public class UserDesignStatisticDTO { private Long accountId; - private Long useDesignTimes; + private Long designTimes; private String userEmail; private String userName; private String isTrial; + + private String trialOrderId; + + private String title; + + private String surname; + + private String givenName; + + private String country; + + private String occupation; + + private String createTime; } diff --git a/src/main/java/com/ai/da/model/vo/DesignItemClothesDetailVO.java b/src/main/java/com/ai/da/model/vo/DesignItemClothesDetailVO.java index 70ca7b46..2b5c3667 100644 --- a/src/main/java/com/ai/da/model/vo/DesignItemClothesDetailVO.java +++ b/src/main/java/com/ai/da/model/vo/DesignItemClothesDetailVO.java @@ -17,6 +17,12 @@ public class DesignItemClothesDetailVO { @ApiModelProperty("对应的上游id") private Long id; + @ApiModelProperty("该id末尾是否被加了随机数") + private Boolean changed; + + @ApiModelProperty("该图片来源 Collection / Library") + private String designType; + @ApiModelProperty("对应的类型 有:Outwear,Dress,Blouse,Skirt,Trousers Shoes Hairstyle Earring Body") private String type; diff --git a/src/main/java/com/ai/da/model/vo/DesignSinglePrint.java b/src/main/java/com/ai/da/model/vo/DesignSinglePrint.java index 94575022..54818442 100644 --- a/src/main/java/com/ai/da/model/vo/DesignSinglePrint.java +++ b/src/main/java/com/ai/da/model/vo/DesignSinglePrint.java @@ -12,6 +12,9 @@ import java.util.List; @ApiModel("design single 印花详情") public class DesignSinglePrint { + @ApiModelProperty("印花是用户上传的还是从library中选的 collection/library") + private String designType; + @ApiModelProperty("印花url") private String path; diff --git a/src/main/java/com/ai/da/model/vo/GenerateResultVO.java b/src/main/java/com/ai/da/model/vo/GenerateResultVO.java new file mode 100644 index 00000000..4a5f1453 --- /dev/null +++ b/src/main/java/com/ai/da/model/vo/GenerateResultVO.java @@ -0,0 +1,36 @@ +package com.ai.da.model.vo; + +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@ApiModel("generate result 响应") +@AllArgsConstructor +@NoArgsConstructor +public class GenerateResultVO { + + private String taskId; + + private Long id; + + private String url; + + private String status; + + private String category; + + public GenerateResultVO(String taskId, Long id, String url, String status) { + this.taskId = taskId; + this.id = id; + this.url = url; + this.status = status; + } + + public GenerateResultVO(Long id, String url, String status) { + this.id = id; + this.url = url; + this.status = status; + } +} diff --git a/src/main/java/com/ai/da/model/vo/PrepareForGenerateVO.java b/src/main/java/com/ai/da/model/vo/PrepareForGenerateVO.java index 438d94db..78c7260c 100644 --- a/src/main/java/com/ai/da/model/vo/PrepareForGenerateVO.java +++ b/src/main/java/com/ai/da/model/vo/PrepareForGenerateVO.java @@ -4,17 +4,19 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.util.List; + @Data @ApiModel("prepare for generate响应vo") public class PrepareForGenerateVO { @ApiModelProperty("uniqueId") - private String uniqueId; + private List uniqueId; @ApiModelProperty("剩余使用次数") private Integer leftUsageCount; - public PrepareForGenerateVO(String uniqueId, Integer leftUsageCount) { + public PrepareForGenerateVO(List uniqueId, Integer leftUsageCount) { this.uniqueId = uniqueId; this.leftUsageCount = leftUsageCount; } diff --git a/src/main/java/com/ai/da/python/PythonService.java b/src/main/java/com/ai/da/python/PythonService.java index 2907a19d..8e42c1d8 100644 --- a/src/main/java/com/ai/da/python/PythonService.java +++ b/src/main/java/com/ai/da/python/PythonService.java @@ -228,19 +228,28 @@ public class PythonService { long noPrintNum = 8 - pinPrintNum - noPinPrintNum; elementVO.setNoPinPrintNum(noPinPrintNum); - int pinSketchNum = 0; - int sysSketchNum = 0; - int noPinSketchNum = 0; + int[] sketchNumbers = new int[3]; for (int i = 0; i < 8; i++) { - CurrentDesignPictureTypeEnum designPictureType = calculateCurrentDesignPictureTypeNew(elementVO, pinSketchNum, sysSketchNum, noPinSketchNum, systemScale); + CurrentDesignPictureTypeEnum designPictureType = calculateCurrentDesignPictureTypeNew(elementVO, sketchNumbers, systemScale); if (designPictureType == null) break; CurrentDesignPrintPictureTypeEnum designPrintPictureType = calculateCurrentDesignPintPictureType(pinPrintNum, noPinPrintNum, noPrintNum); if (designPrintPictureType == null) break; - updateSketchNumbers(designPictureType, pinSketchNum, sysSketchNum, noPinSketchNum); - updatePrintNumbers(designPrintPictureType, pinPrintNum, noPinPrintNum, noPrintNum); + updateSketchNumbers(designPictureType, sketchNumbers); + switch (designPrintPictureType) { + case PIN: + pinPrintNum--; + break; + case NO_PIN: + noPinPrintNum--; + break; + case NO: + noPrintNum--; + break; + } +// updatePrintNumbers(designPrintPictureType, pinPrintNum, noPinPrintNum, noPrintNum); DesignPythonItemPrint designPythonItemPrint = getRandomPrint(elementVO, designPrintPictureType); elementVO.setDesignPythonItemPrint(designPythonItemPrint); @@ -252,16 +261,16 @@ public class PythonService { return designPythonObjects; } - private void updateSketchNumbers(CurrentDesignPictureTypeEnum designPictureType, int pinSketchNum, int sysSketchNum, int noPinSketchNum) { + private void updateSketchNumbers(CurrentDesignPictureTypeEnum designPictureType, int[] sketchNumbers) { switch (designPictureType) { case PIN: - pinSketchNum++; + sketchNumbers[0] ++; break; case NO_PIN: - noPinSketchNum--; + sketchNumbers[2] --; break; case SYS_FILE: - sysSketchNum--; + sketchNumbers[1] --; break; } } @@ -288,16 +297,24 @@ public class PythonService { } - private CurrentDesignPictureTypeEnum calculateCurrentDesignPictureTypeNew(ValidateElementVO elementVO, int pinSketchNum, int sysSketchNum, int noPinSketchNum, BigDecimal systemScale) { + private CurrentDesignPictureTypeEnum calculateCurrentDesignPictureTypeNew(ValidateElementVO elementVO, int[] sketchNumbers, BigDecimal systemScale) { List pinData = getPinData(elementVO); if (CollectionUtil.isNotEmpty(pinData)) { return CurrentDesignPictureTypeEnum.PIN; } else { - if (sysSketchNum == 0 && noPinSketchNum == 0) { - sysSketchNum = systemScale.multiply(BigDecimal.valueOf(8 - pinSketchNum)).setScale(0, BigDecimal.ROUND_HALF_UP).intValue(); - noPinSketchNum = 8 - pinSketchNum - sysSketchNum; + if (sketchNumbers[1] == 0 && sketchNumbers[2] == 0) { + sketchNumbers[1] = systemScale.multiply(BigDecimal.valueOf(8 - sketchNumbers[0])).setScale(0, BigDecimal.ROUND_HALF_UP).intValue(); + sketchNumbers[2] = 8 - sketchNumbers[0] - sketchNumbers[1]; } - if (noPinSketchNum > 0) { + if (sketchNumbers[2] > 0 && sketchNumbers[1] > 0) { + Long l = RandomsUtil.randomSysFile(0l, 2l); + if (l == 0l) { + return CurrentDesignPictureTypeEnum.NO_PIN; + }else { + return CurrentDesignPictureTypeEnum.SYS_FILE; + } + } + if (sketchNumbers[2] > 0) { return CurrentDesignPictureTypeEnum.NO_PIN; } return CurrentDesignPictureTypeEnum.SYS_FILE; @@ -902,7 +919,7 @@ public class PythonService { QueryWrapper qw = new QueryWrapper<>(); qw.lambda().eq(Dressing::getApparel, validateElementVO.getModelSex()); if (validateElementVO.getSingleOverall().equals(SingleOverallEnum.SINGLE.getRealName())) { - qw.lambda().eq(Dressing::getApparel, validateElementVO.getSwitchCategory()); + qw.lambda().eq(Dressing::getStyleCategory, validateElementVO.getSwitchCategory()); } List dressings = dressingMapper.selectList(qw); if (CollectionUtil.isEmpty(dressings)) { @@ -2578,17 +2595,27 @@ public class PythonService { List response = new ArrayList<>(); designSingleItemList.forEach(designSingleItem -> { + Long businessId; + if (!designSingleIncludeLayersDTO.getIsPreview() && designSingleItem.getChanged()){ + String s = String.valueOf(designSingleItem.getId()); + businessId = Long.parseLong(s.substring(0,s.length() - 3)); + }else { + businessId = designSingleItem.getId(); + } response.add(new DesignPythonItem( designSingleItem.getType(), designSingleItem.getPath(), designSingleItem.getColor(), resolveDesignSinglePrint(designSingleItem.getPrintObject(), designSingleItem.getPath()), // businessId designItemDetailId (python端确认没有作用,但是数据库需要存,作用:未知) - designSingleItem.getId(), +// designSingleItem.getId(), + businessId, pythonTAllInfoService.getImageIdByPath(designSingleItem.getPath()), designSingleItem.getOffset(), designSingleItem.getScale(), - designSingleItem.getPriority())); + designSingleItem.getPriority(), + designSingleItem.getGradient(), + designSingleItem.getGradient_angle())); }); @@ -2878,7 +2905,7 @@ public class PythonService { throw new BusinessException("system error!"); } - public List generateSketchOrPrint(GenerateToPythonDTO generateToPythonDTO) { + public Boolean generateSketchOrPrint(GenerateToPythonDTO generateToPythonDTO) { //限流校验 // AccessLimitUtils.validate("generateSketchOrPrint", 5); OkHttpClient client = new OkHttpClient().newBuilder() @@ -2893,7 +2920,8 @@ public class PythonService { // .url("http://18.167.251.121:9992") // .url("http://127.0.0.1:5000/api/diffusion") // .url(accessPythonIp + ":" + accessPythonPort + "/api/diffusion") - .url(accessPythonIp + ":" + accessPythonPort + "/api/generate_image") +// .url(accessPythonIp + ":" + accessPythonPort + "/api/generate_image") + .url(srPythonPort + "/api/generate_image") .method("POST", body) // .addHeader("Authorization", "Basic YWlkbGFiOjEyMw==") .addHeader("Content-Type", "application/json") @@ -2934,12 +2962,13 @@ public class PythonService { if (result && jsonObject.get("code").equals(200)) { log.info("Generate##responseObject###{}", jsonObject); - return setGenerateImageList(jsonObject.getJSONObject("data")); +// return setGenerateImageList(jsonObject.getJSONObject("data")); + return Boolean.TRUE; + }else { + log.info("generateSketchOrPrintPrint失败###{}", jsonObject); + log.info("Generate Exception! Code : " + jsonObject.get("code")); + return Boolean.FALSE; } - log.info("generateSketchOrPrintPrint失败###{}", jsonObject); - log.info("Generate Exception! Code : " + jsonObject.get("code")); - //生成失败 - throw new BusinessException("generate.interface.error"); } public Response sendPostToModel(String content, String portAndRoute, String functionName) { diff --git a/src/main/java/com/ai/da/python/vo/DesignPythonItem.java b/src/main/java/com/ai/da/python/vo/DesignPythonItem.java index efb82472..5e327086 100644 --- a/src/main/java/com/ai/da/python/vo/DesignPythonItem.java +++ b/src/main/java/com/ai/da/python/vo/DesignPythonItem.java @@ -74,6 +74,9 @@ public class DesignPythonItem { */ private Integer priority; + private List> gradient; + + private Float gradient_angle; public static List OUTWEAR_DRESS_BLOUSE = Arrays.asList(CollectionLevel2TypeEnum.OUTWEAR.getRealName(), CollectionLevel2TypeEnum.DRESS.getRealName(), CollectionLevel2TypeEnum.BLOUSE.getRealName()); @@ -123,6 +126,21 @@ public class DesignPythonItem { this.priority = priority; } + public DesignPythonItem(String type, String path, String color, DesignPythonItemPrint print, Long businessId, Long image_id, List offset, Float resize_scale,Integer priority, List> gradient, Float gradient_angle) { + this.type = type; + this.path = path; + this.color = color; + this.print = print; +// this.icon = icon; + this.businessId = businessId; + this.image_id = image_id; + this.offset = offset; + this.resize_scale = resize_scale; + this.priority = priority; + this.gradient = gradient; + this.gradient_angle = gradient_angle; + } + public DesignPythonItem(String type, String path, String color, DesignPythonItemPrint print, String icon, Long businessId, Long image_id) { this.type = type; this.path = path; diff --git a/src/main/java/com/ai/da/service/AccountService.java b/src/main/java/com/ai/da/service/AccountService.java index 5b00ba5b..6d42900b 100644 --- a/src/main/java/com/ai/da/service/AccountService.java +++ b/src/main/java/com/ai/da/service/AccountService.java @@ -99,7 +99,7 @@ public interface AccountService extends IService { Boolean completeGuidance(); - Boolean addTrialUser(AccountTrialDTO accountTrialDTO); + Boolean addTrialUser(AccountTrialDTO accountTrialDTO, HttpServletRequest request); IPage trialOrderList(TrialOrderDTO trialOrderDTO); diff --git a/src/main/java/com/ai/da/service/CallBackService.java b/src/main/java/com/ai/da/service/CallBackService.java deleted file mode 100644 index 39efb1eb..00000000 --- a/src/main/java/com/ai/da/service/CallBackService.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ai.da.service; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -public interface CallBackService { - - Boolean doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException; -} diff --git a/src/main/java/com/ai/da/service/CollectionElementService.java b/src/main/java/com/ai/da/service/CollectionElementService.java index 489e08f8..7f015d3b 100644 --- a/src/main/java/com/ai/da/service/CollectionElementService.java +++ b/src/main/java/com/ai/da/service/CollectionElementService.java @@ -134,6 +134,6 @@ public interface CollectionElementService extends IService { * @param level2Type * @return */ - CollectionElement editLevel2Type(Long elementId, String level2Type); + CollectionElement editLevel2Type(Long elementId, String level2Type, String designType); } diff --git a/src/main/java/com/ai/da/service/CreditsService.java b/src/main/java/com/ai/da/service/CreditsService.java index a2947b5b..a9d35d17 100644 --- a/src/main/java/com/ai/da/service/CreditsService.java +++ b/src/main/java/com/ai/da/service/CreditsService.java @@ -26,4 +26,8 @@ public interface CreditsService extends IService { PageBaseResponse queryCreditsDetailsPage(QueryIncomeOrExpenditureDTO queryPageByTimeDTO); Boolean checkCredits(Long accountId, CreditsEventsEnum event, Integer num); + + Boolean creditsPreDeduction(CreditsEventsEnum event, Integer num); + + void taskCreditsDeduction(Long accountId, String taskId); } diff --git a/src/main/java/com/ai/da/service/GenerateService.java b/src/main/java/com/ai/da/service/GenerateService.java index 8e3a841c..c59513c8 100644 --- a/src/main/java/com/ai/da/service/GenerateService.java +++ b/src/main/java/com/ai/da/service/GenerateService.java @@ -4,10 +4,7 @@ import com.ai.da.mapper.primary.entity.Generate; import com.ai.da.mapper.primary.entity.GenerateDetail; import com.ai.da.model.dto.GenerateLikeDTO; import com.ai.da.model.dto.GenerateThroughImageTextDTO; -import com.ai.da.model.vo.GenerateCaptionVO; -import com.ai.da.model.vo.GenerateCollectionVO; -import com.ai.da.model.vo.GenerateLikeVO; -import com.ai.da.model.vo.PrepareForGenerateVO; +import com.ai.da.model.vo.*; import com.baomidou.mybatisplus.extension.service.IService; import java.util.List; @@ -16,7 +13,9 @@ public interface GenerateService extends IService { GenerateCaptionVO generateCaption(Long sketchElementId); - GenerateCollectionVO generateThroughImageText(GenerateThroughImageTextDTO generateThroughImageTextDTO); + void generateThroughImageText(GenerateThroughImageTextDTO generateThroughImageTextDTO); + + void processGenerateResult(String taskId, String url, String category); GenerateLikeVO generateLike(GenerateLikeDTO generateLikeDTO); @@ -28,10 +27,12 @@ public interface GenerateService extends IService { GenerateCollectionVO getGenerateResult(String uniqueId); + List getGenerateResultList(List taskIdList); + PrepareForGenerateVO prepareForGenerate(GenerateThroughImageTextDTO generateThroughImageTextDTO); Long getRankPosition(String uniqueId); - void cancelGenerate(Long userId, String uniqueId, String timeZone); + void cancelGenerate(Long userId, List uniqueId, String timeZone); } diff --git a/src/main/java/com/ai/da/service/PayPalCheckoutService.java b/src/main/java/com/ai/da/service/PayPalCheckoutService.java index a3f0fcdb..450c521d 100644 --- a/src/main/java/com/ai/da/service/PayPalCheckoutService.java +++ b/src/main/java/com/ai/da/service/PayPalCheckoutService.java @@ -19,7 +19,7 @@ public interface PayPalCheckoutService { Boolean doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException; - String queryOrder(String orderNo) throws SerializeException; + Order queryOrder(String orderNo) throws SerializeException; Order captureOrder(String orderId) throws IOException; @@ -28,5 +28,7 @@ public interface PayPalCheckoutService { String getOAuth(); void processOrder(String orderId); + + void checkOrderStatus(String orderNo) throws SerializeException; } diff --git a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java index b6e75c34..a166eb91 100644 --- a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java @@ -466,7 +466,20 @@ public class AccountServiceImpl extends ServiceImpl impl } @Override - public Boolean addTrialUser(AccountTrialDTO accountTrialDTO) { + public Boolean addTrialUser(AccountTrialDTO accountTrialDTO, HttpServletRequest request) { + // 获取用户申请试用IP + String ipAddress = RequestInfoUtil.getIpAddress(request); + // 先检测试用订单 + QueryWrapper trialOrderQueryWrapper = new QueryWrapper<>(); + trialOrderQueryWrapper.lambda().eq(TrialOrder::getIp, ipAddress); + trialOrderQueryWrapper.lambda().and(wrapper -> + wrapper.eq(TrialOrder::getEmail, accountTrialDTO.getEmail()) + .or() // OR + .like(TrialOrder::getUserName, accountTrialDTO.getUserName())); + List trialOrders = trialOrderMapper.selectList(trialOrderQueryWrapper); + if (CollectionUtil.isNotEmpty(trialOrders)) { + throw new BusinessException("You have submitted a trial application, please wait for approval."); + } // 先检测用户名和邮箱 QueryWrapper qw = new QueryWrapper<>(); qw.lambda().eq(Account::getUserEmail, accountTrialDTO.getEmail()) @@ -487,6 +500,7 @@ public class AccountServiceImpl extends ServiceImpl impl TrialOrder trialOrder = CopyUtil.copyObject(accountTrialDTO, TrialOrder.class); trialOrder.setCreateTime(LocalDateTime.now()); trialOrder.setStatus(0); + trialOrder.setIp(ipAddress); trialOrderMapper.insert(trialOrder); SendEmailUtil.sendCustomEmail("1023316923@qq.com", null, trialOrder,1); SendEmailUtil.sendCustomEmail("calvinwong@aidlab.hk", null, trialOrder,1); diff --git a/src/main/java/com/ai/da/service/impl/CallBackServiceImpl.java b/src/main/java/com/ai/da/service/impl/CallBackServiceImpl.java deleted file mode 100644 index 7c5fd42f..00000000 --- a/src/main/java/com/ai/da/service/impl/CallBackServiceImpl.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.ai.da.service.impl; - -import com.ai.da.common.config.PayPalClient; -import com.ai.da.common.constant.PayPalCheckoutConstant; -import com.ai.da.common.utils.paypalRequest.WebhookVerifyRequest; -import com.ai.da.service.CallBackService; -import com.ai.da.service.PayPalCheckoutService; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.paypal.api.payments.Event; -import com.paypal.base.Constants; -import com.paypal.base.SDKUtil; -import com.paypal.base.rest.APIContext; -import com.paypal.base.rest.PayPalRESTException; -import com.paypal.http.HttpResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SignatureException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - -import static com.ai.da.common.constant.PayPalCheckoutConstant.MODE; - -// #Validate Webhook Sample -// -// This sample code demonstrates how to validate a webhook received on your -// web server. This sample assumes that you use the java servlet, which returns -// the HttpServletRequest object. However, you can modify this code to -// your specific case. -// - -@Slf4j -@Service -public class CallBackServiceImpl implements CallBackService { - - @Value("${paypal.client-id}") - private String clientId; - - @Value("${paypal.client-secret}") - private String clientSecret; - - @Resource - private PayPalClient payPalClient; - - @Resource - private PayPalCheckoutService payPalCheckoutService; - - @Override - public Boolean doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - return doPost(req, resp); - } - - // ##Validate Webhook - protected Boolean doPost(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - try { - String body = getBody(req); - Map webhookEvent = new ObjectMapper().readValue(body, Map.class); - - HashMap webhookRequest = new HashMap<>(); - webhookRequest.put("auth_algo",SDKUtil.validateAndGet(getHeadersInfo(req), "PAYPAL-AUTH-ALGO")); - webhookRequest.put("cert_url",SDKUtil.validateAndGet(getHeadersInfo(req), "PAYPAL-CERT-URL")); - webhookRequest.put("transmission_id",SDKUtil.validateAndGet(getHeadersInfo(req), "PAYPAL-TRANSMISSION-ID")); - webhookRequest.put("transmission_sig",SDKUtil.validateAndGet(getHeadersInfo(req), "PAYPAL-TRANSMISSION-SIG")); - webhookRequest.put("transmission_time",SDKUtil.validateAndGet(getHeadersInfo(req), "PAYPAL-TRANSMISSION-TIME")); - webhookRequest.put("webhook_id",PayPalCheckoutConstant.WEBHOOK_ID); - webhookRequest.put("webhook_event",webhookEvent); - - WebhookVerifyRequest webhookVerifyRequest = new WebhookVerifyRequest(); - webhookVerifyRequest.authorization(payPalCheckoutService.getOAuth()); - webhookVerifyRequest.requestBody(webhookRequest); - // 验签 - HttpResponse verified = payPalClient.client(MODE, clientId, clientSecret).execute(webhookVerifyRequest); - boolean verifyResult = verified.result().get("verification_status").toString().equals("SUCCESS"); - if (verifyResult){ - // ### Api Context - APIContext apiContext = new APIContext(clientId, clientSecret, PayPalCheckoutConstant.MODE); - - // Set the webhookId that you received when you created this webhook. - apiContext.addConfiguration(Constants.PAYPAL_WEBHOOK_ID, PayPalCheckoutConstant.WEBHOOK_ID); - Boolean result = Event.validateReceivedEvent(apiContext, getHeadersInfo( - req), body); - log.info("Webhook Validated: " + result); - - if (result){ - // 处理订单数据 - LinkedHashMap> webhookEventMap = (LinkedHashMap>) webhookEvent; - String orderId = webhookEventMap.get("resource").get("id"); - payPalCheckoutService.processOrder(orderId); - return Boolean.TRUE; - } - - } - } catch (PayPalRESTException | InvalidKeyException | NoSuchAlgorithmException | SignatureException e) { - log.error(e.getMessage()); - } - return Boolean.FALSE; - } - - // Simple helper method to help you extract the headers from HttpServletRequest object. - private static Map getHeadersInfo(HttpServletRequest request) { - Map map = new HashMap(); - @SuppressWarnings("rawtypes") - Enumeration headerNames = request.getHeaderNames(); - while (headerNames.hasMoreElements()) { - String key = (String) headerNames.nextElement(); - String value = request.getHeader(key); - map.put(key, value); - } - return map; - } - - // Simple helper method to fetch request data as a string from HttpServletRequest object. - private static String getBody(HttpServletRequest request) throws IOException { - String body; - StringBuilder stringBuilder = new StringBuilder(); - BufferedReader bufferedReader = null; - try { - InputStream inputStream = request.getInputStream(); - if (inputStream != null) { - bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); - char[] charBuffer = new char[128]; - int bytesRead = -1; - while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { - stringBuilder.append(charBuffer, 0, bytesRead); - } - } else { - stringBuilder.append(""); - } - } catch (IOException ex) { - throw ex; - } finally { - if (bufferedReader != null) { - try { - bufferedReader.close(); - } catch (IOException ex) { - throw ex; - } - } - } - body = stringBuilder.toString(); - log.info("回调参数 ===> {}", body); - return body; - } -} diff --git a/src/main/java/com/ai/da/service/impl/CollectionElementServiceImpl.java b/src/main/java/com/ai/da/service/impl/CollectionElementServiceImpl.java index 82146f3b..fc1455ec 100644 --- a/src/main/java/com/ai/da/service/impl/CollectionElementServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/CollectionElementServiceImpl.java @@ -26,6 +26,7 @@ import com.google.common.collect.Lists; import io.minio.errors.MinioException; import io.netty.util.internal.StringUtil; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -36,6 +37,8 @@ import javax.annotation.Resource; import java.io.File; import java.io.IOException; import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.*; import java.util.stream.Collectors; @@ -622,6 +625,7 @@ public class CollectionElementServiceImpl extends ServiceImpl implements CreditsService { - @Resource - private AccountService accountService; + @Value("${redis.key.credits.pre-deduction}") + private String creditsDeduction; + @Resource + private AccountService accountService; @Resource private AccountMapper accountMapper; + @Resource + private RedisUtil redisUtil; @Override public void initCredits() { @@ -116,20 +125,20 @@ public class CreditsServiceImpl extends ServiceImpl keys = redisUtil.getKeysFromString(creditsDeduction + ":" + accountId + ":*"); + List multiValue = redisUtil.getMultiValue(keys); + int sum = multiValue.stream().mapToInt(Integer::parseInt).sum(); + sum += Integer.parseInt(event.getValue()) * num; + + // 2、获取当前积分 + BigDecimal existingCredits = accountMapper.selectById(accountId).getCredits(); + BigDecimal subtract = existingCredits.subtract(new BigDecimal(sum)); + + // 3、判断剩余积分是否够本次操作 + if (subtract.compareTo(BigDecimal.ZERO) < 0){ + // 3.1 不够,直接返回余额不够,充值 + return Boolean.FALSE; + } + + return Boolean.TRUE; + } + + /** 执行扣除积分,更新数据库 */ + @Override + @Transactional(rollbackFor = Exception.class) + public void taskCreditsDeduction(Long accountId, String taskId){ + String key = creditsDeduction + ":" + accountId + ":" + taskId; + // 1、获取当前任务id对应的积分 + String value = redisUtil.getFromString(key); + + // 1.1 没有。返回,报错,未找到当前任务 + if (StringUtil.isNullOrEmpty(value)){ + throw new BusinessException("当前任务不存在,无法扣除积分"); + } + + // 2、操作数据库,扣除积分 + BigDecimal existingCredits = accountMapper.selectById(accountId).getCredits(); + BigDecimal subtract = existingCredits.subtract(new BigDecimal(value)); + accountService.updateCredits(accountId, subtract.toString()); + + // 3、从redis中移除当前待扣积分 + redisUtil.removeFromString(key); + } + } diff --git a/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java b/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java index 64bc25d4..613d8e71 100644 --- a/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/DesignItemServiceImpl.java @@ -3,11 +3,14 @@ package com.ai.da.service.impl; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import com.ai.da.common.config.exception.BusinessException; +import com.ai.da.common.constant.CommonConstant; import com.ai.da.common.context.UserContext; +import com.ai.da.common.enums.CollectionLevel1TypeEnum; import com.ai.da.common.enums.SingleOverallEnum; import com.ai.da.common.enums.SysFileLevel2TypeEnum; import com.ai.da.common.utils.CopyUtil; import com.ai.da.common.utils.DateUtil; +import com.ai.da.common.utils.MD5Utils; import com.ai.da.common.utils.MinioUtil; import com.ai.da.mapper.primary.DesignItemMapper; import com.ai.da.mapper.primary.entity.*; @@ -30,8 +33,10 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.io.IOException; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; @@ -488,6 +493,8 @@ public class DesignItemServiceImpl extends ServiceImpl idChanged = designSingleItemDTOList.stream().collect(Collectors.toMap(DesignSingleItemDTO::getId, DesignSingleItemDTO::getChanged)); + // 获取每个单品的designType,该状态需要再返回给前端 + Map idDesignType = designSingleItemDTOList.stream().collect(Collectors.toMap(DesignSingleItemDTO::getId, DesignSingleItemDTO::getDesignType)); + boolean flag = singleOrOverall.equals("single"); designSingleItemDTOList.forEach(singleItem -> { DesignItemClothesDetailVO designItemClothesDetailVO = new DesignItemClothesDetailVO(); designItemClothesDetailVO.setId(singleItem.getId()); + designItemClothesDetailVO.setChanged(idChanged.get(singleItem.getId())); + designItemClothesDetailVO.setDesignType(idDesignType.get(singleItem.getId())); designItemClothesDetailVO.setType(singleItem.getType()); designItemClothesDetailVO.setPath(minioUtil.getPresignedUrl(singleItem.getPath(), 24 * 60)); designItemClothesDetailVO.setMinIOPath(singleItem.getPath()); designItemClothesDetailVO.setColor(panToneService.getPantoneByRgb(singleItem.getColor())); -// designItemClothesDetailVO.setPrintObject(new DesignPythonItemPrint(singleItem.getPrintObject().getPath())); designItemClothesDetailVO.setPrintObject(singleItem.getPrintObject()); designItemClothesDetailVO.setLayersObject(layersObject.stream().filter( layers -> (singleItem.getType().toLowerCase().equals(layers.getImageCategory().split("_")[0]) @@ -703,4 +712,68 @@ public class DesignItemServiceImpl extends ServiceImpl libraries = new ArrayList<>(); + // 添加sketch到library + designSingleIncludeLayersDTO.getDesignSingleItemDTOList().forEach(designSingleItem -> { + + if (!StringUtil.isNullOrEmpty(designSingleItem.getDesignType()) && designSingleItem.getDesignType().equals("Collection")){ + String path = minioUtil.getPresignedUrl(designSingleItem.getPath(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME); + try { + String md5 = MD5Utils.encryptFile(path, false); + // 先判断是否需要被加入到library + Boolean needAdd = libraryService.checkMd5(CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName(), + designSingleItem.getType(), + designSingleIncludeLayersDTO.getGender(), + md5); + // 加入到library + if (needAdd){ + Library library = new Library(); + library.setAccountId(UserContext.getUserHolder().getId()); + library.setLevel1Type(CollectionLevel1TypeEnum.SKETCH_BOARD.getRealName()); + library.setLevel2Type(designSingleItem.getType()); + library.setLevel3Type(designSingleIncludeLayersDTO.getGender()); + library.setUrl(designSingleItem.getPath()); + library.setName(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))); + library.setMd5(md5); + library.setCreateDate(DateUtil.getByTimeZone(designSingleIncludeLayersDTO.getTimeZone())); + libraries.add(library); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + // 添加print到library + designSingleItem.getPrintObject().getPrints().forEach(print -> { + if (!StringUtil.isNullOrEmpty(print.getDesignType()) && print.getDesignType().equals("Collection")){ + String path = minioUtil.getPresignedUrl(print.getMinIOPath(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME); + try { + String md5 = MD5Utils.encryptFile(path, false); + // 先判断是否已被加入到library + Boolean needAdd = libraryService.checkMd5(CollectionLevel1TypeEnum.PRINT_BOARD.getRealName(), + null, + null, + md5); + // 加入到library + if (needAdd){ + Library library = new Library(); + library.setAccountId(UserContext.getUserHolder().getId()); + library.setLevel1Type(CollectionLevel1TypeEnum.PRINT_BOARD.getRealName()); + library.setUrl(print.getMinIOPath()); + library.setName(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))); + library.setMd5(md5); + library.setCreateDate(DateUtil.getByTimeZone(designSingleIncludeLayersDTO.getTimeZone())); + libraries.add(library); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + } ); + libraryService.saveBatch(libraries); + } } diff --git a/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java b/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java index 1fabbcc5..1755eb60 100644 --- a/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java @@ -1,6 +1,7 @@ package com.ai.da.service.impl; import com.ai.da.common.config.exception.BusinessException; +import com.ai.da.common.constant.CommonConstant; import com.ai.da.common.context.UserContext; import com.ai.da.common.enums.GenerateModeEnum; import com.ai.da.common.enums.ModelNameEnum; @@ -22,7 +23,9 @@ import com.ai.da.service.RabbitMQService; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.gson.Gson; import io.minio.errors.MinioException; import io.netty.util.internal.StringUtil; import lombok.extern.slf4j.Slf4j; @@ -33,7 +36,9 @@ import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.io.IOException; +import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; import static com.ai.da.common.enums.CollectionLevel1TypeEnum.*; @@ -80,6 +85,9 @@ public class GenerateServiceImpl extends ServiceImpl i @Value("${redis.key.resultMap}") private String resultMapKey; + @Value("${redis.key.generateResult}") + private String generateResultKey; + @Override public GenerateCaptionVO generateCaption(Long sketchElementId) { CollectionElement collectionElement = collectionElementMapper.selectById(sketchElementId); @@ -95,12 +103,12 @@ public class GenerateServiceImpl extends ServiceImpl i @Override @Transactional(rollbackFor = Exception.class) - public GenerateCollectionVO generateThroughImageText(GenerateThroughImageTextDTO generateThroughImageTextDTO) { + public void generateThroughImageText(GenerateThroughImageTextDTO generateThroughImageTextDTO) { // 1、获取用户信息 Long accountId = generateThroughImageTextDTO.getUserId(); String generateType = generateThroughImageTextDTO.getGenerateType(); - // 2、判断必须入参是否为非空 + // 2、判断必须入参是否为非空(在prepare阶段已校验) Generate generate = new Generate(); generate.setAccountId(accountId); generate.setUniqueId(generateThroughImageTextDTO.getUniqueId()); @@ -111,36 +119,51 @@ public class GenerateServiceImpl extends ServiceImpl i generateType); generate.setModelName(StringUtil.isNullOrEmpty(generateThroughImageTextDTO.getVersion()) ? ModelNameEnum.MODEL_0.getCode() : generateThroughImageTextDTO.getVersion()); generate.setCreateDate(DateUtil.getByTimeZone(generateThroughImageTextDTO.getTimeZone())); + generate.setElementSource(StringUtil.isNullOrEmpty(generateThroughImageTextDTO.getDesignType()) ? null : generateThroughImageTextDTO.getDesignType()); String text = generateThroughImageTextDTO.getText(); Long elementId = generateThroughImageTextDTO.getCollectionElementId(); validateGeneraType(generate, text, elementId, generateType); + if (generateType.equals("text") || generateType.equals("text-image")) { + text = modifyPrompt(text, generate, generateThroughImageTextDTO.getLevel1Type()); + } - // 2.1 sketch或print在t_collection_element表中的信息是否需要更新 如 level2Type - CollectionElement collectionElement = collectionElementService.editLevel2Type(elementId, generateThroughImageTextDTO.getLevel2Type()); + // 2.1 sketch或print在t_collection_element表/t_library表中的信息是否需要更新 如 level2Type + CollectionElement collectionElement = collectionElementService.editLevel2Type(elementId, generateThroughImageTextDTO.getLevel2Type(), generateThroughImageTextDTO.getDesignType()); // 3、向模型发起请求 - int mode = GenerateModeEnum.TEXT.getValue().equals(generateType) ? - GenerateModeEnum.TEXT.getCode() : - GenerateModeEnum.TEXT_IMAGE.getCode(); + String mode = GenerateModeEnum.TEXT.getValue().equals(generateType) ? + GenerateModeEnum.TEXT.getType() : + GenerateModeEnum.TEXT_IMAGE.getType(); String category = generateThroughImageTextDTO.getLevel1Type().equals(SKETCH_BOARD.getRealName()) ? "sketch" : generateThroughImageTextDTO.getLevel1Type().equals(PRINT_BOARD.getRealName()) ? "print" : "moodboard"; - AsyncCallerUtil asyncCallerUtil = new AsyncCallerUtil(); - List generatedSketchUrl = asyncCallerUtil.generate(new GenerateToPythonDTO(accountId, Objects.isNull(collectionElement) ? "" : collectionElement.getUrl(), - category, text, mode, "1", generateThroughImageTextDTO.getGender(), generateThroughImageTextDTO.getUniqueId())); -// List generatedSketchUrl = pythonService.generateSketchOrPrint(new GenerateToPythonDTO(accountId, Objects.isNull(elementId) ? null : collectionElement.getUrl(), -// category, text, mode, "1", generateThroughImageTextDTO.getGender())); - log.info("generate 响应 : " + generatedSketchUrl); - if (CollectionUtils.isEmpty(generatedSketchUrl)) { - return null; - } +// AsyncCallerUtil asyncCallerUtil = new AsyncCallerUtil(); +// List generatedSketchUrl = asyncCallerUtil.generate(new GenerateToPythonDTO(accountId, Objects.isNull(collectionElement) ? "" : collectionElement.getUrl(), +// category, text, mode, "1", generateThroughImageTextDTO.getGender(), generateThroughImageTextDTO.getUniqueId())); + Boolean requestResult = pythonService.generateSketchOrPrint(new GenerateToPythonDTO(generateThroughImageTextDTO.getUniqueId(), text, Objects.isNull(collectionElement) ? "" : collectionElement.getUrl(), + mode, category, generateThroughImageTextDTO.getGender())); +// log.info("generate 响应 : " + generatedSketchUrl); +// if (CollectionUtils.isEmpty(generatedSketchUrl)) { +// return null; +// } // 4、将请求信息落库,将本次generate的请求信息添加到t_generate表中 save(generate); + // 5、将本次请求存入redis + String key = generateResultKey + ":" + generateThroughImageTextDTO.getUniqueId(); + String status; + if (requestResult) { + status = "Executing"; + } else { + status = "Fail"; + } + GenerateResultVO generateResultVO = new GenerateResultVO(generateThroughImageTextDTO.getUniqueId(), null, null, status); + redisUtil.addToString(key, new Gson().toJson(generateResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); + // 5、处理模型返回的数据 // 5.1 将相应的url保存到数据库 - List generatedCollectionItems = new ArrayList<>(); + /*List generatedCollectionItems = new ArrayList<>(); generatedSketchUrl.forEach(item -> { GenerateDetail generateDetail = new GenerateDetail(); GenerateCollectionItemVO generateCollectionItemVO = new GenerateCollectionItemVO(); @@ -165,7 +188,48 @@ public class GenerateServiceImpl extends ServiceImpl i // 6、将模型返回的图片地址返回给前端 Long collectionId = Objects.isNull(collectionElement) ? null : collectionElement.getCollectionId(); - return new GenerateCollectionVO(generate.getId(), collectionId, generatedCollectionItems); + return new GenerateCollectionVO(generate.getId(), collectionId, generatedCollectionItems);*/ + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void processGenerateResult(String taskId, String url, String category) { + // 5、处理模型返回的数据 + // 5.1 将相应的url保存到数据库 + GenerateDetail generateDetail = new GenerateDetail(); + GenerateCollectionItemVO generateCollectionItemVO = new GenerateCollectionItemVO(); + Generate generate; + try { + generate = selectByUniqueId(taskId); + } catch (MybatisPlusException e) { + log.error(e.getMessage()); + if (e.getMessage().equals("One record is expected, but the query result is multiple records")) { + generate = selectListByUniqueId(taskId).get(0); + } else { + throw new BusinessException("There are some problems with database query, please try again."); + } + + } +// Generate generate = selectByUniqueId(taskId); + String md5 = MD5Utils.encryptFile(minioUtil.getPresignedUrl(url, 24 * 60), Boolean.FALSE); + // 通过MD5值和level1Type,判断不同level1Type下相同的图片是否被like过 + List> libraryIdList = generateDetailMapper.getLibraryIdThroughMD5(md5, generate.getLevel1Type()); + if (!libraryIdList.isEmpty()) { + generateDetail.setIsLike((byte) 1); + generateDetail.setLibraryId(libraryIdList.get(0).get("library_id")); + generateCollectionItemVO.setIsLiked(Boolean.TRUE); + } + generateDetail.setUrl(url); + generateDetail.setGenerateId(generate.getId()); + generateDetail.setCreateDate(LocalDateTime.now()); + generateDetail.setMd5(md5); + generateDetailMapper.insert(generateDetail); + + String key = generateResultKey + ":" + taskId; + String imageName = url.substring(url.lastIndexOf("/") + 1); + String status = imageName.equals("white_image.jpg") ? "Invalid" : "Success"; + GenerateResultVO generateResultVO = new GenerateResultVO(taskId, generateDetail.getId(), url, status, category); + redisUtil.addToString(key, new Gson().toJson(generateResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); } private void validateGeneraType(Generate generate, String text, Long elementId, String generateType) { @@ -180,18 +244,44 @@ public class GenerateServiceImpl extends ServiceImpl i if (Objects.isNull(elementId)) { throw new BusinessException("please.choose.an.image"); } - generate.setCollectionElementId(elementId); + generate.setElementId(elementId); break; case "text-image": if (StringUtil.isNullOrEmpty(text) || Objects.isNull(elementId)) { throw new BusinessException("please.input.the.caption.and.choose.an.image"); } generate.setText(text); - generate.setCollectionElementId(elementId); + generate.setElementId(elementId); default: } } + private String modifyPrompt(String userInput, Generate generate, String level1Type) { + String text = ""; + switch (level1Type) { + case "Moodboard": + text = userInput + ",high quality"; + generate.setText(text); + break; + case "Printboard": + if (userInput.contains("Painting Style")) { + userInput = "Picasso,increased color saturation,increased glossiness," + userInput; + } else if (userInput.contains("Illustration Style")) { + userInput = "Flat coating,romantic,soft,pencil strokes,accentuating and widening the depth of pencil strokes,paper patterns,block colors,crayons,reducing image contrast,and hand drawn painting marks," + userInput; + } else if (userInput.contains("Real Style")) { + userInput = "Still life photography,hyper realism,3d,deepened projection,increased permutation value,increased concavity and convexity value," + userInput; + } + text = userInput + ", fabric print, high quality"; + generate.setText(text); + break; + case "Sketchboard": + text = "clear lines, simple outlines monochrome white vector image of " + userInput + ", no background, sketch flat, front view display, best quality, ultra-high resolution 8k"; + generate.setText(text); + default: + } + return text; + } + @Override @Transactional(rollbackFor = Exception.class) public GenerateLikeVO generateLike(GenerateLikeDTO generateLikeDTO) { @@ -315,6 +405,7 @@ public class GenerateServiceImpl extends ServiceImpl i @Override public PrepareForGenerateVO prepareForGenerate(GenerateThroughImageTextDTO generateThroughImageTextDTO) { +// public List prepareForGenerate(GenerateThroughImageTextDTO generateThroughImageTextDTO) { // 1、参数检查,判断必须参数是否为空 if (Objects.isNull(generateThroughImageTextDTO.getUserId())) { throw new BusinessException("userId cannot be empty"); @@ -326,9 +417,9 @@ public class GenerateServiceImpl extends ServiceImpl i // 判断试用用户是否还有剩余试用机会 int trialsCount = 0; - if (generateThroughImageTextDTO.getIsTestUser()){ + if (generateThroughImageTextDTO.getIsTestUser()) { trialsCount = getTrialsCount(generateThroughImageTextDTO.getUserId(), generateThroughImageTextDTO.getLevel1Type()); - if (trialsCount >= 2){ + if (trialsCount >= 2) { return new PrepareForGenerateVO(0); } } @@ -340,9 +431,6 @@ public class GenerateServiceImpl extends ServiceImpl i // 2、生成唯一id 使用uuid String uuid = UUID.randomUUID().toString(); -// SnowflakeUtil idWorker = new SnowflakeUtil(0, 0); -// long snowflakeId = idWorker.nextId(); - int num = 1; // 判断已经正常生成结果的uuid或正在排队的uuid中是否有相同的id while ((redisUtil.isElementExistsInMap(resultMapKey, uuid) || @@ -360,18 +448,30 @@ public class GenerateServiceImpl extends ServiceImpl i } uuid = UUID.randomUUID().toString(); } - generateThroughImageTextDTO.setUniqueId(uuid); - String jsonString = JSON.toJSONString(generateThroughImageTextDTO); - // 3、加入redis排队,便于获取实时排队信息 - Double maxScore = redisUtil.getMaxScore(consumptionOrderKey); - redisUtil.addToZSet(consumptionOrderKey, uuid, maxScore); + ArrayList taskIdList = new ArrayList<>(); + for (int i = 1; i <= 4; i++) { + String temp = uuid; + temp += "-" + i + "-" + generateThroughImageTextDTO.getUserId(); + taskIdList.add(temp); + generateThroughImageTextDTO.setUniqueId(temp); + String jsonString = JSON.toJSONString(generateThroughImageTextDTO); - // 4、将消息发布到MQ消息队列 - rabbitMQService.publishMessageToGenerate(jsonString); + // 3、加入redis排队,便于获取实时排队信息 + Double maxScore = redisUtil.getMaxScore(consumptionOrderKey); + redisUtil.addToZSet(consumptionOrderKey, temp, maxScore); + + // 加入resultMap + String key = generateResultKey + ":" + temp; + GenerateResultVO generateResultVO = new GenerateResultVO(generateThroughImageTextDTO.getUniqueId(), null, null, "Waiting"); + redisUtil.addToString(key, new Gson().toJson(generateResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); + + // 4、将消息发布到MQ消息队列 + rabbitMQService.publishMessageToGenerate(jsonString); + } // 5、返回唯一id - return new PrepareForGenerateVO(uuid, 2 - trialsCount); + return new PrepareForGenerateVO(taskIdList, 2 - trialsCount); } @Override @@ -431,6 +531,35 @@ public class GenerateServiceImpl extends ServiceImpl i return new GenerateCollectionVO(generateId, null, generatedCollectionItems); } + @Override + public List getGenerateResultList(List taskIdList) { + List results = new ArrayList<>(); + Set collect = new HashSet<>(); + taskIdList.forEach(taskId -> { + String key = generateResultKey + ":" + taskId; + GenerateResultVO generateResultVO = new Gson().fromJson(redisUtil.getFromString(key), GenerateResultVO.class); + if (!Objects.isNull(generateResultVO) && !StringUtil.isNullOrEmpty(generateResultVO.getUrl())) { + String url = generateResultVO.getUrl(); + if (url.substring(url.lastIndexOf("/") + 1).equals("white_image.jpg")) { + generateResultVO.setStatus("Invalid"); + } else { + generateResultVO.setUrl(minioUtil.getPresignedUrl(url, CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); + } + } else if (Objects.isNull(generateResultVO)) { + generateResultVO = new GenerateResultVO(); + } + if (!StringUtil.isNullOrEmpty(generateResultVO.getStatus())) collect.add(generateResultVO.getStatus()); + results.add(generateResultVO); + }); + // todo + if (taskIdList.size() == 4 && collect.size() == 1 && collect.contains("Fail")) { + log.info("当前4个生成结果均为失败"); + throw new BusinessException("generate.interface.error"); + } + return results; + } + + public Generate selectByUniqueId(String uniqueId) { QueryWrapper qw = new QueryWrapper<>(); qw.eq("unique_id", uniqueId); @@ -438,56 +567,70 @@ public class GenerateServiceImpl extends ServiceImpl i return getOne(qw); } - @Override - @Transactional(rollbackFor = Exception.class) - public void cancelGenerate(Long userId, String uniqueId, String timeZone) { - // 1、确认当前消息是否还在排队中 - Boolean exists = redisUtil.isElementExistsInZSet(consumptionOrderKey, uniqueId); - Boolean flag = Boolean.FALSE; - if (exists) flag = redisUtil.getRank(consumptionOrderKey, uniqueId) > 1L ? Boolean.TRUE : Boolean.FALSE; - // 不管flag的默认值是true还是false,只要exists为false,&& 将短路 - if (exists && flag) { - // 1.1、将需要取消的唯一id加入redis,以便及时取消生成 - redisUtil.addToSet(cancelSetKey, uniqueId); - // 1.2 将需要取消的id从redis的ConsumptionOrder中删除 - redisUtil.removeFromZSet(consumptionOrderKey, uniqueId); - } else { - // 2、判断该消息是否异常 - boolean hasKey = redisUtil.isElementExistsInMap(exceptionMapKey, uniqueId); - // 3、判断该消息是否已经消费结束 - Boolean existsInResult = redisUtil.isElementExistsInMap(resultMapKey, uniqueId); - if (!hasKey && !existsInResult) { - // 设置取等待状态为false - AsyncCallerUtil.waitingStatus.put(uniqueId, false); - // 3、直接发送取消请求到python端 - pythonService.cancelGenerateTask(uniqueId); - } - } + public List selectListByUniqueId(String uniqueId) { + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("unique_id", uniqueId).orderByDesc("id"); - // 3、考虑加一张表,专门用于记录哪些用户在什么时间进行了取消操作 - GenerateCancel generateCancel = new GenerateCancel(userId, uniqueId, DateUtil.getByTimeZone(timeZone)); - generateCancelMapper.insert(generateCancel); + return baseMapper.selectList(qw); } - // 判断试用用户试用generate机会是否使用完毕 - private int getTrialsCount(Long userId, String level1Type){ + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelGenerate(Long userId, List uniqueIdList, String timeZone) { + // todo 取消待优化 + uniqueIdList.forEach(uniqueId -> { + // 1、确认当前消息是否还在排队中 + Boolean exists = redisUtil.isElementExistsInZSet(consumptionOrderKey, uniqueId); + Boolean flag = Boolean.FALSE; + if (exists) flag = redisUtil.getRank(consumptionOrderKey, uniqueId) > 1L ? Boolean.TRUE : Boolean.FALSE; + // 不管flag的默认值是true还是false,只要exists为false,&& 将短路 + if (exists && flag) { + // 1.1、将需要取消的唯一id加入redis,以便及时取消生成 + redisUtil.addToSet(cancelSetKey, uniqueId); + // 1.2 将需要取消的id从redis的ConsumptionOrder中删除 + redisUtil.removeFromZSet(consumptionOrderKey, uniqueId); + } else { + // 2、判断该消息是否异常 + boolean hasKey = redisUtil.isElementExistsInMap(exceptionMapKey, uniqueId); + // 3、判断该消息是否已经消费结束 + Boolean existsInResult = redisUtil.isElementExistsInMap(resultMapKey, uniqueId); + if (!hasKey && !existsInResult) { + // 设置取等待状态为false + AsyncCallerUtil.waitingStatus.put(uniqueId, false); + // 3、直接发送取消请求到python端 + pythonService.cancelGenerateTask(uniqueId); + } + } + String key = generateResultKey + ":" + uniqueId; + redisUtil.addToString(key, new Gson().toJson(new GenerateResultVO(uniqueId, null, null, "Cancelled")), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); + + // 3、考虑加一张表,专门用于记录哪些用户在什么时间进行了取消操作,包括已经异常的请求 + GenerateCancel generateCancel = new GenerateCancel(userId, uniqueId, DateUtil.getByTimeZone(timeZone)); + generateCancelMapper.insert(generateCancel); + }); + + + } + + // 判断试用用户试用generate机会是否使用完毕 每个board 3次机会 + private int getTrialsCount(Long userId, String level1Type) { List getGenerateList = getGenerateByAccountId(userId, level1Type); - int trialsCount ; - if (getGenerateList.isEmpty()){ + int trialsCount; + if (getGenerateList.isEmpty()) { trialsCount = 0; - } else if (getGenerateList.size() == 1) { + } else if (getGenerateList.size() == 1 || (getGenerateList.size() >= 4 && getGenerateList.size() / 4 == 1)) { trialsCount = 1; - } else if (getGenerateList.size() == 2) { + } else if (getGenerateList.size() == 2 || (getGenerateList.size() >= 4 && getGenerateList.size() / 4 == 2)) { trialsCount = 2; - }else { + } else { trialsCount = 2; } return trialsCount; } - public List getGenerateByAccountId(Long accountId, String level1Type){ + public List getGenerateByAccountId(Long accountId, String level1Type) { QueryWrapper qw = new QueryWrapper<>(); - qw.eq("account_id",accountId); + qw.eq("account_id", accountId); qw.eq("level1_type", level1Type); return baseMapper.selectList(qw); diff --git a/src/main/java/com/ai/da/service/impl/LibraryServiceImpl.java b/src/main/java/com/ai/da/service/impl/LibraryServiceImpl.java index d9c10610..080523ed 100644 --- a/src/main/java/com/ai/da/service/impl/LibraryServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/LibraryServiceImpl.java @@ -365,7 +365,7 @@ public class LibraryServiceImpl extends ServiceImpl impl log.info("processSketchBoards请求python 参数:####{}", param); RequestBody body = RequestBody.create(mediaType, param); Request request = new Request.Builder() - .url(accessPythonIp + ":" + accessPythonPort + "/api/sketches_bounding_box") + .url(accessPythonIp + ":" + accessPythonPort + "/api/design_pre_processing") .method("POST", body) // .addHeader("Authorization", "Basic YWlkbGFiOjEyMw==") .addHeader("Content-Type", "application/json") @@ -409,7 +409,8 @@ public class LibraryServiceImpl extends ServiceImpl impl qw.lambda().eq(Library::getLevel2Type, level2Type); qw.lambda().eq(Library::getLevel3Type, sex); } else { - qw.lambda().eq(Library::getLevel2Type, sex); +// qw.lambda().eq(Library::getLevel2Type, sex); + qw.lambda().eq(Library::getLevel3Type, sex); } } qw.lambda().eq(Library::getMd5, md5); diff --git a/src/main/java/com/ai/da/service/impl/PayPalCheckoutServiceImpl.java b/src/main/java/com/ai/da/service/impl/PayPalCheckoutServiceImpl.java index bc7c7434..39eb3206 100644 --- a/src/main/java/com/ai/da/service/impl/PayPalCheckoutServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/PayPalCheckoutServiceImpl.java @@ -3,7 +3,6 @@ package com.ai.da.service.impl; import cn.hutool.core.convert.Convert; import com.ai.da.common.config.PayPalClient; import com.ai.da.common.config.exception.BusinessException; -import com.ai.da.common.constant.PayPalCheckoutConstant; import com.ai.da.common.enums.*; import com.ai.da.common.utils.RedisUtil; import com.ai.da.common.utils.paypalRequest.AuthenticationRequest; @@ -27,7 +26,6 @@ import com.paypal.payments.CapturesRefundRequest; import com.paypal.payments.RefundRequest; import com.paypal.payments.RefundsGetRequest; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -62,6 +60,12 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { @Value("${paypal.client-secret}") private String clientSecret; + @Value("${paypal.mode}") + private String mode; + + @Value("${paypal.webhook_id}") + private String webhookId; + @Resource private PayPalClient payPalClient; @Resource @@ -90,7 +94,7 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { request.requestBody(buildRequestBody(String.valueOf(orderInfo.getTotalFee()), returnUrl)); HttpResponse response = null; try { - response = payPalClient.client(MODE, clientId, clientSecret).execute(request); + response = payPalClient.client(mode, clientId, clientSecret).execute(request); } catch (Exception e) { log.error("调用paypal订单创建失败,失败原因 ===> {}", e.getMessage()); throw new BusinessException("Order creation failed"); @@ -136,21 +140,21 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { webhookRequest.put("transmission_id", SDKUtil.validateAndGet(getHeadersInfo(req), "PAYPAL-TRANSMISSION-ID")); webhookRequest.put("transmission_sig", SDKUtil.validateAndGet(getHeadersInfo(req), "PAYPAL-TRANSMISSION-SIG")); webhookRequest.put("transmission_time", SDKUtil.validateAndGet(getHeadersInfo(req), "PAYPAL-TRANSMISSION-TIME")); - webhookRequest.put("webhook_id", PayPalCheckoutConstant.WEBHOOK_ID); + webhookRequest.put("webhook_id", webhookId); webhookRequest.put("webhook_event", webhookEvent); WebhookVerifyRequest webhookVerifyRequest = new WebhookVerifyRequest(); webhookVerifyRequest.authorization(getOAuth()); webhookVerifyRequest.requestBody(webhookRequest); // 验签 - HttpResponse verified = payPalClient.client(MODE, clientId, clientSecret).execute(webhookVerifyRequest); + HttpResponse verified = payPalClient.client(mode, clientId, clientSecret).execute(webhookVerifyRequest); boolean verifyResult = verified.result().get("verification_status").toString().equals("SUCCESS"); if (verifyResult) { // ### Api Context - APIContext apiContext = new APIContext(clientId, clientSecret, PayPalCheckoutConstant.MODE); + APIContext apiContext = new APIContext(clientId, clientSecret, mode); // Set the webhookId that you received when you created this webhook. - apiContext.addConfiguration(Constants.PAYPAL_WEBHOOK_ID, PayPalCheckoutConstant.WEBHOOK_ID); + apiContext.addConfiguration(Constants.PAYPAL_WEBHOOK_ID, webhookId); Boolean result = Event.validateReceivedEvent(apiContext, getHeadersInfo( req), body); log.info("Webhook Validated: " + result); @@ -323,41 +327,39 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { * @return * @throws SerializeException */ - public String queryOrder(String orderNo) throws SerializeException { + public Order queryOrder(String orderNo) throws SerializeException { OrdersGetRequest request = new OrdersGetRequest(orderNo); HttpResponse response = null; try { - response = payPalClient.client(MODE, clientId, clientSecret).execute(request); + response = payPalClient.client(mode, clientId, clientSecret).execute(request); } catch (Exception e) { log.error("paypal订单查询失败,失败原因 ===> {}", e.getMessage()); + return null; } - System.out.println("Status Code: " + response.statusCode()); - System.out.println("Status: " + response.result().status()); - System.out.println("Order id: " + response.result().id()); + log.debug("Status Code: " + response.statusCode() + "\tStatus: " + response.result().status() + "\tOrder id: " + response.result().id()); if (response.result().purchaseUnits().get(0).payments() != null) { List captures = response.result().purchaseUnits().get(0).payments().captures(); if (captures != null) { for (Capture capture : captures) { - System.out.println("\t订单编号= " + capture.invoiceId() + "\tCapture Id= " + capture.id() + "\tCapture status= " + capture.status() + "\tCapture amount= " + capture.amount().currencyCode() + ":" + capture.amount().value()); + log.debug("\t订单编号= " + capture.invoiceId() + "\tCapture Id= " + capture.id() + "\tCapture status= " + capture.status() + "\tCapture amount= " + capture.amount().currencyCode() + ":" + capture.amount().value()); } } List refunds = response.result().purchaseUnits().get(0).payments().refunds(); if (refunds != null) { for (Refund refund : refunds) { - System.out.println("\t售后编号= " + refund.invoiceId() + "\tRefund Id= " + refund.id() + "\tRefund status= " + refund.status() + "\tRefund amount= " + refund.amount().currencyCode() + ":" + refund.amount().value()); + log.debug("\t售后编号= " + refund.invoiceId() + "\tRefund Id= " + refund.id() + "\tRefund status= " + refund.status() + "\tRefund amount= " + refund.amount().currencyCode() + ":" + refund.amount().value()); } } } - System.out.println("Links: "); for (com.paypal.orders.LinkDescription link : response.result().links()) { - System.out.println("\t" + link.rel() + ": " + link.href() + "\tCall Type: " + link.method()); + log.debug("Links: \t" + link.rel() + ": " + link.href() + "\tCall Type: " + link.method()); } - System.out.println("Full response body:"); + String json = new JSONObject(new Json().serialize(response.result())).toString(4); - System.out.println(json); - return null; + log.info("Full response body: {}", json); + return response.result(); } /** @@ -371,7 +373,7 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { HttpResponse response; try { - response = payPalClient.client(MODE, clientId, clientSecret).execute(request); + response = payPalClient.client(mode, clientId, clientSecret).execute(request); } catch (Exception e) { log.error("调用paypal扣款失败,失败原因 ===> {}", e.getMessage()); throw new BusinessException("Order deduction failed."); @@ -421,7 +423,7 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { public String queryCapture(String orderNo) throws IOException { CapturesGetRequest request = new CapturesGetRequest("扣款id, CaptureOrder生成"); - HttpResponse response = payPalClient.client(MODE, clientId, clientSecret).execute(request); + HttpResponse response = payPalClient.client(mode, clientId, clientSecret).execute(request); System.out.println("Status Code: " + response.statusCode()); System.out.println("Status: " + response.result().status()); System.out.println("Capture ids: " + response.result().id()); @@ -449,7 +451,7 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { ordersGetRequest.authorization("Bearer " + getOAuth()); boolean result; try { - ordersGetResponse = payPalClient.client(MODE, clientId, clientSecret).execute(ordersGetRequest); + ordersGetResponse = payPalClient.client(mode, clientId, clientSecret).execute(ordersGetRequest); } catch (Exception e) { log.error("调用paypal订单查询失败,失败原因 ===> {}", e.getMessage()); throw new BusinessException("Order query failed"); @@ -463,7 +465,7 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { request.requestBody(buildRefundRequestBody(String.valueOf(orderInfo.getTotalFee()), reason)); HttpResponse response = null; try { - response = payPalClient.client(MODE, clientId, clientSecret).execute(request); + response = payPalClient.client(mode, clientId, clientSecret).execute(request); } catch (IOException e) { log.error("调用paypal退款申请失败,失败原因 {}", e.getMessage()); throw new BusinessException("Request for refund failed"); @@ -529,7 +531,7 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { */ public String queryRefund(String orderNo) throws IOException { RefundsGetRequest request = new RefundsGetRequest("退款id RefundOrder生成"); - HttpResponse response = payPalClient.client(MODE, clientId, clientSecret).execute(request); + HttpResponse response = payPalClient.client(mode, clientId, clientSecret).execute(request); System.out.println("Status Code: " + response.statusCode()); System.out.println("Status: " + response.result().status()); System.out.println("Refund Id: " + response.result().id()); @@ -554,7 +556,7 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { AuthenticationRequest authenticationRequest = new AuthenticationRequest(); authenticationRequest.authorization(clientId, clientSecret); try { - HttpResponse authResult = payPalClient.client(MODE, clientId, clientSecret).execute(authenticationRequest); + HttpResponse authResult = payPalClient.client(mode, clientId, clientSecret).execute(authenticationRequest); String accessToken = authResult.result().get("access_token").toString(); long expiresIn = Long.parseLong(authResult.result().get("expires_in").toString()); // 3、存redis @@ -592,6 +594,49 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService { creditsService.buyCredits(orderInfo.getAccountId(), orderInfo.getTotalFee() / Integer.parseInt(CreditsEventsEnum.PRICE.getValue())); } } + + @Override + public void checkOrderStatus(String orderNo) throws SerializeException { + + log.warn("根据订单号核实订单状态 ===> {}", orderNo); + + Order result = this.queryOrder(orderNo); + + // 订单未创建 | 订单异常 | 订单创建过但未支付 + if(result == null || PayPalOrderStatusEnum.CREATED.getStatus().equals(result.status())){ + log.warn("核实订单未创建 ===> {}", orderNo); + //更新本地订单状态 + orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.TIMEOUT_CLOSED); + return ; + } + + // 解析查单响应结果 + String tradeStatus = result.status(); + OrderInfo orderByOrderNo = orderInfoService.getOrderByOrderNo(orderNo); + + // 支付了,但还没完成 + if(PayPalOrderStatusEnum.APPROVED.getStatus().equals(tradeStatus)){ + log.warn("核实订单未支付 ===> {}", orderNo); + // 更新商户端订单状态 + orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.ORDER_PROCESSING); + } + + if(PayPalOrderStatusEnum.COMPLETED.getStatus().equals(tradeStatus)){ + log.warn("核实订单已支付 ===> {}", orderNo); + //如果订单已支付,则更新商户端订单状态 + orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.SUCCESS); + //并记录支付日志 + paymentInfoService.createPaymentInfoForPayPal(result); + // 添加积分变更记录 + creditsService.insertToCreditsDetail(orderByOrderNo.getAccountId(), + CreditsEventsEnum.BUY_CREDITS.getName() + "--Paypal", + CreditsEventsEnum.BUY_CREDITS.getValue(), + "positive"); + // 更新积分 + creditsService.buyCredits(orderByOrderNo.getAccountId(),orderByOrderNo.getTotalFee() / Integer.parseInt(CreditsEventsEnum.PRICE.getValue())); + } + + } } diff --git a/src/main/java/com/ai/da/service/impl/SuperResolutionServiceImpl.java b/src/main/java/com/ai/da/service/impl/SuperResolutionServiceImpl.java index c9ecdec7..eeb565e8 100644 --- a/src/main/java/com/ai/da/service/impl/SuperResolutionServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/SuperResolutionServiceImpl.java @@ -1,6 +1,7 @@ package com.ai.da.service.impl; import com.ai.da.common.config.exception.BusinessException; +import com.ai.da.common.constant.CommonConstant; import com.ai.da.common.context.UserContext; import com.ai.da.common.enums.CreditsEventsEnum; import com.ai.da.common.response.PageBaseResponse; @@ -65,25 +66,24 @@ public class SuperResolutionServiceImpl extends ServiceImpl prepareForSR(List superResolutionDTOList) { Long accountId = UserContext.getUserHolder().getId(); // 1、判断用户当前积分是否够本次超分消耗 - - Boolean credits = creditsService.checkCredits(accountId, CreditsEventsEnum.SUPER_RESOLUTION, superResolutionDTOList.size()); - // todo 积分扣除待升级 - if (credits) { - // 先扣除积分,后失败后再加上 - creditsService.creditsDecrease(accountId, CreditsEventsEnum.SUPER_RESOLUTION.getName()); - } else { + Boolean preDeduction = creditsService.creditsPreDeduction(CreditsEventsEnum.SUPER_RESOLUTION, superResolutionDTOList.size()); + if (!preDeduction) { throw new BusinessException("Not enough Credits"); } ArrayList uuidList = new ArrayList<>(); - for (SuperResolutionDTO superResolutionDTO : superResolutionDTOList) { + // todo 校验倍率是否是2的幂次(前端已做) + // 2、生成唯一id 使用uuid String uuid = UUID.randomUUID().toString(); int num = 1; @@ -119,17 +119,20 @@ public class SuperResolutionServiceImpl extends ServiceImpl(uuid, "SR", name.substring(name.lastIndexOf("/") + 1), superResolutionDTO, "Waiting", LocalDateTime.now().format(dateTimeFormatter))); - // 6、将消息发布到MQ消息队列 + // 7、将消息发布到MQ消息队列 log.info("发送消息到SR_QUEUE,参数 :{}", jsonString); rabbitMQService.publishMessageToSR(jsonString); } - // 6、返回唯一id列表 + // 8、返回唯一id列表 return uuidList; } @@ -156,9 +159,8 @@ public class SuperResolutionServiceImpl extends ServiceImpl i taskDTOS.add(new TaskDTO<>()); } else { SuperResolutionDTO inputParam = taskDTO.getInputParam(); - inputParam.setImages(minioUtil.getPresignedUrl(inputParam.getImages(), 24 * 60)); - taskDTO.setOutputImage(StringUtil.isNullOrEmpty(taskDTO.getOutputImage()) ? null : minioUtil.getPresignedUrl(taskDTO.getOutputImage(), 24 * 60)); + inputParam.setImages(minioUtil.getPresignedUrl(inputParam.getImages(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); + taskDTO.setOutputImage(StringUtil.isNullOrEmpty(taskDTO.getOutputImage()) ? null : minioUtil.getPresignedUrl(taskDTO.getOutputImage(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); taskDTOS.add(taskDTO); } }); @@ -71,7 +72,7 @@ public class TaskListServiceImpl extends ServiceImpl i public void addToTaskListRedis(TaskDTO taskDTO) { String key = taskListKey + ":" + UserContext.getUserHolder().getId() + ":" + taskDTO.getTaskId(); - redisUtil.addToString(key, new Gson().toJson(taskDTO), 24L * 60 * 60 * 3); + redisUtil.addToString(key, new Gson().toJson(taskDTO), CommonConstant.TASK_EXPIRE_TIME); } // 3、更新任务状态 @@ -104,8 +105,8 @@ public class TaskListServiceImpl extends ServiceImpl i // 成功失败的都返回 TaskVO task = new TaskVO(); task.setImageName(s.getInputUrl().substring(s.getInputUrl().lastIndexOf("/") + 1)); - task.setInputImage(minioUtil.getPresignedUrl(s.getInputUrl(), 24 * 60)); - task.setOutputImage(StringUtil.isNullOrEmpty(s.getOutputUrl()) ? null : minioUtil.getPresignedUrl(s.getOutputUrl(), 24 * 60)); + task.setInputImage(minioUtil.getPresignedUrl(s.getInputUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); + task.setOutputImage(StringUtil.isNullOrEmpty(s.getOutputUrl()) ? null : minioUtil.getPresignedUrl(s.getOutputUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); task.setStatus(s.getStatus()); task.setTaskId(s.getTaskId()); task.setCreateDate(s.getCreateTime().format(dateTimeFormatter)); diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 4c8d990c..63a1a5be 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -1,4 +1,4 @@ -server.port=17088 +server.port=5567 spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.primary.jdbcUrl=jdbc:mysql://18.167.251.121:33008/aida?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true @@ -77,9 +77,11 @@ spring.redis.lettuce.pool.max-wait=5 redis.key.orderForGenerate=OrderForGenerate redis.key.generateCancelSet=GenerateCancelSet -redis.key.generateExceptionMap=GenerateExceptionMap +redis.key.generateExceptionMap=Generate:Exception redis.key.resultMap=ResultMap redis.key.orderForSR=OrderForSR redis.key.SRCancelSet=SRCancelSet redis.key.SRExceptionMap=SRExceptionMap -redis.key.taskList=TaskList \ No newline at end of file +redis.key.taskList=TaskList +redis.key.credits.pre-deduction=Credits:PreDeduction +redis.key.generateResult=Generate:Result \ No newline at end of file diff --git a/src/main/resources/mapper/primary/DesignMapper.xml b/src/main/resources/mapper/primary/DesignMapper.xml index edf3f675..6fc69739 100644 --- a/src/main/resources/mapper/primary/DesignMapper.xml +++ b/src/main/resources/mapper/primary/DesignMapper.xml @@ -4,30 +4,45 @@ - - - - - - - - + + + + + + + + - + insert into t_design - (account_id,collection_id,system_scale,single_overall,switch_category,create_date) - values( - #{accountId}, - #{collectionId}, - #{systemScale}, - #{singleOverall}, - #{switchCategory}, - #{createDate}); + (account_id, collection_id, system_scale, single_overall, switch_category, create_date) + values (#{accountId}, + #{collectionId}, + #{systemScale}, + #{singleOverall}, + #{switchCategory}, + #{createDate}); diff --git a/src/main/resources/paypal-sandbox.properties b/src/main/resources/paypal-sandbox.properties index aea3ac83..1b48960c 100644 --- a/src/main/resources/paypal-sandbox.properties +++ b/src/main/resources/paypal-sandbox.properties @@ -1,20 +1,23 @@ -# developer-sandbox -#paypal.client-id=ATbaebYi7-GXWRWJqwRLYMzKEbwjh4BFRqD4Y13i4lZq0rplWIM_IpPrtPKpdkAt_KrPXd6IJTwsDqa5 -#paypal.client-secret=EHWWJqGmmbfjLXqCUpGrvxRYBPPtWvA3hR5ZaAyHlGSVJiHoQPS8skbNaJ9h39VObnchUbgiY2pPu__s -#paypal.receiver.email=sb-ukxfk29608925@business.example.com -#paypal.mode=sandbox +# developer-sandbox-xp +paypal.client-id=ATbaebYi7-GXWRWJqwRLYMzKEbwjh4BFRqD4Y13i4lZq0rplWIM_IpPrtPKpdkAt_KrPXd6IJTwsDqa5 +paypal.client-secret=EHWWJqGmmbfjLXqCUpGrvxRYBPPtWvA3hR5ZaAyHlGSVJiHoQPS8skbNaJ9h39VObnchUbgiY2pPu__s +paypal.receiver.email=sb-ukxfk29608925@business.example.com +paypal.mode=sandbox +# local #paypal.webhook_id=31797347YC028794L +# dev +paypal.webhook_id=51V87014T6406322F -# aida-sandbox +# aida-sandbox-kim #paypal.client-id=AbDDH8jnTrKqjnWLFgEu6LogYzVz2ZLuirE4W54t1M4lrofrP5OzXfhbxqktLLFB-rAO9KeYQVYFJ_tO #paypal.client-secret=EOOoiIAe_dyR2YhY7qCIqWipZvYXCDrmBlFYchphuvkPFms1spsBGTlStlrx580y4hN-EukWwF9m_LAs #paypal.receiver.email=sb-4xe8i29784722@business.example.com #paypal.mode=sandbox #paypal.webhook_id=1WH327112B602422N -# aida-live -paypal.client-id=ASWSIZ3MXJU5w5VOeOHeigWcSw6iinl30ZCipruziKpHclxP0ryf8-7VKG1Ba2VwZwa2DMvGEzTfCTgz -paypal.client-secret=EHQg_K5PSqmp4FJlzEcOEH_kFkmq4aBzaI7jridw53L6cOQRULBAnfv2KakRfrsqaU1PDSkO4Co9Vyxc -paypal.receiver.email=kimwong@code-create.com.hk -paypal.mode=live -paypal.webhook_id=41L14847MC833625B \ No newline at end of file +# aida-live-kim +#paypal.client-id=ASWSIZ3MXJU5w5VOeOHeigWcSw6iinl30ZCipruziKpHclxP0ryf8-7VKG1Ba2VwZwa2DMvGEzTfCTgz +#paypal.client-secret=EHQg_K5PSqmp4FJlzEcOEH_kFkmq4aBzaI7jridw53L6cOQRULBAnfv2KakRfrsqaU1PDSkO4Co9Vyxc +#paypal.receiver.email=kimwong@code-create.com.hk +#paypal.mode=live +#paypal.webhook_id=41L14847MC833625B \ No newline at end of file