Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Domain 20180129 Laravel Package

alibabacloud/domain-20180129

Official Alibaba Cloud Domain (20180129) SDK for PHP, generated from the OpenAPI spec. Provides a Guzzle-based client for querying and managing domains, checking availability, registering and renewing names, and handling domain-related tasks via Alibaba Cloud's API. Requires PHP and Composer.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the generated client and its transitive OpenAPI runtime:

composer require alibabacloud/domain-20180129

You need a RAM user (or STS token) with the AliyunDomainFullAccess policy or a narrower custom policy, and an AccessKey pair. Put them in .env and surface them through config/services.php:

// config/services.php
'alibaba_domain' => [
    'key' => env('ALIYUN_ACCESS_KEY_ID'),
    'secret' => env('ALIYUN_ACCESS_KEY_SECRET'),
    'endpoint' => env('ALIYUN_DOMAIN_ENDPOINT', 'domain.aliyuncs.com'),
],

Construct the client once and bind it as a singleton (it is stateless per request, so one instance is fine):

use AlibabaCloud\SDK\Domain\V20180129\Domain;
use Darabonba\OpenApi\Models\Config;

$this->app->singleton(Domain::class, function () {
    $config = new Config([
        'accessKeyId' => config('services.alibaba_domain.key'),
        'accessKeySecret' => config('services.alibaba_domain.secret'),
    ]);
    $config->endpoint = config('services.alibaba_domain.endpoint');

    return new Domain($config);
});

First real use case — list the account's domains with expiry dates:

use AlibabaCloud\SDK\Domain\V20180129\Models\QueryDomainListRequest;

$request = new QueryDomainListRequest([
    'pageNum' => 1,
    'pageSize' => 100,
]);
$response = $client->queryDomainList($request);

foreach ($response->body->data->domain ?? [] as $domain) {
    // $domain->domainName, $domain->expirationDate, $domain->domainStatus
}

