-
-
Notifications
You must be signed in to change notification settings - Fork 108
Expand file tree
/
Copy pathSubscription.php
More file actions
132 lines (111 loc) · 4.67 KB
/
Subscription.php
File metadata and controls
132 lines (111 loc) · 4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<?php
namespace App\Enums;
use RuntimeException;
enum Subscription: string
{
case Mini = 'mini';
case Pro = 'pro';
case Max = 'max';
case Forever = 'forever';
case Trial = 'trial';
public static function fromStripeSubscription(\Stripe\Subscription $subscription): self
{
// Iterate items, skipping extra seat prices (multi-item subscriptions)
foreach ($subscription->items as $item) {
$priceId = $item->price->id;
if (self::isExtraSeatPrice($priceId)) {
continue;
}
return self::fromStripePriceId($priceId);
}
throw new RuntimeException('Could not resolve a plan price id from subscription items.');
}
public static function isExtraSeatPrice(string $priceId): bool
{
return in_array($priceId, array_filter([
config('subscriptions.plans.max.stripe_extra_seat_price_id'),
config('subscriptions.plans.max.stripe_extra_seat_price_id_monthly'),
]));
}
public static function extraSeatStripePriceId(string $interval): ?string
{
return match ($interval) {
'year' => config('subscriptions.plans.max.stripe_extra_seat_price_id'),
'month' => config('subscriptions.plans.max.stripe_extra_seat_price_id_monthly'),
default => null,
};
}
public static function fromStripePriceId(string $priceId): self
{
return match ($priceId) {
config('subscriptions.plans.mini.stripe_price_id'),
config('subscriptions.plans.mini.stripe_price_id_eap') => self::Mini,
'price_1RoZeVAyFo6rlwXqtnOViUCf',
config('subscriptions.plans.pro.stripe_price_id'),
config('subscriptions.plans.pro.stripe_price_id_discounted'),
config('subscriptions.plans.pro.stripe_price_id_eap') => self::Pro,
'price_1RoZk0AyFo6rlwXqjkLj4hZ0',
config('subscriptions.plans.max.stripe_price_id'),
config('subscriptions.plans.max.stripe_price_id_monthly'),
config('subscriptions.plans.max.stripe_price_id_discounted'),
config('subscriptions.plans.max.stripe_price_id_eap'),
config('subscriptions.plans.max.stripe_price_id_comped') => self::Max,
default => throw new RuntimeException("Unknown Stripe price id: {$priceId}"),
};
}
public static function fromAnystackPolicy(string $policyId): self
{
return match ($policyId) {
config('subscriptions.plans.mini.anystack_policy_id') => self::Mini,
config('subscriptions.plans.pro.anystack_policy_id') => self::Pro,
config('subscriptions.plans.max.anystack_policy_id') => self::Max,
config('subscriptions.plans.forever.anystack_policy_id') => self::Forever,
config('subscriptions.plans.trial.anystack_policy_id') => self::Trial,
default => throw new RuntimeException("Unknown Anystack policy id: {$policyId}"),
};
}
public function name(): string
{
return config("subscriptions.plans.{$this->value}.name");
}
public function stripePriceId(bool $forceEap = false, bool $discounted = false, string $interval = 'year'): string
{
// Monthly billing uses the regular monthly price (no EAP/discounted monthly prices exist)
if ($interval === 'month') {
return config("subscriptions.plans.{$this->value}.stripe_price_id_monthly")
?? config("subscriptions.plans.{$this->value}.stripe_price_id");
}
// EAP ends June 1st at midnight UTC
if (now()->isBefore('2025-06-01 00:00:00') || $forceEap) {
return config("subscriptions.plans.{$this->value}.stripe_price_id_eap");
}
if ($discounted) {
return config("subscriptions.plans.{$this->value}.stripe_price_id_discounted");
}
return config("subscriptions.plans.{$this->value}.stripe_price_id");
}
public function stripePaymentLink(): string
{
return config("subscriptions.plans.{$this->value}.stripe_payment_link");
}
public function anystackProductId(): string
{
return config("subscriptions.plans.{$this->value}.anystack_product_id");
}
public function anystackPolicyId(): string
{
return config("subscriptions.plans.{$this->value}.anystack_policy_id");
}
public function supportsSubLicenses(): bool
{
return in_array($this, [self::Pro, self::Max, self::Forever]);
}
public function subLicenseLimit(): ?int
{
return match ($this) {
self::Pro => 9,
self::Max, self::Forever => null, // Unlimited
default => 0,
};
}
}