首页 / 应用软件 / WordPress REST API 开发教程,集成第三方数据服务

WordPress REST API 开发教程,集成第三方数据服务

WordPress REST API 开发教程:集成第三方数据服务实现实用小工具 引言:WordPress REST API 的强大潜力 WordPress REST API 是现代WordPress开发的核心组件之一,它提供了一种标准化的方式与WordPress进行数据交互。通过REST API,开发者可以创建、读取、更新…

WordPress REST API 开发教程:集成第三方数据服务实现实用小工具

引言:WordPress REST API 的强大潜力

WordPress REST API 是现代WordPress开发的核心组件之一,它提供了一种标准化的方式与WordPress进行数据交互。通过REST API,开发者可以创建、读取、更新和删除WordPress内容,更重要的是,它允许我们将WordPress转变为一个功能强大的应用程序平台。

本教程将深入探讨如何利用WordPress REST API集成第三方数据服务,通过代码二次开发实现各种实用的互联网小工具。我们将从基础概念开始,逐步构建完整的解决方案,每个代码示例都包含详细注释,确保您能够完全理解并应用这些技术。

第一部分:WordPress REST API 基础与环境配置

1.1 REST API 基础概念

WordPress REST API 遵循RESTful架构原则,使用HTTP方法(GET、POST、PUT、DELETE)来操作资源。每个WordPress内容类型(如文章、页面、用户等)都有对应的API端点。

<?php
/**
 * WordPress REST API 基础示例
 * 演示如何注册自定义API端点
 */

// 确保在WordPress环境中运行
if (!defined('ABSPATH')) {
    exit;
}

/**
 * 初始化REST API相关功能
 */
function my_custom_api_init() {
    // 注册自定义命名空间
    register_rest_route('myplugin/v1', '/test', array(
        'methods' => 'GET',
        'callback' => 'my_custom_api_test',
        'permission_callback' => '__return_true' // 允许公开访问
    ));
}
add_action('rest_api_init', 'my_custom_api_init');

/**
 * 自定义API端点回调函数
 * 
 * @param WP_REST_Request $request 请求对象
 * @return WP_REST_Response 响应对象
 */
function my_custom_api_test($request) {
    // 准备响应数据
    $data = array(
        'status' => 'success',
        'message' => 'Hello from WordPress REST API!',
        'timestamp' => current_time('timestamp'),
        'site_name' => get_bloginfo('name')
    );
    
    // 创建并返回响应
    return new WP_REST_Response($data, 200);
}

/**
 * 添加自定义API字段到文章端点
 */
function my_custom_api_register_fields() {
    register_rest_field('post', 'custom_field', array(
        'get_callback' => 'my_custom_api_get_field',
        'update_callback' => null,
        'schema' => array(
            'description' => '自定义字段示例',
            'type' => 'string',
            'context' => array('view', 'edit')
        )
    ));
}
add_action('rest_api_init', 'my_custom_api_register_fields');

/**
 * 获取自定义字段值的回调函数
 */
function my_custom_api_get_field($object, $field_name, $request) {
    return get_post_meta($object['id'], $field_name, true);
}
?>

1.2 开发环境配置

在开始开发前,需要确保您的WordPress环境已正确配置:

  1. 启用永久链接:REST API需要干净的URL结构
  2. 调试模式:在wp-config.php中启用调试功能
  3. 安装必要插件:如"WP REST API Controller"用于管理API端点
  4. 使用开发者工具:推荐Postman或Insomnia测试API

第二部分:集成第三方天气数据服务

2.1 选择天气API服务

我们将使用OpenWeatherMap API作为示例,它提供免费的天气数据服务。首先需要注册获取API密钥。

<?php
/**
 * WordPress天气小工具
 * 集成OpenWeatherMap API
 */

class Weather_Widget_Tool {
    
    private $api_key;
    private $cache_time;
    
    /**
     * 构造函数
     * 
     * @param string $api_key OpenWeatherMap API密钥
     * @param int $cache_time 缓存时间(秒)
     */
    public function __construct($api_key = '', $cache_time = 1800) {
        $this->api_key = $api_key;
        $this->cache_time = $cache_time;
        
        // 初始化钩子
        $this->init_hooks();
    }
    
