腾讯云域名云解析服务(DNS)API接口PHP封装
目前互联网上提供免费的域名托管服务的厂家很多,如阿里云/万网、腾讯云、CloudFlare、华为云等等,我们将域名托管到这些云解析DNS服务商后,虽然服务商都提供了控制台用于域名及解析记录的管理,但是有时候如果我们需要自己实现DDNS动态域名解析等一些基于官网API接口能力的功能,就需要使用到官网提供的API能力,本文将针对腾讯云的API接口,通过PHP封装了常用的函数类,用于托管域名、记录集等的管理。 本文旨在帮助开发者快速使用集成腾讯云域名云解析服务(DNS)的API接口,实现对域名(Zone)和解析记录(Record Set)的自动化管理,如域名托管、记录添加及修改等。 阿里云API官方文档地址详见:https://cloud.tencent.com/document/api/1427 下面是PHP实现的API封装类,代码如下:
/**
* 基于腾讯云API 3.0接口
* 调用方法示例:
* DNSPodDomainDNS::Obj()->DescribeRecordList('example.com');
* 参考文档
* 域名API文档:https://cloud.tencent.com/document/api/242
* 云解析API文档 :https://cloud.tencent.com/document/api/1427
* 引用或者使用本文,请注明来源:楚狐在线- https://chuhu.org
**/
class DNSPodDomainDNS
{
#下面为子账号apisdkuser的密钥
# 在https://console.cloud.tencent.com/cam 用户列表里面 建立子账号 设置密钥
private $secretId = "AK********************************";
private $secretKey = "******************************";
private static $obj = null;
public static function Obj ()
{
if(is_null(self::$obj))
{
self::$obj = new self();
}
return self::$obj;
}
//***********************以下为域名管理服务***********************//
//获取我在腾讯云注册的域名列表
public function DescribeDomainNameList()
{
$param1 = array('Limit'=>100);
$val = $this->requestDomain($param1, 'DescribeDomainNameList');
return $val;
//echo printJsonToHTML($val);
}
//获取域名基本信息(含域名DNS服务器)
public function DescribeDomainBaseInfo($Domain)
{
$param1 = array('Domain'=>$Domain);
$val = $this->requestDomain($param1, 'DescribeDomainBaseInfo');
return $val;
//echo printJsonToHTML($val);
}
//域名注册查询
//Period 年限。该参数为空时无法查询溢价词域名,如 '1',则显示溢价域名和溢价的价格
public function CheckDomain($Domain, $Period=null)
{
$param1 = array('DomainName'=>$Domain);
if(!empty($Period)) {
$param1['Period']=$Period;
};
$val = $this->requestDomain($param1, 'CheckDomain');
return $val;
//echo printJsonToHTML($val);
}
//批量域名 DNS 修改
//$domainName = ['example.net'];
//$domainNameServer = array('aaaaa.ns.cloudflare.com','bbbbb.ns.cloudflare.com');
public function ModifyDomainDNSBatch($Domains, $Dns)
{
$param1 = array('Domains'=>$Domains, 'Dns'=>$Dns);
$val = $this->requestDomain($param1, 'ModifyDomainDNSBatch');
return $val;
//echo printJsonToHTML($val);
}
//批量操作日志状态
//LogIds.N 是 Array of Integer [111]
public function CheckBatchStatus($LogIds)
{
$param1 = array('LogIds'=>$LogIds);
$val = $this->requestDomain($param1, 'CheckBatchStatus');
return $val;
//echo printJsonToHTML($val);
}
//********************************************************************************//
//********************************************************************************//
//********************************************************************************//
//***********************以上为域名管理、以下为域名DNS解析服务***********************//
//********************************************************************************//
//********************************************************************************//
//********************************************************************************//
//获取域名列表
public function DescribeDomainList()
{
$param1 = array('Type'=>'ALL');
$val = $this->requestDNSPod($param1, 'DescribeDomainList');
return $val;
}
//增加域名解析记录:增加单域名记录值
public function CreateRecord($Domain, $RR, $recordType, $value)
{
$param1 = array('Domain'=>$Domain,'SubDomain'=>$RR,'RecordLine'=>'默认','RecordType'=>$recordType,'Value'=>$value,'TTL'=>600);
$val = $this->requestDNSPod($param1,'CreateRecord');
return $val;
}
//增加域名解析记录:增加单域名记录值
public function CreateRecord2($Domain, $RR, $recordType, $value)
{
$param1 = array('Domain'=>$Domain,'SubDomain'=>$RR,'RecordLine'=>'默认','RecordType'=>$recordType,'Value'=>$value,'TTL'=>600);
$val = $this->requestDNSPod($param1,'CreateRecord');
return $val;
}
//更新域名解析记录:修改单域名记录值,实现DDNS
public function ModifyRecord($Domain, $recordId, $RR, $recordType, $value)
{
$param1 = array('Domain'=>$Domain,'SubDomain'=>$RR,'RecordId'=>$recordId,'RecordLine'=>'默认','RecordType'=>$recordType,'Value'=>$value);
$val = $this->requestDNSPod($param1,'ModifyRecord');
return $val;
}
//删除域名解析记录:删除单域名记录值,目前只能一个记录一个记录的删除。
public function DeleteRecord($Domain, $recordId)
{
$param1 = array('Domain'=>$Domain,'RecordId'=>$recordId);
$val = $this->requestDNSPod($param1,'DeleteRecord');
return $val;
}
//获取域名的解析记录列表:获取当前域名的所有解析记录
public function DescribeRecordList($Domain)
{
$param1 = array('Domain'=>$Domain);
$val = $this->requestDNSPod($param1,'DescribeRecordList');
return $val;
}
//获取记录信息:根据ID获取某个记录的解析值
public function DescribeRecord($Domain, $RecordId)
{
$param1 = array('Domain'=>$Domain,'RecordId'=>$RecordId);
$val = $this->requestDNSPod($param1,'DescribeRecord');
return $val;
}
//获取记录信息:根据Subdomain获取某个记录的解析值
//若不指定$RecordType,传入参数null
public function DescribeRecordBySubdomain($Domain, $Subdomain, $RecordType)
{
if($RecordType==null || $RecordType=="") {
$param1 = array('Domain'=>$Domain,'Subdomain'=>$Subdomain);
} else {
$param1 = array('Domain'=>$Domain,'Subdomain'=>$Subdomain,'RecordType'=>$RecordType);
}
$val = $this->requestDNSPod($param1,'DescribeRecordList');
return $val;
}
//DDNS更新处理,若域名记录不存在,则直接创建 (DDNS主用)
//$Domain 主域名
//$Domain 耳机域名名称,不需要完整的。
//主要用于DDNS的更新
//与UpdateDNSRecord传入参数一样,增加了记录值是否存在的判断。
public function ModifyDynamicDNS($RR,$Domain, $value, $type="A")
{
//查出主域名下记录,看是否子域名的解析记录。
$data = $this->DescribeRecordList2($Domain);
$data = json_decode($data,true);
$data = array_filter($data['Response']['RecordList'], function($item) use ($RR, $type) {
return $item['Name'] === $RR && $item['Type'] === $type;
});
$data = array_values($data); //重构数组,删除空
$rc = count($data);
if($rc==0)
{
//没有记录, 创建按记录。
$rtn = $this->CreateRecord2($Domain, $RR, $type, $value);
$rtn = json_decode($rtn,true);
if(count(array_column($rtn,'Error'))==1){
echo "域名".$RR.".".$Domain."的".$type."记录不存在,创建失败。";
}else {
echo "域名".$RR.".".$Domain."创建成功,并配置".$type."记录为:".$value;
}
}
else if($rc>1)
{
echo "域名".$RR.".".$Domain."的".$type."记录有".$rc."条,更新记录失败!";
} else {
if($data[0]['Value']==$value){
echo "处理完成:".$RR.".".$Domain."当前".$data[0]['Type']."记录【".$data[0]['Value']."】与新值【".$value."】一致,无需修改。";
} else {
$param1 = array('Domain'=>$Domain,'SubDomain'=>$RR,'RecordId'=>$data[0]['RecordId'],'RecordLine'=>'默认','Value'=>$value);
$val = $this->requestDNSPod($param1,'ModifyDynamicDNS');
$val = json_decode($val,true);
if(count(array_column($val,'Error'))==1)
{
echo "处理失败:".$val['Response']['Error']['Message'];
}
else
{
if($RR=="@")
{
echo "处理完成:".$Domain."的".$type."记录【".$data[0]['Value']."】已修改为【".$value."】。";
}
else
{
echo "处理完成:".$RR.".".$Domain."的".$type."记录【".$data[0]['Value']."】已修改为【".$value."】。";
}
}
}
}
}
//更新动态 DNS 记录:
public function ModifyDynamicDNS2($Domain, $recordId, $RR, $value)
{
$param1 = array('Domain'=>$Domain,'SubDomain'=>$RR,'RecordId'=>$recordId,'RecordLine'=>'默认','Value'=>$value);
$val = $this->requestDNSPod($param1,'ModifyDynamicDNS');
return $val;
}
//删除单个域名下的所有解析记录
function DeleteRecordList($Domain)
{
//查询源域名记录
$data = $this->DescribeRecordList2($Domain);
$data = json_decode($data,true);
//print_r($data);
if(count(array_column($data,'Error'))==1)
{
echo "域名【".$Domain."】当前主机记录列表为空,无需删除!";
return;
}
$ListCount = $data['Response']['RecordCountInfo']['ListCount'];
echo "下面将删除域名【".$Domain."】的".$ListCount."条记录:
\n";
foreach($data['Response']['RecordList'] as $v)
{
$rtn = $this->DeleteRecord2($Domain, $v['RecordId']);
$rtn = json_decode($rtn,true);
if(count(array_column($rtn,'Error'))==1)
{
echo "域名 ".$Domain." 的主机 ".$v['Name']." 的 ".$v['Type']." 记录[ ".$v['Value']." ]删除失败:".$rtn['Response']['Error']['Message']."(Code:".$rtn['Response']['Error']['Code'].")
\n";
}
else
{
echo "域名 ".$Domain." 的主机 ".$v['Name']." 的 ".$v['Type']." 记录[ ".$v['Value']." ]删除成功(RecordId=".$v['RecordId'].")。
\n";
}
}
}
//***********************以上为域名DNS解析服务***********************//
//构建腾讯云 域名注册 API 3.0 版本请求方法
private function requestDomain($param,$action)
{
$timestamp = time();
$region = "ap-chengdu";
$version = "2018-08-08";
$algorithm = "TC3-HMAC-SHA256";
$service = "domain";
//$host = "domain.tencentcloudapi.com"; //就近地域接入(推荐,只支持非金融区)
$host = "domain.ap-chengdu.tencentcloudapi.com"; //西南地区(成都)
// step 1: build canonical request string
$httpRequestMethod = "POST";
$canonicalUri = "/";
$canonicalQueryString = "";
$canonicalHeaders = "content-type:application/json\n"."host:".$host."\n";
$signedHeaders = "content-type;host";
$payload = json_encode($param); //php5.6以上才要加第二个参数
$hashedRequestPayload = hash("SHA256", $payload);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
// echo $canonicalRequest.PHP_EOL;
// step 2: build string to sign
$date = gmdate("Y-m-d", $timestamp);
$credentialScope = $date."/".$service."/tc3_request";
$hashedCanonicalRequest = hash("SHA256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$timestamp."\n"
.$credentialScope."\n"
.$hashedCanonicalRequest;
// echo $stringToSign.PHP_EOL;
// step 3: sign string
$secretDate = hash_hmac("SHA256", $date, "TC3".$this->secretKey, true);
$secretService = hash_hmac("SHA256", $service, $secretDate, true);
$secretSigning = hash_hmac("SHA256", "tc3_request", $secretService, true);
$signature = hash_hmac("SHA256", $stringToSign, $secretSigning);
// echo $signature.PHP_EOL;
// step 4: build authorization
$authorization = $algorithm
." Credential=".$this->secretId."/".$credentialScope
.", SignedHeaders=content-type;host, Signature=".$signature;
// echo $authorization.PHP_EOL;
$url = "https://".$host;
$header[] = "Authorization:".$authorization;
$header[] = "Content-Type:application/json";
$header[] = "Host:".$host;
$header[] = "X-TC-Action:".$action;
$header[] = "X-TC-Timestamp:".$timestamp;
$header[] = "X-TC-Version:".$version;
$header[] = "X-TC-Region:".$region;
$header[] = "X-TC-Language:zh-CN";
$res = $this->CurlRequest($url,'post',$payload,$header);
return $res;
}
//构建腾讯云 DNSPod API 3.0 版本请求方法
private function requestDNSPod($param,$action)
{
$timestamp = time();
$region = "ap-chengdu";
$version = "2021-03-23";
$algorithm = "TC3-HMAC-SHA256";
$service = "dnspod";
//$host = "dnspod.tencentcloudapi.com"; //就近地域接入(推荐,只支持非金融区)
$host = "dnspod.ap-chengdu.tencentcloudapi.com"; //西南地区(成都)
// step 1: build canonical request string
$httpRequestMethod = "POST";
$canonicalUri = "/";
$canonicalQueryString = "";
$canonicalHeaders = "content-type:application/json\n"."host:".$host."\n";
$signedHeaders = "content-type;host";
$payload = json_encode($param); //php5.6以上才要加第二个参数
$hashedRequestPayload = hash("SHA256", $payload);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
// echo $canonicalRequest.PHP_EOL;
// step 2: build string to sign
$date = gmdate("Y-m-d", $timestamp);
$credentialScope = $date."/".$service."/tc3_request";
$hashedCanonicalRequest = hash("SHA256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$timestamp."\n"
.$credentialScope."\n"
.$hashedCanonicalRequest;
// echo $stringToSign.PHP_EOL;
// step 3: sign string
$secretDate = hash_hmac("SHA256", $date, "TC3".$this->secretKey, true);
$secretService = hash_hmac("SHA256", $service, $secretDate, true);
$secretSigning = hash_hmac("SHA256", "tc3_request", $secretService, true);
$signature = hash_hmac("SHA256", $stringToSign, $secretSigning);
// echo $signature.PHP_EOL;
// step 4: build authorization
$authorization = $algorithm
." Credential=".$this->secretId."/".$credentialScope
.", SignedHeaders=content-type;host, Signature=".$signature;
// echo $authorization.PHP_EOL;
$url = "https://".$host;
$header[] = "Authorization:".$authorization;
$header[] = "Content-Type:application/json";
$header[] = "Host:".$host;
$header[] = "X-TC-Action:".$action;
$header[] = "X-TC-Timestamp:".$timestamp;
$header[] = "X-TC-Version:".$version;
$header[] = "X-TC-Region:".$region;
$header[] = "X-TC-Language:zh-CN";
$res = $this->CurlRequest($url,'post',$payload,$header);
return $res;
}
//发送请求方法
private function CurlRequest($url,$type = null,$data=null,$header=null)
{
//初始化浏览器
$ch = curl_init();
//设置浏览器,把参数url传到浏览器的设置当中
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_NOBODY, false);
//以字符串形式返回到浏览器当中
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//禁止https协议验证域名,0就是禁止验证域名且兼容php5.6
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
//禁止https协议验证ssl安全认证证书
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//判断data是否有数据,如果有data数据传入那么就把curl的请求方式设置为POST请求方式
if ( !empty($data) ) {
switch ($type) {
case 'get':
//设置POST请求方式
@curl_setopt($curl, CURLOPT_HTTPGET, true);
break;
case 'post':
//设置POST请求方式
@curl_setopt($ch, CURLOPT_POST, true);
//设置POST的数据包
@curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
break;
case 'put':
//设置PUT请求方式
@curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"PUT");
//设置POST的数据包
@curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
break;
case 'delete':
//设置POST请求方式
@curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
//设置POST的数据包
@curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
break;
default:
//设置POST请求方式
@curl_setopt($ch, CURLOPT_POST, true);
//设置POST的数据包
@curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
break;
}
}
//设置header头
if ( !empty($header) ) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
}
//让curl发起请求
$httpCode = curl_exec($ch);
$errorCode = curl_errno($ch);
//关闭curl浏览器
curl_close($ch);
if(0 !== $errorCode) {
return false;
}
//把请求回来的数据返回
//return json_decode($httpCode,true); //用output输出,不编码
return $httpCode;
}
}
下面提供一个简单的API调用示例,如下:
# 获取我在腾讯云注册的域名列表
$rtn = DNSPodDomainDNS::Obj()->DescribeDomainNameList();
print_r($rtn);
# 获取当前域名的所有解析记录
$Domain = "example.com";
$rtn = DNSPodDomainDNS::Obj()->DescribeRecordList($Domain);
print_r($rtn);
通过这个PHP封装类,我就可以用自己的域名,在自己的家庭网络设备如NAS上实现家里宽带的动态域名解析了,您可以创建一个ddns.php文件,核心代码如下:
//引入前面的类文件
require_once($_SERVER['DOCUMENT_ROOT'].'/DNSPodDomainDNS-inc.php');
#获取当前客户端的ip
$REMOTE_ADDR = $_SERVER['REMOTE_ADDR'];
//IPv4地址更新
if(filter_var($REMOTE_ADDR, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
{
DNSPodDomainDNS::Obj()->ModifyDynamicDNS("@","ddns.example.com",$REMOTE_ADDR,"A");
}
//IPv6地址更新
if(filter_var($REMOTE_ADDR, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
{
DNSPodDomainDNS::Obj()->ModifyDynamicDNS("@","ddns.example.com",$REMOTE_ADDR,"AAAA");
}
如果您在使用该封装类有任何问题,可留言给我,我会尽快回复。 |