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

基于Contact Form7与OpenAI API的WordPress博客生成插件故障排查

问题描述

我正在开发一款WordPress插件,功能是从Contact Form 7表单提取信息,发送到OpenAI API,再把生成的文本返回给用户查看。这是我第一次开发WordPress插件,按指导写完代码后,点击生成按钮没有内容显示,通过开发者工具发现API请求返回text: null,求解决。


相关代码

openai-blog-generator.php

/*
Plugin Name: AI Blog Generator
Description: Generates blog posts using OpenAI's GPT-3 model
Version: 1.0
Author: trobanko
*/

// Define constants for OpenAI API
define('OPENAI_API_KEY', 'your_openai_api_key');
define('OPENAI_API_URL', 'https://api.openai.com/v1/engines');

// Add shortcode for Contact Form 7 form
add_shortcode('ai_blog_generator_form', 'ai_blog_generator_form_shortcode');
function ai_blog_generator_form_shortcode() {
  error_log("1");
  ob_start();
  ?>
  <div class="ai-blog-generator-form">
    <?php echo do_shortcode('[contact-form-7 id="10" title="Contact form 1"]'); ?>
  </div>
  <?php
  return ob_get_clean();
}

// Add custom endpoint for generating blog post
add_action('rest_api_init', 'ai_blog_generator_register_endpoint');
function ai_blog_generator_register_endpoint() {
  error_log("2");
  register_rest_route('ai-blog-generator/v1', '/generate-blog', array(
    'methods' => 'POST',
    'callback' => 'ai_blog_generator_generate_blog',
  ));
}

// Callback function for generating blog post
function ai_blog_generator_generate_blog($request) {
  error_log("3");
  $params = $request->get_params();

  // Get input data from form fields
  $topic = sanitize_text_field($params['blog_topic']);
  $style = sanitize_text_field($params['writing_style']);
  $outline = sanitize_textarea_field($params['outline']);

  error_log("Input Data: Topic: " . $topic . ", Writing Style: " . $style . ", Outline: " . $outline);

  // Define prompt for OpenAI API
  $prompt = "Blog topic: $topic
Writing style: $style
Outline: $outline
Generate blog post:";
  error_log("Prompt: " . $prompt);

  // Set up API request
  $data = array(
    'prompt' => $prompt,
    'temperature' => 0.5,
    'max_tokens' => 500,
    'n' => 1,
  );
  $args = array(
    'headers' => array(
      'Content-Type' => 'application/json',
      'Authorization' => 'Bearer ' . OPENAI_API_KEY,
    ),
    'body' => json_encode($data),
    'timeout' => 30,
  );

  // Send request to OpenAI API
  error_log("Sending request to OpenAI API...");
  $response = wp_remote_post(OPENAI_API_URL . '/davinci-003/completions', $args);
  error_log("Received response from OpenAI API");

  // Parse response
  if (is_wp_error($response)) {
    $error_message = $response->get_error_message();
    error_log("API Error: " . $error_message);
    return new WP_Error('api_error', $error_message, array('status' => 500));
  } else {
    $body = wp_remote_retrieve_body($response);
    $json = json_decode($body, true);
    $text = $json['choices'][0]['text'];
    error_log("Generated text: " . $text);
    return array('text' => $text);
  }
}

// Add script for generating blog post
add_action('wp_enqueue_scripts', 'ai_blog_generator_enqueue_scripts');
function ai_blog_generator_enqueue_scripts() {
  error_log("4");
  wp_enqueue_script('ai-blog-generator', plugins_url('/js/ai-blog-generator.js', __FILE__), array('jquery'), '1.0', true);
  wp_localize_script('ai-blog-generator', 'aiBlogGeneratorSettings', array(
    'apiUrl' => esc_url_raw(rest_url('ai-blog-generator/v1/generate-blog')),
    'nonce' => wp_create_nonce('wp_rest'),
  ));
}

// Add CSS for Contact Form 7 form
add_action('wp_enqueue_scripts', 'ai_blog_generator_enqueue_styles');
function ai_blog_generator_enqueue_styles() {
  error_log("5");
  wp_enqueue_style('ai-blog-generator', plugins_url('/css/ai-blog-generator.css', __FILE__), array(), '1.0', 'all');
}

