用腾讯云"云API"和PHP写一个查找域名是否可注册的API

初衷

想对接企业微信,或者做一个简单的HTML单页,比起开官网和小程序查快多了。

在批量查询时,可以直接通过Python调用,比起官网的批量查询要灵活得多(官网的还要先用Python生成列表再复制,而且一次查太多网页还容易出问题)。

PHP部署方便,而且腾讯云云API调用有每秒频次限制,不需要多快,很适用。

比起每个应用独自调用腾讯云API去折腾SDK或者签名流程,套一层后只需传入域名即可查询,显然要方便很多。

代码

<?php
    // 请求外部资源
    // 参数:$url,字符串。$post,array。$httpheader,字符数组。
    function getHttpResponse_h($url, $post = false,$httpheader, $timeout = 10){
       // 要先用json_encode()处理,不然就是表单而不是json数据了
       // 传入的数据里要带上Content-Type,标明是application/json
        $po = json_encode($post);
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
//         $httpheader[] = "Accept: */*";
//         $httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
//         $httpheader[] = "Connection: close";
        
        curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        if($post){
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $po);
        }
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
if((!isset($_GET['domain'])or($_GET['domain'] == ""))){
    echo "无参数";
    exit;
}    
$domainname = $_GET['domain'];

$secretId = "填写自己的";
$secretKey = "填写自己的";
$host = "domain.tencentcloudapi.com";
$service = "domain";
$version = "2018-08-08";
$action = "CheckDomain";
$region = "ap-guangzhou";
$timestamp = time();
// $timestamp = 1662042540;
$algorithm = "TC3-HMAC-SHA256";

// step 1: build canonical request string
$httpRequestMethod = "POST";
$canonicalUri = "/";
$canonicalQueryString = "";
$canonicalHeaders = "content-type:application/json"."\n"."host:".$host."\n";
$signedHeaders = "content-type;host";
$payload = '{"DomainName":"'.$domainname.'"}';
$hashedRequestPayload = hash("SHA256", $payload);
$canonicalRequest = $httpRequestMethod."\n"
    .$canonicalUri."\n"
    .$canonicalQueryString."\n"
    .$canonicalHeaders."\n"
    .$signedHeaders."\n"
    .$hashedRequestPayload;
// echo $canonicalRequest.PHP_EOL;
// echo "<br><br>";

// 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;
// echo "<br><br>";

