WooCommerce 文档

title: "WooCommerce 支付令牌 API" post_status: publish comment_status: open taxonomy: category: - woocommerce post_tag: - Payments - Features - Repos


WooCommerce 支付令牌 API

WooCommerce 2.6 引入了一个 API,用于存储和管理网关的支付令牌。用户还可以从他们的账户设置中管理这些令牌,并在结账时从已保存的支付令牌中进行选择。

本指南提供了一些有用的教程,用于使用新的 API,以及您可用的各种方法。

教程

为您的网关添加支付令牌 API 支持

在以下示例中,我们将使用 Simplify Commerce 网关。

步骤 0:扩展正确的网关基础类

WooCommerce 提供了两个用于网关的基础类。这些类与令牌 API 一起在 2.6 中引入。它们是 WC_Payment_Gateway_CC(用于基于信用卡的令牌)和 WC_Payment_Gateway_eCheck(用于基于电子支票的令牌)。它们包含一些用于在结账时生成支付表单的有用代码,并且应该能够覆盖大多数情况。

如果您需要,您还可以通过扩展抽象类 WC_Payment_Gateway 来实现您自己的网关基础类。

由于 Simplify 处理信用卡,因此我们扩展了信用卡网关。

class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC

步骤 1:'Supports' 数组

我们需要告诉 WooCommerce 我们的网关支持令牌化。与其他网关功能一样,这在网关的 __construct 方法中,在一个名为 supports 的数组中定义。

这是 Simplify 的数组:

$this->supports = array(
    'subscriptions',
    'products',
    ...
    'refunds',
    'pre-orders',
);

tokenization 添加到此数组中。

第二步:定义一种方法,用于从“我的账户”中添加/保存新的付款方式

当从“我的账户”部分添加新的付款方式时,将调用表单处理程序,该处理程序会调用网关的 add_payment_method 方法。

您的 add_payment_method 应该返回一个包含两个键的数组,一个 result 字符串和一个 redirect URL:

array(
   'result'   => 'success', // 或者 'failure'
   'redirect' => wc_get_endpoint_url( 'payment-methods' ),
);

在进行任何验证(即,确保从支付提供商处获取了所需的令牌和数据)后,您可以开始构建一个新的令牌,方法是创建以下类之一的实例:WC_Payment_Token_CCWC_Payment_Token_eCheck。 类似于网关,您也可以扩展抽象类 WC_Payment_Token 并定义您自己的令牌类型,如果需要的话。有关这三个类及其方法的更多信息,请参阅本文档的后续部分。

由于 Simplify 使用信用卡,因此我们将使用信用卡类。

$token = new WC_Payment_Token_CC();

我们将使用各种 set_ 方法来传递有关我们令牌的信息。 首先,我们将传递令牌字符串和网关 ID,以便将令牌与 Simplify 相关联。

$token->set_token( $token_string );
$token->set_gateway_id( $this->id ); // `$this->id` 引用在 `__construct` 中设置的网关 ID

此时,我们可以设置任何其他我们想要存储在令牌中的必要信息。 信用卡需要卡类型(Visa、MasterCard 等)、卡号的后四位、到期月份和到期年份。

$token->set_card_type( 'visa' );
$token->set_last4( '1234' );
$token->set_expiry_month( '12' );
$token->set_expiry_year( '2018' );

在大多数情况下,您还希望将令牌与特定用户关联:

$token->set_user_id( get_current_user_id() );

最后,在构建了令牌对象后,我们可以将令牌保存到数据库中。

$token->save();

如果令牌已成功保存,save 将返回 true;如果发生错误(例如缺少字段),则返回 false

第三步:在结账时保存付款方式

WooCommerce 还允许客户在“我的账户”之外,在结账过程中保存新的付款令牌。您需要添加一些代码到您的网关的 process_payment 函数中,以使其正常工作。

要确定是否需要保存新的付款方式,您可以检查以下 POST 字段,如果选择了“保存到账户”复选框,则该字段应返回 true

