feat: initial WooAApanel plugin
Full WooCommerce plugin for aaPanel hosting management: - aaPanel API client (all website + database endpoints) - Admin: server management, site/DB assignments, full site/DB management panels - Customer My Account: web hosting tab with sites and databases - WooDomains PowerDNS integration for DNS management - WooCommerce order auto-provisioning (product → server linking) - Permission model: admin has all actions, customers have scoped access Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
399
includes/class-wooaapanel-api.php
Normal file
399
includes/class-wooaapanel-api.php
Normal file
@@ -0,0 +1,399 @@
|
||||
<?php
|
||||
/**
|
||||
* aaPanel API client.
|
||||
*
|
||||
* Authentication: every request appends request_time and request_token
|
||||
* as query-string parameters.
|
||||
* request_token = md5( time + md5( api_key ) )
|
||||
*
|
||||
* All endpoints use POST with multipart/form-data body.
|
||||
*/
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
class WooAApanel_API {
|
||||
|
||||
private string $base_url;
|
||||
private string $api_key;
|
||||
private int $timeout = 30;
|
||||
|
||||
public function __construct( string $url, string $api_key ) {
|
||||
$this->base_url = rtrim( $url, '/' );
|
||||
$this->api_key = $api_key;
|
||||
}
|
||||
|
||||
// ── Auth helpers ─────────────────────────────────────────────────────────
|
||||
|
||||
private function auth_params(): array {
|
||||
$now = time();
|
||||
return [
|
||||
'request_time' => $now,
|
||||
'request_token' => md5( $now . md5( $this->api_key ) ),
|
||||
];
|
||||
}
|
||||
|
||||
// ── Core HTTP ────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* POST to an aaPanel v2 endpoint.
|
||||
*
|
||||
* @param string $path e.g. '/v2/site?action=AddSite'
|
||||
* @param array $body POST body fields (multipart)
|
||||
*/
|
||||
public function post( string $path, array $body = [] ): array {
|
||||
$auth = $this->auth_params();
|
||||
// Auth params go on the query string.
|
||||
$url = $this->base_url . $path
|
||||
. ( str_contains( $path, '?' ) ? '&' : '?' )
|
||||
. http_build_query( $auth );
|
||||
|
||||
$response = wp_remote_post( $url, [
|
||||
'timeout' => $this->timeout,
|
||||
'sslverify' => apply_filters( 'wooaapanel_sslverify', false ),
|
||||
'body' => $body,
|
||||
] );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return [ 'success' => false, 'error' => $response->get_error_message() ];
|
||||
}
|
||||
|
||||
$code = wp_remote_retrieve_response_code( $response );
|
||||
$raw = wp_remote_retrieve_body( $response );
|
||||
$data = json_decode( $raw, true );
|
||||
|
||||
return [
|
||||
'success' => ( $code >= 200 && $code < 300 ),
|
||||
'data' => $data,
|
||||
'code' => $code,
|
||||
];
|
||||
}
|
||||
|
||||
// ── Connection test ───────────────────────────────────────────────────────
|
||||
|
||||
public function test_connection(): array {
|
||||
return $this->post( '/v2/panel/public/get_soft_status', [ 'name' => 'nginx' ] );
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// WEBSITE / PHP PROJECT
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
// ── Site listing ─────────────────────────────────────────────────────────
|
||||
|
||||
public function get_sites( int $page = 1, int $limit = 50, string $search = '' ): array {
|
||||
return $this->post( '/v2/data?action=getData', [
|
||||
'p' => $page,
|
||||
'limit' => $limit,
|
||||
'table' => 'sites',
|
||||
'search' => $search,
|
||||
'type' => -1,
|
||||
] );
|
||||
}
|
||||
|
||||
public function get_site_types(): array {
|
||||
return $this->post( '/v2/site?action=get_site_types', [] );
|
||||
}
|
||||
|
||||
// ── Site CRUD ────────────────────────────────────────────────────────────
|
||||
|
||||
public function add_site( array $data ): array {
|
||||
return $this->post( '/v2/site?action=AddSite', $data );
|
||||
}
|
||||
|
||||
public function check_delete_site( string $site_name ): array {
|
||||
return $this->post( '/v2/site?action=check_del_data', [ 'name' => $site_name ] );
|
||||
}
|
||||
|
||||
public function delete_site( string $site_name, bool $ftp = false, bool $database = false, bool $path = false ): array {
|
||||
return $this->post( '/v2/site?action=DeleteSite', [
|
||||
'webname' => $site_name,
|
||||
'ftp' => $ftp ? 1 : 0,
|
||||
'database' => $database ? 1 : 0,
|
||||
'path' => $path ? 1 : 0,
|
||||
] );
|
||||
}
|
||||
|
||||
// ── Domains ──────────────────────────────────────────────────────────────
|
||||
|
||||
public function get_site_domains( string $site_name ): array {
|
||||
return $this->post( '/v2/data?action=getData&table=domain', [
|
||||
'search' => $site_name,
|
||||
'limit' => 100,
|
||||
'p' => 1,
|
||||
] );
|
||||
}
|
||||
|
||||
public function add_domain( string $site_name, string $domain ): array {
|
||||
return $this->post( '/v2/site?action=AddDomain', [
|
||||
'id' => 0, // will be resolved by panel
|
||||
'webname' => $site_name,
|
||||
'domain' => $domain,
|
||||
] );
|
||||
}
|
||||
|
||||
public function delete_domain( string $site_name, string $domain, int $site_id = 0 ): array {
|
||||
return $this->post( '/v2/site?action=DelDomain', [
|
||||
'id' => $site_id,
|
||||
'webname' => $site_name,
|
||||
'domain' => $domain,
|
||||
'port' => 80,
|
||||
] );
|
||||
}
|
||||
|
||||
// ── XSS protection ───────────────────────────────────────────────────────
|
||||
|
||||
public function get_xss( string $site_name, string $site_path ): array {
|
||||
return $this->post( '/v2/site?action=GetDirUserINI', [
|
||||
'id' => 0,
|
||||
'name' => $site_name,
|
||||
'path' => $site_path,
|
||||
] );
|
||||
}
|
||||
|
||||
public function set_xss( string $site_name, string $site_path, bool $enable ): array {
|
||||
return $this->post( '/v2/site?action=SetDirUserINI', [
|
||||
'id' => 0,
|
||||
'name' => $site_name,
|
||||
'path' => $site_path,
|
||||
'action' => $enable ? 'set' : 'close',
|
||||
] );
|
||||
}
|
||||
|
||||
// ── Site root ────────────────────────────────────────────────────────────
|
||||
|
||||
public function get_site_root( string $site_name ): array {
|
||||
return $this->post( '/v2/data?action=getKey', [
|
||||
'name' => $site_name,
|
||||
'key' => 'path',
|
||||
] );
|
||||
}
|
||||
|
||||
public function set_run_path( string $site_name, string $run_path ): array {
|
||||
return $this->post( '/v2/site?action=SetSiteRunPath', [
|
||||
'id' => 0,
|
||||
'runPath' => $run_path,
|
||||
'siteName' => $site_name,
|
||||
] );
|
||||
}
|
||||
|
||||
// ── PHP version ──────────────────────────────────────────────────────────
|
||||
|
||||
public function get_site_php_version( string $site_name ): array {
|
||||
return $this->post( '/v2/site?action=GetSitePHPVersion', [ 'siteName' => $site_name ] );
|
||||
}
|
||||
|
||||
public function get_php_versions(): array {
|
||||
return $this->post( '/v2/site?action=GetPHPVersion', [] );
|
||||
}
|
||||
|
||||
public function set_site_php_version( string $site_name, string $version ): array {
|
||||
return $this->post( '/v2/site?action=SetPHPVersion', [
|
||||
'siteName' => $site_name,
|
||||
'version' => $version,
|
||||
] );
|
||||
}
|
||||
|
||||
// ── URL rewrite ──────────────────────────────────────────────────────────
|
||||
|
||||
public function get_rewrite_list( string $site_name ): array {
|
||||
return $this->post( '/v2/site?action=GetRewriteList', [ 'siteName' => $site_name ] );
|
||||
}
|
||||
|
||||
public function get_rewrite_content( string $site_name, string $template ): array {
|
||||
return $this->post( '/v2/files?action=GetFileBody', [
|
||||
'path' => "/www/server/panel/vhost/rewrite/{$site_name}.conf",
|
||||
] );
|
||||
}
|
||||
|
||||
public function set_rewrite( string $site_name, string $content ): array {
|
||||
return $this->post( '/v2/files?action=SaveFileBody', [
|
||||
'path' => "/www/server/panel/vhost/rewrite/{$site_name}.conf",
|
||||
'data' => $content,
|
||||
'encoding' => 'utf-8',
|
||||
] );
|
||||
}
|
||||
|
||||
// ── SSL ──────────────────────────────────────────────────────────────────
|
||||
|
||||
public function get_ssl( string $site_name ): array {
|
||||
return $this->post( '/v2/site?action=GetSSL', [ 'siteName' => $site_name ] );
|
||||
}
|
||||
|
||||
public function close_ssl( string $site_name ): array {
|
||||
return $this->post( '/v2/site?action=CloseSSLConf', [ 'updateOf' => 1, 'siteName' => $site_name ] );
|
||||
}
|
||||
|
||||
public function list_ssl_certs(): array {
|
||||
return $this->post( '/v2/ssl_domain?action=list_ssl_info', [] );
|
||||
}
|
||||
|
||||
public function upload_cert( string $key, string $cert, string $domain ): array {
|
||||
return $this->post( '/v2/ssl_domain?action=upload_cert', [
|
||||
'privateKey' => $key,
|
||||
'certPem' => $cert,
|
||||
'bindDomain' => $domain,
|
||||
] );
|
||||
}
|
||||
|
||||
public function deploy_cert_to_site( string $site_name, int $cert_id ): array {
|
||||
return $this->post( '/v2/ssl_domain?action=cert_deploy_sites', [
|
||||
'siteName' => $site_name,
|
||||
'certId' => $cert_id,
|
||||
] );
|
||||
}
|
||||
|
||||
// ── Server info ──────────────────────────────────────────────────────────
|
||||
|
||||
public function get_server_info(): array {
|
||||
return $this->post( '/v2/panel/public/get_soft_status', [ 'name' => 'nginx' ] );
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// DATABASES / MYSQL
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
// ── Listing ──────────────────────────────────────────────────────────────
|
||||
|
||||
public function get_databases( int $page = 1, int $limit = 50, string $search = '' ): array {
|
||||
return $this->post( '/v2/data?action=getData&table=databases&type=MySQL', [
|
||||
'p' => $page,
|
||||
'limit' => $limit,
|
||||
'search' => $search,
|
||||
'type' => 'MySQL',
|
||||
] );
|
||||
}
|
||||
|
||||
public function get_db_info( string $db_name ): array {
|
||||
return $this->post( '/v2/database?action=GetInfo', [ 'name' => $db_name ] );
|
||||
}
|
||||
|
||||
// ── Add / Delete ─────────────────────────────────────────────────────────
|
||||
|
||||
public function add_database( string $db_name, string $db_user, string $password, string $codeing = 'utf8mb4' ): array {
|
||||
return $this->post( '/v2/database?action=AddDatabase', [
|
||||
'name' => $db_name,
|
||||
'db_user' => $db_user,
|
||||
'password' => $password,
|
||||
'codeing' => $codeing,
|
||||
'address' => '%',
|
||||
'accept' => '%',
|
||||
] );
|
||||
}
|
||||
|
||||
public function check_delete_db( string $db_name ): array {
|
||||
return $this->post( '/v2/database?action=check_del_data', [ 'name' => $db_name ] );
|
||||
}
|
||||
|
||||
public function delete_database( string $db_name ): array {
|
||||
return $this->post( '/v2/database?action=DeleteDatabase', [ 'name' => $db_name ] );
|
||||
}
|
||||
|
||||
// ── Backup ───────────────────────────────────────────────────────────────
|
||||
|
||||
public function backup_database( string $db_name ): array {
|
||||
return $this->post( '/v2/database?action=ToBackup', [ 'name' => $db_name ] );
|
||||
}
|
||||
|
||||
public function get_db_backups( string $db_name ): array {
|
||||
return $this->post( '/v2/data?action=getData', [
|
||||
'p' => 1,
|
||||
'limit' => 100,
|
||||
'table' => 'backup',
|
||||
'search' => $db_name,
|
||||
'type' => 'database',
|
||||
] );
|
||||
}
|
||||
|
||||
public function delete_db_backup( int $backup_id, string $db_name ): array {
|
||||
return $this->post( '/v2/database?action=DelBackup', [
|
||||
'id' => $backup_id,
|
||||
'name' => $db_name,
|
||||
] );
|
||||
}
|
||||
|
||||
public function get_recycle_bin(): array {
|
||||
return $this->post( '/v2/files?action=Get_Recycle_bin', [ 'type' => 'database' ] );
|
||||
}
|
||||
|
||||
public function restore_from_recycle( string $path ): array {
|
||||
return $this->post( '/v2/files?action=Re_Recycle_bin', [ 'path' => $path ] );
|
||||
}
|
||||
|
||||
// ── Optimization ─────────────────────────────────────────────────────────
|
||||
|
||||
public function optimize_table( string $db_name ): array {
|
||||
return $this->post( '/v2/database?action=OpTable', [ 'name' => $db_name ] );
|
||||
}
|
||||
|
||||
public function repair_table( string $db_name ): array {
|
||||
return $this->post( '/v2/database?action=ReTable', [ 'name' => $db_name ] );
|
||||
}
|
||||
|
||||
// ── Credentials / Access ─────────────────────────────────────────────────
|
||||
|
||||
public function get_db_access( string $db_name ): array {
|
||||
return $this->post( '/v2/database?action=GetDatabaseAccess', [ 'name' => $db_name ] );
|
||||
}
|
||||
|
||||
public function set_db_access( string $db_name, string $access ): array {
|
||||
return $this->post( '/v2/database?action=SetDatabaseAccess', [
|
||||
'name' => $db_name,
|
||||
'access' => $access,
|
||||
] );
|
||||
}
|
||||
|
||||
public function reset_db_password( string $db_name, string $db_user, string $password ): array {
|
||||
return $this->post( '/v2/database?action=ResDatabasePassword', [
|
||||
'name' => $db_name,
|
||||
'db_user' => $db_user,
|
||||
'password' => $password,
|
||||
] );
|
||||
}
|
||||
|
||||
public function get_mysql_root_password(): array {
|
||||
return $this->post( '/v2/data?action=getKey', [ 'name' => 'mysql' ] );
|
||||
}
|
||||
|
||||
public function set_mysql_root_password( string $password ): array {
|
||||
return $this->post( '/v2/database?action=SetupPassword', [ 'password' => $password ] );
|
||||
}
|
||||
|
||||
// ── Sync ─────────────────────────────────────────────────────────────────
|
||||
|
||||
public function sync_to_databases( array $ids = [] ): array {
|
||||
return $this->post( '/v2/database?action=SyncToDatabases&type=0', [
|
||||
'ids' => wp_json_encode( $ids ),
|
||||
] );
|
||||
}
|
||||
|
||||
public function sync_get_databases(): array {
|
||||
return $this->post( '/v2/database?action=SyncGetDatabases', [] );
|
||||
}
|
||||
|
||||
// ── Import SQL ───────────────────────────────────────────────────────────
|
||||
|
||||
public function import_sql( string $db_name, string $sql_path ): array {
|
||||
return $this->post( '/v2/database?action=InputSql', [
|
||||
'name' => $db_name,
|
||||
'file' => $sql_path,
|
||||
] );
|
||||
}
|
||||
|
||||
// ── Quota ────────────────────────────────────────────────────────────────
|
||||
|
||||
public function modify_db_quota( string $db_name, int $quota_mb ): array {
|
||||
return $this->post( '/v2/project/quota/modify_database_quota', [
|
||||
'name' => $db_name,
|
||||
'quota' => $quota_mb,
|
||||
] );
|
||||
}
|
||||
|
||||
// ── Static factory ───────────────────────────────────────────────────────
|
||||
|
||||
public static function from_server( object $server ): self {
|
||||
return new self( $server->url, $server->api_key );
|
||||
}
|
||||
|
||||
public function get_base_url(): string {
|
||||
return $this->base_url;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user