源码深度剖析:pay-java-parent如何实现支付服务的统一抽象

【免费下载链接】pay-java-parent egzosn/pay-java-parent: 是一个基于 Java 的分布式支付系统,支持多种支付渠道和支付方式。该项目提供了一个简单易用的分布式支付系统,可以方便地实现各种支付场景的支付处理和结算,同时支持多种支付渠道和支付方式。 【免费下载链接】pay-java-parent 项目地址: https://gitcode.com/gh_mirrors/pa/pay-java-parent

在当今多支付渠道并存的商业环境中,Java开发者面临着一个重要挑战:如何优雅地对接支付宝、微信支付、银联、PayPal等不同支付平台?pay-java-parent项目提供了一个优雅的解决方案,通过统一的抽象层屏蔽了底层支付平台的差异,让开发者能够用一致的API处理各种支付场景。本文将深入剖析这个开源项目的架构设计实现原理,揭示其如何实现支付服务的统一抽象。

项目架构概览:模块化设计思想

pay-java-parent采用模块化设计,将项目分为四个核心部分:

  • pay-java-common - 公共库,包含支付核心与规范定义
  • pay-java-web-support - Web支持包,实现回调相关功能
  • pay-java-demo - 具体的支付演示示例
  • pay-java-* - 具体的支付实现库(如ali、wx、union等)

这种设计遵循了开闭原则,核心抽象层稳定不变,具体支付实现可灵活扩展。项目结构清晰地体现了单一职责原则,每个模块都有明确的职责边界。

支付系统架构图

统一接口设计:PayService的核心抽象

项目的核心在于PayService接口设计,它定义了所有支付渠道必须实现的统一API契约。让我们看看这个接口的关键方法:

// 支付服务接口定义
public interface PayService<PC extends PayConfigStorage> {
    // 订单创建与支付
    Map<String, Object> orderInfo(PayOrder order);
    String toPay(PayOrder order);
    Map<String, Object> app(PayOrder order);
    
    // 交易查询与管理
    Map<String, Object> query(AssistOrder assistOrder);
    Map<String, Object> close(AssistOrder assistOrder);
    RefundResult refund(RefundOrder refundOrder);
    
    // 回调处理
    boolean verify(NoticeParams params);
    PayOutMessage payBack(NoticeRequest request);
    
    // 二维码支付
    BufferedImage genQrPay(PayOrder order);
    String getQrPay(PayOrder order);
}

这个接口的设计精妙之处在于:

  1. 泛型参数PC extends PayConfigStorage确保类型安全
  2. 统一参数:所有方法使用相同的订单模型(PayOrder、RefundOrder等)
  3. 多态返回:返回类型统一为Map<String, Object>或特定结果对象
  4. 回调标准化:统一的回调验证和处理机制

抽象基类实现:BasePayService的通用逻辑

BasePayService作为抽象基类,实现了PayService接口的通用逻辑,为具体支付实现提供了代码复用的基础:

public abstract class BasePayService<PC extends PayConfigStorage> 
    implements PayService<PC> {
    
    protected PC payConfigStorage;
    protected HttpRequestTemplate requestTemplate;
    protected PayMessageHandler handler;
    protected List<PayMessageInterceptor> interceptors;
    
    // 提供通用实现,如HTTP请求模板管理、配置设置等
    @Override
    public BasePayService setPayConfigStorage(PC payConfigStorage) {
        this.payConfigStorage = payConfigStorage;
        return this;
    }
}

基类中包含了公共属性通用方法,具体支付服务只需关注差异化的业务逻辑。这种设计遵循了模板方法模式,将不变的部分放在基类,可变的部分留给子类实现。

配置管理统一:PayConfigStorage体系

支付配置的统一管理通过PayConfigStorage接口实现:

public interface PayConfigStorage extends Attrs {
    String getKeyPrivate();      // 应用私钥
    String getKeyPublic();       // 支付平台公钥
    String getNotifyUrl();       // 异步回调地址
    String getReturnUrl();       // 同步回调地址
    String getSignType();        // 签名加密类型
    String getInputCharset();    // 字符编码
    boolean isTest();           // 是否为沙箱环境
}

每个具体支付渠道都有对应的配置类,如AliPayConfigStorageWxPayConfigStorage等,它们都继承自BasePayConfigStorage。这种设计实现了配置的标准化,无论对接哪个支付平台,配置项都保持一致的结构

支付配置管理

数据模型设计:统一的业务对象

项目定义了一套标准化的数据模型,确保不同支付渠道使用相同的业务对象:

支付订单模型

public class PayOrder extends AssistOrder {
    private String subject;      // 商品名称
    private String body;         // 商品描述
    private BigDecimal price;    // 价格
    private String openid;       // 用户标识
    private CurType curType;     // 支付币种
    private Date expirationTime; // 订单过期时间
}

退款订单模型

public class RefundOrder extends AssistOrder {
    private BigDecimal refundAmount; // 退款金额
    private BigDecimal totalAmount;  // 订单总金额
    private String refundReason;     // 退款原因
}

交易类型接口

public interface TransactionType {
    String getType();  // 获取交易类型
    String getMethod(); // 获取接口方法
}

每个支付渠道都实现了自己的TransactionType枚举,如AliTransactionTypeWxTransactionType等,但它们都遵循相同的接口规范

