PHP做的DDNS更新脚本
把DnspodClient.class.php文件放到class文件夹下面
<?php
class DnspodClient
{
private $secretId;
private $secretKey;
private $endpoint = "dnspod.tencentcloudapi.com";
private $service = "dnspod";
private $version = "2021-03-23";
/**
* Constructor
* @param string $secretId
* @param string $secretKey
*/
public function __construct($secretId, $secretKey)
{
$this->secretId = $secretId;
$this->secretKey = $secretKey;
}
/**
* DescribeRecordList
* @param string $domain
* @param string $subdomain
* @return array
*/
public function describeRecordList($domain, $subdomain) {
$action = "DescribeRecordList";
$payload = [
"Domain" => $domain,
"Subdomain" => $subdomain
];
return $this->request($action, $payload);
}
/**
* Update DNS Record
* @param string $domain Domain name
* @param int $recordId Record ID to update
* @param string $value New value for the record
* @return array
*/
public function updateRecord($Domain, $record) {
$action = "ModifyRecord";
$payload = [
"Domain" => $Domain,
"RecordType" => $record['Type'],
"RecordLine" => $record['Line'],
"Value" => $record['Value'],
"RecordId" => $record['RecordId'],
//"DomainId" => $record[''],
"SubDomain" => $record['Name'],
"RecordLineId" => $record['LineId'],
"MX" => $record['MX'],
"TTL" => $record['TTL'],
//"Weight" => $record['Weight'],
"Status" => $record['Status'],
"Remark" => $record['Remark'],
//"DnssecConflictMode" => $record[''],
];
if ($record['Weight']) {
$payload["Weight"] = $record['Weight'];
}
return $this->request($action, $payload);
}
/**
* Update a specific record's value by domain and record name
*
* @param string $domain Domain name
* @param string $subDomain Subdomain to match
* @param string $value New value to update
* @return array|null API response or null if no record updated
*/
public function updateRecordValue($domain, $subDomain, $value) {
// Fetch current records for the domain/subdomain
$result = $this->describeRecordList($domain, $subDomain);
if (!isset($result['Response']['RecordList']) || empty($result['Response']['RecordList'])) {
return null; // No records found
}
foreach ($result['Response']['RecordList'] as $record) {
if ($record['Value'] === $value) {
return ['code' => 'NoNeedChangeValue'];
}
// Only update 'A' records with different value
if ($record['Type'] === 'A' && $record['Value'] !== $value) {
$record['Value'] = $value;
// Update the record using existing updateRecord method
return $this->updateRecord($domain, $record);
}
}
return null; // No record updated
}
/**
* Send request to Tencent DNSPod API
*/
private function request($action, $payload) {
$timestamp = time();
$algorithm = "TC3-HMAC-SHA256";
// ************ Step 1: Build Canonical Request ************
$httpRequestMethod = "POST";
$canonicalUri = "/";
$canonicalQueryString = "";
$canonicalHeaders = "content-type:application/json\nhost:" . $this->endpoint . "\n";
$signedHeaders = "content-type;host";
$payloadJson = json_encode($payload, JSON_UNESCAPED_UNICODE);
$hashedRequestPayload = hash('sha256', $payloadJson);
$canonicalRequest = $httpRequestMethod . "\n"
. $canonicalUri . "\n"
. $canonicalQueryString . "\n"
. $canonicalHeaders . "\n"
. $signedHeaders . "\n"
. $hashedRequestPayload;
// ************ Step 2: Build String To Sign ************
$date = gmdate("Y-m-d", $timestamp);
$credentialScope = $date . "/" . $this->service . "/tc3_request";
$hashedCanonicalRequest = hash('sha256', $canonicalRequest);
$stringToSign = $algorithm . "\n"
. $timestamp . "\n"
. $credentialScope . "\n"
. $hashedCanonicalRequest;
// ************ Step 3: Calculate Signature ************
$secretDate = hash_hmac('sha256', $date, "TC3" . $this->secretKey, true);
$secretService = hash_hmac('sha256', $this->service, $secretDate, true);
$secretSigning = hash_hmac('sha256', "tc3_request", $secretService, true);
$signature = hash_hmac('sha256', $stringToSign, $secretSigning);
// ************ Step 4: Build Authorization ************
$authorization = $algorithm
. " Credential=" . $this->secretId . "/" . $credentialScope
. ", SignedHeaders=" . $signedHeaders
. ", Signature=" . $signature;
// ************ Step 5: Send HTTP POST ************
$headers = [
"Authorization: $authorization",
"Content-Type: application/json",
"Host: " . $this->endpoint,
"X-TC-Action: $action",
"X-TC-Timestamp: $timestamp",
"X-TC-Version: " . $this->version,
"X-TC-Region: ap-guangzhou"
];
$ch = curl_init("https://" . $this->endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payloadJson);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
throw new Exception("Curl error: " . curl_error($ch));
}
curl_close($ch);
return json_decode($response, true);
}
}
创建index.php文件
<?php
require __DIR__ . '/class/DnspodClient.class.php';
// Get input safely
$domain = isset($_GET['domain']) ? trim($_GET['domain']) : '';
$subdomain = isset($_GET['subdomain']) ? trim($_GET['subdomain']) : '';
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
// Validate input
if (empty($domain) || empty($subdomain)) {
header('Content-Type: application/json');
echo json_encode(['error' => 'Domain and subdomain are required']);
exit;
}
if (!filter_var($ip, FILTER_VALIDATE_IP)) {
header('Content-Type: application/json');
echo json_encode(['error' => 'Invalid IP address']);
exit;
}
try {
// Initialize client with SecretId and SecretKey
$client = new DnspodClient("YourSecretId", "YourSecretKey");
// Update the A record value
$result = $client->updateRecordValue($domain, $subdomain, $ip);
header('Content-Type: application/json');
echo json_encode($result);
} catch (Exception $e) {
header('Content-Type: application/json');
echo json_encode(['error' => $e->getMessage()]);
}
本文来自博客园,作者:项希盛,转载请注明原文链接:https://www.cnblogs.com/xiangxisheng/p/19279471
浙公网安备 33010602011771号