// Add settings link to plugin page
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'ai_blog_generator_settings_link');
function ai_blog_generator_settings_link($links) {
  $settings_link = '<a href="admin.php?page=ai-blog-generator-settings">Settings</a>';
  array_push($links, $settings_link);
  return $links;
}

// Register settings page
add_action('admin_menu', 'ai_blog_generator_settings_page');
function ai_blog_generator_settings_page() {
  add_menu_page('AI Blog Generator Settings', 'AI Blog Generator', 'manage_options', 'ai-blog-generator-settings', 'ai_blog_generator_settings');
}

// Display settings page
function ai_blog_generator_settings() {
  ?>
  <div class="wrap">
    <h1>AI Blog Generator Settings</h1>
    <form method="post" action="options.php">
      <?php
      settings_fields('ai_blog_generator_options');
      do_settings_sections('ai_blog_generator_options');
      submit_button();
      ?>
    </form>
  </div>
  <?php
}

// Register settings
add_action('admin_init', 'ai_blog_generator_register_settings');
function ai_blog_generator_register_settings() {
  register_setting('ai_blog_generator_options', 'ai_blog_generator_api_key');
  add_settings_section('ai_blog_generator_api_settings', 'OpenAI API Settings', 'ai_blog_generator_api_settings_callback', 'ai_blog_generator_options');
  add_settings_field('ai_blog_generator_api_key', 'API Key', 'ai_blog_generator_api_key_callback', 'ai_blog_generator_options', 'ai_blog_generator_api_settings');
}

// Display API settings section
function ai_blog_generator_api_settings_callback() {
  echo '<p>Enter your OpenAI API key below:</p>';
}

// Display API key field
function ai_blog_generator_api_key_callback() {
  $api_key = get_option('ai_blog_generator_api_key');
  echo '<input type="text" name="ai_blog_generator_api_key" value="' . esc_attr($api_key) . '" />';
}

// Add API key to API requests
add_filter('http_request_args', 'ai_blog_generator_add_api_key', 10, 2);
function ai_blog_generator_add_api_key($args, $url) {
  if (strpos($url, 'api.openai.com') !== false) {
    $api_key = get_option('ai_blog_generator_api_key');
    if ($api_key) {
      $args['headers']['Authorization'] = 'Bearer ' . $api_key;
    }
  }
  return $args;
}

ai-blog-generator.js

jQuery(document).ready(function($) {
  $('#generate-blog').on('submit', function(event) {
    event.preventDefault();
    console.log('Form submitted');

    // Get form data
    var formData = $(this).serialize();
    console.log('Form data:', formData);

    // Send AJAX request
    $.ajax({
      url: ai_blog_generator_params.endpoint,
      type: 'POST',
      data: formData,
      beforeSend: function(xhr) {
        xhr.setRequestHeader('X-WP-Nonce', ai_blog_generator_params.nonce);
      },
      success: function(response) {
        console.log('API response:', response);
        var text = response.text;
        if (text) {
          console.log('Generated text:', text);
          $('#blog-post').html(text);
        } else {
          console.log('Error: Empty response');
          $('#blog-post').html('Error: Empty response');
        }
      },
      error: function(jqXHR, textStatus, errorThrown) {
        console.log('AJAX error:', jqXHR.responseText);
        $('#blog-post').html('Error: ' + jqXHR.responseText);
      }
    });
  });
});

ai-blog-generator-rest-api.php

/**
 * Register REST API endpoint for generating blog posts.
 */

// Exit if accessed directly.
if (! defined('ABSPATH')) {
    exit;
}

class AI_Blog_Generator_REST_API {
    /**
     * Initialize REST API endpoint for generating blog posts.
     */
    public function __construct() {
        add_action('rest_api_init', array($this, 'register_routes'));
    }

    /**
     * Register REST API endpoint for generating blog posts.
     */
    public function register_routes() {
        register_rest_route(
            'ai-blog-generator/v1',
            '/generate-blog',
            array(
                'methods' => 'POST',
                'callback' => array($this, 'generate_blog'),
                'permission_callback' => array($this, 'permission_callback')
            )
        );
    }

    /**
     * Check if user has permissions to access the endpoint.
     */
    public function permission_callback() {
        // Add log message
        error_log('Permission check for AI Blog Generator REST API.');

        return current_user_can('manage_options');
    }

