加入积分系统,将充值与积分关联
This commit is contained in:
@@ -128,4 +128,6 @@ public interface AccountService extends IService<Account> {
|
||||
void upgradeNotification();
|
||||
|
||||
void moveLibraryDate();
|
||||
|
||||
void updateCredits(Long accountId, String value);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.ai.da.service;
|
||||
import java.util.Map;
|
||||
|
||||
public interface AliPayService {
|
||||
String tradeCreate(Long productId,String returnUrl);
|
||||
String tradeCreate(Integer amount,String returnUrl);
|
||||
|
||||
String tradeNotify(Map<String, String> params);
|
||||
|
||||
|
||||
16
src/main/java/com/ai/da/service/CreditsService.java
Normal file
16
src/main/java/com/ai/da/service/CreditsService.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.ai.da.service;
|
||||
|
||||
public interface CreditsService {
|
||||
|
||||
void initCredits();
|
||||
|
||||
Boolean buyCredits(Long accountId, Integer quantity);
|
||||
|
||||
void creditsIncrease(Long accountId, String event);
|
||||
|
||||
void creditsDecrease(Long accountId, String event);
|
||||
|
||||
String getCredits();
|
||||
|
||||
void creditsRefund(Long accountId, Integer quantity);
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import java.util.List;
|
||||
|
||||
public interface OrderInfoService extends IService<OrderInfo> {
|
||||
|
||||
OrderInfo createOrderByProductId(Long productId, String paymentType);
|
||||
OrderInfo createOrderByProductId(Integer productId, String paymentType);
|
||||
|
||||
void saveCodeUrl(String orderNo, String codeUrl);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.Map;
|
||||
|
||||
public interface PayPalCheckoutService {
|
||||
|
||||
HashMap<String, String> createOrder(Long productId,String returnUrl) throws SerializeException;
|
||||
HashMap<String, String> createOrder(Integer amount,String returnUrl) throws SerializeException;
|
||||
/**
|
||||
* 回调
|
||||
* @param map
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.springframework.util.Assert;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
@@ -885,4 +886,11 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
|
||||
// 未迁移过的进行迁移,注意模特数据迁移打点信息以及转换模特格式
|
||||
}
|
||||
|
||||
public void updateCredits(Long accountId, String value){
|
||||
Account account = new Account();
|
||||
account.setId(accountId);
|
||||
account.setCredits(new BigDecimal(value));
|
||||
accountMapper.updateById(account);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,12 @@ package com.ai.da.service.impl;
|
||||
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.common.enums.AliPayTradeStateEnum;
|
||||
import com.ai.da.common.enums.CreditsEventsEnum;
|
||||
import com.ai.da.common.enums.OrderStatusEnum;
|
||||
import com.ai.da.common.enums.PayTypeEnum;
|
||||
import com.ai.da.mapper.primary.entity.OrderInfo;
|
||||
import com.ai.da.mapper.primary.entity.RefundInfo;
|
||||
import com.ai.da.service.AliPayService;
|
||||
import com.ai.da.service.OrderInfoService;
|
||||
import com.ai.da.service.PaymentInfoService;
|
||||
import com.ai.da.service.RefundInfoService;
|
||||
import com.ai.da.service.*;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayClient;
|
||||
@@ -49,16 +47,19 @@ public class AliPayServiceImpl implements AliPayService {
|
||||
@Resource
|
||||
private RefundInfoService refundsInfoService;
|
||||
|
||||
@Resource
|
||||
private CreditsService creditsService;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public String tradeCreate(Long productId, String returnUrl) {
|
||||
public String tradeCreate(Integer amount, String returnUrl) {
|
||||
|
||||
try {
|
||||
//生成订单
|
||||
log.info("生成订单");
|
||||
OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId, PayTypeEnum.ALIPAY.getType());
|
||||
OrderInfo orderInfo = orderInfoService.createOrderByProductId(amount, PayTypeEnum.ALIPAY.getType());
|
||||
|
||||
//调用支付宝接口
|
||||
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
|
||||
@@ -74,7 +75,8 @@ public class AliPayServiceImpl implements AliPayService {
|
||||
bizContent.put("out_trade_no", orderInfo.getOrderNo());
|
||||
BigDecimal total = new BigDecimal(orderInfo.getTotalFee().toString());
|
||||
bizContent.put("total_amount", total);
|
||||
bizContent.put("subject", orderInfo.getTitle());
|
||||
// bizContent.put("subject", orderInfo.getTitle());
|
||||
bizContent.put("subject", "积分购买");
|
||||
bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
|
||||
|
||||
request.setBizContent(bizContent.toString());
|
||||
@@ -186,6 +188,7 @@ public class AliPayServiceImpl implements AliPayService {
|
||||
|
||||
//获取订单号
|
||||
String orderNo = params.get("out_trade_no");
|
||||
String totalAmount = params.get("total_amount");
|
||||
|
||||
/*在对业务数据进行状态检查和处理之前,
|
||||
要采用数据锁进行并发控制,
|
||||
@@ -196,7 +199,9 @@ public class AliPayServiceImpl implements AliPayService {
|
||||
try {
|
||||
//处理重复通知
|
||||
//接口调用的幂等性:无论接口被调用多少次,以下业务执行一次
|
||||
String orderStatus = orderInfoService.getOrderStatus(orderNo);
|
||||
// String orderStatus = orderInfoService.getOrderStatus(orderNo);
|
||||
OrderInfo orderByOrderNo = orderInfoService.getOrderByOrderNo(orderNo);
|
||||
String orderStatus = orderByOrderNo.getOrderStatus();
|
||||
// 当订单状态处于未支付或超时已关闭时,更新订单状态
|
||||
if (!OrderStatusEnum.NOT_PAY.getType().equals(orderStatus) || !OrderStatusEnum.TIMEOUT_CLOSED.getType().equals(orderStatus)) {
|
||||
return;
|
||||
@@ -205,6 +210,8 @@ public class AliPayServiceImpl implements AliPayService {
|
||||
orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.SUCCESS);
|
||||
//记录支付日志
|
||||
paymentInfoService.createPaymentInfoForAliPay(params);
|
||||
// 更新积分
|
||||
creditsService.buyCredits(orderByOrderNo.getAccountId(),Integer.parseInt(totalAmount) / Integer.parseInt(CreditsEventsEnum.PRICE.getValue()));
|
||||
} finally {
|
||||
//要主动释放锁
|
||||
lock.unlock();
|
||||
@@ -285,6 +292,7 @@ public class AliPayServiceImpl implements AliPayService {
|
||||
LinkedTreeMap alipayTradeQueryResponse = resultMap.get("alipay_trade_query_response");
|
||||
|
||||
String tradeStatus = (String)alipayTradeQueryResponse.get("trade_status");
|
||||
OrderInfo orderByOrderNo = orderInfoService.getOrderByOrderNo(orderNo);
|
||||
if(AliPayTradeStateEnum.NOTPAY.getType().equals(tradeStatus)){
|
||||
log.warn("核实订单未支付 ===> {}", orderNo);
|
||||
//如果订单未支付,则调用关单接口关闭订单
|
||||
@@ -299,6 +307,8 @@ public class AliPayServiceImpl implements AliPayService {
|
||||
orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.SUCCESS);
|
||||
//并记录支付日志
|
||||
paymentInfoService.createPaymentInfoForAliPay(alipayTradeQueryResponse);
|
||||
// 更新积分
|
||||
creditsService.buyCredits(orderByOrderNo.getAccountId(),orderByOrderNo.getTotalFee() / Integer.parseInt(CreditsEventsEnum.PRICE.getValue()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -368,6 +378,9 @@ public class AliPayServiceImpl implements AliPayService {
|
||||
refundInfo.getRefundNo(),
|
||||
response.getBody(),
|
||||
AliPayTradeStateEnum.REFUND_SUCCESS.getType()); //退款成功
|
||||
// 更新积分状态
|
||||
OrderInfo orderByOrderNo = orderInfoService.getOrderByOrderNo(orderNo);
|
||||
creditsService.creditsRefund(orderByOrderNo.getAccountId(), orderByOrderNo.getTotalFee() / Integer.parseInt(CreditsEventsEnum.PRICE.getValue()));
|
||||
|
||||
} else {
|
||||
log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
|
||||
|
||||
91
src/main/java/com/ai/da/service/impl/CreditsServiceImpl.java
Normal file
91
src/main/java/com/ai/da/service/impl/CreditsServiceImpl.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package com.ai.da.service.impl;
|
||||
|
||||
import com.ai.da.common.config.exception.BusinessException;
|
||||
import com.ai.da.common.context.UserContext;
|
||||
import com.ai.da.common.enums.CreditsEventsEnum;
|
||||
import com.ai.da.mapper.primary.AccountMapper;
|
||||
import com.ai.da.mapper.primary.entity.Account;
|
||||
import com.ai.da.service.AccountService;
|
||||
import com.ai.da.service.CreditsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Service
|
||||
public class CreditsServiceImpl implements CreditsService {
|
||||
|
||||
@Resource
|
||||
private AccountService accountService;
|
||||
|
||||
@Resource
|
||||
private AccountMapper accountMapper;
|
||||
|
||||
@Override
|
||||
public void initCredits() {
|
||||
accountService.updateCredits(UserContext.getUserHolder().getId(), CreditsEventsEnum.INIT.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean buyCredits(Long accountId, Integer quantity) {
|
||||
BigDecimal existingCredits = accountMapper.selectById(accountId).getCredits();
|
||||
BigDecimal newCredits = new BigDecimal(CreditsEventsEnum.BUY_CREDITS.getValue()).multiply(new BigDecimal(quantity));
|
||||
BigDecimal added = existingCredits.add(newCredits);
|
||||
accountService.updateCredits(accountId, added.toString());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void creditsIncrease(Long accountId, String creditsEvent) {
|
||||
CreditsEventsEnum event = null;
|
||||
|
||||
switch (creditsEvent){
|
||||
case "Daily Check-In":
|
||||
event = CreditsEventsEnum.DAILY_CHECKIN;
|
||||
break;
|
||||
case "Social Media Sharing":
|
||||
event = CreditsEventsEnum.SOCIAL_MEDIA_SHARING;
|
||||
break;
|
||||
case "Other":
|
||||
event = CreditsEventsEnum.OTHER;
|
||||
break;
|
||||
default:
|
||||
throw new BusinessException("UNKNOWN TYPE");
|
||||
}
|
||||
BigDecimal existingCredits = accountMapper.selectById(UserContext.getUserHolder().getId()).getCredits();
|
||||
BigDecimal add = new BigDecimal(event.getValue()).add(existingCredits);
|
||||
accountService.updateCredits(UserContext.getUserHolder().getId(), add.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void creditsDecrease(Long accountId, String creditsEvent) {
|
||||
CreditsEventsEnum event = null;
|
||||
|
||||
switch (creditsEvent){
|
||||
case "Super Resolution":
|
||||
event = CreditsEventsEnum.DAILY_CHECKIN;
|
||||
break;
|
||||
case "Other":
|
||||
event = CreditsEventsEnum.OTHER;
|
||||
break;
|
||||
default:
|
||||
throw new BusinessException("UNKNOWN TYPE");
|
||||
}
|
||||
BigDecimal existingCredits = accountMapper.selectById(UserContext.getUserHolder().getId()).getCredits();
|
||||
BigDecimal subtract = existingCredits.subtract(new BigDecimal(event.getValue()));
|
||||
accountService.updateCredits(UserContext.getUserHolder().getId(), subtract.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCredits() {
|
||||
Account account = accountMapper.selectById(UserContext.getUserHolder().getId());
|
||||
return account.getCredits().toString();
|
||||
}
|
||||
|
||||
public void creditsRefund(Long accountId, Integer quantity){
|
||||
BigDecimal existingCredits = accountMapper.selectById(accountId).getCredits();
|
||||
BigDecimal newCredits = new BigDecimal(CreditsEventsEnum.BUY_CREDITS.getValue()).multiply(new BigDecimal(quantity));
|
||||
BigDecimal subtracted = existingCredits.subtract(newCredits);
|
||||
accountService.updateCredits(accountId, subtracted.toString());
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,12 @@ package com.ai.da.service.impl;
|
||||
|
||||
|
||||
import com.ai.da.common.context.UserContext;
|
||||
import com.ai.da.common.enums.CreditsEventsEnum;
|
||||
import com.ai.da.common.enums.OrderStatusEnum;
|
||||
import com.ai.da.common.utils.OrderNoUtils;
|
||||
import com.ai.da.mapper.primary.OrderInfoMapper;
|
||||
import com.ai.da.mapper.primary.ProductMapper;
|
||||
import com.ai.da.mapper.primary.entity.OrderInfo;
|
||||
import com.ai.da.mapper.primary.entity.Product;
|
||||
import com.ai.da.model.vo.AuthPrincipalVo;
|
||||
import com.ai.da.service.OrderInfoService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
@@ -28,26 +28,26 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo
|
||||
private ProductMapper productMapper;
|
||||
|
||||
@Override
|
||||
public OrderInfo createOrderByProductId(Long productId, String paymentType) {
|
||||
public OrderInfo createOrderByProductId(Integer amount, String paymentType) {
|
||||
|
||||
//查找已存在但未支付的订单
|
||||
OrderInfo orderInfo = this.getNoPayOrderByProductId(productId, paymentType);
|
||||
/*OrderInfo orderInfo = this.getNoPayOrderByProductId(amount, paymentType);
|
||||
if( orderInfo != null){
|
||||
return orderInfo;
|
||||
}
|
||||
}*/
|
||||
|
||||
//获取商品信息
|
||||
Product product = productMapper.selectById(productId);
|
||||
// Product product = productMapper.selectById(amount);
|
||||
AuthPrincipalVo userHolder = UserContext.getUserHolder();
|
||||
Long accountId = userHolder.getId();
|
||||
|
||||
//生成订单
|
||||
orderInfo = new OrderInfo();
|
||||
OrderInfo orderInfo = new OrderInfo();
|
||||
orderInfo.setAccountId(accountId);
|
||||
orderInfo.setTitle(product.getTitle());
|
||||
orderInfo.setTitle("积分购买 X" + amount );
|
||||
orderInfo.setOrderNo(OrderNoUtils.getOrderNo()); //订单号 ??
|
||||
orderInfo.setProductId(productId);
|
||||
orderInfo.setTotalFee(product.getPrice()); // 元
|
||||
// orderInfo.setProductId(amount);
|
||||
orderInfo.setTotalFee(Integer.parseInt(CreditsEventsEnum.PRICE.getValue()) * amount); // 元 HKD
|
||||
orderInfo.setOrderStatus(OrderStatusEnum.NOT_PAY.getType()); //未支付
|
||||
orderInfo.setPaymentType(paymentType);
|
||||
baseMapper.insert(orderInfo);
|
||||
|
||||
@@ -9,10 +9,7 @@ import com.ai.da.common.utils.RedisUtil;
|
||||
import com.ai.da.common.utils.paypalRequest.AuthenticationRequest;
|
||||
import com.ai.da.mapper.primary.entity.OrderInfo;
|
||||
import com.ai.da.mapper.primary.entity.RefundInfo;
|
||||
import com.ai.da.service.OrderInfoService;
|
||||
import com.ai.da.service.PayPalCheckoutService;
|
||||
import com.ai.da.service.PaymentInfoService;
|
||||
import com.ai.da.service.RefundInfoService;
|
||||
import com.ai.da.service.*;
|
||||
import com.google.gson.Gson;
|
||||
import com.paypal.http.HttpResponse;
|
||||
import com.paypal.http.exceptions.SerializeException;
|
||||
@@ -60,6 +57,9 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService {
|
||||
@Resource
|
||||
private RefundInfoService refundsInfoService;
|
||||
|
||||
@Resource
|
||||
private CreditsService creditsService;
|
||||
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@@ -67,10 +67,10 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService {
|
||||
* 创建订单的方法
|
||||
*/
|
||||
@Override
|
||||
public HashMap<String, String> createOrder(Long productId,String returnUrl) throws SerializeException {
|
||||
public HashMap<String, String> createOrder(Integer amount, String returnUrl) throws SerializeException {
|
||||
// 生成订单
|
||||
log.info("生成订单");
|
||||
OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId, PayTypeEnum.PAYPAL.getType());
|
||||
OrderInfo orderInfo = orderInfoService.createOrderByProductId(amount, PayTypeEnum.PAYPAL.getType());
|
||||
|
||||
OrdersCreateRequest request = new OrdersCreateRequest();
|
||||
request.header("prefer","return=representation");
|
||||
@@ -372,6 +372,10 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService {
|
||||
response.result().id(),
|
||||
new Gson().toJson(response.result(), com.paypal.payments.Refund.class),
|
||||
AliPayTradeStateEnum.REFUND_SUCCESS.getType()); //退款成功
|
||||
|
||||
// 更新积分状态
|
||||
OrderInfo orderByOrderNo = orderInfoService.getOrderByOrderNo(orderId);
|
||||
creditsService.creditsRefund(orderByOrderNo.getAccountId(), orderByOrderNo.getTotalFee() / Integer.parseInt(CreditsEventsEnum.PRICE.getValue()));
|
||||
log.info("退款成功");
|
||||
result = Boolean.TRUE;
|
||||
}else {
|
||||
@@ -469,6 +473,8 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService {
|
||||
orderInfoService.updateStatusByOrderNo(orderId, OrderStatusEnum.SUCCESS);
|
||||
//记录支付日志
|
||||
paymentInfoService.createPaymentInfoForPayPal(capturedOrder);
|
||||
// 更新积分
|
||||
creditsService.buyCredits(orderInfo.getAccountId(), orderInfo.getTotalFee() / Integer.parseInt(CreditsEventsEnum.PRICE.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user