mirror of
https://github.com/anikeen-com/id.git
synced 2026-10-31 20:59:32 +00:00
AppSubscription::checkout() takes an optional $startsAt (needs id-core
with starts_at support on PUT v1/client/subscriptions/{id}/checkout).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
135 lines
3.5 KiB
PHP
135 lines
3.5 KiB
PHP
<?php
|
|
|
|
namespace Anikeen\Id\Resources;
|
|
|
|
use Anikeen\Id\Exceptions\ApiException;
|
|
use Anikeen\Id\Support\AppRequest;
|
|
use DateTimeInterface;
|
|
use JsonSerializable;
|
|
|
|
/**
|
|
* A subscription managed by the app itself (client credentials), see AppSubscriptions.
|
|
*
|
|
* @property string $id
|
|
* @property string $user_id
|
|
* @property ?string $group
|
|
* @property string $name
|
|
* @property ?string $description
|
|
* @property string $unit
|
|
* @property float $price
|
|
* @property ?float $vat_rate
|
|
* @property bool $active
|
|
* @property bool $autorenew
|
|
* @property bool $cancelled
|
|
* @property ?string $status "active" or "inactive"
|
|
* @property ?string $starts_at
|
|
* @property ?string $ends_at
|
|
* @property ?string $accounting_at
|
|
* @property bool $is_past_due
|
|
* @property int $failed_renewal_retries
|
|
* @property ?array $payload
|
|
* @property ?string $idempotency_key
|
|
*/
|
|
class AppSubscription implements JsonSerializable
|
|
{
|
|
public function __construct(protected object $data)
|
|
{
|
|
}
|
|
|
|
public function __get(string $name): mixed
|
|
{
|
|
return $this->data->{$name} ?? null;
|
|
}
|
|
|
|
public function __isset(string $name): bool
|
|
{
|
|
return isset($this->data->{$name});
|
|
}
|
|
|
|
/**
|
|
* Change a subscription that wasn't checked out yet.
|
|
*
|
|
* @throws ApiException
|
|
*/
|
|
public function update(array $attributes): self
|
|
{
|
|
return $this->send('PUT', '', $attributes);
|
|
}
|
|
|
|
/**
|
|
* Activate the subscription and bill its first period.
|
|
*
|
|
* $startsAt (in the past) books a service that is already running, e.g. a domain registered
|
|
* earlier: the first period runs from $startsAt, is billed now and renews when it ends.
|
|
*
|
|
* @throws ApiException 409 "already_active", "billing_address_missing", "period_already_ended", …
|
|
*/
|
|
public function checkout(DateTimeInterface|string|null $startsAt = null): self
|
|
{
|
|
if ($startsAt instanceof DateTimeInterface) {
|
|
$startsAt = $startsAt->format(DateTimeInterface::ATOM);
|
|
}
|
|
|
|
return $this->send('PUT', '/checkout', $startsAt === null ? null : ['starts_at' => $startsAt]);
|
|
}
|
|
|
|
/**
|
|
* Cancel the subscription. With $refund (only within 14 days of its start), its not yet
|
|
* charged usage is credited.
|
|
*
|
|
* @throws ApiException 409 "already_cancelled", 404 "subscription_not_found", …
|
|
*/
|
|
public function revoke(bool $refund = false): self
|
|
{
|
|
return $this->send('PUT', '/revoke', ['refund' => $refund]);
|
|
}
|
|
|
|
/**
|
|
* Stop renewing; the subscription expires when its paid period ends.
|
|
*
|
|
* @throws ApiException
|
|
*/
|
|
public function pause(): self
|
|
{
|
|
return $this->send('PUT', '/pause');
|
|
}
|
|
|
|
/**
|
|
* Renew again (an expired subscription starts a new period).
|
|
*
|
|
* @throws ApiException
|
|
*/
|
|
public function resume(): self
|
|
{
|
|
return $this->send('PUT', '/resume');
|
|
}
|
|
|
|
/**
|
|
* @throws ApiException
|
|
*/
|
|
public function refresh(): self
|
|
{
|
|
return $this->send('GET', '');
|
|
}
|
|
|
|
public function toArray(): array
|
|
{
|
|
return (array) $this->data;
|
|
}
|
|
|
|
public function jsonSerialize(): array
|
|
{
|
|
return $this->toArray();
|
|
}
|
|
|
|
/**
|
|
* @throws ApiException
|
|
*/
|
|
private function send(string $method, string $action, ?array $payload = null): self
|
|
{
|
|
$this->data = AppRequest::send($method, sprintf('v1/client/subscriptions/%s%s', $this->id, $action), $payload)->data;
|
|
|
|
return $this;
|
|
}
|
|
}
|