    /**
     * 初始化WordPress钩子
     */
    private function init_hooks() {
        // 注册REST API端点
        add_action('rest_api_init', array($this, 'register_weather_endpoints'));
        
        // 注册短代码
        add_shortcode('weather_widget', array($this, 'weather_shortcode'));
        
        // 注册小工具
        add_action('widgets_init', function() {
            register_widget('Weather_Widget_Class');
        });
    }
    
    /**
     * 注册天气相关的REST API端点
     */
    public function register_weather_endpoints() {
        // 获取当前天气
        register_rest_route('weather/v1', '/current/(?P<city>[a-zA-Z0-9s,]+)', array(
            'methods' => 'GET',
            'callback' => array($this, 'get_current_weather'),
            'args' => array(
                'city' => array(
                    'required' => true,
                    'validate_callback' => function($param) {
                        return !empty($param);
                    }
                ),
                'units' => array(
                    'required' => false,
                    'default' => 'metric',
                    'enum' => array('metric', 'imperial')
                )
            ),
            'permission_callback' => '__return_true'
        ));
        
        // 获取天气预报
        register_rest_route('weather/v1', '/forecast/(?P<city>[a-zA-Z0-9s,]+)', array(
            'methods' => 'GET',
            'callback' => array($this, 'get_weather_forecast'),
            'permission_callback' => '__return_true'
        ));
    }
    
