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_CC 或 WC_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_Token 的 validate() 方法。
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_Order 的 get_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_ 函数),并将它们实际保存到数据库中。 返回 true 或 false,具体取决于是否成功。
$token = WC_Payment_Tokens::get( 42 ); // 信用卡令牌
$token->set_expiry_year( '2020' );
$token->set_expiry_month( '06 ');
$token->update();
create()
这将创建一个新的令牌到数据库中。 因此,一旦您构建了它,create() 将在数据库中创建一个新的令牌,其中包含详细信息。 返回 true 或 false,具体取决于是否成功。
$token = new WC_Payment_Token_CC();
// 设置 last4、到期年份、月份和卡类型
$token->create(); // 保存到数据库
save()
save() 可以替代 update() 和 create()。 如果您正在处理现有的令牌,则 save() 将调用 update()。 新的令牌将调用 create()。 返回 true 或 false,具体取决于是否成功。
// 调用 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();