wc-{$gateway_id}-new-payment-method

如果您之前为用户提供了已保存的令牌,您还可以查看 wc-{$gateway_id}-payment-token 字段,如果该字段的值为 new,则表示选择了“使用新卡”/“使用新的付款方式”单选按钮。

一旦确定需要保存令牌,您就可以像在第二步中那样,使用 set_save 方法来保存令牌。

第 4 步:处理支付时获取令牌

如果用户选择了某个令牌,您需要在网关中处理支付时检索该已保存的令牌。这应该也在您的 process_payment 方法中完成。

您可以使用类似于以下的代码片段来检查是否应使用现有令牌:

if ( isset( $_POST['wc-simplify_commerce-payment-token'] ) && 'new' !== $_POST['wc-simplify_commerce-payment-token'] ) {

wc-{$gateway_id}}-payment-token 将返回所选令牌的 ID。

然后,您可以从 ID 加载令牌(稍后在本文档中将详细介绍 WC_Payment_Tokens 类):

$token_id = wc_clean( $_POST['wc-simplify_commerce-payment-token'] );
$token    = WC_Payment_Tokens::get( $token_id );

会检查加载的令牌是否属于当前用户。您可以使用简单的检查来完成此操作:

// 令牌用户 ID 与当前用户 ID 不匹配... 停止支付处理。
if ( $token->get_user_id() !== get_current_user_id() ) {
    // 可选地使用 `wc_add_notice` 显示通知
    return;
}

在加载了令牌并执行了任何必要的检查后,您可以使用 $token->get_token() 来获取实际的令牌字符串(以便将其传递给您的支付提供商)。

创建新的令牌类型

如果您提供的电子支票 (eCheck) 和信用卡 (CC) 令牌类型不能满足您的需求,您可以扩展抽象类 WC_Payment_Token 并创建新的令牌类型。 如果您这样做,则需要包含一些内容。

第 0 步:扩展 WC_Payment_Token 并命名您的类型

首先,扩展 WC_Payment_Token 并为新的类型提供一个名称。 让我们看看 eCheck 令牌类的构建方式,因为它是在 WooCommerce 核心中提供的最基本的令牌类型。

一个最基本的令牌文件的外观如下:

class WC_Payment_Token_eCheck extends WC_Payment_Token {

    /** @protected string 令牌类型字符串 */
    protected $type = 'eCheck';

}

此令牌类型的名称为 'eCheck'。 $type 中提供的值需要与类名匹配(即:WC_Payment_Token_$type)。

第一步:提供一个验证方法

在将令牌保存到数据库之前,会执行一些基本的验证。WC_Payment_Token 检查实际令牌值是否已设置,以及上面定义的 $type。 如果您想验证其他数据的存在(例如,eCheck 需要最后 4 位数字)或长度(到期月份应为 2 个字符),您可以提供自己的 validate() 方法。

validate() 方法应返回 true,如果一切正常;如果出现问题,则返回 false

始终确保在添加自己的逻辑之前,调用 WC_Payment_Tokenvalidate() 方法。

public function validate() {
    if ( false === parent::validate() ) {
           return false;
    }

现在,我们可以添加一些逻辑来处理“最后 4 位”数字。

if ( ! $this->get_last4() ) {
    return false;
}

最后,如果顺利执行到 validate() 方法的末尾,则返回 true

    return true;
}

第二步:为额外数据提供 get_set_ 方法

现在,您可以为每个您想要公开的数据添加自己的方法。 提供了方便的函数,可以轻松地存储和检索数据。 所有数据都存储在元数据表中,因此您无需创建自己的表或向现有表添加新字段。

为每个您想要捕获的数据提供一个 get_set_ 方法。 对于 eCheck,这是“last4”,表示支票的最后 4 位数字。

public function get_last4() {
    return $this->get_meta( 'last4' );
}

