在开始之前,确保你已经查看了如何创建WooCommerce支付网关的完整指南(重要的是在阅读这篇文章之前先阅读那个)。但是,如果你正在使用WooCommerce的最新版本(我认为是从8.3开始),你可能会发现你的自定义支付方式没有出现在结账区块中。
比如说,如果你试图在商店里禁用除了你自定义的支付方式以外的所有支付方式,你可能会遇到以下的错误信息:
虽然使用旧版的
不过别担心,我们有了一个新教程来填补这个空白。我会一步步带你了解如何为WooCommerce的购物车和结账区块添加一个自定义支付方式,以确保它与最新版本兼容。
到本教程结束时,我们的目标是:
当然,我也会教你一些额外的小技巧,比如给你的支付方式加上一个自定义图标。
服务器端集成
首先,我们将从服务器端的集成开始。我知道你们很多人可能更喜欢使用PHP来开发,而不是JavaScript和React,所以我们就从简单的部分开始吧。
注册一个块支持 PHP 类
区块支持PHP类”是一个PHP类,用于处理我们的支付网关,除了主要的支付网关类外。我们将用以下简单的代码片段来注册它,这个过程和我们之前在woocommerce_payment_gateways
钩子中注册主网关类的方式很相似。
add_action( 'woocommerce_blocks_loaded', 'rudr_gateway_block_support' );
function rudr_gateway_block_support() {
// if( ! class_exists( 'Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType' ) ) {
// return;
// }
// 在这里引入 "gateway block support class" 文件
require_once __DIR__ . '/includes/class-wc-misha-gateway-blocks-support.php';
// 注册我们刚才引入的 PHP 类
add_action(
'woocommerce_blocks_payment_method_type_registration',
function( Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry $payment_method_registry ) {
$payment_method_registry->register( new WC_Misha_Gateway_Blocks_Support );
}
);
}
请记住以下几点:
- 我去掉了
class_exists()
这个条件,因为我们现在不需要它了。这是因为结账区块已经成为WooCommerce的一部分,不再是一个单独的插件。 - 我们的区块支持PHP类将被放在一个独立的文件中,我们会在接下来的步骤中详细讨论这个文件,它的名字是
class-wc-misha-gateway-blocks-support.php
。
块支持 PHP 类
在这一部分,我将会创建一个名为WC_Misha_Gateway_Blocks_Support
的PHP类,这个类将扩展WooCommerce的AbstractPaymentMethodType
类。同时,请记住我们已经有了一个名为WC_Misha_Gateway
的类,它扩展了WC_Payment_Gateway
。
对于我自己,我会把这个新的类文件放到includes/class-wc-misha-gateway-blocks-support.php
中。
<?php
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
final class WC_Misha_Gateway_Blocks_Support extends AbstractPaymentMethodType {
private $gateway;
protected $name = 'misha'; // payment gateway id
public function initialize() {
// get payment gateway settings
$this->settings = get_option( "woocommerce_{$this->name}_settings", array() );
// you can also initialize your payment gateway here
// $gateways = WC()->payment_gateways->payment_gateways();
// $this->gateway = $gateways[ $this->name ];
}
public function is_active() {
return ! empty( $this->settings[ 'enabled' ] ) && 'yes' === $this->settings[ 'enabled' ];
}
public function get_payment_method_script_handles() {
wp_register_script(
'wc-misha-blocks-integration',
plugin_dir_url( __DIR__ ) . 'build/index.js',
array(
'wc-blocks-registry',
'wc-settings',
'wp-element',
'wp-html-entities',
),
null, // or time() or filemtime( ... ) to skip caching
true
);
return array( 'wc-misha-blocks-integration' );
}
public function get_payment_method_data() {
return array(
'title' => $this->get_setting( 'title' ),
// almost the same way:
// 'title' => isset( $this->settings[ 'title' ] ) ? $this->settings[ 'title' ] : 'Default value';
'description' => $this->get_setting( 'description' ),
// if $this->gateway was initialized on line 15
// 'supports' => array_filter( $this->gateway->supports, [ $this->gateway, 'supports' ] ),
// example of getting a public key
// 'publicKey' => $this->get_publishable_key(),
);
}
//private function get_publishable_key() {
// $test_mode = ( ! empty( $this->settings[ 'testmode' ] ) && 'yes' === $this->settings[ 'testmode' ] );
// $setting_key = $test_mode ? 'test_publishable_key' : 'publishable_key';
// return ! empty( $this->settings[ $setting_key ] ) ? $this->settings[ $setting_key ] : '';
//}
}
让我们先来看看这个类的属性和方法:
属性:
$name
:这是支付网关的唯一标识符。$gateway
:这里可以存放支付网关对象的实例,但这不是强制的,因此我在代码中没有包括这部分。
方法:
is_active()
:这个方法用来检查支付方式是否激活。get_payment_method_script_handles()
:这里是添加JavaScript文件的地方,这些文件包含客户端部分的集成代码。get_payment_method_data()
:这个方法提供了所有你需要在前端使用的数据,以关联数组的形式呈现。
你还可以利用index.asset.php
来获取脚本的版本和依赖项。
public function get_payment_method_script_handles() {
$asset_path = plugin_dir_path( __DIR__ ) . 'build/index.asset.php';
$version = null;
$dependencies = array();
if( file_exists( $asset_path ) ) {
$asset = require $asset_path;
$version = isset( $asset[ 'version' ] ) ? $asset[ 'version' ] : $version;
$dependencies = isset( $asset[ 'dependencies' ] ) ? $asset[ 'dependencies' ] : $dependencies;
}
wp_register_script(
'wc-misha-blocks-integration',
plugin_dir_url( __DIR__ ) . 'build/index.js',
$dependencies,
$version,
true
);
return array( 'wc-misha-blocks-integration' );
}
声明兼容性
当你的支付方式不支持WooCommerce的结账区块时,这部分特别重要。
当用户在Gutenberg编辑器里编辑结账页面时,他们会看到一个提示信息:
方法如下:
add_action( 'before_woocommerce_init', 'rudr_cart_checkout_blocks_compatibility' );
function rudr_cart_checkout_blocks_compatibility() {
if( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
'cart_checkout_blocks',
__FILE__,
false // true (compatible, default) or false (not compatible)
);
}
}
客户端集成
设置项目
我想让这个教程保持非常简单,所以我会使用@wordpress/scripts
来完成。
在构建过程中,你当然可以进行更深入的配置,比如设置WooCommerce的混合构建,这样你就能使用import { registerPaymentMethod } from ....
这样的代码。
这是我的文件夹结构看起来的样子:
为 WooCommerce Checkout 区块注册自定义付款方式
这是/src/index.js
文件的内容,以便于您更好地理解
import { decodeEntities } from '@wordpress/html-entities';
const { registerPaymentMethod } = window.wc.wcBlocksRegistry
const { getSetting } = window.wc.wcSettings
const settings = getSetting( 'misha_data', {} )
const label = decodeEntities( settings.title )
const Content = () => {
return decodeEntities( settings.description || '' )
}
const Label = ( props ) => {
const { PaymentMethodLabel } = props.components
return <PaymentMethodLabel text={ label } />
}
registerPaymentMethod( {
name: "misha",
label: <Label />,
content: <Content />,
edit: <Content />,
canMakePayment: () => true,
ariaLabel: label,
supports: {
features: settings.supports,
}
})
也许深入探讨registerPaymentMethod()
和registerExpressPaymentMethod()
会很有帮助,但我打算在我的博客的下一篇教程里更详细地讲解这些例子。
最后,恭喜你完成了这一步!
如果您想知道付款方式标题和说明的来源:
添加付款方式图标
因为我承诺会给你更多的例子,而你可能不想等待下一篇教程,所以我们现在就开始吧。
我要做的是在WooCommerce结账区块的自定义支付网关旁边展示一个图标:
首先,我们来调整我们的区块支持PHP类,特别是get_payment_method_data()
方法,在那里我们会增加一个新的参数:
public function get_payment_method_data() {
return array(
'title' => $this->get_setting( 'title' ),
'description' => $this->get_setting( 'description' ),
'icon' => plugin_dir_url( __DIR__ ) . 'assets/icon.png',
...
然后我建议为其创建另一个 React 组件:
const Icon = () => {
return settings.icon
? <img src={settings.icon} style={{ float: 'right', marginRight: '20px' }} />
: ''
}
const Label = () => {
return (
<span style={{ width: '100%' }}>
{label}
<Icon />
</span>
);
};
如果没有提供图标的图片链接,那么<img>
标签就不会显示,这真是太好了!
- 最新
- 最热
只看作者