    /**
     * 获取当前天气数据
     * 
     * @param WP_REST_Request $request 请求对象
     * @return WP_REST_Response|WP_Error 响应数据或错误
     */
    public function get_current_weather($request) {
        $city = sanitize_text_field($request['city']);
        $units = sanitize_text_field($request->get_param('units') ?: 'metric');
        
        // 检查缓存
        $cache_key = 'weather_current_' . md5($city . $units);
        $cached_data = get_transient($cache_key);
        
        if ($cached_data !== false) {
            return new WP_REST_Response($cached_data, 200);
        }
        
        // 构建API请求URL
        $api_url = add_query_arg(array(
            'q' => $city,
            'appid' => $this->api_key,
            'units' => $units,
            'lang' => get_locale()
        ), 'https://api.openweathermap.org/data/2.5/weather');
        
        // 发送API请求
        $response = wp_remote_get($api_url, array(
            'timeout' => 15
        ));
        
        // 检查请求是否成功
        if (is_wp_error($response)) {
            return new WP_Error('api_error', 
                __('无法连接到天气服务', 'textdomain'), 
                array('status' => 500));
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        // 检查API响应
        if (isset($data['cod']) && $data['cod'] != 200) {
            return new WP_Error('weather_error', 
                $data['message'] ?? __('获取天气数据失败', 'textdomain'), 
                array('status' => $data['cod']));
        }
        
        // 格式化响应数据
        $formatted_data = array(
            'city' => $data['name'] ?? $city,
            'country' => $data['sys']['country'] ?? '',
            'temperature' => round($data['main']['temp']),
            'feels_like' => round($data['main']['feels_like']),
            'humidity' => $data['main']['humidity'],
            'pressure' => $data['main']['pressure'],
            'weather' => array(
                'main' => $data['weather'][0]['main'],
                'description' => $data['weather'][0]['description'],
                'icon' => $this->get_weather_icon_url($data['weather'][0]['icon'])
            ),
            'wind' => array(
                'speed' => $data['wind']['speed'],
                'deg' => $data['wind']['deg'] ?? 0
            ),
            'units' => $units,
            'timestamp' => time(),
            'sunrise' => $data['sys']['sunrise'],
            'sunset' => $data['sys']['sunset']
        );
        
        // 缓存数据
        set_transient($cache_key, $formatted_data, $this->cache_time);
        
        return new WP_REST_Response($formatted_data, 200);
    }
    
    /**
     * 获取天气图标URL
     * 
     * @param string $icon_code 图标代码
     * @return string 图标URL
     */
    private function get_weather_icon_url($icon_code) {
        return sprintf('https://openweathermap.org/img/wn/%s@2x.png', $icon_code);
    }
    
    /**
     * 天气小工具短代码
     * 
     * @param array $atts 短代码属性
     * @return string HTML输出
     */
    public function weather_shortcode($atts) {
        $atts = shortcode_atts(array(
            'city' => 'Beijing',
            'units' => 'metric',
            'show_icon' => true,
            'show_details' => false
        ), $atts, 'weather_widget');
        
        // 获取天气数据
        $request = new WP_REST_Request('GET', '/weather/v1/current/' . urlencode($atts['city']));
        $request->set_param('units', $atts['units']);
        
        $response = rest_do_request($request);
        
        if ($response->is_error()) {
            return '<div class="weather-error">' . 
                   __('无法加载天气数据', 'textdomain') . 
                   '</div>';
        }
        
        $weather_data = $response->get_data();
        
        // 构建HTML输出
        ob_start();
        ?>
        <div class="weather-widget" data-city="<?php echo esc_attr($atts['city']); ?>">
            <div class="weather-header">
                <h3><?php echo esc_html($weather_data['city']); ?></h3>
                <?php if ($atts['show_icon']): ?>
                <img src="<?php echo esc_url($weather_data['weather']['icon']); ?>" 
                     alt="<?php echo esc_attr($weather_data['weather']['description']); ?>"
                     class="weather-icon">
                <?php endif; ?>
            </div>
            <div class="weather-main">
                <div class="temperature">
                    <?php echo esc_html($weather_data['temperature']); ?>°
                    <?php echo $atts['units'] == 'metric' ? 'C' : 'F'; ?>
                </div>
                <div class="description">
                    <?php echo esc_html($weather_data['weather']['description']); ?>
                </div>
            </div>
            <?php if ($atts['show_details']): ?>
            <div class="weather-details">
                <div class="detail-item">
                    <span class="label"><?php _e('体感温度', 'textdomain'); ?>:</span>
                    <span class="value"><?php echo esc_html($weather_data['feels_like']); ?>°</span>
                </div>
                <div class="detail-item">
                    <span class="label"><?php _e('湿度', 'textdomain'); ?>:</span>
                    <span class="value"><?php echo esc_html($weather_data['humidity']); ?>%</span>
                </div>
                <div class="detail-item">
                    <span class="label"><?php _e('风速', 'textdomain'); ?>:</span>
                    <span class="value"><?php echo esc_html($weather_data['wind']['speed']); ?> m/s</span>
                </div>
            </div>
            <?php endif; ?>
        </div>
        <style>
            .weather-widget {
                border: 1px solid #e0e0e0;
                border-radius: 8px;
                padding: 20px;
                max-width: 300px;
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                color: white;
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            }
            .weather-header {
                display: flex;
                justify-content: space-between;
                align-items: center;
                margin-bottom: 15px;
            }
            .weather-header h3 {
                margin: 0;
                font-size: 1.5em;
            }
            .weather-icon {
                width: 60px;
                height: 60px;
            }
            .weather-main {
                text-align: center;
                margin-bottom: 15px;
            }
            .temperature {
                font-size: 3em;
                font-weight: bold;
                line-height: 1;
            }
            .description {
                font-size: 1.2em;
                text-transform: capitalize;
            }
            .weather-details {
                border-top: 1px solid rgba(255,255,255,0.2);
                padding-top: 15px;
            }
            .detail-item {
                display: flex;
                justify-content: space-between;
                margin-bottom: 8px;
                font-size: 0.9em;
            }
            .weather-error {
                padding: 10px;
                background: #f8d7da;
                color: #721c24;
                border: 1px solid #f5c6cb;
                border-radius: 4px;
            }
        </style>
        <?php
        return ob_get_clean();
    }
}

/**
 * 天气小工具类
 */
class Weather_Widget_Class extends WP_Widget {
    
    public function __construct() {
        parent::__construct(
            'weather_widget',
            __('天气小工具', 'textdomain'),
            array('description' => __('显示当前天气信息', 'textdomain'))
        );
    }
    
    public function widget($args, $instance) {
        echo $args['before_widget'];
        
        if (!empty($instance['title'])) {
            echo $args['before_title'] . 
                 apply_filters('widget_title', $instance['title']) . 
                 $args['after_title'];
        }
        
        // 使用短代码显示天气
        echo do_shortcode('[weather_widget city="' . 
                         esc_attr($instance['city']) . 
                         '" units="' . 
                         esc_attr($instance['units']) . 
                         '" show_details="' . 
                         ($instance['show_details'] ? 'true' : 'false') . 
                         '"]');
        
        echo $args['after_widget'];
    }
    
