楚狐在线 - 资讯杂烩
资讯杂烩   在线工具   益智游戏   影音娱乐   网站导航

Spaceship域名云解析服务(DNS)API接口PHP封装


  目前互联网上提供免费的域名托管服务的厂家很多,如阿里云/万网、腾讯云、CloudFlare、Spaceship、华为云等等,我们将域名托管到这些云解析DNS服务商后,虽然服务商都提供了控制台用于域名及解析记录的管理,但是有时候如果我们需要自己实现DDNS动态域名解析等一些基于官网API接口能力的功能,就需要使用到官网提供的API能力,本文将针对Spaceship的API接口,通过PHP封装了常用的函数类,用于托管域名、记录集等的管理。
  本文旨在帮助开发者快速使用集成Spaceship域名云解析服务(DNS)的API接口,实现对域名(Zone)DNS管理和解析记录(Record Set)的自动化管理,如域名托管、记录添加及修改等。
  Spaceship的API官方文档地址详见:https://docs.spaceship.dev
  其中接入需要的API密钥,在登录spaceship.com后,点击右上角【】往下拉,选择【API管理器】,然后点击最下方的【添加API密钥】根据提示填写名称就可以生成了,“管理API访问”选项选择“完全访问”即可,创建API密钥完成后记得马上保存一份,如下图: 


  下面是PHP实现的API封装类,代码如下:

/**
 * Spaceship API 封装类
 * 
 * 基于官方 API 文档实现:https://docs.spaceship.dev
 * 支持域名列表、域名详情、DNS修改、DNSSEC管理等功能
 * 
 * @author Spaceship API Integration
 * @version 1.0.0
 */
class SpaceshipDomainAPI
{
	private const BASE_URL = 'https://spaceship.dev/api/v1';	//API 基础地址
	private string $apiKey;			//API Key
	private string $apiSecret;		//API Secret
	private int $timeout;			//HTTP请求超时时间(秒)
	private int $maxPollAttempts;	//异步操作最大轮询次数
	private int $pollInterval;		//异步操作轮询间隔(秒)

	private static $obj  = null;

	public static function Obj ()
	{
		if(is_null(self::$obj))
		{
			self::$obj = new self();
		}
		return self::$obj;
	}

    //构造函数
    public function __construct()
	{
        $this->apiKey = "Ax****cs";
        $this->apiSecret = "m*************************************YJ";
        $this->timeout = 30;
        $this->maxPollAttempts = 60;
        $this->pollInterval = 2;
    }
    
    /**
     * 发送 API 请求
     * 
     * @param string $method HTTP方法 (GET, POST, PUT, DELETE)
     * @param string $endpoint API端点
     * @param array|null $data 请求数据(可选)
     * @return array API响应
     * @throws Exception 请求失败时抛出异常
     */
    private function request(string $method, string $endpoint, ?array $data = null): array
    {
        $url = self::BASE_URL . $endpoint;
        $ch = curl_init();
        
        $headers = [
            'X-Api-Key: ' . $this->apiKey,
            'X-Api-Secret: ' . $this->apiSecret,
            'Content-Type: application/json'
        ];
        
        $options = [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $this->timeout,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_CUSTOMREQUEST => $method
        ];
        
        if ($data !== null && ($method === 'POST' || $method === 'PUT' || $method === 'PATCH')) {
            $options[CURLOPT_POSTFIELDS] = json_encode($data);
        } elseif ($data !== null && $method === 'DELETE') {
            $options[CURLOPT_POSTFIELDS] = json_encode($data);
        }
        
        curl_setopt_array($ch, $options);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);

        curl_close($ch);

        if ($error) {
            throw new Exception("cURL Error: " . $error);
        }

        $decodedResponse = json_decode($response, true);

        // 处理异步操作(202 Accepted)
        if ($httpCode === 202) {
            return $decodedResponse;
        }

		if ($httpCode === 204) {
			return [
				"code" => 200,  // 将 204 转换为 200 表示成功
				"message" => "操作成功",
				"data" => []
			];
		}

        // 处理错误状态码
        if ($httpCode < 200 || $httpCode >= 300) {
            $errorMsg = isset($decodedResponse['message']) 
                ? $decodedResponse['message'] 
                : "HTTP Error: " . $httpCode;
            throw new Exception($errorMsg, $httpCode);
        }

