钱包支付 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;
|
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.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.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.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
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 实现类
|
* 钱包 Service 实现类
|
||||||
*
|
*
|
||||||
* @author jason
|
* @author jason
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
@Slf4j
|
||||||
public class PayWalletServiceImpl implements PayWalletService {
|
public class PayWalletServiceImpl implements PayWalletService {
|
||||||
|
private static final String WALLET_CHANNEL_NO_PREFIX = "W";
|
||||||
|
@Resource
|
||||||
|
@Lazy
|
||||||
|
private PayOrderService payOrderService;
|
||||||
@Resource
|
@Resource
|
||||||
private PayWalletMapper payWalletMapper;
|
private PayWalletMapper payWalletMapper;
|
||||||
|
@Resource
|
||||||
|
private PayWalletTransactionService payWalletTransactionService;
|
||||||
|
@Resource
|
||||||
|
private PayNoRedisDAO noRedisDAO;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PayWalletDO getPayWallet(Long userId, Integer userType) {
|
public PayWalletDO getPayWallet(Long userId, Integer userType) {
|
||||||
return payWalletMapper.selectByUserIdAndType(userId, 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