    public function form($instance) {
        $title = !empty($instance['title']) ? $instance['title'] : '';
        $city = !empty($instance['city']) ? $instance['city'] : 'Beijing';
        $units = !empty($instance['units']) ? $instance['units'] : 'metric';
        $show_details = !empty($instance['show_details']) ? $instance['show_details'] : false;
        ?>
        <p>
            <label for="<?php echo esc_attr($this->get_field_id('title')); ?>">
                <?php _e('标题:', 'textdomain'); ?>
            </label>
            <input class="widefat" 
                   id="<?php echo esc_attr($this->get_field_id('title')); ?>"
                   name="<?php echo esc_attr($this->get_field_name('title')); ?>"
                   type="text" 
                   value="<?php echo esc_attr($title); ?>">
        </p>
        <p>
            <label for="<?php echo esc_attr($this->get_field_id('city')); ?>">
                <?php _e('城市:', 'textdomain'); ?>
            </label>
            <input class="widefat" 
                   id="<?php echo esc_attr($this->get_field_id('city')); ?>"
                   name="<?php echo esc_attr($this->get_field_name('city')); ?>"
                   type="text" 
                   value="<?php echo esc_attr($city); ?>">
        </p>
        <p>
            <label for="<?php echo esc_attr($this->get_field_id('units')); ?>">
                <?php _e('单位:', 'textdomain'); ?>
            </label>
            <select class="widefat"
                    id="<?php echo esc_attr($this->get_field_id('units')); ?>"
                    name="<?php echo esc_attr($this->get_field_name('units')); ?>">
                <option value="metric" <?php selected($units, 'metric'); ?>>
                    <?php _e('公制 (°C)', 'textdomain'); ?>
                </option>
                <option value="imperial" <?php selected($units, 'imperial'); ?>>
                    <?php _e('英制 (°F)', 'textdomain'); ?>
                </option>
            </select>
        </p>
        <p>
            <input type="checkbox" 
                   id="<?php echo esc_attr($this->get_field_id('show_details')); ?>"
                   name="<?php echo esc_attr($this->get_field_name('show_details')); ?>"
                   value="1" <?php checked($show_details, 1); ?>>
            <label for="<?php echo esc_attr($this->get_field_id('show_details')); ?>">
                <?php _e('显示详细天气信息', 'textdomain'); ?>
            </label>
        </p>
        <?php
    }
    
