乐于分享
好东西不私藏

woocommerce支付插件之一个插件如何撑起 15+ 支付方式

本文最后更新于2026-03-10,某些文章具有时效性,若有错误或已失效,请在下方留言或联系老夜

woocommerce支付插件之一个插件如何撑起 15+ 支付方式

Antom 支付网关核心架构解析:一套代码如何撑起 15+ 支付方式

做电商开发的都知道,支付集成是个体力活。每接一个新的支付渠道,就要写一套网关代码,重复造轮子不说,维护起来更是噩梦。

今天聊聊 Antom 支付网关的设计思路。他们用一个通用基类搞定了支付宝、信用卡、GCash、DANA、Boost 等十几种支付方式,代码复用率相当高。这套架构是怎么设计的?咱们拆开来看。

Antom 支付引导

架构设计的核心思路

Antom 的解决方案很直接:抽象共性,隔离差异

所有支付方式都有相似的流程:用户下单 → 构造支付请求 → 调用支付 API → 处理异步通知 → 更新订单状态。差异点主要在于支付方法类型、支持的币种、前端展示方式这些配置项。

所以他们设计了一个抽象基类 WC_Gateway_Antom_Common,把通用逻辑全部封装进去。具体支付方式只需要继承这个基类,设置自己的唯一标识,剩下的都交给父类处理。

来看下类继承关系:

// 所有电子钱包都继承同一个基类
class WC_Gateway_Antom_DANA extends WC_Gateway_Antom_Common
{
    public
 $id = 'antom_dana';
}

class WC_Gateway_Antom_GCash extends WC_Gateway_Antom_Common
{
    public
 $id = 'antom_gcash';
}

class WC_Gateway_Antom_Boost extends WC_Gateway_Antom_Common
{
    public
 $id = 'antom_boost';
}

就这么简单。每个子类只需要定义自己的 ID,支付流程、通知处理、状态管理全部复用基类实现。

支付流程的完整链路

当用户在 WooCommerce 结账页提交订单时,核心流程是这样的:

插件设置

1. 支付请求初始化

process_payment() 方法是整个流程的入口。这里做了几件关键的事:

