wpbridge/includes/Commercial/BridgeClient.php
feibisi 5e18f378bb feat(commercial): add BridgeClient for Go server integration
- Add BridgeClient class for wpbridge-server communication
- Update BridgeManager to use Bridge Server for plugin list
- Add Bridge Server URL and API Key settings in admin
- Add AJAX handler for testing Bridge Server connection
- Include commercial bridge spec and review docs

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-02-15 09:28:51 +08:00

370 lines
7.4 KiB
PHP

<?php
/**
* Bridge Server 客户端
*
* 与 wpbridge-server Go 服务端通信
*
* @package WPBridge
* @since 0.9.8
*/
declare(strict_types=1);
namespace WPBridge\Commercial;
use WPBridge\Core\Logger;
// 防止直接访问
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* BridgeClient 类
*/
class BridgeClient {
/**
* 服务端 URL
*
* @var string
*/
private string $server_url;
/**
* API Key
*
* @var string
*/
private string $api_key;
/**
* 请求超时(秒)
*
* @var int
*/
private int $timeout;
/**
* 构造函数
*
* @param string $server_url 服务端 URL
* @param string $api_key API Key
* @param int $timeout 请求超时(秒)
*/
public function __construct( string $server_url, string $api_key, int $timeout = 30 ) {
$this->server_url = rtrim( $server_url, '/' );
$this->api_key = $api_key;
$this->timeout = $timeout;
}
/**
* 获取插件信息
*
* @param string $slug 插件 slug
* @return array|null
*/
public function get_plugin_info( string $slug ): ?array {
$response = $this->request( 'GET', "/api/v1/plugin/{$slug}" );
if ( is_wp_error( $response ) ) {
Logger::error( 'Failed to get plugin info', [
'slug' => $slug,
'error' => $response->get_error_message(),
] );
return null;
}
return $response;
}
/**
* 获取下载 URL
*
* @param string $slug 插件 slug
* @return string|null
*/
public function get_download_url( string $slug ): ?string {
// 下载端点会返回重定向或直接代理
return $this->server_url . "/api/v1/download/{$slug}";
}
/**
* 列出所有供应商(需要认证)
*
* @return array
*/
public function list_vendors(): array {
$response = $this->request( 'GET', '/api/v1/admin/vendors', [], true );
if ( is_wp_error( $response ) ) {
Logger::error( 'Failed to list vendors', [
'error' => $response->get_error_message(),
] );
return [];
}
return $response ?? [];
}
/**
* 创建供应商(需要认证)
*
* @param array $data 供应商数据
* @return array
*/
public function create_vendor( array $data ): array {
$response = $this->request( 'POST', '/api/v1/admin/vendors', $data, true );
if ( is_wp_error( $response ) ) {
return [
'success' => false,
'message' => $response->get_error_message(),
];
}
return [
'success' => true,
'data' => $response,
];
}
/**
* 更新供应商(需要认证)
*
* @param int $id 供应商 ID
* @param array $data 供应商数据
* @return array
*/
public function update_vendor( int $id, array $data ): array {
$response = $this->request( 'PUT', "/api/v1/admin/vendors/{$id}", $data, true );
if ( is_wp_error( $response ) ) {
return [
'success' => false,
'message' => $response->get_error_message(),
];
}
return [
'success' => true,
'data' => $response,
];
}
/**
* 删除供应商(需要认证)
*
* @param int $id 供应商 ID
* @return array
*/
public function delete_vendor( int $id ): array {
$response = $this->request( 'DELETE', "/api/v1/admin/vendors/{$id}", [], true );
if ( is_wp_error( $response ) ) {
return [
'success' => false,
'message' => $response->get_error_message(),
];
}
return [
'success' => true,
];
}
/**
* 列出所有插件(需要认证)
*
* @return array
*/
public function list_plugins(): array {
$response = $this->request( 'GET', '/api/v1/admin/plugins', [], true );
if ( is_wp_error( $response ) ) {
Logger::error( 'Failed to list plugins', [
'error' => $response->get_error_message(),
] );
return [];
}
return $response ?? [];
}
/**
* 创建插件(需要认证)
*
* @param array $data 插件数据
* @return array
*/
public function create_plugin( array $data ): array {
$response = $this->request( 'POST', '/api/v1/admin/plugins', $data, true );
if ( is_wp_error( $response ) ) {
return [
'success' => false,
'message' => $response->get_error_message(),
];
}
return [
'success' => true,
'data' => $response,
];
}
/**
* 获取插件详情(需要认证)
*
* @param string $slug 插件 slug
* @return array|null
*/
public function get_plugin( string $slug ): ?array {
$response = $this->request( 'GET', "/api/v1/admin/plugins/{$slug}", [], true );
if ( is_wp_error( $response ) ) {
return null;
}
return $response;
}
/**
* 更新插件(需要认证)
*
* @param string $slug 插件 slug
* @param array $data 插件数据
* @return array
*/
public function update_plugin( string $slug, array $data ): array {
$response = $this->request( 'PUT', "/api/v1/admin/plugins/{$slug}", $data, true );
if ( is_wp_error( $response ) ) {
return [
'success' => false,
'message' => $response->get_error_message(),
];
}
return [
'success' => true,
'data' => $response,
];
}
/**
* 删除插件(需要认证)
*
* @param string $slug 插件 slug
* @return array
*/
public function delete_plugin( string $slug ): array {
$response = $this->request( 'DELETE', "/api/v1/admin/plugins/{$slug}", [], true );
if ( is_wp_error( $response ) ) {
return [
'success' => false,
'message' => $response->get_error_message(),
];
}
return [
'success' => true,
];
}
/**
* 健康检查
*
* @return bool
*/
public function health_check(): bool {
$response = $this->request( 'GET', '/health' );
if ( is_wp_error( $response ) ) {
return false;
}
return isset( $response['status'] ) && $response['status'] === 'ok';
}
/**
* 发送请求
*
* @param string $method HTTP 方法
* @param string $endpoint API 端点
* @param array $data 请求数据
* @param bool $auth 是否需要认证
* @return array|\WP_Error
*/
private function request( string $method, string $endpoint, array $data = [], bool $auth = false ) {
$url = $this->server_url . $endpoint;
$args = [
'method' => $method,
'timeout' => $this->timeout,
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
];
// 添加认证头
if ( $auth && ! empty( $this->api_key ) ) {
$args['headers']['X-API-Key'] = $this->api_key;
}
// 添加请求体
if ( ! empty( $data ) && in_array( $method, [ 'POST', 'PUT', 'PATCH' ], true ) ) {
$args['body'] = wp_json_encode( $data );
}
$response = wp_remote_request( $url, $args );
if ( is_wp_error( $response ) ) {
return $response;
}
$status_code = wp_remote_retrieve_response_code( $response );
$body = wp_remote_retrieve_body( $response );
// 处理 204 No Content
if ( $status_code === 204 ) {
return [];
}
// 处理错误状态码
if ( $status_code >= 400 ) {
$error_data = json_decode( $body, true );
$message = $error_data['message'] ?? $error_data['error'] ?? "HTTP {$status_code}";
return new \WP_Error( 'bridge_server_error', $message, [ 'status' => $status_code ] );
}
// 解析 JSON 响应
$decoded = json_decode( $body, true );
if ( json_last_error() !== JSON_ERROR_NONE ) {
return new \WP_Error( 'json_decode_error', 'Invalid JSON response' );
}
return $decoded;
}
/**
* 获取服务端 URL
*
* @return string
*/
public function get_server_url(): string {
return $this->server_url;
}
/**
* 检查是否已配置
*
* @return bool
*/
public function is_configured(): bool {
return ! empty( $this->server_url ) && ! empty( $this->api_key );
}
}