public function set_last4( $last4 ) {
    $this->add_meta_data( 'last4', $last4, true );
}

就此为止! 这些元数据函数由 WC_Data 提供。

第三步:使用您的新令牌类型

现在,您可以直接在创建新令牌时使用您的新令牌类型:

`$token = new WC_Payment_Token_eCheck();`
// 设置令牌属性
$token->save()

或者,当使用 WC_Payment_Tokens::get( $token_id ) 时,它将返回您的新令牌类型。

WC_Payment_Tokens

此类提供了一组有用的方法,用于与支付令牌进行交互。 所有方法都是静态的,可以在不创建类的实例的情况下调用。

get_customer_tokens( $customer_id, $gateway_id = '' )

返回一个包含 $customer_id 中指定客户的令牌对象的数组。 您可以通过提供网关 ID 来按网关进行过滤。

// 获取当前用户的全部令牌
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id() );
// 获取用户 42 的全部令牌
$tokens = WC_Payment_Tokens::get_customer_tokens( 42 );
// 获取当前用户的所有 Simplify 令牌
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), 'simplify_commerce' );

get_customer_default_token( $customer_id )

返回标记为“默认”的支付令牌对象(即在结账时自动选择的令牌)。 如果用户没有默认支付令牌/没有支付令牌,此函数将返回 null。

// 获取当前用户的默认支付令牌
$token = WC_Payment_Tokens::get_customer_default_token( get_current_user_id() );
// 获取用户 520 的默认支付令牌
$token = WC_Payment_Tokens::get_customer_default_token( 520 );

get_order_tokens( $order_id )

订单可以关联支付令牌(例如,用于订阅产品和续费)。 您可以使用此函数获取关联的令牌列表。 另外,您还可以使用 WC_Orderget_payment_tokens() 函数来获得相同的结果。

// 获取与订单 25 关联的支付令牌
$tokens = WC_Payment_Tokens::get_order_tokens( 25 );
// 通过 WC_Order 获取与订单 25 关联的支付令牌
$order = wc_get_order( 25 );
$tokens =  $order->get_payment_tokens();

get( $token_id )

返回由提供的 $token_id 指定的单个支付令牌对象。

// 获取支付令牌 52
$token = WC_Payment_Tokens::get( 52 );

delete( $token_id )

删除提供的令牌。

// 删除支付令牌 52
WC_Payment_Tokens::delete( 52 );

set_users_default( $user_id, $token_id )

将提供的令牌 ($token_id) 设置为提供的用户 ($user_id) 的默认令牌。 它会移除当前设置为默认的令牌,并设置新的令牌。

// 将用户 17 的默认令牌设置为令牌 82
WC_Payment_Tokens::set_users_default( 17, 82 );

get_token_type_by_id( $token_id )

如果您知道令牌的 ID,但不知道它的类型(信用卡、电子支票等),可以使用此函数。

// 确定支付令牌 23 是信用卡令牌
$type = WC_Payment_Tokens::get_token_type_by_id( 23 );

WC_Payment_Token_CC

set_ 方法不会更新数据库中的令牌。 您必须调用 save()create()(仅用于新令牌)或 update()(仅用于现有令牌)。

validate()

确保信用卡令牌存储了后 4 位数字,有效期年份的格式为 YYYY,有效期月份的格式为 MM,卡类型以及实际的令牌。

$token = new WC_Payment_Token_CC();
$token->set_token( 'token here' );
$token->set_last4( '4124' );
$token->set_expiry_year( '2017' );
$token->set_expiry_month( '1' ); // 长度不正确
$token->set_card_type( 'visa' );
var_dump( $token->validate() ); // bool(false)
$token->set_expiry_month( '01' );
var_dump( $token->validate() ); // bool(true)

get_card_type()

获取卡类型(visa、mastercard 等)。

$token = WC_Payment_Tokens::get( 42 );
echo $token->get_card_type();

set_card_type( $type )

