乐于分享
好东西不私藏

WooCommerce 支付插件开发 – 可扩展支付网关基类设计

WooCommerce 支付插件开发 – 可扩展支付网关基类设计

做 WooCommerce 支付插件开发,最头疼的就是重复代码。每接一个新渠道,都要从头写一遍支付流程、通知处理、配置管理。代码越写越多,维护成本越来越高。

今天分享一个实战方案:设计一个可扩展的支付网关基类,让新增支付方式只需要几行代码。

woo-antom-gateway-支付引导

为什么需要基类设计

先说说问题。传统的支付插件开发是这样的:

// 支付宝网关
class WC_Gateway_Alipay extends WC_Payment_Gateway
{
    public
function process_payment($order_id{ /* 300行代码 */ }
    public
function payment_notify_handler({ /* 200行代码 */ }
    // ... 各种重复逻辑

}

// 微信支付网关  

class WC_Gateway_Wechat extends WC_Payment_Gateway
{
    public
function process_payment($order_id{ /* 又是300行,几乎一样 */ }
    public
function payment_notify_handler({ /* 又是200行,几乎一样 */ }
}

看起来是两个不同的支付方式,实际上 80% 的代码是一样的:

  • • 订单金额转换和校验
  • • 支付请求构造和发送
  • • 异步通知接收和验签
  • • 订单状态更新逻辑
  • • 错误处理和日志记录

基类设计的核心思想就是:把共性抽出来,差异点留给子类。

基类架构设计

我们的基类 WC_Gateway_Antom_Common 继承自 WooCommerce 的 WC_Payment_Gateway,这是标准做法。

abstractclass WC_Gateway_Antom_Common extends WC_Payment_Gateway{
    protected
 $currency;

    public
function __construct({
        $this
->init_settings();
        $this
->setup_props();
        $this
->init_form_fields();

        // 注册必要的事件钩子

        add_action
('woocommerce_update_options_payment_gateways_' . $this->id, 
                   [$this, 'process_admin_options']);
        add_action
('woocommerce_api_antom_payment_notify'
                   [$this, 'payment_notify_handler']);
    }
}

注意这里用了 abstract,强制子类必须实现某些方法,同时基类里可以包含完整的通用逻辑。

属性初始化:setup_props()

每个支付方式都有图标、支持的币种、显示名称等属性。基类里统一处理:

protectedfunction setup_props({
    // 从配置中读取图标

    $this
->icon = $this->get_pay_setting('icon');
    $this
->has_fields = true;
    $this
->supports = ['products'];

    // 支持的币种列表

    $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);
}

这里的关键设计是 get_pay_setting() 方法,它从统一的配置数组中读取当前支付方式的属性。新增支付方式时,只需要在配置数组里加一条记录,不用改基类代码。

核心支付流程: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'];

    // 2. 检查支付环境

    if
 (!$this->is_valid_for_use()) {
        return
 $this->return_failure('支付方式配置错误');
    }

    // 3. 构造支付请求

    $request
 = $this->build_payment_request($order, $core_settings);

    // 4. 发送请求并处理响应

    $response
 = $this->send_payment_request($request);

    // 5. 返回结果给 WooCommerce

    return
 $this->handle_payment_response($order, $response);
}

基类里封装了完整的支付流程,子类只需要关心自己的特殊逻辑。比如信用卡支付需要额外的 3D 验证处理,可以在子类里重写特定方法。

异步通知处理

支付完成后,第三方平台会异步通知商户。基类里提供完整的验签和状态更新逻辑:

publicfunction payment_notify_handler({
    // 1. 获取请求数据

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

    // 2. 提取关键字段

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

    // 3. 验签(安全第一)

    $verify_result
 = Antom_Signature_Tool::verify(
        'POST'
, '/wc-api/antom_payment_notify',
        $client_id
, $headers['Request-Time'],
        $body
, $signature, $public_key
    );

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

    // 4. 解析通知内容

    $notify_data
 = json_decode($body, true);
    $order
 = $this->get_order_by_payment_request_id(
        $notify_data
['paymentRequestId']
    );

    // 5. 更新订单状态(幂等处理)

    $this
->update_order_status($order, $notify_data);
}

这里有几个关键点:

  • • 验签必须做:防止伪造通知
  • • 幂等处理:同一笔支付可能多次通知,要根据当前状态判断是否处理
  • • 快速响应:异步通知要求尽快返回,不要在这里做耗时操作

子类实现:极简模式

有了基类,子类的实现就简单多了。以 DANA 钱包为例:

class WC_Gateway_Antom_DANA extends WC_Gateway_Antom_Common{
    public
 $id = 'antom_dana';
}

就这几行,一个完整的支付方式就实现了。所有支付流程、通知处理、配置管理都复用基类。

再看信用卡支付,需要一些特殊处理:

class WC_Gateway_Antom_Card extends WC_Gateway_Antom_Common{
    public
 $id = 'antom_card';

    // 信用卡需要额外收集卡号信息

    public
function payment_fields({
        // 渲染卡号输入表单

        echo
 $this->get_card_form_html();
    }

    // 处理信用卡特有的 3D 验证

    protected
function handle_3d_secure($order, $response{
        if
 (isset($response['normalUrl'])) {
            // 跳转到 3D 验证页面

            return
 ['result' => 'success', 'redirect' => $response['normalUrl']];
        }
        return
 parent::handle_payment_response($order, $response);
    }
}

子类只需要关注自己的差异点,通用逻辑全部下沉到基类。

配置管理设计

支付方式的各种属性(图标、币种、显示名称等)集中管理:

function antom_get_payment_methods({
    return
 [
        'antom_alipay_cn'
 => [
            'slug'
 => 'antom_alipay_cn',
            'payment_method_type'
 => 'ALIPAY_CN',
            'support_currencies'
 => ['CNY', 'USD', 'HKD', 'SGD'],
            'icon'
 => ['alipay-icon.svg'],
            'gateway_file'
 => 'includes/gateways/class-wc-gateway-antom-alipay-cn.php',
            'gateway_class'
 => 'WC_Gateway_Antom_Alipay_CN',
        ],
        'antom_dana'
 => [
            'slug'
 => 'antom_dana',
            'payment_method_type'
 => 'DANA',
            'support_currencies'
 => ['IDR', 'USD'],
            'icon'
 => ['dana-icon.svg'],
            'gateway_file'
 => 'includes/gateways/class-wc-gateway-antom-dana.php',
            'gateway_class'
 => 'WC_Gateway_Antom_DANA',
        ],
        // ... 更多支付方式

    ];
}

主插件文件里统一加载:

// 加载基类
require_once
 'includes/gateways/class-wc-gateway-antom-common.php';

// 自动加载所有支付方式

$payment_methods
 = antom_get_payment_methods();
foreach
 ($payment_methods as $method) {
    if
 (is_file($method['gateway_file'])) {
        require_once
 $method['gateway_file'];
    }
}

// 注册到 WooCommerce

add_filter
('woocommerce_payment_gateways', function($gateways) {
    $methods
 = antom_get_payment_methods();
    foreach
 ($methods as $method) {
        if
 (class_exists($method['gateway_class'])) {
            $gateways
[] = $method['gateway_class'];
        }
    }
    return
 $gateways;
});

新增支付方式只需要:

  1. 1. 在配置数组里加一条记录
  2. 2. 创建一个继承基类的子类(通常就几行代码)

安全设计

支付插件安全是重中之重,基类里必须包含:

1. 请求签名

所有发往支付平台的请求都要签名:

class Antom_Signature_Tool{
    public
 staticfunction sign($httpMethod, $path, $clientId,
                               $reqTime
, $content, $privateKey
{
        // 构造签名内容

        $signContent
 = $httpMethod . ' ' . $path . "\n"
                     . $clientId . '.' . $reqTime . '.' . $content;

        // RSA-SHA256 签名

        openssl_sign
($signContent, $signature, $privateKey, 'sha256');
        return
 urlencode(base64_encode($signature));
    }
}

2. 响应验签

支付平台的回调通知必须验签:

public staticfunction verify($httpMethod, $path, $clientId,
                              $rspTime
, $rspBody, $signature, $publicKey
{
    $rspContent
 = $httpMethod . ' ' . $path . "\n"
                . $clientId . '.' . $rspTime . '.' . $rspBody;

    $signature
 = urldecode($signature);
    return
 openssl_verify($rspContent, base64_decode($signature),
                         $publicKey
, 'sha256') === 1;
}

3. 并发控制

防止用户重复点击支付按钮导致重复扣款:

class Antom_Payment_Request_Checker{
    public
function check_payment_limit($order{
        // 检查是否已有成功支付

        if
 ($this->has_successful_payment()) {
            return
 ['result' => 'success', 'redirect' => $order->get_view_order_url()];
        }

        // 检查并发请求数量

        if
 ($this->payment_request_count >= 20) {
            return
 ['error' => '支付尝试次数已达上限'];
        }

        // 生成或复用 payment_request_id

        return
 $this->get_or_create_payment_request_id();
    }
}

总结

这套基类设计支撑了 15+ 支付方式的接入,核心思路就几点:

1. 抽象共性,隔离差异

  • • 支付流程、通知处理、配置管理全部下沉到基类
  • • 子类只关注自己的特殊逻辑

2. 配置驱动

  • • 支付方式属性集中管理
  • • 新增渠道只需改配置,不用改代码

3. 安全第一

  • • 请求签名 + 响应验签
  • • 并发控制和幂等处理
  • • 敏感信息不硬编码

4. 可扩展性

  • • 抽象基类 + 具体实现
  • • 钩子机制支持自定义
  • • 自动加载减少重复代码

实际项目中,这套架构让新增一个支付方式的时间从几天缩短到几小时。对于需要接入多渠道支付的项目,这种设计思路很有参考价值。

woo-antom-gateway-插件设置
本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » WooCommerce 支付插件开发 – 可扩展支付网关基类设计

猜你喜欢

  • 暂无文章