TASK:优化订阅收件人列表创建方式

This commit is contained in:
2026-05-05 11:22:17 +08:00
parent d20bb27244
commit c558ebb3d0
8 changed files with 94 additions and 52 deletions

View File

@@ -17,17 +17,38 @@ import com.tencentcloudapi.ses.v20201002.models.SendEmailRequest;
import com.tencentcloudapi.ses.v20201002.models.SendEmailResponse; import com.tencentcloudapi.ses.v20201002.models.SendEmailResponse;
import com.tencentcloudapi.ses.v20201002.models.Template; import com.tencentcloudapi.ses.v20201002.models.Template;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import jakarta.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Base64; import java.util.Base64;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
* 邮件发送类 * 邮件发送类
*/ */
@Slf4j @Slf4j
@Component
public class SendEmailUtil { public class SendEmailUtil {
@Value("${merchant.email:}")
private String merchantEmailInstance;
@Value("${developer.email: xupei@code-create.com.hk}")
private String developerEmailInstance;
private static String merchantEmail;
private static String developerEmail;
@PostConstruct
public void init() {
merchantEmail = merchantEmailInstance;
developerEmail = developerEmailInstance;
}
/** /**
* 秘钥id * 秘钥id
*/ */
@@ -765,9 +786,7 @@ public class SendEmailUtil {
public static boolean subscriptionEmailReminder(String type, SubscriptionEmailParamsDTO subscriptionEmailParamsDTO, String language, String receiverAddress) { public static boolean subscriptionEmailReminder(String type, SubscriptionEmailParamsDTO subscriptionEmailParamsDTO, String language, String receiverAddress) {
try { try {
String merchantEmail = "kimwong@code-create.com.hk"; String[] receiverEmail = buildMerchantReceiverEmail();
String developer = "xupei3360@163.com";
String[] receiverEmail = {/*merchantEmail,*/ developer};
Credential cred = new Credential(SECRET_ID, SECRET_KEy); Credential cred = new Credential(SECRET_ID, SECRET_KEy);
// 实例化一个http选项可选的没有特殊需求可以跳过 // 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile(); HttpProfile httpProfile = new HttpProfile();
@@ -966,9 +985,7 @@ public class SendEmailUtil {
// 实例化一个请求对象,每个接口都会对应一个request对象 // 实例化一个请求对象,每个接口都会对应一个request对象
SendEmailRequest req = new SendEmailRequest(); SendEmailRequest req = new SendEmailRequest();
req.setFromEmailAddress(SEND_ADDRESS); req.setFromEmailAddress(SEND_ADDRESS);
String merchantEmail = "kimwong@code-create.com.hk"; req.setDestination(buildMerchantReceiverEmail());
String developerEmail = "xupei@code-create.com.hk";
req.setDestination(new String[]{/*merchantEmail,*/ developerEmail});
Template template = new Template(); Template template = new Template();
req.setSubject("New Credit Purchase Order"); req.setSubject("New Credit Purchase Order");
template.setTemplateID(CREDITS_PURCHASE_MERCHANT); template.setTemplateID(CREDITS_PURCHASE_MERCHANT);
@@ -1076,4 +1093,25 @@ public class SendEmailUtil {
} }
public static String[] buildMerchantReceiverEmail() {
List<String> emails = new ArrayList<>();
if (!StringUtils.isEmpty(merchantEmail)) {
for (String e : merchantEmail.split(",")) {
String trimmed = e.trim();
if (!trimmed.isEmpty()) {
emails.add(trimmed);
}
}
}
if (!StringUtils.isEmpty(developerEmail)) {
for (String e : developerEmail.split(",")) {
String trimmed = e.trim();
if (!trimmed.isEmpty()) {
emails.add(trimmed);
}
}
}
return emails.toArray(new String[0]);
}
} }

View File

@@ -34,7 +34,6 @@ import jakarta.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
@@ -80,9 +79,7 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
affiliate.setPromotionMethod(promotionMethod); affiliate.setPromotionMethod(promotionMethod);
baseMapper.insert(affiliate); baseMapper.insert(affiliate);
// 邮件通知审批者 // 邮件通知审批者
String merchantEmail = "kimwong@code-create.com.hk"; String[] receiverEmail = buildMerchantReceiverEmail();
String developer = "xupei3360@163.com";
String[] receiverEmail = {/*merchantEmail,*/ developer};
SendEmailUtil.affiliateEmailReminder(receiverEmail, new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new"); SendEmailUtil.affiliateEmailReminder(receiverEmail, new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
// emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new"); // emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
}else { }else {
@@ -440,9 +437,7 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
affiliateEmailParamsDTO.setUnpaidEarnings(String.valueOf(unpaidCommission)); affiliateEmailParamsDTO.setUnpaidEarnings(String.valueOf(unpaidCommission));
affiliateEmailParamsDTO.setPaidEarnings(String.valueOf(paidCommission)); affiliateEmailParamsDTO.setPaidEarnings(String.valueOf(paidCommission));
String merchantEmail = "kimwong@code-create.com.hk"; String[] receiverEmail = buildMerchantReceiverEmail();
String developer = "xupei3360@163.com";
String[] receiverEmail = {/*merchantEmail,*/ developer};
// 邮件通知 // 邮件通知
SendEmailUtil.affiliateEmailReminder(receiverEmail, affiliateEmailParamsDTO, "summary"); SendEmailUtil.affiliateEmailReminder(receiverEmail, affiliateEmailParamsDTO, "summary");
// emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), affiliateEmailParamsDTO, "summary"); // emailService.affiliateEmailReminder(Arrays.asList(/*merchantEmail,*/ developer), affiliateEmailParamsDTO, "summary");
@@ -607,4 +602,8 @@ public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate
coupon.setUnpaidCommission(unpaidCommission); coupon.setUnpaidCommission(unpaidCommission);
} }
private String[] buildMerchantReceiverEmail() {
return SendEmailUtil.buildMerchantReceiverEmail();
}
} }

View File

@@ -7,6 +7,7 @@ import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.DateUtil; import com.ai.da.common.utils.DateUtil;
import com.ai.da.common.utils.MailUtil; import com.ai.da.common.utils.MailUtil;
import com.ai.da.common.utils.RedisUtil; import com.ai.da.common.utils.RedisUtil;
import com.ai.da.common.utils.SendEmailUtil;
import com.ai.da.mapper.primary.AccountMapper; import com.ai.da.mapper.primary.AccountMapper;
import com.ai.da.mapper.primary.EmailLogMapper; import com.ai.da.mapper.primary.EmailLogMapper;
import com.ai.da.mapper.primary.EmailTemplateMapper; import com.ai.da.mapper.primary.EmailTemplateMapper;
@@ -585,9 +586,7 @@ public class EmailServiceImpl implements EmailService {
public boolean subscriptionEmailReminder(String type, SubscriptionEmailParamsDTO subscriptionEmailParamsDTO, String language, String receiverAddress) { public boolean subscriptionEmailReminder(String type, SubscriptionEmailParamsDTO subscriptionEmailParamsDTO, String language, String receiverAddress) {
try { try {
String merchantEmail = "kimwong@code-create.com.hk"; List<String> merchantReceiver = buildMerchantReceiverList();
String developer = "xupei3360@163.com";
List<String> merchantReceiver = Arrays.asList(/*merchantEmail,*/ developer);
String merchantSubject = null; String merchantSubject = null;
String merchantTemplate = null; String merchantTemplate = null;
@@ -723,15 +722,13 @@ public class EmailServiceImpl implements EmailService {
private final static String CREDITS_PURCHASE_MERCHANT = "133275_AiDA 积分购买通知-merchant.html"; private final static String CREDITS_PURCHASE_MERCHANT = "133275_AiDA 积分购买通知-merchant.html";
public void creditsPurchaseReminder(String username, String quantity, String amount) { public void creditsPurchaseReminder(String username, String quantity, String amount) {
String merchantEmail = "kimwong@code-create.com.hk";
String developerEmail = "xupei@code-create.com.hk";
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
// 设置试用订单相关数据 // 设置试用订单相关数据
jsonObject.put("username", username); jsonObject.put("username", username);
jsonObject.put("quantity", quantity); jsonObject.put("quantity", quantity);
jsonObject.put("totalFee", amount); jsonObject.put("totalFee", amount);
sendEmail(Arrays.asList(/*merchantEmail,*/ developerEmail), jsonObject, CREDITS_PURCHASE_MERCHANT, "New Credit Purchase Order", null, null); sendEmail(buildMerchantReceiverList(), jsonObject, CREDITS_PURCHASE_MERCHANT, "New Credit Purchase Order", null, null);
} }
private final static String COMMON_EXCEPTION_REMINDER = "135279_common-exception-reminder.html"; private final static String COMMON_EXCEPTION_REMINDER = "135279_common-exception-reminder.html";
@@ -742,6 +739,10 @@ public class EmailServiceImpl implements EmailService {
sendEmail(destination, param, COMMON_EXCEPTION_REMINDER, "AiDA发生异常请及时处理", null, null); sendEmail(destination, param, COMMON_EXCEPTION_REMINDER, "AiDA发生异常请及时处理", null, null);
} }
private List<String> buildMerchantReceiverList() {
return Arrays.asList(SendEmailUtil.buildMerchantReceiverEmail());
}
} }

View File

@@ -180,7 +180,7 @@ public class StripeSubscriptionServiceImpl implements StripeSubscriptionService
.orderByDesc("id") .orderByDesc("id")
.last("LIMIT 1"); .last("LIMIT 1");
if (!type.contains("fail")) { if (!type.contains("fail")) {
last.in("trade_state", "paid", "COMPLETED"); last.in("trade_state", "paid", "COMPLETED", "Refunded");
} }
List<PaymentInfo> infos = paymentInfoMapper.selectList(last); List<PaymentInfo> infos = paymentInfoMapper.selectList(last);
return infos.isEmpty() ? null : infos.getFirst(); return infos.isEmpty() ? null : infos.getFirst();

View File

@@ -67,7 +67,7 @@ public class SubscriptionDeletedHandler implements StripeEventHandler {
// 发送取消订阅通知邮件 // 发送取消订阅通知邮件
if (subscriptionInfo.getCancelNotified() == 0) { if (subscriptionInfo.getCancelNotified() == 0) {
boolean sent = stripeSubscriptionService.sendSubscriptionEmail(null, "cancel", subscriptionInfo.getOrderNo(), null); boolean sent = stripeSubscriptionService.sendSubscriptionEmail(null, "cancel", subscriptionInfo.getOrderNo(), subscriptionInfo);
if (sent) { if (sent) {
subscriptionInfo.setCancelNotified((byte) 1); subscriptionInfo.setCancelNotified((byte) 1);

View File

@@ -181,4 +181,10 @@ file.upload.max.size.video=104857600
# 上传任务过期时间(小时) # 上传任务过期时间(小时)
file.upload.task.expiry.hours=24 file.upload.task.expiry.hours=24
global.award.link=https://aida-global-design-awards.com.hk/contestants?id= global.award.link=https://aida-global-design-awards.com.hk/contestants?id=
# merchant email receivers (comma-separated, multiple supported)
# dev/local: developer.email 不配置,使用默认值 xupei3360@163.com
# prod: 两个都配置
merchant.email=
developer.email=xupei@code-create.com.hk,yizhang@aidlab.hk

View File

@@ -179,4 +179,9 @@ file.upload.max.size.video=104857600
# 上传任务过期时间(小时) # 上传任务过期时间(小时)
file.upload.task.expiry.hours=24 file.upload.task.expiry.hours=24
global.award.link=https://aida-global-design-awards.com.hk/contestants?id= global.award.link=https://aida-global-design-awards.com.hk/contestants?id=
# merchant email receivers (comma-separated, multiple supported)
# prod: includes merchant email
merchant.email=kimwong@code-create.com.hk
developer.email=xupei3360@163.com

View File

@@ -51,47 +51,41 @@
a.user_email email, a.user_email email,
p.payment_type platform, p.payment_type platform,
p.payer_total, p.payer_total,
p.type, CASE
WHEN o.title LIKE '%Subscription' THEN 'Subscription'
ELSE 'Credits'
END AS type,
p.payment_method, p.payment_method,
p.last4, p.last4,
p.country, p.country,
p.city, p.city,
p.create_time, p.create_time,
CASE CASE
WHEN p.trade_state IN ('paid', 'COMPLETED', 'complete', 'liquidated') THEN 'Success'
WHEN p.trade_state IN ( 'paid', 'COMPLETED', 'complete', 'liquidated' ) THEN WHEN p.trade_state IN ('failed', 'expired', 'VOIDED', 'void', 'uncollectible') THEN 'Fail'
'Success' WHEN p.trade_state IN ('Refunded') THEN 'Refunded'
WHEN p.trade_state IN ( 'failed', 'expired', 'VOIDED', 'void', 'uncollectible' ) THEN
'Fail'
WHEN p.trade_state IN ( 'Refunded' ) THEN
'Refunded'
ELSE 'Pending' ELSE 'Pending'
END AS status END AS status
FROM FROM t_payment_info p
t_payment_info p LEFT JOIN t_order_info o ON p.order_no = o.order_no
LEFT JOIN LEFT JOIN t_account a ON a.id = o.account_id
t_order_info o ON p.order_no = o.order_no WHERE 1 = 1
LEFT JOIN
t_account a ON a.id = o.account_id
WHERE
1 = 1
<if test="paymentType != null and paymentType != ''"> <if test="paymentType != null and paymentType != ''">
AND p.payment_type = #{paymentType} AND p.payment_type = #{paymentType}
</if> </if>
<if test="payerTotal != null and payerTotal != ''"> <if test="payerTotal != null and payerTotal != ''">
AND p.payer_total = #{payerTotal} AND p.payer_total = #{payerTotal}
</if> </if>
<if test="type != null and type != ''"> <!-- 修复1删除 type 过滤条件,因为 type 是计算字段 -->
AND p.type = #{type}
</if>
<if test="status != null and status != ''"> <if test="status != null and status != ''">
AND AND (
CASE (p.trade_state IN ('paid', 'COMPLETED', 'complete', 'liquidated') AND #{status} = 'Success')
WHEN p.trade_state IN ('paid', 'COMPLETED', 'complete', 'liquidated') THEN 'Success' OR (p.trade_state IN ('failed', 'expired', 'VOIDED', 'void', 'uncollectible') AND #{status} = 'Fail')
WHEN p.trade_state IN ('failed', 'expired', 'VOIDED', 'void', 'uncollectible') THEN 'Fail' OR (p.trade_state IN ('Refunded') AND #{status} = 'Refunded')
WHEN p.trade_state IN ('Refunded') THEN 'Refunded' OR (p.trade_state NOT IN ('paid', 'COMPLETED', 'complete', 'liquidated',
ELSE 'Pending' 'failed', 'expired', 'VOIDED', 'void', 'uncollectible', 'Refunded')
END = #{status} AND #{status} = 'Pending')
)
</if> </if>
<if test="country != null and country != ''"> <if test="country != null and country != ''">
AND p.country = #{country} AND p.country = #{country}
@@ -106,9 +100,8 @@
AND a.user_name = #{payer} AND a.user_name = #{payer}
</if> </if>
AND p.transaction_id NOT LIKE 'cs_test%' AND p.transaction_id NOT LIKE 'cs_test%'
ORDER BY ORDER BY p.id ${order} <!-- 建议使用白名单校验 -->
p.id ${order} LIMIT #{limit} OFFSET #{offset} <!-- 修复:改为 #{} -->
LIMIT ${limit} OFFSET ${offset}
</select> </select>
<select id="queryPaymentInfoCount" resultType="java.lang.Long"> <select id="queryPaymentInfoCount" resultType="java.lang.Long">