与结账模块集成保护功能
如果您是 CAPTCHA 或欺诈防护插件的开发者,请确保您的解决方案与 Store API 接口对接,并与结账模块进行集成。本教程将指导您完成向 WooCommerce 结账模块添加保护机制的流程。
概述
WooCommerce 结账模块使用 Store API 来处理订单,它提供一个安全、未认证的 API,用于面向客户的功能。为了集成保护机制,例如 CAPTCHA 或欺诈检测,您需要:
- 渲染您的保护元素,使用 WordPress 块过滤器将其插入到结账模块中。
- 处理客户端验证,使用结账数据存储。
- 在服务器端进行验证,使用 Store API 的认证钩子。
第一步:渲染您的保护元素
第一步是渲染您的 CAPTCHA 或保护元素到结账模块中。您可以使用 render_block 过滤器,在特定的结账模块之前或之后注入您的 HTML。
使用 render_block 过滤器
render_block 过滤器允许您修改任何 WordPress 块的输出。对于结账模块,您需要针对 woocommerce/checkout-actions-block,该模块包含“提交订单”按钮。
add_filter(
'render_block_woocommerce/checkout-actions-block',
function( $block_content ) {
ob_start();
?>
<div class="my-captcha-element" data-sitekey="<?php echo esc_attr( get_option( 'plugin_captcha_sitekey' ) ); ?>">
</div>
<?php
echo $block_content;
$block_content = ob_get_contents();
ob_end_clean();
return $block_content;
},
999,
1
);
此代码的关键点:
- 该过滤器针对
woocommerce/checkout-actions-block,即包含提交订单按钮的块。 - 我们使用优先级
999,以确保我们的内容在其他修改之后添加。 data-sitekey属性存储您的 CAPTCHA 配置,但对于您的插件,这可能会有所不同。- 我们将在原始块内容之后附加我们的保护元素。
第二步:客户端集成
一旦您的保护元素被渲染,您需要将其与结账数据存储集成,以捕获验证令牌,并将其传递到服务器。
使用结账数据存储
结账模块使用数据存储来管理状态。 您可以使用 setExtensionData 方法将您的保护令牌传递给服务器。
/* Woo 结账模块 */
document.addEventListener( 'DOMContentLoaded', function () {
if ( wp && wp.data ) {
var unsubscribe = wp.data.subscribe( function () {
const turnstileItem = document.querySelector(
'.my-captcha-element'
);
if ( turnstile && turnstileItem ) {
turnstile.render( turnstileItem, {
sitekey: turnstileItem.dataset.sitekey,
callback: function ( data ) {
wp.data
.dispatch( 'wc/store/checkout' )
.setExtensionData( 'plugin-namespace-turnstile', {
token: data,
} );
},
} );
unsubscribe();
}
}, 'wc/store/cart' );
}
} );
关于此 JavaScript 的关键点:
- 我们订阅购物车数据存储,以便检测结账是否已准备就绪。
turnstile.render()方法初始化您的验证码(替换为您的特定实现)。setExtensionData()将令牌存储在结账数据存储中。- 命名空间应是您插件的唯一标识(例如,
my-plugin-turnstile)。
数据存储集成
有关结账数据存储和可用方法的更多信息,请参阅 结账数据存储文档。
第 3 步:服务器端验证
最关键的步骤是在服务器端验证保护令牌。 这应该在身份验证过程的早期发生,以防止任何未经授权的结账尝试。
使用核心 rest_authentication_errors 过滤器
[rest_authentication_errors](https://developer.wordpress.org/reference/hooks/rest_authentication_errors/) 过滤器是验证您的保护令牌的理想位置,因为它在任何结账处理开始之前运行。
add_filter( 'rest_authentication_errors', 'plugin_check_turnstile_token' );
function plugin_check_turnstile_token( $result ) {
// 如果不是 POST 请求,则跳过。
if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] !== 'POST' ) {
// 始终返回结果或错误,切勿返回布尔值。 这可确保其他检查(例如速率限制或身份验证)不会被忽略。
return $result;
}
// 如果不是结账端点,则跳过。
if ( ! preg_match( '#/wc/store(?:/v\d+)?/checkout#', $GLOBALS['wp']->query_vars['rest_route'] ) ) {
return $result;
}
// 获取请求体
$request_body = json_decode( \WP_REST_Server::get_raw_data(), true );
if ( isset( $request_body['payment_method'] ) ) {
$chosen_payment_method = sanitize_text_field( $request_body['payment_method'] );
// 提供一种机制,允许跳过检查,以便允许快速付款或托管结账绕过检查。
$selected_payment_methods = apply_filters( 'plugin_payment_methods_to_skip', array('woocommerce_payments' ) );
if( is_array( $selected_payment_methods ) ) {
if ( in_array( $chosen_payment_method, $selected_payment_methods, true ) ) {
return $result;
}
}
}
$extensions = $request_body['extensions'];
if ( empty( $extensions ) || ! isset( $extensions['plugin-namespace-turnstile'] ) ) {
return new WP_Error( 'challenge_failed', '验证码挑战失败' );
}
$token = sanitize_text_field( $extensions['plugin-namespace-turnstile']['token'] );
/**
* 注意:函数 `my_token_check_function` 将在您的插件中实现,以处理令牌验证。
**/
$check = my_token_check_function( $token );
$success = $check['success'];
if( $success !== true ) {
return new WP_Error( 'challenge_failed', '验证码挑战失败' );
}
return $result;
}
关于服务器端验证的关键点:
- 我们专门检查发送到结账端点的 POST 请求。
- 保护令牌通过
$request_body['extensions']['your-namespace']访问。 - 始终返回
$result参数,以避免干扰其他身份验证检查。 - 如果验证失败,则返回一个
WP_Error对象。 - 考虑允许某些付款方式绕过保护(例如,快速付款)。
重要提示
安全注意事项
- 始终在服务器端进行验证 - 客户端验证可以被绕过。
- 使用 HTTPS - 保护令牌应通过安全的方式传输。
- 速率限制 - 考虑为您的保护端点实施 速率限制。
- 令牌过期 - 确保您的保护令牌具有适当的过期时间。
测试您的集成
在测试您的保护集成时:
- 启用结账阻止进行测试。
- 验证当未提供令牌时,验证失败。
- 使用不同的付款方式进行测试。
- 确保保护功能不会干扰合法的结账流程。