// step 3: sign string
$secretDate = hash_hmac("SHA256", $date, "TC3".$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;
// echo "<br><br>";

// step 4: build authorization
$authorization = $algorithm
    ." Credential=".$secretId."/".$credentialScope
    .", SignedHeaders=content-type;host, Signature=".$signature;
// echo $authorization.PHP_EOL;
// echo "<br><br>";

$curl = "curl -X POST https://".$host
    .'<br>{"Authorization": "'.$authorization.'",<br>'
    .'"Content-Type": "application/json",<br>'
    .'"Host": "'.$host.'",<br>'
    .'"X-TC-Action": "'.$action.'",<br>'
    .'"X-TC-Timestamp": "'.$timestamp.'",<br>'
    .'"X-TC-Version": "'.$version.'",<br>'
    .'"X-TC-Region": "'.$region.'"}<br>'
    ." -d '".$payload."'";
// echo $curl.PHP_EOL;

$he = ['Authorization: '.$authorization,
    'Content-Type: application/json',
    'Host: '.$host,
    'X-TC-Action: '.$action,
    'X-TC-Timestamp: '.$timestamp,
    'X-TC-Version: '.$version,
    'X-TC-Region: '.$region];
    
$post_data = array("DomainName" => $domainname);
        
        $output = getHttpResponse_h($url = "https://".$host,$post = $post_data,$httpheader = $he);
// echo($output);

$outjson = json_decode($output,true);
$is_no = $outjson['Response']['Available'];

// $ResponseDat = $outjson['Response'];
// echo json_encode($ResponseDat);

// 判断有无错误消息
if(!isset($outjson['Response']['Error'])){
    if($is_no == false){
        echo("已注册");
    }elseif ($is_no == true) {
        echo("未注册");
    }
}else{
    echo($outjson['Response']['Error']['Code']);
}

代码升级

腾讯云云API每秒10次的调用限制很容易碰上。
唯一的解决方法是准备多个账号,但账号分配成了问题。

使用场景:个人使用

均匀分配

统计每个账户调用次数,每次选择最小的使用。
问题:还得弄数据库什么的,太麻烦。

随机(入选)

每次随机选一个账户访问
问题:脸黑的人可能10次都是同一个

超限自动切换

如果超出限制了,自动切换另一个账号再次调用。
问题:这个有点离题了,因为目标是避开限制,节省多次请求消耗的时间,而不是遇到限制如何处理。搭配其他的使用倒是不错。

代码

如果多个账户要按需修改(随机数生成和列表两地方)
$domainname = $_GET['domain'];
$acc_id_list = [["账户一secretId","账户一secretKey "],["账户二secretId","账户二secretKey "]];
$indexP = rand(0,1);
$secretId = $acc_id_list[$indexP][0];
$secretKey = $acc_id_list[$indexP][1];

$host = "domain.tencentcloudapi.com";

API返回值研究(部分)

错误返回值

常见的就两种,一种是签名错误,这个一般在早期出现:

{
    "Response": {
        "Error": {
            "Code": "AuthFailure.SignatureFailure",
            "Message": "The provided credentials could not be validated. Please check your signature is correct."
        },
        "RequestId": "9920bce6-81de-4f2c-bd22-7f95eaad28d8"
    }
}

一种是每秒调用数超出限制,这个比较常见:

{
    "Response": {
        "Error": {
            "Code": "RequestLimitExceeded",
            "Message": "Your current request times equals to `28` in a second, which exceeds the frequency limit `10` for a second. Please reduce the frequency of calls."
        },
        "RequestId": "fd5f460b-3eb7-4a48-a00b-4a39b3fee63b"
    }
}

域名无法注册的返回值

常见的有两种,一种是被注册了没法注册

"该域名已被注册,请选择其他域名"
{
    "Response": {
        "DomainName": "ius.cn",
        "FeeTransfer": 0,
        "RequestId": "2957fcbd-bfb9-48c8-a867-e0a9956d26ec",
        "RealPrice": 29,
        "BlackWord": false,
        "FeeRenew": 0,
        "Available": false,
        "Premium": false,
        "RecordSupport": true,
        "Price": 35,
        "Describe": "",
        "FeeRestore": 0,
        "Period": 1,
        "Reason": "\u8be5\u57df\u540d\u5df2\u88ab\u6ce8\u518c\uff0c\u8bf7\u9009\u62e9\u5176\u4ed6\u57df\u540d"
    }
}

一种是含敏感词无法注册(至少在腾讯云无法注册,别的平台不清楚),但要注意,这只能说明这个域名有敏感词,不能说明没有被注册,腾讯云的逻辑是先检查敏感与否再检查是否被注册了。

"域名包含敏感词不可注册,请选择其他域名"
{
    "Response": {
        "DomainName": "xxx.cn",
        "FeeTransfer": 0,
        "RequestId": "398ad69e-32fb-4286-908a-05f684e755f6",
        "RealPrice": 29,
        "BlackWord": true,
        "FeeRenew": 0,
        "Available": false,
        "Premium": false,
        "RecordSupport": true,
        "Price": 35,
        "Describe": "",
        "FeeRestore": 0,
        "Period": 1,
        "Reason": "\u57df\u540d\u5305\u542b\u654f\u611f\u8bcd\u4e0d\u53ef\u6ce8\u518c\uff0c\u8bf7\u9009\u62e9\u5176\u4ed6\u57df\u540d"
    }
}

编写笔记

通过curl发送json格式数据的post请求(发送表单数据按代码注释修改)

// 请求外部资源
// 参数:$url,字符串。$post,array。$httpheader,字符数组。
function getHttpResponse_h($url, $post = false,$httpheader, $timeout = 10) {
    // 要先用json_encode()处理,不然就是表单而不是json数据了
    // 传入的数据里要带上Content-Type,标明是application/json
    $po = json_encode($post);
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    //         $httpheader[] = "Accept: */*";
    //         $httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
    //         $httpheader[] = "Connection: close";
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    if($post) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $po);
    }
    $response = curl_exec($ch);
    curl_close($ch);
    return $response;
}

腾讯云API文档签名代码修改

在第一步,文档里的代码是

$canonicalHeaders = "content-type:application/json; charset=utf-8\n"."host:".$host."\n";

但是在这次测试里这样写会报错AuthFailure.SignatureFailure
修改成下面这样就不报错了

$canonicalHeaders = "content-type:application/json"."\n"."host:".$host."\n";
腾讯云活动
最后修改:2022 年 09 月 06 日
如果觉得我的文章对你有用,请随意赞赏

发表评论
使用cookie技术保留您的个人信息以便您下次快速评论,继续评论表示您已同意该条款

🎲