package cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.wallet; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.module.pay.enums.PayChannelEnum; import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum; import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderRespDTO; import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.refund.PayRefundRespDTO; import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.transfer.PayTransferRespDTO; import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; import cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.AbstractPayClient; import cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.NonePayClientConfig; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService; import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService; import cn.iocoder.yudao.module.pay.service.wallet.PayWalletTransactionService; import lombok.extern.slf4j.Slf4j; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_EXTENSION_NOT_FOUND; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.REFUND_NOT_FOUND; /** * 钱包支付的 PayClient 实现类 * * @author jason */ @Slf4j public class WalletPayClient extends AbstractPayClient { public static final String WALLET_ID_KEY = "walletId"; private PayWalletService wallService; private PayWalletTransactionService walletTransactionService; private PayOrderService orderService; private PayRefundService refundService; private PayTransferService transferService; public WalletPayClient(Long channelId, NonePayClientConfig config) { super(channelId, PayChannelEnum.WALLET.getCode(), config); } @Override protected void doInit() { if (wallService == null) { wallService = SpringUtil.getBean(PayWalletService.class); } if (walletTransactionService == null) { walletTransactionService = SpringUtil.getBean(PayWalletTransactionService.class); } } @Override @SuppressWarnings("PatternVariableCanBeUsed") protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { try { Long walletId = MapUtil.getLong(reqDTO.getChannelExtras(), WALLET_ID_KEY); Assert.notNull(walletId, "钱包编号"); PayWalletTransactionDO transaction = wallService.orderPay(walletId, reqDTO.getOutTradeNo(), reqDTO.getPrice()); return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), transaction.getCreateTime(), reqDTO.getOutTradeNo(), transaction); } catch (Throwable ex) { log.error("[doUnifiedOrder][reqDTO({}) 异常]", reqDTO, ex); Integer errorCode = INTERNAL_SERVER_ERROR.getCode(); String errorMsg = INTERNAL_SERVER_ERROR.getMsg(); if (ex instanceof ServiceException) { ServiceException serviceException = (ServiceException) ex; errorCode = serviceException.getCode(); errorMsg = serviceException.getMessage(); } return PayOrderRespDTO.closedOf(String.valueOf(errorCode), errorMsg, reqDTO.getOutTradeNo(), ""); } } @Override protected PayOrderRespDTO doParseOrderNotify(Map params, String body, Map headers) { throw new UnsupportedOperationException("钱包支付无支付回调"); } @Override protected PayOrderRespDTO doGetOrder(String outTradeNo) { if (orderService == null) { orderService = SpringUtil.getBean(PayOrderService.class); } PayOrderExtensionDO orderExtension = orderService.getOrderExtensionByNo(outTradeNo); // 支付交易拓展单不存在, 返回关闭状态 if (orderExtension == null) { return PayOrderRespDTO.closedOf(String.valueOf(PAY_ORDER_EXTENSION_NOT_FOUND.getCode()), PAY_ORDER_EXTENSION_NOT_FOUND.getMsg(), outTradeNo, ""); } // 关闭状态 if (PayOrderStatusEnum.isClosed(orderExtension.getStatus())) { return PayOrderRespDTO.closedOf(orderExtension.getChannelErrorCode(), orderExtension.getChannelErrorMsg(), outTradeNo, ""); } // 成功状态 if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { PayWalletTransactionDO walletTransaction = walletTransactionService.getWalletTransaction( String.valueOf(orderExtension.getOrderId()), PayWalletBizTypeEnum.PAYMENT); Assert.notNull(walletTransaction, "支付单 {} 钱包流水不能为空", outTradeNo); return PayOrderRespDTO.successOf(walletTransaction.getNo(), walletTransaction.getCreator(), walletTransaction.getCreateTime(), outTradeNo, walletTransaction); } // 其它状态为无效状态 log.error("[doGetOrder] 支付单 {} 的状态不正确", outTradeNo); throw new IllegalStateException(String.format("支付单[%s] 状态不正确", outTradeNo)); } @Override @SuppressWarnings("PatternVariableCanBeUsed") protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { try { PayWalletTransactionDO payWalletTransaction = wallService.orderRefund(reqDTO.getOutRefundNo(), reqDTO.getRefundPrice(), reqDTO.getReason()); return PayRefundRespDTO.successOf(payWalletTransaction.getNo(), payWalletTransaction.getCreateTime(), reqDTO.getOutRefundNo(), payWalletTransaction); } catch (Throwable ex) { log.error("[doUnifiedRefund][reqDOT({}) 异常]", reqDTO, ex); Integer errorCode = INTERNAL_SERVER_ERROR.getCode(); String errorMsg = INTERNAL_SERVER_ERROR.getMsg(); if (ex instanceof ServiceException) { ServiceException serviceException = (ServiceException) ex; errorCode = serviceException.getCode(); errorMsg = serviceException.getMessage(); } return PayRefundRespDTO.failureOf(String.valueOf(errorCode), errorMsg, reqDTO.getOutRefundNo(), ""); } } @Override protected PayRefundRespDTO doParseRefundNotify(Map params, String body, Map headers) { throw new UnsupportedOperationException("钱包支付无退款回调"); } @Override protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) { if (refundService == null) { refundService = SpringUtil.getBean(PayRefundService.class); } PayRefundDO payRefund = refundService.getRefundByNo(outRefundNo); // 支付退款单不存在, 返回退款失败状态 if (payRefund == null) { return PayRefundRespDTO.failureOf(String.valueOf(REFUND_NOT_FOUND), REFUND_NOT_FOUND.getMsg(), outRefundNo, ""); } // 退款失败 if (PayRefundStatusEnum.isFailure(payRefund.getStatus())) { return PayRefundRespDTO.failureOf(payRefund.getChannelErrorCode(), payRefund.getChannelErrorMsg(), outRefundNo, ""); } // 退款成功 if (PayRefundStatusEnum.isSuccess(payRefund.getStatus())) { PayWalletTransactionDO walletTransaction = walletTransactionService.getWalletTransaction( String.valueOf(payRefund.getId()), PayWalletBizTypeEnum.PAYMENT_REFUND); Assert.notNull(walletTransaction, "支付退款单 {} 钱包流水不能为空", outRefundNo); return PayRefundRespDTO.successOf(walletTransaction.getNo(), walletTransaction.getCreateTime(), outRefundNo, walletTransaction); } // 其它状态为无效状态 log.error("[doGetRefund] 支付退款单 {} 的状态不正确", outRefundNo); throw new IllegalStateException(String.format("支付退款单[%s] 状态不正确", outRefundNo)); } @Override @SuppressWarnings("PatternVariableCanBeUsed") public PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) { try { Long walletId = Long.parseLong(reqDTO.getUserAccount()); PayWalletTransactionDO transaction = wallService.addWalletBalance(walletId, String.valueOf(reqDTO.getOutTransferNo()), PayWalletBizTypeEnum.TRANSFER, reqDTO.getPrice()); return PayTransferRespDTO.successOf(transaction.getNo(), transaction.getCreateTime(), reqDTO.getOutTransferNo(), transaction); } catch (Throwable ex) { log.error("[doUnifiedTransfer][reqDTO({}) 异常]", reqDTO, ex); Integer errorCode = INTERNAL_SERVER_ERROR.getCode(); String errorMsg = INTERNAL_SERVER_ERROR.getMsg(); if (ex instanceof ServiceException) { ServiceException serviceException = (ServiceException) ex; errorCode = serviceException.getCode(); errorMsg = serviceException.getMessage(); } return PayTransferRespDTO.closedOf(String.valueOf(errorCode), errorMsg, reqDTO.getOutTransferNo(), ""); } } @Override protected PayTransferRespDTO doParseTransferNotify(Map params, String body, Map headers) { throw new UnsupportedOperationException("钱包支付无转账回调"); } @Override protected PayTransferRespDTO doGetTransfer(String outTradeNo) { if (transferService == null) { transferService = SpringUtil.getBean(PayTransferService.class); } // 获取转账单 PayTransferDO transfer = transferService.getTransferByNo(outTradeNo); // 转账单不存在,返回关闭状态 if (transfer == null) { return PayTransferRespDTO.closedOf(String.valueOf(PAY_ORDER_EXTENSION_NOT_FOUND.getCode()), PAY_ORDER_EXTENSION_NOT_FOUND.getMsg(), outTradeNo, ""); } // 关闭状态 if (PayTransferStatusEnum.isClosed(transfer.getStatus())) { return PayTransferRespDTO.closedOf(transfer.getChannelErrorCode(), transfer.getChannelErrorMsg(), outTradeNo, ""); } // 成功状态 if (PayTransferStatusEnum.isSuccess(transfer.getStatus())) { PayWalletTransactionDO walletTransaction = walletTransactionService.getWalletTransaction( String.valueOf(transfer.getId()), PayWalletBizTypeEnum.TRANSFER); Assert.notNull(walletTransaction, "转账单 {} 钱包流水不能为空", outTradeNo); return PayTransferRespDTO.successOf(walletTransaction.getNo(), walletTransaction.getCreateTime(), outTradeNo, walletTransaction); } // 处理中状态 if (PayTransferStatusEnum.isProcessing(transfer.getStatus())) { return PayTransferRespDTO.processingOf(transfer.getChannelTransferNo(), outTradeNo, transfer); } // 等待状态 if (PayTransferStatusEnum.isWaiting(transfer.getStatus())) { return PayTransferRespDTO.waitingOf(transfer.getChannelTransferNo(), outTradeNo, transfer); } // 其它状态为无效状态 log.error("[doGetTransfer] 转账单 {} 的状态不正确", outTradeNo); throw new IllegalStateException(String.format("转账单[%s] 状态不正确", outTradeNo)); } }