WooCommerce 结账后未跳转到 payment gateway
结论
从日志看,问题出在 payment gateway 插件的兼容性或支付流程实现,而不是 WordPress 核心。
调用栈显示,提示来自:
WC_DirectPayV3_Gateway->process_payment
网关代码直接读取了订单对象的 order_key 属性。WooCommerce 3.0 之后不再推荐直接访问订单属性,应使用订单对象提供的 getter:
$order->get_order_key()
不过,这条日志的 PHP 级别是 NOTICE,通常不会单独造成结账中断或跳转失败。更需要检查的是网关插件的 process_payment(),包括它是否正确生成了支付地址,以及是否向 WooCommerce 返回了正确的跳转结果。
排查和修复应先由 payment gateway 插件开发者或集成方处理。
日志具体说明了什么
关键内容是:
order_key was called incorrectly. Order properties should not be accessed directly.
这通常表示插件中使用了类似写法:
$order_key = $order->order_key;
WooCommerce 已通过 CRUD API 封装订单数据,正确写法是:
$order_key = $order->get_order_key();
调用栈还表明,这段代码是在结账付款阶段执行的:
WC_Checkout->process_order_payment
WC_DirectPayV3_Gateway->process_payment
WC_Abstract_Legacy_Order->__get
整个过程可以还原为:
- WordPress 正常接收结账请求。
- WooCommerce 进入订单付款处理。
- WooCommerce 调用
WC_DirectPayV3_Gateway的process_payment()。 - 网关插件读取订单数据时使用了旧接口。
日志中的请求:
POST /?wc-ajax=checkout HTTP/1.1
返回 HTTP 200,说明请求没有因 PHP 致命错误而直接失败。Nginx 把 PHP 输出到 stderr 并记为 error,也不代表请求遇到了致命异常。这里真正的 PHP 日志级别仍是 NOTICE。
为什么会直接进入 Thank You 页面
对于需要跳转到第三方网站的托管式支付网关,process_payment() 通常应返回:
return [
'result' => 'success',
'redirect' => $gateway_url,
];
WooCommerce 收到这个结果后,前端结账脚本才会跳转到 $gateway_url。
如果插件错误地返回订单完成页,例如:
return [
'result' => 'success',
'redirect' => $this->get_return_url($order),
];
用户就会直接看到 Thank You 页面,而不会进入支付网关。
其他可能的情况包括:
- 插件未能取得网关支付 URL,随后回退到订单完成页。
process_payment()过早调用了$order->payment_complete()。- 插件将订单标记为
processing或completed后,直接返回订单页面。 - 网关 API 请求失败,但插件没有把失败结果返回给 WooCommerce。
- 插件版本与当前 WooCommerce 或 PHP 版本不兼容。
- 网关配置、商户凭据、测试或生产环境地址、回调地址发生了变化。
- 结账 AJAX 响应被其他插件、主题代码或缓存机制修改。
仅凭这条 NOTICE,还不能认定它是跳转失败的唯一原因。不过,它已经证明网关插件仍在调用旧式 WooCommerce API,需要更新。
网关插件应如何修复
先把所有直接访问订单属性的代码改为对应的 getter。常见示例如下:
// 旧写法
$order_key = $order->order_key;
$order_id = $order->id;
$total = $order->order_total;
$email = $order->billing_email;
// 推荐写法
$order_key = $order->get_order_key();
$order_id = $order->get_id();
$total = $order->get_total();
$email = $order->get_billing_email();
接着检查 process_payment() 是否正确处理网关响应。简化示例:
public function process_payment($order_id)
{
$order = wc_get_order($order_id);
if (!$order) {
wc_add_notice(__('Unable to create the payment.', 'your-text-domain'), 'error');
return [
'result' => 'failure',
];
}
$gateway_url = $this->create_gateway_payment($order);
if (is_wp_error($gateway_url) || empty($gateway_url)) {
$message = is_wp_error($gateway_url)
? $gateway_url->get_error_message()
: __('The payment gateway did not return a redirect URL.', 'your-text-domain');
wc_add_notice($message, 'error');
return [
'result' => 'failure',
];
}
$order->update_status(
'pending',
__('Waiting for payment at the external gateway.', 'your-text-domain')
);
return [
'result' => 'success',
'redirect' => esc_url_raw($gateway_url),
];
}
只有在网关确认付款成功后,插件才应在回调或返回处理逻辑中执行:
$order->payment_complete($transaction_id);
用户刚点击“下单”但尚未完成支付时,不应调用该方法。
建议的排查步骤
1. 查看结账 AJAX 的实际响应
在浏览器开发者工具的 Network 面板中找到:
?wc-ajax=checkout
检查响应 JSON,重点查看:
{
"result": "success",
"redirect": "..."
}
如果 redirect 已经指向 WooCommerce 的 order-received 地址,基本可以确定问题出在网关插件的 process_payment() 返回逻辑。
如果响应中包含第三方支付地址,但浏览器没有跳转,再检查前端 JavaScript 错误、结账模板覆盖和优化插件。
2. 记录网关 API 的响应
在不记录银行卡号、CVV、密钥等敏感信息的前提下,应记录:
- 请求是否真正发送到了支付网关。
- 网关返回的 HTTP 状态码。
- 响应中是否包含支付会话 ID。
- 响应中是否包含跳转 URL。
- 插件最终返回给 WooCommerce 的
result和redirect。
可以使用 WooCommerce 日志接口:
$logger = wc_get_logger();
$logger->debug(
'Gateway payment session created.',
[
'source' => 'directpay-v3',
'order_id' => $order->get_id(),
]
);
不要把 API secret、完整支付令牌或银行卡数据写入日志。
3. 检查版本兼容性
确认近期是否更新过以下组件:
- WooCommerce
- WordPress
- PHP
- payment gateway 插件
- 结账相关插件或当前主题
如果网关插件长期无人维护,应联系插件提供方,索取兼容当前 WooCommerce 版本的更新。直接修改第三方插件只适合临时验证,因为插件升级后,这些改动会被覆盖。
4. 在测试环境排除冲突
先备份网站,然后在 staging 环境中进行以下测试:
- 切换到 WooCommerce 官方默认主题。
- 暂停缓存、压缩和结账优化插件。
- 暂停 WooCommerce 与该支付网关之外的其他插件。
- 使用网关 sandbox 或测试商户账号重新下单。
如果问题仍然存在,可以把排查范围集中到网关插件及其远程 API。如果问题消失,再逐个恢复插件和主题,定位具体冲突。
应由哪一方处理
可以按以下方式划分责任:
- 网关插件开发者或集成方:修复对
$order->order_key的直接访问,并检查process_payment()返回值、支付 URL 生成逻辑和网关 API 错误处理。 - 支付服务商:确认商户状态、API 凭据、接口地址、支付会话创建结果和服务端限制。
- 网站维护方:提供版本信息、WooCommerce 状态报告、结账 AJAX 响应和脱敏后的网关日志,并完成冲突测试。
- WooCommerce 或 WordPress 核心:现有日志没有显示问题来自核心代码。
最有效的处理方式,是把完整调用栈、结账 AJAX 响应、WooCommerce 状态报告和脱敏后的网关请求结果交给 payment gateway 插件开发者。当前日志已经明确表明,该插件至少有一处 WooCommerce 兼容性代码需要修复。
备注:内容仅供参考。
