新增功能 -- 产品订阅 年度/月度

This commit is contained in:
2024-11-18 16:20:25 +08:00
parent 4a23e33080
commit 8d27b5b51e
21 changed files with 1029 additions and 318 deletions

View File

@@ -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";
}

View File

@@ -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;
}

View File

@@ -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<OrderInfo> orderInfoList = orderInfoService.getNoPayOrderByDuration(5, PayTypeEnum.ALIPAY.getType());
for (OrderInfo orderInfo : orderInfoList) {
String orderNo = orderInfo.getOrderNo();
log.warn("超时订单 ===> {}", orderNo);
//核实订单状态:调用支付宝查单接口
aliPayService.checkOrderStatus(orderNo);
}
}
}

View File

@@ -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){
}
}
}

View File

@@ -0,0 +1,96 @@
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.AliPayService;
import com.ai.da.service.OrderInfoService;
import com.ai.da.service.PayPalCheckoutService;
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 PaymentTask {
@Resource
private OrderInfoService orderInfoService;
@Resource
private StripeService stripeService;
// @Scheduled(cron = "0/30 * * * * ?")
public void orderConfirmForStripe() throws SerializeException {
// 查看超过30分钟以上仍未支付的订单 置为超时订单
List<OrderInfo> 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<OrderInfo> 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<OrderInfo> 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();
}
}

View File

@@ -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<OrderInfo> orderInfoList = orderInfoService.getNoPayOrderByDuration(30, PayTypeEnum.PAYPAL.getType());
for (OrderInfo orderInfo : orderInfoList) {
String orderNo = orderInfo.getOrderNo();
log.warn("超时订单 ===> {}", orderNo);
//核实订单状态:调用支付宝查单接口
payPalCheckoutService.checkOrderStatus(orderNo);
}
}
}

View File

@@ -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<OrderInfo> orderInfoList = orderInfoService.getNoPayOrderByDuration(30, PayTypeEnum.STRIPE.getType());
for (OrderInfo orderInfo : orderInfoList) {
String orderNo = orderInfo.getOrderNo();
log.warn("超时订单 ===> {}", orderNo);
//核实订单状态:调用支付宝查单接口
stripeService.checkOrderStatus(orderNo);
}
}
}

View File

@@ -2,8 +2,10 @@ 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.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;
@@ -767,4 +769,94 @@ 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;
public static void subscriptionEmailReminder(String type, SubscriptionEmailParamsDTO subscriptionEmailParamsDTO, String language, String receiverAddress){
try{
String kimEmail = "kimwong@code-create.com.hk";
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(new String[]{kimEmail});
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 "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);
// 返回的resp是一个SendEmailResponse的实例与请求对象对应
SendEmailResponse respUser = client.SendEmail(user);
// todo 暂时先不发商家邮件
// SendEmailResponse respMerchant = client.SendEmail(merchant);
log.info("邮件发送结果toUser###{}", SendEmailResponse.toJsonString(respUser));
// log.info("邮件发送结果toMerchant###{}", SendEmailResponse.toJsonString(respMerchant));
} catch (TencentCloudSDKException e) {
log.info("邮件发送失败###{}", e.toString());
throw new BusinessException("failed.to.send.mail");
}
}
}