    public function update($new_instance, $old_instance) {
        $instance = array();
        $instance['title'] = (!empty($new_instance['title'])) ? 
                            strip_tags($new_instance['title']) : '';
        $instance['city'] = (!empty($new_instance['city'])) ? 

city']) : 'Beijing';

    $instance['units'] = (!empty($new_instance['units'])) ? 
                        sanitize_text_field($new_instance['units']) : 'metric';
    $instance['show_details'] = (!empty($new_instance['show_details'])) ? 1 : 0;
    return $instance;
}

}

// 初始化天气小工具
$weather_api_key = 'your_openweathermap_api_key_here'; // 请替换为您的API密钥
new Weather_Widget_Tool($weather_api_key);
?>


### 2.2 天气预报功能扩展

<?php
/**

  • 天气预报功能扩展
  • 提供5天天气预报数据
    */

class Weather_Forecast_Extension {


private $api_key;

public function __construct($api_key) {
    $this->api_key = $api_key;
    $this->init();
}

private function init() {
    // 注册天气预报短代码
    add_shortcode('weather_forecast', array($this, 'forecast_shortcode'));
    
    // 添加AJAX处理
    add_action('wp_ajax_get_weather_forecast', array($this, 'ajax_get_forecast'));
    add_action('wp_ajax_nopriv_get_weather_forecast', array($this, 'ajax_get_forecast'));
    
    // 注册前端脚本
    add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
}

/**
 * 获取天气预报数据
 */
public function get_weather_forecast($request) {
    $city = sanitize_text_field($request['city']);
    $units = sanitize_text_field($request->get_param('units') ?: 'metric');
    
    $cache_key = 'weather_forecast_' . md5($city . $units);
    $cached_data = get_transient($cache_key);
    
    if ($cached_data !== false) {
        return new WP_REST_Response($cached_data, 200);
    }
    
    $api_url = add_query_arg(array(
        'q' => $city,
        'appid' => $this->api_key,
        'units' => $units,
        'cnt' => 40 // 5天数据(每3小时一次)
    ), 'https://api.openweathermap.org/data/2.5/forecast');
    
    $response = wp_remote_get($api_url, array('timeout' => 15));
    
    if (is_wp_error($response)) {
        return new WP_Error('api_error', 
            __('无法获取天气预报数据', 'textdomain'), 
            array('status' => 500));
    }
    
    $data = json_decode(wp_remote_retrieve_body($response), true);
    
    if ($data['cod'] != '200') {
        return new WP_Error('forecast_error', 
            $data['message'] ?? __('获取预报数据失败', 'textdomain'), 
            array('status' => $data['cod']));
    }
    
    // 按天分组预报数据
    $forecast_by_day = array();
    foreach ($data['list'] as $forecast) {
        $date = date('Y-m-d', $forecast['dt']);
        if (!isset($forecast_by_day[$date])) {
            $forecast_by_day[$date] = array(
                'date' => $date,
                'day_name' => date_i18n('l', $forecast['dt']),
                'forecasts' => array(),
                'temp_min' => PHP_INT_MAX,
                'temp_max' => PHP_INT_MIN,
                'icons' => array()
            );
        }
        
        $forecast_by_day[$date]['forecasts'][] = array(
            'time' => date('H:i', $forecast['dt']),
            'temp' => round($forecast['main']['temp']),
            'feels_like' => round($forecast['main']['feels_like']),
            'humidity' => $forecast['main']['humidity'],
            'weather' => array(
                'main' => $forecast['weather'][0]['main'],
                'description' => $forecast['weather'][0]['description'],
                'icon' => $this->get_weather_icon_url($forecast['weather'][0]['icon'])
            ),
            'wind_speed' => $forecast['wind']['speed']
        );
        
        // 更新当天温度范围
        $forecast_by_day[$date]['temp_min'] = min(
            $forecast_by_day[$date]['temp_min'], 
            round($forecast['main']['temp_min'])
        );
        $forecast_by_day[$date]['temp_max'] = max(
            $forecast_by_day[$date]['temp_max'], 
            round($forecast['main']['temp_max'])
        );
        
        // 收集天气图标
        $forecast_by_day[$date]['icons'][] = $forecast['weather'][0]['icon'];
    }
    
    // 确定每天的主要天气图标
    foreach ($forecast_by_day as &$day) {
        $icon_counts = array_count_values($day['icons']);
        arsort($icon_counts);
        $day['main_icon'] = $this->get_weather_icon_url(key($icon_counts));
    }
    
    $formatted_data = array(
        'city' => $data['city']['name'],
        'country' => $data['city']['country'],
        'forecast_days' => array_values($forecast_by_day),
        'units' => $units,
        'updated_at' => current_time('mysql')
    );
    
    set_transient($cache_key, $formatted_data, 3600); // 缓存1小时
    
    return new WP_REST_Response($formatted_data, 200);
}

private function get_weather_icon_url($icon_code) {
    return sprintf('https://openweathermap.org/img/wn/%s@2x.png', $icon_code);
}

/**
 * 天气预报短代码
 */
public function forecast_shortcode($atts) {
    $atts = shortcode_atts(array(
        'city' => 'Beijing',
        'days' => 5,
        'units' => 'metric',
        'layout' => 'horizontal' // horizontal 或 vertical
    ), $atts, 'weather_forecast');
    
    ob_start();
    ?>
    <div class="weather-forecast-widget" 
         data-city="<?php echo esc_attr($atts['city']); ?>"
         data-days="<?php echo esc_attr($atts['days']); ?>"
         data-units="<?php echo esc_attr($atts['units']); ?>"
         data-layout="<?php echo esc_attr($atts['layout']); ?>">
        <div class="forecast-loading">
            <?php _e('加载天气预报...', 'textdomain'); ?>
        </div>
        <div class="forecast-content" style="display: none;"></div>
    </div>
    <?php
    return ob_get_clean();
}

/**
 * 注册前端脚本
 */
public function enqueue_scripts() {
    wp_register_script('weather-forecast', 
        plugins_url('js/weather-forecast.js', __FILE__),
        array('jquery'), 
        '1.0.0', 
        true);
    
    wp_localize_script('weather-forecast', 'weatherForecast', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('weather_forecast_nonce')
    ));
    
    wp_enqueue_script('weather-forecast');
    
    wp_enqueue_style('weather-forecast-style',
        plugins_url('css/weather-forecast.css', __FILE__));
}

/**
 * AJAX获取天气预报
 */
public function ajax_get_forecast() {
    // 验证nonce
    if (!wp_verify_nonce($_POST['nonce'], 'weather_forecast_nonce')) {
        wp_die('Security check failed');
    }
    
    $city = sanitize_text_field($_POST['city']);
    $units = sanitize_text_field($_POST['units']);
    
    // 构建REST请求
    $request = new WP_REST_Request('GET', '/weather/v1/forecast/' . urlencode($city));
    $request->set_param('units', $units);
    
    $response = rest_do_request($request);
    
    if ($response->is_error()) {
        wp_send_json_error($response->as_error()->get_error_message());
    }
    
    wp_send_json_success($response->get_data());
}

}

