564 lines
19 KiB
PHP
564 lines
19 KiB
PHP
<?php
|
||
namespace Std\Lib;
|
||
|
||
use Std\Lib\Curl;
|
||
|
||
class Openprovider {
|
||
protected string $dataDir = ROOT."/data/cache/";
|
||
protected int $tokenDuration = 172800; // 48時間
|
||
protected int $dataDuration = 1800; // 30分
|
||
|
||
private string $user = '';
|
||
private string $pass = '';
|
||
private string $token = '';
|
||
private string $ip = '';
|
||
private int $resellerId = 0;
|
||
private int $lastAuth = 0;
|
||
private string $BASEURL = DEBUG_MODE ? 'http://api.sandbox.openprovider.nl:8480/v1beta'
|
||
: 'https://api.openprovider.eu/v1beta';
|
||
|
||
public function __construct() {
|
||
if (!OPENPROVIDER_ENABLED) return;
|
||
$this->user = OPENPROVIDER['username'];
|
||
$this->pass = OPENPROVIDER['password'];
|
||
$this->ip = OPENPROVIDER['ip'];
|
||
}
|
||
|
||
/***
|
||
* トークンの受け取り。
|
||
* このライブリリーを使ったら、一回「login()」を実行する事が必須となります。
|
||
*
|
||
* @return Result 結果
|
||
*/
|
||
public function login(): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$cache = $this->getCache('login');
|
||
if (time() < ($this->lastAuth + $this->tokenDuration)) {
|
||
$this->token = $cache['data']['token'];
|
||
$this->lastAuth = $cache['last_auth'];
|
||
return \Result::Success('', $cache);
|
||
}
|
||
|
||
$curl = new Curl("{$this->BASEURL}/auth/login");
|
||
$payload = [
|
||
'username' => $this->user,
|
||
'password' => $this->pass,
|
||
'ip' => $this->ip ?: '0.0.0.0',
|
||
];
|
||
|
||
$curl->setMethod("POST");
|
||
$curl->setPostRaw(json_encode($payload));
|
||
$curl->addHeader("Content-Type", "application/json");
|
||
$curl->addHeader("Accept", "application/json");
|
||
|
||
$res = $curl->execute();
|
||
if (!$res->isSuccess) {
|
||
$err = "CURLの実行に失敗: ".$curl->message;
|
||
assert_unless_success($res, $err);
|
||
return \Result::Error($err);
|
||
}
|
||
|
||
$body = $curl->getResponseBody();
|
||
if ($curl->getResponseCode() != 200) {
|
||
$err = json_decode($body, true);
|
||
assert_not_null($err, "エラーの受け取りに失敗。");
|
||
assert($curl->getResponseCode() == 200, $err['desc']);
|
||
return \Result::Error();
|
||
}
|
||
assert_not_null($body, "返事ボディーは空です。");
|
||
|
||
$res = json_decode($body, true);
|
||
if (isset($res['data']['token'])) {
|
||
$this->token = $res['data']['token'];
|
||
$this->lastAuth = time();
|
||
$res['last_auth'] = $this->lastAuth;
|
||
$this->setCache('login', $res);
|
||
|
||
return \Result::Success('', $res);
|
||
}
|
||
|
||
return \Result::Error('ログインに失敗。');
|
||
}
|
||
|
||
// カスタマー
|
||
|
||
// ドメイン
|
||
|
||
//// ドメイン
|
||
|
||
/***
|
||
* ドメイン一覧。
|
||
*
|
||
* @return Result 結果。
|
||
*/
|
||
public function listDomains(array $query = []): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$cache = $this->getCache('listdomains');
|
||
if ($this->isValidLifespan($cache, $query)) return \Result::Success('', $cache);
|
||
|
||
$curl = $this->setupCurl('/domains');
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res['data']['results'])) {
|
||
$this->setCache('listdomains', $res->data);
|
||
return \Result::Success('', $res['data']['results']);
|
||
}
|
||
|
||
return \Result::Error('ドメインの確認に失敗。');
|
||
}
|
||
|
||
/**
|
||
* ドメイン名の登録。
|
||
*
|
||
* @param string $name 登録したいドメイン名(例:"076studio.jp")
|
||
* @param array $info カスタマー情報等
|
||
* @param int $period 年間(デフォルト=1年)
|
||
* @return Result 結果。配列の場合:'activation_date'(リアルタイムで成功したのみ), 'auth_code'(TLDが対応している場合のみ), 'expiration_date', 'id', 'renewal_date', 'status'(ACT又はREQ)
|
||
*/
|
||
public function createDomain(string $name, array $info, int $period = 1): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
if (!isset($info['owner_handle']) || $info['owner_handle'] === '') $info['owner_handle'] = OPENPROVIDER['owner_handle'];
|
||
if (!isset($info['admin_handle']) || $info['admin_handle'] === '') $info['admin_handle'] = OPENPROVIDER['owner_handle'];
|
||
if (!isset($info['tech_handle']) || $info['tech_handle'] === '') $info['tech_handle'] = OPENPROVIDER['owner_handle'];
|
||
if (!isset($info['billing_handle']) || $info['billing_handle'] === '') $info['billing_handle'] = OPENPROVIDER['owner_handle'];
|
||
if (!isset($info['reseller_handle']) || $info['reseller_handle'] === '') $info['reseller_handle'] = OPENPROVIDER['owner_handle'];
|
||
if (!isset($info['name_servers']) || empty($info['name_servers'])) $info['name_servers'] = ['ns1.openprovider.nl', 'ns2.openprovider.be', 'ns3.openprovider.eu'];
|
||
if (!isset($info['autorenew']) || $info['autorenew'] === '') $info['autorenew'] = 'default';
|
||
|
||
// 新しい顧客の場合
|
||
|
||
$parts = explode('.', $name, 2);
|
||
assert_exists($parts[0]);
|
||
assert_exists($parts[1]);
|
||
$domain = [
|
||
'name' => $parts[0],
|
||
'extension' => $parts[1],
|
||
];
|
||
|
||
$ns = [];
|
||
foreach ($info['name_servers'] as $n) {
|
||
$ns[] = ['name' => $n];
|
||
}
|
||
|
||
$payload = [
|
||
'name' => $domain,
|
||
'period' => $period,
|
||
'owner_handle' => $owner_handle,
|
||
'admin_handle' => $admin_handle,
|
||
'tech_handle' => $tech_handle,
|
||
'billing_handle' => $billing_handle,
|
||
'reseller_handle' => $reseller_handle,
|
||
'name_servers' => $ns,
|
||
'autorenew' => $autorenew,
|
||
];
|
||
|
||
$curl = $this->setupCurl('/domains/', 'POST', $payload);
|
||
kys('TODO');
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res['data'])) return \Result::Success('', $res);
|
||
|
||
return \Result::Error('ドメインの確認に失敗。');
|
||
}
|
||
|
||
/***
|
||
* ドメインを登録可能かどうかの確認。
|
||
*
|
||
* @param array $domains ドメイン名リスト。例:['076.moe', '076.co.jp', '076.com']
|
||
* @param bool $with_price 値段を表示するかどうか。デフォルトは「false」
|
||
* @return Result 結果。配列の場合:'domain'と'status'はいつでもあり、'reason', 'premium', 'is_premium'が多分あり、そして'price'が「with_price」が「true」の場合のみ。
|
||
*/
|
||
public function checkDomainAvailable(array $domains, bool $with_price = false): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$domainList = [];
|
||
foreach ($domains as $d) {
|
||
$domain = explode('.', $d);
|
||
assert_exists($domain[0]);
|
||
assert_exists($domain[1]);
|
||
if (count($domain) !== 2) {
|
||
return \Result::Error("不正なドメイン形: {$d}");
|
||
}
|
||
|
||
$domainList[] = [
|
||
'name' => $domain[0],
|
||
'extension' => $domain[1],
|
||
];
|
||
}
|
||
|
||
$payload = [
|
||
'domains' => $domainList,
|
||
'with_price' => $with_price,
|
||
];
|
||
|
||
$curl = $this->setupCurl('/domains/check', 'POST', $payload);
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res->data['data']['results'])) return \Result::Success('', $res->data['data']['results']);
|
||
|
||
return \Result::Error('ドメインの確認に失敗。');
|
||
}
|
||
|
||
//// 追加データ
|
||
|
||
//// 顧客様の追加データ
|
||
|
||
/**
|
||
* 顧客様の一覧
|
||
*
|
||
* @param array $query 検索クエリー
|
||
* @return Result
|
||
*/
|
||
public function listCustomers(array $query = []): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$cache = $this->getCache('listcustomers');
|
||
if ($this->isValidLifespan($cache, $query)) return \Result::Success('', $cache);
|
||
|
||
foreach ($query as $k => $v) { if (is_bool($v)) $query[$k] = $v ? '1' : '0'; }
|
||
$uri = '/customers?'.http_build_query($query, '', '&', PHP_QUERY_RFC3986);
|
||
$curl = $this->setupCurl($uri);
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res->data['data'])) {
|
||
$res->data['query'] = $query;
|
||
$this->setCache('listcustomers', $res->data);
|
||
return \Result::Success('', $res->data);
|
||
}
|
||
|
||
return \Result::Error('顧客様一覧の受け取りに失敗。');
|
||
}
|
||
|
||
/**
|
||
* 顧客様の表示
|
||
*
|
||
* @param string $handle ハンドル
|
||
* @param bool $withAdditionalData 詳細データ含むか?
|
||
* @return Result
|
||
*/
|
||
public function getCustomer(string $handle, bool $withAdditionalData = false): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$cacheName = "getcustomer-{$handle}";
|
||
$cache = $this->getCache($cacheName);
|
||
if ($this->isValidLifespan($cache, $handle, 'handle')) return \Result::Success('', $cache);
|
||
|
||
$query = [ 'with_additional_data' => $withAdditionalData ? 'true' : 'false' ];
|
||
$uri = "/customers/{$handle}?".http_build_query($query, '', '&', PHP_QUERY_RFC3986);
|
||
// kys($uri);
|
||
$curl = $this->setupCurl($uri);
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res->data['data'])) {
|
||
$res->data['handle'] = $handle;
|
||
$this->setCache($cacheName, $res->data);
|
||
return \Result::Success('', $res->data);
|
||
}
|
||
|
||
return \Result::Error('顧客様の受け取りに失敗。');
|
||
}
|
||
|
||
//// ドメイン値段
|
||
|
||
/**
|
||
* ドメイン値段一覧
|
||
*
|
||
* @param array $query 検索クエリー
|
||
* @return Result
|
||
*/
|
||
public function getDomainPrices(array $query): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$name = '';
|
||
$ext = '';
|
||
if (isset($query['domain.name'])) $name = $query['domain.name'];
|
||
if (isset($query['domain.extension'])) $ext = $query['domain.extension'];
|
||
$cacheName = $name && $ext ? "domainprices-{$name}.{$ext}" : 'domainprices';
|
||
|
||
$cache = $this->getCache($cacheName);
|
||
if ($this->isValidLifespan($cache)) return \Result::Success('', $cache);
|
||
|
||
$uri = "/domains/prices?".http_build_query($query, '', '&', PHP_QUERY_RFC3986);
|
||
$curl = $this->setupCurl($uri);
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res->data['data'])) {
|
||
$this->setCache($cacheName, $res->data);
|
||
return \Result::Success('', $res->data);
|
||
}
|
||
|
||
return \Result::Error('TLD一覧の受け取りに失敗。');
|
||
}
|
||
|
||
//// 認証コード
|
||
|
||
//// TLD
|
||
|
||
/**
|
||
* TLD一覧
|
||
*
|
||
* @param array $query 検索クエリー
|
||
* @return Result
|
||
*/
|
||
public function listTlds(array $query = []): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$cache = $this->getCache('listtlds');
|
||
if ($this->isValidLifespan($cache)) return \Result::Success('', $cache);
|
||
|
||
if (empty($query)) $query = [ 'limit' => 10, 'offset' => 0, 'order' => 'ASC' ];
|
||
foreach ($query as $k => $v) if (is_bool($v)) $query[$k] = $v ? '1' : '0';
|
||
|
||
$uri = '/tlds?'.http_build_query($query, '', '&', PHP_QUERY_RFC3986);
|
||
$curl = $this->setupCurl($uri);
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res->data['data'])) {
|
||
$this->setCache('listtlds', $res->data);
|
||
return \Result::Success('', $res->data);
|
||
}
|
||
|
||
return \Result::Error('TLD一覧の受け取りに失敗。');
|
||
}
|
||
|
||
/**
|
||
* TLDの表示
|
||
*
|
||
* @param string $tld TLD
|
||
* @param array $query 検索クエリー
|
||
* @return Result
|
||
*/
|
||
public function getTld(string $tld, array $query = []): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$cache = $this->getCache("gettld-{$tld}");
|
||
if ($this->isValidLifespan($cache)) return \Result::Success('', $cache);
|
||
|
||
if (empty($query)) $query = [ 'limit' => 10, 'offset' => 0 ];
|
||
foreach ($query as $k => $v) if (is_bool($v)) $query[$k] = $v ? '1' : '0';
|
||
|
||
$uri = "/tlds/{$tld}?".http_build_query($query, '', '&', PHP_QUERY_RFC3986);
|
||
$curl = $this->setupCurl($uri);
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res->data['data'])) {
|
||
$this->setCache("gettld-{$tld}", $res->data);
|
||
return \Result::Success('', $res->data);
|
||
}
|
||
|
||
return \Result::Error('TLD一覧の受け取りに失敗。');
|
||
}
|
||
|
||
/**
|
||
* TLDの受け取り
|
||
*/
|
||
|
||
// 請求
|
||
//// 請求書
|
||
//// 支払
|
||
//// トランザクション
|
||
|
||
// DNS
|
||
//// DomainToken
|
||
//// ネームサーバー
|
||
//// NSグループ
|
||
//// テンプレート
|
||
//// ゾーン
|
||
|
||
/**
|
||
* DNSゾーン一覧
|
||
*
|
||
* @param array $query
|
||
* @return Result
|
||
*/
|
||
public function listDnsZones(array $query = []): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$cache = $this->getCache('listdnszones');
|
||
if ($this->isValidLifespan($cache, $query)) return \Result::Success('', $cache);
|
||
|
||
if (empty($query)) $query = [ 'limit' => 25, 'offset' => 0, 'order_by.name' => 'asc' ];
|
||
foreach ($query as $k => $v) if (is_bool($v)) $query[$k] = $v ? '1' : '0';
|
||
|
||
$uri = "/dns/zones?".http_build_query($query, '', '&', PHP_QUERY_RFC3986);
|
||
$curl = $this->setupCurl($uri);
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res->data['data'])) {
|
||
$this->setCache('listdnszones', $res->data);
|
||
return \Result::Success('', $res->data);
|
||
}
|
||
|
||
return \Result::Error('TLD一覧の受け取りに失敗。');
|
||
}
|
||
|
||
/**
|
||
* DNSゾーン一覧
|
||
*
|
||
* @param string $domain ドメイン名
|
||
* @param array $query 検索クエリー
|
||
* @return Result
|
||
*/
|
||
public function getDnsZone(string $domain, array $query = []): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$cache = $this->getCache("getdnszone-{$domain}");
|
||
if ($this->isValidLifespan($cache)) return \Result::Success('', $cache);
|
||
|
||
if (empty($query)) $query = [ 'limit' => 100, 'offset' => 0, 'order_by.name' => 'asc' ];
|
||
foreach ($query as $k => $v) if (is_bool($v)) $query[$k] = $v ? '1' : '0';
|
||
|
||
$uri = "/dns/zones/{$domain}?".http_build_query($query, '', '&', PHP_QUERY_RFC3986);
|
||
$curl = $this->setupCurl($uri);
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res->data['data'])) {
|
||
$this->setCache("getdnszone-{$domain}", $res->data);
|
||
return \Result::Success('', $res->data);
|
||
}
|
||
|
||
return \Result::Error('TLD一覧の受け取りに失敗。');
|
||
}
|
||
|
||
//// ゾーンレコード
|
||
|
||
/**
|
||
* DNSレコード一覧
|
||
*
|
||
* @param string $domain
|
||
* @return Result
|
||
*/
|
||
public function listZoneRecords(string $domain): \Result {
|
||
if (!OPENPROVIDER_ENABLED) return \Result::error('エラー:OpenProviderは無効です。');
|
||
$cache = $this->getCache("getzonerecords-{$domain}");
|
||
if ($this->isValidLifespan($cache)) return \Result::Success('', $cache);
|
||
|
||
$curl = $this->setupCurl("/dns/zones/{$domain}/records");
|
||
$res = $this->curlResult($curl);
|
||
if (isset($res->data['data'])) {
|
||
$this->setCache("getzonerecords-{$domain}", $res->data);
|
||
return \Result::Success('', $res->data);
|
||
}
|
||
|
||
return \Result::Error('TLD一覧の受け取りに失敗。');
|
||
}
|
||
|
||
// Easydmarc
|
||
|
||
// ライセンス
|
||
|
||
// リセラー・顧客様
|
||
|
||
// SpamExpert
|
||
|
||
// SSL証明書
|
||
|
||
////////
|
||
|
||
/**
|
||
* トークンの受け取り。
|
||
*
|
||
* @return string トークン
|
||
*/
|
||
public function getToken(): string {
|
||
if (!OPENPROVIDER_ENABLED) return '';
|
||
return $this->token;
|
||
}
|
||
|
||
/**
|
||
* リセラーIDの受け取り。
|
||
*
|
||
* @return int リセラーID
|
||
*/
|
||
public function getResellerId(): int {
|
||
if (!OPENPROVIDER_ENABLED) return 0;
|
||
return $this->resellerId;
|
||
}
|
||
|
||
//////////
|
||
|
||
private function setupCurl(string $uri, string $resType = 'GET', array $payload = []): Curl {
|
||
$curl = new Curl("{$this->BASEURL}{$uri}");
|
||
|
||
$curl->setMethod($resType);
|
||
if (!empty($payload)) $curl->setPostRaw(json_encode($payload));
|
||
$curl->setBearerAuth($this->token);
|
||
$curl->addHeader('Content-Type', 'application/json');
|
||
$curl->addHeader('Accept', 'application/json');
|
||
|
||
return $curl;
|
||
}
|
||
|
||
private function curlResult(Curl &$curl): \Result {
|
||
$res = $curl->execute();
|
||
if (!$res->isSuccess) {
|
||
$err = "CURL実行に失敗: {$curl->message}";
|
||
assert_unless_success($res, $err);
|
||
return \Result::Error($err);
|
||
}
|
||
|
||
$body = $curl->getResponseBody();
|
||
if ($curl->getResponseCode() != 200) {
|
||
$err = json_decode($body, true);
|
||
assert_not_null($err, "エラーの受け取りに失敗。");
|
||
assert($curl->getResponseCode() == 200, $err['desc']);
|
||
return \Result::Error($err['desc']);
|
||
}
|
||
assert_not_null($body, "返事ボディーは空です。");
|
||
|
||
return \Result::Success('', json_decode($body, true));
|
||
}
|
||
|
||
/**
|
||
* キャッシュの作成
|
||
*
|
||
* @param string $type キャッシュ類(例:login、domainlist等)
|
||
* @param array $data 保存するデータ
|
||
* @return Result
|
||
*/
|
||
private function setCache(string $type, array $data): \Result {
|
||
if (!file_exists($this->dataDir)) {
|
||
if (!mkdir($this->dataDir, 0755))
|
||
return \Result::Error('エラー:ユーザーのアイコンディレクトリの作成に失敗。');
|
||
}
|
||
|
||
$data['lifespan'] = time();
|
||
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||
if (file_put_contents("{$this->dataDir}{$type}.json", $json) === false) return \Result::Error('エラー:ユーザーデータの保存に失敗。');
|
||
|
||
return \Result::Success();
|
||
}
|
||
|
||
/**
|
||
* キャッシュから受け取り
|
||
*
|
||
* @param string $type キャッシュ類(例:login、domainlist等)
|
||
* @return array
|
||
*/
|
||
private function getCache(string $type): array {
|
||
if (!file_exists("{$this->dataDir}{$type}.json")) return [];
|
||
|
||
$content = file_get_contents("{$this->dataDir}{$type}.json");
|
||
if ($content === false) return [];
|
||
|
||
$data = json_decode($content, true);
|
||
if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) return [];
|
||
|
||
if ($type === 'login') {
|
||
$this->token = $data['data']['token'];
|
||
$this->lastAuth = $data['last_auth'];
|
||
}
|
||
|
||
return $data;
|
||
}
|
||
|
||
/**
|
||
* キャッシュを破壊する
|
||
*
|
||
* @param string $name キャッシュのファイル名
|
||
* @return Result
|
||
*/
|
||
private function murderCache(string $name): \Result {
|
||
if (!file_exists("{$this->dataDir}{$name}.json")) return \Result::Error('キャッシュファイルが存在しない。');
|
||
if (!unlink("{$this->dataDir}{$name}.json")) return \Result::Error('キャッシュファイルの削除に失敗。');
|
||
return \Result::Success();
|
||
}
|
||
|
||
/**
|
||
* キャッシュ有効期限の確認
|
||
*
|
||
* @param array $cache
|
||
* @param mixed $data デフォルト=null
|
||
* @param string $dataPoint デフォルト=query
|
||
* @return bool
|
||
*/
|
||
private function isValidLifespan(array $cache, mixed $data = null, string $dataPoint = 'query'): bool {
|
||
if (NULL === $data) return (!empty($cache) && (isset($cache['lifespan']) && time() < ($cache['lifespan'] + $this->dataDuration)));
|
||
else return (!empty($cache)
|
||
&& (isset($cache[$dataPoint])
|
||
&& $cache[$dataPoint] === $data)
|
||
&& (isset($cache['lifespan']) && time() < ($cache['lifespan'] + $this->dataDuration)));
|
||
}
|
||
} |