具体支付实现:以支付宝为例

让我们看看AliPayService如何实现统一的支付接口:

public class AliPayService extends BasePayService<AliPayConfigStorage> 
    implements TransferService, AliPayServiceInf {
    
    @Override
    public Map<String, Object> orderInfo(PayOrder order) {
        // 构建支付宝特定的请求参数
        Map<String, Object> orderInfo = new TreeMap<>();
        orderInfo.put("app_id", payConfigStorage.getAppid());
        orderInfo.put("method", "alipay.trade.page.pay");
        orderInfo.put("charset", payConfigStorage.getInputCharset());
        
        // 调用支付宝API
        return requestTemplate.postForObject(
            getReqUrl(transactionType), 
            orderInfo, 
            Map.class
        );
    }
    
    @Override
    public boolean verify(NoticeParams noticeParams) {
        // 支付宝特定的签名验证逻辑
        Map<String, Object> params = noticeParams.getBody();
        return signVerify(params, (String) params.get("sign"));
    }
}

AliPayService继承了BasePayService,只需要实现支付宝特有的业务逻辑,如API调用参数构建、签名验证等。其他支付渠道的实现方式类似但不同,每个渠道都封装了自己的特殊处理逻辑

设计模式应用:策略模式与工厂模式

pay-java-parent巧妙运用了多种设计模式

策略模式

每个支付渠道都是一个具体的策略,通过统一的PayService接口对外提供服务。开发者可以根据需要动态切换支付策略:

// 策略模式的应用
PayService payService;
if ("ali".equals(payType)) {
    payService = new AliPayService(config);
} else if ("wx".equals(payType)) {
    payService = new WxPayService(config);
}
// 统一的调用方式
Map<String, Object> result = payService.orderInfo(payOrder);

工厂模式

在demo模块中,通过ApyAccountService实现了支付服务的工厂创建

public PayResponse getPayResponse(Integer payId) {
    ApyAccount apyAccount = apyAccounts.get(payId);
    return getPayResponse(apyAccount);
}

public PayResponse getPayResponse(ApyAccount apyAccount) {
    // 根据账户配置创建对应的支付服务
    if (apyAccount.getPayType() == PayType.aliPay) {
        return new PayResponse(apyAccount.buildAliPayService());
    } else if (apyAccount.getPayType() == PayType.wxPay) {
        return new PayResponse(apyAccount.buildWxPayService());
    }
    // ... 其他支付渠道
}

扩展机制:支持新的支付渠道

项目的可扩展性是其核心优势之一。要添加新的支付渠道,只需:

  1. 实现配置类:继承BasePayConfigStorage
  2. 实现服务类:继承BasePayService并实现PayService接口
  3. 定义交易类型:实现TransactionType接口
  4. 添加业务对象:定义渠道特定的业务模型(可选)

这种设计使得新增支付渠道变得非常简单,无需修改现有代码,符合开闭原则

实际应用:简洁的API调用

通过统一的抽象层,开发者可以极简地调用支付功能

// 1. 创建支付配置
AliPayConfigStorage config = new AliPayConfigStorage();
config.setAppid("your_app_id");
config.setKeyPrivate("your_private_key");

// 2. 创建支付服务
PayService payService = new AliPayService(config);

// 3. 创建支付订单
PayOrder order = new PayOrder("订单标题", "订单描述", BigDecimal.valueOf(0.01));

// 4. 发起支付
Map<String, Object> result = payService.orderInfo(order);
String payUrl = payService.toPay(order);

// 5. 处理回调
boolean verified = payService.verify(noticeParams);
if (verified) {
    // 处理支付成功逻辑
}

总结:统一抽象的价值

pay-java-parent通过精心的架构设计,实现了支付服务的统一抽象,为Java开发者带来了多重价值:

  1. 降低学习成本:一套API应对所有支付渠道
  2. 提高开发效率:无需重复编写支付对接代码
  3. 增强可维护性:支付逻辑集中管理,便于维护
  4. 提升扩展性:轻松支持新的支付渠道
  5. 保证一致性:统一的错误处理、日志记录、监控等

这个项目的设计哲学值得所有Java开发者学习:通过合理的抽象和分层,将复杂的多支付渠道对接问题转化为简单的统一API调用问题。无论是小型创业公司还是大型企业系统,pay-java-parent都能提供可靠、灵活、易用的支付解决方案。

通过深入理解这个项目的架构设计实现原理,开发者不仅能够更好地使用这个工具,还能从中学习到优秀的软件设计思想,提升自己的架构设计能力。支付服务的统一抽象不仅是一个技术实现,更是一种工程智慧的体现

【免费下载链接】pay-java-parent egzosn/pay-java-parent: 是一个基于 Java 的分布式支付系统,支持多种支付渠道和支付方式。该项目提供了一个简单易用的分布式支付系统,可以方便地实现各种支付场景的支付处理和结算,同时支持多种支付渠道和支付方式。 【免费下载链接】pay-java-parent 项目地址: https://gitcode.com/gh_mirrors/pa/pay-java-parent

Logo

立足具身智能前沿赛道,致力于搭建全球化、开源化、全栈式技术交流与实践共创平台。

更多推荐