    /**
     * Generate blog post using OpenAI's GPT-3 model.
     */
    public function generate_blog($request) {
        // Add log message
        error_log('Generate blog endpoint called for AI Blog Generator REST API.');

        $params = $request->get_params();

        // Get input data from form fields.
        $topic = sanitize_text_field($params['blog_topic']);
        $style = sanitize_text_field($params['writing_style']);
        $outline = sanitize_textarea_field($params['outline']);

        // Define prompt for OpenAI API.
        $prompt = "Blog topic: $topic
Writing style: $style
Outline: $outline
Generate blog post:";

        // Set up API request.
        $data = array(
            'prompt' => $prompt,
            'temperature' => 0.5,
            'max_tokens' => 500,
            'n' => 1,
        );
        $args = array(
            'headers' => array(
                'Content-Type' => 'application/json',
                'Authorization' => 'Bearer ' . OPENAI_API_KEY,
            ),
            'body' => json_encode($data),
            'timeout' => 30,
        );

        // Send request to OpenAI API.
        $response = wp_remote_post(OPENAI_API_URL . '/davinci-003/completions', $args);

        // Parse response.
        if (is_wp_error($response)) {
            $error_message = $response->get_error_message();

            // Add log message
            error_log('Error occurred in AI Blog Generator REST API: ' . $error_message);

            return new WP_Error('api_error', $error_message, array('status' => 500));
        } else {
            $body = wp_remote_retrieve_body($response);
            $json = json_decode($body, true);
            $text = $json['choices'][0]['text'];

            // Add log message
            error_log('AI Blog Generator REST API: Generated text: ' . $text);

            return array('text' => $text);
        }
    }
}

new AI_Blog_Generator_REST_API();

问题排查与修复

1. 重复注册REST端点导致冲突

代码同时在openai-blog-generator.php和ai-blog-generator-rest-api.php中注册了同一个ai-blog-generator/v1/generate-blog端点,回调执行逻辑混乱。
修复: 删除openai-blog-generator.php中从add_action('rest_api_init', ...)到ai_blog_generator_generate_blog函数的全部代码。

2. JavaScript变量名不匹配

PHP中通过wp_localize_script注册的变量是aiBlogGeneratorSettings,但JS中使用ai_blog_generator_params调用,导致无法获取正确的API地址和Nonce。
修复: 修改ai-blog-generator.js中的变量名:

// 替换原AJAX配置中的url和nonce参数
url: aiBlogGeneratorSettings.apiUrl,
beforeSend: function(xhr) {
  xhr.setRequestHeader('X-WP-Nonce', aiBlogGeneratorSettings.nonce);
},

3. OpenAI API密钥未正确读取

类中的API请求直接使用常量OPENAI_API_KEY,但设置页面的密钥存储在ai_blog_generator_api_key选项中,导致设置无效。
修复: 修改ai-blog-generator-rest-api.php中的API请求头部:

// 替换原请求参数中的Authorization部分
$api_key = get_option('ai_blog_generator_api_key');
$args = array(
    'headers' => array(
        'Content-Type' => 'application/json',
        'Authorization' => 'Bearer ' . $api_key,
    ),
    'body' => json_encode($data),
    'timeout' => 30,
);

同时删除openai-blog-generator.php中的define('OPENAI_API_KEY', 'your_openai_api_key');代码。

4. 未处理OpenAI API错误响应

当前代码直接读取$json['choices'][0]['text'],如果API返回错误(如密钥无效、额度不足),会导致$text为null。
修复: 在ai-blog-generator-rest-api.php的响应解析部分添加错误判断:

} else {
    $body = wp_remote_retrieve_body($response);
    $json = json_decode($body, true);
    
    // 检查API错误
    if (isset($json['error'])) {
        error_log('OpenAI API Error: ' . $json['error']['message']);
        return new WP_Error('openai_error', $json['error']['message'], array('status' => 400));
    }
    
    // 检查响应结构
    if (!isset($json['choices'][0]['text'])) {
        error_log('OpenAI API returned invalid response: ' . $body);
        return new WP_Error('invalid_response', 'Invalid response from OpenAI API', array('status' => 500));
    }
    
    $text = $json['choices'][0]['text'];
    error_log('AI Blog Generator REST API: Generated text: ' . $text);
    return array('text' => $text);
}

5. 权限限制过严(可选)

当前权限回调要求用户具备manage_options权限,普通用户无法使用。如需开放给更多用户,可修改:

public function permission_callback() {
    // 允许所有登录用户访问
    return is_user_logged_in();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:17:05