按国家/地区划分的多个Stripe账户
我有一个 WordPress(WooCommerce) 网站,已集成 Stripe 并连接到一个Stripe账户。
我想基于客户的账单国家使用两个Stripe账户。举例来说,如果客户在账单地址中选择美国,支付应通过默认Stripe账户进行处理。如果账单国家不是美国,支付应通过第二个Stripe账户进行处理。
我目前正在尝试实现自定义功能以实现这一行为。
// 1. Create function to find Product ID
function bbloomer_product_id_in_cart( $id ) {
if ( ! WC()->cart ) return false;
$product_cart_id = WC()->cart->generate_cart_id( $id );
$in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
if ( $in_cart ) return true;
return false;
}
// -------------------
// 2. Change Stripe keys on the go
add_filter( 'wc_stripe_upe_params', 'bbloomer_conditional_publishable_key_upe', 9999 );
function bbloomer_conditional_publishable_key_upe( $params ) {
// PRODUCT ID HERE
if ( WC()->customer && WC()->customer->get_billing_country() == 'US' ) return $params;
// STRIPE Live Publishable Key HERE
$params[ 'key' ] = 'pk_live_................';
return $params;
}
add_filter( 'wc_stripe_params', 'bbloomer_conditional_publishable_key', 9999 );
function bbloomer_conditional_publishable_key( $params ) {
// PRODUCT ID HERE
if ( WC()->customer && WC()->customer->get_billing_country() == 'US' ) return $params;
// STRIPE Live Publishable Key HERE
$params[ 'key' ] = 'pk_live_................';
return $params;
}
add_filter( 'wc_stripe_payment_request_params', 'bbloomer_conditional_publishable_key_request', 9999 );
function bbloomer_conditional_publishable_key_request( $params ) {
// PRODUCT ID HERE
if ( WC()->customer && WC()->customer->get_billing_country() == 'US' ) return $params;
// STRIPE Live Publishable Key HERE
$params[ 'stripe' ][ 'key' ] = 'pk_live_................';
return $params;
}
add_filter( 'woocommerce_stripe_request_headers', 'bbloomer_conditional_private_key_headers', 9999 );
function bbloomer_conditional_private_key_headers( $params ) {
// PRODUCT ID HERE
if ( WC()->customer && WC()->customer->get_billing_country() == 'US' ) return $params;
// STRIPE Live Secret Key HERE
$params[ 'Authorization' ] = 'Basic ' . base64_encode( 'sk_live_..........' . ':' );
return $params;
}
在结账过程中更改账单国家时会出现问题。
如果账单国家已设为US,支付将进入默认Stripe账户。如果结账加载时已选择了其他国家,则会正确使用第二个Stripe账户。
然而,当用户在结账页将国家从US改为其他国家时,Stripe密钥切换成功(如我在控制台中所看到),但支付会失败,错误信息为:
处理支付时出错:无法处理此笔支付,请重试或使用其他方法。
解决方案
Why your code is failing
核心问题在于后端PHP过滤器与前端 Stripe.js 初始化之间的不同步。
当WooCommerce结账页面首次加载时,为了创建一个安全会话,会发生两件事:
- Backend: 你的服务器使用默认账户的 Secret Key 来准备
PaymentIntent。 - Frontend: WooCommerce将默认的 Publishable Key 传递给浏览器。
Stripe.js脚本使用此密钥将安全的信用卡输入字段(Stripe Elements)挂载到屏幕上。
当用户更改账单国家时,WooCommerce会触发一个AJAX update_checkout 请求。你的自定义PHP函数成功拦截并在后端切换密钥。然而,前端的Stripe Element已经绑定了原始的Publishable Key。你不能在已挂载的Stripe Element上热切换Publishable Key。
因为前端正在以账户A 的身份提交支付,但后端现在使用账户B 的Secret Key进行校验,Stripe会检测到身份验证不匹配并拒绝支付。
如何修复
你有两种选项,取决于你想如何架构你的结账流程。
Option 1: Force a frontend reload (The Workaround)
如果你想保留当前的PHP逻辑,必须在国家改变时强制前端从头重新构建Stripe Elements。你可以通过监听WooCommerce的 updated_checkout 事件,并在国家切换时触发一次硬刷新来实现。
Note: 虽然这解决了结账错误,但通过过滤器动态切换密钥通常不建议,因为它可能破坏自动化的webhooks和未来的退款(WooCommerce不会知道向哪个账户发送退款请求)。
Option 2: Use Multiple Gateways
处理多个区域Stripe账户的最稳妥方法是完全避免过滤核心API密钥。相反,使用WooCommerce内置的网关筛选器,根据用户所在的国家切换可用的支付方式。