diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b68a78 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +ps_root_dir/ +vendor/ + +composer.lock +.php-cs-fixer.php +.php-cs-fixer.cache \ No newline at end of file diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..819ca8c --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,25 @@ +in([ + __DIR__, + ]) + ->exclude([ + 'vendor', + 'ps_root_dir', + ]); + +$config = new PhpCsFixer\Config(); + +return $config + ->setRules([ + '@PER-CS2.0' => true, + 'declare_strict_types' => true, + 'strict_param' => true, + 'concat_space' => ['spacing' => 'one'], + 'protected_to_private' => true, + 'nullable_type_declaration_for_default_null_value' => true, + 'final_class' => true, + ]) + ->setRiskyAllowed(true) + ->setFinder($finder); \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f6f9be4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 SimPay.pl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..eeed923 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +fixer: + vendor/bin/php-cs-fixer fix + +phpstan: + vendor/bin/phpstan analyse + +sa: fixer phpstan \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7d1e8b0 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Simpay Prestashop diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..cabe8a7 --- /dev/null +++ b/composer.json @@ -0,0 +1,35 @@ +{ + "license": "MIT", + "name": "simpaypl/prestashop", + "type": "prestashop-module", + "description": "Module for integration with SimPay payment gateway", + "keywords": [ + "simpay", + "prestashop", + "payment", + "gateway" + ], + "authors": [ + { + "name": "SimPay Core Team" + } + ], + "autoload": { + "psr-4": { + "SimPaypl\\PrestaShop\\": "src/" + } + }, + "require": { + "php": "^8.1", + "simpaypl/simpay": "^3.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.10", + "prestashop/php-dev-tools": "^4.3" + }, + "config": { + "preferred-install": "dist", + "prepend-autoloader": false, + "sort-packages": true + } +} diff --git a/config.xml b/config.xml new file mode 100644 index 0000000..a1f1c7d --- /dev/null +++ b/config.xml @@ -0,0 +1,12 @@ + + + simpay + + + + + + + 1 + 1 + \ No newline at end of file diff --git a/config/admin/index.php b/config/admin/index.php new file mode 100644 index 0000000..232bfba --- /dev/null +++ b/config/admin/index.php @@ -0,0 +1,11 @@ +setTemplate('module:simpay/views/templates/front/failed.tpl'); + } +} diff --git a/controllers/front/index.php b/controllers/front/index.php new file mode 100644 index 0000000..232bfba --- /dev/null +++ b/controllers/front/index.php @@ -0,0 +1,11 @@ + 'error', 'message' => 'Invalid payload, expected JSON'])); + } + + /** @var array{ + * id: string, + * service_id: string, + * status: string, + * amount: array{ + * value: float, + * currency: string, + * commission: float, + * }, + * control: string, + * channel: string, + * environment: string, + * signature: string + * }|bool|null $payload + */ + $payload = json_decode($jsonPayload, true); + + if (!is_array($payload)) { + http_response_code(400); + header('Content-Type: application/json'); + die(json_encode(['status' => 'error', 'message' => 'Invalid payload, expected JSON'])); + } + + $signatureValues = []; + array_walk_recursive($payload, function (mixed $item, string $key) use (&$signatureValues) { + if ($key === 'signature') { + return; + } + + $signatureValues[] = (string) $item; + }); + + $signatureValues[] = Configuration::get('SIMPAY_SERVICE_IPN_SIGNATURE_KEY'); + $signatureValues = implode('|', $signatureValues); + $signatureHash = hash('sha256', $signatureValues); + + if ($payload['signature'] !== $signatureHash) { + http_response_code(400); + header('Content-Type: application/json'); + die(json_encode(['status' => 'error', 'message' => 'Invalid signature'])); + } + + $order = Order::getByCartId((int) $payload['control']); + + if (null === $order) { + http_response_code(400); + header('Content-Type: application/json'); + die(json_encode(['status' => 'error', 'message' => 'Order not found'])); + } + + if ((int) Configuration::get(Simpay::CONFIG_OS_AWAITING) === $order->getCurrentState()) { + + $orderStatusId = (int) match($payload['status']) { + 'transaction_paid' => Configuration::get('PS_OS_PAYMENT'), + default => Configuration::get('PS_OS_ERROR'), + }; + + $orderHistory = new OrderHistory(); + $orderHistory->id_order = (int) $order->id; + $orderHistory->changeIdOrderState($orderStatusId, (int) $order->id, true); + $orderHistory->save(); + } + + + http_response_code(200); + header('Content-Type: application/json'); + die(json_encode(['status' => 'ok'])); + } +} diff --git a/controllers/front/validate.php b/controllers/front/validate.php new file mode 100644 index 0000000..d776e3d --- /dev/null +++ b/controllers/front/validate.php @@ -0,0 +1,175 @@ +assertModuleIsActive(); + + if (!$this->checkIfContextIsValid()) { + $this->redirectToOrder(); + + return; + } + + if (!$this->checkIfPaymentOptionIsAvailable()) { + $this->redirectToOrder(); + + return; + } + + /** @var Cart $cart */ + $cart = $this->context->cart; + /** @var Currency $currency */ + $currency = $this->context->currency; + + $customer = new Customer($cart->id_customer); + if (false === Validate::isLoadedObject($customer)) { + $this->redirectToOrder(); + + return; + } + + /** @var PaymentInterface $paymentClient */ + $paymentClient = $this->get('prestashop.module.simpay.front.payment_client'); + + /** @var string $serviceIdString */ + $serviceIdString = Configuration::get(SimpayDataConfiguration::SERVICE_ID); + $response = $paymentClient->paymentTransactionCreate( + new ServiceId($serviceIdString), + $this->createPaymentRequest($cart, $customer->secure_key), + ); + + $this->module->validateOrder( + (int) $cart->id, + (int) Configuration::get(Simpay::CONFIG_OS_AWAITING), + $cart->getOrderTotal(), + $this->trans('SimPay', [], 'Modules.Simpay.Shop'), + null, + [ + 'transaction_id' => $response->transactionId, + ], + $currency->id, + false, + $customer->secure_key, + ); + + $this->setTemplate('module:simpay/views/templates/front/validate.tpl'); + $this->context->smarty?->assign([ + 'action' => $response->redirectUrl, + ]); + + } + private function assertModuleIsActive(): void + { + if (!Module::isEnabled($this->module->name)) { + die($this->trans('This payment method is not available.', [], 'Modules.Simpay.Shop')); + } + + if (!$this->module->active) { + die($this->trans('SimPay module module isn\'t active.', [], 'Modules.Simpay.Shop')); + } + } + + private function checkIfContextIsValid(): bool + { + if (null === $this->context->cart) { + return false; + } + + if (null === $this->context->currency) { + return false; + } + + return Validate::isLoadedObject($this->context->cart) + && Validate::isUnsignedInt($this->context->cart->id_customer) + && Validate::isUnsignedInt($this->context->cart->id_address_delivery) + && Validate::isUnsignedInt($this->context->cart->id_address_invoice); + } + + private function checkIfPaymentOptionIsAvailable(): bool + { + $modules = Module::getPaymentModules(); + + if (empty($modules)) { + return false; + } + + foreach ($modules as $module) { + if (isset($module['name']) && $this->module->name === $module['name']) { + return true; + } + } + + return false; + } + + private function redirectToOrder(): void + { + /** @var Link $link */ + $link = $this->context->link; + + Tools::redirect($link->getPageLink( + 'order', + true, + (int) $this->context->language?->id, + [ + 'step' => 1, + ] + )); + } + + private function createPaymentRequest(Cart $cart, string $customerSecureKey): CreatePayment + { + $amount = (float) $cart->getOrderTotal(); + + /** @var Link $link */ + $link = $this->context->link; + + $successReturnUrl = $link->getPageLink( + 'order-confirmation', + true, + $this->context->language?->id, + [ + 'id_cart' => (int) $cart->id, + 'id_module' => (int) $this->module->id, + 'id_order' => $this->module->currentOrder, + 'key' => $customerSecureKey + ] + ); + + $failureReturnUrl = $link->getModuleLink( + 'simpay', + 'failed', + [], + true, + $this->context->language?->id, + ); + + return new CreatePayment( + new Amount($amount), + [], + null, + new SimpayCurrency('PLN'), + null, + new Control((string) $cart->id), + null, + null, + null, + new CallbackReturnUrl($successReturnUrl, $failureReturnUrl), + ); + } +} diff --git a/controllers/index.php b/controllers/index.php new file mode 100644 index 0000000..232bfba --- /dev/null +++ b/controllers/index.php @@ -0,0 +1,11 @@ + + + + {payment} + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+ + + + +
+ + +
+ +
+ + +
+ + +
+ + +
+
+
+ +
+
+ + + + + +
+ + +
+ +
+ + +
+ + + + + + + + +
+
+ Hi {firstname} {lastname}, +
+
+
+ Thank you for shopping with {shop_name}! +
+
+
+
+ +
+
+ + + +
+ + +
+ +
+ + +
+

