WooCommerce自定义支付网关集成:二次API调用失败致订单待处理
WooCommerce自定义CIB支付网关二次API调用失效问题解决
问题概述
为WooCommerce集成自定义CIB支付网关,API流程分为两个阶段:
- 客户提交订单后触发首次API调用,跳转至支付网关填写银行卡信息;
- 客户完成支付验证后重定向回网站,需触发二次API调用确认支付状态。
目前第一阶段流程正常,但第二阶段API调用未生效,订单始终停留在待处理状态,尝试template_redirect钩子未达到预期效果。
代码问题分析
原代码存在几个核心问题导致二次调用失效:
- 钩子触发时机错误:
woocommerce_payment_complete钩子仅在订单状态变为「已支付」时触发,此时订单仍为「待处理」,钩子根本不会执行; - 返回URL参数拼接错误:直接拼接
order_id到URL,未使用add_query_arg规范处理,导致参数传递异常; - 未获取订单对象:
confirm_payment函数中直接调用$order->update_status,但未通过wc_get_order($order_id)获取有效订单实例; - API URL缺失完整域名:两次API调用均使用相对路径,
wp_remote_get无法发起有效请求; - 调试输出破坏页面:
echo $api_url2和echo $api_response2会干扰订单接收页的正常渲染。
修复方案
1. 更换触发钩子
使用template_redirect钩子监听支付网关的返回请求,确保客户重定向回网站时立即执行二次验证逻辑。
2. 规范返回URL参数
用add_query_arg正确拼接订单ID、自定义订单号等参数,保证参数能正常传递。
3. 完善订单对象处理
在确认支付函数中先通过wc_get_order()获取订单实例,再执行状态更新操作。
4. 补充API完整域名
给API URL添加支付网关的完整域名(如https://payment.cib.com),确保请求能正确发送。
5. 替换调试输出为日志
使用error_log()记录调试信息,避免破坏前端页面结构,方便后续排查问题。
修复后完整代码
<?php add_action('plugins_loaded', 'init_cib_payment_gateway'); function init_cib_payment_gateway() { class WC_CIB_Payment_Gateway extends WC_Payment_Gateway { public function __construct() { $this->id = 'cib_payment_gateway'; $this->method_title = 'CIB Payment Gateway'; $this->title = 'CIB Payment Gateway'; $this->has_fields = false; // 无需额外字段,复用WooCommerce默认结账表单 $this->init_form_fields(); $this->init_settings(); add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options')); } public function init_form_fields() { // 后台配置字段,避免硬编码敏感信息 $this->form_fields = array( 'api_username' => array( 'title' => __('API用户名', 'cib-pay-woo'), 'type' => 'text', 'description' => __('CIB支付网关API用户名', 'cib-pay-woo'), 'default' => '', 'desc_tip' => true, ), 'api_password' => array( 'title' => __('API密码', 'cib-pay-woo'), 'type' => 'password', 'description' => __('CIB支付网关API密码', 'cib-pay-woo'), 'default' => '', 'desc_tip' => true, ), 'api_domain' => array( 'title' => __('API域名', 'cib-pay-woo'), 'type' => 'text', 'description' => __('CIB支付网关完整域名,如https://payment.cib.com', 'cib-pay-woo'), 'default' => '', 'desc_tip' => true, ), ); } public function process_payment($order_id) { $order = wc_get_order($order_id); // 从后台配置读取API参数 $username = $this->get_option('api_username'); $password = $this->get_option('api_password'); $api_domain = $this->get_option('api_domain'); $amount = $order->get_total() * 100; $currency = '012'; // 对应货币代码 $random_string = substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'), 0, 5); $order_number = $order_id . $random_string; // 规范拼接返回URL,包含验证所需参数 $return_url = add_query_arg( array( 'confirmPayment' => 'true', 'orderId' => $order_id, 'orderNumber' => $order_number ), wc_get_checkout_url() . 'order-received/' ); $jsonParams = json_encode(array( "force_terminal_id" => "E010900759", "udf1" => "2018105301346", "udf5" => "ggsf85s42524s5uhgsf" )); // 拼接完整的首次API请求URL $api_url = add_query_arg( array( 'timeout' => 50, 'userName' => $username, 'password' => $password, 'orderNumber' => $order_number, 'amount' => $amount, 'currency' => $currency, 'returnUrl' => $return_url, 'language' => 'EN', 'jsonParams' => $jsonParams, ), $api_domain . '/payment/rest/register.do' ); // 发起首次API请求 $api_response = wp_remote_get($api_url, array('sslverify' => false)); // 根据实际情况开启SSL验证 if (is_wp_error($api_response)) { wc_add_notice(__('支付初始化失败:' . $api_response->get_error_message(), 'cib-pay-woo'), 'error'); return; } $body_response = wp_remote_retrieve_body($api_response); $response = json_decode($body_response, true); if (!isset($response['formUrl'])) { wc_add_notice(__('支付网关返回无效响应', 'cib-pay-woo'), 'error'); return; } // 保存订单元数据,用于二次验证 update_post_meta($order_id, 'cib_order_number', $order_number); update_post_meta($order_id, 'cib_payment_need_confirm', true); // 标记订单为待支付状态 $order->update_status('pending', __('等待CIB支付网关确认', 'cib-pay-woo')); // 跳转至支付网关页面 return array( 'result' => 'success', 'redirect' => $response['formUrl'], ); } public function payment_fields() { // 无需额外显示字段 } } function add_cib_payment_gateway($methods) { $methods[] = 'WC_CIB_Payment_Gateway'; return $methods; } add_filter('woocommerce_payment_gateways', 'add_cib_payment_gateway'); } // 监听订单接收页的返回请求,执行二次支付验证 add_action('template_redirect', 'cib_confirm_payment'); function cib_confirm_payment() { // 仅在订单接收页且存在验证参数时执行 if (!is_wc_endpoint_url('order-received') || !isset($_GET['confirmPayment']) || $_GET['confirmPayment'] !== 'true') { return; } $order_id = isset($_GET['orderId']) ? absint($_GET['orderId']) : 0; $order = wc_get_order($order_id); // 验证订单有效性及是否需要确认 if (!$order || !get_post_meta($order_id, 'cib_payment_need_confirm', true)) { return; } // 获取API配置参数 $gateway = WC()->payment_gateways()->get_gateway('cib_payment_gateway'); $username = $gateway->get_option('api_username'); $password = $gateway->get_option('api_password'); $api_domain = $gateway->get_option('api_domain'); $order_number = get_post_meta($order_id, 'cib_order_number', true); // 拼接二次验证API URL $api_url2 = add_query_arg( array( 'language' => 'EN', 'orderNumber' => $order_number, 'password' => $password, 'userName' => $username, ), $api_domain . '/payment/rest/confirmOrder.do' ); // 发起二次API请求 $api_response2 = wp_remote_get($api_url2, array('sslverify' => false)); if (is_wp_error($api_response2)) { $error_msg = 'CIB支付确认失败:' . $api_response2->get_error_message(); error_log($error_msg); $order->update_status('failed', __($error_msg, 'cib-pay-woo')); delete_post_meta($order_id, 'cib_payment_need_confirm'); return; } $body_response2 = wp_remote_retrieve_body($api_response2); $response2 = json_decode($body_response2, true); // 记录API返回日志,便于排查问题 error_log('CIB支付确认响应:' . print_r($response2, true)); // 根据API返回结果更新订单状态 if (isset($response2['ErrorCode']) && $response2['ErrorCode'] == 0) { $order->update_status('completed', __('CIB支付已确认', 'cib-pay-woo')); $order->payment_complete(); // 触发WooCommerce支付完成逻辑(减库存、发送通知等) } else { $error_msg = isset($response2['ErrorMessage']) ? $response2['ErrorMessage'] : '未知错误'; $order->update_status('failed', __('CIB支付确认失败:' . $error_msg, 'cib-pay-woo')); } // 清理验证标记元数据 delete_post_meta($order_id, 'cib_payment_need_confirm'); } ?>
关键优化点
- 钩子合理性:
template_redirect能精准监听前端页面跳转,确保二次验证逻辑在客户返回时立即执行; - 参数安全性:将API敏感信息移至后台配置,避免硬编码泄露风险;
- 流程规范性:严格遵循WooCommerce订单状态流转逻辑,首次调用后标记为「待支付」,验证完成后更新为「已完成」或「失败」;
- 调试便利性:用日志记录替代页面输出,不影响用户体验同时便于问题排查。
内容的提问来源于stack exchange,提问作者Mina
相关产品推荐
相关产品推荐

