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

WooCommerce自定义支付网关IPN回调返回-1无法处理求助

解决WooCommerce支付网关回调未触发及URL配置问题

问题诊断

  1. 回调URL格式错误:你收到的回调URL里出现了两个?(http://localhost:8000/?wc-api=WC_Plugin_Gateway?x_account_id=...),这会导致WooCommerce无法正确识别API端点——第二个?应替换为&,否则参数无法被解析,钩子woocommerce_api_wc_plugin_gateway不会触发。
  2. 三个URL混淆使用:x_url_callback(服务器端IPN回调)、x_url_complete(用户成功跳转页)、x_url_cancel(用户取消跳转页)不应全部指向同一个notify_url,需按用途区分配置。
  3. 回调逻辑缺失验证与业务处理:当前代码仅输出日志,未验证网关签名,也未处理订单状态更新,既不安全也无法完成业务闭环。

修复步骤

1. 修正回调URL的生成与配置

确保notify_url是正确的WooCommerce API端点,同时区分三个URL的用途:

class WC_Plugin_Gateway extends \WC_Payment_Gateway{
    public function __construct(){
        // 生成服务器端IPN用的回调地址
        $this->notify_url = WC()->api_request_url('WC_Plugin_Gateway');
        // 注册回调钩子,类名转小写后拼接钩子前缀
        add_action('woocommerce_api_' . strtolower(__CLASS__), array($this, 'handle_callback'));
        
        // 配置用户跳转的成功/取消页面(用WooCommerce默认页或自定义页)
        $this->return_url = $this->get_return_url(null);
        $this->cancel_url = wc_get_page_permalink('cart');
    }

    // 构建支付请求数据时区分三个URL
    public function process_payment($order_id){
        $order = wc_get_order($order_id);
        $email = $order->get_billing_email();
        $nombre_customer = $order->get_billing_first_name();
        $apellido = $order->get_billing_last_name();
        $telefono = $order->get_billing_phone();
        $monto = $order->get_total();
        $cadenaProductos = '订单 #' . $order_id;
        $nombreSitio = get_bloginfo('name');
        $shop_country = WC()->countries->get_base_country();

        $new_data = array(
            "platform" => "woocommerce",
            "paymentMethod" => "webpay",
            "x_account_id" => $this->token_service,
            "x_amount" => round($monto),
            "x_currency" => get_woocommerce_currency(),
            "x_customer_email" => $email,
            "x_customer_first_name" => $nombre_customer,
            "x_customer_last_name" => $apellido,
            "x_customer_phone" => $telefono,
            "x_description" => $cadenaProductos,
            "x_reference" => $order_id,
            "x_shop_country" => !empty($shop_country) ? $shop_country : 'CL',
            "x_shop_name" => $nombreSitio,
            // 服务器端IPN回调,用于后台更新订单状态
            "x_url_callback" => $this->notify_url,
            // 用户取消支付后跳转回购物车
            "x_url_cancel" => $this->cancel_url,
            // 用户支付成功后跳转回订单完成页
            "x_url_complete" => $this->return_url,
            "secret" => $_ENV['SECRET']
        );

        // 此处添加生成支付链接并跳转的逻辑
        // ...

        return array(
            'result' => 'success',
            'redirect' => '生成的支付链接'
        );
    }
}

2. 完善回调处理逻辑(含签名验证)

修复URL参数解析问题,添加签名验证,实现订单状态更新:

public function handle_callback(){
    // 修复URL参数:将错误的第二个?替换为&
    $request_uri = $_SERVER['REQUEST_URI'];
    $request_uri = str_replace('?wc-api=WC_Plugin_Gateway?', '?wc-api=WC_Plugin_Gateway&', $request_uri);
    parse_str(parse_url($request_uri, PHP_URL_QUERY), $params);

    // 验证请求签名(必须实现,防止伪造回调)
    $received_signature = $params['x_signature'] ?? '';
    $expected_signature = $this->generate_signature($params);

    if($received_signature !== $expected_signature){
        error_log('Invalid callback signature');
        wp_die('Invalid signature', 'Error', array('response' => 403));
    }

    // 处理回调参数
    $order_id = $params['x_reference'] ?? '';
    $result = strtolower($params['x_result'] ?? '');
    $order = wc_get_order($order_id);

    if(!$order){
        error_log('Order not found for callback: ' . $order_id);
        wp_die('Order not found', 'Error', array('response' => 404));
    }

    // 根据支付结果更新订单状态
    switch($result){
        case 'success':
            $order->payment_complete();
            $order->add_order_note('支付成功,网关回调确认');
            break;
        case 'failed':
            $error_msg = $params['x_message'] ?? '未知原因';
            $order->update_status('failed', "支付失败:{$error_msg}");
            break;
        case 'cancelled':
            $order->update_status('cancelled', '用户取消支付');
            break;
        default:
            $order->add_order_note('收到未知支付状态:' . $result);
            break;
    }

    // 返回200状态码告知网关回调已接收
    header('HTTP/1.1 200 OK');
    wp_die();
}

// 参考网关文档实现签名生成逻辑
private function generate_signature($params){
    // 示例:按网关要求排序参数、拼接字符串后生成签名
    ksort($params);
    $signature_string = '';
    foreach($params as $key => $value){
        if($key !== 'x_signature'){
            $signature_string .= "{$key}={$value}&";
        }
    }
    $signature_string = rtrim($signature_string, '&') . $_ENV['SECRET'];
    return hash('sha256', $signature_string); // 替换为网关指定的哈希算法
}

3. 排查网关端参数拼接问题

如果修复后仍收到带有两个?的URL,说明网关在拼接回调参数时存在错误,需检查网关文档确认参数拼接规则,或联系网关技术支持修正——正确的回调URL格式应为:
http://localhost:8000/?wc-api=WC_Plugin_Gateway&x_account_id=secret&x_amount=1230.0&...

测试方法

  1. 开启WordPress调试日志(wp-config.php中设置WP_DEBUG_LOG = true),查看wp-content/debug.log是否有回调相关日志输出。
  2. 用Postman直接向notify_url发送模拟请求,验证钩子是否触发。
  3. 完整测试支付流程,检查订单状态是否正确更新。

内容的提问来源于stack exchange,提问作者Fabian Andres

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:24:55