设置信用卡类型。这是一个自由格式的文本字段,但可以使用以下值,WooCommerce 将显示格式化的标签。可以通过 woocommerce_credit_card_type_labels 过滤器添加新的标签。

$token = WC_Payment_Tokens::get( 42 );
$token->set_last4( 'visa' );
echo $token->get_card_type(); // 返回 visa

支持的类型/标签:

array(
    'mastercard'       => __( 'MasterCard', 'woocommerce' ),
    'visa'             => __( 'Visa', 'woocommerce' ),
    'discover'         => __( 'Discover', 'woocommerce' ),
    'american express' => __( 'American Express', 'woocommerce' ),
    'diners'           => __( 'Diners', 'woocommerce' ),
    'jcb'              => __( 'JCB', 'woocommerce' ),
) );

get_expiry_year()

获取信用卡的到期年份。

$token = WC_Payment_Tokens::get( 42 );
echo $token->get_expiry_year;

set_expiry_year( $year )

设置信用卡的到期年份。格式为 YYYY。

$token = WC_Payment_Tokens::get( 42 );
$token->set_expiry_year( '2018' );
echo $token->get_expiry_year(); // 返回 2018

get_expiry_month()

获取信用卡的到期月份。

$token = WC_Payment_Tokens::get( 42 );
echo $token->get_expiry_month();

set_expiry_month( $month )

设置信用卡的到期月份。格式为 MM。

$token = WC_Payment_Tokens::get( 42 );
$token->set_expiry_year( '12' );
echo $token->get_expiry_month(); // 返回 12

get_last4()

获取存储的信用卡号码的后 4 位数字。

$token = WC_Payment_Tokens::get( 42 );
echo $token->get_last4();

set_last4( $last4 )

设置存储的信用卡号码的后 4 位数字。

$token = WC_Payment_Tokens::get( 42 );
$token->set_last4( '2929' );
echo $token->get_last4(); // 返回 2929

WC_Payment_Token_eCheck

set_ 方法不会更新数据库中的令牌。您必须调用 save()create()(仅适用于新令牌)或 update()(仅适用于现有令牌)。

validate()

确保 eCheck 令牌存储了后 4 位数字以及实际的令牌。

$token = new WC_Payment_Token_eCheck();
$token->set_token( 'token here' );
var_dump( $token->validate() ); // bool(false)
$token->set_last4( '4123' );
var_dump( $token->validate() ); // bool(true)

get_last4()

获取存储的账户号码的后 4 位数字。

$token = WC_Payment_Tokens::get( 42 );
echo $token->get_last4();

set_last4( $last4 )

设置存储的信用卡号码的后 4 位数字。

$token = WC_Payment_Tokens::get( 42 );
$token->set_last4( '2929' );
echo $token->get_last4(); // 返回 2929

WC_Payment_Token

您不应该直接使用 WC_Payment_Token 类。请使用其中一个内置的令牌类 (WC_Payment_Token_CC 用于信用卡,WC_Payment_Token_eCheck 用于电子支票)。 如果上述方法都不适用于您,您可以扩展此类。 此部分中定义的所有方法都可供这些类使用。

set_ 方法不会更新数据库中的令牌。 您必须调用 save() (保存),create() (仅用于创建新令牌),或 update() (仅用于更新现有令牌)。

get_id()

获取令牌的 ID。

// 获取用户 ID 为 26 的默认令牌的 ID
$token = WC_Payment_Tokens::get_customer_default_token( 26 );
echo $token->get_id();

get_token()

获取实际的令牌字符串(用于与支付处理商通信)。

$token = WC_Payment_Tokens::get( 49 );
echo $token->get_token();

set_token( $token )

设置令牌字符串。

// $api_token 来自向支付处理商的 API 请求。
$token = WC_Payment_Tokens::get( 42 );
$token->set_token( $api_token );
echo $token->get_token(); // 返回我们的令牌

get_type()

获取令牌的类型。可以是 CC(信用卡)或 eCheck(电子支票)。 这也会返回任何新引入的类型。

