Affiliate-新增、查询、佣金计算等

This commit is contained in:
2024-12-09 16:53:29 +08:00
parent 1b15aed6a2
commit 47ca7bde41
21 changed files with 561 additions and 57 deletions

View File

@@ -79,5 +79,7 @@ public class CommonConstant {
public static final String TIME_FORMAT_MMM_dd_yyyy = "MMM. dd, yyyy";
public static final String AFFILIATE_LINK = "";
}

View File

@@ -278,4 +278,18 @@ 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);
}
}

View File

@@ -2,6 +2,7 @@ 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;
@@ -270,7 +271,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 {
// 实例化一个认证对象
@@ -372,6 +375,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 {
// 实例化一个认证对象
@@ -420,6 +424,7 @@ public class SendEmailUtil {
}
private final static Long GENERATE_EXCEPTION_WARNING_ID = 122589L;
public static void sendGenerateExceptionWarning(String message) {
try {
// 实例化一个认证对象
@@ -459,6 +464,7 @@ 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) {
try {
// 实例化一个认证对象
@@ -723,6 +729,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 {
// 实例化一个认证对象
@@ -883,4 +890,57 @@ public class SendEmailUtil {
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(new String[]{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");
}
}
}

View File

@@ -0,0 +1,63 @@
package com.ai.da.controller;
import com.ai.da.common.response.Response;
import com.ai.da.mapper.primary.entity.Affiliate;
import com.ai.da.model.dto.AffiliateQueryDTO;
import com.ai.da.model.vo.AffiliateVO;
import com.ai.da.service.AffiliateService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
@Slf4j
@RestController
@RequestMapping("/api/affiliate")
public class AffiliateController {
@Resource
private AffiliateService affiliateService;
@ApiOperation(value = "注册成为affiliate")
@GetMapping("/registration")
public Response<Boolean> completeGuidance(@RequestParam("promotionMethod") String promotionMethod) {
return Response.success(affiliateService.registerAsAnAffiliate(promotionMethod));
}
@ApiOperation(value = "获取affiliate列表")
@PostMapping("/list")
public Response<IPage<Affiliate>> getAffiliateList(@Valid @RequestBody AffiliateQueryDTO affiliateQueryDTO) {
return Response.success(affiliateService.getAffiliateList(affiliateQueryDTO));
}
@ApiOperation(value = "获取affiliate个人中心")
@GetMapping("/personalCenter")
public Response<AffiliateVO> personalAffiliateCenter() {
return Response.success(affiliateService.personalAffiliateCenter());
}
@ApiOperation(value = "审批affiliate申请")
@GetMapping("/approval")
public Response<Boolean> applicationApproval(@RequestParam("id") Long id, @RequestParam("isApproved")Boolean isApproved) {
return Response.success(affiliateService.applicationApproval(id, isApproved));
}
@ApiOperation(value = "审批affiliate申请")
@GetMapping("/testTask")
public Response<String> testTask() {
affiliateService.updateAffiliateInfoWithPayment();
return Response.success("success ");
}
@ApiOperation(value = "affiliate链接浏览量增加")
@GetMapping("/viewsIncrease")
public Response<Boolean> viewsGet(@RequestParam("id") Long id) {
return Response.success(affiliateService.affiliateLinkViewsIncrease(id));
}
}

View File

@@ -66,6 +66,8 @@ public class ElementController {
return Response.success();
}
/** 该功能已删除 */
@Deprecated
@ApiOperation(value = "生成印花")
@PostMapping("/generatePrint")
public Response<GenerateCollectionItemVO> generatePrint(@Valid @RequestBody CollectionGeneratePrintDTO generatePrintDTO) {

View File

@@ -99,4 +99,10 @@ public class StripeController {
return Response.success(stripeService.sendRenewalFailEmail(invoiceId, subscriptionId,orderNo));
}
@ApiOperation("临时 查询指定用户绑定的付款方式")
@GetMapping("/getCustomerPaymentMethod")
public Response<String> getCustomerPaymentMethod(@RequestParam String name, @RequestParam String email) {
return Response.success(stripeService.getCustomerPaymentMethod(name, email));
}
}

View File

@@ -0,0 +1,7 @@
package com.ai.da.mapper.primary;
import com.ai.da.mapper.primary.entity.Affiliate;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface AffiliateMapper extends BaseMapper<Affiliate> {
}

View File

@@ -104,4 +104,7 @@ public class Account implements Serializable {
* 头像
*/
private String avatar;
private Long invitationCode;
}

View File

@@ -0,0 +1,28 @@
package com.ai.da.mapper.primary.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("t_affiliate")
public class Affiliate extends BaseEntity{
private Long accountId;
// Active活跃 || Inactive过期 || Pending待审批 || Refused(拒绝)
private String status;
private Float totalEarnings = 0.00F;
private Float monthlyEarnings = 0.00F;
private Float unpaidEarnings = 0.00F;
private Integer visits = 0;
private Boolean approved = false;
private String link;
}

View File

@@ -24,4 +24,9 @@ public class OrderInfo extends BaseEntity{
private String note;
private String paymentType;//支付方式
// 可用于标记用户订单是否首次订阅
private byte isFirstSubscription = 0;
private byte isCommissionCalculated = 0;
}

View File

@@ -0,0 +1,31 @@
package com.ai.da.model.dto;
import lombok.Data;
@Data
public class AffiliateEmailParamsDTO {
private String username;
private String promotionMethod;
private String totalProgramRevenue;
private String newApprovedAffiliates;
private String unpaidEarnings;
private String paidEarnings;
public AffiliateEmailParamsDTO() {
}
public AffiliateEmailParamsDTO(String username) {
this.username = username;
}
public AffiliateEmailParamsDTO(String username, String promotionMethod) {
this.username = username;
this.promotionMethod = promotionMethod;
}
}

View File

@@ -0,0 +1,13 @@
package com.ai.da.model.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel("查询affiliate列表")
public class AffiliateQueryDTO extends TimeQueryBaseDTO{
private String status;
}

View File

@@ -12,49 +12,50 @@ import javax.validation.constraints.NotNull;
public class GenerateThroughImageTextDTO {
@NotNull(message = "userId cannot be empty")
@ApiModelProperty("用户id")
Long userId;
private Long userId;
@ApiModelProperty("caption | prompt")
String text;
private String text;
@ApiModelProperty("图片在t_collection_element表中的id")
Long collectionElementId;
private Long collectionElementId;
// todo 后续取消这个字段的传输,由后端自行判断相关参数是否有值
// @NotBlank(message = "you have to choose the generate type")
@ApiModelProperty("text image text-image")
String generateType;
private String generateType;
@ApiModelProperty("图片来源update从library中选择,从toProductImage结果中选择 collection || library || productImage")
String designType;
private String designType;
@NotBlank(message = "level1Type cannot be empty!")
@ApiModelProperty("Moodboard Printboard Sketchboard MarketingSketch")
String level1Type;
private String level1Type;
@ApiModelProperty("Outwear Dress Blouse Skirt Trousers || Logo Slogan Pattern")
String level2Type;
private String level2Type;
@ApiModelProperty("性别")
String gender;
private String gender;
@ApiModelProperty("选择的模型名")
String version;
@ApiModelProperty("选择的模型名 high || fast")
private String version;
@NotBlank(message = "timeZone cannot be empty!")
@ApiModelProperty("本地时区,比如 'Asia/Tokyo' 东京时间 , 'Asia/Shanghai' 北京时间 由js本地获取")
String timeZone;
private String timeZone;
@ApiModelProperty("唯一id用于保持消息唯一性")
String uniqueId;
private String uniqueId;
@NotNull(message = "Please check if the required fields are empty.(isTestUser)")
@ApiModelProperty("是否是测试用户")
Boolean isTestUser;
private Boolean isTestUser;
@ApiModelProperty("页面上用户设计的slogan所截的图片")
String sloganBase64;
private String sloganBase64;
@ApiModelProperty("种子 取值范围 0~500")
String seed;
private String seed;
}

View File

@@ -0,0 +1,19 @@
package com.ai.da.model.dto;
import com.ai.da.model.vo.PageQueryBaseVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel("按时间查询")
public class TimeQueryBaseDTO extends PageQueryBaseVo {
@ApiModelProperty("按时间区间查询 区间起点")
private String startTime;
@ApiModelProperty("按时间区间查询 区间终点")
private String endTime;
}

View File

@@ -0,0 +1,15 @@
package com.ai.da.model.vo;
import com.ai.da.mapper.primary.entity.Affiliate;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AffiliateVO extends Affiliate {
private Long linkViewCount;
}

View File

@@ -0,0 +1,22 @@
package com.ai.da.service;
import com.ai.da.mapper.primary.entity.Affiliate;
import com.ai.da.model.dto.AffiliateQueryDTO;
import com.ai.da.model.vo.AffiliateVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
public interface AffiliateService extends IService<Affiliate> {
Boolean registerAsAnAffiliate(String promotionMethod);
IPage<Affiliate> getAffiliateList(AffiliateQueryDTO affiliateQueryDTO);
AffiliateVO personalAffiliateCenter();
Boolean applicationApproval(Long id, Boolean isApproved);
void updateAffiliateInfoWithPayment();
Boolean affiliateLinkViewsIncrease(Long id);
}

View File

@@ -19,6 +19,8 @@ public interface StripeService {
List<String> getSubscriptionIds(String name, String userEmail) throws StripeException;
Map<String, String> getPaymentMethodByInvoiceId(String invoiceId);
void cancelSubscription(String orderNo);
void cancelSubscriptionTemp(String subscriptionId);
@@ -38,4 +40,6 @@ public interface StripeService {
String changeCustomerPayment(String name, String email);
boolean sendRenewalFailEmail(String invoiceId, String subscriptionId, String orderNo);
String getCustomerPaymentMethod(String name, String email);
}

View File

@@ -0,0 +1,189 @@
package com.ai.da.service.impl;
import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.constant.CommonConstant;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.CopyUtil;
import com.ai.da.common.utils.ObjectUtils;
import com.ai.da.common.utils.RedisUtil;
import com.ai.da.common.utils.SendEmailUtil;
import com.ai.da.mapper.primary.AffiliateMapper;
import com.ai.da.mapper.primary.entity.*;
import com.ai.da.model.dto.AffiliateEmailParamsDTO;
import com.ai.da.model.dto.AffiliateQueryDTO;
import com.ai.da.model.vo.AffiliateVO;
import com.ai.da.model.vo.AuthPrincipalVo;
import com.ai.da.service.AccountService;
import com.ai.da.service.AffiliateService;
import com.ai.da.service.OrderInfoService;
import com.ai.da.service.PaymentInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
@Service
@Slf4j
public class AffiliateServiceImpl extends ServiceImpl<AffiliateMapper, Affiliate> implements AffiliateService {
@Resource
private OrderInfoService orderInfoService;
@Resource
private AccountService accountService;
@Resource
private PaymentInfoService paymentInfoService;
@Resource
private RedisUtil redisUtil;
// 推广者注册
public Boolean registerAsAnAffiliate(String promotionMethod){
AuthPrincipalVo userHolder = UserContext.getUserHolder();
// 判断该用户是否已注册
QueryWrapper<Affiliate> qw = new QueryWrapper<>();
qw.eq("account_id", userHolder.getId());
Affiliate affiliate = baseMapper.selectOne(qw);
if (Objects.isNull(affiliate)){
affiliate = new Affiliate();
affiliate.setAccountId(userHolder.getId());
affiliate.setStatus("Pending");
affiliate.setCreateTime(LocalDateTime.now());
baseMapper.insert(affiliate);
// 邮件通知审批者
// String email = "kimwong@code-create.com.hk";
String email = "xupei3360@163.com";
SendEmailUtil.affiliateEmailReminder(email, new AffiliateEmailParamsDTO(userHolder.getUsername(), promotionMethod), "new");
}else {
throw new BusinessException("You have registered an Affiliate", ResultEnum.PROMPT.getCode());
}
return true;
}
public IPage<Affiliate> getAffiliateList(AffiliateQueryDTO affiliateQueryDTO){
QueryWrapper<Affiliate> qw = new QueryWrapper<>();
qw.eq(affiliateQueryDTO.getStatus() != null, "status", affiliateQueryDTO.getStatus());
qw.gt(affiliateQueryDTO.getStartTime() != null, "create_time", affiliateQueryDTO.getStartTime());
qw.lt(affiliateQueryDTO.getEndTime() != null, "create_time", affiliateQueryDTO.getEndTime());
return baseMapper.selectPage(new Page<>(affiliateQueryDTO.getPage(), affiliateQueryDTO.getSize()), qw);
}
public AffiliateVO personalAffiliateCenter(){
QueryWrapper<Affiliate> qw = new QueryWrapper<>();
Long accountId = UserContext.getUserHolder().getId();
qw.eq("account_id", accountId);
Affiliate affiliate = baseMapper.selectOne(qw);
AffiliateVO affiliateVO = CopyUtil.copyObject(affiliate, AffiliateVO.class);
affiliateVO.setLinkViewCount(getAffiliateLinkViewCount(accountId));
return affiliateVO;
}
// 审批申请
public Boolean applicationApproval(Long id, Boolean isApproved){
Affiliate affiliate = baseMapper.selectById(id);
// 1、更新db状态
if (isApproved){
// 更新状态
affiliate.setStatus("Active");
affiliate.setApproved(true);
affiliate.setLink(CommonConstant.AFFILIATE_LINK + affiliate.getId());
} else {
affiliate.setStatus("Inactive");
affiliate.setApproved(false);
}
affiliate.setUpdateTime(LocalDateTime.now());
// 2、将批准结果邮件通知用户
Account account = accountService.getById(affiliate.getAccountId());
String userEmail = account.getUserEmail();
String userName = account.getUserName();
if (isApproved){
SendEmailUtil.affiliateEmailReminder(userEmail, new AffiliateEmailParamsDTO(userName), "accepted");
}else {
SendEmailUtil.affiliateEmailReminder(userEmail, new AffiliateEmailParamsDTO(userName), "refused");
}
return true;
}
// 定时计算佣金
public void updateAffiliateInfoWithPayment(){
// id存redis
String lastTime = redisUtil.getFromString(RedisUtil.PAYMENT_INFO_LAST_SCAN_TIME);
String currentTime = LocalDateTime.now().toString();
// 1、查上次更新之后有无新订单
QueryWrapper<PaymentInfo> queryWrapper = new QueryWrapper<>();
if (!StringUtil.isNullOrEmpty(lastTime)){
queryWrapper.gt("create_time", lastTime);
}
queryWrapper.eq("type","new").eq("trade_state", "paid");
List<PaymentInfo> paymentInfos = paymentInfoService.getBaseMapper().selectList(queryWrapper);
if (!paymentInfos.isEmpty()){
paymentInfos.forEach(paymentInfo -> {
// 2、根据order_no查付款用户id
OrderInfo orderInfo = orderInfoService.getOrderByOrderNo(paymentInfo.getOrderNo());
Long accountId = orderInfo.getAccountId();
// 3、查该用户之前是否有初次订阅的订单
QueryWrapper<OrderInfo> qwOrderInfo = new QueryWrapper<>();
qwOrderInfo.eq("account_id", accountId).eq("is_first_subscription", 1);
List<OrderInfo> orderInfos = orderInfoService.getBaseMapper().selectList(qwOrderInfo);
// 该用户首次订阅(非首次订阅,不分配佣金)
if (orderInfos.isEmpty()){
// 查询是否绑定affiliateId
Account account = accountService.getById(accountId);
if (!Objects.isNull(account.getInvitationCode())){
// 3、若有, 直接更新affiliate的所得
Affiliate affiliate = baseMapper.selectById(account.getInvitationCode());
Float payerTotal = paymentInfo.getPayerTotal();
if (payerTotal > 0){
// 分配新用户首次订阅所付费用的25%作为佣金
BigDecimal commission = BigDecimal.valueOf(payerTotal).multiply(new BigDecimal("0.25"));
BigDecimal monthlyEarning = BigDecimal.valueOf(affiliate.getMonthlyEarnings()).add(commission);
BigDecimal unpaidEarnings = BigDecimal.valueOf(affiliate.getUnpaidEarnings()).add(commission);
int visits = affiliate.getVisits() + 1;
affiliate.setMonthlyEarnings(monthlyEarning.floatValue());
affiliate.setUnpaidEarnings(unpaidEarnings.floatValue());
affiliate.setVisits(visits);
affiliate.setUpdateTime(LocalDateTime.now());
baseMapper.updateById(affiliate);
orderInfo.setIsCommissionCalculated((byte)1);
}
}
orderInfo.setIsFirstSubscription((byte)1);
orderInfo.setUpdateTime(LocalDateTime.now());
orderInfoService.updateById(orderInfo);
}
});
}
redisUtil.addToString(RedisUtil.PAYMENT_INFO_LAST_SCAN_TIME, currentTime);
}
public Boolean affiliateLinkViewsIncrease(Long id) {
redisUtil.increaseAffiliateLinkViewCount(id);
return Boolean.TRUE;
}
private Long getAffiliateLinkViewCount(Long accountId) {
return redisUtil.getAffiliateLinkViewCount(accountId);
}
// todo 每个月给kim发一封邮件统计本月的affiliate等的收入
public void commissionCalculation(){
}
}

View File

@@ -216,6 +216,8 @@ public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementM
collectionElementMapper.deleteBatchIds(ids);
}
/** 该方法已不再使用 */
@Deprecated
@Override
public GenerateCollectionItemVO generatePrint(CollectionGeneratePrintDTO generatePrintDTO) {
Long userId = UserContext.getUserHolder().getId();
@@ -908,7 +910,7 @@ public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementM
generate.setAccountId(userId);
generate.setLevel1Type(CollectionLevel1TypeEnum.PRINT_BOARD.getRealName());
generate.setGenerateType("synthesis");
generate.setModelName("Image Synthesis Model");
// generate.setModelName("Image Synthesis Model");
generate.setCreateDate(DateUtil.getByTimeZone(timeZone));
return generate;
}

View File

@@ -4,7 +4,7 @@ import com.ai.da.common.enums.PayTypeEnum;
import com.ai.da.mapper.primary.PaymentInfoMapper;
import com.ai.da.mapper.primary.entity.PaymentInfo;
import com.ai.da.model.dto.AlipayHKCallbackDTO;
import com.ai.da.service.PaymentInfoService;
import com.ai.da.service.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
@@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
@@ -30,11 +31,8 @@ import java.util.Objects;
@Slf4j
public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, PaymentInfo> implements PaymentInfoService {
private final StripeServiceImpl stripeServiceImpl;
public PaymentInfoServiceImpl(StripeServiceImpl stripeServiceImpl) {
this.stripeServiceImpl = stripeServiceImpl;
}
@Resource
private StripeService stripeService;
/**
* 记录支付日志:微信支付
@@ -220,7 +218,7 @@ public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, Payme
String type = invoice.getBillingReason().equals("subscription_create") ? "new" :
invoice.getBillingReason().equals("subscription_cycle") ? "renewal" : invoice.getBillingReason();
Map<String, String> paymentMethod = stripeServiceImpl.getPaymentMethodByInvoiceId(invoiceId);
Map<String, String> paymentMethod = stripeService.getPaymentMethodByInvoiceId(invoiceId);
paymentInfo = new PaymentInfo();
paymentInfo.setOrderNo(orderNo);

View File

@@ -553,7 +553,8 @@ public class StripeServiceImpl implements StripeService {
Subscription cancel = subscription.cancel();
cancel.getStatus();
} catch (StripeException e) {
throw new RuntimeException(e);
log.error(e.getMessage());
// throw new RuntimeException(e);
}
}
@@ -988,7 +989,8 @@ public class StripeServiceImpl implements StripeService {
try {
OrderInfo orderInfo = orderInfoService.createOrderByProductId(1, PayTypeEnum.STRIPE.getType(), ProductEnum.DailySubscription);
String paymentMethodCode = "pm_card_mastercard";
String customerId = getCustomer(name, email);
/* String paymentMethodCode = "pm_card_mastercard";
PaymentMethod paymentMethod = PaymentMethod.retrieve(paymentMethodCode);
String customerId = getCustomer(name, email);
@@ -997,14 +999,14 @@ public class StripeServiceImpl implements StripeService {
PaymentMethodAttachParams attachParams = PaymentMethodAttachParams.builder()
.setCustomer(customerId)
.build();
paymentMethod.attach(attachParams);
paymentMethod.attach(attachParams);*/
// 设置默认付款方式
Customer updatedCustomer = Customer.retrieve(customerId);
CustomerUpdateParams params = CustomerUpdateParams.builder()
.setInvoiceSettings(
CustomerUpdateParams.InvoiceSettings.builder()
.setDefaultPaymentMethod(paymentMethod.getId())
// .setDefaultPaymentMethod(paymentMethod.getId())
.build()
)
.build();
@@ -1064,4 +1066,22 @@ public class StripeServiceImpl implements StripeService {
}
}
public String getCustomerPaymentMethod(String name, String email){
Stripe.apiKey = privateKey;
try {
String customerId = getCustomer(name, email);
Customer customer = Customer.retrieve(customerId);
PaymentMethodCollection paymentMethodCollection = customer.listPaymentMethods();
List<PaymentMethod> data = paymentMethodCollection.getData();
// todo 方向: 向用户添加了多种付款方式,更改默认的付款方式后,默认付款方式付款失败后是否自动使用其他付款方式付款?
// 如果是的,则需要删除能成功的付款方式,保留唯一失败的付款方式进行续订付款失败测试
} catch (StripeException e) {
throw new RuntimeException(e);
}
return null;
}
}