WooCommerce支付网关 API 是基于类的一个接口,我们可以使用这个接口为 WooCoomerce 开发一个自定义支付网关 WordPress插件,在这篇文章中,我俩为大家介绍一下使用支付网关 API 为WooCommerce添加支付网关的方法。
WooCommerce支付网关的类型
WooCommerce有 4 种类型的支付网关:
- 基于表单 – 这种方法中,用户必须点击表单中的提交按钮,然后跳转到第三方支付网关的网站处理支付。如 PayPal 标准接口, Authorize.net DPM,支付宝。
- 基于 iFrame – 这种方法在 iframe 内加载网关支付系统,如: SagePay 表单, PayPal 高级接口。
- 直接支付 – 如果使用这种支付方法,在结帐页面当点击 ‘下订单’ 的同时,已经支付成功了。 如: PayPal Pro, Authorize.net AIM
- 线下支付 – 没有线上处理过程. 如: Cheque, Bank Transfer
基于表单和基于 iframe 的支付方式需要发送 post 数据到相应的第三方支付网关站点,没有太多安全问题需要考虑,直接支付需要实施服务端加密(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
– 如果需要在前端的支付网关名称后面显示一个图标,在这里定义图片 URLI。$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' );
最后,我们需要添加一个方法到保存设置 hook 上:
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
init_form_fields()
使用此方法设置 $this->form_fields
– 将有一些选项被添加到支付网关的设置页面中,这些选项通过 WC Settings API 添加。
最起码,我们应该添加3个基本的设置字段——是否启用、标题和描述:
$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 同时告诉 WC 重定向用户到什么页面,以上处理通过返回的一个数组实现。
下面是从 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' ));
// 减少库存
$order->reduce_order_stock();
// 清空购物车
$woocommerce->cart->empty_cart();
// 返回感谢购物页面跳转
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
}
如上面看到的上面的方法完成了以下几个工作:
- 获取并更新订单状态为等待中或支付成功
- 减少库存并情况购物车
- 返回成功信息并跳转到指定 URL (在此示例中为更些购买页面)
Cheque 不能自动确认支付状态,所以指定订单状态为“等待中”,如果我们创建的支付网关可以自动判断订单状态,我们可以直接完成订单。
$order->payment_complete();
这个方法确保库存会发生相应减少,并修改订状态为正确的值。
如果支付失败,我们应该报出一个报错,并返回 null:
wc_add_notice( __('Payment error:', 'woothemes') . $error_message, 'error' );
return;
WooCommerce将捕捉到这个错误,并在结账页面显示。
更新订单状态并添加订单备注
更新订单状态可以使用订单类中的方法,我们只应该在订单没有处理的时候更新订单状态,如果订单处理成功,我们应该使用 payment_complete() 方法完成订单。下面是更新订单状态的示例:
$order = new WC_Order( $order_id );
$order->update_status('on-hold', __('Awaiting cheque payment', 'woothemes'));
上面的实力代码更新订单状态为“等待中”,并添加了一个订单备注通知管理员正在等待 Cheque 网关确认,我们可以使用 add_order_note()方法直接添加订单备注,而不用更新订单状态,以方便调试支付网关。
$order->add_order_note( __('IPN payment completed', 'woothemes') );
订单状态最佳实践
- 如果订单完成了,但是需要管理员进行手动确认的,使用“等待中”状态。
- 如果订单支付失败,设置为 “失效”
- 如果支付已完成,使用
$order->payment_complete()
方法让WooCommerce设置订单状态和备注信息WooCommerce将使用 已完成 maybe 处理中 状态并处理库存。
直接支付网关注意事项
如果我们在创建一个高级的,直接支付网关,(直接在支付页面上进行支付), 有几步额外的工作需要完成:
$this->has_fields = true;
此变量告诉支付页面输出一个 ‘payment_box’ 容器,显示我们定义的支付网关信息。
创建一个名为 payment_fields()
的方法——此方法包含一个表单信息,类似信用卡支付样式。
下一步可选方法是添加一个 validate_fields()
,如果表单通过验证,返回 true,否则返回 false,如果需要显示一个错误信息,可以使用 wc_add_notice()
function.
最后,我们需要在 process_payment( $order_id )
方法中添加支付代码,此代码获取表单提交的数据,并通过第三方支付网关进行支付。
如果支付失败,我们应该输出一个错误信息,不返回任何信息。
wc_add_notice( __('Payment error:', 'woothemes') . $error_message, 'error' );
return;
如果支付成功,我们应该设置订单为“已支付”,并返回成功信息数组。
// 支付完成
$order->payment_complete();
// 返回成功信息,并跳转到感谢后买页面。
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
支付网关回调
如果我们正在开发一个支持使用回调传回订单状态的网关,我们需要在网关中添加处理回调的代码。添加回调和回调方法最好的方法是使用 woocommerce_api_(action) Action 钩子, 下面是 PayPal 标准方法的示例,设置 回调/IPN URL 为:
str_replace( 'https:', 'http:', add_query_arg( 'wc-api', 'WC_Gateway_Paypal', home_url( '/' ) ) );
然后挂载到他自己的处理方法到 hook 上:
add_action( 'woocommerce_api_wc_gateway_paypal', array( $this, 'check_ipn_response' ) );
当支付网站返回信息到我们定义的支付回调 URL 时,WooCommerce会调用我们的自定义支付网关并执行相应的操作。
更多信息,请参见 WC_API 文档The
支付网关 Hooks
需要格外注意的是,添加功能到支付网关类中可能不会被触发,支付网关只有在需要时才会加载,比如在支付页面或后台管理页面中。如果我们需要挂载 WordPress 事件到类中时,我们应该在类外边或者使用 WC-API 挂载。