$token = WC_Payment_Tokens::get( 49 );
echo $token->get_type();

get_user_id()

获取与令牌关联的用户 ID。

$token = WC_Payment_Tokens::get( 49 );
if ( $token->get_user_id() === get_current_user_id() ) {
    // 此令牌属于当前用户。
}

set_user_id( $user_id )

将令牌与用户关联。

$token = WC_Payment_Tokens::get( 42 );
$token->set_user_id( '21' ); // 此令牌现在属于用户 21。
echo $token->get_last4(); // 返回 2929

get_gateway_id

获取与令牌关联的网关。

$token = WC_Payment_Tokens::get( 49 );
$token->get_gateway_id();

set_gateway_id( $gateway_id )

设置与令牌关联的网关。 这应该与您网关中定义的 "ID" 匹配。 例如,'simplify_commerce' 是核心中 Simplify 实现的 ID。

$token->set_gateway_id( 'simplify_commerce' );
echo $token->get_gateway_id();

is_default()

如果令牌被标记为用户的默认令牌,则返回 true。 默认令牌将在结账时自动选择。

$token = WC_Payment_Tokens::get( 42 ); // 令牌 42 是用户 3 的默认令牌
var_dump( $token->is_default() ); // 返回 true
$token = WC_Payment_Tokens::get( 43 ); // 令牌 43 是用户 3 的令牌,但不是默认的
var_dump( $token->is_default() ); // 返回 false

set_default( $is_default )

切换一个令牌的“默认”标志。 传递 true 将其设置为默认值,如果它只是另一个令牌,则传递 false。 这不会取消设置任何其他可能设置为默认值的令牌。 您可以使用 WC_Payment_Tokens::set_users_default() 来处理这种情况。

$token = WC_Payment_Tokens::get( 42 ); // 令牌 42 是用户 3 的默认令牌
var_dump( $token->is_default() ); // 返回 true
$token->set_default( false );
var_dump( $token->is_default() ); // 返回 false

validate()

进行检查,以确保令牌和令牌类型(信用卡、电子支票等)都存在。 请参阅 WC_Payment_Token_CC::validate()WC_Payment_Token_eCheck::validate() 以了解用法。

read( $token_id )

从数据库加载现有的令牌对象。 请参阅 WC_Payment_Tokens::get(),它是此函数的别名。

// 加载信用卡令牌,ID 为 55,用户 ID 为 5
$token = WC_Payment_Token_CC();
$token->read( 55 );
echo $token->get_id(); // 返回 55
echo $token->get_user_id(); // 返回 5

update()

更新现有的令牌。 这将获取所有更改的字段(set_ 函数),并将它们实际保存到数据库中。 返回 truefalse,具体取决于是否成功。

$token = WC_Payment_Tokens::get( 42 ); // 信用卡令牌
$token->set_expiry_year( '2020' );
$token->set_expiry_month( '06 ');
$token->update();

create()

这将创建一个新的令牌到数据库中。 因此,一旦您构建了它,create() 将在数据库中创建一个新的令牌,其中包含详细信息。 返回 truefalse,具体取决于是否成功。

$token = new WC_Payment_Token_CC();
// 设置 last4、到期年份、月份和卡类型
$token->create(); // 保存到数据库

save()

save() 可以替代 update()create()。 如果您正在处理现有的令牌,则 save() 将调用 update()。 新的令牌将调用 create()。 返回 truefalse,具体取决于是否成功。

// 调用 update
$token = WC_Payment_Tokens::get( 42 ); // 信用卡令牌
$token->set_expiry_year( '2020' );
$token->set_expiry_month( '06 ');
$token->save();
// 调用 create
$token = new WC_Payment_Token_CC();
// 设置 last4、到期年份、月份和卡类型
$token->save();

delete()

从数据库中删除一个令牌。

$token = WC_Payment_Tokens::get( 42 );
$token->delete();