From c36ba6211a6aa1d2e66149cc533b9d3328d2ac54 Mon Sep 17 00:00:00 2001 From: xupei Date: Tue, 2 Dec 2025 14:34:12 +0800 Subject: [PATCH 1/4] =?UTF-8?q?DEV=20=E6=95=B0=E6=8D=AE=E5=BA=93=E5=88=87?= =?UTF-8?q?=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-dev.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 9e73b8bd..37b6a737 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -1,7 +1,7 @@ server.port=5567 spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.primary.jdbcUrl=jdbc:mysql://18.167.251.121:33008/aida_back?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true +spring.datasource.primary.jdbcUrl=jdbc:mysql://18.167.251.121:33008/aida?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true #spring.datasource.primary.jdbcUrl=jdbc:mysql://18.167.251.121:33008/aida_back?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true #spring.datasource.primary.jdbcUrl=jdbc:mysql://18.167.251.121:33008/test_aida_3.1?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true spring.datasource.primary.username=aida_con From fab0c7b37256357c5884bc3ff55027dfe08f1ee5 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 2 Dec 2025 14:48:23 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20.gitea/workflows/devel?= =?UTF-8?q?op=5Fbuild=5Fmanual.yaml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/develop_build_manual.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/develop_build_manual.yaml b/.gitea/workflows/develop_build_manual.yaml index 2121a10f..597cc4a5 100644 --- a/.gitea/workflows/develop_build_manual.yaml +++ b/.gitea/workflows/develop_build_manual.yaml @@ -157,7 +157,7 @@ jobs: password: ${{ secrets.MAIL_PASSWORD }} # 存储在Secrets中的邮箱密码 subject: 'Gitea Actions 构建通知: ${{ job.status }} - AiDA back-java Develop' # 收件人列表,可以根据需要更改 - to: 'xupei3360@163.com,txli@aidlab.hk,cgzhou@aidlab.hk,zchengrong@yeah.net' # 替换为实际收件人邮箱 + to: 'cgzhou@aidlab.hk,zchengrong@yeah.net' # 替换为实际收件人邮箱 # --- 邮件正文内容 --- body: | From bd69793a728e703b2c44228de35edd7ae3d48136 Mon Sep 17 00:00:00 2001 From: xupei Date: Wed, 3 Dec 2025 13:55:52 +0800 Subject: [PATCH 3/4] =?UTF-8?q?TASK:=E8=AE=A2=E9=98=85=E5=88=B0=E6=9C=9F?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E6=88=96=E7=BB=AD=E8=AE=A2=E9=80=9A=E7=9F=A5?= =?UTF-8?q?(=E6=9A=82=E6=97=B6=E5=85=B3=E9=97=AD=E9=82=AE=E4=BB=B6?= =?UTF-8?q?=E5=8F=91=E9=80=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/task/SubscriptionReminderTask.java | 31 ++++++++++++------- .../com/ai/da/common/utils/SendEmailUtil.java | 15 +++++---- .../ai/da/service/impl/StripeServiceImpl.java | 8 +++-- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/ai/da/common/task/SubscriptionReminderTask.java b/src/main/java/com/ai/da/common/task/SubscriptionReminderTask.java index 7266f30d..07af58db 100644 --- a/src/main/java/com/ai/da/common/task/SubscriptionReminderTask.java +++ b/src/main/java/com/ai/da/common/task/SubscriptionReminderTask.java @@ -10,8 +10,11 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import io.netty.util.internal.StringUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.ZoneOffset; import java.util.ArrayList; import java.util.HashMap; @@ -19,6 +22,7 @@ import java.util.List; import java.util.Map; @Slf4j +@Component @RequiredArgsConstructor public class SubscriptionReminderTask { @@ -32,10 +36,11 @@ public class SubscriptionReminderTask { private static final Map REMINDER_DAYS_CONFIG = new HashMap<>(); static { - REMINDER_DAYS_CONFIG.put("monthly", 7); - REMINDER_DAYS_CONFIG.put("yearly", 14); + REMINDER_DAYS_CONFIG.put("month", 7); + REMINDER_DAYS_CONFIG.put("year", 14); } + @Scheduled(cron = "0 0 9 * * ?") public void subscriptionReminder() { // 获取所有需要通知的订阅 List subscriptionInfos = getDueSubscriptions(); @@ -52,7 +57,7 @@ public class SubscriptionReminderTask { continue; } - boolean success = stripeService.sendEmail(subscriptionInfo.getSubscriptionId(), "reminder_subscriber", null); + boolean success = stripeService.sendEmail(subscriptionInfo.getSubscriptionId(), emailType, subscriptionInfo.getOrderNo()); if (success) { log.info("提前{}天向用户 {} 发送续订通知邮件,订阅类型: {}", daysBefore, subscriptionInfo.getAccountId(), subscriptionInfo.getType()); @@ -78,26 +83,30 @@ public class SubscriptionReminderTask { LocalDateTime startOfDay = targetDate.toLocalDate().atStartOfDay(); LocalDateTime endOfDay = targetDate.toLocalDate().atTime(23, 59, 59); - long startTimestamp = startOfDay.toEpochSecond(ZoneOffset.UTC); - long endTimestamp = endOfDay.toEpochSecond(ZoneOffset.UTC); + // 使用系统默认时区 + ZoneId zoneId = ZoneId.systemDefault(); + long startTimestamp = startOfDay.atZone(zoneId).toEpochSecond(); + long endTimestamp = endOfDay.atZone(zoneId).toEpochSecond(); QueryWrapper qw = new QueryWrapper<>(); - qw.ge("current_period_end", startTimestamp); - qw.lt("current_period_end", endTimestamp); + qw.lambda().ge(SubscriptionInfo::getCurrentPeriodEnd, startTimestamp); + qw.lambda().lt(SubscriptionInfo::getCurrentPeriodEnd, endTimestamp); // qw.eq("status", "active"); - qw.eq("subscription_type", subscriptionType); + qw.lambda().eq(SubscriptionInfo::getType, subscriptionType); return subscriptionInfoMapper.selectList(qw); } + @Scheduled(cron = "0 0 9 * * ?") public void trialReminder() { // 今天的 00:00:00 和 23:59:59 LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay(); LocalDateTime endOfDay = LocalDateTime.now().toLocalDate().atTime(23, 59, 59); - // 转为时间戳 - long startTimestamp = startOfDay.toEpochSecond(ZoneOffset.UTC); - long endTimestamp = endOfDay.toEpochSecond(ZoneOffset.UTC); + // 使用系统默认时区 + ZoneId zoneId = ZoneId.systemDefault(); + long startTimestamp = startOfDay.atZone(zoneId).toEpochSecond() * 1000; + long endTimestamp = endOfDay.atZone(zoneId).toEpochSecond() * 1000; QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().gt(Account::getValidEndTime, startTimestamp) 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 c155b463..6712ac2c 100644 --- a/src/main/java/com/ai/da/common/utils/SendEmailUtil.java +++ b/src/main/java/com/ai/da/common/utils/SendEmailUtil.java @@ -21,6 +21,7 @@ import org.springframework.util.StringUtils; import java.util.Base64; import java.util.Date; +import java.util.Objects; /** * 邮件发送类 @@ -832,7 +833,7 @@ public class SendEmailUtil { if (language.equals("ENGLISH")) { user.setSubject("[Code-Create] AiDA Subscription Renewal Reminder"); templateUser.setTemplateID(156072L); - } else if (language.equals("CHINESE")){ + } else if (language.equals("CHINESE_SIMPLIFIED")){ user.setSubject("[Code-Create] AiDA续订提醒"); templateUser.setTemplateID(156073L); } else { @@ -844,7 +845,7 @@ public class SendEmailUtil { if (language.equals("ENGLISH")) { user.setSubject("[Code-Create] AiDA account is about to expire"); templateUser.setTemplateID(156749L); - } else if (language.equals("CHINESE")){ + } else if (language.equals("CHINESE_SIMPLIFIED")){ user.setSubject("[Code-Create] 您的AiDA账号即将到期"); templateUser.setTemplateID(156750L); } else { @@ -856,7 +857,7 @@ public class SendEmailUtil { if (language.equals("ENGLISH")) { user.setSubject("[Code-Create] AiDA — Free Trial Ending"); templateUser.setTemplateID(156075L); - } else if (language.equals("CHINESE")){ + } else if (language.equals("CHINESE_SIMPLIFIED")){ user.setSubject("[Code-Create] AiDA — 免费试用结束提醒"); templateUser.setTemplateID(156076L); } else { @@ -874,14 +875,16 @@ public class SendEmailUtil { templateUser.setTemplateData(JSON.toJSONString(subscriptionEmailParamsDTO)); user.setTemplate(templateUser); - subscriptionEmailParamsDTO.setEndDate("When cancelled"); + if (Objects.nonNull(subscriptionEmailParamsDTO)) { + subscriptionEmailParamsDTO.setEndDate("When cancelled"); + } 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)); +// SendEmailResponse respUser = client.SendEmail(user); + log.info("邮件主题:{},发送结果toUser###{}, email:{}", user.getSubject(), /*SendEmailResponse.toJsonString(respUser)*/null, receiverAddress); } if (!type.startsWith("reminder")) { SendEmailResponse respMerchant = client.SendEmail(merchant); diff --git a/src/main/java/com/ai/da/service/impl/StripeServiceImpl.java b/src/main/java/com/ai/da/service/impl/StripeServiceImpl.java index 8ad8b034..737cbc0c 100644 --- a/src/main/java/com/ai/da/service/impl/StripeServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/StripeServiceImpl.java @@ -20,6 +20,7 @@ import com.ai.da.model.enums.Language; import com.ai.da.model.vo.CheckCouponsVO; import com.ai.da.service.*; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringUtils; @@ -1075,7 +1076,7 @@ public class StripeServiceImpl implements StripeService { String key = RedisUtil.SUBSCRIPTION_SENT_EMAIL_TYPE + subscriptionInfo.getId(); // 先判断当前订单 这个类型的邮件是否已发送过 Boolean elementExistsInSet = redisUtil.isElementExistsInSet(key, type); - if (!type.startsWith("reminder") && !type.equals("cancel") && paymentInfo.getNotified() == 1 && elementExistsInSet){ + if (/*!type.startsWith("reminder") && */!type.equals("cancel") && paymentInfo.getNotified() == 1 && elementExistsInSet){ // 已经邮件通知过,直接返回 log.info("不发送邮件,原因:【type为:{},order_no为:{},已经进行邮件通知】", type, orderNo); return true; @@ -1099,9 +1100,10 @@ public class StripeServiceImpl implements StripeService { emailParamsDTO.setEndOfPrepaidTerm(DateUtil.changeTimeStampFormat(subscriptionInfo.getCurrentPeriodEnd(), "seconds", CommonConstant.TIME_FORMAT_MMM_dd_yyyy)); setSubscriptionParams(paymentInfo, subscriptionInfo, orderByOrderNo, emailParamsDTO, language); - boolean b = SendEmailUtil.subscriptionEmailReminder(type, emailParamsDTO, language, account.getUserEmail()); + log.info("SEND EMAIL: type={}, params={}, language={}, receiver={}", type, JSONObject.toJSON(emailParamsDTO), language, account.getUserEmail()); +// boolean b = SendEmailUtil.subscriptionEmailReminder(type, emailParamsDTO, language, account.getUserEmail()); // boolean b = emailService.subscriptionEmailReminder(type, emailParamsDTO, language, account.getUserEmail()); - if (!b) return false; +// if (!b) return false; // 邮件通知成功后,更新标志 if (!type.startsWith("reminder") && !type.equals("cancel")){ From a940105fa4d768bd5c86a34411d6cfcc73cceee3 Mon Sep 17 00:00:00 2001 From: xupei Date: Wed, 3 Dec 2025 14:18:58 +0800 Subject: [PATCH 4/4] =?UTF-8?q?DEV=20=E6=95=B0=E6=8D=AE=E5=BA=93=E5=88=87?= =?UTF-8?q?=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-dev.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 37b6a737..13ce7029 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -1,8 +1,8 @@ server.port=5567 spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.primary.jdbcUrl=jdbc:mysql://18.167.251.121:33008/aida?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true -#spring.datasource.primary.jdbcUrl=jdbc:mysql://18.167.251.121:33008/aida_back?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true +#spring.datasource.primary.jdbcUrl=jdbc:mysql://18.167.251.121:33008/aida?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true +spring.datasource.primary.jdbcUrl=jdbc:mysql://18.167.251.121:33008/aida_back?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true #spring.datasource.primary.jdbcUrl=jdbc:mysql://18.167.251.121:33008/test_aida_3.1?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true spring.datasource.primary.username=aida_con spring.datasource.primary.password=123456