+

+ +
+
+ +
+
+ + + + +
+ + +
+ +
+ + +
+ + +
+
+ Order ID {order_name} - Pending payment +
+
+
+
+ +
+
+ + + + +
+ + +
+ +
+ + +
+ + +
+
+ Your order with the reference {order_name} has been placed successfully. You can expect delivery as soon as your payment is received. +
+
+
+
+ +
+
+ + + + +
+ + +
+ +
+ + +
+ + +
+
+ Payment method: {payment} +
+
+
+
+ +
+
+ + + + +
+ + +
+ +
+ + +
+ + + + + + + +
+
+ You have decided to pay via SimPay. +
+
+
+ Amount: + {total_paid} +
+
+
+
+ +
+
+ + + + +
+ + +
+ +
+ + +
+
+ Follow your order and download your invoice on our shop, go to the Order history and details section of your customer account. +
+
+
+ +
+
+ + + + +
+ + +
+ +
+ + +
+
+ If you have a guest account, you can follow your order via the Guest Tracking section on our shop. +
+
+
+ +
+
+ + + + + + + +
+
+ + + + +
+ + +
+ +
+ + + + + + + +
+ +
+
Powered by PrestaShop +
+
+
+ +
+
+ + + + +
+ + \ No newline at end of file diff --git a/mails/en/awaiting_simpay_payment.txt b/mails/en/awaiting_simpay_payment.txt new file mode 100644 index 0000000..aa7ab6a --- /dev/null +++ b/mails/en/awaiting_simpay_payment.txt @@ -0,0 +1,23 @@ +{shop_url} + +Hi {firstname} {lastname}, + +Thank you for shopping with {shop_name}! + +Order ID {order_name} - Pending payment + +Your order with the reference {order_name} has been placed successfully. You can expect delivery as soon as your payment is received. + +Payment method: {payment} + +You have decided to pay via SimPay. + +Amount: {total_paid} + +Follow your order and download your invoice on our shop, go to the [Order history and details]({history_url}) section of your customer account. + +If you have a guest account, you can follow your order via the [Guest Tracking]({guest_tracking_url}) section on our shop. + +[{shop_name}]({shop_url}) + +Powered by [PrestaShop](https://www.prestashop.com/?utm_source=marchandprestashop&utm_medium=e-mail=utm_campaign=footer_1-7) \ No newline at end of file diff --git a/mails/en/index.php b/mails/en/index.php new file mode 100644 index 0000000..232bfba --- /dev/null +++ b/mails/en/index.php @@ -0,0 +1,11 @@ + 'SimpayConfigurationAdminParentController', + 'name' => 'SimPay Module', + 'parent_class_name' => 'AdminParentModulesSf', + 'visible' => false, + ], + [ + 'class_name' => 'SimpayConfigurationAdminController', + 'route_name' => 'simpay_configuration', + 'name' => 'Configuration', + 'parent_class_name' => 'SimpayConfigurationAdminParentController', + 'visible' => false, + ], + ]; + + private const HOOKS = [ + 'paymentOptions', + ]; + + public function __construct() + { + $this->name = 'simpay'; + $this->tab = 'payments_gateways'; + $this->version = '0.1.0'; + $this->author = 'Payments Solution Sp. z o.o.'; + $this->ps_versions_compliancy = [ + 'min' => '8.0.0', + 'max' => '8.99.99', + ]; + $this->controllers = ['failed', 'notify', 'validate']; + + $this->bootstrap = true; + parent::__construct(); + + $this->displayName = $this->trans('SimPay', [], 'Modules.Simpay.Admin'); + $this->description = $this->trans('Connect your shop directly with SimPay gateway', [], 'Modules.Simpay.Admin'); + $this->confirmUninstall = $this->trans('Are you sure you want to uninstall?', [], 'Modules.Simpay.Admin'); + } + + public function install(): bool + { + if (!parent::install()) { + return false; + } + + if (!$this->registerHook(self::HOOKS)) { + return false; + } + + if (!$this->createOrderState( + self::CONFIG_OS_AWAITING, + [ + 'en' => 'Awaiting SimPay payment', + ], + '#34209e', + true, + false, + false, + false, + false, + false, + false, + false, + 'awaiting_simpay_payment' + )) { + return false; + } + + if (!$this->installTabs()) { + return false; + } + + return true; + } + + public function uninstall(): bool + { + if (!parent::uninstall()) { + return false; + } + + if (!$this->deleteOrderState()) { + return false; + } + + if (!$this->uninstallTabs()) { + return false; + } + + return true; + } + + /** + * @param array{cart: Cart} $params + * @return array + */ + public function hookPaymentOptions(array $params): array + { + $cart = $params['cart']; + + if (false === Validate::isLoadedObject($cart)) { + return []; + } + + if (false === $this->checkCurrency($cart)) { + return []; + } + + if ($cart->isVirtualCart()) { + return []; + } + + if (!isset($this->context->link)) { + return []; + } + + $logoPath = Media::getMediaPath(_PS_MODULE_DIR_ . $this->name . '/views/img/option/simpay.png'); + + $simpayPaymentOption = (new PaymentOption()) + ->setModuleName((string) $this->name) + ->setCallToActionText('Pay with Simpay') + ->setAction($this->context->link->getModuleLink((string) $this->name, 'validate', [], true)) + ->setInputs([ + 'token' => [ + 'name' => 'token', + 'type' => 'hidden', + 'value' => '[5cbfniD+(gEV<59lYbG/,3VmHiEsetLogo($logoPath); + } + + return [$simpayPaymentOption]; + } + + public function getContent(): void + { + /** @var Router $router */ + $router = $this->get('router'); + Tools::redirectAdmin($router->generate('simpay_configuration')); + } + + private function installTabs(): bool + { + foreach (self::MODULE_ADMIN_CONTROLLERS as $controller) { + if (Tab::getIdFromClassName($controller['class_name'])) { + continue; + } + + $tab = new Tab(); + $tab->class_name = $controller['class_name']; + $tab->active = $controller['visible']; + + /** @var array, + * }> $languages + */ + $languages = Language::getLanguages(false); + foreach ($languages as $lang) { + $tab->name[$lang['id_lang']] = $this->trans($controller['name'], [], 'Modules.Simpay.Admin', $lang['locale']); + } + $tab->id_parent = Tab::getIdFromClassName($controller['parent_class_name']); + $tab->module = 'simpay'; + if (!$tab->add()) { + return false; + } + } + + return true; + } + + private function uninstallTabs(): bool + { + foreach (self::MODULE_ADMIN_CONTROLLERS as $controller) { + $id_tab = (int) Tab::getIdFromClassName($controller['class_name']); + $tab = new Tab($id_tab); + if (Validate::isLoadedObject($tab)) { + if (!$tab->delete()) { + return false; + } + } + } + + return true; + } + + /** @param array $nameByLangIsoCode */ + private function createOrderState( + string $configurationKey, + array $nameByLangIsoCode, + string $color, + bool $isLogable = false, + bool $isPaid = false, + bool $isInvoice = false, + bool $isShipped = false, + bool $isDelivery = false, + bool $isPdfDelivery = false, + bool $isPdfInvoice = false, + bool $isSendEmail = false, + string $template = '', + bool $isHidden = false, + bool $isUnremovable = true, + bool $isDeleted = false, + ): bool { + $tabNameByLangId = []; + + foreach ($nameByLangIsoCode as $langIsoCode => $name) { + /** @var array> $languages */ + $languages = Language::getLanguages(false); + foreach ($languages as $language) { + if (Tools::strtolower($language['iso_code']) === $langIsoCode) { + $tabNameByLangId[(int) $language['id_lang']] = $name; + } elseif (isset($nameByLangIsoCode['en'])) { + $tabNameByLangId[(int) $language['id_lang']] = $nameByLangIsoCode['en']; + } + } + } + + $orderState = new OrderState(); + $orderState->module_name = $this->name; + $orderState->name = $tabNameByLangId; + $orderState->color = $color; + $orderState->logable = $isLogable; + $orderState->paid = $isPaid; + $orderState->invoice = $isInvoice; + $orderState->shipped = $isShipped; + $orderState->delivery = $isDelivery; + $orderState->pdf_delivery = $isPdfDelivery; + $orderState->pdf_invoice = $isPdfInvoice; + $orderState->send_email = $isSendEmail; + $orderState->hidden = $isHidden; + $orderState->unremovable = $isUnremovable; + $orderState->template = $template; + $orderState->deleted = $isDeleted; + + if (false === $orderState->add()) { + $this->_errors[] = sprintf( + 'Failed to create OrderState %s', + $configurationKey + ); + + return false; + } + + if (false === Configuration::updateGlobalValue($configurationKey, (int) $orderState->id)) { + $this->_errors[] = sprintf( + 'Failed to save OrderState %s to Configuration', + $configurationKey + ); + + return false; + } + + $orderStateImgPath = $this->getLocalPath() . 'views/img/orderstate/' . $configurationKey . '.png'; + if (false === Tools::file_exists_cache($orderStateImgPath)) { + $this->_errors[] = sprintf( + 'Failed to find icon file of OrderState %s', + $configurationKey + ); + + return false; + } + + if (false === Tools::copy($orderStateImgPath, _PS_ORDER_STATE_IMG_DIR_ . $orderState->id . '.gif')) { + $this->_errors[] = sprintf( + 'Failed to copy icon of OrderState %s', + $configurationKey + ); + + return false; + } + + return true; + } + + private function deleteOrderState(): bool + { + $result = true; + + $orderStateCollection = new PrestaShopCollection('OrderState'); + $orderStateCollection->where('module_name', '=', $this->name); + /** @var OrderState[] $orderStates */ + $orderStates = $orderStateCollection->getAll(); + + foreach ($orderStates as $orderState) { + $orderState->deleted = true; + if (!$orderState->save()) { + $result = false; + } + } + + return $result; + } + + private function checkCurrency(Cart $cart): bool + { + $currencyOrder = new Currency($cart->id_currency); + + return 'PLN' === $currencyOrder->iso_code; + } +} diff --git a/src/Controller/SimpayConfigurationAdminController.php b/src/Controller/SimpayConfigurationAdminController.php new file mode 100644 index 0000000..ddaa42d --- /dev/null +++ b/src/Controller/SimpayConfigurationAdminController.php @@ -0,0 +1,42 @@ +simpayFormDataHandler = $simpayFormDataHandler; + } + public function configureAction(Request $request): Response + { + $configurationForm = $this->simpayFormDataHandler->getForm(); + $configurationForm->handleRequest($request); + + if ($configurationForm->isSubmitted() && $configurationForm->isValid()) { + /** @var array $data */ + $data = $configurationForm->getData(); + $errors = $this->simpayFormDataHandler->save($data); + + if (empty($errors)) { + $this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success')); + + return $this->redirectToRoute('simpay_configuration'); + } + + $this->flashErrors($errors); + } + + return $this->render('@Modules/simpay/views/templates/admin/configuration.html.twig', [ + 'configurationForm' => $configurationForm->createView(), + ]); + } +} diff --git a/src/Controller/index.php b/src/Controller/index.php new file mode 100644 index 0000000..232bfba --- /dev/null +++ b/src/Controller/index.php @@ -0,0 +1,11 @@ +configuration = $configuration; + } + + /** @return array{api_key: string, api_password: string, service_id: string, service_ipn_signature_key: string} */ + public function getConfiguration(): array + { + return [ + 'api_key' => (string) $this->configuration->get(self::API_KEY), + 'api_password' => (string) $this->configuration->get(self::API_PASSWORD), + 'service_id' => (string) $this->configuration->get(self::SERVICE_ID), + 'service_ipn_signature_key' => (string) $this->configuration->get(self::SERVICE_IPN_SIGNATURE_KEY), + ]; + } + + /** + * @param array{api_key: string, api_password: string, service_id: string, service_ipn_signature_key: string} $configuration + * @return array + */ + public function updateConfiguration(array $configuration) + { + if (!$this->validateConfiguration($configuration)) { + return ['Invalid configuration']; + } + + $this->configuration->set(self::API_KEY, $configuration['api_key']); + $this->configuration->set(self::API_PASSWORD, $configuration['api_password']); + $this->configuration->set(self::SERVICE_ID, $configuration['service_id']); + $this->configuration->set(self::SERVICE_IPN_SIGNATURE_KEY, $configuration['service_ipn_signature_key']); + + + + return []; + } + + /** + * @param array $configuration + */ + public function validateConfiguration(array $configuration): bool + { + return isset($configuration['api_key']) + && isset($configuration['api_password']) + && isset($configuration['service_id']) + && isset($configuration['service_ipn_signature_key']); + } +} diff --git a/src/Form/SimpayFormDataProvider.php b/src/Form/SimpayFormDataProvider.php new file mode 100644 index 0000000..19795a4 --- /dev/null +++ b/src/Form/SimpayFormDataProvider.php @@ -0,0 +1,33 @@ +simpayDataConfiguration = $simpayDataConfiguration; + } + + /** @return array{api_key: string, api_password: string, service_id: string, service_ipn_signature_key: string} */ + public function getData(): array + { + return $this->simpayDataConfiguration->getConfiguration(); + + } + + /** + * @param array{api_key: string, api_password: string, service_id: string, service_ipn_signature_key: string} $data + * @return array + */ + public function setData(array $data): array + { + return $this->simpayDataConfiguration->updateConfiguration($data); + } +} diff --git a/src/Form/SimpayFormType.php b/src/Form/SimpayFormType.php new file mode 100644 index 0000000..86f809f --- /dev/null +++ b/src/Form/SimpayFormType.php @@ -0,0 +1,63 @@ +add('api_key', TextType::class, [ + 'label' => $this->trans('API Key', 'Modules.Simpay.Admin'), + 'help' => $this->trans('Konto Klienta -> API -> Szczegoly -> Klucz', 'Modules.Simpay.Admin'), + 'constraints' => [ + new NotBlank(), + ], + ]) + + ->add('api_password', TextType::class, [ + 'label' => $this->trans('API Password', 'Modules.Simpay.Admin'), + 'help' => $this->trans('Konto Klienta -> API -> Szczegoly -> Hasło / Bearer Token ', 'Modules.Simpay.Admin'), + 'constraints' => [ + new NotBlank(), + ], + ]) + + ->add('service_id', TextType::class, [ + 'label' => $this->trans('Service ID', 'Modules.Simpay.Admin'), + 'help' => $this->trans('Platnosci online -> Uslugi -> Szczegoly -> ID', 'Modules.Simpay.Admin'), + 'constraints' => [ + new NotBlank(), + ], + ]) + + ->add('service_ipn_signature_key', TextType::class, [ + 'label' => $this->trans('Service IPN Signature Key', 'Modules.Simpay.Admin'), + 'help' => $this->trans('Platnosci online -> Uslugi -> Szczegoly -> Ustawienia -> Klucz do sygnatury IPN', 'Modules.Simpay.Admin'), + 'constraints' => [ + new NotBlank(), + ], + ]) + + ->add('service_ipn_notify_url', UrlType::class, [ + 'label' => $this->trans('Service IPN Notify URL', 'Modules.Simpay.Admin'), + 'help' => $this->trans('Platnosci online -> Uslugi -> Szczegoly -> Ustawienia -> Adres url do powiadomień IPN', 'Modules.Simpay.Admin'), + 'required' => false, + 'mapped' => false, + 'disabled' => true, + 'data' => (new Link())->getModuleLink('simpay', 'notify', [], true), + ]) + ; + } + +} diff --git a/src/Form/index.php b/src/Form/index.php new file mode 100644 index 0000000..232bfba --- /dev/null +++ b/src/Form/index.php @@ -0,0 +1,11 @@ +configuration = $configuration; + } + public function __invoke(): PaymentInterface + { + return new PaymentApi( + new HttpClientFactory( + new SimpayConfiguration( + $this->configuration->get('SIMPAY_API_KEY'), + $this->configuration->get('SIMPAY_API_PASSWORD'), + 'en', + ) + ) + ); + } +} diff --git a/src/index.php b/src/index.php new file mode 100644 index 0000000..232bfba --- /dev/null +++ b/src/index.php @@ -0,0 +1,11 @@ + +
+
+

+ settings {{ 'Settings'|trans({}, 'Modules.Simpay.Admin') }} +

+ +
+
+ {{ form_widget(configurationForm) }} +
+
+ + +
+
+ + {{ form_end(configurationForm) }} +{% endblock %} \ No newline at end of file diff --git a/views/templates/admin/index.php b/views/templates/admin/index.php new file mode 100644 index 0000000..232bfba --- /dev/null +++ b/views/templates/admin/index.php @@ -0,0 +1,11 @@ + + +
+

There was an error during the payment process

+
+ +{/block} + +{block name="link_rewrite"} + simpay-payment-error +{/block} \ No newline at end of file diff --git a/views/templates/front/index.php b/views/templates/front/index.php new file mode 100644 index 0000000..232bfba --- /dev/null +++ b/views/templates/front/index.php @@ -0,0 +1,11 @@ + + {l s='You will be redirected to SimPay payment gateway. Please wait...' mod='simpay'} +

{l s='If you are not redirected automatically' mod='simpay'}

+
+ +
+ +{/block} + +{*{block name='javascript_bottom'}*} +{* {include file="_partials/javascript.tpl" javascript=$javascript.bottom}*} +{* *} +{*{/block}*} \ No newline at end of file