CloudFlare.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. <?php
  2. namespace App\Utils\DDNS;
  3. use App\Utils\Library\Templates\DNS;
  4. use Arr;
  5. use Http;
  6. use Log;
  7. class CloudFlare implements DNS
  8. {
  9. // 开发依据: https://developers.cloudflare.com/api/
  10. private string $apiHost;
  11. private array $auth;
  12. public function __construct(private readonly string $subDomain)
  13. {
  14. $this->apiHost = 'https://api.cloudflare.com/client/v4/zones/';
  15. $this->auth = ['X-Auth-Key' => sysConfig('ddns_secret'), 'X-Auth-Email' => sysConfig('ddns_key')];
  16. $zoneIdentifier = $this->getZone();
  17. if ($zoneIdentifier) {
  18. $this->apiHost .= $zoneIdentifier.'/dns_records/';
  19. }
  20. }
  21. private function getZone(): string
  22. {
  23. $zones = $this->send('list');
  24. if ($zones) {
  25. foreach ($zones as $zone) {
  26. if (str_contains($this->subDomain, Arr::get($zone, 'name'))) {
  27. return $zone['id'];
  28. }
  29. }
  30. }
  31. exit(400);
  32. }
  33. private function send(string $action, array $parameters = [], ?string $identifier = null): array
  34. {
  35. $client = Http::timeout(10)->retry(3, 1000)->withHeaders($this->auth)->baseUrl($this->apiHost)->asJson();
  36. $response = match ($action) {
  37. 'list' => $client->get(''),
  38. 'get' => $client->get('', $parameters),
  39. 'create' => $client->post('', $parameters),
  40. 'update' => $client->put($identifier, $parameters),
  41. 'delete' => $client->delete($identifier),
  42. };
  43. $data = $response->json();
  44. if ($data) {
  45. if ($response->ok() && Arr::get($data, 'success')) {
  46. return Arr::get($data, 'result');
  47. }
  48. Log::error('[CloudFlare - '.$action.'] 返回错误信息:'.Arr::get($data, 'errors.error_chain.message', Arr::get($data, 'errors.0.message')));
  49. } else {
  50. Log::error('[CloudFlare - '.$action.'] 请求失败');
  51. }
  52. exit(400);
  53. }
  54. public function store(string $ip, string $type): bool
  55. {
  56. $ret = $this->send('create', ['content' => $ip, 'name' => $this->subDomain, 'type' => $type]);
  57. return (bool) $ret;
  58. }
  59. public function update(string $latest_ip, string $original_ip, string $type): bool
  60. {
  61. $recordId = Arr::first($this->getRecordId($type, $original_ip));
  62. if ($recordId) {
  63. $ret = $this->send('update', ['content' => $latest_ip, 'name' => $this->subDomain, 'type' => $type], $recordId);
  64. }
  65. return (bool) ($ret ?? false);
  66. }
  67. private function getRecordId(string $type, string $ip): array|false
  68. {
  69. $records = $this->send('get', ['content' => $ip, 'name' => $this->subDomain, 'type' => $type]);
  70. if ($records) {
  71. return data_get($records, '*.id');
  72. }
  73. return false;
  74. }
  75. public function destroy(string $type, string $ip): int
  76. {
  77. $records = $this->getRecordId($type, $ip);
  78. $count = 0;
  79. if ($records) {
  80. foreach ($records as $record) {
  81. $ret = $this->send('delete', [], $record);
  82. if ($ret) {
  83. $count++;
  84. }
  85. }
  86. }
  87. return $count;
  88. }
  89. }