WooCommerce 支付网关 API
WooCommerce 中的支付网关基于类,可以通过传统的插件进行添加。本指南提供支付网关开发的入门介绍。
支付网关的类型
支付网关有多种类型:
- 基于表单 - 用户必须点击表单上的一个按钮,然后被重定向到支付处理商的网站。示例: PayPal 标准版,Authorize.net DPM
- 基于 iFrame - 支付网关的支付系统加载在您的商店的 iFrame 中。示例: SagePay Form,PayPal 高级版
- 直接 - 支付字段直接显示在结账页面上,用户在点击“提交订单”按钮时完成支付。示例: PayPal Pro,Authorize.net AIM
- 离线 - 不进行在线支付。示例: 支票,银行转账
基于表单和 iFrame 的网关会将数据发送到外部服务器,这意味着您需要考虑的安全问题较少。但是,直接网关需要实施服务器安全措施(例如,SSL 证书),并且可能需要满足一定的 PCI 合规性 标准。
创建基本的支付网关
注意: 以下说明适用于默认的结账页面。如果您想为新的结账块添加自定义支付方式,请查看 支付方式集成文档。
支付网关应该作为附加插件创建,并与 WooCommerce 集成。在插件内部,您需要在插件加载后创建一个类。例如:
add_action( 'plugins_loaded', 'init_your_gateway_class' );
重要的是,您的网关类应该继承 WooCommerce 的基本网关类,以便您可以使用重要的方法和 设置 API。
function init_your_gateway_class() {
class WC_Gateway_Your_Gateway extends WC_Payment_Gateway {}
}
您可以在 API 文档中查看 WC_Payment_Gateway 类。
除了定义您的类之外,您还需要告诉 WooCommerce (WC) 它的存在。通过过滤 woocommerce_payment_gateways 来实现:
function add_your_gateway_class( $methods ) {
$methods[] = 'WC_Gateway_Your_Gateway';
return $methods;
}
add_filter( 'woocommerce_payment_gateways', 'add_your_gateway_class' );
必需的方法
大多数方法是从 WC_Payment_Gateway 类继承的,但某些方法需要在您的自定义网关中实现。
__construct()
在您的构造函数中,您应该定义以下变量:
$this->id- 您的网关的唯一 ID,例如 'your_gateway'$this->icon- 如果您想在前端显示网关名称旁边的图像,请输入指向图像的 URL。$this->has_fields- 布尔值。 如果您希望在结账页面显示支付字段(如果进行直接集成),则可以将其设置为 true。$this->method_title- 在管理页面上显示的支付方法标题。$this->method_description- 在管理页面上显示的支付方法描述。
您的构造函数还应该定义和加载设置字段:
$this->init_form_fields();
$this->init_settings();
稍后我们将介绍 init_form_fields(),但它基本上定义了您的设置,然后使用 init_settings() 加载。
在调用 init_settings() 之后,您可以获取设置并将它们加载到变量中,例如:
$this->title = $this->get_option( 'title' );
最后,您需要添加一个保存钩子,用于您的设置:
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
init_form_fields()
使用此方法来设置 $this->form_fields - 这些是在您的网关设置页面上的管理界面中显示的选项,并使用 WC 设置 API。
您的网关的基本设置应包括 启用/禁用、标题 和 描述:
$this->form_fields = array(
'enabled' => array(
'title' => __( '启用 / 禁用', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( '启用支票支付', 'woocommerce' ),
'default' => 'yes'
),
'title' => array(
'title' => __( '标题', 'woocommerce' ),
'type' => 'text',
'description' => __( '这控制用户在结账过程中看到的标题。', 'woocommerce' ),
'default' => __( '支票支付', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'title' => __( '客户消息', 'woocommerce' ),
'type' => 'textarea',
'default' => ''
)
);
process_payment( $order_id )
现在,我们来看网关最重要的部分:处理支付和处理订单。 process_payment 函数还会告诉 WooCommerce 将用户重定向到哪里,这通过返回的数组来实现。
以下是 Cheque 网关中 process_payment 函数的一个示例:
function process_payment( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
// 标记为待处理 (我们正在等待支票)
$order->update_status('on-hold', __( 'Awaiting cheque payment', 'woocommerce' ));
// 清空购物车
$woocommerce->cart->empty_cart();
// 返回感谢页面重定向
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
}
如您所见,它的作用是:
- 获取并更新正在处理的订单
- 返回成功状态和重定向 URL (在本例中是感谢页面)
Cheque 网关将订单状态设置为“待处理”,因为无法自动验证支付。 但是,如果您正在构建一个直接网关,则可以在此处完成订单。 不要使用 update_status 来更新已支付的订单,而应该使用 payment_complete:
$order->payment_complete();
这可以确保库存减少,并将状态更改为正确的值。
如果支付失败,您应该抛出错误并返回一个包含失败状态的数组:
wc_add_notice( __('Payment error:', 'woothemes') . $error_message, 'error' );
return array(
'result' => 'failure'
);
WooCommerce 会捕获此错误并在结账页面上显示它。
库存级别是通过操作 (woocommerce_payment_complete 以及订单状态之间的转换) 进行更新的,因此在处理支付时,不再需要手动调用减少库存级别的函数。
更新订单状态和添加备注
可以使用订单类中的函数来更新订单状态。 只有当订单状态不是“处理中”时,才应这样做(在这种情况下,您应该使用 payment_complete())。 更新为自定义状态的示例:
$order = new WC_Order( $order_id );
$order->update_status('on-hold', __('Awaiting cheque payment', 'woothemes'));
上面的示例将状态更新为“待处理”,并添加一条备注,告知所有者正在等待支票。 可以在不更新订单状态的情况下添加备注;这用于添加调试消息:
$order->add_order_note( __('IPN payment completed', 'woothemes') );
订单状态的最佳实践
- 如果订单已完成,但管理员需要手动验证支付,请使用 On-Hold 状态。
- 如果订单失败并且已创建,请将其设置为 Failed 状态。
- 如果支付已完成,请让 WooCommerce 处理状态,并使用
$order->payment_complete()。 WooCommerce 将使用 Completed 或 Processing 状态,并处理库存。
关于直接支付网关的说明
如果您正在创建一个高级、直接支付网关(即,一个在实际的结账页面上进行支付的网关),则涉及的步骤会更多。首先,您需要在网关构造函数中设置 has_fields 为 true:
$this->has_fields = true;
这会告诉结账系统输出一个名为 'payment_box' 的区域,其中包含您定义的直接支付表单。
创建一个名为 payment_fields() 的方法,该方法包含您的表单,通常会包含信用卡详细信息。
下一个可选的方法是 validate_fields()。如果表单通过验证,则返回 true;如果验证失败,则返回 false。您可以使用 wc_add_notice() 函数来添加错误信息并在用户界面上显示。
最后,您需要在 process_payment( $order_id ) 方法中添加支付代码。此代码接收已提交的表单数据,并尝试直接通过支付提供商进行支付。
如果支付失败,您应该输出一个错误信息并返回失败数组:
wc_add_notice( __('Payment error:', 'woothemes') . $error_message, 'error' );
return array(
'result' => 'failure',
);
如果支付成功,您应该将订单状态设置为已支付,并返回成功数组:
// 支付完成
$order->payment_complete();
// 返回感谢页面重定向
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
使用支付网关回调(例如 PayPal IPN)
如果您正在构建一个网关,该网关会向您的商店发送回调,以告知您订单的状态,则需要在您的网关中添加代码来处理此操作。
添加回调和回调处理程序最好的方法是使用 WC-API 钩子。一个例子是 PayPal Standard 的做法。它将回调/IPN URL 设置为:
str_replace( 'https:', 'http:', add_query_arg( 'wc-api', 'WC_Gateway_Paypal', home_url( '/' ) ) );
然后,它将处理程序挂载到该钩子上:
add_action( 'woocommerce_api_wc_gateway_paypal', array( $this, 'check_ipn_response' ) );
当访问该 URL 时,WooCommerce 会调用您的网关并运行该操作。
有关更多信息,请参阅 WC_API - WooCommerce API 回调。
网关中的钩子
重要的是要注意,在网关类中添加钩子可能不会触发。网关仅在需要时才会被加载,例如在结账过程中和在管理后台的设置页面。
如果您需要从您的类中挂载到 WordPress 事件,请将钩子放在类外部,或者使用 WC-API。