钱包支付 Client 的实现
parent
1baa7f4aee
commit
c7f6f92159
@ -0,0 +1,58 @@
|
||||
package cn.iocoder.yudao.framework.pay.core.client.impl.delegate;
|
||||
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author jason
|
||||
*/
|
||||
public abstract class DelegatePayClient<Config extends PayClientConfig> extends AbstractPayClient<PayClientConfig> {
|
||||
|
||||
private final DelegatePayClient<Config> delegate;
|
||||
|
||||
public DelegatePayClient(Long channelId, String channelCode, PayClientConfig config) {
|
||||
super(channelId, channelCode, config);
|
||||
delegate = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
delegate.doInit();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
|
||||
return delegate.doUnifiedOrder(reqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayOrderRespDTO doGetOrder(String outTradeNo) {
|
||||
return delegate.doGetOrder(outTradeNo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
|
||||
return delegate.doUnifiedRefund(reqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) {
|
||||
return delegate.doGetRefund(outTradeNo, outRefundNo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayRefundRespDTO doParseRefundNotify(Map<String,String> params, String body) {
|
||||
return delegate.doParseRefundNotify(params, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayOrderRespDTO doParseOrderNotify(Map<String,String> params, String body) {
|
||||
return delegate.doParseOrderNotify(params, body);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package cn.iocoder.yudao.module.pay.framework.pay.wallet;
|
||||
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.delegate.DelegatePayClient;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
|
||||
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 钱包支付的 PayClient 实现类
|
||||
*
|
||||
* @author jason
|
||||
*/
|
||||
@Slf4j
|
||||
public class WalletPayClient extends DelegatePayClient<NonePayClientConfig> {
|
||||
|
||||
private PayWalletService payWalletService;
|
||||
|
||||
public WalletPayClient(Long channelId, String channelCode, NonePayClientConfig config) {
|
||||
super(channelId, channelCode, config);
|
||||
}
|
||||
|
||||
public WalletPayClient(Long channelId, String channelCode, NonePayClientConfig config, PayWalletService payWalletService) {
|
||||
this(channelId, channelCode, config);
|
||||
this.payWalletService = payWalletService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
// 钱包支付 无需初始化
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
|
||||
PayWalletTransactionDO payWalletTransaction = payWalletService.pay(reqDTO.getOutTradeNo(), reqDTO.getPrice());
|
||||
return PayOrderRespDTO.successOf(payWalletTransaction.getNo(), payWalletTransaction.getCreator(),
|
||||
payWalletTransaction.getTransactionTime(),
|
||||
reqDTO.getOutTradeNo(), "");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) {
|
||||
throw new UnsupportedOperationException("钱包支付无支付回调");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayOrderRespDTO doGetOrder(String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) {
|
||||
throw new UnsupportedOperationException("钱包支付无退款回调");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,81 @@
|
||||
package cn.iocoder.yudao.module.pay.service.wallet;
|
||||
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper;
|
||||
import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
|
||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType;
|
||||
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.pay.enums.member.WalletBizTypeEnum.PAYMENT;
|
||||
|
||||
/**
|
||||
* 钱包 Service 实现类
|
||||
*
|
||||
* @author jason
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PayWalletServiceImpl implements PayWalletService {
|
||||
|
||||
private static final String WALLET_CHANNEL_NO_PREFIX = "W";
|
||||
@Resource
|
||||
@Lazy
|
||||
private PayOrderService payOrderService;
|
||||
@Resource
|
||||
private PayWalletMapper payWalletMapper;
|
||||
@Resource
|
||||
private PayWalletTransactionService payWalletTransactionService;
|
||||
@Resource
|
||||
private PayNoRedisDAO noRedisDAO;
|
||||
|
||||
@Override
|
||||
public PayWalletDO getPayWallet(Long userId, Integer userType) {
|
||||
return payWalletMapper.selectByUserIdAndType(userId, userType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public PayWalletTransactionDO pay(String outTradeNo, Integer price) {
|
||||
// 判断支付交易拓展单是否存在
|
||||
PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo);
|
||||
if (orderExtension == null) {
|
||||
throw exception(ORDER_EXTENSION_NOT_FOUND);
|
||||
}
|
||||
Long userId = getLoginUserId();
|
||||
Integer userType = getLoginUserType();
|
||||
PayWalletDO payWallet = getPayWallet(userId, userType);
|
||||
if (payWallet == null) {
|
||||
log.error("[pay] 用户 {} 钱包不存在", userId);
|
||||
throw exception(WALLET_NOT_FOUND);
|
||||
}
|
||||
// 判断余额是否足够
|
||||
int afterBalance = payWallet.getBalance() - price;
|
||||
if(afterBalance < 0){
|
||||
throw exception(WALLET_NOT_ENOUGH);
|
||||
}
|
||||
payWallet.setBalance(afterBalance);
|
||||
payWallet.setTotalExpense(payWallet.getTotalExpense() + price);
|
||||
payWalletMapper.updateById(payWallet);
|
||||
|
||||
// 生成钱包渠道流水号
|
||||
String walletNo = noRedisDAO.generate(WALLET_CHANNEL_NO_PREFIX);
|
||||
PayWalletTransactionDO payWalletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId())
|
||||
.setNo(walletNo).setAmount(price).setBalance(afterBalance).setTransactionTime(LocalDateTime.now())
|
||||
.setBizId(orderExtension.getOrderId()).setBizType(PAYMENT.getBizType());
|
||||
payWalletTransactionService.addPayWalletTransaction(payWalletTransaction);
|
||||
|
||||
return payWalletTransaction;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue