mirror of
https://github.com/anikeen-com/id.git
synced 2026-11-04 22:59:41 +00:00
Start subscriptions with a free trial
trial_days, trial_ends_at and trial_once when creating subscriptions (app and user token) and per subscription of checkout sessions. isTrial() on subscriptions, the subscription.trial_will_end event type, and the trial_already_used error code in the docs.
This commit is contained in:
10 files changed
+130
-9
No files matched your search
@@ -48,6 +48,14 @@ trait HasSubscriptionStatus
|
||||
return in_array($this->status(), [SubscriptionStatus::TRIAL, SubscriptionStatus::ACTIVE, SubscriptionStatus::PAUSED, SubscriptionStatus::CANCELLING], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* In its free trial: running, nothing billed until trial_ends_at.
|
||||
*/
|
||||
public function isTrial(): bool
|
||||
{
|
||||
return $this->status() === SubscriptionStatus::TRIAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Paused: runs until the paid period ends, then expires (resume() to continue).
|
||||
*/
|
||||
|
||||
@@ -36,7 +36,10 @@ class AppCheckoutSessions
|
||||
* predecessor_id?: null|string,
|
||||
* vat_rate?: float,
|
||||
* payload?: null|array,
|
||||
* ends_at?: null|string
|
||||
* ends_at?: null|string,
|
||||
* trial_days?: null|int,
|
||||
* trial_ends_at?: null|string,
|
||||
* trial_once?: bool
|
||||
* }>,
|
||||
* return_url?: null|string,
|
||||
* metadata?: null|array,
|
||||
@@ -45,6 +48,8 @@ class AppCheckoutSessions
|
||||
* } $attributes return_url must share scheme, host and port with one of the app's redirect
|
||||
* URIs; the user comes back to it with `status` and `checkout_session`. A
|
||||
* repeated idempotency_key returns the first session instead of a new one.
|
||||
* trial_days / trial_ends_at give a subscription a free trial from the user's
|
||||
* confirmation on; trial_once is allowed on one subscription per group.
|
||||
*
|
||||
* @throws ApiException 422 validation (e.g. return_url), 409 "idempotency_key_conflict"
|
||||
*/
|
||||
|
||||
@@ -49,6 +49,9 @@ class AppSubscriptions
|
||||
* vat_rate?: float,
|
||||
* payload?: null|array,
|
||||
* ends_at?: null|string,
|
||||
* trial_days?: null|int,
|
||||
* trial_ends_at?: null|string,
|
||||
* trial_once?: bool,
|
||||
* idempotency_key?: null|string
|
||||
* } $attributes With an idempotency_key (max. 191 characters), a retried call returns the
|
||||
* subscription created by the first one instead of a duplicate.
|
||||
@@ -56,8 +59,13 @@ class AppSubscriptions
|
||||
* at most 2 decimals, not below price; null = no cap).
|
||||
* predecessor_id: the subscription this one replaces (a resize; same user and
|
||||
* app, checked out, not cancelled): both share the monthly cap within a month.
|
||||
* trial_days: a free trial of 1–365 days from the checkout on (status `trial`,
|
||||
* nothing billed; the first period is billed when it ends), or
|
||||
* trial_ends_at: a fixed end of the trial (ISO 8601, in the future), not both.
|
||||
* trial_once: refuse the trial if the user already had one with the app in the
|
||||
* same group (422 here, 409 "trial_already_used" on checkout).
|
||||
*
|
||||
* @throws ApiException
|
||||
* @throws ApiException 422 validation, 409 "idempotency_key_conflict", …
|
||||
*/
|
||||
public function create(array $attributes): AppSubscription
|
||||
{
|
||||
|
||||
@@ -24,7 +24,10 @@ class Subscriptions extends BaseCollection
|
||||
* predecessor_id?: null|string,
|
||||
* vat_rate: float,
|
||||
* payload: null|array,
|
||||
* ends_at: null|string
|
||||
* ends_at: null|string,
|
||||
* trial_days?: null|int,
|
||||
* trial_ends_at?: null|string,
|
||||
* trial_once?: bool
|
||||
* } $attributes The subscription data:
|
||||
* - group: The group (optional)
|
||||
* - name: The name
|
||||
@@ -36,6 +39,9 @@ class Subscriptions extends BaseCollection
|
||||
* - vat_rate: The VAT rate (required when set)
|
||||
* - payload: The payload (optional)
|
||||
* - ends_at: The end date (optional)
|
||||
* - trial_days: A free trial of 1–365 days from the user's confirmation on (optional)
|
||||
* - trial_ends_at: Or a fixed end of the free trial (ISO 8601, in the future; optional)
|
||||
* - trial_once: Refuse the trial if the user already had one with the app in the group (optional)
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function create(array $attributes): Subscription
|
||||
|
||||
@@ -21,6 +21,9 @@ final class EventType
|
||||
public const SUBSCRIPTION_CANCELLED = 'subscription.cancelled';
|
||||
public const SUBSCRIPTION_EXPIRED = 'subscription.expired';
|
||||
|
||||
/** The free trial of a running subscription ends in a few days (see trial_ends_at); billing starts then. */
|
||||
public const SUBSCRIPTION_TRIAL_WILL_END = 'subscription.trial_will_end';
|
||||
|
||||
/** The user confirmed a checkout session: all of its subscriptions are running (sent after their subscription.activated). */
|
||||
public const CHECKOUT_COMPLETED = 'checkout.completed';
|
||||
|
||||
|
||||
Reference in new issue
Block a user