// 初始化天气预报扩展
$forecast_extension = new Weather_Forecast_Extension($weather_api_key);
?>


## 第三部分:集成汇率转换工具

### 3.1 汇率API集成

<?php
/**

  • 汇率转换工具
  • 使用免费汇率API
    */

class Currency_Converter_Tool {


private $api_base = 'https://api.exchangerate-api.com/v4/latest/';
private $cache_time = 3600; // 1小时缓存

public function __construct() {
    $this->init_hooks();
}

private function init_hooks() {
    // 注册REST API端点
    add_action('rest_api_init', array($this, 'register_currency_endpoints'));
    
    // 注册短代码
    add_shortcode('currency_converter', array($this, 'converter_shortcode'));
    
    // 注册小工具
    add_action('widgets_init', function() {
        register_widget('Currency_Converter_Widget');
    });
}

/**
 * 注册汇率API端点
 */
public function register_currency_endpoints() {
    // 获取汇率
    register_rest_route('currency/v1', '/rates/(?P<base>[A-Z]{3})', array(
        'methods' => 'GET',
        'callback' => array($this, 'get_exchange_rates'),
        'args' => array(
            'base' => array(
                'required' => true,
                'validate_callback' => function($param) {
                    return preg_match('/^[A-Z]{3}$/', $param);
                }
            )
        ),
        'permission_callback' => '__return_true'
    ));
    
    // 货币转换
    register_rest_route('currency/v1', '/convert', array(
        'methods' => 'GET',
        'callback' => array($this, 'convert_currency'),
        'args' => array(
            'amount' => array(
                'required' => true,
                'validate_callback' => function($param) {
                    return is_numeric($param) && $param > 0;
                }
            ),
            'from' => array(
                'required' => true,
                'validate_callback' => function($param) {
                    return preg_match('/^[A-Z]{3}$/', $param);
                }
            ),
            'to' => array(
                'required' => true,
                'validate_callback' => function($param) {
                    return preg_match('/^[A-Z]{3}$/', $param);
                }
            )
        ),
        'permission_callback' => '__return_true'
    ));
    
    // 获取支持的货币列表
    register_rest_route('currency/v1', '/currencies', array(
        'methods' => 'GET',
        'callback' => array($this, 'get_currency_list'),
        'permission_callback' => '__return_true'
    ));
}

/**
 * 获取汇率数据
 */
public function get_exchange_rates($request) {
    $base_currency = strtoupper($request['base']);
    
    $cache_key = 'exchange_rates_' . $base_currency;
    $cached_data = get_transient($cache_key);
    
    if ($cached_data !== false) {
        return new WP_REST_Response($cached_data, 200);
    }
    
    $api_url = $this->api_base . $base_currency;
    $response = wp_remote_get($api_url, array('timeout' => 15));
    
    if (is_wp_error($response)) {
        // 备用API
        $api_url = "https://api.exchangerate.host/latest?base={$base_currency}";
        $response = wp_remote_get($api_url, array('timeout' => 15));
        
        if (is_wp_error($response)) {
            return new WP_Error('api_error', 
                __('无法获取汇率数据', 'textdomain'), 
                array('status' => 500));
        }
    }
    
    $data = json_decode(wp_remote_retrieve_body($response), true);
    
    if (empty($data['rates'])) {
        return new WP_Error('data_error', 
            __('无效的汇率数据', 'textdomain'), 
            array('status' => 500));
    }
    
    $formatted_data = array(
        'base' => $base_currency,
        'rates' => $data['rates'],
        'date' => $data['date'] ?? current_time('Y-m-d'),
        'timestamp' => time()
    );
    
    set_transient($cache_key, $formatted_data, $this->cache_time);
    
    return new WP_REST_Response($formatted_data, 200);
}

/**
 * 货币转换
 */
public function convert_currency($request) {
    $amount = floatval($request['amount']);
    $from_currency = strtoupper($request['from']);
    $to_currency = strtoupper($request['to']);
    
    // 获取汇率
    $rates_request = new WP_REST_Request('GET', '/currency/v1/rates/' . $from_currency);
    $rates_response = rest_do_request($rates_request);
    
    if ($rates_response->is_error()) {
        return $rates_response->as_error();
    }
    
    $rates_data = $rates_response->get_data();
    
    if (!isset($rates_data['rates'][$to_currency])) {
        return new WP_Error('currency_error', 
            __('不支持的目标货币', 'textdomain'), 
            array('status' => 400));
    }
    
    $rate = $rates_data['rates'][$to_currency];
    $converted_amount = $amount * $rate;
    
    $result = array(
        'amount' => $amount,
        'from' => $from_currency,
        'to' => $to_currency,
        'rate' => $rate,
        'converted' => round($converted_amount, 4),
        'timestamp' => time(),
        'date' => $rates_data['date']
    );
    
    return new WP_REST_Response($result, 200);
}

/**
 * 获取货币列表
 */
public function get_currency_list() {
    $currencies = array(
        'USD' => __('美元', 'textdomain'),
        'EUR' => __('欧元', 'textdomain'),
        'GBP' => __('英镑', 'textdomain'),
        'JPY' => __('日元', 'textdomain'),
        'CNY' => __('人民币', 'textdomain'),
        'CAD' => __('加元', 'textdomain'),
        'AUD' => __('澳元', 'textdomain'),
        'CHF' => __('瑞士法郎', 'textdomain'),
        'HKD' => __('港币', 'textdomain'),
        'SGD' => __('新加坡元', 'textdomain'),
        'KRW' => __('韩元', 'textdomain'),
        'INR' => __('印度卢比', 'textdomain'),
        'RUB' => __('俄罗斯卢布', 'textdomain'),
        'BRL' => __('巴西雷亚尔', 'textdomain'),
        'MXN' => __('墨西哥比索', 'textdomain')
    );
    
    return new WP_REST_Response($currencies, 200);
}

/**
 * 汇率转换器短代码
 */
public function converter_shortcode($atts) {
    $atts = shortcode_atts(array(
        'default_from' => 'USD',
        'default_to' => 'CNY',
        'show_historical' => false,
        'theme' => 'light'
    ), $atts, 'currency_converter');
    
    // 获取货币列表
    $request = new WP_REST_Request('GET', '/currency/v1/currencies');
    $response = rest_do_request($request);
    $currencies = $response->is_error() ? array() : $response->get_data();
    
    ob_start();
    ?>
    <div class="currency-converter-widget theme-<?php echo esc_attr($atts['theme']); ?>">
        <div class="converter-header">
            <h3><?php _e('汇率转换器', 'textdomain'); ?></h3>
            <div class="last-updated">
                <?php _e('实时汇率', 'textdomain'); ?>
            </div>
        </div>
        
        <div class="converter-form">
            <div class="input-group">
                <div class="input-wrapper">
                    <input type="number" 
                           class="amount-input" 
                           value="1" 
                           min="0" 
                           step="0.01"
                           placeholder="<?php esc_attr_e('金额', 'textdomain'); ?>">
                    
                    <select class="currency-select from-currency">
                        <?php foreach ($currencies as $code => $name): ?>
                        <option value="<?php echo esc_attr($code); ?>"
                                <?php selected($code, $atts['default_from']); ?>>
                            <?php echo esc_html("$code - $name"); ?>
                        </option>
                        <?php endforeach; ?>
                    </select>
                </div>
                
                <div class="swap-button">
                    <button type="button" class="swap-currencies">
                        <span class="swap-icon">⇄</span>
                    </button>
                </div>
                
                <div class="input-wrapper">
                    <input type="text" 
                           class="result-output" 
                           readonly
                           placeholder="<?php esc_attr_e('转换结果', 'textdomain'); ?>">
                    
                    <select class="currency-select to-currency">
                        <?php foreach ($currencies as $code => $name): ?>
                        <option value="<?php echo esc_attr($code); ?>"
                                <?php selected($code, $atts['default_to']);
本文来自网络投稿,不代表本站点的立场,转载请注明出处:https://www.gongxiangcang.com/5051.html

溯源库®作者

漳州柔性供应链服务有限公司 小批量订单定制化服务商( 投稿邮箱:vip@jiaochengku.com)
上一篇
下一篇

为您推荐

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@suyuanku.com

工作时间:周一至周五,9:00-17:30,节假日休息
关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部