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);
如果您在使用该封装类有任何问题,可留言给我,我会尽快回复。 |