Cloudflare域名云解析服务(DNS)API接口PHP封装
目前互联网上提供免费的域名托管服务的厂家很多,如阿里云/万网、腾讯云、CloudFlare、华为云等等,我们将域名托管到这些云解析DNS服务商后,虽然服务商都提供了控制台用于域名及解析记录的管理,但是有时候如果我们需要自己实现DDNS动态域名解析等一些基于官网API接口能力的功能,就需要使用到官网提供的API能力,本文将针对Cloudflare的API接口,通过PHP封装了常用的函数类,用于托管域名、记录集等的管理。 本文旨在帮助开发者快速使用集成Cloudflare域名云解析服务(DNS)的API接口,实现对域名(Zone)和解析记录(Record Set)的自动化管理,如域名托管、记录添加及修改等。 阿里云API官方文档地址详见:https://developers.cloudflare.com/api/resources/dns/subresources/records 下面是PHP实现的API封装类,代码如下:
//************************开始Cloudflare的解析处理******************************//
/**
* Cloudflare的域名DNS云解析API封装类
* api文档地址:https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-list-dns-records
* 引用或者使用本文,请注明来源:楚狐在线- https://chuhu.org
**/
class DNSCloudflare
{
//x_api_token、x_auth_key 在request_post函数里面切换,当前用API 令牌x_api_token
// API 令牌,获取步骤:我的个人资料 > API 令牌 > 上面的API 令牌 > 创建令牌 > 编辑区域 DNS (使用模板)
// API 密钥 Global API Key,获取步骤:My profile > API Tokens > 下面的API Keys > Global API Key > View
private $x_api_token = '*************';
private $x_account_id = '*********';
private $x_email = 'example@example.com'; // 您的cf注册邮箱地址
protected static $obj = null;
public static function Obj ()
{
//if(is_null(self::$obj)) //2025年4月27日
if(is_null(static::$obj))
{
self::$obj = new self();
}
return self::$obj;
}
// 允许构造方法初始化 token 2025年4月27日增加
protected function __construct($para = null) {
if ($para === "OTHER_ACCOUNT") {
$this->x_api_token = 'Gl*******************';
$this->x_account_id = '***********';
$this->x_email = 'OTHER_ACCOUNT@example.com';
}
}
//列出当前用户名下所有域名,返回数组
//数组内容包括:域名name,域名id,域名状态status
//不翻页,默认显示100个
//与ZonesList差异:只显示域名,id,状态三个内容,其他的不显示
public function DomainListAll()
{
$curl_url = "https://api.cloudflare.com/client/v4/zones?page=1&per_page=100";
$curl_request = "GET";
$rtn = $this->request_post($curl_url,$curl_request);
$dml = $rtn['result'];
$final_list = array();
foreach ($dml as $k => $oneZone) {
$final_list[] = array(
'domain' => strtolower($oneZone['name']),
'id' => $oneZone['id'],
'status' => $oneZone['status']
);
}
return $final_list;
}
//查询域名的对应zond_id
public function DomainIDQuery($domain)
{
$dmid = null;
$curl_url = "https://api.cloudflare.com/client/v4/zones?page=1&per_page=100";
$curl_request = "GET";
$rtn = $this->request_post($curl_url,$curl_request);
$dml = $rtn['result'];
$final_list = array();
foreach ($dml as $k => $oneZone) {
if(strtolower($oneZone['name'])==strtolower($domain))
{
$dmid = $oneZone['id'];
}
}
return $dmid;
}
//根据域名zone_id查询当前域名解析记录
//返回数组
public function DNSRecordsList($zone_id)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/dns_records";
$curl_request = "GET";
$rtn = $this->request_post($curl_url,$curl_request);
//print_r($rtn);
return $rtn;
}
//根据域名zone_id、记录ID查询当前域名解析记录
//返回数组
public function DNSRecordDetails($zone_id, $dns_record_id)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/dns_records/".$dns_record_id;
$curl_request = "GET";
$rtn = $this->request_post($curl_url,$curl_request);
//print_r($rtn);
return $rtn;
}
//创建新记录
//$domain_name 完整的二级或三级域名
//返回数组
public function CreateDNSRecord($zone_id, $domain_name, $content, $type="A", $proxied=false, $ttl=60, $comment="")
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/dns_records";
$curl_request = "POST";
$data = array(
'comment' => $comment,
'content' => $content,
'name' => $domain_name,
'proxied' => $proxied, // true启用代理,false禁用代理
'type' => $type,
'ttl' => $ttl // 数字1代表自动ttl
);
$rtn = $this->request_post($curl_url,$curl_request,$data);
return $rtn;
}
//删除DNS Record
//$domain_name 完整的二级或三级域名
//返回数组
public function DeleteDNSRecord($zone_id, $dns_record_id)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/dns_records/".$dns_record_id;
$curl_request = "DELETE";
$rtn = $this->request_post($curl_url,$curl_request);
return $rtn;
}
//DDNS更新处理,首先查询域名解析记录是否一致
//$domain_name 完整的二级或三级域名
//主要用于DDNS的更新
//与UpdateDNSRecord传入参数一样,增加了记录值是否存在的判断。
public function ModifyDynamicDNS($zone_id,$dns_record_id,$domain_name,$new_ip,$type,$proxied,$ttl)
{
$data = $this->DNSRecordDetails($zone_id, $dns_record_id);
if($data['success'])
{
if($data['result']['content']==$new_ip)
{
echo "处理完成:".$domain_name."当前".$data['result']['type']."记录【".$data['result']['content']."】与新值【".$new_ip."】一致,无需修改。";
}
else
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/dns_records/".$dns_record_id;
$curl_request = "PUT";
$data1 = array(
'content' => $new_ip,
'name' => $domain_name,
'proxied' => $proxied, // true启用代理,false禁用代理
'type' => $type,
'ttl' => $ttl // 数字1代表自动ttl
);
$rtn = $this->request_post($curl_url,$curl_request,$data1);
if($rtn['success'])
{
echo "处理完成:".$domain_name."的".$data['result']['type']."记录【".$data['result']['content']."】已修改为【".$new_ip."】。";
}
else
{
echo "处理失败:".$rtn['errors'][0]['message']."(code=".$rtn['errors'][0]['code'].")";
}
}
} else {
echo "错误:".$data['errors'][0]['message']."(code=".$data['errors'][0]['code'].")";
}
}
//DDNS更新处理,若域名记录不存在,则直接创建 (DDNS主用)
//$domain_name 完整的二级或三级域名
//$sub_domain 只要名称,不需要完整的。
//主要用于DDNS的更新
//与UpdateDNSRecord传入参数一样,增加了记录值是否存在的判断。
public function ModifyDynamicDNS2($sub_domain,$domain_name,$new_ip,$type="A",$proxied=false,$ttl=60)
{
if($sub_domain=="@"){
$sub_domain = $domain_name;
} else {
$sub_domain = $sub_domain.".".$domain_name;
}
$zone_id = $this->DomainIDQuery($domain_name);
$RecordsList = $this->DNSRecordsList($zone_id);
$data = array_filter($RecordsList['result'], function($item) use ($sub_domain, $type) {
return $item['name'] === $sub_domain && $item['type'] === $type;
});
$data = array_values($data); //重构数组,删除空
$rc = count($data);
if($rc==0)
{
//没有记录, 创建按记录。
$rtn = $this->CreateDNSRecord($zone_id, $sub_domain, $new_ip, $type, $proxied, $ttl);
if($rtn['success'])
{
echo "域名".$sub_domain."创建成功,并配置".$type."记录为:".$new_ip;
}
}
else if($rc>1)
{
echo "域名".$sub_domain."的".$type."记录有".$rc."条,更新记录失败!";
} else {
$dns_record_id = $data[0]['id'];
if($data[0]['content']==$new_ip){
echo "处理完成:".$sub_domain."当前".$data[0]['type']."记录【".$data[0]['content']."】与新值【".$new_ip."】一致,无需修改。";
} else {
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/dns_records/".$dns_record_id;
$curl_request = "PUT";
$data1 = array(
'content' => $new_ip,
'name' => $sub_domain,
'proxied' => $proxied, // true启用代理,false禁用代理
'type' => $type,
'ttl' => $ttl // 数字1代表自动ttl
);
$rtn = $this->request_post($curl_url,$curl_request,$data1);
if($rtn['success'])
{
echo "处理完成:".$sub_domain."的".$data[0]['type']."记录【".$data[0]['content']."】已修改为【".$new_ip."】。";
}
else
{
echo "处理失败:".$rtn['errors'][0]['message']."(code=".$rtn['errors'][0]['code'].")";
}
}
}
}
//查询当前账户下的所有域及每个域的详细信息,List Zones,返回数组
//$zone_id 为空则输出当前账号下所有域名
public function ZonesList($zone_id=null)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones";
if(!empty($zone_id))
{
$curl_url = $curl_url."/".$zone_id;
} else
{
$curl_url = $curl_url."?page=1&per_page=100";
}
$curl_request = "GET";
$rtn = $this->request_post($curl_url,$curl_request);
return $rtn;
}
//查询当前账户下的所有域及每个域的详细信息,List Zones,输出为html
public function ZonesListHtml()
{
$curl_url = "https://api.cloudflare.com/client/v4/zones";
if(!empty($zone_id))
{
$curl_url = $curl_url."/".$zone_id;
} else
{
$curl_url = $curl_url."?page=1&per_page=100";
}
$curl_request = "GET";
$this->request_post_html($curl_url,$curl_request);
}
//根据$zone_id查询该域名下的所有DNS解析记录,List DNS Records,输出html
public function DNSRecordsListHTML($zone_id)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/dns_records";
$curl_request = "GET";
$this->request_post_html($curl_url,$curl_request);
}
//Update DNS Record,输入为html
//$domain_name 完整的二级或三级域名
//根据传入的$new_ip,$type,$proxied,$ttl,更新域名记录
public function UpdateDNSRecordHtml($zone_id,$dns_record_id,$domain_name,$new_ip,$type,$proxied,$ttl)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/dns_records/".$dns_record_id;
$curl_request = "PUT";
$data = array(
'content' => $new_ip,
'name' => $domain_name,
'proxied' => $proxied, // true启用代理,false禁用代理
'type' => $type,
'ttl' => $ttl // 数字1代表自动ttl
);
$this->request_post_html($curl_url,$curl_request,$data);
}
//Update DNS Record,返回数组
//$domain_name 完整的二级或三级域名
//根据传入的$new_ip,$type,$proxied,$ttl,更新域名记录
public function UpdateDNSRecord($zone_id,$dns_record_id,$domain_name,$new_ip,$type,$proxied,$ttl)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/dns_records/".$dns_record_id;
$curl_request = "PUT";
$data = array(
'content' => $new_ip,
'name' => $domain_name,
'proxied' => $proxied, // true启用代理,false禁用代理
'type' => $type,
'ttl' => $ttl // 数字1代表自动ttl
);
$rtn = $this->request_post($curl_url,$curl_request,$data);
return $rtn;
}
//增加域名 Create Zone
public function CreateZone($domain)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones";
$curl_request = "POST";
$accid = array( 'id' => "{$this->x_account_id}" );
$data = array(
'account' => $accid,
'name' => $domain,
'type' => "full"
);
$rtn = $this->request_post($curl_url,$curl_request,$data);
return $rtn;
}
//删除域名 Delete Zone
public function DeleteZone($zone_id)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id;
$curl_request = "DELETE";
$rtn = $this->request_post($curl_url,$curl_request);
return $rtn;
}
//增加域名 Edit Zone
//dns 为dns数组 $dns = array('ns1.nishui.com','ns2.nishui.com');
public function EditZoneDNS($zone_id, $dns)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id;
$curl_request = "PATCH";
$data = array(
'type' => "full",
'vanity_name_servers' => $dns
);
$rtn = $this->request_post($curl_url,$curl_request,$data);
return $rtn;
}
//域名激活检查 Activation Check
//返回true or false
//注意:每小时每个域名执行一次,否则返回false:You may only perform this action once per hour.
public function ZoneActivationCheck($zone_id)
{
$curl_url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/activation_check";
$curl_request = "PUT";
$rtn = $this->request_post($curl_url,$curl_request);
if($rtn['success'])
{
if($rtn['messages'][0]['code']=='10002') return true;
else return false;
}
else
{
return false;
}
}
/**
* 批量操作 DNS 记录 (创建、修改、删除)
* 调用方法如下
BatchDNSRecords($zone_id, $adds, $updates, $deletes);
BatchDNSRecords($zone_id, $adds, [], []);
BatchDNSRecords($zone_id, [], $updates, []);
BatchDNSRecords($zone_id, [], [], $deletes);
* 参考官方文档: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/batch
* * @param string $zone_id 区域ID ,可以用 DomainIDQuery($domain) 获取
* @param array $adds 需要新增的记录数组,每项包含: name, type, content, ttl(可选), proxied(可选), comment(可选),格式参考如下:
$adds = [
[
'name' => 'test1.truhoo.win',
'type' => 'A',
'content' => '1.1.1.1',
'proxied' => false,
'ttl' => 60
],
];
* @param array $updates 需要修改的记录数组,每项包含: id, name, type, content, ttl(可选), proxied(可选), comment(可选) (在批量中官方底层通常对应 puts/patches),格式参考如下:
$updates = [
[
'id' => 'c988db3fe4dab0b159ba1066f9bdc12f', //除了ID其他的都可以修改。
'name' => 't21.truhoo.win',
'type' => 'A',
'content' => '3.3.13.13',
'proxied' => false,
'comment' => 'comment',
'ttl' => 60
],
];
* @param array $deletes 需要删除的记录数组,每项包含: id,格式参考如下:
$deletes = [
['id' => '57ffb097803f56cf6653c1552b476411'],
['id' => '8a46ced175ef3721819185a791a8b17e'],
];
* @return array 返回 API 请求结果
**/
public function BatchDNSRecords($zone_id, $adds = [], $updates = [], $deletes = [])
{
$url = "https://api.cloudflare.com/client/v4/zones/".$zone_id."/dns_records/batch";
$payload = array();
// 1. 批量增加:官方最新文档规定的键名为 'posts' (注意不是 adds)
if (is_array($adds) && !empty($adds)) {
$payload['posts'] = array_values($adds);
}
// 2. 批量局部修改:官方键名为 'patches'
if (is_array($updates) && !empty($updates)) {
$payload['patches'] = array_values($updates);
}
// 3. 批量删除:官方键名为 'deletes'
if (is_array($deletes) && !empty($deletes)) {
$payload['deletes'] = array_values($deletes);
}
// 如果三个操作全是空的,直接拦截,不浪费 API 请求
if (empty($payload)) {
return array("success" => false, "errors" => [["code" => 0, "message" => "未传入任何操作数据"]]);
}
// 强行转换为严格的 JSON 字符串
$json_data = json_encode($payload);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"Content-Length: " . strlen($json_data),
"Authorization: Bearer {$this->x_api_token}",
"X-Auth-Email: {$this->x_email}"
]);
$response = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);
if ($err) {
return array("success" => false, "errors" => [["code" => 0, "message" => "cURL 错误: " . $err]]);
} else {
return (array) json_decode($response, true);
}
}
//构建cloudflare请求参数,返回数组
//$url:请求的地址
//$param:请求的方法:GET,PUT,PATCH
//$data=null:请求参数,array,可以为null
function request_post($url, $param, $data=null)
{
if (empty($url) || empty($param))
{
return "缺少必要的URL地址或request参数!";
exit;
}
$curl = curl_init();
$setopts = array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $param,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
//"X-Auth-Key: {$this->x_auth_key}",
"Authorization: Bearer {$this->x_api_token}",
"X-Auth-Email: {$this->x_email}"]
);
if(isset($data))
{
$setopts[CURLOPT_POSTFIELDS] = json_encode($data);
}
curl_setopt_array($curl, $setopts);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
return "发生错误#:" . $err;
} else {
return (array) json_decode($response,true);
}
}
// 将request_post的方法结果输出为html文本
function request_post_html($url, $param, $data=null)
{
$response = $this->request_post($url, $param, $data) ;
$response = json_encode($response);
echo printJsonToHTML($response);
}
}
下面提供一个简单的API调用示例,如下:
# 列出当前用户名下所有域名
$rtn = DNSCloudflare::Obj()->DomainListAll();
print_r($rtn);
# 根据域名zone_id查询当前域名解析记录
$zone_id = "****************";
$rtn = DNSCloudflare::Obj()->DNSRecordsList($zone_id);
print_r($rtn);
通过这个PHP封装类,我就可以用自己的域名,在自己的家庭网络设备如NAS上实现家里宽带的动态域名解析了,您可以创建一个ddns.php文件,核心代码如下:
//引入前面的类文件
require_once($_SERVER['DOCUMENT_ROOT'].'/DNSCloudflare-inc.php');
#获取当前客户端的ip
$REMOTE_ADDR = $_SERVER['REMOTE_ADDR'];
//IPv4地址更新
if(filter_var($REMOTE_ADDR, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
{
DNSCloudflare::Obj()->ModifyDynamicDNS2("","example.com",$REMOTE_ADDR,"A");
}
//IPv6地址更新
if(filter_var($REMOTE_ADDR, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
{
DNSCloudflare::Obj()->ModifyDynamicDNS2("","example.com",$REMOTE_ADDR,"AAAA");
}
如果您在使用该封装类有任何问题,可留言给我,我会尽快回复。 |