diff --git a/pom.xml b/pom.xml
index e20e83e1..db7bdb0b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -151,9 +151,15 @@
3.0.3
+
+
+
+
+
+
com.tencentcloudapi
- tencentcloud-sdk-java-ses
+ tencentcloud-sdk-java
3.1.572
@@ -288,6 +294,28 @@
spring-boot-starter-websocket
+
+ com.google.auth
+ google-auth-library-oauth2-http
+ 1.8.0
+
+
+
+ com.google.api-client
+ google-api-client
+ 1.32.1
+
+
+ com.google.oauth-client
+ google-oauth-client
+ 1.32.1
+
+
+ com.google.http-client
+ google-http-client-jackson2
+ 1.41.5
+
+
diff --git a/src/main/java/com/ai/da/common/config/MyTaskScheduler.java b/src/main/java/com/ai/da/common/config/MyTaskScheduler.java
index 7eb5d0d2..3e73536e 100644
--- a/src/main/java/com/ai/da/common/config/MyTaskScheduler.java
+++ b/src/main/java/com/ai/da/common/config/MyTaskScheduler.java
@@ -51,7 +51,7 @@ public class MyTaskScheduler {
// 定时任务,每十五天执行一次
// @Scheduled(cron = "0 0 0 ? * MON")
- @Scheduled(cron = "0 0 0 */15 * ?")
+// @Scheduled(cron = "0 0 0 */15 * ?")
public void checkExpiry() {
// 检测正式用户是否快要过期
QueryWrapper qw = new QueryWrapper<>();
@@ -85,7 +85,7 @@ public class MyTaskScheduler {
}
}
}
- @Scheduled(cron = "0 0 9 * * ?")
+// @Scheduled(cron = "0 0 9 * * ?")
public void sendTrialOrderExcelToManagements() {
// 获取前一天日期
LocalDate yesterday = LocalDate.now().minusDays(1);
diff --git a/src/main/java/com/ai/da/common/config/exception/TokenMissingOrExpiredException.java b/src/main/java/com/ai/da/common/config/exception/TokenMissingOrExpiredException.java
new file mode 100644
index 00000000..5d47dc41
--- /dev/null
+++ b/src/main/java/com/ai/da/common/config/exception/TokenMissingOrExpiredException.java
@@ -0,0 +1,12 @@
+package com.ai.da.common.config.exception;
+
+public class TokenMissingOrExpiredException extends RuntimeException {
+ public TokenMissingOrExpiredException(String message) {
+ super(message);
+ }
+
+ @Override
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/src/main/java/com/ai/da/common/constant/CommonConstant.java b/src/main/java/com/ai/da/common/constant/CommonConstant.java
index 71f6c86b..35ff4504 100644
--- a/src/main/java/com/ai/da/common/constant/CommonConstant.java
+++ b/src/main/java/com/ai/da/common/constant/CommonConstant.java
@@ -75,5 +75,9 @@ public class CommonConstant {
public static final String PORTFOLIO_DELETED_CN = "作品已删除";
+ public static final String TIME_FORMAT_MMM_dd_yyyy_EEEE = "MMM. dd, yyyy, EEEE";
+ public static final String TIME_FORMAT_MMM_dd_yyyy = "MMM. dd, yyyy";
+
+ public static final String AFFILIATE_LINK = "https://www.aida.com.hk?ref=";
}
diff --git a/src/main/java/com/ai/da/common/enums/AuthenticationOperationTypeEnum.java b/src/main/java/com/ai/da/common/enums/AuthenticationOperationTypeEnum.java
index a8300691..784edb63 100644
--- a/src/main/java/com/ai/da/common/enums/AuthenticationOperationTypeEnum.java
+++ b/src/main/java/com/ai/da/common/enums/AuthenticationOperationTypeEnum.java
@@ -27,7 +27,11 @@ public enum AuthenticationOperationTypeEnum {
/**
* 更改邮箱
*/
- CHANGE_MAILBOX;
+ CHANGE_MAILBOX,
+ /**
+ * 填写用户国家和职业
+ */
+ UPDATE_USERINFO;
public static AuthenticationOperationTypeEnum of(String name) {
return Stream.of(AuthenticationOperationTypeEnum.values()).filter(v -> v.name().equals(name)).findFirst().orElse(null);
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 532934b0..e8565984 100644
--- a/src/main/java/com/ai/da/common/enums/CreditsEventsEnum.java
+++ b/src/main/java/com/ai/da/common/enums/CreditsEventsEnum.java
@@ -8,9 +8,11 @@ import lombok.Getter;
public enum CreditsEventsEnum {
PRICE("price","6"),
+// PRICE("price","1"),// for test
// PRICE("price","0.1"),
BUY_CREDITS("Buy Credits","60"),
+// BUY_CREDITS("Buy Credits","10"),// for test
REFUND("Refund","60"),
// BUY_CREDITS("Buy Credits","10"),
@@ -20,6 +22,7 @@ public enum CreditsEventsEnum {
INIT_MONTHLY("init_monthly", "5000"),
INIT_TRIAL("init_trial", "100"),
INIT_WEEKLY("init_weekly","6000"),
+ RESET_YEAR_CREDITS("reset_year_credits","6000"),
// SUPER_RESOLUTION("Super Resolution","30"),
SUPER_RESOLUTION("Super Resolution","10"),
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 aac9719d..02767686 100644
--- a/src/main/java/com/ai/da/common/enums/OrderStatusEnum.java
+++ b/src/main/java/com/ai/da/common/enums/OrderStatusEnum.java
@@ -10,38 +10,34 @@ public enum OrderStatusEnum {
* 未支付
*/
NOT_PAY("未支付"),
-
-
/**
* 支付成功
*/
SUCCESS("支付成功"),
-
+ /**
+ * 支付失败
+ */
+ FAILURE("支付失败"),
/**
* 已关闭
*/
TIMEOUT_CLOSED("超时已关闭"),
-
/**
* 已取消
*/
CANCEL("用户已取消"),
-
/**
* 退款中
*/
REFUND_PROCESSING("退款中"),
-
/**
* 已退款
*/
REFUND_SUCCESS("已退款"),
-
/**
* 退款异常
*/
REFUND_ABNORMAL("退款异常"),
-
/**
* paypal订单状态为 APPROVED
*/
diff --git a/src/main/java/com/ai/da/common/enums/ProductEnum.java b/src/main/java/com/ai/da/common/enums/ProductEnum.java
new file mode 100644
index 00000000..11237ffe
--- /dev/null
+++ b/src/main/java/com/ai/da/common/enums/ProductEnum.java
@@ -0,0 +1,25 @@
+package com.ai.da.common.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum ProductEnum {
+ // 积分购买
+ CreditsProduct("AiDA credits purchase", 6L),
+ // 年度订阅
+ AnnualSubscription("AiDA Annual Subscription", 5000L),
+ // 月度订阅
+ MonthlySubscription("AiDA Monthly Subscription", 500L),
+ // 测试
+ DailySubscription("AiDA Daily Subscription", 5L),
+ ;
+
+ /**
+ * 类型
+ */
+ private final String name;
+
+ private final Long price;
+}
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 a70bc51b..acd4b1be 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
@@ -1,6 +1,7 @@
package com.ai.da.common.security.filter;
import cn.hutool.core.util.StrUtil;
+import com.ai.da.common.config.exception.TokenMissingOrExpiredException;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.security.config.SecurityProperties;
import com.ai.da.common.security.jwt.JWTTokenHelper;
@@ -51,7 +52,7 @@ public class AuthenticationFilter extends OncePerRequestFilter {
"/api/python/flush","/api/account/healthy","/api/ali-pay/trade/notify","/api/paypal/ipn/back","/api/alipay-hk/trade/notify",
"/api/portfolio/page", "/api/portfolio/detail", "/api/portfolio/commentPage", "/api/portfolio/viewsIncrease",
"/api/account/designWorksRegister","/api/account/questionnaire","/api/stripe/trade/notify",
- "/notification","/api/account/activateNewEmail","/api/third/party/auth/google_callback"
+ "/notification","/api/account/activateNewEmail","/api/third/party/auth/google_callback","/api/third/party/parseGoogleCredential","/api/third/party/receiveDesignResults","/api/third/party/parseWeChatCode"
);
@Override
@@ -101,7 +102,8 @@ public class AuthenticationFilter extends OncePerRequestFilter {
if (StrUtil.isBlank(jwtToken)) {
String ipAddress = RequestInfoUtil.getIpAddress(request);
log.info("本次请求的ip为 : " + ipAddress);
- throw new RuntimeException("请传入token!");
+// throw new RuntimeException("请传入token!");
+ throw new TokenMissingOrExpiredException("请传入token!");
}
if(jwtToken.equals("Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIyIiwic3ViIjoie1wiaWRcIjoyLFwidXNlcm5hbWVcIjpcImxpcnNcIn0iLCJpYXQiOjE2NjU3NDEwODcsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE2NzQzODEwODd9.ShM9R_NNFD7oo1OvxrEgg7PFeWinOuAKkuInUCMQupp66s64Hhv8tN0Wwr83nIN4rHPqtn95wmd4msWcvaFYJA")){
//写死 暂时放行
@@ -112,7 +114,8 @@ public class AuthenticationFilter extends OncePerRequestFilter {
if (validate) {
AuthPrincipalVo principal = jwtTokenHelper.parserToUser(jwtToken);
if (principal == null) {
- throw new RuntimeException("TOKEN已过期,请重新登录!");
+// throw new RuntimeException("TOKEN已过期,请重新登录!");
+ throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(token without userInfo)");
}
//先清空当前线程变量,防止上一个线程遗留
UserContext.delete();
@@ -122,10 +125,12 @@ public class AuthenticationFilter extends OncePerRequestFilter {
String cacheToken = LocalCacheUtils.getTokenCache(String.valueOf(principal.getId()));
if(StringUtils.isEmpty(cacheToken)){
- throw new RuntimeException("TOKEN已过期,请重新登录!");
+// throw new RuntimeException("TOKEN已过期,请重新登录!");
+ throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(local cache empty)");
}
if(!cacheToken.equals(jwtToken) ){
- throw new RuntimeException("TOKEN已过期,请重新登录!");
+// throw new RuntimeException("TOKEN已过期,请重新登录!");
+ throw new TokenMissingOrExpiredException("TOKEN已过期,请重新登录!(token not match local cache)");
}
// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(null, null);
// SecurityContextHolder.getContext().setAuthentication(authentication);
diff --git a/src/main/java/com/ai/da/common/task/AccountTask.java b/src/main/java/com/ai/da/common/task/AccountTask.java
index 6950878d..b4aacac8 100644
--- a/src/main/java/com/ai/da/common/task/AccountTask.java
+++ b/src/main/java/com/ai/da/common/task/AccountTask.java
@@ -1,5 +1,6 @@
package com.ai.da.common.task;
+import com.ai.da.common.utils.RedisUtil;
import com.ai.da.mapper.primary.entity.Account;
import com.ai.da.service.AccountService;
import lombok.extern.slf4j.Slf4j;
@@ -15,25 +16,29 @@ public class AccountTask {
@Resource
private AccountService accountService;
+ @Resource
+ private RedisUtil redisUtil;
/**
* 每周日晚上刷新 年付用户、月付用户的积分
+ * 替换为
+ * 每个月月初只刷新年付用户的积分
*/
- @Scheduled(cron = "59 59 23 ? * SUN")
// @Scheduled(cron = "59 59 23 * * ?")
+ @Scheduled(cron = "0 0 0 1 * ?")
public void refreshCreditsMonthly() {
- log.info("每周日晚11:59:59刷新付费用户积分为 6000");
+ log.info("每月1号0点 将年费用户积分重置为 6000");
accountService.refreshCreditsWeekly();
}
- @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
+// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
public void getPaidUser() {
// 获取code-create 表中 指定日期之后 订单状态为wc-processing的订单
accountService.extendValidityForCC();
}
// 每天凌晨0点执行一次
- @Scheduled(cron = "0 0 0 * * ?")
+// @Scheduled(cron = "0 0 0 * * ?")
public void cancelActivityBenefits() {
// 1、查询当前所有参与了活动且过期的用户
List accountList = accountService.getExpiredUserBySystemUser(4);
@@ -46,7 +51,7 @@ public class AccountTask {
}
// 每天检测正式用户到期情况,每天凌晨0点执行
- @Scheduled(cron = "0 0 0 * * ?")
+// @Scheduled(cron = "0 0 0 * * ?")
public void paidUserToVisitor() {
// 1、查询当前已过期正式用户或试用用户
List accountList = accountService.getExpiredUserBySystemUser(1);
@@ -63,8 +68,15 @@ public class AccountTask {
/**
* 将Code-Create上注册的用户添加为AiDA的游客
*/
- @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
+// @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
public void registerUserToVisitor() {
accountService.registerUserToVisitor();
}
+
+ @Scheduled(cron = "0 0 0 1 * ?")
+ // 每月初刷新所有用户用户名剩余修改次数
+ public void resetUsernameModifyTimes(){
+ log.info("重置所有用户的用户名修改次数");
+ redisUtil.batchDeleteKeysWithSamePrefix(RedisUtil.NICKNAME_MODIFY_TIMES);
+ }
}
diff --git a/src/main/java/com/ai/da/common/task/AliPayTask.java b/src/main/java/com/ai/da/common/task/AliPayTask.java
deleted file mode 100644
index 670a417c..00000000
--- a/src/main/java/com/ai/da/common/task/AliPayTask.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.ai.da.common.task;
-
-import com.ai.da.mapper.primary.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("Alipay orderConfirm 被执行......");
-
- List orderInfoList = orderInfoService.getNoPayOrderByDuration(5, 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/task/GenerateTask.java b/src/main/java/com/ai/da/common/task/GenerateTask.java
deleted file mode 100644
index 038976d0..00000000
--- a/src/main/java/com/ai/da/common/task/GenerateTask.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.ai.da.common.task;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-@Component
-@Slf4j
-public class GenerateTask {
-
-// @Scheduled(cron = "0 0 */1 * * ?")
- public void generateScheduled(){
- log.info("测试定时器:generate");
-
- try{
-
- }catch(Exception e){
-
- }
- }
-}
diff --git a/src/main/java/com/ai/da/common/task/PaymentTask.java b/src/main/java/com/ai/da/common/task/PaymentTask.java
new file mode 100644
index 00000000..f926e6f3
--- /dev/null
+++ b/src/main/java/com/ai/da/common/task/PaymentTask.java
@@ -0,0 +1,122 @@
+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.*;
+import com.paypal.http.exceptions.SerializeException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.util.List;
+
+@Slf4j
+@Component
+public class PaymentTask {
+
+ @Resource
+ private OrderInfoService orderInfoService;
+
+ @Resource
+ private StripeService stripeService;
+
+ @Resource
+ private AffiliateService affiliateService;
+
+ // 考虑删除该定时任务(原因:之后的订单列允许用户查看发票,发票未过期时仍可以支付,所以不需要手动使订单过期)
+// @Scheduled(cron = "0/30 * * * * ?")
+ public void orderConfirmForStripe() throws SerializeException {
+
+ // 查看超过30分钟以上仍未支付的订单 置为超时订单
+ List orderInfoList = orderInfoService.getNoPayOrderByDuration(30, PayTypeEnum.STRIPE.getType());
+
+ for (OrderInfo orderInfo : orderInfoList) {
+ String orderNo = orderInfo.getOrderNo();
+ log.warn("超时订单 ===> {}", orderNo);
+
+ //核实订单状态:调用支付宝查单接口
+ stripeService.checkOrderStatus(orderNo);
+
+ }
+ }
+
+ @Resource
+ private PayPalCheckoutService payPalCheckoutService;
+
+ // @Scheduled(cron = "0/30 * * * * ?")
+ public void orderConfirmForPaypal() throws SerializeException {
+
+// log.info("PayPal orderConfirm 被执行......");
+
+ List orderInfoList = orderInfoService.getNoPayOrderByDuration(30, PayTypeEnum.PAYPAL.getType());
+
+ for (OrderInfo orderInfo : orderInfoList) {
+ String orderNo = orderInfo.getOrderNo();
+ log.warn("超时订单 ===> {}", orderNo);
+
+ //核实订单状态:调用支付宝查单接口
+ payPalCheckoutService.checkOrderStatus(orderNo);
+
+ }
+ }
+
+ @Resource
+ private AliPayService aliPayService;
+
+ /**
+ * 从第0秒开始每隔30秒执行1次,查询创建超过5分钟,并且未支付的订单
+ */
+// @Scheduled(cron = "0/30 * * * * ?")
+ public void orderConfirmForAlipay(){
+/*
+ log.info("Alipay orderConfirm 被执行......");
+
+ List orderInfoList = orderInfoService.getNoPayOrderByDuration(5, PayTypeEnum.ALIPAY.getType());
+
+ for (OrderInfo orderInfo : orderInfoList) {
+ String orderNo = orderInfo.getOrderNo();
+ log.warn("超时订单 ===> {}", orderNo);
+
+ //核实订单状态:调用支付宝查单接口
+ aliPayService.checkOrderStatus(orderNo);
+ }*/
+ }
+
+ // 提前7天向用户发送提醒邮件,每天早上8点执行
+ @Scheduled(cron = "0 0 8 * * ?")
+ public void subscriptionReminder(){
+ stripeService.subscriptionReminder();
+ }
+
+ // 每天凌晨检查subscription中有哪些已过期,更新状态
+// @Scheduled(cron = "0 0 0 * * ?")
+// public void checkSubscriptionExpiration(){
+// stripeService.checkSubscriptionExpiration();
+// }
+
+ // 如果有订阅已创建,但是没有发邮件通知的,需要主动获取回调信息并向用户发送邮件
+ public void checkSubscriptionPayment(){
+ //
+
+ }
+
+ @Scheduled(cron = "0 */5 * * * *") // Run every 5 minutes
+ public void updateAffiliateInfoWithPayment(){
+// log.info("佣金计算定时器");
+ affiliateService.updateAffiliateInfoWithPayment();
+ }
+
+ @Scheduled(cron = "0 0 8 28-31 * ?")
+ public void commissionSummaryReminder(){
+ // 每个月末的最后一天的早上八点执行
+ LocalDate today = LocalDate.now();
+ // 判断是否为月底
+ if (today.plusDays(1).getDayOfMonth() == 1) {
+ log.info("今天是月底,执行佣金结算提醒任务!");
+ affiliateService.commissionCalculation(null, null);
+ }
+ }
+
+}
diff --git a/src/main/java/com/ai/da/common/task/PaypalTask.java b/src/main/java/com/ai/da/common/task/PaypalTask.java
deleted file mode 100644
index 865eaaa4..00000000
--- a/src/main/java/com/ai/da/common/task/PaypalTask.java
+++ /dev/null
@@ -1,42 +0,0 @@
-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(30, 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/task/StripeTask.java b/src/main/java/com/ai/da/common/task/StripeTask.java
deleted file mode 100644
index 45d98997..00000000
--- a/src/main/java/com/ai/da/common/task/StripeTask.java
+++ /dev/null
@@ -1,40 +0,0 @@
-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.StripeService;
-import com.paypal.http.exceptions.SerializeException;
-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 StripeTask {
-
- @Resource
- private OrderInfoService orderInfoService;
-
- @Resource
- private StripeService stripeService;
-
- @Scheduled(cron = "0/30 * * * * ?")
- public void orderConfirm() throws SerializeException {
-
- // 查看超过30分钟以上仍未支付的订单 置为超时订单
- List orderInfoList = orderInfoService.getNoPayOrderByDuration(30, PayTypeEnum.STRIPE.getType());
-
- for (OrderInfo orderInfo : orderInfoList) {
- String orderNo = orderInfo.getOrderNo();
- log.warn("超时订单 ===> {}", orderNo);
-
- //核实订单状态:调用支付宝查单接口
- stripeService.checkOrderStatus(orderNo);
-
- }
- }
-}
diff --git a/src/main/java/com/ai/da/common/utils/DateUtil.java b/src/main/java/com/ai/da/common/utils/DateUtil.java
index 94269826..e386ad54 100644
--- a/src/main/java/com/ai/da/common/utils/DateUtil.java
+++ b/src/main/java/com/ai/da/common/utils/DateUtil.java
@@ -9,8 +9,8 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
-import java.util.Calendar;
import java.util.Date;
+import java.util.Locale;
import java.util.TimeZone;
@Slf4j
@@ -18,6 +18,7 @@ public class DateUtil {
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static final String YYYYMM = "yyyyMM";
public static final String YYYY_MM_DD = "yyyyMMdd";
+ public static final String YYYY_MM_DD_hh_mm_ss = "yyyyMMddHHMMss";
/**
* LocalDate -> Date
@@ -81,4 +82,21 @@ public class DateUtil {
return String.valueOf(epochSecond).substring(0, 10);
}
+ public static String changeTimeStampFormat(Long timeStamp, String type, String format){
+ // 将秒级时间戳转换为毫秒级
+ if (type.equals("seconds")){
+ timeStamp = timeStamp * 1000;
+ }
+ // 输出格式
+ SimpleDateFormat outputFormat = new SimpleDateFormat(format, Locale.ENGLISH);
+ // 创建Date对象
+ Date date = new Date(timeStamp);
+ // 格式化输出
+ return outputFormat.format(date);
+ }
+
+ public static String changeTimeStampFormat(LocalDateTime localDate){
+ return localDate.format(DateTimeFormatter.ofPattern("MMM. dd, yyyy, EEEE", Locale.US));
+ }
+
}
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 7d5295dc..a0d42840 100644
--- a/src/main/java/com/ai/da/common/utils/RedisUtil.java
+++ b/src/main/java/com/ai/da/common/utils/RedisUtil.java
@@ -278,4 +278,26 @@ public class RedisUtil {
// 设置过期时间为 5 分钟(300 秒)
redisTemplate.expire(redisKey, 5, TimeUnit.MINUTES);
}
+
+ public final static String PAYMENT_INFO_LAST_SCAN_TIME = "PaymentInfoLastScanTime";
+
+ public final static String AFFILIATE_LINK_VIEW_KEY = "AffiliateLink:view:";
+
+ public void increaseAffiliateLinkViewCount(Long accountId) {
+ String key = AFFILIATE_LINK_VIEW_KEY + accountId;
+ redisTemplate.opsForValue().increment(key);
+ }
+
+ public Long getAffiliateLinkViewCount(Long accountId) {
+ String key = AFFILIATE_LINK_VIEW_KEY + accountId;
+ return redisTemplate.opsForValue().increment(key, 0);
+ }
+
+ public void batchDeleteKeysWithSamePrefix(String prefix){
+ Set keys = redisTemplate.keys(prefix + "*");
+ assert keys != null;
+ if (!keys.isEmpty()){
+ redisTemplate.delete(keys);
+ }
+ }
}
diff --git a/src/main/java/com/ai/da/common/utils/RequestInfoUtil.java b/src/main/java/com/ai/da/common/utils/RequestInfoUtil.java
index 5f87110e..d041362f 100644
--- a/src/main/java/com/ai/da/common/utils/RequestInfoUtil.java
+++ b/src/main/java/com/ai/da/common/utils/RequestInfoUtil.java
@@ -1,7 +1,16 @@
package com.ai.da.common.utils;
-import javax.servlet.http.HttpServletRequest;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Map;
+
+@Slf4j
public class RequestInfoUtil {
/**
@@ -45,4 +54,58 @@ public class RequestInfoUtil {
return ip;
}
+ /**
+ * 免费 API 服务可能有请求频率限制,如果你需要处理大量 IP 地址,可能需要考虑使用付费服务或购买 IP 地理位置数据库。此外,始终要遵守 API 提供商的使用条款和隐私政策
+ * @param ip https://ip-api.com/docs/api:json 使用的接口api
+ * @return
+ * {
+ * "query": "24.48.0.1",
+ * "status": "success",
+ * "country": "Canada",
+ * "countryCode": "CA",
+ * "region": "QC",
+ * "regionName": "Quebec",
+ * "city": "Montreal",
+ * "zip": "H1L",
+ * "lat": 45.6026,
+ * "lon": -73.5167,
+ * "timezone": "America/Toronto",
+ * "isp": "Le Groupe Videotron Ltee",
+ * "org": "Videotron Ltee",
+ * "as": "AS5769 Videotron Ltee"
+ * }
+ */
+ public static Map getIPLocation(String ip) {
+// String ip = "117.143.125.1"; // 替换为你想查询的 IP 地址
+// String ip = "194.5.48.180"; // 替换为你想查询的 IP 地址
+ String apiURL = "http://ip-api.com/json/" + ip;
+
+ try {
+ URL url = new URL(apiURL);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("GET");
+ conn.setRequestProperty("Accept", "application/json");
+
+ if (conn.getResponseCode() != 200) {
+ throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
+ }
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+ String output;
+ StringBuilder outputBuilder = new StringBuilder();
+ System.out.println("Output from Server .... \n");
+ while ((output = br.readLine()) != null) {
+ outputBuilder.append(output);
+ System.out.println(output);
+ }
+ conn.disconnect();
+ Map map = JSONObject.parseObject(outputBuilder.toString(), Map.class);
+ log.info("map: {}", map);
+ return map;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
}
diff --git a/src/main/java/com/ai/da/common/utils/SendEmailUtil.java b/src/main/java/com/ai/da/common/utils/SendEmailUtil.java
index 25e07339..7770019e 100644
--- a/src/main/java/com/ai/da/common/utils/SendEmailUtil.java
+++ b/src/main/java/com/ai/da/common/utils/SendEmailUtil.java
@@ -2,8 +2,11 @@ package com.ai.da.common.utils;
import com.ai.da.mapper.primary.entity.Account;
import com.ai.da.mapper.primary.entity.TrialOrder;
+import com.ai.da.model.dto.AffiliateEmailParamsDTO;
+import com.ai.da.model.dto.SubscriptionEmailParamsDTO;
import com.alibaba.fastjson.JSONObject;
import com.ai.da.common.config.exception.BusinessException;
+import com.alibaba.fastjson2.JSON;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
@@ -70,7 +73,8 @@ public class SendEmailUtil {
/**
* 绑定邮箱模板id
*/
- public static Long BIND_MAILBOX_TEMPLATE_ID = 45619L;
+// public static Long BIND_MAILBOX_TEMPLATE_ID = 45619L;
+ public static Long BIND_MAILBOX_TEMPLATE_ID = 132754L;
public static Long CHANGE_MAILBOX_TEMPLATE_ID = 128210L;
@@ -175,7 +179,7 @@ public class SendEmailUtil {
subject = "Approval Confirmation for AiDA System Trial Access";
if (country.equals("China")) {
template.setTemplateID(NOTIFICATION_CHINESE_TEMPLATE_ID);
- }else {
+ } else {
template.setTemplateID(NOTIFICATION_TEMPLATE_ID);
}
template.setTemplateData(buildNotificationData(trialOrder, link));
@@ -225,7 +229,7 @@ public class SendEmailUtil {
attachment.setFileName(fileName); // 设置附件文件名
// 设置附件内容
attachment.setContent(Base64.getEncoder().encodeToString(fileContent));
- req.setAttachments(new Attachment[] {attachment});
+ req.setAttachments(new Attachment[]{attachment});
// 发送邮件
SendEmailResponse resp = client.SendEmail(req);
log.info("短信发送结果res###{}", SendEmailResponse.toJsonString(resp));
@@ -268,7 +272,9 @@ public class SendEmailUtil {
throw new BusinessException("failed.to.send.mail");
}
}
+
private final static Long WILLBEEXPIRED_TEMPLATE_ID = 118178L;
+
public static void sendWillBeExpiredEmail(Account account, String senderAddress) {
try {
// 实例化一个认证对象
@@ -360,7 +366,7 @@ public class SendEmailUtil {
jsonObject.put("email", trialOrder.getEmail());
if (link) {
jsonObject.put("days", 14);
- }else {
+ } else {
jsonObject.put("days", 5);
}
return jsonObject.toJSONString();
@@ -370,6 +376,7 @@ public class SendEmailUtil {
private final static Long UPGRADE_SUCCESS_NOTIFICATION_ID = 118856L;
private final static Long UPGRADE_NOTIFICATION_ID_CHINESE = 122898L;
private final static Long UPGRADE_SUCCESS_NOTIFICATION_ID_CHINESE = 122899L;
+
public static void sendUpgradeNotification(Account account, String senderAddress, Integer type) {
try {
// 实例化一个认证对象
@@ -418,7 +425,8 @@ public class SendEmailUtil {
}
private final static Long GENERATE_EXCEPTION_WARNING_ID = 122589L;
- public static void sendGenerateExceptionWarning(String message){
+
+ public static void sendGenerateExceptionWarning(String message) {
try {
// 实例化一个认证对象
Credential cred = new Credential(SECRET_ID, SECRET_KEy);
@@ -457,7 +465,8 @@ public class SendEmailUtil {
private final static Long QUESTIONNAIRE_FEEDBACK_EN_ID = 124151L;
private final static Long QUESTIONNAIRE_FEEDBACK_CN_ID = 124156L;
- public static void questionnaireRelatedNotify(String userName, String email, String language){
+
+ public static void questionnaireRelatedNotify(String userName, String email, String language) {
try {
// 实例化一个认证对象
Credential cred = new Credential(SECRET_ID, SECRET_KEy);
@@ -502,7 +511,7 @@ public class SendEmailUtil {
private final static Long RENEWAL_NOTIFICATION_FOR_OLD_USER_EN = 124892L;
private final static Long RENEWAL_NOTIFICATION_FOR_OLD_USER_CN = 124891L;
- public static void notificationForPaidUser(String receiverAddress, int emailType, String country, String userName, String date){
+ public static void notificationForPaidUser(String receiverAddress, int emailType, String country, String userName, String date) {
try {
// 实例化一个认证对象
Credential cred = new Credential(SECRET_ID, SECRET_KEy);
@@ -525,7 +534,7 @@ public class SendEmailUtil {
subject = "Welcome to AiDA!";
if (country.equals("China")) {
template.setTemplateID(NEW_USER_PAYMENT_NOTIFICATION_CN);
- }else {
+ } else {
template.setTemplateID(NEW_USER_PAYMENT_NOTIFICATION_EN);
}
parameter.put("userName", userName);
@@ -536,7 +545,7 @@ public class SendEmailUtil {
subject = "Account renewal notification";
if (country.equals("China")) {
template.setTemplateID(RENEWAL_NOTIFICATION_FOR_OLD_USER_CN);
- }else {
+ } else {
template.setTemplateID(RENEWAL_NOTIFICATION_FOR_OLD_USER_EN);
}
break;
@@ -597,8 +606,8 @@ public class SendEmailUtil {
private final static Long NEW_USER_REGISTER_NOTIFICATION_EN = 126919L;
- public static void notificationForRegisterUser(String receiverAddress){
- try{
+ public static void notificationForRegisterUser(String receiverAddress) {
+ try {
// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
@@ -634,8 +643,8 @@ public class SendEmailUtil {
private final static Long CHANGE_MAILBOX_CONFIRM_CN = 128278L;
private final static Long CHANGE_MAILBOX_CONFIRM_EN = 128277L;
- public static void changeMailboxConfirm(String receiverAddress, String language, String name, String link){
- try{
+ public static void changeMailboxConfirm(String receiverAddress, String language, String name, String link) {
+ try {
// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
@@ -653,10 +662,10 @@ public class SendEmailUtil {
req.setFromEmailAddress(SEND_ADDRESS);
req.setDestination(new String[]{receiverAddress});
Template template = new Template();
- if (language.equals("ENGLISH")){
+ if (language.equals("ENGLISH")) {
req.setSubject("Change the email address bound to the AiDA account");
template.setTemplateID(CHANGE_MAILBOX_CONFIRM_EN);
- }else {
+ } else {
req.setSubject("更换AiDA账号绑定的邮箱地址");
template.setTemplateID(CHANGE_MAILBOX_CONFIRM_CN);
}
@@ -678,12 +687,12 @@ public class SendEmailUtil {
private final static Long UPLOAD_TIMEOUT_REMINDER = 128324L;
- public static void uploadTimeoutReminder(String userName, String time){
+ public static void uploadTimeoutReminder(String userName, String time) {
String xp = "xupei3360@163.com";
String shb = "shahaibodd99@gmail.com";
String wxd = "X1627315083@163.com";
String pkc = "kaicpang.pang@connect.polyu.hk";
- try{
+ try {
// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
@@ -721,6 +730,7 @@ public class SendEmailUtil {
private final static Long HALFPRICEPROMOTION_CN_ID = 128582L;
private final static Long HALFPRICEPROMOTION_EN_ID = 128583L;
+
public static void halfPricePromotion(Account account, String senderAddress, int type) {
try {
// 实例化一个认证对象
@@ -750,7 +760,7 @@ public class SendEmailUtil {
if (type == 1) {
subject = "AiDA workshop - Win a trip to Hong Kong!";
template.setTemplateID(HALFPRICEPROMOTION_EN_ID);
- }else {
+ } else {
subject = "AiDA workshop - 赢取香港之旅";
template.setTemplateID(HALFPRICEPROMOTION_CN_ID);
}
@@ -808,4 +818,212 @@ public class SendEmailUtil {
throw new BusinessException("failed.to.send.mail");
}
}
+
+ private final static Long CANCEL_MERCHANT_EN = 130720L;
+ private final static Long NEW_MERCHANT_EN = 130721L;
+ private final static Long NEW_USER_EN = 130722L;
+ private final static Long NEW_USER_CN = 130723L;
+ private final static Long RENEWAL_MERCHANT_EN = 130724L;
+ private final static Long RENEWAL_USER_EN = 130725L;
+ private final static Long RENEWAL_USER_CN = 130726L;
+ private final static Long RENEWAL_REMINDER_USER_EN = 130727L;
+ private final static Long RENEWAL_REMINDER_USER_CN = 130728L;
+ private final static Long PAYMENT_FAILED_NEW_MERCHANT_EN = 131230L;
+ private final static Long PAYMENT_FAILED_RENEWAL_MERCHANT_EN = 131225L;
+ private final static Long PAYMENT_FAILED_RENEWAL_USER_EN = 131563L;
+ private final static Long PAYMENT_FAILED_RENEWAL_USER_CN = 131564L;
+
+ public static void subscriptionEmailReminder(String type, SubscriptionEmailParamsDTO subscriptionEmailParamsDTO, String language, String receiverAddress) {
+ try {
+// String merchantEmail = "kimwong@code-create.com.hk";
+ String developer = "xupei3360@163.com";
+ String[] receiverEmail = {/*merchantEmail, */developer};
+ Credential cred = new Credential(SECRET_ID, SECRET_KEy);
+ // 实例化一个http选项,可选的,没有特殊需求可以跳过
+ HttpProfile httpProfile = new HttpProfile();
+ httpProfile.setEndpoint("ses.tencentcloudapi.com");
+ // 实例化一个client选项,可选的,没有特殊需求可以跳过
+ ClientProfile clientProfile = new ClientProfile();
+ clientProfile.setHttpProfile(httpProfile);
+ // 实例化要请求产品的client对象,clientProfile是可选的
+ SesClient client = new SesClient(cred, "ap-hongkong", clientProfile);
+ // 实例化一个请求对象,每个接口都会对应一个request对象
+ SendEmailRequest user = new SendEmailRequest();
+ user.setFromEmailAddress(SEND_ADDRESS);
+ user.setDestination(new String[]{receiverAddress});
+ SendEmailRequest merchant = new SendEmailRequest();
+ merchant.setFromEmailAddress(SEND_ADDRESS);
+ merchant.setDestination(receiverEmail);
+ Template templateUser = new Template();
+ Template templateMerchant = new Template();
+ switch (type) {
+ case "cancel":
+ merchant.setSubject("[Code-Create] Subscription Cancelled");
+ templateMerchant.setTemplateID(CANCEL_MERCHANT_EN);
+ break;
+ case "fail_new":
+ merchant.setSubject("[Code-Create] Payment Failed : New Order (" + subscriptionEmailParamsDTO.getOrderId() + ")");
+ templateMerchant.setTemplateID(PAYMENT_FAILED_NEW_MERCHANT_EN);
+ break;
+ case "fail_renewal":
+ merchant.setSubject("[Code-Create] Payment Failed : Renewal Order (" + subscriptionEmailParamsDTO.getOrderId() + ")");
+ templateMerchant.setTemplateID(PAYMENT_FAILED_RENEWAL_MERCHANT_EN);
+ // todo to user
+ if (language.equals("ENGLISH")) {
+ user.setSubject("[Code-Create] Payment Failed : Renewal Order (" + subscriptionEmailParamsDTO.getOrderId() + ")");
+ templateUser.setTemplateID(PAYMENT_FAILED_RENEWAL_USER_EN);
+ } else {
+ user.setSubject("[Code-Create] 自动续费失败 (" + subscriptionEmailParamsDTO.getOrderId() + ")");
+ templateUser.setTemplateID(PAYMENT_FAILED_RENEWAL_USER_CN);
+ }
+ break;
+ case "new":
+ merchant.setSubject("[Code-Create] New Order(" + subscriptionEmailParamsDTO.getOrderId() + ")");
+ templateMerchant.setTemplateID(NEW_MERCHANT_EN);
+ if (language.equals("ENGLISH")) {
+ user.setSubject("[Code-Create] You have successfully subscribed to AiDA");
+ templateUser.setTemplateID(NEW_USER_EN);
+ } else {
+ user.setSubject("[Code-Create] 您已成功订阅AiDA");
+ templateUser.setTemplateID(NEW_USER_CN);
+ }
+ break;
+ case "renewal":
+ merchant.setSubject("[Code-Create] New subscription renewal order (" + subscriptionEmailParamsDTO.getOrderId() + ")");
+ templateMerchant.setTemplateID(RENEWAL_MERCHANT_EN);
+ if (language.equals("ENGLISH")) {
+ user.setSubject("[Code-Create] AiDA Renewal Successful");
+ templateUser.setTemplateID(RENEWAL_USER_EN);
+ } else {
+ user.setSubject("[Code-Create] AiDA续订成功");
+ templateUser.setTemplateID(RENEWAL_USER_CN);
+ }
+ break;
+ case "reminder":
+ if (language.equals("ENGLISH")) {
+ user.setSubject("[Code-Create] AiDA Subscription Renewal Reminder");
+ templateUser.setTemplateID(RENEWAL_REMINDER_USER_EN);
+ } else {
+ user.setSubject("[Code-Create] AiDA续订提醒");
+ templateUser.setTemplateID(RENEWAL_REMINDER_USER_CN);
+ }
+ break;
+ default:
+ log.error("unknown subscription email type");
+// throw new BusinessException("unknown subscription email type");
+ }
+
+ templateUser.setTemplateData(JSON.toJSONString(subscriptionEmailParamsDTO));
+ user.setTemplate(templateUser);
+
+ templateMerchant.setTemplateData(JSON.toJSONString(subscriptionEmailParamsDTO));
+ merchant.setTemplate(templateMerchant);
+
+ if (!type.equals("cancel") && !type.equals("fail_new")) {
+ // 返回的resp是一个SendEmailResponse的实例,与请求对象对应
+ SendEmailResponse respUser = client.SendEmail(user);
+ log.info("邮件主题:{},发送结果toUser###{}", user.getSubject(), SendEmailResponse.toJsonString(respUser));
+ }
+ if (!type.equals("reminder")) {
+ SendEmailResponse respMerchant = client.SendEmail(merchant);
+ log.info("邮件主题:{},发送结果toMerchant###{}", merchant.getSubject(), SendEmailResponse.toJsonString(respMerchant));
+ }
+ } catch (TencentCloudSDKException e) {
+ log.info("邮件发送失败###{}", e.toString());
+ throw new BusinessException("failed.to.send.mail");
+ }
+ }
+
+ private final static Long NEW_REGISTRATION = 132123L;
+ private final static Long AFFILIATE_ACCEPTED = 132124L;
+ private final static Long AFFILIATE_REFUSED = 132125L;
+ private final static Long AFFILIATE_MONTHLY_SUMMARY = 132126L;
+
+ public static void affiliateEmailReminder(String[] receiverAddress, AffiliateEmailParamsDTO paramsDTO, String type) {
+ try {
+ Credential cred = new Credential(SECRET_ID, SECRET_KEy);
+ // 实例化一个http选项,可选的,没有特殊需求可以跳过
+ HttpProfile httpProfile = new HttpProfile();
+ httpProfile.setEndpoint("ses.tencentcloudapi.com");
+ // 实例化一个client选项,可选的,没有特殊需求可以跳过
+ ClientProfile clientProfile = new ClientProfile();
+ clientProfile.setHttpProfile(httpProfile);
+ // 实例化要请求产品的client对象,clientProfile是可选的
+ SesClient client = new SesClient(cred, "ap-hongkong", clientProfile);
+ // 实例化一个请求对象,每个接口都会对应一个request对象
+ SendEmailRequest req = new SendEmailRequest();
+ req.setFromEmailAddress(SEND_ADDRESS);
+ req.setDestination(receiverAddress);
+ Template template = new Template();
+ switch (type) {
+ case "new":
+ req.setSubject("New Affiliate Registration");
+ template.setTemplateID(NEW_REGISTRATION);
+ break;
+ case "accepted":
+ req.setSubject("Affiliate Application Accepted");
+ template.setTemplateID(AFFILIATE_ACCEPTED);
+ break;
+ case "refused":
+ req.setSubject("Affiliate Application Refused");
+ template.setTemplateID(AFFILIATE_REFUSED);
+ break;
+ case "summary":
+ req.setSubject("Your Monthly AffiliateWP Summary for AiDA");
+ template.setTemplateID(AFFILIATE_MONTHLY_SUMMARY);
+ break;
+ }
+
+ template.setTemplateData(JSON.toJSONString(paramsDTO));
+ req.setTemplate(template);
+
+ // 返回的resp是一个SendEmailResponse的实例,与请求对象对应
+ SendEmailResponse resp = client.SendEmail(req);
+ log.info("短信发送结果res###{}", SendEmailResponse.toJsonString(resp));
+ } catch (TencentCloudSDKException e) {
+ log.info("邮件发送失败###{}", e.toString());
+ throw new BusinessException("failed.to.send.mail");
+ }
+ }
+
+ private final static Long CREDITS_PURCHASE_MERCHANT = 133275L;
+
+ public static void creditsPurchaseReminder(String username, String quantity, String amount) {
+ try {
+ Credential cred = new Credential(SECRET_ID, SECRET_KEy);
+ // 实例化一个http选项,可选的,没有特殊需求可以跳过
+ HttpProfile httpProfile = new HttpProfile();
+ httpProfile.setEndpoint("ses.tencentcloudapi.com");
+ // 实例化一个client选项,可选的,没有特殊需求可以跳过
+ ClientProfile clientProfile = new ClientProfile();
+ clientProfile.setHttpProfile(httpProfile);
+ // 实例化要请求产品的client对象,clientProfile是可选的
+ SesClient client = new SesClient(cred, "ap-hongkong", clientProfile);
+ // 实例化一个请求对象,每个接口都会对应一个request对象
+ SendEmailRequest req = new SendEmailRequest();
+ req.setFromEmailAddress(SEND_ADDRESS);
+ String merchantEmail = "kimwong@code-create.com.hk";
+ String developerEmail = "xupei@code-create.com.hk";
+ req.setDestination(new String[]{merchantEmail, developerEmail});
+ Template template = new Template();
+ req.setSubject("New Credit Purchase Order");
+ template.setTemplateID(CREDITS_PURCHASE_MERCHANT);
+ JSONObject jsonObject = new JSONObject();
+ // 设置试用订单相关数据
+ jsonObject.put("userName", username);
+ jsonObject.put("quantity", quantity);
+ jsonObject.put("totalFee", amount);
+
+ template.setTemplateData(JSON.toJSONString(jsonObject));
+ req.setTemplate(template);
+
+ // 返回的resp是一个SendEmailResponse的实例,与请求对象对应
+ SendEmailResponse resp = client.SendEmail(req);
+ log.info("短信发送结果res###{}", SendEmailResponse.toJsonString(resp));
+ } catch (TencentCloudSDKException e) {
+ log.info("邮件发送失败###{}", e.toString());
+ throw new BusinessException("failed.to.send.mail");
+ }
+ }
+
}
diff --git a/src/main/java/com/ai/da/controller/AccountController.java b/src/main/java/com/ai/da/controller/AccountController.java
index ebf9b8a8..de8dc770 100644
--- a/src/main/java/com/ai/da/controller/AccountController.java
+++ b/src/main/java/com/ai/da/controller/AccountController.java
@@ -3,10 +3,13 @@ package com.ai.da.controller;
import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.response.PageBaseResponse;
import com.ai.da.common.response.Response;
+import com.ai.da.mapper.primary.entity.Account;
+import com.ai.da.mapper.primary.entity.AccountExtend;
import com.ai.da.mapper.primary.entity.TrialOrder;
import com.ai.da.model.dto.*;
import com.ai.da.model.vo.AccountLoginVO;
import com.ai.da.model.vo.AccountPreLoginVO;
+import com.ai.da.model.vo.BindEmailVO;
import com.ai.da.model.vo.PersonalHomepageVO;
import com.ai.da.service.AccountService;
import io.swagger.annotations.Api;
@@ -48,8 +51,8 @@ public class AccountController {
@ApiOperation(value = "绑定邮箱")
@PostMapping("/bindEmail")
- public Response bindEmail(@Valid @RequestBody AccountBindEmailDTO accountBindEmailDTO) {
- return Response.success(accountService.bindEmail(accountBindEmailDTO));
+ public Response bindEmail(@Valid @RequestBody AccountBindEmailDTO accountBindEmailDTO, HttpServletRequest request) {
+ return Response.success(accountService.bindEmail(accountBindEmailDTO, request));
}
@ApiOperation(value = "忘记密码")
@@ -222,7 +225,7 @@ public class AccountController {
@ApiOperation(value = "getUsernameModifyTimes")
@GetMapping("/getNicknameModifyTimes")
- public Response