        return $decodedResponse;
    }
    
    /**
     * 轮询异步操作状态
     * 
     * @param string $operationId 操作ID
     * @return array 最终操作结果
     * @throws Exception 操作失败或超时时抛出异常
     */
    private function pollAsyncOperation(string $operationId): array
    {
        $attempts = 0;
        
        while ($attempts < $this->maxPollAttempts) {
            $result = $this->request('GET', '/async-operations/' . $operationId);
            
            $status = $result['status'] ?? 'pending';
            
            if ($status === 'success') {
                return $result;
            } elseif ($status === 'failed') {
                $errorMsg = $result['details']['error'] ?? 'Async operation failed';
                throw new Exception($errorMsg);
            }
            
            $attempts++;
            sleep($this->pollInterval);
        }
        
        throw new Exception('Async operation timeout after ' . $this->maxPollAttempts . ' attempts');
    }
    
    /**
     * 1. 获取当前账户下的所有域名清单
     * 
     * @param int $take 每页数量(默认100,最大100)
     * @param int $skip 跳过数量(默认0)
     * @param string|null $orderBy 排序字段(name, -name, unicodeName, -unicodeName, registrationDate, -registrationDate, expirationDate, -expirationDate)
     * @return array 域名列表 ['items' => [...], 'total' => ...]
     * @throws Exception
     */
    public function listDomains(int $take = 100, int $skip = 0, ?string $orderBy = null): array
    {
        $params = http_build_query([
            'take' => min($take, 100),
            'skip' => max($skip, 0)
        ]);
        
        if ($orderBy !== null) {
            $params .= '&orderBy=' . urlencode($orderBy);
        }
        
        $endpoint = '/domains?' . $params;
        return $this->request('GET', $endpoint);
    }
    
    /**
     * 2. 查询某个域名的所有信息
     * 
     * @param string $domain 域名(ASCII格式,如 example.com)
     * @return array 域名详细信息
     * @throws Exception
     */
    public function getDomainInfo(string $domain): array
    {
        $endpoint = '/domains/' . urlencode($domain);
        return $this->request('GET', $endpoint);
    }

    /**
     * 3. 修改域名的 DNS 服务器
	 * 
	 * 根据官方 API 文档:
	 * PUT /api/v1/domains/{domain}/nameservers
	 * 
	 * @param string $domain 域名
	 * @param array $nameservers DNS服务器列表,如 
	 * $cf_dns = ['aurora.ns.cloudflare.com','peyton.ns.cloudflare.com'];
	 * @param string $provider DNS服务商类型('basic' 或 'custom')
	 * @return array
	 */
	public function updateNameservers(string $domain, array $nameservers, string $provider = 'custom'): array
	{
		$domain = strtolower(trim($domain));
		
		// 根据官方示例构建正确的请求体
		$data = [
			'provider' => $provider,
			'hosts' => $nameservers
		];
		
		// 注意:使用 PUT 方法,端点是 /domains/{domain}/nameservers
		return $this->request('PUT', '/domains/' . urlencode($domain) . '/nameservers', $data);
	}

    /**
     * 获取域名的 DNS 记录列表
     * 
     * @param string $domain 域名
     * @param int $take 每页数量
     * @param int $skip 跳过数量
     * @return array DNS 记录列表
     * @throws Exception
     */
    public function listDNSRecords(string $domain, int $take = 100, int $skip = 0, ?string $orderBy = null): array
    {
        $params = http_build_query([
            'take' => min($take, 100),
            'skip' => $skip
        ]);

        if ($orderBy !== null) {
            $params .= '&orderBy=' . urlencode($orderBy);
        }

        $endpoint = '/dns/records/' . urlencode($domain) . '?' . $params;
        return $this->request('GET', $endpoint);
    }
    
    /**
     * 创建 DNS 记录
     * 
     * @param string $domain 域名
     * @param array $records DNS记录数组
		 $records = [
			['type' => 'A', 'name' => 'dd', 'address' => '185.23.36.99', 'ttl' => 3600],
			['type' => 'A', 'name' => 'c', 'address' => '185.23.36.100', 'ttl' => 3600]
		];
     * @return array 操作结果
     * @throws Exception
     */
    public function createDNSRecords(string $domain, array $records): array
    {
        $data = [
            'force' => true,
            'items' => $records
        ];
        return $this->request('PUT', '/dns/records/' . urlencode($domain), $data);
    }
    
    /**
     * 删除 DNS 记录
     * 
     * @param string $domain 域名
     * @param array $records 要删除的记录列表
		$records = [
			['type' => 'A', 'name' => 'dd00', 'address' => '185.23.36.1', 'ttl' => 3600],
			['type' => 'A', 'name' => 'dd00', 'address' => '185.23.36.2', 'ttl' => 3600],
			['type' => 'A', 'name' => 'dd00', 'address' => '185.23.36.3', 'ttl' => 3600]
		];
     * @return array 操作结果
     * @throws Exception
     */
    public function deleteDNSRecords(string $domain, array $records): array
    {
        return $this->request('DELETE', '/dns/records/' . urlencode($domain), $records);
    }
    
    /**
     * 获取账户余额信息
     * 
     * @return array 账户余额
     * @throws Exception
     */
    public function getAccountBalance(): array
    {
        return $this->request('GET', '/billing/balance');
    }
    
    /**
     * 获取联系人信息
     * 
     * @param string $contactId 联系人ID
     * @return array 联系人详情
     * @throws Exception
     */
    public function getContact(string $contactId): array
    {
        return $this->request('GET', '/contacts/' . urlencode($contactId));
    }
    
    /**
     * 创建或更新联系人
     * 
     * @param array $contactData 联系人数据
     * @return array 操作结果
     * @throws Exception
     */
    public function saveContact(array $contactData): array
    {
        return $this->request('POST', '/contacts', $contactData);
    }
}

  下面提供一个简单的API调用示例,如下:

# 列出当前用户名下所有域名
$rtn = SpaceshipDomainAPI::Obj()->listDomains();
print_r($rtn);

# 根据域名zone_id查询当前域名解析记录
$domain = "example.com";
$nameservers = ['happy.ns.cloudflare.com','hello.ns.cloudflare.com'];
$rtn = SpaceshipDomainAPI::Obj()->updateNameservers($domain, $nameservers):
print_r($rtn);

  如果您在使用该封装类有任何问题,可留言给我,我会尽快回复

返回首页    发布日期:2026年06月11日

Copyright © 2026   楚狐在线   All Rights ReservedLA.   反馈留言