Where to look first: src/V20180129/Domain.php is the complete method list (one method per OpenAPI action — queryDomainList, checkDomain, queryDomainByDomainName, saveSingleTaskForCreatingOrderActivate, saveBatchTaskForCreatingOrderActivate, etc.), and src/V20180129/Models/ contains the paired *Request/*Response classes with every field name. Match those against the Alibaba Cloud "Domain" API reference by version 2018-01-29; the SDK adds nothing beyond what the OpenAPI spec declares, so field semantics live in the docs, not in the code.

Implementation Patterns

Wrap the client behind your own service. Never let generated request objects leak into controllers. A thin DomainService that takes the Domain client and returns small readonly DTOs or arrays buys you type safety, a mockable seam for tests, and insulation from the SDK's frequent generated-code churn.

final class DomainService
{
    public function __construct(private Domain $client) {}

    public function all(): Collection
    {
        $domains = collect();
        $page = 1;

        do {
            $res = $this->client->queryDomainList(new QueryDomainListRequest([
                'pageNum' => $page,
                'pageSize' => 100,
            ]));

            $batch = collect($res->body->data->domain ?? []);
            $domains = $domains->merge($batch);
            $page++;
        } while ($batch->count() === 100);

        return $domains;
    }
}

Treat mutations as asynchronous tasks. Registration, renewal, transfer, DNS modification and contact updates are all saveSingleTaskFor* / saveBatchTaskFor* calls that return a task number immediately. The work happens server-side; you must poll queryTaskDetailHistory/queryTaskInfoHistory (or queryTaskDetailList) for completion. Model this as a queued job with $tries, exponential backoff(), and a terminal "failed" state — not as a synchronous controller action.

final class PollDomainTask implements ShouldQueue
{
    public int $tries = 10;

    public function backoff(): array
    {
        return [10, 30, 60, 120, 300];
    }

    public function handle(DomainService $domains): void
    {
        $status = $domains->taskStatus($this->taskNo);

        if ($status === 'SUCCEED') {
            DomainRegistered::dispatch($this->domainName);
            return;
        }

        if ($status === 'FAILED') {
            throw new DomainRegistrationFailed($this->taskNo);
        }

        $this->release(60);
    }
}

Prefer the batch activation call for bulk work. saveBatchTaskForCreatingOrderActivate takes an OrderActivateParam list and returns a single task number, which is one HTTP round-trip instead of N throttled ones:

use AlibabaCloud\SDK\Domain\V20180129\Models\SaveBatchTaskForCreatingOrderActivateRequest;
use AlibabaCloud\SDK\Domain\V20180129\Models\SaveBatchTaskForCreatingOrderActivateRequestOrderActivateParam;

$request = new SaveBatchTaskForCreatingOrderActivateRequest([
    'orderActivateParam' => [
        new SaveBatchTaskForCreatingOrderActivateRequestOrderActivateParam([
            'domainName' => 'example.com',
            'registrantProfileId' => $profileId,
            'expectedPunycode' => idn_to_ascii('example.com'), // 5.1.1+
        ]),
        // ...
    ],
]);

$taskNo = $client->saveBatchTaskForCreatingOrderActivate($request)->body->taskNo;

Note the nested parameter naming: on the wire it is OrderActivateParam.$.ExpectedPunycode, in PHP it is a list of typed param objects.

Guard mutations with ShouldBeUnique. Domain registration is money-moving and non-idempotent in practice: saveSingleTaskForCreatingOrderActivate charges the account. Use Laravel's unique job lock keyed on the domain name, and additionally pass the API's clientToken field when the action supports it.

Schedule a nightly sync command. Pull queryDomainList and queryDomainByDomainName, upsert expiration_date, domain_status, registrant_profile_id. Fire events for anything expiring in 30/14/7 days. Cache the result — do not call this API per page view.

Use the request objects' mass-assignment constructor deliberately. new QueryDomainListRequest(['pageSize' => 100]) works because generated models hydrate public properties from the array, but unknown keys silently do nothing. If you typo 'page_size', you get the default page size and no error. Build a small map in tests that asserts the exact request object built for a given input.

Runtime options for timeouts and retries — the client accepts per-call runtime options, which is where you control connect/read timeouts rather than in the Config:

use AlibabaCloud\Tea\Utils\Utils;

$client->queryDomainList($request, Utils::runtimeOptions([
    'connectTimeout' => 5000,
    'readTimeout' => 10000,
    'autoretry' => true,
    'maxAttempts' => 3,
]));

Gotchas and Tips

Response bodies are models, not arrays. $response->body is a generated object tree; $response->body->data->domain may be null when the result set is empty, so always use ?? []. Call ->toMap() to recurse into plain arrays for logging or JSON responses — but be aware toMap() on the response drops nulls, which can make debugging "field missing vs. field empty" confusing. Log $response->body->toMap() at debug level alongside the request ID.

Errors arrive in two flavours. Transport/SDK failures throw Tea\Exception\TeaError (and TeaUnableRetryError after retries) — wrap those in a 502-style exception. Business errors from the API surface as a coded error on the response (e.g. InvalidDomainName, DomainNotAvailable, QuotaExceeded) — map these to domain exceptions with the original RequestId preserved, because Alibaba support will ask for it. Catch broadly at the service boundary and rethrow your own types.

Throttling and ServiceUnavailable need backoff, not immediate retry. Query endpoints are rate-limited per account. If you are iterating hundreds of domains one-by-one with queryDomainByDomainName, add a small delay or batch via queryDomainList, and prefer autoretry over hand-rolled loops.

Endpoint and account type matter. domain.aliyuncs.com is the global endpoint, but behaviour differs for international vs. mainland-China accounts: several TLDs, real-name verification flows, and registrant-template APIs behave differently or are unavailable. Test with the same account class you deploy against; a staging account in another region can produce false confidence.

Registrant profiles are a prerequisite, not an afterthought. Creating an order without a valid, verified registrantProfileId (and, for .cn and friends, completed real-name verification) fails late with an opaque error. Query profiles via queryRegistrantProfiles up front and validate before you call any order-creating action.

Punycode: normalise AND declare it. IDN domains must be converted (idn_to_ascii) before checkDomain/order calls, and the API returns the ASCII form in responses — normalise both sides or your upserts will create duplicate rows. As of 5.1.1 the activation calls accept an explicit expectedPunycode (ExpectedPunycode on SaveSingleTaskForCreatingOrderActivate, OrderActivateParam.$.ExpectedPunycode on SaveBatchTaskForCreatingOrderActivate); populate it so the task validates the ASCII form you actually intended instead of silently deriving one. Validate locally that expectedPunycode === $request->domainName in ASCII form before enqueueing, and reject mixed unicode/ASCII input at your form-request layer. On older pinned versions the field is ignored by the mass-assignment constructor with no error — check the version before relying on it.

Do not mock the generated client in tests. Its constructor and internal doRequest plumbing are generated and unstable across releases. Bind DomainService to an interface (or a fake implementation) in the container and test your job/command logic against that. Reserve a single integration test, tagged and excluded from CI by default, for a real sandbox call.

Package versioning is generated, not semantic. The release cadence tracks OpenAPI spec regeneration; a patch bump can add request properties or change @return types. 5.1.1 is a textbook case — a patch release that only adds expectedPunycode fields to two activation models and touches nothing else. Pin the version in composer.json, review diffs in src/V20180129/Models when bumping, and keep all SDK calls inside your wrapper so upgrades touch one directory. Because unknown request keys fail silently, an upgrade that adds a field is safe but an upgrade that renames one is not detectable at runtime — assert the built request objects in tests.

Dates are UTC ISO-8601 strings, not Carbon. Every timestamp (expirationDate, creationDate, updateDate) is a string in the account's configured format. Parse explicitly with Carbon::parse($value, 'UTC') and store in a UTC column; otherwise expiry reminders drift by the server timezone.

Extension points are limited to what you build. There is no service provider, no publishable config, no events. Everything Laravel-flavoured — the singleton binding, the wrapper service, the queued poller, the scheduled sync, the exception mapping — is yours to write. Budget for it: the SDK is a transport, not an integration.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route