Affiliate-新增、查询、佣金计算等
This commit is contained in:
@@ -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 = "";
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
63
src/main/java/com/ai/da/controller/AffiliateController.java
Normal file
63
src/main/java/com/ai/da/controller/AffiliateController.java
Normal 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));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -66,6 +66,8 @@ public class ElementController {
|
||||
return Response.success();
|
||||
}
|
||||
|
||||
/** 该功能已删除 */
|
||||
@Deprecated
|
||||
@ApiOperation(value = "生成印花")
|
||||
@PostMapping("/generatePrint")
|
||||
public Response<GenerateCollectionItemVO> generatePrint(@Valid @RequestBody CollectionGeneratePrintDTO generatePrintDTO) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -104,4 +104,7 @@ public class Account implements Serializable {
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
private Long invitationCode;
|
||||
|
||||
}
|
||||
|
||||
28
src/main/java/com/ai/da/mapper/primary/entity/Affiliate.java
Normal file
28
src/main/java/com/ai/da/mapper/primary/entity/Affiliate.java
Normal 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;
|
||||
}
|
||||
@@ -24,4 +24,9 @@ public class OrderInfo extends BaseEntity{
|
||||
private String note;
|
||||
|
||||
private String paymentType;//支付方式
|
||||
|
||||
// 可用于标记用户订单是否首次订阅
|
||||
private byte isFirstSubscription = 0;
|
||||
|
||||
private byte isCommissionCalculated = 0;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
13
src/main/java/com/ai/da/model/dto/AffiliateQueryDTO.java
Normal file
13
src/main/java/com/ai/da/model/dto/AffiliateQueryDTO.java
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
19
src/main/java/com/ai/da/model/dto/TimeQueryBaseDTO.java
Normal file
19
src/main/java/com/ai/da/model/dto/TimeQueryBaseDTO.java
Normal 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;
|
||||
}
|
||||
15
src/main/java/com/ai/da/model/vo/AffiliateVO.java
Normal file
15
src/main/java/com/ai/da/model/vo/AffiliateVO.java
Normal 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;
|
||||
|
||||
}
|
||||
22
src/main/java/com/ai/da/service/AffiliateService.java
Normal file
22
src/main/java/com/ai/da/service/AffiliateService.java
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
189
src/main/java/com/ai/da/service/impl/AffiliateServiceImpl.java
Normal file
189
src/main/java/com/ai/da/service/impl/AffiliateServiceImpl.java
Normal 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(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user