diff --git a/app/config/collections/payments.php b/app/config/collections/payments.php index 924f8defce..a9f78e0c31 100644 --- a/app/config/collections/payments.php +++ b/app/config/collections/payments.php @@ -130,5 +130,3 @@ return [ ], ]; - - diff --git a/app/init/resources.php b/app/init/resources.php index 16a30168b8..a8fe947d49 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -56,7 +56,6 @@ use Utopia\Storage\Storage; use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; use Utopia\Telemetry\Adapter\None as NoTelemetry; -use Redis; use Utopia\Validator\Hostname; use Utopia\Validator\WhiteList; use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub; diff --git a/src/Appwrite/Payments/Provider/Adapter.php b/src/Appwrite/Payments/Provider/Adapter.php index 5a904a7c03..d5a3440cd9 100644 --- a/src/Appwrite/Payments/Provider/Adapter.php +++ b/src/Appwrite/Payments/Provider/Adapter.php @@ -40,5 +40,3 @@ interface Adapter public function testConnection(array $config): ProviderTestResult; } - - diff --git a/src/Appwrite/Payments/Provider/ProviderCheckoutSession.php b/src/Appwrite/Payments/Provider/ProviderCheckoutSession.php index 7377ee518b..ff34b7e9b8 100644 --- a/src/Appwrite/Payments/Provider/ProviderCheckoutSession.php +++ b/src/Appwrite/Payments/Provider/ProviderCheckoutSession.php @@ -10,5 +10,3 @@ class ProviderCheckoutSession ) { } } - - diff --git a/src/Appwrite/Payments/Provider/ProviderFeatureRef.php b/src/Appwrite/Payments/Provider/ProviderFeatureRef.php index 28086e1e50..782388b7a3 100644 --- a/src/Appwrite/Payments/Provider/ProviderFeatureRef.php +++ b/src/Appwrite/Payments/Provider/ProviderFeatureRef.php @@ -10,5 +10,3 @@ class ProviderFeatureRef ) { } } - - diff --git a/src/Appwrite/Payments/Provider/ProviderPlanRef.php b/src/Appwrite/Payments/Provider/ProviderPlanRef.php index 50758859da..405dd7c257 100644 --- a/src/Appwrite/Payments/Provider/ProviderPlanRef.php +++ b/src/Appwrite/Payments/Provider/ProviderPlanRef.php @@ -10,5 +10,3 @@ class ProviderPlanRef ) { } } - - diff --git a/src/Appwrite/Payments/Provider/ProviderPortalSession.php b/src/Appwrite/Payments/Provider/ProviderPortalSession.php index 1594b72e1b..bc58d1c776 100644 --- a/src/Appwrite/Payments/Provider/ProviderPortalSession.php +++ b/src/Appwrite/Payments/Provider/ProviderPortalSession.php @@ -10,5 +10,3 @@ class ProviderPortalSession ) { } } - - diff --git a/src/Appwrite/Payments/Provider/ProviderState.php b/src/Appwrite/Payments/Provider/ProviderState.php index 51411ac02a..f709c6b757 100644 --- a/src/Appwrite/Payments/Provider/ProviderState.php +++ b/src/Appwrite/Payments/Provider/ProviderState.php @@ -11,5 +11,3 @@ class ProviderState ) { } } - - diff --git a/src/Appwrite/Payments/Provider/ProviderSubscriptionRef.php b/src/Appwrite/Payments/Provider/ProviderSubscriptionRef.php index 95c2e45649..eb5efb90a7 100644 --- a/src/Appwrite/Payments/Provider/ProviderSubscriptionRef.php +++ b/src/Appwrite/Payments/Provider/ProviderSubscriptionRef.php @@ -10,5 +10,3 @@ class ProviderSubscriptionRef ) { } } - - diff --git a/src/Appwrite/Payments/Provider/ProviderTestResult.php b/src/Appwrite/Payments/Provider/ProviderTestResult.php index 4ba85c5adb..2202ad7ffd 100644 --- a/src/Appwrite/Payments/Provider/ProviderTestResult.php +++ b/src/Appwrite/Payments/Provider/ProviderTestResult.php @@ -11,5 +11,3 @@ class ProviderTestResult ) { } } - - diff --git a/src/Appwrite/Payments/Provider/ProviderUsageReport.php b/src/Appwrite/Payments/Provider/ProviderUsageReport.php index 7b016ba009..d4e46c7216 100644 --- a/src/Appwrite/Payments/Provider/ProviderUsageReport.php +++ b/src/Appwrite/Payments/Provider/ProviderUsageReport.php @@ -10,5 +10,3 @@ class ProviderUsageReport ) { } } - - diff --git a/src/Appwrite/Payments/Provider/ProviderWebhookResult.php b/src/Appwrite/Payments/Provider/ProviderWebhookResult.php index c90227a947..c9ccc64210 100644 --- a/src/Appwrite/Payments/Provider/ProviderWebhookResult.php +++ b/src/Appwrite/Payments/Provider/ProviderWebhookResult.php @@ -10,5 +10,3 @@ class ProviderWebhookResult ) { } } - - diff --git a/src/Appwrite/Payments/Provider/Registry.php b/src/Appwrite/Payments/Provider/Registry.php index e4978dac92..6b9fd1566f 100644 --- a/src/Appwrite/Payments/Provider/Registry.php +++ b/src/Appwrite/Payments/Provider/Registry.php @@ -43,5 +43,3 @@ class Registry return $adapter; } } - - diff --git a/src/Appwrite/Payments/Provider/StripeAdapter.php b/src/Appwrite/Payments/Provider/StripeAdapter.php index bb7b6b9000..ac65239b19 100644 --- a/src/Appwrite/Payments/Provider/StripeAdapter.php +++ b/src/Appwrite/Payments/Provider/StripeAdapter.php @@ -2,10 +2,13 @@ namespace Appwrite\Payments\Provider; +use Swoole\Coroutine\Http\ClientProxy; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\System\System; use Utopia\Database\Query; +use Utopia\System\System; + +use function Swoole\Coroutine\Http\request; class StripeAdapter implements Adapter { @@ -46,10 +49,12 @@ class StripeAdapter implements Adapter 'description' => 'Appwrite Payments Webhook for Project ' . $project->getId() ]); + $endpointData = json_decode($endpoint->getBody(), true); + $meta = [ 'currency' => $account['default_currency'] ?? 'usd', - 'webhookEndpointId' => $endpoint['id'] ?? null, - 'webhookSecret' => $endpoint['secret'] ?? null, + 'webhookEndpointId' => $endpointData['id'] ?? null, + 'webhookSecret' => $endpointData['secret'] ?? null, ]; return new ProviderState($this->getIdentifier(), $config, $meta); } @@ -59,6 +64,17 @@ class StripeAdapter implements Adapter $apiKey = (string) ($state->config['secretKey'] ?? ''); $name = (string) ($planData['name'] ?? ''); $description = (string) ($planData['description'] ?? ''); + + $providerPlanId = json_decode($planData['providers']['stripe']['planId'] ?? '', true); + + // Check if product already exists + $existingProduct = $this->request($apiKey, 'GET', '/products/' . $providerPlanId); + + if ($existingProduct->getStatusCode() === 200) { + $data = json_decode($existingProduct->getBody(), true); + return new ProviderPlanRef(externalPlanId: $data['id'], metadata: ['productId' => $data['id']]); + } + $product = $this->request($apiKey, 'POST', '/products', [ 'name' => $name, 'description' => $description, @@ -67,7 +83,8 @@ class StripeAdapter implements Adapter 'plan_id' => (string) ($planData['planId'] ?? '') ] ]); - $productId = (string) ($product['id'] ?? ''); + $productData = json_decode($product->getBody(), true); + $productId = (string) ($productData['id'] ?? ''); $refs = ['productId' => $productId, 'prices' => []]; $pricing = (array) ($planData['pricing'] ?? []); foreach ($pricing as $price) { @@ -93,7 +110,7 @@ class StripeAdapter implements Adapter { $apiKey = (string) ($state->config['secretKey'] ?? ''); - // 1) Update product name/description if provided + // Update product name/description if provided $updates = []; if (isset($planData['name']) && $planData['name'] !== '') { $updates['name'] = (string) $planData['name']; @@ -105,18 +122,21 @@ class StripeAdapter implements Adapter $this->request($apiKey, 'POST', '/products/' . $reference->externalPlanId, $updates); } - // 2) Reconcile prices: create new prices for provided pricing entries; deactivate orphaned + // Reconcile prices: create new prices for provided pricing entries; deactivate orphaned $newPricing = (array) ($planData['pricing'] ?? []); $existingPrices = (array) ($reference->metadata['prices'] ?? []); // Fetch details for existing price ids $existingMap = []; // key => priceId foreach ($existingPrices as $pid) { - if (!$pid) { continue; } + if (!$pid) { + continue; + } $price = $this->request($apiKey, 'GET', '/prices/' . $pid); - $currency = (string) ($price['currency'] ?? ''); - $interval = (string) ($price['recurring']['interval'] ?? ''); - $amount = (int) ($price['unit_amount'] ?? 0); + $priceData = json_decode($price->getBody(), true); + $currency = (string) ($priceData['currency'] ?? ''); + $interval = (string) ($priceData['recurring']['interval'] ?? ''); + $amount = (int) ($priceData['unit_amount'] ?? 0); $key = $currency . ':' . $interval . ':' . $amount; $existingMap[$key] = (string) $pid; } @@ -147,7 +167,8 @@ class StripeAdapter implements Adapter 'type' => 'payments_plan_price' ] ]); - $keptPriceIds[] = (string) ($res['id'] ?? ''); + $resData = json_decode($res->getBody(), true); + $keptPriceIds[] = (string) ($resData['id'] ?? ''); } // Deactivate any existing price not in desired set @@ -250,8 +271,10 @@ class StripeAdapter implements Adapter 'metadata' => [ 'project_id' => $this->project->getId(), 'actor_id' => $actor->getId() ] ]); + $respData = json_decode($resp->getBody(), true); + // Map Stripe status to internal status - $stripeStatus = (string) ($resp['status'] ?? 'incomplete'); + $stripeStatus = (string) ($respData['status'] ?? 'incomplete'); $statusMap = [ 'active' => 'active', 'trialing' => 'trialing', @@ -265,7 +288,7 @@ class StripeAdapter implements Adapter $internalStatus = $statusMap[$stripeStatus] ?? 'pending'; return new ProviderSubscriptionRef( - externalSubscriptionId: (string) ($resp['id'] ?? ''), + externalSubscriptionId: (string) ($respData['id'] ?? ''), metadata: ['status' => $internalStatus] ); } @@ -276,7 +299,8 @@ class StripeAdapter implements Adapter $newPriceId = (string) ($changes['priceId'] ?? ''); if ($newPriceId !== '') { $sub = $this->request($apiKey, 'GET', '/subscriptions/' . $subscription->externalSubscriptionId); - $itemId = $sub['items']['data'][0]['id'] ?? ''; + $subData = json_decode($sub->getBody(), true); + $itemId = $subData['items']['data'][0]['id'] ?? ''; if ($itemId !== '') { $this->request($apiKey, 'POST', '/subscriptions/' . $subscription->externalSubscriptionId, [ 'items' => [ [ 'id' => $itemId, 'price' => $newPriceId ] ], @@ -315,8 +339,9 @@ class StripeAdapter implements Adapter 'client_reference_id' => $actor->getId(), 'metadata' => [ 'project_id' => $this->project->getId(), 'actor_id' => $actor->getId() ] ]; - $session = $this->request($apiKey, 'POST', '/checkout/sessions', $params); - return new ProviderCheckoutSession(url: (string) ($session['url'] ?? '')); + $sessionResponse = $this->request($apiKey, 'POST', '/checkout/sessions', $params); + $sessionData = json_decode($sessionResponse->getBody(), true); + return new ProviderCheckoutSession(url: (string) ($sessionData['url'] ?? '')); } public function createPortalSession(Document $actor, ProviderState $state, array $options = []): ProviderPortalSession @@ -324,8 +349,9 @@ class StripeAdapter implements Adapter $apiKey = (string) ($state->config['secretKey'] ?? ''); $returnUrl = (string) ($options['returnUrl'] ?? ''); $customerId = $this->ensureCustomer($apiKey, $actor); - $session = $this->request($apiKey, 'POST', '/billing_portal/sessions', [ 'customer' => $customerId, 'return_url' => $returnUrl ]); - return new ProviderPortalSession(url: (string) ($session['url'] ?? '')); + $sessionResponse = $this->request($apiKey, 'POST', '/billing_portal/sessions', [ 'customer' => $customerId, 'return_url' => $returnUrl ]); + $sessionData = json_decode($sessionResponse->getBody(), true); + return new ProviderPortalSession(url: (string) ($sessionData['url'] ?? '')); } public function reportUsage(ProviderSubscriptionRef $subscription, string $featureId, int $quantity, \DateTimeInterface $timestamp, ProviderState $state): void @@ -337,7 +363,8 @@ class StripeAdapter implements Adapter if ($stripeSubId !== '') { try { $sub = $this->request($apiKey, 'GET', '/subscriptions/' . $stripeSubId); - $customerId = (string) ($sub['customer'] ?? ''); + $subData = json_decode($sub->getBody(), true); + $customerId = (string) ($subData['customer'] ?? ''); } catch (\Throwable $_) { $customerId = ''; } @@ -368,7 +395,9 @@ class StripeAdapter implements Adapter $parts = []; foreach (explode(',', $signature) as $part) { [$k, $v] = array_pad(explode('=', trim($part), 2), 2, ''); - if ($k !== '') { $parts[$k] = $v; } + if ($k !== '') { + $parts[$k] = $v; + } } $ts = (string) ($parts['t'] ?? ''); $v1 = (string) ($parts['v1'] ?? ''); @@ -413,8 +442,12 @@ class StripeAdapter implements Adapter $prov = (array) ($providerMap['stripe'] ?? []); if ((string) ($prov['subscriptionId'] ?? '') === $stripeSubId) { $sub->setAttribute('status', $internalStatus); - if ($periodStart) $sub->setAttribute('currentPeriodStart', $periodStart); - if ($periodEnd) $sub->setAttribute('currentPeriodEnd', $periodEnd); + if ($periodStart) { + $sub->setAttribute('currentPeriodStart', $periodStart); + } + if ($periodEnd) { + $sub->setAttribute('currentPeriodEnd', $periodEnd); + } $this->dbForPlatform->updateDocument('payments_subscriptions', $sub->getId(), $sub); $changes['subscription'] = $sub->getId(); $changes['status'] = $internalStatus; @@ -461,8 +494,9 @@ class StripeAdapter implements Adapter { $eventName = 'appwrite.payments.feature.usage.' . $projectId . '.' . $planId . '.' . $featureId; $list = $this->request($apiKey, 'GET', '/billing/meters', ['limit' => 100]); - if (isset($list['data']) && is_array($list['data'])) { - foreach ($list['data'] as $m) { + $listData = json_decode($list->getBody(), true); + if (isset($listData['data']) && is_array($listData['data'])) { + foreach ($listData['data'] as $m) { if ((string) ($m['event_name'] ?? '') === $eventName) { $id = (string) ($m['id'] ?? ''); if ($id !== '' && (($m['active'] ?? true) === false)) { @@ -479,19 +513,23 @@ class StripeAdapter implements Adapter 'value_settings' => [ 'event_payload_key' => 'value' ], 'customer_mapping' => [ 'type' => 'by_id', 'event_payload_key' => 'stripe_customer_id' ], ]); - return (string) ($meter['id'] ?? ''); + $meterData = json_decode($meter->getBody(), true); + return (string) ($meterData['id'] ?? ''); } private function ensureCustomer(string $apiKey, Document $actor): string { // Persist per-actor customer id in platform DB cache (users/teams) with dedicated attribute $existing = (string) $actor->getAttribute('stripeCustomerId', ''); - if ($existing !== '') return $existing; + if ($existing !== '') { + return $existing; + } $customer = $this->request($apiKey, 'POST', '/customers', [ 'email' => $actor->getAttribute('email', ''), 'metadata' => [ 'project_id' => $this->project->getId(), 'actor_id' => $actor->getId() ] ]); - $customerId = (string) ($customer['id'] ?? ''); + $customerData = json_decode($customer->getBody(), true); + $customerId = (string) ($customerData['id'] ?? ''); try { $actor->setAttribute('stripeCustomerId', $customerId); $collection = $actor->getAttribute('kind', '') === 'team' ? 'teams' : 'users'; @@ -502,37 +540,39 @@ class StripeAdapter implements Adapter return $customerId; } - public function request(string $apiKey, string $method, string $path, array $params = []): array + public function request(string $apiKey, string $method, string $path, array $params = []): ClientProxy { - $ch = \curl_init(); - $url = 'https://api.stripe.com/v1' . $path; - $headers = [ 'Authorization: Bearer ' . $apiKey, 'Content-Type: application/x-www-form-urlencoded' ]; - \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - switch ($method) { - case 'GET': - if (!empty($params)) { $url .= '?' . http_build_query($params); } - break; - case 'POST': - \curl_setopt($ch, CURLOPT_POST, true); - if (!empty($params)) { \curl_setopt($ch, CURLOPT_POSTFIELDS, $this->buildFormData($params)); } - break; - case 'DELETE': - \curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); - if (!empty($params)) { \curl_setopt($ch, CURLOPT_POSTFIELDS, $this->buildFormData($params)); } - break; - } - \curl_setopt($ch, CURLOPT_URL, $url); - $response = \curl_exec($ch); - $httpCode = (int) \curl_getinfo($ch, CURLINFO_HTTP_CODE); - \curl_close($ch); - if ($response === false) { throw new \RuntimeException('Stripe API request failed'); } - $data = \json_decode($response, true); - if ($httpCode >= 400) { - $message = is_array($data) && isset($data['error']['message']) ? (string) $data['error']['message'] : 'Stripe API error'; - throw new \RuntimeException($message, $httpCode); - } - return is_array($data) ? $data : []; + // $ch = \curl_init(); + // $url = 'https://api.stripe.com/v1' . $path; + // $headers = [ 'Authorization: Bearer ' . $apiKey, 'Content-Type: application/x-www-form-urlencoded' ]; + // \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + // \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + // switch ($method) { + // case 'GET': + // if (!empty($params)) { $url .= '?' . http_build_query($params); } + // break; + // case 'POST': + // \curl_setopt($ch, CURLOPT_POST, true); + // if (!empty($params)) { \curl_setopt($ch, CURLOPT_POSTFIELDS, $this->buildFormData($params)); } + // break; + // case 'DELETE': + // \curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); + // if (!empty($params)) { \curl_setopt($ch, CURLOPT_POSTFIELDS, $this->buildFormData($params)); } + // break; + // } + // \curl_setopt($ch, CURLOPT_URL, $url); + // $response = \curl_exec($ch); + // $httpCode = (int) \curl_getinfo($ch, CURLINFO_HTTP_CODE); + // \curl_close($ch); + // if ($response === false) { throw new \RuntimeException('Stripe API request failed'); } + // $data = \json_decode($response, true); + // if ($httpCode >= 400) { + // $message = is_array($data) && isset($data['error']['message']) ? (string) $data['error']['message'] : 'Stripe API error'; + // throw new \RuntimeException($message, $httpCode); + // } + // return is_array($data) ? $data : []; + $response = request($method, $path, $params, ['headers' => [ 'Authorization: Bearer ' . $apiKey, 'Content-Type: application/x-www-form-urlencoded' ]]); + return $response; } private function buildFormData(array $params, string $prefix = ''): string @@ -549,5 +589,3 @@ class StripeAdapter implements Adapter return implode('&', $data); } } - - diff --git a/src/Appwrite/Platform/Appwrite.php b/src/Appwrite/Platform/Appwrite.php index 1356042c5a..0c7cd82dae 100644 --- a/src/Appwrite/Platform/Appwrite.php +++ b/src/Appwrite/Platform/Appwrite.php @@ -6,11 +6,11 @@ use Appwrite\Platform\Modules\Console; use Appwrite\Platform\Modules\Core; use Appwrite\Platform\Modules\Databases; use Appwrite\Platform\Modules\Functions; +use Appwrite\Platform\Modules\Payments; use Appwrite\Platform\Modules\Projects; use Appwrite\Platform\Modules\Proxy; use Appwrite\Platform\Modules\Sites; use Appwrite\Platform\Modules\Tokens; -use Appwrite\Platform\Modules\Payments; use Utopia\Platform\Platform; class Appwrite extends Platform diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Features/Create.php b/src/Appwrite/Platform/Modules/Payments/Http/Features/Create.php index 176b9c2372..9885e716ca 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Features/Create.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Features/Create.php @@ -65,8 +65,7 @@ class Create extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -90,5 +89,3 @@ class Create extends Base $response->json($created->getArrayCopy()); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Features/Delete.php b/src/Appwrite/Platform/Modules/Payments/Http/Features/Delete.php index c626acd19e..84e1edf554 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Features/Delete.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Features/Delete.php @@ -54,8 +54,7 @@ class Delete extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -78,5 +77,3 @@ class Delete extends Base $response->noContent(); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Features/Update.php b/src/Appwrite/Platform/Modules/Payments/Http/Features/Update.php index 368458d5e9..57af4ef21f 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Features/Update.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Features/Update.php @@ -66,8 +66,7 @@ class Update extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -86,12 +85,16 @@ class Update extends Base $response->json(['message' => 'Feature not found']); return; } - if ($name !== '') $feature->setAttribute('name', $name); - if ($type !== '') $feature->setAttribute('type', $type); - if ($description !== '') $feature->setAttribute('description', $description); + if ($name !== '') { + $feature->setAttribute('name', $name); + } + if ($type !== '') { + $feature->setAttribute('type', $type); + } + if ($description !== '') { + $feature->setAttribute('description', $description); + } $feature = $dbForPlatform->updateDocument('payments_features', $feature->getId(), $feature); $response->json($feature->getArrayCopy()); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Features/XList.php b/src/Appwrite/Platform/Modules/Payments/Http/Features/XList.php index 36a08a00fc..e98827adb4 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Features/XList.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Features/XList.php @@ -57,8 +57,7 @@ class XList extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { $filters = [ Query::equal('projectId', [$project->getId()]) ]; if ($search !== '') { $filters[] = Query::search('name', $search); @@ -70,5 +69,3 @@ class XList extends Base ]); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/Assign.php b/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/Assign.php index c8949fca17..68a4d6d7d2 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/Assign.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/Assign.php @@ -2,24 +2,24 @@ namespace Appwrite\Platform\Modules\Payments\Http\PlanFeatures; +use Appwrite\Event\Audit; +use Appwrite\Event\Event; +use Appwrite\Payments\Provider\ProviderState; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; -use Appwrite\Payments\Provider\ProviderState; -use Appwrite\Payments\Provider\Registry; use Appwrite\Utopia\Response; -use Appwrite\Event\Event; -use Appwrite\Event\Audit; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; -use Utopia\Validator\Text; -use Utopia\Validator\Integer; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; +use Utopia\Validator\Integer; +use Utopia\Validator\Text; class Assign extends Base { @@ -89,8 +89,7 @@ class Assign extends Base Document $project, Event $queueForEvents, Audit $queueForAudits - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -186,5 +185,3 @@ class Assign extends Base $response->json($created->getArrayCopy()); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/Remove.php b/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/Remove.php index 25bf517913..41718cdede 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/Remove.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/Remove.php @@ -2,14 +2,14 @@ namespace Appwrite\Platform\Modules\Payments\Http\PlanFeatures; +use Appwrite\Event\Audit; +use Appwrite\Event\Event; +use Appwrite\Payments\Provider\ProviderState; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; -use Appwrite\Payments\Provider\ProviderState; -use Appwrite\Payments\Provider\Registry; use Appwrite\Utopia\Response; -use Appwrite\Event\Event; -use Appwrite\Event\Audit; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; @@ -68,8 +68,7 @@ class Remove extends Base Document $project, Event $queueForEvents, Audit $queueForAudits - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -123,5 +122,3 @@ class Remove extends Base $response->noContent(); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/XList.php b/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/XList.php index f8c4874a36..04d08606eb 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/XList.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/PlanFeatures/XList.php @@ -57,8 +57,7 @@ class XList extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { $items = $dbForPlatform->find('payments_plan_features', [ Query::equal('projectId', [$project->getId()]), Query::equal('planId', [$planId]) @@ -69,5 +68,3 @@ class XList extends Base ]); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Plans/Create.php b/src/Appwrite/Platform/Modules/Payments/Http/Plans/Create.php index 0b25cf2423..ccbfb1f428 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Plans/Create.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Plans/Create.php @@ -2,14 +2,18 @@ namespace Appwrite\Platform\Modules\Payments\Http\Plans; +use Appwrite\AppwriteException; +use Appwrite\Extend\Exception as ExtendException; +use Appwrite\Payments\Provider\ProviderState; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\Query; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; -use Appwrite\Payments\Provider\ProviderState; -use Appwrite\Payments\Provider\Registry; -use Appwrite\Utopia\Response; use Appwrite\Utopia\Database\Validator\CustomId; +use Appwrite\Utopia\Response; +use Exception; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Platform\Action; @@ -78,8 +82,7 @@ class Create extends Base Database $dbForProject, Registry $registryPayments, Document $project - ) - { + ) { $document = new Document([ 'projectId' => $project->getId(), 'projectInternalId' => $project->getSequence(), @@ -104,6 +107,16 @@ class Create extends Base return; } + // Check if plan already exists + $existingPlan = $dbForPlatform->findOne('payments_plans', [ + Query::equal('projectId', [$project->getId()]), + Query::equal('planId', [$planId]) + ]); + if ($existingPlan !== null && !$existingPlan->isEmpty()) { + // TODO: create a custom exception for this + return new AppwriteException(ExtendException::RESOURCE_ALREADY_EXISTS); + } + $created = $dbForPlatform->createDocument('payments_plans', $document); // Provision on configured providers @@ -134,5 +147,3 @@ class Create extends Base $response->json($created->getArrayCopy()); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Plans/Delete.php b/src/Appwrite/Platform/Modules/Payments/Http/Plans/Delete.php index 33a420efce..1d687a1120 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Plans/Delete.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Plans/Delete.php @@ -5,7 +5,6 @@ namespace Appwrite\Platform\Modules\Payments\Http\Plans; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; -use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; @@ -55,8 +54,7 @@ class Delete extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -79,5 +77,3 @@ class Delete extends Base $response->noContent(); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Plans/Get.php b/src/Appwrite/Platform/Modules/Payments/Http/Plans/Get.php index 791ecbce78..faa466d837 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Plans/Get.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Plans/Get.php @@ -57,8 +57,7 @@ class Get extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { $plan = $dbForPlatform->findOne('payments_plans', [ Query::equal('projectId', [$project->getId()]), Query::equal('planId', [$planId]) @@ -73,5 +72,3 @@ class Get extends Base $response->dynamic($plan, Response::MODEL_PAYMENT_PLAN); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Plans/Update.php b/src/Appwrite/Platform/Modules/Payments/Http/Plans/Update.php index 9f42378ef4..cafbb9d38b 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Plans/Update.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Plans/Update.php @@ -2,12 +2,12 @@ namespace Appwrite\Platform\Modules\Payments\Http\Plans; +use Appwrite\Payments\Provider\ProviderState; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; -use Appwrite\Payments\Provider\ProviderState; -use Appwrite\Payments\Provider\Registry; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; @@ -78,8 +78,7 @@ class Update extends Base Database $dbForProject, Registry $registryPayments, Document $project - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -98,11 +97,17 @@ class Update extends Base $response->json(['message' => 'Plan not found']); return; } - if ($name !== '') $plan->setAttribute('name', $name); - if ($description !== '') $plan->setAttribute('description', $description); + if ($name !== '') { + $plan->setAttribute('name', $name); + } + if ($description !== '') { + $plan->setAttribute('description', $description); + } $plan->setAttribute('isDefault', $isDefault); $plan->setAttribute('isFree', $isFree); - if (!empty($pricing)) $plan->setAttribute('pricing', $pricing); + if (!empty($pricing)) { + $plan->setAttribute('pricing', $pricing); + } $plan = $dbForPlatform->updateDocument('payments_plans', $plan->getId(), $plan); // Update on providers if pricing changed or name/desc changed @@ -129,5 +134,3 @@ class Update extends Base $response->json($plan->getArrayCopy()); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Plans/XList.php b/src/Appwrite/Platform/Modules/Payments/Http/Plans/XList.php index d1df7965f8..09b562e9f1 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Plans/XList.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Plans/XList.php @@ -57,8 +57,7 @@ class XList extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { $filters = [ Query::equal('projectId', [$project->getId()]) ]; if ($search !== '') { $filters[] = Query::search('search', $search); @@ -71,5 +70,3 @@ class XList extends Base $response->dynamic(new Document($payload), Response::MODEL_PAYMENT_PLAN_LIST); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Providers/Actions/Test/Create.php b/src/Appwrite/Platform/Modules/Payments/Http/Providers/Actions/Test/Create.php index 479ee82c3c..3fab3b4e7e 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Providers/Actions/Test/Create.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Providers/Actions/Test/Create.php @@ -2,12 +2,12 @@ namespace Appwrite\Platform\Modules\Payments\Http\Providers\Actions\Test; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; -use Appwrite\Payments\Provider\Registry; use Utopia\Database\Document; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -63,5 +63,3 @@ class Create extends Base $response->json(['success' => $result->success, 'message' => $result->message]); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Providers/Get.php b/src/Appwrite/Platform/Modules/Payments/Http/Providers/Get.php index 6a92d34f12..0161ee0605 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Providers/Get.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Providers/Get.php @@ -55,12 +55,14 @@ class Get extends Base $payments = (array) $projectDoc->getAttribute('payments', []); $providers = (array) ($payments['providers'] ?? []); foreach ($providers as $pid => &$cfg) { - if (isset($cfg['secretKey'])) $cfg['secretKey'] = '***'; - if (isset($cfg['webhookSecret'])) $cfg['webhookSecret'] = '***'; + if (isset($cfg['secretKey'])) { + $cfg['secretKey'] = '***'; + } + if (isset($cfg['webhookSecret'])) { + $cfg['webhookSecret'] = '***'; + } } $payments['providers'] = $providers; $response->json(['payments' => $payments]); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Providers/Update.php b/src/Appwrite/Platform/Modules/Payments/Http/Providers/Update.php index a4e6c8c3df..fdfae7e014 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Providers/Update.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Providers/Update.php @@ -2,17 +2,16 @@ namespace Appwrite\Platform\Modules\Payments\Http\Providers; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; -use Appwrite\Payments\Provider\Registry; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; -use Utopia\Validator\ArrayList; use Utopia\Validator\JSON as JSONValidator; class Update extends Base @@ -103,12 +102,14 @@ class Update extends Base $out = (array) $updated->getAttribute('payments', []); $prov = (array) ($out['providers'] ?? []); foreach ($prov as $pid => &$cfg) { - if (isset($cfg['secretKey'])) $cfg['secretKey'] = '***'; - if (isset($cfg['webhookSecret'])) $cfg['webhookSecret'] = '***'; + if (isset($cfg['secretKey'])) { + $cfg['secretKey'] = '***'; + } + if (isset($cfg['webhookSecret'])) { + $cfg['webhookSecret'] = '***'; + } } $out['providers'] = $prov; $response->json(['payments' => $out]); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Cancel.php b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Cancel.php index cc9e350f86..265e911dfe 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Cancel.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Cancel.php @@ -2,11 +2,11 @@ namespace Appwrite\Platform\Modules\Payments\Http\Subscriptions; +use Appwrite\Payments\Provider\ProviderState; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; -use Appwrite\Payments\Provider\ProviderState; -use Appwrite\Payments\Provider\Registry; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; @@ -62,8 +62,7 @@ class Cancel extends Base Document $user, Registry $registryPayments, Document $project - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -131,5 +130,3 @@ class Cancel extends Base $response->noContent(); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Create.php b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Create.php index f90052c691..3d8e3da2f2 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Create.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Create.php @@ -2,13 +2,13 @@ namespace Appwrite\Platform\Modules\Payments\Http\Subscriptions; +use Appwrite\Event\Event; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; -use Appwrite\Payments\Provider\Registry; use Appwrite\Utopia\Response; -use Appwrite\Event\Event; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; @@ -79,8 +79,7 @@ class Create extends Base Registry $registryPayments, Document $project, Event $queueForEvents - ) - { + ) { // Feature flag: block if payments disabled $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -158,42 +157,66 @@ class Create extends Base $state = new \Appwrite\Payments\Provider\ProviderState((string) $primary, $config, (array) ($config['state'] ?? [])); // Find the fixed plan price (not metered features) - $planPriceId = null; + // Plan prices are stored first in the prices array, followed by feature prices $priceIds = (array) ($planProviders[$primary]['prices'] ?? []); - $apiKey = (string) ($config['secretKey'] ?? ''); + // If no prices in plan providers, return error + if (empty($priceIds)) { + $response->setStatusCode(Response::STATUS_CODE_BAD_REQUEST); + $response->json(['message' => 'Plan has no prices configured for provider: ' . $primary]); + return; + } + + // Use the first price ID as the plan price + // Plan prices are created first and stored first in the array (see StripeAdapter::ensurePlan) + $planPriceId = null; foreach ($priceIds as $priceId) { - // Fetch price details to check metadata - try { - $priceData = $adapter->request($apiKey, 'GET', '/prices/' . $priceId); - if (($priceData['metadata']['type'] ?? '') === 'payments_plan_price') { - $planPriceId = $priceId; - break; - } - } catch (\Throwable $e) { - // Skip invalid prices - continue; + if (!empty($priceId)) { + $planPriceId = $priceId; + break; } } - // Create checkout session if we have URLs - if ($planPriceId && $successUrl !== '' && $cancelUrl !== '') { - $checkoutSession = $adapter->createCheckoutSession($payer, [ - 'priceId' => $planPriceId - ], $state, [ - 'successUrl' => $successUrl, - 'cancelUrl' => $cancelUrl - ]); - $checkoutUrl = $checkoutSession->url; + if ($planPriceId === null) { + $response->setStatusCode(Response::STATUS_CODE_BAD_REQUEST); + $response->json(['message' => 'Plan has no valid prices configured for provider: ' . $primary]); + return; } - $subRef = $adapter->ensureSubscription($payer, [ - 'planId' => $planId, - 'planProviders' => $planProviders - ], $state); - $providerData = [ (string) $primary => [ 'subscriptionId' => $subRef->externalSubscriptionId ] ]; - // Use status from provider if available - $initialStatus = (string) ($subRef->metadata['status'] ?? 'pending'); + // Create checkout session if we have a price ID and URLs + if ($planPriceId && $successUrl !== '' && $cancelUrl !== '') { + try { + $checkoutSession = $adapter->createCheckoutSession($payer, [ + 'priceId' => $planPriceId + ], $state, [ + 'successUrl' => $successUrl, + 'cancelUrl' => $cancelUrl + ]); + $checkoutUrl = $checkoutSession->url; + } catch (\Throwable $e) { + // Log error but continue with subscription creation + // The subscription can be created without checkout URL for manual payment flows + } + } + + // Create or ensure subscription exists in provider + try { + $subRef = $adapter->ensureSubscription($payer, [ + 'planId' => $planId, + 'planProviders' => $planProviders + ], $state); + $providerData = [ (string) $primary => [ 'subscriptionId' => $subRef->externalSubscriptionId ] ]; + // Use status from provider if available + $initialStatus = (string) ($subRef->metadata['status'] ?? 'pending'); + } catch (\Throwable $e) { + $response->setStatusCode(Response::STATUS_CODE_INTERNAL_SERVER_ERROR); + $response->json(['message' => 'Failed to create subscription: ' . $e->getMessage()]); + return; + } + } else { + $response->setStatusCode(Response::STATUS_CODE_BAD_REQUEST); + $response->json(['message' => 'No payment provider configured for this project']); + return; } $subscription = new Document([ @@ -233,5 +256,3 @@ class Create extends Base $response->json($responseData); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Get.php b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Get.php index 4ebdd46eef..0047514f22 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Get.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Get.php @@ -57,8 +57,7 @@ class Get extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { $sub = $dbForPlatform->findOne('payments_subscriptions', [ Query::equal('projectId', [$project->getId()]), Query::equal('subscriptionId', [$subscriptionId]) @@ -75,10 +74,10 @@ class Get extends Base Query::equal('projectId', [$project->getId()]), Query::equal('planId', [$planId]) ]); - if ($plan) $arr['plan'] = $plan->getArrayCopy(); + if ($plan) { + $arr['plan'] = $plan->getArrayCopy(); + } } $response->dynamic(new Document($arr), Response::MODEL_PAYMENT_SUBSCRIPTION); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Resume.php b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Resume.php index 6d34d091d2..2251c1e1a7 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Resume.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Resume.php @@ -2,11 +2,11 @@ namespace Appwrite\Platform\Modules\Payments\Http\Subscriptions; +use Appwrite\Payments\Provider\ProviderState; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; -use Appwrite\Payments\Provider\ProviderState; -use Appwrite\Payments\Provider\Registry; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; @@ -62,8 +62,7 @@ class Resume extends Base Document $user, Registry $registryPayments, Document $project - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -131,5 +130,3 @@ class Resume extends Base $response->noContent(); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Update.php b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Update.php index 5d7d00c03f..1994960a44 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Update.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/Update.php @@ -2,12 +2,12 @@ namespace Appwrite\Platform\Modules\Payments\Http\Subscriptions; +use Appwrite\Payments\Provider\ProviderState; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; -use Appwrite\Payments\Provider\ProviderState; -use Appwrite\Payments\Provider\Registry; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; @@ -73,8 +73,7 @@ class Update extends Base Document $user, Registry $registryPayments, Document $project - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -154,5 +153,3 @@ class Update extends Base $response->json($sub->getArrayCopy()); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/XList.php b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/XList.php index ff3ad3a588..a56c420023 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/XList.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Subscriptions/XList.php @@ -61,12 +61,17 @@ class XList extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { $filters = [ Query::equal('projectId', [$project->getId()]) ]; - if ($actorType !== '') $filters[] = Query::equal('actorType', [$actorType]); - if ($actorId !== '') $filters[] = Query::equal('actorId', [$actorId]); - if ($status !== '') $filters[] = Query::equal('status', [$status]); + if ($actorType !== '') { + $filters[] = Query::equal('actorType', [$actorType]); + } + if ($actorId !== '') { + $filters[] = Query::equal('actorId', [$actorId]); + } + if ($status !== '') { + $filters[] = Query::equal('status', [$status]); + } $list = $dbForPlatform->find('payments_subscriptions', $filters); $plansById = []; foreach ($list as $sub) { @@ -76,7 +81,9 @@ class XList extends Base Query::equal('projectId', [$project->getId()]), Query::equal('planId', [$planId]) ]); - if ($plan) $plansById[$planId] = $plan; + if ($plan) { + $plansById[$planId] = $plan; + } } } $subs = []; @@ -91,5 +98,3 @@ class XList extends Base $response->dynamic(new Document(['total' => count($subs), 'subscriptions' => $subs]), Response::MODEL_PAYMENT_SUBSCRIPTION_LIST); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Usage/Create.php b/src/Appwrite/Platform/Modules/Payments/Http/Usage/Create.php index 6cd3b6795b..eb897a7e55 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Usage/Create.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Usage/Create.php @@ -66,8 +66,7 @@ class Create extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { // Feature flag: block if payments disabled for project $projDoc = $dbForPlatform->getDocument('projects', $project->getId()); $paymentsCfg = (array) $projDoc->getAttribute('payments', []); @@ -105,5 +104,3 @@ class Create extends Base $response->json($created->getArrayCopy()); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Usage/Events/XList.php b/src/Appwrite/Platform/Modules/Payments/Http/Usage/Events/XList.php index 05af15fdc5..8db43372cb 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Usage/Events/XList.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Usage/Events/XList.php @@ -62,11 +62,14 @@ class XList extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { $filters = [ Query::equal('projectId', [$project->getId()]) ]; - if ($subscriptionId !== '') $filters[] = Query::equal('subscriptionId', [$subscriptionId]); - if ($featureId !== '') $filters[] = Query::equal('featureId', [$featureId]); + if ($subscriptionId !== '') { + $filters[] = Query::equal('subscriptionId', [$subscriptionId]); + } + if ($featureId !== '') { + $filters[] = Query::equal('featureId', [$featureId]); + } $list = $dbForPlatform->find('payments_usage_events', $filters); $response->json([ 'total' => count($list), @@ -74,5 +77,3 @@ class XList extends Base ]); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Payments/Http/Usage/Get.php index c0045b205a..a0e7659464 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Usage/Get.php @@ -60,8 +60,7 @@ class Get extends Base Response $response, Database $dbForPlatform, Document $project - ) - { + ) { $events = $dbForPlatform->find('payments_usage_events', [ Query::equal('projectId', [$project->getId()]), Query::equal('subscriptionId', [$subscriptionId]) @@ -77,5 +76,3 @@ class Get extends Base ]); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Usage/Reconcile/Create.php b/src/Appwrite/Platform/Modules/Payments/Http/Usage/Reconcile/Create.php index ac192cb463..4efc13c4fc 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Usage/Reconcile/Create.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Usage/Reconcile/Create.php @@ -2,11 +2,11 @@ namespace Appwrite\Platform\Modules\Payments\Http\Usage\Reconcile; +use Appwrite\Payments\Provider\Registry as ProviderRegistry; use Appwrite\Platform\Modules\Compute\Base; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\Utopia\Response; -use Appwrite\Payments\Provider\Registry as ProviderRegistry; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; @@ -96,5 +96,3 @@ class Create extends Base $response->noContent(); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Http/Webhooks/Provider/Create.php b/src/Appwrite/Platform/Modules/Payments/Http/Webhooks/Provider/Create.php index 6cc7823048..d985ed5e6e 100644 --- a/src/Appwrite/Platform/Modules/Payments/Http/Webhooks/Provider/Create.php +++ b/src/Appwrite/Platform/Modules/Payments/Http/Webhooks/Provider/Create.php @@ -2,12 +2,10 @@ namespace Appwrite\Platform\Modules\Payments\Http\Webhooks\Provider; +use Appwrite\Payments\Provider\Registry; use Appwrite\Platform\Modules\Compute\Base; -use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\Utopia\Response; -use Appwrite\Payments\Provider\Registry; -use Utopia\Database\Document; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -68,12 +66,14 @@ class Create extends Base $payload = \file_get_contents('php://input') ?: ''; $signature = (string) ($request->getHeader('stripe-signature') ?? ''); $json = []; - try { $json = \json_decode($payload, true) ?: []; } catch (\Throwable $e) { $json = []; } + try { + $json = \json_decode($payload, true) ?: []; + } catch (\Throwable $e) { + $json = []; + } $json['_signature'] = $signature; $json['_raw'] = $payload; - $registryPayments->get($providerId, $config, $project, $dbForPlatform, $dbForProject)->handleWebhook($json , new \Appwrite\Payments\Provider\ProviderState($providerId, $config, (array) ($config['state'] ?? []))); + $registryPayments->get($providerId, $config, $project, $dbForPlatform, $dbForProject)->handleWebhook($json, new \Appwrite\Payments\Provider\ProviderState($providerId, $config, (array) ($config['state'] ?? []))); $response->noContent(); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Module.php b/src/Appwrite/Platform/Modules/Payments/Module.php index ba9f1d59dc..bd09d044cd 100644 --- a/src/Appwrite/Platform/Modules/Payments/Module.php +++ b/src/Appwrite/Platform/Modules/Payments/Module.php @@ -14,5 +14,3 @@ class Module extends Platform\Module $this->addService('workers', new Workers()); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Services/Http.php b/src/Appwrite/Platform/Modules/Payments/Services/Http.php index 2d4fcb0bc9..616225532b 100644 --- a/src/Appwrite/Platform/Modules/Payments/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Payments/Services/Http.php @@ -2,31 +2,31 @@ namespace Appwrite\Platform\Modules\Payments\Services; -use Appwrite\Platform\Modules\Payments\Http\Plans\Create as PlansCreate; -use Appwrite\Platform\Modules\Payments\Http\Plans\Get as PlansGet; -use Appwrite\Platform\Modules\Payments\Http\Plans\XList as PlansList; -use Appwrite\Platform\Modules\Payments\Http\Plans\Update as PlansUpdate; -use Appwrite\Platform\Modules\Payments\Http\Plans\Delete as PlansDelete; use Appwrite\Platform\Modules\Payments\Http\Features\Create as FeaturesCreate; -use Appwrite\Platform\Modules\Payments\Http\Features\XList as FeaturesList; -use Appwrite\Platform\Modules\Payments\Http\Features\Update as FeaturesUpdate; use Appwrite\Platform\Modules\Payments\Http\Features\Delete as FeaturesDelete; +use Appwrite\Platform\Modules\Payments\Http\Features\Update as FeaturesUpdate; +use Appwrite\Platform\Modules\Payments\Http\Features\XList as FeaturesList; use Appwrite\Platform\Modules\Payments\Http\PlanFeatures\Assign as PlanFeaturesAssign; -use Appwrite\Platform\Modules\Payments\Http\PlanFeatures\XList as PlanFeaturesList; use Appwrite\Platform\Modules\Payments\Http\PlanFeatures\Remove as PlanFeaturesRemove; -use Appwrite\Platform\Modules\Payments\Http\Subscriptions\Create as SubscriptionsCreate; -use Appwrite\Platform\Modules\Payments\Http\Subscriptions\XList as SubscriptionsList; -use Appwrite\Platform\Modules\Payments\Http\Subscriptions\Get as SubscriptionsGet; -use Appwrite\Platform\Modules\Payments\Http\Subscriptions\Update as SubscriptionsUpdate; -use Appwrite\Platform\Modules\Payments\Http\Subscriptions\Cancel as SubscriptionsCancel; -use Appwrite\Platform\Modules\Payments\Http\Subscriptions\Resume as SubscriptionsResume; -use Appwrite\Platform\Modules\Payments\Http\Usage\Get as UsageGet; -use Appwrite\Platform\Modules\Payments\Http\Usage\Create as UsageCreate; -use Appwrite\Platform\Modules\Payments\Http\Usage\Events\XList as UsageEventsList; -use Appwrite\Platform\Modules\Payments\Http\Usage\Reconcile\Create as UsageReconcile; +use Appwrite\Platform\Modules\Payments\Http\PlanFeatures\XList as PlanFeaturesList; +use Appwrite\Platform\Modules\Payments\Http\Plans\Create as PlansCreate; +use Appwrite\Platform\Modules\Payments\Http\Plans\Delete as PlansDelete; +use Appwrite\Platform\Modules\Payments\Http\Plans\Get as PlansGet; +use Appwrite\Platform\Modules\Payments\Http\Plans\Update as PlansUpdate; +use Appwrite\Platform\Modules\Payments\Http\Plans\XList as PlansList; +use Appwrite\Platform\Modules\Payments\Http\Providers\Actions\Test\Create as ProvidersTest; use Appwrite\Platform\Modules\Payments\Http\Providers\Get as ProvidersGet; use Appwrite\Platform\Modules\Payments\Http\Providers\Update as ProvidersUpdate; -use Appwrite\Platform\Modules\Payments\Http\Providers\Actions\Test\Create as ProvidersTest; +use Appwrite\Platform\Modules\Payments\Http\Subscriptions\Cancel as SubscriptionsCancel; +use Appwrite\Platform\Modules\Payments\Http\Subscriptions\Create as SubscriptionsCreate; +use Appwrite\Platform\Modules\Payments\Http\Subscriptions\Get as SubscriptionsGet; +use Appwrite\Platform\Modules\Payments\Http\Subscriptions\Resume as SubscriptionsResume; +use Appwrite\Platform\Modules\Payments\Http\Subscriptions\Update as SubscriptionsUpdate; +use Appwrite\Platform\Modules\Payments\Http\Subscriptions\XList as SubscriptionsList; +use Appwrite\Platform\Modules\Payments\Http\Usage\Create as UsageCreate; +use Appwrite\Platform\Modules\Payments\Http\Usage\Events\XList as UsageEventsList; +use Appwrite\Platform\Modules\Payments\Http\Usage\Get as UsageGet; +use Appwrite\Platform\Modules\Payments\Http\Usage\Reconcile\Create as UsageReconcile; use Appwrite\Platform\Modules\Payments\Http\Webhooks\Provider\Create as WebhookProviderCreate; use Utopia\Platform\Service; @@ -77,5 +77,3 @@ class Http extends Service $this->addAction(WebhookProviderCreate::getName(), new WebhookProviderCreate()); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Services/Workers.php b/src/Appwrite/Platform/Modules/Payments/Services/Workers.php index f15f7e8d66..5478c744a2 100644 --- a/src/Appwrite/Platform/Modules/Payments/Services/Workers.php +++ b/src/Appwrite/Platform/Modules/Payments/Services/Workers.php @@ -13,5 +13,3 @@ class Workers extends Service $this->addAction(UsageSync::getName(), new UsageSync()); } } - - diff --git a/src/Appwrite/Platform/Modules/Payments/Workers/UsageSync.php b/src/Appwrite/Platform/Modules/Payments/Workers/UsageSync.php index 0e4a5802ff..4e865c853d 100644 --- a/src/Appwrite/Platform/Modules/Payments/Workers/UsageSync.php +++ b/src/Appwrite/Platform/Modules/Payments/Workers/UsageSync.php @@ -2,10 +2,10 @@ namespace Appwrite\Platform\Modules\Payments\Workers; -use Appwrite\Payments\Provider\Registry as ProviderRegistry; -use Appwrite\Platform\Action; use Appwrite\Payments\Provider\ProviderState; use Appwrite\Payments\Provider\ProviderSubscriptionRef; +use Appwrite\Payments\Provider\Registry as ProviderRegistry; +use Appwrite\Platform\Action; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; @@ -99,5 +99,3 @@ class UsageSync extends Action } } } - - diff --git a/src/Appwrite/Platform/Services/Tasks.php b/src/Appwrite/Platform/Services/Tasks.php index 7d296be404..cbe7a41c6b 100644 --- a/src/Appwrite/Platform/Services/Tasks.php +++ b/src/Appwrite/Platform/Services/Tasks.php @@ -10,6 +10,7 @@ use Appwrite\Platform\Tasks\QueueRetry; use Appwrite\Platform\Tasks\ScheduleExecutions; use Appwrite\Platform\Tasks\ScheduleFunctions; use Appwrite\Platform\Tasks\ScheduleMessages; +use Appwrite\Platform\Tasks\SchedulePaymentsUsage; use Appwrite\Platform\Tasks\Screenshot; use Appwrite\Platform\Tasks\SDKs; use Appwrite\Platform\Tasks\Specs; @@ -18,7 +19,6 @@ use Appwrite\Platform\Tasks\StatsResources; use Appwrite\Platform\Tasks\Upgrade; use Appwrite\Platform\Tasks\Vars; use Appwrite\Platform\Tasks\Version; -use Appwrite\Platform\Tasks\SchedulePaymentsUsage; use Utopia\Platform\Service; class Tasks extends Service diff --git a/src/Appwrite/Platform/Tasks/SchedulePaymentsUsage.php b/src/Appwrite/Platform/Tasks/SchedulePaymentsUsage.php index 46106766f5..9ec028c6f2 100644 --- a/src/Appwrite/Platform/Tasks/SchedulePaymentsUsage.php +++ b/src/Appwrite/Platform/Tasks/SchedulePaymentsUsage.php @@ -11,7 +11,6 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Queue\Broker\Pool as BrokerPool; -use Utopia\Queue\Publisher; use Utopia\System\System; class SchedulePaymentsUsage extends Action @@ -67,5 +66,3 @@ class SchedulePaymentsUsage extends Action }, $interval); } } - - diff --git a/src/Appwrite/Utopia/Response/Model/PaymentFeature.php b/src/Appwrite/Utopia/Response/Model/PaymentFeature.php index 760e5fa34c..e68461cdc4 100644 --- a/src/Appwrite/Utopia/Response/Model/PaymentFeature.php +++ b/src/Appwrite/Utopia/Response/Model/PaymentFeature.php @@ -52,5 +52,3 @@ class PaymentFeature extends Model return Response::MODEL_PAYMENT_FEATURE; } } - - diff --git a/src/Appwrite/Utopia/Response/Model/PaymentPlan.php b/src/Appwrite/Utopia/Response/Model/PaymentPlan.php index 9e6eb45bf0..57e6d8b78a 100644 --- a/src/Appwrite/Utopia/Response/Model/PaymentPlan.php +++ b/src/Appwrite/Utopia/Response/Model/PaymentPlan.php @@ -32,5 +32,3 @@ class PaymentPlan extends Model return Response::MODEL_PAYMENT_PLAN; } } - - diff --git a/src/Appwrite/Utopia/Response/Model/PaymentSubscription.php b/src/Appwrite/Utopia/Response/Model/PaymentSubscription.php index 745936bdd9..cf3f748327 100644 --- a/src/Appwrite/Utopia/Response/Model/PaymentSubscription.php +++ b/src/Appwrite/Utopia/Response/Model/PaymentSubscription.php @@ -64,5 +64,3 @@ class PaymentSubscription extends Model return Response::MODEL_PAYMENT_SUBSCRIPTION; } } - -