新增功能 -- 产品订阅 年度/月度
This commit is contained in:
@@ -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";
|
||||
|
||||
|
||||
}
|
||||
|
||||
25
src/main/java/com/ai/da/common/enums/ProductEnum.java
Normal file
25
src/main/java/com/ai/da/common/enums/ProductEnum.java
Normal 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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
96
src/main/java/com/ai/da/common/task/PaymentTask.java
Normal file
96
src/main/java/com/ai/da/common/task/PaymentTask.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user