publicfunction process_payment( $order_id{
    $order
 = wc_get_order( $order_id );

    // 1. 加载核心配置

    $core_settings
 = antom_get_core_settings();
    $client_id
 = $core_settings['clientid'];
    $private_key
 = $core_settings['private_key'];
    $test_mode
 = $core_settings['test_mode'];

    // 2. 根据模式选择 API 端点

    $api_host
 = Antom_Payment_Gateways_Statement::ANTOM_ALIPAY_API_HOST;
    $path
 = $test_mode ?
        Antom_Payment_Gateways_Statement
::ANTOM_ALIPAY_SANDBOX_PATH :
        Antom_Payment_Gateways_Statement
::ANTOM_ALIPAY_PATH;

    // 3. 检查结算币种(生产环境必须设置)

    if
 ( ! $test_mode && ! $core_settings['settlement_currency'] ) {
        return
 $this->return_failure( '结算币种未设置' );
    }

    // ... 构造支付请求

}

这段代码体现了几个设计细节:

  • • 配置集中管理:通过 antom_get_core_settings() 统一读取,避免散落在各处
  • • 沙箱/生产自动切换:根据 test_mode 自动选择 API 端点,开发和上线无缝切换
  • • 前置校验:结算币种这种关键配置,在发起请求前就检查,而不是等 API 报错

2. 订单模型组装

支付请求需要携带订单信息、金额、支付方法、环境参数等。Antom 用了一组模型类来结构化这些数据:

// 构造金额模型
$total_amount
 = intval( antom_order_amount_value_to_decimal( $total, $currency ) );
$amount_model
 = new Antom_Order_Amount_Model();
$amount_model
->set_currency( $currency );
$amount_model
->set_value( $total_amount );

// 构造订单模型

$order_model
 = new Antom_Order_Model();
$order_model
->set_order_amount( $amount_model->toArray() );
$order_model
->set_reference_order_id( $order_id );
$order_model
->set_order_description( 'order info' );

// 构造支付方法模型

$payment_method_model
 = new Antom_Order_Payment_Method_Model();
$payment_method_model
->set_payment_method_type( $payment_method_type );

这种模型化的设计有几个好处:

  • • 类型安全:不用裸数组传参,IDE 能提示,减少手误
  • • 结构清晰:每个模型职责单一,金额就是金额,订单就是订单
  • • 易于扩展:加字段改模型就行,不用动核心逻辑

3. 支付请求检查器

这里有个很有意思的设计——Antom_Payment_Request_Checker。它负责管理支付请求的生命周期,防止重复支付和并发问题。

$payment_request_checker = new Antom_Payment_Request_Checker( $order );
$payment_request_checker
->load_all_payment_request_ids();

// 检查是否已有成功支付的记录

if
 ( $payment_request_checker->has_successful_payment_request_id() ) {
    return
 array(
        'result'
 => 'success',
        'redirect'
 => $order->get_view_order_url(),
    );
}

// 检查并发支付请求数量是否超限(默认最多 20 个)

if
 ( $payment_request_checker->payment_request_ids_number_is_limit() ) {
    return
 $this->return_failure( '支付尝试次数已达上限' );
}

// 获取或生成支付请求 ID

$payment_request_id_info
 = $payment_request_checker->get_intermediate_payment_request_id_info();

这个检查器解决了几个实际场景的问题:

  • • 用户重复点击支付按钮:生成唯一的 payment_request_id,同一订单多次点击不会重复扣款
  • • 页面刷新后重新支付:复用已有的支付请求 ID,避免创建新订单
  • • 并发控制:限制同时进行的支付请求数量,防止资源耗尽

异步通知处理机制

支付完成后,第三方支付平台会异步通知商户服务器。Antom 的处理逻辑在 payment_notify_handler() 方法里:

publicfunction payment_notify_handler({
    // 1. 获取请求头和请求体

    $headers
 = getallheaders();
    $body
 = file_get_contents( 'php://input' );

    // 2. 提取关键字段

    $client_id
 = $headers['Client-Id'] ?? '';
    $signature
 = $headers['Signature'] ?? '';
    $request_time
 = $headers['Request-Time'] ?? '';

    // 3. 验证签名(防止伪造通知)

    $verify_result
 = Antom_Signature_Tool::verify(
        'POST'
,
        '/wc-api/antom_payment_notify'
,
        $client_id
,
        $request_time
,
        $body
,
        $signature
,
        $alipay_public_key

    );

    if
 ( ! $verify_result ) {
        wp_die
( '签名验证失败' );
    }

    // 4. 解析通知内容

    $notify_data
 = json_decode( $body, true );
    $notify_type
 = $notify_data['notifyType']; // PAYMENT_RESULT / CAPTURE_RESULT
    $payment_request_id
 = $notify_data['paymentRequestId'];

    // 5. 查找对应订单并更新状态

    $order
 = $this->get_order_by_payment_request_id( $payment_request_id );
    // ... 更新订单状态

}

通知处理有几个关键点:

签名验证是第一道防线。任何人都可以往你的回调地址发请求,必须通过 RSA 公钥验证签名,确认消息确实来自支付平台。

幂等处理防止重复更新。同一笔支付可能多次通知,需要根据订单当前状态判断是否需要处理。已完成的订单直接返回成功,不做重复操作。

快速响应。异步通知要求尽快返回,不要在这里做耗时操作。订单状态更新、邮件通知这些可以丢给后台任务。

数字签名工具类

签名是支付安全的基石。Antom 的 Antom_Signature_Tool 工具类封装了 RSA-SHA256 的签名和验签逻辑:

class Antom_Signature_Tool{
    // 生成请求签名

    public
 staticfunction sign( $httpMethod, $path, $clientId, $reqTime, $content, $merchantPrivateKey{
        // 构造签名内容:方法 + 路径 + clientId + 时间戳 + 请求体

        $signContent
 = self::genSignContent( $httpMethod, $path, $clientId, $reqTime, $content );

        // 使用商户私钥签名

        $signValue
 = self::signWithSHA256RSA( $signContent, $merchantPrivateKey );

        return
 urlencode( $signValue );
    }

    // 验证响应签名

    public
 staticfunction verify( $httpMethod, $path, $clientId, $rspTime, $rspBody, $signature, $alipayPublicKey{
        $rspContent
 = self::genSignContent( $httpMethod, $path, $clientId, $rspTime, $rspBody );
        return
 self::verifySignatureWithSHA256RSA( $rspContent, $signature, $alipayPublicKey );
    }

    private
 staticfunction genSignContent( $httpMethod, $path, $clientId, $timeString, $content{
        // 格式:GET /ams/api/v1/payments/pay\nclientId.2024-01-01T00:00:00+08:00.{json}

        return
 $httpMethod . ' ' . $path . "\n" . $clientId . '.' . $timeString . '.' . $content;
    }
}

签名内容的构造很有讲究。它不是简单地把参数拼接,而是按照固定格式:

HTTP_METHOD PATH\nClientId.RequestTime.RequestBody

这种格式保证了签名的唯一性和不可篡改性。哪怕只改一个字符,签名就会对不上。

配置管理与币种支持

Antom 把支付方式的配置集中管理,通过 antom_get_payment_methods() 函数统一返回:

function antom_get_payment_methods({
    return
 array(
        'antom_alipay_cn'
 => array(
            'slug'
 => 'antom_alipay_cn',
            'payment_method_type'
 => 'ALIPAY_CN',
            'support_currencies'
 => array( 'CNY', 'USD', 'HKD', 'SGD' ),
            'icon'
 => array( 'alipay-icon.svg' ),
        ),
        'antom_card'
 => array(
            'slug'
 => 'antom_card',
            'payment_method_type'
 => 'CARD',
            'support_currencies'
 => array( 'USD', 'EUR', 'GBP', 'JPY', 'AUD' ),
        ),
        // ... 其他支付方式

    );
}

网关基类在初始化时会读取这些配置,自动设置支持的币种、图标、显示名称等:

protectedfunction setup_props({
    $this
->icon = $this->get_pay_setting( 'icon' );
    $this
->currency = $this->get_pay_setting( 'support_currencies' );
    $this
->title = $this->get_option( 'title' ) ?: $this->get_pay_setting( 'default_display_name' );

    // 后台显示支持的币种列表

    $show_currency
 = array_slice( $this->currency, 0, 4 );
    if
 ( count( $this->currency ) > 4 ) {
        $show_currency
[] = ' and others';
    }
    $this
->method_description = '支持币种: ' . implode( ' ', $show_currency );
}

总结

Antom 支付网关的架构设计有几个值得借鉴的点:

抽象基类 + 具体实现:把通用逻辑下沉到基类,子类只关注差异点,代码复用率高

模型化数据:用对象代替数组,结构清晰,类型安全

状态机管理:支付请求检查器控制并发和重复,保证数据一致性

安全第一:签名验证贯穿请求和响应,防止中间人攻击和伪造通知

这套架构支撑了 15+ 支付方式的接入,新增一个钱包只需要几行代码。对于需要接入多渠道支付的项目,这种设计思路很有参考价值。

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » woocommerce支付插件之一个插件如何撑起 15+ 支付方式

评论 抢沙发

5 + 7 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