You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WooCommerce自定义支付网关集成:二次API调用失败致订单待处理

WooCommerce自定义CIB支付网关二次API调用失效问题解决

问题概述

为WooCommerce集成自定义CIB支付网关,API流程分为两个阶段:

  • 客户提交订单后触发首次API调用,跳转至支付网关填写银行卡信息;
  • 客户完成支付验证后重定向回网站,需触发二次API调用确认支付状态。

目前第一阶段流程正常,但第二阶段API调用未生效,订单始终停留在待处理状态,尝试template_redirect钩子未达到预期效果。

代码问题分析

原代码存在几个核心问题导致二次调用失效:

  1. 钩子触发时机错误:woocommerce_payment_complete钩子仅在订单状态变为「已支付」时触发,此时订单仍为「待处理」,钩子根本不会执行;
  2. 返回URL参数拼接错误:直接拼接order_id到URL,未使用add_query_arg规范处理,导致参数传递异常;
  3. 未获取订单对象:confirm_payment函数中直接调用$order->update_status,但未通过wc_get_order($order_id)获取有效订单实例;
  4. API URL缺失完整域名:两次API调用均使用相对路径,wp_remote_get无法发起有效请求;
  5. 调试输出破坏页面: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 20:14:51