diff --git a/docker-compose.yml b/docker-compose.yml
index a37c5319..e69de29b 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,10 +0,0 @@
-version: "3"
-services:
- aida_back:
- container_name: stable-version-aida-back
- build: .
-# volumes:
-# # 数据挂载
-# - /workspace/home/aida/file/:/workspace/home/aida/file/
- ports:
- - "10086:5567"
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index af34168f..87a9fc66 100644
--- a/pom.xml
+++ b/pom.xml
@@ -177,6 +177,13 @@
commons-pool2
+
+
+ com.alipay.sdk
+ alipay-sdk-java
+ 4.22.57.ALL
+
+
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 d4e24508..bb4aa412 100644
--- a/src/main/java/com/ai/da/common/RabbitMQ/MQConfig.java
+++ b/src/main/java/com/ai/da/common/RabbitMQ/MQConfig.java
@@ -16,7 +16,9 @@ import org.springframework.beans.factory.annotation.Value;
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-prod";
+// public static final String GENERATE_QUEUE = "generate-queue-test";
+ public static final String GENERATE_QUEUE = "generate-queue-dev";
public MQConfig() {
}
diff --git a/src/main/java/com/ai/da/common/config/AlipayClientConfig.java b/src/main/java/com/ai/da/common/config/AlipayClientConfig.java
new file mode 100644
index 00000000..5b1ec344
--- /dev/null
+++ b/src/main/java/com/ai/da/common/config/AlipayClientConfig.java
@@ -0,0 +1,43 @@
+package com.ai.da.common.config;
+
+import com.alipay.api.*;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+
+import javax.annotation.Resource;
+
+@Configuration
+//加载配置文件
+@PropertySource("classpath:alipay-sandbox.properties")
+public class AlipayClientConfig {
+
+ @Resource
+ private Environment config;
+
+ @Bean
+ public AlipayClient alipayClient() throws AlipayApiException {
+
+ AlipayConfig alipayConfig = new AlipayConfig();
+
+ //设置网关地址
+ alipayConfig.setServerUrl(config.getProperty("alipay.gateway-url"));
+ //设置应用Id
+ alipayConfig.setAppId(config.getProperty("alipay.app-id"));
+ //设置应用私钥
+ alipayConfig.setPrivateKey(config.getProperty("alipay.merchant-private-key"));
+ //设置请求格式,固定值json
+ alipayConfig.setFormat(AlipayConstants.FORMAT_JSON);
+ //设置字符集
+ alipayConfig.setCharset(AlipayConstants.CHARSET_UTF8);
+ //设置支付宝公钥
+ alipayConfig.setAlipayPublicKey(config.getProperty("alipay.alipay-public-key"));
+ //设置签名类型
+ alipayConfig.setSignType(AlipayConstants.SIGN_TYPE_RSA2);
+ //构造client
+ AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
+
+ return alipayClient;
+ }
+}
diff --git a/src/main/java/com/ai/da/common/enums/AliPayTradeStateEnum.java b/src/main/java/com/ai/da/common/enums/AliPayTradeStateEnum.java
new file mode 100644
index 00000000..573ec7dd
--- /dev/null
+++ b/src/main/java/com/ai/da/common/enums/AliPayTradeStateEnum.java
@@ -0,0 +1,39 @@
+package com.ai.da.common.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum AliPayTradeStateEnum {
+
+ /**
+ * 支付成功
+ */
+ SUCCESS("TRADE_SUCCESS"),
+
+ /**
+ * 未支付
+ */
+ NOTPAY("WAIT_BUYER_PAY"),
+
+ /**
+ * 已关闭
+ */
+ CLOSED("TRADE_CLOSED"),
+
+ /**
+ * 退款成功
+ */
+ REFUND_SUCCESS("REFUND_SUCCESS"),
+
+ /**
+ * 退款失败
+ */
+ REFUND_ERROR("REFUND_ERROR");
+
+ /**
+ * 类型
+ */
+ private final String type;
+}
diff --git a/src/main/java/com/ai/da/common/enums/OrderStatusEnum.java b/src/main/java/com/ai/da/common/enums/OrderStatusEnum.java
new file mode 100644
index 00000000..ede1e162
--- /dev/null
+++ b/src/main/java/com/ai/da/common/enums/OrderStatusEnum.java
@@ -0,0 +1,49 @@
+package com.ai.da.common.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum OrderStatusEnum {
+ /**
+ * 未支付
+ */
+ NOT_PAY("未支付"),
+
+
+ /**
+ * 支付成功
+ */
+ SUCCESS("支付成功"),
+
+ /**
+ * 已关闭
+ */
+ CLOSED("超时已关闭"),
+
+ /**
+ * 已取消
+ */
+ CANCEL("用户已取消"),
+
+ /**
+ * 退款中
+ */
+ REFUND_PROCESSING("退款中"),
+
+ /**
+ * 已退款
+ */
+ REFUND_SUCCESS("已退款"),
+
+ /**
+ * 退款异常
+ */
+ REFUND_ABNORMAL("退款异常");
+
+ /**
+ * 类型
+ */
+ private final String type;
+}
diff --git a/src/main/java/com/ai/da/common/enums/PayTypeEnum.java b/src/main/java/com/ai/da/common/enums/PayTypeEnum.java
new file mode 100644
index 00000000..cb2e89f8
--- /dev/null
+++ b/src/main/java/com/ai/da/common/enums/PayTypeEnum.java
@@ -0,0 +1,24 @@
+package com.ai.da.common.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum PayTypeEnum {
+ /**
+ * 微信
+ */
+ WXPAY("微信"),
+
+
+ /**
+ * 支付宝
+ */
+ ALIPAY("支付宝");
+
+ /**
+ * 类型
+ */
+ private final String type;
+}
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 c2625612..6efefd84 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
@@ -47,7 +47,7 @@ public class AuthenticationFilter extends OncePerRequestFilter {
"/api/third/party/addUser","/api/third/party/addTrialUser", "/api/third/party/editUser", "/api/element/initDefaultSysFile",
"/api/third/party/addNoLoginRequiredNew","/api/third/party/deleteNoLoginRequiredNew",
"/api/third/party/existNoLoginRequired","/api/third/party/getRedirectUrl",
- "/api/python/chatStream",
+// "/api/python/chatStream",
"/api/python/flush",
"/api/account/healthy"
);
diff --git a/src/main/java/com/ai/da/common/task/AliPayTask.java b/src/main/java/com/ai/da/common/task/AliPayTask.java
new file mode 100644
index 00000000..0d9c8390
--- /dev/null
+++ b/src/main/java/com/ai/da/common/task/AliPayTask.java
@@ -0,0 +1,42 @@
+package com.ai.da.common.task;
+
+import com.ai.da.mapper.entity.OrderInfo;
+import com.ai.da.common.enums.PayTypeEnum;
+import com.ai.da.service.AliPayService;
+import com.ai.da.service.OrderInfoService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Slf4j
+@Component
+public class AliPayTask {
+
+ @Resource
+ private OrderInfoService orderInfoService;
+
+ @Resource
+ private AliPayService aliPayService;
+
+ /**
+ * 从第0秒开始每隔30秒执行1次,查询创建超过5分钟,并且未支付的订单
+ */
+ @Scheduled(cron = "0/30 * * * * ?")
+ public void orderConfirm(){
+
+ log.info("orderConfirm 被执行......");
+
+ List orderInfoList = orderInfoService.getNoPayOrderByDuration(1, PayTypeEnum.ALIPAY.getType());
+
+ for (OrderInfo orderInfo : orderInfoList) {
+ String orderNo = orderInfo.getOrderNo();
+ log.warn("超时订单 ===> {}", orderNo);
+
+ //核实订单状态:调用支付宝查单接口
+ aliPayService.checkOrderStatus(orderNo);
+ }
+ }
+}
diff --git a/src/main/java/com/ai/da/common/utils/OrderNoUtils.java b/src/main/java/com/ai/da/common/utils/OrderNoUtils.java
new file mode 100644
index 00000000..2b0108de
--- /dev/null
+++ b/src/main/java/com/ai/da/common/utils/OrderNoUtils.java
@@ -0,0 +1,46 @@
+package com.ai.da.common.utils;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Random;
+
+/**
+ * 订单号工具类
+ *
+ * @author qy
+ * @since 1.0
+ */
+public class OrderNoUtils {
+
+ /**
+ * 获取订单编号
+ * @return
+ */
+ public static String getOrderNo() {
+ return "ORDER_" + getNo();
+ }
+
+ /**
+ * 获取退款单编号
+ * @return
+ */
+ public static String getRefundNo() {
+ return "REFUND_" + getNo();
+ }
+
+ /**
+ * 获取编号
+ * @return
+ */
+ public static String getNo() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+ String newDate = sdf.format(new Date());
+ String result = "";
+ Random random = new Random();
+ for (int i = 0; i < 3; i++) {
+ result += random.nextInt(10);
+ }
+ return newDate + result;
+ }
+
+}
diff --git a/src/main/java/com/ai/da/controller/AliPayController.java b/src/main/java/com/ai/da/controller/AliPayController.java
new file mode 100644
index 00000000..a6f3c20f
--- /dev/null
+++ b/src/main/java/com/ai/da/controller/AliPayController.java
@@ -0,0 +1,208 @@
+package com.ai.da.controller;
+
+import com.ai.da.common.response.Response;
+import com.ai.da.mapper.entity.OrderInfo;
+import com.ai.da.service.AliPayService;
+import com.ai.da.service.OrderInfoService;
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayConstants;
+import com.alipay.api.internal.util.AlipaySignature;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.Map;
+
+@CrossOrigin
+@RestController
+@RequestMapping("/api/ali-pay")
+@Api(tags = "网站支付宝支付")
+@Slf4j
+public class AliPayController {
+
+ @Resource
+ private AliPayService aliPayService;
+
+ @Resource
+ private Environment config;
+
+ @Resource
+ private OrderInfoService orderInfoService;
+
+ @ApiOperation("统一收单下单并支付页面接口的调用")
+ @PostMapping("/trade/page/pay/{productId}")
+ public Response tradePagePay(@PathVariable Long productId,@RequestParam String returnUrl){
+
+ System.out.println(productId + " " + returnUrl);
+
+ log.info("统一收单下单并支付页面接口的调用");
+ //支付宝开放平台接受 request 请求对象后
+ // 会为开发者生成一个html 形式的 form表单,包含自动提交的脚本
+ String formStr = aliPayService.tradeCreate(productId, returnUrl);
+ //我们将form表单字符串返回给前端程序,之后前端将会调用自动提交脚本,进行表单的提交
+ //此时,表单会自动提交到action属性所指向的支付宝开放平台中,从而为用户展示一个支付页面
+ return Response.success(formStr);
+ }
+
+ @ApiOperation("支付通知")
+ @PostMapping("/trade/notify")
+ public String tradeNotify(@RequestParam Map params){
+
+ log.info("支付通知正在执行");
+ log.info("通知参数 ===> {}", params);
+
+ String result = "failure";
+
+ try {
+ //异步通知验签
+ boolean signVerified = AlipaySignature.rsaCheckV1(
+ params,
+ config.getProperty("alipay.alipay-public-key"),
+ AlipayConstants.CHARSET_UTF8,
+ AlipayConstants.SIGN_TYPE_RSA2); //调用SDK验证签名
+
+ if(!signVerified){
+ //验签失败则记录异常日志,并在response中返回failure.
+ log.error("支付成功异步通知验签失败!");
+ return result;
+ }
+
+ // 验签成功后
+ log.info("支付成功异步通知验签成功!");
+
+ //按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,
+ //1 商户需要验证该通知数据中的 out_trade_no 是否为商户系统中创建的订单号
+ String outTradeNo = params.get("out_trade_no");
+ OrderInfo order = orderInfoService.getOrderByOrderNo(outTradeNo);
+ if(order == null){
+ log.error("订单不存在");
+ return result;
+ }
+
+ //2 判断 total_amount 是否确实为该订单的实际金额(即商户订单创建时的金额)
+ String totalAmount = params.get("total_amount");
+ int totalAmountInt = new BigDecimal(totalAmount).multiply(new BigDecimal("100")).intValue();
+ int totalFeeInt = order.getTotalFee().intValue();
+ if(totalAmountInt != totalFeeInt){
+ log.error("金额校验失败");
+ return result;
+ }
+
+ //3 校验通知中的 seller_id(或者 seller_email) 是否为 out_trade_no 这笔单据的对应的操作方
+ String sellerId = params.get("seller_id");
+ String sellerIdProperty = config.getProperty("alipay.seller-id");
+ if(!sellerId.equals(sellerIdProperty)){
+ log.error("商家pid校验失败");
+ return result;
+ }
+
+ //4 验证 app_id 是否为该商户本身
+ String appId = params.get("app_id");
+ String appIdProperty = config.getProperty("alipay.app-id");
+ if(!appId.equals(appIdProperty)){
+ log.error("appid校验失败");
+ return result;
+ }
+
+ //在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS时,
+ // 支付宝才会认定为买家付款成功。
+ String tradeStatus = params.get("trade_status");
+ if(!"TRADE_SUCCESS".equals(tradeStatus)){
+ log.error("支付未成功");
+ return result;
+ }
+
+ //处理业务 修改订单状态 记录支付日志
+ aliPayService.processOrder(params);
+
+ //校验成功后在response中返回success并继续商户自身业务处理,校验失败返回failure
+ result = "success";
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * 用户取消订单
+ * @param orderNo
+ * @return
+ */
+ @ApiOperation("用户取消订单")
+ @PostMapping("/trade/close/{orderNo}")
+ public Response cancel(@PathVariable String orderNo){
+
+ log.info("取消订单");
+ aliPayService.cancelOrder(orderNo);
+ return Response.success("订单已取消");
+ }
+
+ /**
+ * 查询订单
+ * @param orderNo
+ * @return
+ */
+ @ApiOperation("查询订单:测试订单状态用")
+ @GetMapping("/trade/query/{orderNo}")
+ public Response queryOrder(@PathVariable String orderNo) {
+
+ log.info("查询订单");
+
+ String result = aliPayService.queryOrder(orderNo);
+ return Response.success(result);
+
+ }
+
+ /**
+ * 申请退款
+ * @param orderNo
+ * @param reason
+ * @return
+ */
+ @ApiOperation("申请退款")
+ @PostMapping("/trade/refund/{orderNo}/{reason}")
+ public Response refunds(@PathVariable String orderNo, @PathVariable String reason){
+
+ log.info("申请退款");
+ aliPayService.refund(orderNo, reason);
+ return Response.success();
+ }
+
+ /**
+ * 查询退款
+ * @param orderNo
+ * @return
+ * @throws Exception
+ */
+ @ApiOperation("查询退款:测试用")
+ @GetMapping("/trade/fastpay/refund/{orderNo}")
+ public Response queryRefund(@PathVariable String orderNo) throws Exception {
+
+ log.info("查询退款");
+
+ String result = aliPayService.queryRefund(orderNo);
+ return Response.success(result);
+ }
+
+ /**
+ * 根据账单类型和日期获取账单url地址
+ *
+ * @param billDate
+ * @param type
+ * @return
+ */
+ @ApiOperation("获取账单url")
+ @GetMapping("/bill/downloadurl/query/{billDate}/{type}")
+ public Response queryTradeBill(
+ @PathVariable String billDate,
+ @PathVariable String type) {
+ log.info("获取账单url");
+ String downloadUrl = aliPayService.queryBill(billDate, type);
+ return Response.success(downloadUrl);
+ }
+
+}
diff --git a/src/main/java/com/ai/da/controller/GenerateController.java b/src/main/java/com/ai/da/controller/GenerateController.java
index b3f6fb5b..c752fbc0 100644
--- a/src/main/java/com/ai/da/controller/GenerateController.java
+++ b/src/main/java/com/ai/da/controller/GenerateController.java
@@ -6,6 +6,7 @@ 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.service.GenerateService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -55,7 +56,7 @@ public class GenerateController {
@ApiOperation(value = "发起生成请求,异步获取结果")
@PostMapping("/prepare")
- public Response prepareForGenerate(@Valid @RequestBody GenerateThroughImageTextDTO generateThroughImageTextDTO) {
+ public Response prepareForGenerate(@Valid @RequestBody GenerateThroughImageTextDTO generateThroughImageTextDTO) {
return Response.success(generateService.prepareForGenerate(generateThroughImageTextDTO));
}
diff --git a/src/main/java/com/ai/da/controller/OrderInfoController.java b/src/main/java/com/ai/da/controller/OrderInfoController.java
new file mode 100644
index 00000000..b71d0e04
--- /dev/null
+++ b/src/main/java/com/ai/da/controller/OrderInfoController.java
@@ -0,0 +1,50 @@
+package com.ai.da.controller;
+
+import com.ai.da.common.enums.OrderStatusEnum;
+import com.ai.da.common.response.Response;
+import com.ai.da.mapper.entity.OrderInfo;
+import com.ai.da.service.OrderInfoService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@CrossOrigin //开放前端的跨域访问
+@Api(tags = "商品订单管理")
+@RestController
+@RequestMapping("/api/order-info")
+public class OrderInfoController {
+
+ @Resource
+ private OrderInfoService orderInfoService;
+
+ @ApiOperation("订单列表")
+ @GetMapping("/list")
+ public Response> list(){
+
+ List list = orderInfoService.listOrderByCreateTimeDesc();
+ return Response.success(list);
+ }
+
+ /**
+ * 查询本地订单状态
+ * @param orderNo
+ * @return
+ */
+ @ApiOperation("查询本地订单状态")
+ @GetMapping("/query-order-status/{orderNo}")
+ public Response queryOrderStatus(@PathVariable String orderNo){
+
+ String orderStatus = orderInfoService.getOrderStatus(orderNo);
+ if(OrderStatusEnum.SUCCESS.getType().equals(orderStatus)){
+ return Response.success("支付成功"); //支付成功
+ }
+
+ return Response.success(101,"支付中......");
+ }
+
+
+
+}
diff --git a/src/main/java/com/ai/da/controller/ProductController.java b/src/main/java/com/ai/da/controller/ProductController.java
new file mode 100644
index 00000000..b22b1537
--- /dev/null
+++ b/src/main/java/com/ai/da/controller/ProductController.java
@@ -0,0 +1,42 @@
+package com.ai.da.controller;
+
+
+import com.ai.da.common.response.Response;
+import com.ai.da.mapper.entity.Product;
+import com.ai.da.service.ProductService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+@CrossOrigin //开放前端的跨域访问
+@Api(tags = "商品管理")
+@RestController
+@RequestMapping("/api/product")
+public class ProductController {
+
+ @Resource
+ private ProductService productService;
+
+ @ApiOperation("测试接口")
+ @GetMapping("/test")
+ public Response test(){
+
+ return Response.success("now" + new Date());
+ }
+
+ @ApiOperation("商品列表")
+ @GetMapping("/list")
+ public Response> list(){
+
+ List list = productService.list();
+ return Response.success(list);
+ }
+
+}
diff --git a/src/main/java/com/ai/da/mapper/OrderInfoMapper.java b/src/main/java/com/ai/da/mapper/OrderInfoMapper.java
new file mode 100644
index 00000000..4b8b6d68
--- /dev/null
+++ b/src/main/java/com/ai/da/mapper/OrderInfoMapper.java
@@ -0,0 +1,8 @@
+package com.ai.da.mapper;
+
+import com.ai.da.mapper.entity.OrderInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+public interface OrderInfoMapper extends BaseMapper {
+
+}
diff --git a/src/main/java/com/ai/da/mapper/PaymentInfoMapper.java b/src/main/java/com/ai/da/mapper/PaymentInfoMapper.java
new file mode 100644
index 00000000..1406b6bc
--- /dev/null
+++ b/src/main/java/com/ai/da/mapper/PaymentInfoMapper.java
@@ -0,0 +1,7 @@
+package com.ai.da.mapper;
+
+import com.ai.da.mapper.entity.PaymentInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+public interface PaymentInfoMapper extends BaseMapper {
+}
diff --git a/src/main/java/com/ai/da/mapper/ProductMapper.java b/src/main/java/com/ai/da/mapper/ProductMapper.java
new file mode 100644
index 00000000..1ffdf2eb
--- /dev/null
+++ b/src/main/java/com/ai/da/mapper/ProductMapper.java
@@ -0,0 +1,8 @@
+package com.ai.da.mapper;
+
+import com.ai.da.mapper.entity.Product;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+public interface ProductMapper extends BaseMapper {
+
+}
diff --git a/src/main/java/com/ai/da/mapper/RefundInfoMapper.java b/src/main/java/com/ai/da/mapper/RefundInfoMapper.java
new file mode 100644
index 00000000..8f9c746e
--- /dev/null
+++ b/src/main/java/com/ai/da/mapper/RefundInfoMapper.java
@@ -0,0 +1,9 @@
+package com.ai.da.mapper;
+
+
+import com.ai.da.mapper.entity.RefundInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+public interface RefundInfoMapper extends BaseMapper {
+
+}
diff --git a/src/main/java/com/ai/da/mapper/primary/entity/OrderInfo.java b/src/main/java/com/ai/da/mapper/primary/entity/OrderInfo.java
new file mode 100644
index 00000000..12255f12
--- /dev/null
+++ b/src/main/java/com/ai/da/mapper/primary/entity/OrderInfo.java
@@ -0,0 +1,25 @@
+package com.ai.da.mapper.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName("t_order_info")
+public class OrderInfo extends BaseEntity{
+
+ private String title;//订单标题
+
+ private String orderNo;//商户订单编号
+
+ private Long userId;//用户id
+
+ private Long productId;//支付产品id
+
+ private Integer totalFee;//订单金额(分)
+
+ private String codeUrl;//订单二维码连接
+
+ private String orderStatus;//订单状态
+
+ private String paymentType;//支付方式
+}
diff --git a/src/main/java/com/ai/da/mapper/primary/entity/PaymentInfo.java b/src/main/java/com/ai/da/mapper/primary/entity/PaymentInfo.java
new file mode 100644
index 00000000..ceacf94a
--- /dev/null
+++ b/src/main/java/com/ai/da/mapper/primary/entity/PaymentInfo.java
@@ -0,0 +1,23 @@
+package com.ai.da.mapper.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName("t_payment_info")
+public class PaymentInfo extends BaseEntity{
+
+ private String orderNo;//商品订单编号
+
+ private String transactionId;//支付系统交易编号
+
+ private String paymentType;//支付类型
+
+ private String tradeType;//交易类型
+
+ private String tradeState;//交易状态
+
+ private Integer payerTotal;//支付金额(分)
+
+ private String content;//通知参数
+}
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
new file mode 100644
index 00000000..9aa55531
--- /dev/null
+++ b/src/main/java/com/ai/da/mapper/primary/entity/Product.java
@@ -0,0 +1,13 @@
+package com.ai.da.mapper.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName("t_product")
+public class Product extends BaseEntity{
+
+ private String title; //商品名称
+
+ private Integer price; //价格(分)
+}
diff --git a/src/main/java/com/ai/da/mapper/primary/entity/RefundInfo.java b/src/main/java/com/ai/da/mapper/primary/entity/RefundInfo.java
new file mode 100644
index 00000000..594be318
--- /dev/null
+++ b/src/main/java/com/ai/da/mapper/primary/entity/RefundInfo.java
@@ -0,0 +1,27 @@
+package com.ai.da.mapper.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName("t_refund_info")
+public class RefundInfo extends BaseEntity{
+
+ private String orderNo;//商品订单编号
+
+ private String refundNo;//退款单编号
+
+ private String refundId;//支付系统退款单号
+
+ private Integer totalFee;//原订单金额(分)
+
+ private Integer refund;//退款金额(分)
+
+ private String reason;//退款原因
+
+ private String refundStatus;//退款单状态
+
+ private String contentReturn;//申请退款返回参数
+
+ private String contentNotify;//退款结果通知参数
+}
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 fd45533c..1adfdbef 100644
--- a/src/main/java/com/ai/da/model/dto/GenerateThroughImageTextDTO.java
+++ b/src/main/java/com/ai/da/model/dto/GenerateThroughImageTextDTO.java
@@ -47,4 +47,7 @@ public class GenerateThroughImageTextDTO {
@ApiModelProperty("唯一id,用于保持消息唯一性")
String uniqueId;
+
+ @ApiModelProperty("是否是测试用户")
+ Boolean isTestUser;
}
diff --git a/src/main/java/com/ai/da/model/vo/PrepareForGenerateVO.java b/src/main/java/com/ai/da/model/vo/PrepareForGenerateVO.java
new file mode 100644
index 00000000..438d94db
--- /dev/null
+++ b/src/main/java/com/ai/da/model/vo/PrepareForGenerateVO.java
@@ -0,0 +1,25 @@
+package com.ai.da.model.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel("prepare for generate响应vo")
+public class PrepareForGenerateVO {
+
+ @ApiModelProperty("uniqueId")
+ private String uniqueId;
+
+ @ApiModelProperty("剩余使用次数")
+ private Integer leftUsageCount;
+
+ public PrepareForGenerateVO(String uniqueId, Integer leftUsageCount) {
+ this.uniqueId = uniqueId;
+ this.leftUsageCount = leftUsageCount;
+ }
+
+ public PrepareForGenerateVO(Integer leftUsageCount) {
+ this.leftUsageCount = leftUsageCount;
+ }
+}
diff --git a/src/main/java/com/ai/da/service/AliPayService.java b/src/main/java/com/ai/da/service/AliPayService.java
new file mode 100644
index 00000000..796126a2
--- /dev/null
+++ b/src/main/java/com/ai/da/service/AliPayService.java
@@ -0,0 +1,22 @@
+package com.ai.da.service;
+
+import java.util.Map;
+
+public interface AliPayService {
+ String tradeCreate(Long productId,String returnUrl);
+
+ void processOrder(Map params);
+
+ void cancelOrder(String orderNo);
+
+ String queryOrder(String orderNo);
+
+ void checkOrderStatus(String orderNo);
+
+ void refund(String orderNo, String reason);
+
+ String queryRefund(String orderNo);
+
+ String queryBill(String billDate, String type);
+
+}
diff --git a/src/main/java/com/ai/da/service/GenerateService.java b/src/main/java/com/ai/da/service/GenerateService.java
index 09b10687..8e3a841c 100644
--- a/src/main/java/com/ai/da/service/GenerateService.java
+++ b/src/main/java/com/ai/da/service/GenerateService.java
@@ -7,6 +7,7 @@ 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.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
@@ -27,7 +28,7 @@ public interface GenerateService extends IService {
GenerateCollectionVO getGenerateResult(String uniqueId);
- String prepareForGenerate(GenerateThroughImageTextDTO generateThroughImageTextDTO);
+ PrepareForGenerateVO prepareForGenerate(GenerateThroughImageTextDTO generateThroughImageTextDTO);
Long getRankPosition(String uniqueId);
diff --git a/src/main/java/com/ai/da/service/OrderInfoService.java b/src/main/java/com/ai/da/service/OrderInfoService.java
new file mode 100644
index 00000000..1507d931
--- /dev/null
+++ b/src/main/java/com/ai/da/service/OrderInfoService.java
@@ -0,0 +1,25 @@
+package com.ai.da.service;
+
+
+import com.ai.da.common.enums.OrderStatusEnum;
+import com.ai.da.mapper.entity.OrderInfo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+public interface OrderInfoService extends IService {
+
+ OrderInfo createOrderByProductId(Long productId, String paymentType);
+
+ void saveCodeUrl(String orderNo, String codeUrl);
+
+ List listOrderByCreateTimeDesc();
+
+ void updateStatusByOrderNo(String orderNo, OrderStatusEnum orderStatus);
+
+ String getOrderStatus(String orderNo);
+
+ List getNoPayOrderByDuration(int minutes, String paymentType);
+
+ OrderInfo getOrderByOrderNo(String orderNo);
+}
diff --git a/src/main/java/com/ai/da/service/PaymentInfoService.java b/src/main/java/com/ai/da/service/PaymentInfoService.java
new file mode 100644
index 00000000..aa1470e4
--- /dev/null
+++ b/src/main/java/com/ai/da/service/PaymentInfoService.java
@@ -0,0 +1,10 @@
+package com.ai.da.service;
+
+import java.util.Map;
+
+public interface PaymentInfoService {
+
+ void createPaymentInfo(String plainText);
+
+ void createPaymentInfoForAliPay(Map params);
+}
diff --git a/src/main/java/com/ai/da/service/ProductService.java b/src/main/java/com/ai/da/service/ProductService.java
new file mode 100644
index 00000000..9ac2597d
--- /dev/null
+++ b/src/main/java/com/ai/da/service/ProductService.java
@@ -0,0 +1,8 @@
+package com.ai.da.service;
+
+import com.ai.da.mapper.entity.Product;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+public interface ProductService extends IService {
+
+}
diff --git a/src/main/java/com/ai/da/service/RefundInfoService.java b/src/main/java/com/ai/da/service/RefundInfoService.java
new file mode 100644
index 00000000..014004cd
--- /dev/null
+++ b/src/main/java/com/ai/da/service/RefundInfoService.java
@@ -0,0 +1,20 @@
+package com.ai.da.service;
+
+
+import com.ai.da.mapper.entity.RefundInfo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+public interface RefundInfoService extends IService {
+
+ RefundInfo createRefundByOrderNo(String orderNo, String reason);
+
+ void updateRefund(String content);
+
+ List getNoRefundOrderByDuration(int minutes);
+
+ RefundInfo createRefundByOrderNoForAliPay(String orderNo, String reason);
+
+ void updateRefundForAliPay(String refundNo, String content, String refundStatus);
+}
diff --git a/src/main/java/com/ai/da/service/impl/AliPayServiceImpl.java b/src/main/java/com/ai/da/service/impl/AliPayServiceImpl.java
new file mode 100644
index 00000000..a018ff9d
--- /dev/null
+++ b/src/main/java/com/ai/da/service/impl/AliPayServiceImpl.java
@@ -0,0 +1,395 @@
+package com.ai.da.service.impl;
+
+import com.ai.da.common.enums.AliPayTradeStateEnum;
+import com.ai.da.common.enums.OrderStatusEnum;
+import com.ai.da.common.enums.PayTypeEnum;
+import com.ai.da.mapper.entity.OrderInfo;
+import com.ai.da.mapper.entity.RefundInfo;
+import com.ai.da.service.AliPayService;
+import com.ai.da.service.OrderInfoService;
+import com.ai.da.service.PaymentInfoService;
+import com.ai.da.service.RefundInfoService;
+import com.alibaba.fastjson.JSONObject;
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.request.*;
+import com.alipay.api.response.*;
+import com.google.gson.Gson;
+import com.google.gson.internal.LinkedTreeMap;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantLock;
+
+@Service
+@Slf4j
+public class AliPayServiceImpl implements AliPayService {
+
+ @Resource
+ private OrderInfoService orderInfoService;
+
+ @Resource
+ private AlipayClient alipayClient;
+
+ @Resource
+ private Environment config;
+
+ @Resource
+ private PaymentInfoService paymentInfoService;
+
+ @Resource
+ private RefundInfoService refundsInfoService;
+
+ private final ReentrantLock lock = new ReentrantLock();
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public String tradeCreate(Long productId, String returnUrl) {
+
+ try {
+ //生成订单
+ log.info("生成订单");
+ OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId, PayTypeEnum.ALIPAY.getType());
+
+ //调用支付宝接口
+ AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
+ //配置需要的公共请求参数
+ //支付完成后,支付宝发起异步通知的地址
+ request.setNotifyUrl(config.getProperty("alipay.notify-url"));
+ //支付完成后,我们想让页面跳转回aida的页面,配置returnUrl
+// request.setReturnUrl(config.getProperty("alipay.return-url"));
+ request.setReturnUrl(returnUrl);
+
+ //组装当前业务方法的请求参数
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_trade_no", orderInfo.getOrderNo());
+ BigDecimal total = new BigDecimal(orderInfo.getTotalFee().toString()).divide(new BigDecimal("100"));
+ bizContent.put("total_amount", total);
+ bizContent.put("subject", orderInfo.getTitle());
+ bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
+
+ request.setBizContent(bizContent.toString());
+
+ //执行请求,调用支付宝接口
+ AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
+
+ if(response.isSuccess()){
+ log.info("调用成功,返回结果 ===> " + response.getBody());
+ return response.getBody();
+ } else {
+ log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
+ throw new RuntimeException("创建支付交易失败");
+ }
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ throw new RuntimeException("创建支付交易失败");
+ }
+ }
+
+ /**
+ * 处理订单
+ * @param params
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void processOrder(Map params) {
+
+ log.info("处理订单");
+
+ //获取订单号
+ String orderNo = params.get("out_trade_no");
+
+ /*在对业务数据进行状态检查和处理之前,
+ 要采用数据锁进行并发控制,
+ 以避免函数重入造成的数据混乱*/
+ //尝试获取锁:
+ // 成功获取则立即返回true,获取失败则立即返回false。不必一直等待锁的释放
+ if(lock.tryLock()) {
+ try {
+
+ //处理重复通知
+ //接口调用的幂等性:无论接口被调用多少次,以下业务执行一次
+ String orderStatus = orderInfoService.getOrderStatus(orderNo);
+ if (!OrderStatusEnum.NOT_PAY.getType().equals(orderStatus)) {
+ return;
+ }
+
+ //更新订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.SUCCESS);
+
+ //记录支付日志
+ paymentInfoService.createPaymentInfoForAliPay(params);
+
+ } finally {
+ //要主动释放锁
+ lock.unlock();
+ }
+ }
+
+ }
+
+ /**
+ * 用户取消订单
+ * @param orderNo
+ */
+ @Override
+ public void cancelOrder(String orderNo) {
+
+ //调用支付宝提供的统一收单交易关闭接口
+ this.closeOrder(orderNo);
+
+ //更新用户订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.CANCEL);
+ }
+
+ /**
+ * 查询订单
+ * @param orderNo
+ * @return 返回订单查询结果,如果返回null则表示支付宝端尚未创建订单
+ */
+ @Override
+ public String queryOrder(String orderNo) {
+
+ try {
+ log.info("查单接口调用 ===> {}", orderNo);
+
+ AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_trade_no", orderNo);
+ request.setBizContent(bizContent.toString());
+
+ AlipayTradeQueryResponse response = alipayClient.execute(request);
+ if(response.isSuccess()){
+ log.info("调用成功,返回结果 ===> " + response.getBody());
+ return response.getBody();
+ } else {
+ log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
+ //throw new RuntimeException("查单接口的调用失败");
+ return null;//订单不存在
+ }
+
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ throw new RuntimeException("查单接口的调用失败");
+ }
+ }
+
+ /**
+ * 根据订单号调用支付宝查单接口,核实订单状态
+ * 如果订单未创建,则更新商户端订单状态
+ * 如果订单未支付,则调用关单接口关闭订单,并更新商户端订单状态
+ * 如果订单已支付,则更新商户端订单状态,并记录支付日志
+ * @param orderNo
+ */
+ @Override
+ public void checkOrderStatus(String orderNo) {
+
+ log.warn("根据订单号核实订单状态 ===> {}", orderNo);
+
+ String result = this.queryOrder(orderNo);
+
+ //订单未创建
+ if(result == null){
+ log.warn("核实订单未创建 ===> {}", orderNo);
+ //更新本地订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.CLOSED);
+ }
+
+ //解析查单响应结果
+ Gson gson = new Gson();
+ HashMap resultMap = gson.fromJson(result, HashMap.class);
+ LinkedTreeMap alipayTradeQueryResponse = resultMap.get("alipay_trade_query_response");
+
+ String tradeStatus = (String)alipayTradeQueryResponse.get("trade_status");
+ if(AliPayTradeStateEnum.NOTPAY.getType().equals(tradeStatus)){
+ log.warn("核实订单未支付 ===> {}", orderNo);
+
+ //如果订单未支付,则调用关单接口关闭订单
+ this.closeOrder(orderNo);
+
+ // 并更新商户端订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.CLOSED);
+ }
+
+ if(AliPayTradeStateEnum.SUCCESS.getType().equals(tradeStatus)){
+ log.warn("核实订单已支付 ===> {}", orderNo);
+
+ //如果订单已支付,则更新商户端订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.SUCCESS);
+
+ //并记录支付日志
+ paymentInfoService.createPaymentInfoForAliPay(alipayTradeQueryResponse);
+ }
+
+ }
+
+ /**
+ * 关单接口的调用
+ * @param orderNo 订单号
+ */
+ private void closeOrder(String orderNo) {
+
+ try {
+ log.info("关单接口的调用,订单号 ===> {}", orderNo);
+
+ AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_trade_no", orderNo);
+ request.setBizContent(bizContent.toString());
+ AlipayTradeCloseResponse response = alipayClient.execute(request);
+
+ if(response.isSuccess()){
+ log.info("调用成功,返回结果 ===> " + response.getBody());
+ } else {
+ log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
+ //throw new RuntimeException("关单接口的调用失败");
+ }
+
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ throw new RuntimeException("关单接口的调用失败");
+ }
+ }
+
+ /**
+ * 退款
+ * @param orderNo
+ * @param reason
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void refund(String orderNo, String reason) {
+
+ try {
+ log.info("调用退款API");
+
+ //创建退款单
+ RefundInfo refundInfo = refundsInfoService.createRefundByOrderNoForAliPay(orderNo, reason);
+
+ //调用统一收单交易退款接口
+ AlipayTradeRefundRequest request = new AlipayTradeRefundRequest ();
+
+ //组装当前业务方法的请求参数
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_trade_no", orderNo);//订单编号
+ BigDecimal refund = new BigDecimal(refundInfo.getRefund().toString()).divide(new BigDecimal("100"));
+ //BigDecimal refund = new BigDecimal("2").divide(new BigDecimal("100"));
+ bizContent.put("refund_amount", refund);//退款金额:不能大于支付金额
+ bizContent.put("refund_reason", reason);//退款原因(可选)
+
+ request.setBizContent(bizContent.toString());
+
+ //执行请求,调用支付宝接口
+ AlipayTradeRefundResponse response = alipayClient.execute(request);
+
+ if(response.isSuccess()){
+ log.info("调用成功,返回结果 ===> " + response.getBody());
+
+ //更新订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.REFUND_SUCCESS);
+
+ //更新退款单
+ refundsInfoService.updateRefundForAliPay(
+ refundInfo.getRefundNo(),
+ response.getBody(),
+ AliPayTradeStateEnum.REFUND_SUCCESS.getType()); //退款成功
+
+ } else {
+ log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
+
+ //更新订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.REFUND_ABNORMAL);
+
+ //更新退款单
+ refundsInfoService.updateRefundForAliPay(
+ refundInfo.getRefundNo(),
+ response.getBody(),
+ AliPayTradeStateEnum.REFUND_ERROR.getType()); //退款失败
+ }
+
+
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ throw new RuntimeException("创建退款申请失败");
+ }
+ }
+
+ /**
+ * 查询退款
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public String queryRefund(String orderNo) {
+
+ try {
+ log.info("查询退款接口调用 ===> {}", orderNo);
+
+ AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("out_trade_no", orderNo);
+ bizContent.put("out_request_no", orderNo);
+ request.setBizContent(bizContent.toString());
+
+ AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
+ if(response.isSuccess()){
+ log.info("调用成功,返回结果 ===> " + response.getBody());
+ return response.getBody();
+ } else {
+ log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
+ //throw new RuntimeException("查单接口的调用失败");
+ return null;//订单不存在
+ }
+
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ throw new RuntimeException("查单接口的调用失败");
+ }
+ }
+
+ /**
+ * 申请账单
+ * @param billDate
+ * @param type
+ * @return
+ */
+ @Override
+ public String queryBill(String billDate, String type) {
+
+ try {
+
+ AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
+ JSONObject bizContent = new JSONObject();
+ bizContent.put("bill_type", type);
+ bizContent.put("bill_date", billDate);
+ request.setBizContent(bizContent.toString());
+ AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);
+
+ if(response.isSuccess()){
+ log.info("调用成功,返回结果 ===> " + response.getBody());
+
+ //获取账单下载地址
+ Gson gson = new Gson();
+ HashMap resultMap = gson.fromJson(response.getBody(), HashMap.class);
+ LinkedTreeMap billDownloadurlResponse = resultMap.get("alipay_data_dataservice_bill_downloadurl_query_response");
+ String billDownloadUrl = (String)billDownloadurlResponse.get("bill_download_url");
+
+ return billDownloadUrl;
+ } else {
+ log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
+ throw new RuntimeException("申请账单失败");
+ }
+
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ throw new RuntimeException("申请账单失败");
+ }
+ }
+
+}
diff --git a/src/main/java/com/ai/da/service/impl/ChatRobotServiceImpl.java b/src/main/java/com/ai/da/service/impl/ChatRobotServiceImpl.java
index fb56d871..7e3ba77d 100644
--- a/src/main/java/com/ai/da/service/impl/ChatRobotServiceImpl.java
+++ b/src/main/java/com/ai/da/service/impl/ChatRobotServiceImpl.java
@@ -74,6 +74,8 @@ public class ChatRobotServiceImpl implements ChatRobotService {
@Value("${minio.bucketName.sysImage}")
private String sysImage;
+ @Resource
+ private AccountMapper accountMapper;
Gson gson = new GsonBuilder().create();
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
@@ -178,7 +180,8 @@ public class ChatRobotServiceImpl implements ChatRobotService {
chatRobot.setSessionId(data.getString("session_id"));
BigDecimal totalCost = data.getBigDecimal("total_cost");
// 校验本次余额够不够
- checkBalance(totalCost, chatSendDTO.getUser_id());
+ ChatRobotVO balance = checkBalance(totalCost, chatSendDTO.getUser_id());
+ if (!Objects.isNull(balance)) return balance;
chatRobot.setTotalCost(totalCost);
chatRobot.setTotalTokens(data.getLong("total_tokens"));
chatRobot.setUserId(chatSendDTO.getUser_id());
@@ -248,7 +251,7 @@ public class ChatRobotServiceImpl implements ChatRobotService {
throw new BusinessException("chat-bot.interface.exception");
}
- private void checkBalance(BigDecimal totalCost, Long userId) {
+ private ChatRobotVO checkBalance(BigDecimal totalCost, Long userId) {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userId);
queryWrapper.ge("create_time", LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0));
@@ -257,10 +260,25 @@ public class ChatRobotServiceImpl implements ChatRobotService {
List chatRobots = chatRobotMapper.selectList(queryWrapper);
if (!CollectionUtils.isEmpty(chatRobots)) {
BigDecimal totalCostUsed = chatRobots.get(0).getTotalCost();
- if (totalCostUsed.add(totalCost).compareTo(BigDecimal.valueOf(5)) > 0) {
- throw new BusinessException("Your balance is insufficient");
+ Account account = accountMapper.selectById(userId);
+ ChatRobot chatRobot = new ChatRobot();
+ if (account.getIsTrial() == 1) {
+ if (totalCostUsed.add(totalCost).compareTo(BigDecimal.valueOf(0.1)) > 0) {
+ String messageFromResource = BusinessException.getMessageFromResource("balance.insufficient.for.trial");
+ chatRobot.setOutput(messageFromResource);
+// throw new BusinessException("Your balance is insufficient");
+ return CopyUtil.copyObject(chatRobot, ChatRobotVO.class);
+ }
+ }else {
+ if (totalCostUsed.add(totalCost).compareTo(BigDecimal.valueOf(5)) > 0) {
+ String messageFromResource = BusinessException.getMessageFromResource("balance.insufficient.for.paying");
+ chatRobot.setOutput(messageFromResource);
+// throw new BusinessException("Your balance is insufficient");
+ return CopyUtil.copyObject(chatRobot, ChatRobotVO.class);
+ }
}
}
+ return null;
}
@Override
@@ -323,9 +341,14 @@ public class ChatRobotServiceImpl implements ChatRobotService {
if (CollectionUtils.isEmpty(chatRobots)) {
return BigDecimal.ONE;
} else {
+ Account account = accountMapper.selectById(userId);
BigDecimal totalCost = BigDecimal.valueOf(5).subtract(chatRobots.get(0).getTotalCost());
- BigDecimal result = totalCost.divide(BigDecimal.valueOf(5), 4, RoundingMode.HALF_UP);
- return result;
+ if (account.getIsTrial() == 1) {
+ totalCost = BigDecimal.valueOf(0.1).subtract(chatRobots.get(0).getTotalCost());
+ return totalCost.divide(BigDecimal.valueOf(0.1), 4, RoundingMode.HALF_UP);
+ }else {
+ return totalCost.divide(BigDecimal.valueOf(5), 4, RoundingMode.HALF_UP);
+ }
}
}
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 14a16046..cae9902e 100644
--- a/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java
+++ b/src/main/java/com/ai/da/service/impl/GenerateServiceImpl.java
@@ -314,7 +314,7 @@ public class GenerateServiceImpl extends ServiceImpl i
}
@Override
- public String prepareForGenerate(GenerateThroughImageTextDTO generateThroughImageTextDTO) {
+ public PrepareForGenerateVO prepareForGenerate(GenerateThroughImageTextDTO generateThroughImageTextDTO) {
// 1、参数检查,判断必须参数是否为空
if (Objects.isNull(generateThroughImageTextDTO.getUserId())) {
throw new BusinessException("userId cannot be empty");
@@ -323,6 +323,16 @@ public class GenerateServiceImpl extends ServiceImpl i
if (!GenerateModeEnum.getGenerateModeList().contains(generateType)) {
throw new BusinessException("unknown.generate.type");
}
+
+ // 判断试用用户是否还有剩余试用机会
+ int trialsCount = 0;
+ if (generateThroughImageTextDTO.getIsTestUser()){
+ trialsCount = getTrialsCount(generateThroughImageTextDTO.getUserId(), generateThroughImageTextDTO.getLevel1Type());
+ if (trialsCount >= 2){
+ return new PrepareForGenerateVO(0);
+ }
+ }
+
String text = generateThroughImageTextDTO.getText();
Long elementId = generateThroughImageTextDTO.getCollectionElementId();
validateGeneraType(new Generate(), text, elementId, generateType);
@@ -361,7 +371,7 @@ public class GenerateServiceImpl extends ServiceImpl i
rabbitMQService.publishMessage(jsonString);
// 5、返回唯一id
- return uuid;
+ return new PrepareForGenerateVO(uuid, 2 - trialsCount);
}
@Override
@@ -458,4 +468,28 @@ public class GenerateServiceImpl extends ServiceImpl i
GenerateCancel generateCancel = new GenerateCancel(userId, uniqueId, DateUtil.getByTimeZone(timeZone));
generateCancelMapper.insert(generateCancel);
}
+
+ // 判断试用用户试用generate机会是否使用完毕
+ private int getTrialsCount(Long userId, String level1Type){
+ List getGenerateList = getGenerateByAccountId(userId, level1Type);
+ int trialsCount ;
+ if (getGenerateList.isEmpty()){
+ trialsCount = 0;
+ } else if (getGenerateList.size() == 1) {
+ trialsCount = 1;
+ } else if (getGenerateList.size() == 2) {
+ trialsCount = 2;
+ }else {
+ trialsCount = 2;
+ }
+ return trialsCount;
+ }
+
+ public List getGenerateByAccountId(Long accountId, String level1Type){
+ QueryWrapper qw = new QueryWrapper<>();
+ 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/OrderInfoServiceImpl.java b/src/main/java/com/ai/da/service/impl/OrderInfoServiceImpl.java
new file mode 100644
index 00000000..aa1f5255
--- /dev/null
+++ b/src/main/java/com/ai/da/service/impl/OrderInfoServiceImpl.java
@@ -0,0 +1,172 @@
+package com.ai.da.service.impl;
+
+
+import com.ai.da.common.enums.OrderStatusEnum;
+import com.ai.da.common.utils.OrderNoUtils;
+import com.ai.da.mapper.OrderInfoMapper;
+import com.ai.da.mapper.ProductMapper;
+import com.ai.da.mapper.entity.OrderInfo;
+import com.ai.da.mapper.entity.Product;
+import com.ai.da.service.OrderInfoService;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.List;
+
+@Service
+@Slf4j
+public class OrderInfoServiceImpl extends ServiceImpl implements OrderInfoService {
+
+ @Resource
+ private ProductMapper productMapper;
+
+ /*@Resource
+ private OrderInfoMapper orderInfoMapper;*/
+
+ @Override
+ public OrderInfo createOrderByProductId(Long productId, String paymentType) {
+
+ //查找已存在但未支付的订单
+ OrderInfo orderInfo = this.getNoPayOrderByProductId(productId, paymentType);
+ if( orderInfo != null){
+ return orderInfo;
+ }
+
+ //获取商品信息
+ Product product = productMapper.selectById(productId);
+
+ //生成订单
+ orderInfo = new OrderInfo();
+ orderInfo.setTitle(product.getTitle());
+ orderInfo.setOrderNo(OrderNoUtils.getOrderNo()); //订单号
+ orderInfo.setProductId(productId);
+ orderInfo.setTotalFee(product.getPrice()); //分
+ orderInfo.setOrderStatus(OrderStatusEnum.NOT_PAY.getType()); //未支付
+ orderInfo.setPaymentType(paymentType);
+ baseMapper.insert(orderInfo);
+
+ return orderInfo;
+ }
+
+ /**
+ * 存储订单二维码
+ * @param orderNo
+ * @param codeUrl
+ */
+ @Override
+ public void saveCodeUrl(String orderNo, String codeUrl) {
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("order_no", orderNo);
+
+ OrderInfo orderInfo = new OrderInfo();
+ orderInfo.setCodeUrl(codeUrl);
+
+ baseMapper.update(orderInfo, queryWrapper);
+ }
+
+ /**
+ * 查询订单列表,并倒序查询
+ * @return
+ */
+ @Override
+ public List listOrderByCreateTimeDesc() {
+
+ QueryWrapper queryWrapper = new QueryWrapper().orderByDesc("create_time");
+ return baseMapper.selectList(queryWrapper);
+ }
+
+ /**
+ * 根据订单号更新订单状态
+ * @param orderNo
+ * @param orderStatus
+ */
+ @Override
+ public void updateStatusByOrderNo(String orderNo, OrderStatusEnum orderStatus) {
+
+ log.info("更新订单状态 ===> {}", orderStatus.getType());
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("order_no", orderNo);
+
+ OrderInfo orderInfo = new OrderInfo();
+ orderInfo.setOrderStatus(orderStatus.getType());
+
+ baseMapper.update(orderInfo, queryWrapper);
+ }
+
+ /**
+ * 根据订单号获取订单状态
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public String getOrderStatus(String orderNo) {
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("order_no", orderNo);
+ OrderInfo orderInfo = baseMapper.selectOne(queryWrapper);
+ if(orderInfo == null){
+ return null;
+ }
+ return orderInfo.getOrderStatus();
+ }
+
+ /**
+ * 查询创建超过minutes分钟并且未支付的订单
+ * @param minutes
+ * @return
+ */
+ @Override
+ public List getNoPayOrderByDuration(int minutes, String paymentType) {
+
+ Instant instant = Instant.now().minus(Duration.ofMinutes(minutes));
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("order_status", OrderStatusEnum.NOT_PAY.getType());
+ queryWrapper.le("create_time", instant);
+ queryWrapper.eq("payment_type", paymentType);
+
+ List orderInfoList = baseMapper.selectList(queryWrapper);
+
+ return orderInfoList;
+ }
+
+ /**
+ * 根据订单号获取订单
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public OrderInfo getOrderByOrderNo(String orderNo) {
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("order_no", orderNo);
+ OrderInfo orderInfo = baseMapper.selectOne(queryWrapper);
+
+ return orderInfo;
+ }
+
+
+ /**
+ * 根据商品id查询未支付订单
+ * 防止重复创建订单对象
+ * @param productId
+ * @return
+ */
+ private OrderInfo getNoPayOrderByProductId(Long productId, String paymentType) {
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("product_id", productId);
+ queryWrapper.eq("order_status", OrderStatusEnum.NOT_PAY.getType());
+ queryWrapper.eq("payment_type", paymentType);
+// queryWrapper.eq("user_id", userId);
+ OrderInfo orderInfo = baseMapper.selectOne(queryWrapper);
+ return orderInfo;
+ }
+}
diff --git a/src/main/java/com/ai/da/service/impl/PaymentInfoServiceImpl.java b/src/main/java/com/ai/da/service/impl/PaymentInfoServiceImpl.java
new file mode 100644
index 00000000..4bafa595
--- /dev/null
+++ b/src/main/java/com/ai/da/service/impl/PaymentInfoServiceImpl.java
@@ -0,0 +1,90 @@
+package com.ai.da.service.impl;
+
+import com.ai.da.common.enums.PayTypeEnum;
+import com.ai.da.mapper.PaymentInfoMapper;
+import com.ai.da.mapper.entity.PaymentInfo;
+import com.ai.da.service.PaymentInfoService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+@Slf4j
+public class PaymentInfoServiceImpl extends ServiceImpl implements PaymentInfoService {
+
+ /**
+ * 记录支付日志:微信支付
+ * @param plainText
+ */
+ @Override
+ public void createPaymentInfo(String plainText) {
+
+ log.info("记录支付日志");
+
+ Gson gson = new Gson();
+ HashMap plainTextMap = gson.fromJson(plainText, HashMap.class);
+
+ //订单号
+ String orderNo = (String)plainTextMap.get("out_trade_no");
+ //业务编号
+ String transactionId = (String)plainTextMap.get("transaction_id");
+ //支付类型
+ String tradeType = (String)plainTextMap.get("trade_type");
+ //交易状态
+ String tradeState = (String)plainTextMap.get("trade_state");
+ //用户实际支付金额
+ Map amount = (Map)plainTextMap.get("amount");
+ Integer payerTotal = ((Double) amount.get("payer_total")).intValue();
+
+ PaymentInfo paymentInfo = new PaymentInfo();
+ paymentInfo.setOrderNo(orderNo);
+ paymentInfo.setPaymentType(PayTypeEnum.WXPAY.getType());
+ paymentInfo.setTransactionId(transactionId);
+ paymentInfo.setTradeType(tradeType);
+ paymentInfo.setTradeState(tradeState);
+ paymentInfo.setPayerTotal(payerTotal);
+ paymentInfo.setContent(plainText);
+
+ baseMapper.insert(paymentInfo);
+ }
+
+ /**
+ * 记录支付日志:支付宝
+ * @param params
+ */
+ @Override
+ public void createPaymentInfoForAliPay(Map params) {
+
+ log.info("记录支付日志");
+
+ //获取订单号
+ String orderNo = params.get("out_trade_no");
+ //业务编号
+ String transactionId = params.get("trade_no");
+ //交易状态
+ String tradeStatus = params.get("trade_status");
+ //交易金额
+ String totalAmount = params.get("total_amount");
+ int totalAmountInt = new BigDecimal(totalAmount).multiply(new BigDecimal("100")).intValue();
+
+
+ PaymentInfo paymentInfo = new PaymentInfo();
+ paymentInfo.setOrderNo(orderNo);
+ paymentInfo.setPaymentType(PayTypeEnum.ALIPAY.getType());
+ paymentInfo.setTransactionId(transactionId);
+ paymentInfo.setTradeType("电脑网站支付");
+ paymentInfo.setTradeState(tradeStatus);
+ paymentInfo.setPayerTotal(totalAmountInt);
+
+ Gson gson = new Gson();
+ String json = gson.toJson(params, HashMap.class);
+ paymentInfo.setContent(json);
+
+ baseMapper.insert(paymentInfo);
+ }
+}
diff --git a/src/main/java/com/ai/da/service/impl/ProductServiceImpl.java b/src/main/java/com/ai/da/service/impl/ProductServiceImpl.java
new file mode 100644
index 00000000..0aa9d4b3
--- /dev/null
+++ b/src/main/java/com/ai/da/service/impl/ProductServiceImpl.java
@@ -0,0 +1,12 @@
+package com.ai.da.service.impl;
+
+import com.ai.da.mapper.ProductMapper;
+import com.ai.da.mapper.entity.Product;
+import com.ai.da.service.ProductService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ProductServiceImpl extends ServiceImpl implements ProductService {
+
+}
diff --git a/src/main/java/com/ai/da/service/impl/RefundInfoServiceImpl.java b/src/main/java/com/ai/da/service/impl/RefundInfoServiceImpl.java
new file mode 100644
index 00000000..f05dd74f
--- /dev/null
+++ b/src/main/java/com/ai/da/service/impl/RefundInfoServiceImpl.java
@@ -0,0 +1,156 @@
+package com.ai.da.service.impl;
+
+import com.ai.da.common.utils.OrderNoUtils;
+import com.ai.da.mapper.RefundInfoMapper;
+import com.ai.da.mapper.entity.OrderInfo;
+import com.ai.da.mapper.entity.RefundInfo;
+import com.ai.da.service.OrderInfoService;
+import com.ai.da.service.RefundInfoService;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.gson.Gson;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class RefundInfoServiceImpl extends ServiceImpl implements RefundInfoService {
+
+ @Resource
+ private OrderInfoService orderInfoService;
+
+ /**
+ * 根据订单号创建退款订单
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public RefundInfo createRefundByOrderNo(String orderNo, String reason) {
+
+ //根据订单号获取订单信息
+ OrderInfo orderInfo = orderInfoService.getOrderByOrderNo(orderNo);
+
+ //根据订单号生成退款订单
+ RefundInfo refundInfo = new RefundInfo();
+ refundInfo.setOrderNo(orderNo);//订单编号
+ refundInfo.setRefundNo(OrderNoUtils.getRefundNo());//退款单编号
+ refundInfo.setTotalFee(orderInfo.getTotalFee());//原订单金额(分)
+ refundInfo.setRefund(orderInfo.getTotalFee());//退款金额(分)
+ refundInfo.setReason(reason);//退款原因
+
+ //保存退款订单
+ baseMapper.insert(refundInfo);
+
+ return refundInfo;
+ }
+
+
+ /**
+ * 记录退款记录
+ * @param content
+ */
+ @Override
+ public void updateRefund(String content) {
+
+ //将json字符串转换成Map
+ Gson gson = new Gson();
+ Map resultMap = gson.fromJson(content, HashMap.class);
+
+ //根据退款单编号修改退款单
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("refund_no", resultMap.get("out_refund_no"));
+
+ //设置要修改的字段
+ RefundInfo refundInfo = new RefundInfo();
+
+ refundInfo.setRefundId(resultMap.get("refund_id"));//微信支付退款单号
+
+ //查询退款和申请退款中的返回参数
+ if(resultMap.get("status") != null){
+ refundInfo.setRefundStatus(resultMap.get("status"));//退款状态
+ refundInfo.setContentReturn(content);//将全部响应结果存入数据库的content字段
+ }
+ //退款回调中的回调参数
+ if(resultMap.get("refund_status") != null){
+ refundInfo.setRefundStatus(resultMap.get("refund_status"));//退款状态
+ refundInfo.setContentNotify(content);//将全部响应结果存入数据库的content字段
+ }
+
+ //更新退款单
+ baseMapper.update(refundInfo, queryWrapper);
+ }
+
+ /**
+ * 找出申请退款超过minutes分钟并且未成功的退款单
+ * @param minutes
+ * @return
+ */
+ @Override
+ public List getNoRefundOrderByDuration(int minutes) {
+
+ //minutes分钟之前的时间
+ Instant instant = Instant.now().minus(Duration.ofMinutes(minutes));
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+// queryWrapper.eq("refund_status", WxRefundStatus.PROCESSING.getType());
+ queryWrapper.le("create_time", instant);
+ List refundInfoList = baseMapper.selectList(queryWrapper);
+ return refundInfoList;
+ }
+
+ /**
+ * 根据订单号创建退款订单
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public RefundInfo createRefundByOrderNoForAliPay(String orderNo, String reason) {
+
+ //根据订单号获取订单信息
+ OrderInfo orderInfo = orderInfoService.getOrderByOrderNo(orderNo);
+
+ //根据订单号生成退款订单
+ RefundInfo refundInfo = new RefundInfo();
+ refundInfo.setOrderNo(orderNo);//订单编号
+ refundInfo.setRefundNo(OrderNoUtils.getRefundNo());//退款单编号
+
+ refundInfo.setTotalFee(orderInfo.getTotalFee());//原订单金额(分)
+ refundInfo.setRefund(orderInfo.getTotalFee());//退款金额(分)
+ refundInfo.setReason(reason);//退款原因
+
+ //保存退款订单
+ baseMapper.insert(refundInfo);
+
+ return refundInfo;
+ }
+
+ /**
+ * 更新退款记录
+ * @param refundNo
+ * @param content
+ * @param refundStatus
+ */
+ @Override
+ public void updateRefundForAliPay(String refundNo, String content, String refundStatus) {
+
+ //根据退款单编号修改退款单
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("refund_no", refundNo);
+
+ //设置要修改的字段
+ RefundInfo refundInfo = new RefundInfo();
+ refundInfo.setRefundStatus(refundStatus);//退款状态
+ refundInfo.setContentReturn(content);//将全部响应结果存入数据库的content字段
+
+ //更新退款单
+ baseMapper.update(refundInfo, queryWrapper);
+
+ }
+
+}
diff --git a/src/main/resources/alipay-sandbox.properties b/src/main/resources/alipay-sandbox.properties
new file mode 100644
index 00000000..45a528e0
--- /dev/null
+++ b/src/main/resources/alipay-sandbox.properties
@@ -0,0 +1,39 @@
+# 支付宝支付相关参数
+
+# 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
+#alipay.app-id=2021000119635499
+alipay.app-id=9021000134653815
+
+# 商户PID,卖家支付宝账号ID
+#alipay.seller-id=2088621957993562
+alipay.seller-id=2088721029614572
+
+# 支付宝网关
+#alipay.gateway-url=https://openapi.alipaydev.com/gateway.do
+alipay.gateway-url=https://openapi-sandbox.dl.alipaydev.com/gateway.do
+
+# 商户私钥,您的PKCS8格式RSA2私钥
+#alipay.merchant-private-key=MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCJPnt6TMZ1A06SMeNxQT0WhGbRd74JBCcdqQt4POzBMJ1NE6U/OiG2xZEnUqYWC2ukkOgZZEvTuWDI9q2aEFN7E2Fcj39JCwRmE0an153JIOkb9L2nngTsAAN7cwLZZ6/dAPnrZjtN0f/HRVBXPSNLBdpoS/pbKRurM2NccZkbTZtluCdt4IvBBjjcV3DJOCYP9yrLTP3HYDxep3HrZCvXuR2Iseb+c6qc4IF/2UKQTz+iavxCy3zJTYbDzD0cL7yC4HmSD7vbNGZvkzZB1RNWt0NILj2LdFG10T7zZahN461FiYozRfD7LDPXqq+uuZMM5i0jpXVrs2MDk6HeS0lJAgMBAAECggEAF87wCrpQ3zGwqqne4+HGYCad046rN9MxmfKeW8Bt7eGqGBnlW7+Q460ITkMHLuHSTZ0ZtnXwtYz+Hj60xPo6ESq+hBkcoqY3oCGN60X7SE3eQoxFblN6VRp3gC3me6KCHpuxv0Vf2lMoxP/gPRINElG0ns03ZCMQerWSchH+1n5xUX/SrsgYDLaHfCxSpGsI/iyjTHXl+KqZeiFoRY+0tlJCTsc6P8JBYEeI5l8Iza/CjxDgFT41B4RksMw9ZEUCwxMiQhqIOThdTxtpA+MpUjoizhngq1xAXMcEz3QlnV7V2icyWjDAAz7bMCISUBa2MLkNWb392/yROKCBcXKYZQKBgQDY5T8QbC3GiUw0IQrVwm1A46zBzMDuQV+a4/2q63f8BBRZcbOluzxuCSfsTIVFKF1eJqpD75+76rB2z39P5xSS2/9SuO9FofV5iUDZuC93mOvR5nwh0rkgizhes81p+i7S9VcQcLTM/gK8ta3VXC3Pv/9bIGlTyFPLS0iMLUJlywKBgQCh/PIjoBFqKWpB6wSTn8hotvvE0WU1XMhm09WnlrMN2O+TuL71PoVS5vhCBgCJW5e3OOOS1K8uYLWaAQY9g/PvzYWLKF7CkCZNTvdds67QMreU9Cfm3jOwUkOibXarJEwY0l52k4xihQ6o8QGvG6XmNw3oq3RX/t/Y0DC84lMKuwKBgQCBQnYIAoBxToe0lXCQnfNgdY8SXEUqeJlShMc7YmM6NPAvsfxfK6vC4///6kaORZUHNEHKhPcMFbyeweBcrRlswGF0WjR2qiPSD4MvfX4EZ4U6rYKS4bNkerPYdI1ZuDjJjl8ZtCF7/XGCJz/25J2Eryauly1OOhf+Etqkd6CXawKBgDlmf4seMm2TBWMcW3/QM9zfUnHY3Ws+WIkPcXs0THiQsbx/z7Lpl6bbz4bdx5zkxusXDpU+JmFhxZgv2r07n9oO0s6P3JxHJjtoywD6Je0Cu8jdh7IodNp7HBpXfaCBeTGmgfC0sh9LFPnKhRU+z9e3FIepEc4Is9uJUmvsKw73AoGAM44/Oz7axzcVEIaD/7jyy1GiaYCmI55qqjocXfbK9QlWDiLnGfbx2UB6BC1y7WD6a9bMpatLXppTDEL+qHX0jUp0u06LQnJi9SAUBcff4LioSJxBrYx6ovYjAEmpoyiW/AAQBJ1oyp1UvpX0avfMa0Hdo1e+YnFEZluCr184uns=
+alipay.merchant-private-key=MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCS8D3aAKvh+juT+5GEXkbKsHtoSK8odQ3htEH3XE+TP5PiXiOiv7pCnVDaIJ5gxfVBeQNC/D7E0zD7J+F1pRFtXA2MQ/ZMXd21hCjkXjIdBBo7iprPKD51AQIHJ8ocjKH0AnCcWAKPN03HvwCbPyYVXHcGO7XrIE2XFgTszsJYOw/dvruVxVF/OEXtVmgOJYIbHQnd+EfJ68BbMWbebzNBgy2YN/EBJldMMoaFcwtei7wCvUcNxWWqaus+n5u9+xFzPX/5495F3clu9yDydIdmvoRYEMdlzb0PbEzGg1KAaIHb8weNVd0bypOTkVK4Y/2tkPfAAv1hF4e6Uf2MAFw5AgMBAAECggEAc1/mAP4T+F0mWLzodrob9dz7GVgxCKBYpQeH4HWAGguKz+zBKHJJCzNBH/UKxsvJFn6xe/BaTOvTAvI+isRw2aC1FpTqmO3/Px6liSMZUEU/X88mXVCpMe/3qqyoeyBFrjYYO/qzD8cJ8LReAohkG9O9tYw+/H8hzWdBuLtkSCft1iHMUFT9M78lHgHIidUZHio+ga55yLEzx8iLibKXeRTFBAtrzknP0SWO25yHtPuPQhmAF8MGDzACm7fFOsccqBH11EmJGUlMAygT89bWXkWSGtPtbmprNe1lVsg0BlyZdgts5qHIrQYAEr/8o/MZI1d3dXv0UC4YTbA1ibaDsQKBgQDWui+5fJ/Xxc30XsSqGU9mgmM2Qf6PrriixTWfbe0Xdw090D+n4zjyfHOjZCEchFbv1FaDNpTt04IZ0bt2Fx6TwhHFxZnIWAMuLLt0ei4A/iCgTfkCrSwvhJ5uuAA5wFDTJIfyQ+JOpk79BVXm5uk2WuvXWTZXIcz2gA4E8PPnJQKBgQCvLnSQkmWCRv9TU8Mk9lXpWruQf8c3oVxvJ0CFDJK3+33PswiZTX+jcymAvK6kd1H0Mg8jJvH+uyeNPyF7aQW8NHasejqRNhyGyj1ZhRTuDIDGs2qIkZv1RAoDB12T0zATMeoJRbycQpOvi6FGI6KkOmjbgVzrrOPLdYh7wKxOhQKBgBg9MEH6BXkwBQ2+3Ohurv3dXiGz1W6WxJTrOiBjIk5xy/bcWTM0fSsyTUN2fB5h+gZcq99n++vU4mzTthughH0dfTAcHD33YXSG7Co72JGYHkq6Qo/AyKociF3rO2tJgFY1W3tHmnZSY7xAK/BCxLS0EsdedLnlQOPalLqOEJpZAoGAOFCq0D7/ut2v/s2SkjNOcvHkEhPBqzSIToNDzoG4OMT0MOzQ+tdbDORclzIQwnZJNkNRcm92o/juQg3laZLdcR88dz3jzgKjMQGar0iE7fG/BCFxQe3tQO9aeJbJklf1wHXvUoPEmkccyvYMJkwWYM0WIFp50JmHsURbV80clzECgYEAjJdoYgyJSKyuOSJQ8DSyAGGmUZdUILNDZl3KTYWAlPySmDqtqRb0nHpr/iOSlCuazEfOm3CnKaNqa7lx+Fyp3JYdYKa218crif4mjAnEoINcxTrCFVCe+bQqj2oYNi+rSptO6ingTUMv9HPjz0U2DhBRFI/pLPyQnOZx70hOCyQ=
+
+# 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥
+#alipay.alipay-public-key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvKoCpGtG31iY2Llj3t8MKRpaVCntnalWmXbKcHCiaYcUUjzcMPH3/tOr5ORK5W1NjuLu9uRrsXqROBmQYN+0y4nea+fU989i2IxtOGR/h2Kvhyyk/lPjNkmgz7K8VqbGGeVzTadPSK49FcrDVEshJ6C92vEKq6TmUfhKgCLiLZ288fHBDRvzUnoj8O/LBXiDroq1zX+DXYCHcQeFljkF5ivyxDZBkWl23hYTtnFClvN5lVLK4d294wyprF7IMv3XhQOfJS+Pr527CsfwT0JE44lyidCvslvn9DSdHdIfTIzHDsIEiDzB/OvRCbwpEA7UGnWQxQf7AusX2TTRQHWW7wIDAQAB
+alipay.alipay-public-key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhDXg0niJ+GSB4VRvPJqzgDhNCP68TRZRLSKLCr/cw6qy911UxRNS96f/ALE7TOLYEsqsolV1inrJ1PU3+BZY9LiKthzEJhdVNzEwXtQrZVknRt3rDtWM2PkKanlQt9LN1Kr28eZ1jJipbkyTLBZOR5RxQ6M6BW0hewrMq/aJLzugP6I7pFHy2iF9zmIm0upy3bUiO5kJwCCXAXfKTG4bLPzhMZCWmDipuscnvR/TN2Nka3WGAJVpiUuRo/poxWKlQpKl6K9rz5RypiAJSaW8zacNyBZ45xIoep3d48v/izOSq2NxLDs6oMUb/BwpJRgfex6dOrnqyIXy0+i9DwEDEwIDAQAB
+
+# 接口内容加密秘钥,对称秘钥
+#alipay.content-key=D8entyfafkkFwtMbUqj3Mw==
+alipay.content-key=hKZgxtPGmOivCphtHM5gNg==
+
+# 页面跳转同步通知页面路径
+alipay.return-url=http://localhost:8080/#/success
+
+# 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
+# 注意:每次重新启动ngrok,都需要根据实际情况修改这个配置
+#alipay.notify-url=https://77ea-221-239-177-21.ngrok.io/api/ali-pay/trade/notify
+#alipay.notify-url=https://03a3-117-143-125-44.ngrok-free.app/api/ali-pay/trade/notify
+alipay.notify-url=https://3b38-18-167-251-121.ngrok-free.app/api/ali-pay/trade/notify
+
+
+
+
+
diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties
index 4e41f8a4..7bd28386 100644
--- a/src/main/resources/application-dev.properties
+++ b/src/main/resources/application-dev.properties
@@ -20,7 +20,8 @@ spring.security.jwtTokenPrefix=Bearer-
spring.security.jwtExpiration=8640000000
#spring security权限设置 认证了token还要认证权限 不然报错Full authentication is required to access this resource
spring.security.ignorePaths=/,/favicon.ico,/doc.html,/webjars/**,/swagger-resources,/v2/api-docs,\
- /api/account/**,/api/element/**,/api/python/**,/api/design/**,/api/history/**,/api/library/**,/api/third/party/**,/api/generate/**,/api/workspace/**,/api/classification/**
+ /api/account/**,/api/element/**,/api/python/**,/api/design/**,/api/history/**,/api/library/**,/api/third/party/**,/api/generate/**,/api/workspace/**,/api/classification/**,\
+ /api/product/**,/api/ali-pay/**,/api/order-info/**
spring.security.authApi=/auth/login
diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties
index e4df2d00..6a2b9d4d 100644
--- a/src/main/resources/application-prod.properties
+++ b/src/main/resources/application-prod.properties
@@ -1,10 +1,11 @@
-server.port=5566
+server.port=5567
#datasource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://18.167.251.121:3306/aida?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=QWa998345
+#spring.datasource.password=QWa998345
#security
spring.security.jwtSecret=JWTSECRET
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index f00b793a..974fee23 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -2,7 +2,7 @@
#spring.profiles.active=test
#����application-prod�ļ�(��������)
-spring.profiles.active=dev
+#spring.profiles.active=prod
#����application-dev�ļ�(��������)
-#spring.profiles.active=dev
+spring.profiles.active=dev
diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties
index 3fa4295a..ca17378d 100644
--- a/src/main/resources/messages_en.properties
+++ b/src/main/resources/messages_en.properties
@@ -152,6 +152,8 @@ classificationName.already.exists=The label name you've entered already exists.
# 用来提醒用户可能会导致不良后果的操作,但不一定是错误。用户需要认真考虑是否继续当前操作。
the.classification.you.deleted.has.associated.library=The label you are attempting to delete is associated with existing data. Are you sure you wish to proceed with deletion?
the.model.has.been.referenced.by.the.workspace=This model is currently in use by a workspace. Deleting it might affect the workspace. Confirm deletion only if you are sure.
+balance.insufficient.for.trial=Want to continue using it immediately? Please consider upgrading to our subscription plan to get more quota.
+balance.insufficient.for.paying=You have reached your usage limit for this month.
# Errors:
# 这类错误是由系统内部错误引起的,用户通常无法自行解决,需要联系支持或等待系统管理员介入。
diff --git a/src/main/resources/messages_zh.properties b/src/main/resources/messages_zh.properties
index 6f330d93..8fecb5f9 100644
--- a/src/main/resources/messages_zh.properties
+++ b/src/main/resources/messages_zh.properties
@@ -150,6 +150,8 @@ classificationName.already.exists=您输入的标签名已存在。请输入不
# 用来提醒用户可能会导致不良后果的操作,但不一定是错误。用户需要认真考虑是否继续当前操作。
the.classification.you.deleted.has.associated.library=您正在尝试删除的标签与现有数据相关联。您确定要继续删除吗?
the.model.has.been.referenced.by.the.workspace=此模型当前正在工作区中使用。删除它可能会影响工作区。仅在确信后再确认删除。
+balance.insufficient.for.trial=想要立即继续使用?请考虑升级到我们的订阅计划,以获得更多额度。
+balance.insufficient.for.paying=您已达到本月的使用额度限制。
# Errors:
# 这类错误是由系统内部错误引起的,用户通常无法自行解决,需要联系支持或等待系统管理员介入。