From c7f6f921598990cc0b3709e03e46628a9e8f7fbd Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sun, 27 Aug 2023 10:10:28 +0800 Subject: [PATCH] =?UTF-8?q?=E9=92=B1=E5=8C=85=E6=94=AF=E4=BB=98=20Client?= =?UTF-8?q?=20=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pay/core/client/PayClientFactory.java | 4 ++ .../core/client/impl/NonePayClientConfig.java | 31 ++++++++ .../client/impl/PayClientFactoryImpl.java | 6 ++ .../impl/delegate/DelegatePayClient.java | 58 +++++++++++++++ .../core/enums/channel/PayChannelEnum.java | 5 +- .../module/pay/enums/ErrorCodeConstants.java | 1 + .../pay/enums/member/WalletBizTypeEnum.java | 3 +- .../framework/pay/wallet/WalletPayClient.java | 72 +++++++++++++++++++ .../channel/PayChannelServiceImpl.java | 24 ++++++- .../pay/service/order/PayOrderService.java | 8 +++ .../service/order/PayOrderServiceImpl.java | 5 ++ .../pay/service/wallet/PayWalletService.java | 3 + .../service/wallet/PayWalletServiceImpl.java | 59 ++++++++++++++- .../wallet/PayWalletTransactionService.java | 2 + .../PayWalletTransactionServiceImpl.java | 10 ++- 15 files changed, 285 insertions(+), 6 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/NonePayClientConfig.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java index f6d0ca6b5..5825c83e5 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.pay.core.client; +import cn.iocoder.yudao.framework.pay.core.client.impl.delegate.DelegatePayClient; + /** * 支付客户端的工厂接口 * @@ -25,4 +27,6 @@ public interface PayClientFactory { void createOrUpdatePayClient(Long channelId, String channelCode, Config config); + void createOrUpdateDelegatePayClient(Long channelId, DelegatePayClient delegatePayClient); + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/NonePayClientConfig.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/NonePayClientConfig.java new file mode 100644 index 000000000..48319036c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/NonePayClientConfig.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.framework.pay.core.client.impl; + +import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; +import lombok.Data; + +import javax.validation.Validator; + +/** + * 无需任何配置 PayClientConfig 实现类 + * + * @author jason + */ +@Data +public class NonePayClientConfig implements PayClientConfig { + + /** + * 配置名称 + *

+ * 如果不加任何属性,JsonUtils.parseObject2 解析会报错,所以暂时加个名称 + */ + private String name; + + public NonePayClientConfig(){ + this.name = "none-config"; + } + + @Override + public void validate(Validator validator) { + // 无任何配置不需要校验 + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java index 121aeb087..e8ae76607 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.*; +import cn.iocoder.yudao.framework.pay.core.client.impl.delegate.DelegatePayClient; import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClient; import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.*; @@ -51,6 +52,11 @@ public class PayClientFactoryImpl implements PayClientFactory { } } + @Override + public void createOrUpdateDelegatePayClient(Long channelId, DelegatePayClient delegatePayClient) { + clients.put(channelId, delegatePayClient); + } + @SuppressWarnings("unchecked") private AbstractPayClient createPayClient( Long channelId, String channelCode, Config config) { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java new file mode 100644 index 000000000..e700c70ec --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java @@ -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 extends AbstractPayClient { + + private final DelegatePayClient 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 params, String body) { + return delegate.doParseRefundNotify(params, body); + } + + @Override + protected PayOrderRespDTO doParseOrderNotify(Map params, String body) { + return delegate.doParseOrderNotify(params, body); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java index 073b17f3c..cbe0a242a 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.pay.core.enums.channel; import cn.hutool.core.util.ArrayUtil; +import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClientConfig; @@ -29,7 +30,9 @@ public enum PayChannelEnum { ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class), ALIPAY_BAR("alipay_bar", "支付宝条码支付", AlipayPayClientConfig.class), - MOCK("mock", "模拟支付", MockPayClientConfig.class); + MOCK("mock", "模拟支付", MockPayClientConfig.class), + + WALLET("wallet", "钱包支付", NonePayClientConfig.class); /** * 编码 diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java index b319f006f..5b244b79f 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java @@ -43,6 +43,7 @@ public interface ErrorCodeConstants { // ========== 钱包模块(退款) 1007007000 ========== ErrorCode WALLET_NOT_FOUND = new ErrorCode(1007007000, "用户钱包不存在"); + ErrorCode WALLET_NOT_ENOUGH = new ErrorCode(1007007001, "钱包余额不足"); // ========== 示例订单 1007900000 ========== ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在"); diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletBizTypeEnum.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletBizTypeEnum.java index b39ed9d09..1ea73d8b0 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletBizTypeEnum.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletBizTypeEnum.java @@ -12,7 +12,8 @@ import lombok.Getter; @Getter public enum WalletBizTypeEnum { RECHARGE(1, "充值"), - RECHARGE_REFUND(2, "充值退款"); + RECHARGE_REFUND(2, "充值退款"), + PAYMENT(3, "支付"); // TODO 后续增加 /** diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java new file mode 100644 index 000000000..26300bbcc --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java @@ -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 { + + 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 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 params, String body) { + throw new UnsupportedOperationException("钱包支付无退款回调"); + } + + @Override + protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) { + return null; + } +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java index 57aaf07d0..9604ffbf7 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; @@ -15,6 +16,8 @@ import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateR import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; +import cn.iocoder.yudao.module.pay.framework.pay.wallet.WalletPayClient; +import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -26,6 +29,7 @@ import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.validation.Validator; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -56,6 +60,8 @@ public class PayChannelServiceImpl implements PayChannelService { @Resource private Validator validator; + @Resource + private PayWalletService payWalletService; /** * 初始化 {@link #payClientFactory} 缓存 @@ -75,10 +81,24 @@ public class PayChannelServiceImpl implements PayChannelService { log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]"); } log.info("[initLocalCache][缓存支付渠道,数量为:{}]", channels.size()); - + List walletChannels = new ArrayList<>(); + List otherChannels = new ArrayList<>(); + channels.forEach(t -> { + if (PayChannelEnum.WALLET.getCode().equals(t.getCode())) { + walletChannels.add(t); + } else { + otherChannels.add(t); + } + }); // 第二步:构建缓存:创建或更新支付 Client - channels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(), + otherChannels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(), payChannel.getCode(), payChannel.getConfig())); + + walletChannels.forEach(payChannel -> { + WalletPayClient walletPayClient = new WalletPayClient(payChannel.getId(), payChannel.getCode(), + (NonePayClientConfig) payChannel.getConfig(), payWalletService); + payClientFactory.createOrUpdateDelegatePayClient(payChannel.getId(), walletPayClient); + }); this.channelCache = channels; }); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java index 12618c287..3d66ae9b1 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java @@ -106,6 +106,14 @@ public interface PayOrderService { */ PayOrderExtensionDO getOrderExtension(Long id); + /** + * 获得支付订单 + * + * @param no 支付订单 no + * @return 支付订单 + */ + PayOrderExtensionDO getOrderExtensionByNo(String no); + /** * 同步订单的支付状态 * diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 20bb26087..d56035187 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -415,6 +415,11 @@ public class PayOrderServiceImpl implements PayOrderService { return orderExtensionMapper.selectById(id); } + @Override + public PayOrderExtensionDO getOrderExtensionByNo(String no) { + return orderExtensionMapper.selectByNo(no); + } + @Override public int syncOrder(LocalDateTime minCreateTime) { // 1. 查询指定创建时间内的待支付订单 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java index 3d99e5258..473e6f704 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.pay.service.wallet; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; /** * 钱包 Service 接口 @@ -15,4 +16,6 @@ public interface PayWalletService { * @param userType 用户类型 */ PayWalletDO getPayWallet(Long userId, Integer userType); + + PayWalletTransactionDO pay(String outTradeNo, Integer price); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java index 7d29b613e..d322c73e1 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java @@ -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; + } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java index a9bc91ab5..2ec913222 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java @@ -20,4 +20,6 @@ public interface PayWalletTransactionService { */ PageResult getWalletTransactionPage(Long userId, Integer userType, AppPayWalletTransactionPageReqVO pageVO); + + Long addPayWalletTransaction(PayWalletTransactionDO payWalletTransaction); } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java index f574b779f..e62edf549 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java @@ -21,7 +21,7 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.WALLET_NOT_FO */ @Service @Slf4j -public class PayWalletTransactionServiceImpl implements PayWalletTransactionService{ +public class PayWalletTransactionServiceImpl implements PayWalletTransactionService { @Resource private PayWalletService payWalletService; @Resource @@ -38,4 +38,12 @@ public class PayWalletTransactionServiceImpl implements PayWalletTransactionSer return payWalletTransactionMapper.selectPageByWalletIdAndQueryType(payWallet.getId(), WalletTransactionQueryTypeEnum.valueOf(pageVO.getType()), pageVO); } + + @Override + public Long addPayWalletTransaction(PayWalletTransactionDO payWalletTransaction) { + payWalletTransactionMapper.insert(payWalletTransaction); + return payWalletTransaction.getId(); + } + + }