diff --git a/services/nginx/app/classes/stripe.php b/services/nginx/app/classes/stripe.php new file mode 100644 index 00000000..30b3e44f --- /dev/null +++ b/services/nginx/app/classes/stripe.php @@ -0,0 +1,127 @@ +config = new stripe_c(); + $this->customers = new stripe_endpoint_customers(); + $this->payment_link = new stripe_endpoint_payment_link(); + $this->product = new stripe_endpoint_product(); + $this->prices = new stripe_endpoint_prices(); + } + + /** + * @inheritDoc + * @throws Exception + */ + public function getClient(): StripeClient + { + // Get the stripe client + if (!isset($this->client)) { + // Require the module to be enabled + self::requireModuleEnabled(); + // Require the secret key to be set + self::requireValidSecretKey(); + // Require the publishable key to be set + self::requireValidPublishableKey(); + // Create the client + $this->client = new StripeClient([ + 'api_key' => $this->config->secret_key->getVariableValue() + ]); + } + return $this->client; + } + + /** + * @inheritDoc + * @throws Exception + */ + function requireModuleEnabled(): void + { + // Check if the module is enabled + if (!$this->config->enabled->isTrue()) { + throw new Exception('The Stripe module is not enabled'); + } + } + + /** + * @inheritDoc + * @throws Exception + */ + function requireValidSecretKey(): void + { + // Check if the secret key is valid + if ($this->config->secret_key->getVariableValue() === null) { + throw new Exception('Invalid secret key'); + } + } + + /** + * @inheritDoc + * @throws Exception + */ + public function requireValidPublishableKey(): void + { + // Check if the publishable key is valid + if ($this->config->publishable_key->getVariableValue() === null) { + throw new Exception('Invalid publishable key'); + } + } +} \ No newline at end of file diff --git a/services/nginx/app/index.php b/services/nginx/app/index.php index 47a9dde3..fd11e5f1 100644 --- a/services/nginx/app/index.php +++ b/services/nginx/app/index.php @@ -59,6 +59,7 @@ require_once 'classes/recaptcha.php'; require_once 'classes/email.php'; require_once 'classes/backup_store.php'; require_once 'classes/motorapi.php'; +require_once 'classes/stripe.php'; /** * Modules diff --git a/services/nginx/app/interfaces/stripe_i.php b/services/nginx/app/interfaces/stripe_i.php new file mode 100644 index 00000000..e2122967 --- /dev/null +++ b/services/nginx/app/interfaces/stripe_i.php @@ -0,0 +1,32 @@ +customers->create($data); + } + + /** + * Retrieve a customer + * @param string $id + * @return Customer + * @throws ApiErrorException + * @throws Exception + */ + public function retrieve(string $id): Customer + { + return self::getClient()->customers->retrieve($id); + } + + /** + * Update a customer + * @param string $id + * @param array $data + * @return Customer + * @throws ApiErrorException + * @throws Exception + */ + public function update(string $id, array $data): Customer + { + return self::getClient()->customers->update($id, $data); + } + + /** + * Delete a customer + * @param string $id + * @return Customer + * @throws Exception + */ + public function delete(string $id): Customer + { + return self::getClient()->customers->delete($id); + } + + /** + * List all customers + * @return Collection + * @throws ApiErrorException + * @throws Exception + */ + public function list(): Collection + { + return self::getClient()->customers->all(); + } + +} \ No newline at end of file diff --git a/services/nginx/app/modules/stripe/endpoints/stripe_endpoint_payment_link.php b/services/nginx/app/modules/stripe/endpoints/stripe_endpoint_payment_link.php new file mode 100644 index 00000000..e4703ad7 --- /dev/null +++ b/services/nginx/app/modules/stripe/endpoints/stripe_endpoint_payment_link.php @@ -0,0 +1,75 @@ +paymentLinks->retrieve($id); + } + + /** + * @throws ApiErrorException + * @throws Exception + */ + public function generate(int $order_id, string $email): PaymentLink + { + $order = (new orders_o())->select($order_id); + $order->requireSelected(); + // Get the order items + $order_items = $order->getOrderItems($order_id); + // Create a new line items object + $line_items = new stripe_line_items(); + // Loop through the order items + foreach ( $order_items as $order_item ) { + // Add the order item to the line items + $line_items->add( + new stripe_line_item( + $order_item['product_id'], + $order_item['price'], + $order_item['quantity'] + ) + ); + } + // Create the payment link + return $this->create($line_items, [ + 'order_id' => $order_id, + 'email' => $email + ]); + } + + /** + * Create a new payment link + * @param stripe_line_items $line_items + * @param array $metadata Additional metadata + * @return PaymentLink + * @throws ApiErrorException + * @throws Exception + */ + public function create(stripe_line_items $line_items, array $metadata = []): PaymentLink + { + return self::getClient()->paymentLinks->create([ + 'line_items' => $line_items->get(), + 'metadata' => $metadata + ]); + } + +} \ No newline at end of file diff --git a/services/nginx/app/modules/stripe/endpoints/stripe_endpoint_prices.php b/services/nginx/app/modules/stripe/endpoints/stripe_endpoint_prices.php new file mode 100644 index 00000000..053db290 --- /dev/null +++ b/services/nginx/app/modules/stripe/endpoints/stripe_endpoint_prices.php @@ -0,0 +1,49 @@ +prices->all(); + } + + /** + * @throws ApiErrorException + * @throws Exception + */ + public function create(stripe_price $stripe_price): \Stripe\Price + { + return self::getClient()->prices->create([ + 'unit_amount' => $stripe_price->getUnitAmount(), + 'currency' => $stripe_price->getCurrency(), + 'product' => $stripe_price->getProductID(), + ]); + } + + /** + * @throws ApiErrorException + * @throws Exception + */ + public function retrieve(string $id): \Stripe\Price + { + return self::getClient()->prices->retrieve($id); + } + + +} \ No newline at end of file diff --git a/services/nginx/app/modules/stripe/endpoints/stripe_endpoint_product.php b/services/nginx/app/modules/stripe/endpoints/stripe_endpoint_product.php new file mode 100644 index 00000000..38696ca7 --- /dev/null +++ b/services/nginx/app/modules/stripe/endpoints/stripe_endpoint_product.php @@ -0,0 +1,54 @@ +products->all(); + } + + /** + * Create a new product + * @param stripe_product $product + * @return Product + * @throws ApiErrorException + * @throws Exception + */ + public function create(stripe_product $product): Product + { + return self::getClient()->products->create( + $product->get() + ); + } + + /** + * Retrieve a product + * @param string $id + * @return Product + * @throws ApiErrorException + * @throws Exception + */ + public function retrieve(string $id): Product + { + return self::getClient()->products->retrieve($id); + } + + +} \ No newline at end of file diff --git a/services/nginx/app/modules/stripe/helpers/stripe_line_item.php b/services/nginx/app/modules/stripe/helpers/stripe_line_item.php new file mode 100644 index 00000000..def695af --- /dev/null +++ b/services/nginx/app/modules/stripe/helpers/stripe_line_item.php @@ -0,0 +1,109 @@ +product_id = $product_id; + $this->price = $price; + $this->quantity = $quantity; + } + + /** + * Check if a product exists + * @param int $product_id + * @return bool + */ + public static function doesProductExist(int $product_id): bool + { + // Check if the product exists + $stripe = new stripe(); + try { + $stripe->product->retrieve($product_id); + return true; + } catch (ApiErrorException|Exception $e) { + return false; + } + } + + /** + * Create a product + * @param int $product_id + * @throws ApiErrorException + * @throws Exception + */ + public static function createProduct(int $product_id): void + { + // Create a new product + $stripe = new stripe(); + $stripe->product->create( + new stripe_product($product_id) + ); + } + + /** + * Create a price + * @param int $product_id + * @param int $unit_amount + * @throws ApiErrorException + */ + private function createPrice(int $product_id, int $unit_amount): void + { + // Create a new price + $stripe = new stripe(); + $price = $stripe->prices->create( + new stripe_price($product_id, $unit_amount) + ); + $this->price_id = $price->id; + } + + public function __toString(): string + { + // Return the line item as a JSON string + return json_encode( + self::get() + ); + } + + public function get(): array + { + return [ + //'product' => (int)$this->product_id, + 'price' => (string)$this->price_id, + 'quantity' => (int)$this->quantity, + ]; + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/stripe/helpers/stripe_line_items.php b/services/nginx/app/modules/stripe/helpers/stripe_line_items.php new file mode 100644 index 00000000..0c82621e --- /dev/null +++ b/services/nginx/app/modules/stripe/helpers/stripe_line_items.php @@ -0,0 +1,32 @@ +line_items as $line_item ) { + $line_items[] = is_array($line_item) ? $line_item : $line_item->get(); + } + return $line_items; + } + + public function add(stripe_line_item|array $line_item): void + { + $this->line_items[] = $line_item; + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/stripe/helpers/stripe_price.php b/services/nginx/app/modules/stripe/helpers/stripe_price.php new file mode 100644 index 00000000..eb221102 --- /dev/null +++ b/services/nginx/app/modules/stripe/helpers/stripe_price.php @@ -0,0 +1,36 @@ +product_id = $product_id; + $this->unit_amount = $unit_amount; + $this->currency = $currency; + } + + public function getProductID(): int + { + return $this->product_id; + } + + public function getUnitAmount(): int + { + return $this->unit_amount; + } + + public function getCurrency(): string + { + return $this->currency; + } + + +} \ No newline at end of file diff --git a/services/nginx/app/modules/stripe/helpers/stripe_product.php b/services/nginx/app/modules/stripe/helpers/stripe_product.php new file mode 100644 index 00000000..39950802 --- /dev/null +++ b/services/nginx/app/modules/stripe/helpers/stripe_product.php @@ -0,0 +1,50 @@ +select($id); + $product->requireSelected(); + $this->id = $id; + $this->product = $product; + } + + public function __toString(): string + { + // Return the line item as a JSON string + return json_encode( + self::get() + ); + } + + public function get(): array + { + return [ + 'name' => $this->product->name->value(), + 'id' => $this->id, + ]; + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/stripe/stripe_c.php b/services/nginx/app/modules/stripe/stripe_c.php new file mode 100644 index 00000000..69360d31 --- /dev/null +++ b/services/nginx/app/modules/stripe/stripe_c.php @@ -0,0 +1,45 @@ +setupConfig('Stripe'); + $this->allowUpdate([ + stripe_enabled_c::class, + stripe_publishable_key_c::class, + stripe_secret_key_c::class + ]); + $this->enabled = new stripe_enabled_c(); + $this->publishable_key = new stripe_publishable_key_c(); + $this->secret_key = new stripe_secret_key_c(); + } +} \ No newline at end of file diff --git a/services/nginx/app/objects/orders_o.php b/services/nginx/app/objects/orders_o.php index a1d78048..2328b102 100644 --- a/services/nginx/app/objects/orders_o.php +++ b/services/nginx/app/objects/orders_o.php @@ -22,57 +22,13 @@ class orders_o extends db public economic_module_orders $economic_module_orders; public object_property $created_at; public object_property $deleted_at; + public stripe_module_orders_o $stripe_module_orders; public function structure(): void { $this->setTable('orders'); } - public function objectChanged(): void - { - // Since the orders object is not cached, there is no need to invalidate the cache - } - - public function add(int $customer_id, int $cashier_id, string $reference, string $notes, int $department_id, string $reg_1 = '', string $reg_2 = '', string $reg_3 = ''): orders_o - { - global $db, $response; - try { - // Avoid SQL injection - $reference = $db->escape_string($reference); - $notes = $db->escape_string($notes); - $reg_1 = $db->escape_string($reg_1); - $reg_2 = $db->escape_string($reg_2); - $reg_3 = $db->escape_string($reg_3); - // Create a new record in the database - $sql = "INSERT INTO $this->table (customer_id, cashier_id, reference, notes, department_id, reg_1, reg_2, reg_3) VALUES ($customer_id, $cashier_id, '$reference', '$notes', $department_id, '$reg_1', '$reg_2', '$reg_3')"; - $db->query($sql); - - // Get the id of the new record - $this->id = $db->insert_id(); - - // Set the values of the object properties - $this->getObjectProperties(); - return $this; - } catch (\Exception $e) { - $response->error($e->getMessage()); - } - } - - public function getObjectProperties(): void - { - $this->customer_id = new object_property($this->table, $this->id, 'customer_id', 'int', true); - $this->cashier_id = new object_property($this->table, $this->id, 'cashier_id', 'int', true); - $this->reference = new object_property($this->table, $this->id, 'reference', 'string', true); - $this->notes = new object_property($this->table, $this->id, 'notes', 'string', false); - $this->department_id = new object_property($this->table, $this->id, 'department_id', 'int', true); - $this->reg_1 = new object_property($this->table, $this->id, 'reg_1', 'string', false); - $this->reg_2 = new object_property($this->table, $this->id, 'reg_2', 'string', false); - $this->reg_3 = new object_property($this->table, $this->id, 'reg_3', 'string', false); - $this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false); - $this->economic_module_orders = (new economic_module_orders())->getByOrderId($this->id); - $this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false); - } - public function edit(int $id, int $customer_id, int $cashier_id, string $reference, string $notes, int $department_id): void { global $db, $response; @@ -92,6 +48,22 @@ class orders_o extends db } } + public function getObjectProperties(): void + { + $this->customer_id = new object_property($this->table, $this->id, 'customer_id', 'int', true); + $this->cashier_id = new object_property($this->table, $this->id, 'cashier_id', 'int', true); + $this->reference = new object_property($this->table, $this->id, 'reference', 'string', true); + $this->notes = new object_property($this->table, $this->id, 'notes', 'string', false); + $this->department_id = new object_property($this->table, $this->id, 'department_id', 'int', true); + $this->reg_1 = new object_property($this->table, $this->id, 'reg_1', 'string', false); + $this->reg_2 = new object_property($this->table, $this->id, 'reg_2', 'string', false); + $this->reg_3 = new object_property($this->table, $this->id, 'reg_3', 'string', false); + $this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false); + $this->economic_module_orders = (new economic_module_orders())->getByOrderId($this->id); + $this->stripe_module_orders = (new stripe_module_orders_o())->select($this->id); + $this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false); + } + public function includeIncludes(): orders_o { global /** @var response $response */ @@ -117,6 +89,12 @@ class orders_o extends db if ($response->getRequestParameter('includeEconomicModuleOrders') || $includeEverything) { $response->add_include('economicModuleOrders', $this->economic_module_orders->getByOrderId($this->id)->asArray()); } + /** + * stripeModuleOrders + */ + if ($response->getRequestParameter('includeStripeModuleOrders') || $includeEverything) { + $response->add_include('stripeModuleOrders', $this->stripe_module_orders->exists() ? $this->stripe_module_orders->asArray() : []); + } return $this; } @@ -172,6 +150,16 @@ class orders_o extends db ]; } + public function exists(): bool + { + // Check if the id is greater than 0, and that the deleted_at property is null + if ($this->id > 0) { + $this->getObjectProperties(); + return $this->deleted_at->value() === null; + } + return false; + } + public function getCustomerByOrderId(?string $order_id): users_o { global $db; @@ -285,16 +273,6 @@ class orders_o extends db $this->{$data['field']}->set($data['value']); } - public function exists(): bool - { - // Check if the id is greater than 0, and that the deleted_at property is null - if ($this->id > 0) { - $this->getObjectProperties(); - return $this->deleted_at->value() === null; - } - return false; - } - /** * Get the order history for a vehicle plate * @param string $plate The vehicle plate @@ -320,5 +298,46 @@ class orders_o extends db throw new \Exception('Order not found'); } + /** + * Set the stripe invoicing for an order + * @throws \Exception + */ + public function setStripeInvoicing(string $payment_link_id, string $email, string $url): void + { + self::requireSelected(); + $this->stripe_module_orders->add($this->id, $email, $payment_link_id, $url); + self::objectChanged(); + } + + public function add(int $customer_id, int $cashier_id, string $reference, string $notes, int $department_id, string $reg_1 = '', string $reg_2 = '', string $reg_3 = ''): orders_o + { + global $db, $response; + try { + // Avoid SQL injection + $reference = $db->escape_string($reference); + $notes = $db->escape_string($notes); + $reg_1 = $db->escape_string($reg_1); + $reg_2 = $db->escape_string($reg_2); + $reg_3 = $db->escape_string($reg_3); + // Create a new record in the database + $sql = "INSERT INTO $this->table (customer_id, cashier_id, reference, notes, department_id, reg_1, reg_2, reg_3) VALUES ($customer_id, $cashier_id, '$reference', '$notes', $department_id, '$reg_1', '$reg_2', '$reg_3')"; + $db->query($sql); + + // Get the id of the new record + $this->id = $db->insert_id(); + + // Set the values of the object properties + $this->getObjectProperties(); + return $this; + } catch (\Exception $e) { + $response->error($e->getMessage()); + } + } + + public function objectChanged(): void + { + // Since the orders object is not cached, there is no need to invalidate the cache + } + } \ No newline at end of file diff --git a/services/nginx/app/objects/stripe_module_orders_o.php b/services/nginx/app/objects/stripe_module_orders_o.php new file mode 100644 index 00000000..85c1066a --- /dev/null +++ b/services/nginx/app/objects/stripe_module_orders_o.php @@ -0,0 +1,93 @@ +setTable('stripe_module_orders'); + } + + /** + * Add a payment link to the database + * @param int $order_id + * @param string $email + * @param string $payment_link_id + * @param string $url The URL of the payment link + * @return void + * @throws Exception If the object was not created successfully + */ + public function add(int $order_id, string $email, string $payment_link_id, string $url): void + { + $tmp_id = self::add_object([ + 'id' => $order_id, + 'email' => $email, + 'payment_link_id' => $payment_link_id, + 'url' => $url, + ]); + $this->id = $tmp_id; + self::getObjectProperties(); + self::objectChanged(); + } + + public function getObjectProperties(): void + { + $this->payment_link_id = new object_property($this->table, $this->id, 'payment_link_id', 'string', false); + $this->email = new object_property($this->table, $this->id, 'email', 'string', false); + $this->email_sent = new object_property($this->table, $this->id, 'email_sent', 'timestamp', false); + $this->url = new object_property($this->table, $this->id, 'url', 'string', false); + $this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false); + } + + public function objectChanged(): void + { + //TODO: Add cache invalidation + } + + /** + * @throws ApiErrorException + */ + public function asArray(): array + { + return [ + 'id' => (int)$this->id, + 'payment_link_id' => (string)$this->payment_link_id->value(), + 'email' => (string)$this->email->value(), + 'email_sent' => $this->email_sent->value() ? (string)$this->email_sent->value() : null, + 'url' => (string)$this->url->value(), + 'created_at' => (string)$this->created_at->value(), + 'object' => self::retrievePaymentLink() + ]; + } + + /** + * @throws ApiErrorException + * @throws Exception + */ + public function retrievePaymentLink(): object + { + // Validate the object + self::requireSelected(); + // Return the payment link + return (new stripe())->payment_link->retrieve($this->payment_link_id->value()); + } + +} \ No newline at end of file diff --git a/services/nginx/app/routes/moduleConfigRoute.php b/services/nginx/app/routes/moduleConfigRoute.php index 512a48a6..a0106210 100644 --- a/services/nginx/app/routes/moduleConfigRoute.php +++ b/services/nginx/app/routes/moduleConfigRoute.php @@ -10,6 +10,7 @@ use classes\motorapi; use classes\recaptcha; use classes\response; use classes\router; +use classes\stripe; use objects\logs_o; use traits\route_t; @@ -208,5 +209,37 @@ class moduleConfigRoute $response->error('Invalid session', 400); } }); + + /** Stripe config > GET */ + $this->get('/stripe/config', function () { + global $response; + $this->requirePermission('stripe_config'); + $user = (new authentication())->get_user(); + if ($user) { + (new logs_o())->add('stripe_config', 'global', 1, $user->id, 'STRIPE_CONFIG', 'Successfully fetched stripe config'); + $response->success( + (new stripe())->config->getConfigRequest() + ); + } else { + (new logs_o())->add('stripe_config', 'global', 1, 0, 'STRIPE_CONFIG', 'No user found, or invalid session'); + $response->error('Invalid session', 400); + } + }); + + /** Stripe config > POST */ + $this->post('/stripe/config', function () { + global $response; + $this->requirePermission('stripe_config'); + $user = (new authentication())->get_user(); + if ($user) { + (new logs_o())->add('stripe_config', 'global', 1, $user->id, 'STRIPE_CONFIG', 'Successfully updated stripe config'); + $response->success( + (new stripe())->config->postConfigRequest() + ); + } else { + (new logs_o())->add('stripe_config', 'global', 1, 0, 'STRIPE_CONFIG', 'No user found, or invalid session'); + $response->error('Invalid session', 400); + } + }); } } \ No newline at end of file diff --git a/services/nginx/app/routes/moduleStripeRoute.php b/services/nginx/app/routes/moduleStripeRoute.php new file mode 100644 index 00000000..0aca95f0 --- /dev/null +++ b/services/nginx/app/routes/moduleStripeRoute.php @@ -0,0 +1,105 @@ + Stripe > Customers > List */ + $this->get('/modules/stripe/customers', function () { + global $response; + self::requirePermission('modules_stripe_customers_list'); + $user = (new authentication())->get_user(); + if ($user) { + (new logs_o())->add('modules_stripe', 'global', 1, 0, 'MODULES_STRIPE', 'User accessed the customers list'); + $result = (new stripe())->customers->list(); + $response->success((object)$result); + } else { + (new logs_o())->add('modules_stripe', 'global', 0, 0, 'MODULES_STRIPE', 'User tried to access the customers list without a valid session'); + $response->error('Invalid session', 400); + } + }); + + /** Modules > Stripe > Products > List */ + $this->get('/modules/stripe/products', function () { + global $response; + self::requirePermission('modules_stripe_products_list'); + $user = (new authentication())->get_user(); + if ($user) { + (new logs_o())->add('modules_stripe', 'global', 1, 0, 'MODULES_STRIPE', 'User accessed the products list'); + $result = (new stripe())->product->list(); + $response->success((object)$result); + } else { + (new logs_o())->add('modules_stripe', 'global', 0, 0, 'MODULES_STRIPE', 'User tried to access the products list without a valid session'); + $response->error('Invalid session', 400); + } + }); + + /** Modules > Stripe > Prices > List */ + $this->get('/modules/stripe/prices', function () { + global $response; + self::requirePermission('modules_stripe_prices_list'); + $user = (new authentication())->get_user(); + if ($user) { + (new logs_o())->add('modules_stripe', 'global', 1, 0, 'MODULES_STRIPE', 'User accessed the prices list'); + $result = (new stripe())->prices->list(); + $response->success((object)$result); + } else { + (new logs_o())->add('modules_stripe', 'global', 0, 0, 'MODULES_STRIPE', 'User tried to access the prices list without a valid session'); + $response->error('Invalid session', 400); + } + }); + + /** Modules > Stripe > Send Invoice */ + $this->post('/modules/stripe/invoice', function () { + global $response; + self::requirePermission('modules_stripe_invoice_send'); + $user = (new authentication())->get_user(); + if ($user) { + self::requireParameters(['email', 'order_id']); + self::requireType(self::fromRequest('email'), 'string'); + self::requireType((int)self::fromRequest('order_id'), self::TYPE_INT()); + self::requireMinLength('email', 4); + self::requireMaxLength('email', 255); + self::requireMinLength('order_id', 1); + self::requireMaxLength('order_id', 255); + // Check if the email is valid + if (!filter_var(self::fromRequest('email'), FILTER_VALIDATE_EMAIL)) { + $response->error('Invalid email', 400); + } + // Check if the order exists + $order = (new orders_o())->select((int)self::fromRequest('order_id')); + $order->requireSelected(); + // Log the action + (new logs_o())->add('modules_stripe', 'global', 1, $user->id, 'MODULES_STRIPE', 'User sent an invoice'); + $result = (new stripe())->payment_link->generate( + (int)self::fromRequest('order_id'), + (string)self::fromRequest('email') + ); + // Set the order stripe invoice details + $order->setStripeInvoicing($result->id, (string)self::fromRequest('email'), $result->url); + // Return the result + $response->success((object)$result); + } else { + (new logs_o())->add('modules_stripe', 'global', 0, 0, 'MODULES_STRIPE', 'User tried to send an invoice without a valid session'); + $response->error('Invalid session', 400); + } + }); + } +} \ No newline at end of file diff --git a/services/nginx/app/traits/stripe_endpoint_t.php b/services/nginx/app/traits/stripe_endpoint_t.php new file mode 100644 index 00000000..cf49c3bc --- /dev/null +++ b/services/nginx/app/traits/stripe_endpoint_t.php @@ -0,0 +1,38 @@ +Stripe()->getClient(); + } + + /** + * Get the stripe class + * @return stripe + */ + public function Stripe(): stripe + { + if (!isset($this->stripe)) { + $this->stripe = new stripe(); + } + return $this->stripe; + } +} \ No newline at end of file