From d496bca60f1d974a5b47ba0f3d73ccd24315e6ae Mon Sep 17 00:00:00 2001 From: Bastien Tafforeau Date: Wed, 28 Jun 2023 17:09:04 +0200 Subject: [PATCH 01/31] Upgrade script for 6.3.4.0 --- upgrade/upgrade-6.3.4.0.php | 94 +++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 upgrade/upgrade-6.3.4.0.php diff --git a/upgrade/upgrade-6.3.4.0.php b/upgrade/upgrade-6.3.4.0.php new file mode 100644 index 000000000..8caf24f3f --- /dev/null +++ b/upgrade/upgrade-6.3.4.0.php @@ -0,0 +1,94 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 + */ +if (!defined('_PS_VERSION_')) { + exit; +} + +/** + * Update main function for module version 6.3.4.0 + * + * @param Ps_checkout $module + * + * @return bool + */ +function upgrade_module_6_3_4_0($module) +{ + $orderStateCollection = new PrestaShopCollection(OrderState::class); + $orderStateCollection->where('module_name', '=', $module->name); + $orderStateCollection->where('deleted', '=', '0'); + + /** @var OrderState[] $orderStates */ + $orderStates = $orderStateCollection->getResults(); + + if (!empty($orderStates)) { + foreach ($orderStates as $orderState) { + if (in_array($orderState->id, [Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT'), Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT'), Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT')])) { + $orderState->deleted = true; + $orderState->save(); + } + } + } + + ps_checkout_create_order_state_6_3_4_0('PS_CHECKOUT_STATE_WAITING_PAYMENT', '#34209E', [ + 'en' => 'Waiting for payment', + 'fr' => 'En attente de paiement', + 'es' => 'Esperando el pago', + 'it' => 'In attesa di pagamento', + 'nl' => 'Wachten op betaling', + 'de' => 'Warten auf Zahlung', + 'pl' => 'Oczekiwanie na płatność', + 'pt' => 'Aguardando pagamento pelo', + ]); + + return true; +} + +function ps_checkout_create_order_state_6_3_4_0($configuration_key, $color, $nameByLangIsoCode) +{ + $orderStateNameByLangId = []; + foreach ($nameByLangIsoCode as $langIsoCode => $name) { + foreach (Language::getLanguages(false) as $language) { + if (Tools::strtolower($language['iso_code']) === $langIsoCode) { + $orderStateNameByLangId[(int) $language['id_lang']] = $name; + } elseif (isset($nameByLangIsoCode['en'])) { + $orderStateNameByLangId[(int) $language['id_lang']] = $nameByLangIsoCode['en']; + } + } + } + + $orderState = new OrderState(); + $orderState->name = $orderStateNameByLangId; + $orderState->module_name = 'ps_checkout'; + $orderState->unremovable = true; + $orderState->color = $color; + $orderState->delivery = false; + $orderState->shipped = false; + $orderState->pdf_delivery = false; + $orderState->pdf_invoice = false; + $orderState->hidden = false; + $orderState->invoice = false; + $orderState->send_email = false; + $orderState->paid = false; + $orderState->logable = false; + $orderState->deleted = false; + $orderState->template = []; + $orderState->save(); + Configuration::updateGlobalValue($configuration_key, $orderState->id); +} From eec0ab489fe820b3c4bfaa7ad033e613e10d2879 Mon Sep 17 00:00:00 2001 From: sgodard Date: Tue, 11 Jul 2023 14:59:54 +0200 Subject: [PATCH 02/31] update translation --- upgrade/upgrade-6.3.4.0.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/upgrade/upgrade-6.3.4.0.php b/upgrade/upgrade-6.3.4.0.php index 8caf24f3f..8a45a9fc3 100644 --- a/upgrade/upgrade-6.3.4.0.php +++ b/upgrade/upgrade-6.3.4.0.php @@ -54,7 +54,7 @@ function upgrade_module_6_3_4_0($module) 'nl' => 'Wachten op betaling', 'de' => 'Warten auf Zahlung', 'pl' => 'Oczekiwanie na płatność', - 'pt' => 'Aguardando pagamento pelo', + 'pt' => 'Aguardando pagamento', ]); return true; From c754b0561e40bee5ee71ce72452b0b15c4fcb64b Mon Sep 17 00:00:00 2001 From: Laurynas Date: Tue, 11 Jul 2023 15:24:17 +0300 Subject: [PATCH 03/31] Added code to remove virtual url from admin urls --- src/Adapter/LinkAdapter.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Adapter/LinkAdapter.php b/src/Adapter/LinkAdapter.php index 98e06fae8..085f2905a 100644 --- a/src/Adapter/LinkAdapter.php +++ b/src/Adapter/LinkAdapter.php @@ -58,7 +58,10 @@ public function __construct(\Link $link = null) public function getAdminLink($controller, $withToken = true, $sfRouteParams = [], $params = []) { if ((new ShopContext())->isShop17()) { - return $this->link->getAdminLink($controller, $withToken, $sfRouteParams, $params); + $shop = \Context::getContext()->shop; + $link = $this->link->getAdminLink($controller, $withToken, $sfRouteParams, $params); + + return str_replace($shop->physical_uri . $shop->virtual_uri, $shop->physical_uri, $link); } $paramsAsString = ''; From 23b962b3700265182f391c282da5ae2c3dedc533 Mon Sep 17 00:00:00 2001 From: Laurynas Date: Tue, 11 Jul 2023 15:58:21 +0300 Subject: [PATCH 04/31] Changed the code to work on all ps versions --- src/Adapter/LinkAdapter.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Adapter/LinkAdapter.php b/src/Adapter/LinkAdapter.php index 085f2905a..9a377e65e 100644 --- a/src/Adapter/LinkAdapter.php +++ b/src/Adapter/LinkAdapter.php @@ -57,11 +57,12 @@ public function __construct(\Link $link = null) */ public function getAdminLink($controller, $withToken = true, $sfRouteParams = [], $params = []) { + $shop = \Context::getContext()->shop; + if ((new ShopContext())->isShop17()) { - $shop = \Context::getContext()->shop; $link = $this->link->getAdminLink($controller, $withToken, $sfRouteParams, $params); - return str_replace($shop->physical_uri . $shop->virtual_uri, $shop->physical_uri, $link); + return $shop->virtual_uri !== '' ? str_replace($shop->physical_uri . $shop->virtual_uri, $shop->physical_uri, $link) : $link; } $paramsAsString = ''; @@ -69,6 +70,8 @@ public function getAdminLink($controller, $withToken = true, $sfRouteParams = [] $paramsAsString .= "&$key=$value"; } - return \Tools::getShopDomainSsl(true) . __PS_BASE_URI__ . basename(_PS_ADMIN_DIR_) . '/' . $this->link->getAdminLink($controller, $withToken) . $paramsAsString; + $link = \Tools::getShopDomainSsl(true) . __PS_BASE_URI__ . basename(_PS_ADMIN_DIR_) . '/' . $this->link->getAdminLink($controller, $withToken) . $paramsAsString; + + return $shop->virtual_uri !== '' ? str_replace($shop->physical_uri . $shop->virtual_uri, $shop->physical_uri, $link) : $link; } } From 88e6c739cf2ede6be67d1eb5958472cb9647e7a9 Mon Sep 17 00:00:00 2001 From: Laurynas Date: Wed, 12 Jul 2023 16:18:32 +0300 Subject: [PATCH 05/31] Added authentication route when redirecting after onboarding --- .../admin/AdminPaypalOnboardingPrestashopCheckoutController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/admin/AdminPaypalOnboardingPrestashopCheckoutController.php b/controllers/admin/AdminPaypalOnboardingPrestashopCheckoutController.php index 464791fa4..53904dff8 100755 --- a/controllers/admin/AdminPaypalOnboardingPrestashopCheckoutController.php +++ b/controllers/admin/AdminPaypalOnboardingPrestashopCheckoutController.php @@ -54,7 +54,7 @@ public function postProcess() [ 'configure' => 'ps_checkout', ] - ) + ) . '#/authentication' ); } catch (Exception $e) { $this->errors[] = $e->getMessage(); From 229d4f050d29970d8e057f82bf44b21061bf6691 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:13:54 +0200 Subject: [PATCH 06/31] Add BLIK as APM --- src/FundingSource/FundingSourceCollectionBuilder.php | 8 +++++++- views/img/blik.svg | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 views/img/blik.svg diff --git a/src/FundingSource/FundingSourceCollectionBuilder.php b/src/FundingSource/FundingSourceCollectionBuilder.php index b4ef4052c..25aba65be 100644 --- a/src/FundingSource/FundingSourceCollectionBuilder.php +++ b/src/FundingSource/FundingSourceCollectionBuilder.php @@ -107,6 +107,12 @@ public function create() $sofort->setIsEnabled($this->configuration->isEnabled('sofort')); $sofort->setCountries($this->eligibilityConstraint->getCountries('sofort')); - return [$paypal, $paylater, $card, $bancontact, $eps, $giropay, $ideal, $mybank, $p24, $sofort]; + // BLIK + $blik = new FundingSourceEntity('blik'); + $blik->setPosition($this->configuration->getPosition('blik', 11)); + $blik->setIsEnabled($this->configuration->isEnabled('blik')); + $blik->setCountries($this->eligibilityConstraint->getCountries('blik')); + + return [$paypal, $paylater, $card, $bancontact, $eps, $giropay, $ideal, $mybank, $p24, $sofort, $blik]; } } diff --git a/views/img/blik.svg b/views/img/blik.svg new file mode 100644 index 000000000..b88037d1c --- /dev/null +++ b/views/img/blik.svg @@ -0,0 +1 @@ + \ No newline at end of file From 38a1cfed2a87a4b93a062ec811222a72b0921593 Mon Sep 17 00:00:00 2001 From: sgodard Date: Thu, 29 Jun 2023 20:37:20 +0200 Subject: [PATCH 07/31] add PS_CHECKOUT_STATE_WAITING_PAYMENT --- .../State/OrderStateConfigurationKeys.php | 1 + src/OrderStates.php | 4 +- src/Translations/OrderStatesTranslations.php | 46 +++++-------------- 3 files changed, 13 insertions(+), 38 deletions(-) diff --git a/src/Order/State/OrderStateConfigurationKeys.php b/src/Order/State/OrderStateConfigurationKeys.php index 6edd8961a..acaf1cdd4 100644 --- a/src/Order/State/OrderStateConfigurationKeys.php +++ b/src/Order/State/OrderStateConfigurationKeys.php @@ -37,4 +37,5 @@ class OrderStateConfigurationKeys const WAITING_CREDIT_CARD_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT'; const WAITING_LOCAL_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT'; const WAITING_PAYPAL_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT'; + const WAITING_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_PAYMENT'; } diff --git a/src/OrderStates.php b/src/OrderStates.php index f417523f2..b617c32b8 100644 --- a/src/OrderStates.php +++ b/src/OrderStates.php @@ -35,9 +35,7 @@ class OrderStates const BLUE_HEXA_COLOR = '#3498D8'; const GREEN_HEXA_COLOR = '#01B887'; const ORDER_STATES = [ - 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT' => self::DARK_BLUE_HEXA_COLOR, - 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT' => self::DARK_BLUE_HEXA_COLOR, - 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT' => self::DARK_BLUE_HEXA_COLOR, + 'PS_CHECKOUT_STATE_WAITING_PAYMENT' => self::DARK_BLUE_HEXA_COLOR, 'PS_CHECKOUT_STATE_AUTHORIZED' => self::BLUE_HEXA_COLOR, 'PS_CHECKOUT_STATE_PARTIAL_REFUND' => self::GREEN_HEXA_COLOR, 'PS_CHECKOUT_STATE_WAITING_CAPTURE' => self::BLUE_HEXA_COLOR, diff --git a/src/Translations/OrderStatesTranslations.php b/src/Translations/OrderStatesTranslations.php index 50bcf6f0b..a60265521 100644 --- a/src/Translations/OrderStatesTranslations.php +++ b/src/Translations/OrderStatesTranslations.php @@ -23,35 +23,15 @@ class OrderStatesTranslations { const STANDARD_ISO_CODE = 'en'; - const PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT = [ - 'en' => 'Waiting for PayPal payment', - 'fr' => 'En attente de paiement par PayPal', - 'es' => 'Esperando el pago con PayPal', - 'it' => 'In attesa di pagamento con PayPal', - 'nl' => 'Wachten op PayPal-betaling', - 'de' => 'Warten auf PayPal-Zahlung', - 'pl' => 'Oczekiwanie na płatność PayPal', - 'pt' => 'Aguardando pagamento pelo PayPal', - ]; - const PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT = [ - 'en' => 'Waiting for Credit Card Payment', - 'fr' => 'En attente de paiement par Carte de Crédit', - 'es' => 'Esperando el pago con tarjeta de crédito', - 'it' => 'In attesa di pagamento con carta di credito', - 'nl' => 'Wachten op creditcard-betaling', - 'de' => 'Warten auf Kreditkartenzahlung', - 'pl' => 'Oczekiwanie na płatność kartą kredytową', - 'pt' => 'Aguardando pagamento por cartão de crédito', - ]; - const PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT = [ - 'en' => 'Waiting for Local Payment Method Payment', - 'fr' => 'En attente de paiement par moyen de paiement local', - 'es' => 'Esperando el pago con un método de pago local', - 'it' => 'In attesa di pagamento con metodo di pagamento locale', - 'nl' => 'Wachten op nlaatselijke betaling', - 'de' => 'Warten auf Zahlung per lokaler Zahlungsmethode', - 'pl' => 'Oczekiwanie na płatność lokalnym środkiem płatności', - 'pt' => 'Aguardando pagamento pelo método de pagamento local', + const PS_CHECKOUT_STATE_WAITING_PAYMENT = [ + 'en' => 'Waiting for payment', + 'fr' => 'En attente de paiement', + 'es' => 'Esperando el pago', + 'it' => 'In attesa di pagamento', + 'nl' => 'Wachten op betaling', + 'de' => 'Warten auf Zahlung', + 'pl' => 'Oczekiwanie na płatność', + 'pt' => 'Aguardando pagamento', ]; const PS_CHECKOUT_STATE_AUTHORIZED = [ 'en' => 'Authorized. To be captured by merchant', @@ -94,9 +74,7 @@ public function getTranslations($isoCode) $isoCode = $this->confirmIsoCode($isoCode); return [ - 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT' => self::PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT[$isoCode], - 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT' => self::PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT[$isoCode], - 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT' => self::PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT[$isoCode], + 'PS_CHECKOUT_STATE_WAITING_PAYMENT' => self::PS_CHECKOUT_STATE_WAITING_PAYMENT[$isoCode], 'PS_CHECKOUT_STATE_AUTHORIZED' => self::PS_CHECKOUT_STATE_AUTHORIZED[$isoCode], 'PS_CHECKOUT_STATE_PARTIAL_REFUND' => self::PS_CHECKOUT_STATE_PARTIAL_REFUND[$isoCode], 'PS_CHECKOUT_STATE_WAITING_CAPTURE' => self::PS_CHECKOUT_STATE_WAITING_CAPTURE[$isoCode], @@ -112,9 +90,7 @@ public function getTranslations($isoCode) */ private function confirmIsoCode($isoCode) { - if (!array_key_exists($isoCode, self::PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT) || - !array_key_exists($isoCode, self::PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT) || - !array_key_exists($isoCode, self::PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT) || + if (!array_key_exists($isoCode, self::PS_CHECKOUT_STATE_WAITING_PAYMENT) || !array_key_exists($isoCode, self::PS_CHECKOUT_STATE_AUTHORIZED) || !array_key_exists($isoCode, self::PS_CHECKOUT_STATE_PARTIAL_REFUND) || !array_key_exists($isoCode, self::PS_CHECKOUT_STATE_WAITING_CAPTURE)) { From dd8fd4f770dbe63c86e629c66c491cd11970385f Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Wed, 28 Jun 2023 12:14:26 +0200 Subject: [PATCH 08/31] Change order status to canceled if exist when payment approval is reversed --- config/common.yml | 8 ++ .../GetOrderForApprovalReversedQuery.php | 50 +++++++++ ...GetOrderForApprovalReversedQueryResult.php | 102 ++++++++++++++++++ ...etOrderForApprovalReversedQueryHandler.php | 92 ++++++++++++++++ .../PayPalOrderEventSubscriber.php | 58 ++++++++-- 5 files changed, 304 insertions(+), 6 deletions(-) create mode 100644 src/Order/Query/GetOrderForApprovalReversedQuery.php create mode 100644 src/Order/Query/GetOrderForApprovalReversedQueryResult.php create mode 100644 src/Order/QueryHandler/GetOrderForApprovalReversedQueryHandler.php diff --git a/config/common.yml b/config/common.yml index 088128b69..0e63db593 100644 --- a/config/common.yml +++ b/config/common.yml @@ -462,6 +462,7 @@ services: PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForPaymentPendingQuery: "ps_checkout.query.handler.order.get_order_for_payment_pending" PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForPaymentRefundedQuery: "ps_checkout.query.handler.order.get_order_for_payment_refunded" PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForPaymentReversedQuery: "ps_checkout.query.handler.order.get_order_for_payment_reversed" + PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForApprovalReversedQuery: "ps_checkout.query.handler.order.get_order_for_approval_reversed" PrestaShop\Module\PrestashopCheckout\PayPal\Identity\Query\GetClientTokenPayPalQuery: "ps_checkout.query.handler.paypal.identity.get_client_token" PrestaShop\Module\PrestashopCheckout\PayPal\Order\Query\GetCurrentPayPalOrderStatusQuery: "ps_checkout.query.handler.paypal.order.get_current_paypal_order_status" PrestaShop\Module\PrestashopCheckout\PayPal\Order\Query\GetPayPalOrderForCheckoutCompletedQuery: "ps_checkout.query.handler.paypal.order.get_paypal_order_for_checkout_completed" @@ -497,6 +498,7 @@ services: - "@ps_checkout.cache.paypal.order" - "@ps_checkout.checkout.checker" - "@ps_checkout.paypal.order.service.check_transition_paypal_order_status" + - "@ps_checkout.order.state.service.order_state_mapper" ps_checkout.event.subscriber.paypal.capture: class: 'PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Capture\EventSubscriber\PayPalCaptureEventSubscriber' @@ -604,6 +606,12 @@ services: arguments: - "@ps_checkout.repository.pscheckoutcart" + ps_checkout.query.handler.order.get_order_for_approval_reversed: + class: 'PrestaShop\Module\PrestashopCheckout\Order\QueryHandler\GetOrderForApprovalReversedQueryHandler' + public: true + arguments: + - "@ps_checkout.repository.pscheckoutcart" + ps_checkout.query.handler.paypal.identity.get_client_token: class: 'PrestaShop\Module\PrestashopCheckout\PayPal\Identity\QueryHandler\GetClientTokenPayPalQueryHandler' public: true diff --git a/src/Order/Query/GetOrderForApprovalReversedQuery.php b/src/Order/Query/GetOrderForApprovalReversedQuery.php new file mode 100644 index 000000000..f9c4ec4ea --- /dev/null +++ b/src/Order/Query/GetOrderForApprovalReversedQuery.php @@ -0,0 +1,50 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 + */ + +namespace PrestaShop\Module\PrestashopCheckout\Order\Query; + +use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Exception\PayPalOrderException; +use PrestaShop\Module\PrestashopCheckout\PayPal\Order\ValueObject\PayPalOrderId; + +class GetOrderForApprovalReversedQuery +{ + /** + * @var PayPalOrderId + */ + private $orderPayPalId; + + /** + * @param string $orderPayPalId + * + * @throws PayPalOrderException + */ + public function __construct($orderPayPalId) + { + $this->orderPayPalId = new PayPalOrderId($orderPayPalId); + } + + /** + * @return PayPalOrderId + */ + public function getOrderPayPalId() + { + return $this->orderPayPalId; + } +} diff --git a/src/Order/Query/GetOrderForApprovalReversedQueryResult.php b/src/Order/Query/GetOrderForApprovalReversedQueryResult.php new file mode 100644 index 000000000..96cc0b578 --- /dev/null +++ b/src/Order/Query/GetOrderForApprovalReversedQueryResult.php @@ -0,0 +1,102 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 + */ + +namespace PrestaShop\Module\PrestashopCheckout\Order\Query; + +use PrestaShop\Module\PrestashopCheckout\Order\Exception\OrderException; +use PrestaShop\Module\PrestashopCheckout\Order\State\Exception\OrderStateException; +use PrestaShop\Module\PrestashopCheckout\Order\State\ValueObject\OrderStateId; +use PrestaShop\Module\PrestashopCheckout\Order\ValueObject\OrderId; + +class GetOrderForApprovalReversedQueryResult +{ + /** + * @var OrderId + */ + private $orderId; + + /** + * @var OrderStateId + */ + private $currentStateId; + + /** + * @var bool + */ + private $hasBeenPaid; + + /** + * @var bool + */ + private $hasBeenCanceled; + + /** + * @param int $orderId + * @param int $currentStateId + * @param bool $hasBeenPaid + * @param bool $hasBeenCanceled + * + * @throws OrderException + * @throws OrderStateException + */ + public function __construct( + $orderId, + $currentStateId, + $hasBeenPaid, + $hasBeenCanceled + ) { + $this->orderId = new OrderId($orderId); + $this->currentStateId = new OrderStateId($currentStateId); + $this->hasBeenPaid = $hasBeenPaid; + $this->hasBeenCanceled = $hasBeenCanceled; + } + + /** + * @return OrderId + */ + public function getOrderId() + { + return $this->orderId; + } + + /** + * @return OrderStateId + */ + public function getCurrentStateId() + { + return $this->currentStateId; + } + + /** + * @return bool + */ + public function hasBeenPaid() + { + return $this->hasBeenPaid; + } + + /** + * @return bool + */ + public function hasBeenCanceled() + { + return $this->hasBeenCanceled; + } +} diff --git a/src/Order/QueryHandler/GetOrderForApprovalReversedQueryHandler.php b/src/Order/QueryHandler/GetOrderForApprovalReversedQueryHandler.php new file mode 100644 index 000000000..4c394c044 --- /dev/null +++ b/src/Order/QueryHandler/GetOrderForApprovalReversedQueryHandler.php @@ -0,0 +1,92 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 + */ + +namespace PrestaShop\Module\PrestashopCheckout\Order\QueryHandler; + +use Configuration; +use Order; +use PrestaShop\Module\PrestashopCheckout\Cart\Exception\CartNotFoundException; +use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException; +use PrestaShop\Module\PrestashopCheckout\Order\Exception\OrderNotFoundException; +use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForApprovalReversedQuery; +use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForApprovalReversedQueryResult; +use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateConfigurationKeys; +use PrestaShop\Module\PrestashopCheckout\Repository\PsCheckoutCartRepository; +use PrestaShopCollection; +use PrestaShopDatabaseException; +use PrestaShopException; +use PsCheckoutCart; +use Validate; + +class GetOrderForApprovalReversedQueryHandler +{ + /** + * @var PsCheckoutCartRepository + */ + private $psCheckoutCartRepository; + + public function __construct(PsCheckoutCartRepository $psCheckoutCartRepository) + { + $this->psCheckoutCartRepository = $psCheckoutCartRepository; + } + + /** + * @param GetOrderForApprovalReversedQuery $query + * + * @return GetOrderForApprovalReversedQueryResult + * + * @throws PsCheckoutException + * @throws PrestaShopDatabaseException + * @throws PrestaShopException + */ + public function handle(GetOrderForApprovalReversedQuery $query) + { + /** @var PsCheckoutCart|false $psCheckoutCart */ + $psCheckoutCart = $this->psCheckoutCartRepository->findOneByPayPalOrderId($query->getOrderPayPalId()->getValue()); + + if (!$psCheckoutCart) { + throw new CartNotFoundException('No PrestaShop Cart associated to this PayPal Order at this time.'); + } + + $orders = new PrestaShopCollection(Order::class); + $orders->where('id_cart', '=', $psCheckoutCart->getIdCart()); + + if (!$orders->count()) { + throw new OrderNotFoundException('No PrestaShop Order associated to this PayPal Order at this time.'); + } + + /** @var Order $order */ + $order = $orders->getFirst(); + + if (!Validate::isLoadedObject($order)) { + throw new OrderNotFoundException('No PrestaShop Order associated to this PayPal Order at this time.'); + } + + $hasBeenCanceled = count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::CANCELED))); + + return new GetOrderForApprovalReversedQueryResult( + (int) $order->id, + (int) $order->getCurrentState(), + (bool) $order->hasBeenPaid(), + (bool) $hasBeenCanceled + ); + } +} diff --git a/src/PayPal/Order/EventSubscriber/PayPalOrderEventSubscriber.php b/src/PayPal/Order/EventSubscriber/PayPalOrderEventSubscriber.php index b1ed55843..9d74b1b9c 100644 --- a/src/PayPal/Order/EventSubscriber/PayPalOrderEventSubscriber.php +++ b/src/PayPal/Order/EventSubscriber/PayPalOrderEventSubscriber.php @@ -22,7 +22,14 @@ namespace PrestaShop\Module\PrestashopCheckout\PayPal\Order\EventSubscriber; use PrestaShop\Module\PrestashopCheckout\Checkout\CheckoutChecker; +use PrestaShop\Module\PrestashopCheckout\CommandBus\CommandBusInterface; use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException; +use PrestaShop\Module\PrestashopCheckout\Order\Command\UpdateOrderStatusCommand; +use PrestaShop\Module\PrestashopCheckout\Order\Exception\OrderNotFoundException; +use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForApprovalReversedQuery; +use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForApprovalReversedQueryResult; +use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateConfigurationKeys; +use PrestaShop\Module\PrestashopCheckout\Order\State\Service\OrderStateMapper; use PrestaShop\Module\PrestashopCheckout\PayPal\Order\CheckTransitionPayPalOrderStatusService; use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Command\CapturePayPalOrderCommand; use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Command\SavePayPalOrderCommand; @@ -64,18 +71,31 @@ class PayPalOrderEventSubscriber implements EventSubscriberInterface */ private $checkTransitionPayPalOrderStatusService; + /** + * @var OrderStateMapper + */ + private $orderStateMapper; + + /** + * @var CommandBusInterface + */ + private $commandBus; + public function __construct( Ps_checkout $module, PsCheckoutCartRepository $psCheckoutCartRepository, CacheInterface $orderPayPalCache, CheckoutChecker $checkoutChecker, - CheckTransitionPayPalOrderStatusService $checkTransitionPayPalOrderStatusService + CheckTransitionPayPalOrderStatusService $checkTransitionPayPalOrderStatusService, + OrderStateMapper $orderStateMapper ) { $this->module = $module; $this->psCheckoutCartRepository = $psCheckoutCartRepository; $this->orderPayPalCache = $orderPayPalCache; $this->checkoutChecker = $checkoutChecker; $this->checkTransitionPayPalOrderStatusService = $checkTransitionPayPalOrderStatusService; + $this->orderStateMapper = $orderStateMapper; + $this->commandBus = $this->module->getService('ps_checkout.bus.command'); } /** @@ -99,6 +119,7 @@ public static function getSubscribedEvents() ], PayPalOrderApprovalReversedEvent::class => [ ['saveApprovalReversedPayPalOrder'], + ['setApprovalReversedOrderStatus'], ['clearCache'], ], ]; @@ -116,7 +137,7 @@ public function saveCreatedPayPalOrder(PayPalOrderCreatedEvent $event) return; } - $this->module->getService('ps_checkout.bus.command')->handle(new SavePayPalOrderCommand( + $this->commandBus->handle(new SavePayPalOrderCommand( $event->getOrderPayPalId()->getValue(), PayPalOrderStatus::CREATED, $event->getOrderPayPal() @@ -135,7 +156,7 @@ public function saveApprovedPayPalOrder(PayPalOrderApprovedEvent $event) return; } - $this->module->getService('ps_checkout.bus.command')->handle(new SavePayPalOrderCommand( + $this->commandBus->handle(new SavePayPalOrderCommand( $event->getOrderPayPalId()->getValue(), PayPalOrderStatus::APPROVED, $event->getOrderPayPal() @@ -154,7 +175,7 @@ public function saveCompletedPayPalOrder(PayPalOrderCompletedEvent $event) return; } - $this->module->getService('ps_checkout.bus.command')->handle(new SavePayPalOrderCommand( + $this->commandBus->handle(new SavePayPalOrderCommand( $event->getOrderPayPalId()->getValue(), PayPalOrderStatus::COMPLETED, $event->getOrderPayPal() @@ -173,7 +194,7 @@ public function saveApprovalReversedPayPalOrder(PayPalOrderApprovalReversedEvent return; } - $this->module->getService('ps_checkout.bus.command')->handle(new SavePayPalOrderCommand( + $this->commandBus->handle(new SavePayPalOrderCommand( $event->getOrderPayPalId()->getValue(), PayPalOrderStatus::REVERSED, $event->getOrderPayPal() @@ -199,7 +220,7 @@ public function capturePayPalOrder(PayPalOrderApprovedEvent $event) $this->checkoutChecker->continueWithAuthorization($psCheckoutCart->getIdCart(), $event->getOrderPayPal()); - $this->module->getService('ps_checkout.bus.command')->handle( + $this->commandBus->handle( new CapturePayPalOrderCommand( $event->getOrderPayPalId()->getValue(), $psCheckoutCart->getPaypalFundingSource() @@ -207,6 +228,31 @@ public function capturePayPalOrder(PayPalOrderApprovedEvent $event) ); } + public function setApprovalReversedOrderStatus(PayPalOrderApprovalReversedEvent $event) + { + try { + /** @var GetOrderForApprovalReversedQueryResult $order */ + $order = $this->commandBus->handle( + new GetOrderForApprovalReversedQuery( + $event->getOrderPayPalId()->getValue() + ) + ); + } catch (OrderNotFoundException $exception) { + return; + } + + if ($order->hasBeenCanceled() || $order->hasBeenPaid()) { + return; + } + + $this->commandBus->handle( + new UpdateOrderStatusCommand( + $order->getOrderId()->getValue(), + $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::CANCELED) + ) + ); + } + public function updateCache(PayPalOrderEvent $event) { $currentOrderPayPal = $this->orderPayPalCache->get($event->getOrderPayPalId()->getValue()); From 3eb9a497b599612e167fae5e26771d6a0011f7a8 Mon Sep 17 00:00:00 2001 From: Laurynas Date: Tue, 6 Jun 2023 17:32:50 +0300 Subject: [PATCH 09/31] Added configuration batch saving --- config/common.yml | 10 ++ .../AdminAjaxPrestashopCheckoutController.php | 117 ++++++++++++++++++ .../BatchConfigurationProcessor.php | 48 +++++++ src/OrderStates.php | 9 ++ src/Validator/BatchConfigurationValidator.php | 56 +++++++++ 5 files changed, 240 insertions(+) create mode 100644 src/Configuration/BatchConfigurationProcessor.php create mode 100644 src/Validator/BatchConfigurationValidator.php diff --git a/config/common.yml b/config/common.yml index 088128b69..56cad354e 100644 --- a/config/common.yml +++ b/config/common.yml @@ -291,6 +291,10 @@ services: - "@ps_checkout.express_checkout.configuration" - "@ps_checkout.pay_later.configuration" + ps_checkout.validator.batch_configuration: + class: 'PrestaShop\Module\PrestashopCheckout\Validator\BatchConfigurationValidator' + public: true + ps_checkout.cache.directory: class: 'PrestaShop\ModuleLibCacheDirectoryProvider\Cache\CacheDirectoryProvider' public: true @@ -422,6 +426,12 @@ services: - "@ps_checkout.webhook.service.secret_token" - ["@ps_checkout.webhook.handler.event.configuration_updated"] + ps_checkout.configuration.batch_processor: + class: 'PrestaShop\Module\PrestashopCheckout\Configuration\BatchConfigurationProcessor' + public: true + arguments: + - '@ps_checkout.configuration' + ps_accounts.installer: class: 'PrestaShop\PsAccountsInstaller\Installer\Installer' public: true diff --git a/controllers/admin/AdminAjaxPrestashopCheckoutController.php b/controllers/admin/AdminAjaxPrestashopCheckoutController.php index 7913cd1d3..e410da135 100755 --- a/controllers/admin/AdminAjaxPrestashopCheckoutController.php +++ b/controllers/admin/AdminAjaxPrestashopCheckoutController.php @@ -17,13 +17,17 @@ * @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 */ + use Monolog\Logger; +use PrestaShop\Module\PrestashopCheckout\Configuration\BatchConfigurationProcessor; use PrestaShop\Module\PrestashopCheckout\Logger\LoggerDirectory; use PrestaShop\Module\PrestashopCheckout\Logger\LoggerFactory; use PrestaShop\Module\PrestashopCheckout\Logger\LoggerFileFinder; use PrestaShop\Module\PrestashopCheckout\Logger\LoggerFileReader; +use PrestaShop\Module\PrestashopCheckout\OrderStates; use PrestaShop\Module\PrestashopCheckout\Presenter\Order\OrderPresenter; use PrestaShop\Module\PrestashopCheckout\Settings\RoundingSettings; +use PrestaShop\Module\PrestashopCheckout\Validator\BatchConfigurationValidator; use Psr\SimpleCache\CacheInterface; class AdminAjaxPrestashopCheckoutController extends ModuleAdminController @@ -849,6 +853,119 @@ public function ajaxProcessCheckConfiguration() $this->exitWithResponse($response); } + public function ajaxProcessFetchConfiguration() + { + $response = []; + + $query = new DbQuery(); + $query->select('name, value, date_add, date_upd'); + $query->from('configuration'); + $query->where('name LIKE "PS_CHECKOUT_%"'); + + /** @var int|null $shopId When multishop is disabled, it returns null, so we don't have to restrict results by shop */ + $shopId = Shop::getContextShopID(true); + + // When ShopId is not NULL, we have to retrieve global values with id_shop = NULL and shop values with id_shop = ShopId + if ($shopId) { + $query->where('id_shop IS NULL OR id_shop = ' . (int) $shopId); + } + + $configurations = Db::getInstance()->executeS($query); + + $response = [ + 'httpCode' => 200, + 'status' => !empty($configurations), + 'configuration' => array_map(function ($configuration) { + return [ + 'name' => $configuration['name'], + 'value' => $configuration['value'], + ]; + }, $configurations), + ]; + + $this->exitWithResponse($response); + } + + public function ajaxProcessGetMappedOrderStates() + { + /** @var \PrestaShop\Module\PrestashopCheckout\Configuration\PrestaShopConfiguration $configuration */ + $configuration = $this->module->getService('ps_checkout.configuration'); + + $mappedOrderStates = [ + OrderStates::PS_CHECKOUT_STATE_PENDING => [ + 'default' => '0', + 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_PENDING, ['default' => '0']), + ], + OrderStates::PS_CHECKOUT_STATE_COMPLETED => [ + 'default' => $configuration->get('PS_OS_PAYMENT'), + 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_COMPLETED, ['default' => '0']), + ], + OrderStates::PS_CHECKOUT_STATE_CANCELED => [ + 'default' => $configuration->get('PS_OS_CANCELED'), + 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_CANCELED, ['default' => '0']), + ], + OrderStates::PS_CHECKOUT_STATE_ERROR => [ + 'default' => $configuration->get('PS_OS_ERROR'), + 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_ERROR, ['default' => '0']), + ], + OrderStates::PS_CHECKOUT_STATE_REFUNDED => [ + 'default' => $configuration->get('PS_OS_REFUND'), + 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_REFUNDED, ['default' => '0']), + ], + OrderStates::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED => [ + 'default' => '0', + 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED, ['default' => '0']), + ], + OrderStates::PS_CHECKOUT_STATE_PARTIALLY_PAID => [ + 'default' => '0', + 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_PARTIALLY_PAID, ['default' => '0']), + ], + OrderStates::PS_CHECKOUT_STATE_AUTHORIZED => [ + 'default' => '0', + 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_AUTHORIZED, ['default' => '0']), + ], + ]; + + $this->exitWithResponse([ + 'status' => true, + 'mappedOrderStates' => $mappedOrderStates, + ]); + } + + public function ajaxProcessBatchSaveConfiguration() + { + /** @var BatchConfigurationValidator $configurationValidator */ + $configurationValidator = $this->module->getService('ps_checkout.validator.batch_configuration'); + /** @var BatchConfigurationProcessor $batchConfigurationProcessor */ + $batchConfigurationProcessor = $this->module->getService('ps_checkout.configuration.batch_processor'); + + $configuration = json_decode(Tools::getValue('configuration'), true); + try { + $configurationValidator->validateAjaxBatchConfiguration($configuration); + $batchConfigurationProcessor->saveBatchConfiguration($configuration); + + $this->exitWithResponse([ + 'status' => true, + ]); + } catch (Exception $exception) { + $this->exitWithResponse([ + 'httpCode' => 500, + 'status' => false, + 'error' => $exception->getMessage(), + ]); + } + } + + public function ajaxProcessGetOrderStates() + { + $orderStates = OrderState::getOrderStates(Context::getContext()->language->id); + + $this->exitWithResponse([ + 'status' => true, + 'orderStates' => $orderStates, + ]); + } + /** * @param array $response * diff --git a/src/Configuration/BatchConfigurationProcessor.php b/src/Configuration/BatchConfigurationProcessor.php new file mode 100644 index 000000000..2603e7103 --- /dev/null +++ b/src/Configuration/BatchConfigurationProcessor.php @@ -0,0 +1,48 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 + */ + +namespace PrestaShop\Module\PrestashopCheckout\Configuration; + +use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException; + +class BatchConfigurationProcessor +{ + /** @var PrestaShopConfiguration */ + private $prestaShopConfiguration; + + public function __construct(PrestaShopConfiguration $prestaShopConfiguration) + { + $this->prestaShopConfiguration = $prestaShopConfiguration; + } + + /** + * @param array $configuration + * + * @return void + * + * @throws PsCheckoutException + */ + public function saveBatchConfiguration($configuration) + { + foreach ($configuration as $configurationItem) { + $this->prestaShopConfiguration->set(pSQL($configurationItem['name']), pSQL($configurationItem['value'])); + } + } +} diff --git a/src/OrderStates.php b/src/OrderStates.php index f417523f2..d6b79ec04 100644 --- a/src/OrderStates.php +++ b/src/OrderStates.php @@ -34,6 +34,15 @@ class OrderStates const DARK_BLUE_HEXA_COLOR = '#34209E'; const BLUE_HEXA_COLOR = '#3498D8'; const GREEN_HEXA_COLOR = '#01B887'; + + const PS_CHECKOUT_STATE_PENDING = 'PS_CHECKOUT_STATE_PENDING'; + const PS_CHECKOUT_STATE_COMPLETED = 'PS_CHECKOUT_STATE_COMPLETED'; + const PS_CHECKOUT_STATE_CANCELED = 'PS_CHECKOUT_STATE_CANCELED'; + const PS_CHECKOUT_STATE_ERROR = 'PS_CHECKOUT_STATE_ERROR'; + const PS_CHECKOUT_STATE_PARTIALLY_REFUNDED = 'PS_CHECKOUT_STATE_PARTIALLY_REFUNDED'; + const PS_CHECKOUT_STATE_REFUNDED = 'PS_CHECKOUT_STATE_REFUNDED'; + const PS_CHECKOUT_STATE_PARTIALLY_PAID = 'PS_CHECKOUT_STATE_PARTIALLY_PAID'; + const PS_CHECKOUT_STATE_AUTHORIZED = 'PS_CHECKOUT_STATE_AUTHORIZED'; const ORDER_STATES = [ 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT' => self::DARK_BLUE_HEXA_COLOR, 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT' => self::DARK_BLUE_HEXA_COLOR, diff --git a/src/Validator/BatchConfigurationValidator.php b/src/Validator/BatchConfigurationValidator.php new file mode 100644 index 000000000..1cc375643 --- /dev/null +++ b/src/Validator/BatchConfigurationValidator.php @@ -0,0 +1,56 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 + */ + +namespace PrestaShop\Module\PrestashopCheckout\Validator; + +use Exception; +use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration; + +class BatchConfigurationValidator +{ + const BLACKLISTED_CONFIGURATION_KEYS = [ + PayPalConfiguration::PS_CHECKOUT_PAYPAL_ID_MERCHANT, + PayPalConfiguration::PS_CHECKOUT_PAYPAL_COUNTRY_MERCHANT, + PayPalConfiguration::PS_CHECKOUT_PAYPAL_EMAIL_STATUS, + PayPalConfiguration::PS_CHECKOUT_PAYPAL_PAYMENT_STATUS, + ]; + + /** + * @param array $configuration + * + * @throws Exception + */ + public function validateAjaxBatchConfiguration($configuration) + { + if (empty($configuration) || !is_array($configuration)) { + throw new Exception("Config can't be empty"); + } + + foreach ($configuration as $configurationItem) { + if (empty($configurationItem['name']) || 0 !== strpos($configurationItem['name'], 'PS_CHECKOUT_')) { + throw new Exception('Received invalid configuration key'); + } + + if (array_search($configurationItem['name'], self::BLACKLISTED_CONFIGURATION_KEYS)) { + throw new Exception('Received blacklisted configuration key'); + } + } + } +} From 2f294e8b4ce0af8c3cfb9fffa2a199a70e5f5d82 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Thu, 13 Jul 2023 13:01:57 +0200 Subject: [PATCH 10/31] Waiting payment order state --- .../CommandHandler/CreateOrderCommandHandler.php | 11 +---------- .../GetOrderForPaymentPendingQueryHandler.php | 3 ++- src/Order/State/Service/OrderStateMapper.php | 1 + .../PayPalCaptureEventSubscriber.php | 13 +------------ src/Presenter/Order/OrderPendingPresenter.php | 3 ++- 5 files changed, 7 insertions(+), 24 deletions(-) diff --git a/src/Order/CommandHandler/CreateOrderCommandHandler.php b/src/Order/CommandHandler/CreateOrderCommandHandler.php index ec7408102..ce8055023 100644 --- a/src/Order/CommandHandler/CreateOrderCommandHandler.php +++ b/src/Order/CommandHandler/CreateOrderCommandHandler.php @@ -155,16 +155,7 @@ public function handle(CreateOrderCommand $command) $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PAYMENT_ACCEPTED); } } else { - switch ($fundingSource) { - case 'card': - $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::WAITING_CREDIT_CARD_PAYMENT); - break; - case 'paypal': - $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::WAITING_PAYPAL_PAYMENT); - break; - default: - $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::WAITING_LOCAL_PAYMENT); - } + $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::WAITING_PAYMENT); } /** @var FundingSourceTranslationProvider $fundingSourceTranslationProvider */ diff --git a/src/Order/QueryHandler/GetOrderForPaymentPendingQueryHandler.php b/src/Order/QueryHandler/GetOrderForPaymentPendingQueryHandler.php index 89875d65d..b04b6f19a 100644 --- a/src/Order/QueryHandler/GetOrderForPaymentPendingQueryHandler.php +++ b/src/Order/QueryHandler/GetOrderForPaymentPendingQueryHandler.php @@ -95,7 +95,8 @@ public function handle(GetOrderForPaymentPendingQuery $query) */ private function isInPending(Order $order) { - return count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::WAITING_CREDIT_CARD_PAYMENT))) + return count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::WAITING_PAYMENT))) + || count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::WAITING_CREDIT_CARD_PAYMENT))) || count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::WAITING_PAYPAL_PAYMENT))) || count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::WAITING_LOCAL_PAYMENT))); } diff --git a/src/Order/State/Service/OrderStateMapper.php b/src/Order/State/Service/OrderStateMapper.php index b050f4fa3..f11782f68 100644 --- a/src/Order/State/Service/OrderStateMapper.php +++ b/src/Order/State/Service/OrderStateMapper.php @@ -55,6 +55,7 @@ public function __construct(PrestaShopConfiguration $configuration) OrderStateConfigurationKeys::WAITING_CREDIT_CARD_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::WAITING_CREDIT_CARD_PAYMENT, ['global' => true]), OrderStateConfigurationKeys::WAITING_PAYPAL_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::WAITING_PAYPAL_PAYMENT, ['global' => true]), OrderStateConfigurationKeys::WAITING_LOCAL_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::WAITING_LOCAL_PAYMENT, ['global' => true]), + OrderStateConfigurationKeys::WAITING_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::WAITING_PAYMENT, ['global' => true]), ]; } diff --git a/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php b/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php index 59b1df49b..e7c4693c0 100644 --- a/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php +++ b/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php @@ -184,18 +184,7 @@ public function setPaymentPendingOrderStatus(PayPalCapturePendingEvent $event) return; } - switch ($order->getPaymentMethod()) { - case 'card': - $newOrderStateId = $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::WAITING_CREDIT_CARD_PAYMENT); - break; - case 'paypal': - $newOrderStateId = $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::WAITING_PAYPAL_PAYMENT); - break; - default: - $newOrderStateId = $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::WAITING_LOCAL_PAYMENT); - } - - $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $newOrderStateId)); + $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::WAITING_PAYMENT))); } public function setPaymentDeclinedOrderStatus(PayPalCaptureDeclinedEvent $event) diff --git a/src/Presenter/Order/OrderPendingPresenter.php b/src/Presenter/Order/OrderPendingPresenter.php index b73087dcb..0089891c7 100644 --- a/src/Presenter/Order/OrderPendingPresenter.php +++ b/src/Presenter/Order/OrderPendingPresenter.php @@ -47,7 +47,8 @@ public function present() $orderTranslations = new OrderStatesTranslations(); $orderTranslations = $orderTranslations->getTranslations($context->language->iso_code); foreach (OrderStates::ORDER_STATES as $key => $value) { - if ($key == 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT' || + if ($key == 'PS_CHECKOUT_STATE_WAITING_PAYMENT' || + $key == 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT' || $key == 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT' || $key == 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT' || $key == 'PS_CHECKOUT_STATE_WAITING_CAPTURE' From 557b06b09897b946d6ddb8157365f13ae30714df Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Thu, 13 Jul 2023 11:53:14 +0200 Subject: [PATCH 11/31] Fix stocks management issues before PS 1.7.3.2 --- src/Checkout/CheckoutChecker.php | 33 ++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/Checkout/CheckoutChecker.php b/src/Checkout/CheckoutChecker.php index 9ffef68a2..5fe0dd87f 100644 --- a/src/Checkout/CheckoutChecker.php +++ b/src/Checkout/CheckoutChecker.php @@ -25,6 +25,7 @@ use Customer; use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException; use PrestaShop\Module\PrestashopCheckout\PayPal\Card3DSecure; +use Product; use Psr\Log\LoggerInterface; use Validate; @@ -107,10 +108,7 @@ public function continueWithAuthorization($cartId, $orderPayPal) throw new PsCheckoutException(sprintf('Cart with id %s has no product. Cannot capture the order.', var_export($cart->id, true)), PsCheckoutException::CART_PRODUCT_MISSING); } - if ($cart->isAllProductsInStock() !== true || - (method_exists($cart, 'checkAllProductsAreStillAvailableInThisState') && $cart->checkAllProductsAreStillAvailableInThisState() !== true) || - (method_exists($cart, 'checkAllProductsHaveMinimalQuantities') && $cart->checkAllProductsHaveMinimalQuantities() !== true) - ) { + if (!$this->isAllProductsInStock($cart)) { throw new PsCheckoutException(sprintf('Cart with id %s contains products unavailable. Cannot capture the order.', var_export($cart->id, true)), PsCheckoutException::CART_PRODUCT_UNAVAILABLE); } @@ -134,4 +132,31 @@ public function continueWithAuthorization($cartId, $orderPayPal) throw new PsCheckoutException('The transaction amount does not match with the cart amount.', PsCheckoutException::DIFFERENCE_BETWEEN_TRANSACTION_AND_CART); } } + + private function isAllProductsInStock(Cart $cart) + { + if (!Configuration::get('PS_STOCK_MANAGEMENT')) { + return true; + } + + if (version_compare(_PS_VERSION_, '1.7.3.2', '>=')) { + return $cart->isAllProductsInStock() !== true || + (method_exists($cart, 'checkAllProductsAreStillAvailableInThisState') && $cart->checkAllProductsAreStillAvailableInThisState() !== true) || + (method_exists($cart, 'checkAllProductsHaveMinimalQuantities') && $cart->checkAllProductsHaveMinimalQuantities() !== true); + } + + foreach ($cart->getProducts() as $product) { + $availableOutOfStock = Product::isAvailableWhenOutOfStock($product['out_of_stock']); + $productQuantity = Product::getQuantity( + $product['id_product'], + !empty($product['id_product_attribute']) ? $product['id_product_attribute'] : null + ); + + if ($productQuantity < 0 && !$availableOutOfStock) { + return false; + } + } + + return true; + } } From 1667c483c283fae4d20f9cc56faae2354e3cef91 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:52:20 +0200 Subject: [PATCH 12/31] Update upgrade files --- ps_checkout.php | 2 +- upgrade/upgrade-6.3.3.0.php | 209 ------------------------------------ upgrade/upgrade-6.3.4.0.php | 198 ++++++++++++++++++++++++++++++---- 3 files changed, 177 insertions(+), 232 deletions(-) diff --git a/ps_checkout.php b/ps_checkout.php index 18182fd36..c02d049b1 100755 --- a/ps_checkout.php +++ b/ps_checkout.php @@ -115,7 +115,7 @@ class Ps_checkout extends PaymentModule 'PS_CHECKOUT_LIVE_STEP_VIEWED' => false, 'PS_CHECKOUT_INTEGRATION_DATE' => self::INTEGRATION_DATE, 'PS_CHECKOUT_WEBHOOK_SECRET' => '', - 'PS_CHECKOUT_LIABILITY_SHIFT_REQ' => '1', + 'PS_CHECKOUT_LIABILITY_SHIFT_REQ' => '0', ]; public $confirmUninstall; diff --git a/upgrade/upgrade-6.3.3.0.php b/upgrade/upgrade-6.3.3.0.php index 21ccd35bf..bbce6e781 100644 --- a/upgrade/upgrade-6.3.3.0.php +++ b/upgrade/upgrade-6.3.3.0.php @@ -42,182 +42,6 @@ function upgrade_module_6_3_3_0($module) try { $db = Db::getInstance(); - - // Installing FundingSource if table pscheckout_funding_source is empty or incomplete - $fundingSources = ['paypal', 'paylater', 'card', 'bancontact', 'eps', 'giropay', 'ideal', 'mybank', 'p24', 'sofort']; - $availableFundingSourcesByShops = []; - $maxPositionByShops = []; - $availableFundingSources = $db->executeS('SELECT * FROM ' . _DB_PREFIX_ . 'pscheckout_funding_source'); - - if (!empty($availableFundingSources)) { - foreach ($availableFundingSources as $availableFundingSource) { - $currentPosition = (int) $availableFundingSource['position']; - $shopId = (int) $availableFundingSource['id_shop']; - if ( - !isset($maxPositionByShops[$shopId]) - || $maxPositionByShops[$shopId] < $currentPosition - ) { - $maxPositionByShops[$shopId] = $currentPosition; - } - $availableFundingSourcesByShops[$shopId][] = $availableFundingSource['name']; - } - } - - foreach (Shop::getShops(false, null, true) as $shopId) { - $currentPosition = isset($maxPositionByShops[(int) $shopId]) ? $maxPositionByShops[(int) $shopId] + 1 : 1; - foreach ($fundingSources as $fundingSource) { - if (!isset($availableFundingSourcesByShops[(int) $shopId]) || !in_array($fundingSource, $availableFundingSourcesByShops[(int) $shopId], true)) { - $db->insert( - 'pscheckout_funding_source', - [ - 'name' => pSQL($fundingSource), - 'active' => 1, - 'position' => (int) $currentPosition, - 'id_shop' => (int) $savedShopId, - ] - ); - ++$currentPosition; - } - } - } - - // Check module OrderState - $moduleOrderStates = [ - 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT'), - 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT'), - 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT'), - 'PS_CHECKOUT_STATE_AUTHORIZED' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_AUTHORIZED'), - 'PS_CHECKOUT_STATE_PARTIAL_REFUND' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_PARTIAL_REFUND'), - 'PS_CHECKOUT_STATE_WAITING_CAPTURE' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_CAPTURE'), - ]; - $moduleOrderStatesId = array_values($moduleOrderStates); - - $orderStateCollection = new PrestaShopCollection(OrderState::class); - $orderStateCollection->where('module_name', '=', $module->name); - $orderStateCollection->where('deleted', '=', '0'); - - /** @var OrderState[] $orderStates */ - $orderStates = $orderStateCollection->getResults(); - $currentModuleOrderStatesId = []; - - if (!empty($orderStates)) { - foreach ($orderStates as $orderState) { - $orderStateId = (int) $orderState->id; - if (!in_array($orderStateId, $moduleOrderStatesId, true)) { - $orderState->deleted = true; - $orderState->save(); - } else { - $currentModuleOrderStatesId[] = $orderStateId; - } - } - } - - foreach ($moduleOrderStates as $configuration_key => $id_order_state) { - if ( - !$id_order_state - || !in_array((int) $id_order_state, $currentModuleOrderStatesId, true) - ) { - switch ($configuration_key) { - case 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT': - ps_checkout_create_order_state_6_3_3_0( - 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT', - '#34209E', - [ - 'en' => 'Waiting for PayPal payment', - 'fr' => 'En attente de paiement par PayPal', - 'es' => 'Esperando el pago con PayPal', - 'it' => 'In attesa di pagamento con PayPal', - 'nl' => 'Wachten op PayPal-betaling', - 'de' => 'Warten auf PayPal-Zahlung', - 'pl' => 'Oczekiwanie na płatność PayPal', - 'pt' => 'Aguardando pagamento pelo PayPal', - ] - ); - break; - case 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT': - ps_checkout_create_order_state_6_3_3_0( - 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT', - '#34209E', - [ - 'en' => 'Waiting for Credit Card Payment', - 'fr' => 'En attente de paiement par Carte de Crédit', - 'es' => 'Esperando el pago con tarjeta de crédito', - 'it' => 'In attesa di pagamento con carta di credito', - 'nl' => 'Wachten op creditcard-betaling', - 'de' => 'Warten auf Kreditkartenzahlung', - 'pl' => 'Oczekiwanie na płatność kartą kredytową', - 'pt' => 'Aguardando pagamento por cartão de crédito', - ] - ); - break; - case 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT': - ps_checkout_create_order_state_6_3_3_0( - 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT', - '#34209E', - [ - 'en' => 'Waiting for Local Payment Method Payment', - 'fr' => 'En attente de paiement par moyen de paiement local', - 'es' => 'Esperando el pago con un método de pago local', - 'it' => 'In attesa di pagamento con metodo di pagamento locale', - 'nl' => 'Wachten op nlaatselijke betaling', - 'de' => 'Warten auf Zahlung per lokaler Zahlungsmethode', - 'pl' => 'Oczekiwanie na płatność lokalnym środkiem płatności', - 'pt' => 'Aguardando pagamento pelo método de pagamento local', - ] - ); - break; - case 'PS_CHECKOUT_STATE_AUTHORIZED': - ps_checkout_create_order_state_6_3_3_0( - 'PS_CHECKOUT_STATE_AUTHORIZED', - '#3498D8', - [ - 'en' => 'Authorized. To be captured by merchant', - 'fr' => 'Autorisation. A capturer par le marchand', - 'es' => 'Autorizado. El vendedor lo capturará', - 'it' => 'Autorizzato. Sarà acquisito dal commerciante', - 'nl' => 'Goedgekeurd. Door retailer te registreren.', - 'de' => 'Autorisiert. Wird von Händler erfasst.', - 'pl' => 'Pomyślna autoryzacja. Transfer do przeprowadzenia przez sklep', - 'pt' => 'Autorizado. A ser capturado pelo comerciante', - ] - ); - break; - case 'PS_CHECKOUT_STATE_PARTIAL_REFUND': - ps_checkout_create_order_state_6_3_3_0( - 'PS_CHECKOUT_STATE_PARTIAL_REFUND', - '#01B887', - [ - 'en' => 'Partial refund', - 'fr' => 'Remboursement partiel', - 'es' => 'Reembolso parcial', - 'it' => 'Rimborso parziale', - 'nl' => 'Gedeeltelijke terugbetaling', - 'de' => 'Teilweise Rückerstattung', - 'pl' => 'Częściowy zwrot', - 'pt' => 'Reembolso parcial', - ] - ); - break; - case 'PS_CHECKOUT_STATE_WAITING_CAPTURE': - ps_checkout_create_order_state_6_3_3_0( - 'PS_CHECKOUT_STATE_WAITING_CAPTURE', - '#3498D8', - [ - 'en' => 'Waiting capture', - 'fr' => 'En attente de capture', - 'es' => 'Esperando la captura', - 'it' => 'In attesa di essere acquisito', - 'nl' => 'Wachten op registratie', - 'de' => 'Warten auf Erfassung', - 'pl' => 'Oczekiwanie na transfer', - 'pt' => 'Aguardando a captura', - ] - ); - break; - } - } - } - $db->delete( 'pscheckout_cart', 'paypal_order IS NULL' @@ -249,36 +73,3 @@ function upgrade_module_6_3_3_0($module) return true; } - -function ps_checkout_create_order_state_6_3_3_0($configuration_key, $color, $nameByLangIsoCode) -{ - $orderStateNameByLangId = []; - foreach ($nameByLangIsoCode as $langIsoCode => $name) { - foreach (Language::getLanguages(false) as $language) { - if (Tools::strtolower($language['iso_code']) === $langIsoCode) { - $orderStateNameByLangId[(int) $language['id_lang']] = $name; - } elseif (isset($nameByLangIsoCode['en'])) { - $orderStateNameByLangId[(int) $language['id_lang']] = $nameByLangIsoCode['en']; - } - } - } - - $orderState = new OrderState(); - $orderState->name = $orderStateNameByLangId; - $orderState->module_name = 'ps_checkout'; - $orderState->unremovable = true; - $orderState->color = $color; - $orderState->delivery = false; - $orderState->shipped = false; - $orderState->pdf_delivery = false; - $orderState->pdf_invoice = false; - $orderState->hidden = false; - $orderState->invoice = false; - $orderState->send_email = false; - $orderState->paid = false; - $orderState->logable = false; - $orderState->deleted = false; - $orderState->template = []; - $orderState->save(); - Configuration::updateGlobalValue($configuration_key, $orderState->id); -} diff --git a/upgrade/upgrade-6.3.4.0.php b/upgrade/upgrade-6.3.4.0.php index 8a45a9fc3..33acdb790 100644 --- a/upgrade/upgrade-6.3.4.0.php +++ b/upgrade/upgrade-6.3.4.0.php @@ -30,32 +30,186 @@ */ function upgrade_module_6_3_4_0($module) { - $orderStateCollection = new PrestaShopCollection(OrderState::class); - $orderStateCollection->where('module_name', '=', $module->name); - $orderStateCollection->where('deleted', '=', '0'); - - /** @var OrderState[] $orderStates */ - $orderStates = $orderStateCollection->getResults(); - - if (!empty($orderStates)) { - foreach ($orderStates as $orderState) { - if (in_array($orderState->id, [Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT'), Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT'), Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT')])) { - $orderState->deleted = true; - $orderState->save(); + // Force PrestaShop to upgrade for all shop to avoid issues + $savedShopContext = Shop::getContext(); + $savedShopId = Shop::getContextShopID(); + $savedGroupShopId = Shop::getContextShopGroupID(); + Shop::setContext(Shop::CONTEXT_ALL); + + try { + $shopsList = Shop::getShops(false, null, true); + + foreach ($shopsList as $shopId) { + Configuration::updateValue('PS_CHECKOUT_LIABILITY_SHIFT_REQ', '0', false, null, (int) $shopId); + } + + Configuration::updateGlobalValue('PS_CHECKOUT_LIABILITY_SHIFT_REQ', '0'); + + $db = Db::getInstance(); + + // Installing FundingSource if table pscheckout_funding_source is empty or incomplete - including BLIK + $fundingSources = ['paypal', 'paylater', 'card', 'bancontact', 'eps', 'giropay', 'ideal', 'mybank', 'p24', 'sofort', 'blik']; + $availableFundingSourcesByShops = []; + $maxPositionByShops = []; + $availableFundingSources = $db->executeS('SELECT * FROM ' . _DB_PREFIX_ . 'pscheckout_funding_source'); + + if (!empty($availableFundingSources)) { + foreach ($availableFundingSources as $availableFundingSource) { + $currentPosition = (int) $availableFundingSource['position']; + $shopId = (int) $availableFundingSource['id_shop']; + + if ( + !isset($maxPositionByShops[$shopId]) + || $maxPositionByShops[$shopId] < $currentPosition + ) { + $maxPositionByShops[$shopId] = $currentPosition; + } + + $availableFundingSourcesByShops[$shopId][] = $availableFundingSource['name']; + } + } + + foreach (Shop::getShops(false, null, true) as $shopId) { + $currentPosition = isset($maxPositionByShops[(int) $shopId]) ? $maxPositionByShops[(int) $shopId] + 1 : 1; + foreach ($fundingSources as $fundingSource) { + if ( + !isset($availableFundingSourcesByShops[(int) $shopId]) + || !in_array($fundingSource, $availableFundingSourcesByShops[(int) $shopId], true) + ) { + $db->insert( + 'pscheckout_funding_source', + [ + 'name' => pSQL($fundingSource), + 'active' => 1, + 'position' => (int) $currentPosition, + 'id_shop' => (int) $savedShopId, + ] + ); + ++$currentPosition; + } } } + + // Check module OrderState + $moduleOrderStates = [ + 'PS_CHECKOUT_STATE_AUTHORIZED' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_AUTHORIZED'), + 'PS_CHECKOUT_STATE_PARTIAL_REFUND' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_PARTIAL_REFUND'), + 'PS_CHECKOUT_STATE_WAITING_CAPTURE' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_CAPTURE'), + 'PS_CHECKOUT_STATE_WAITING_PAYMENT' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_PAYMENT'), + ]; + $moduleOrderStatesId = array_values($moduleOrderStates); + $moduleOrderStatesIdToDelete = [ + (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT'), + (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT'), + (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT'), + ]; + + $orderStateCollection = new PrestaShopCollection(OrderState::class); + $orderStateCollection->where('module_name', '=', $module->name); + $orderStateCollection->where('deleted', '=', '0'); + + /** @var OrderState[] $orderStates */ + $orderStates = $orderStateCollection->getResults(); + $currentModuleOrderStatesId = []; + + if (!empty($orderStates)) { + foreach ($orderStates as $orderState) { + $orderStateId = (int) $orderState->id; + if ( + !in_array($orderStateId, $moduleOrderStatesId, true) + || in_array($orderState->id, $moduleOrderStatesIdToDelete, true) + ) { + $orderState->deleted = true; + $orderState->save(); + } else { + $currentModuleOrderStatesId[] = $orderStateId; + } + } + } + + foreach ($moduleOrderStates as $configuration_key => $id_order_state) { + if ( + !$id_order_state + || !in_array((int) $id_order_state, $currentModuleOrderStatesId, true) + ) { + switch ($configuration_key) { + case 'PS_CHECKOUT_STATE_AUTHORIZED': + ps_checkout_create_order_state_6_3_4_0( + 'PS_CHECKOUT_STATE_AUTHORIZED', + '#3498D8', + [ + 'en' => 'Authorized. To be captured by merchant', + 'fr' => 'Autorisation. A capturer par le marchand', + 'es' => 'Autorizado. El vendedor lo capturará', + 'it' => 'Autorizzato. Sarà acquisito dal commerciante', + 'nl' => 'Goedgekeurd. Door retailer te registreren.', + 'de' => 'Autorisiert. Wird von Händler erfasst.', + 'pl' => 'Pomyślna autoryzacja. Transfer do przeprowadzenia przez sklep', + 'pt' => 'Autorizado. A ser capturado pelo comerciante', + ] + ); + break; + case 'PS_CHECKOUT_STATE_PARTIAL_REFUND': + ps_checkout_create_order_state_6_3_4_0( + 'PS_CHECKOUT_STATE_PARTIAL_REFUND', + '#01B887', + [ + 'en' => 'Partial refund', + 'fr' => 'Remboursement partiel', + 'es' => 'Reembolso parcial', + 'it' => 'Rimborso parziale', + 'nl' => 'Gedeeltelijke terugbetaling', + 'de' => 'Teilweise Rückerstattung', + 'pl' => 'Częściowy zwrot', + 'pt' => 'Reembolso parcial', + ] + ); + break; + case 'PS_CHECKOUT_STATE_WAITING_PAYMENT': + ps_checkout_create_order_state_6_3_4_0('PS_CHECKOUT_STATE_WAITING_PAYMENT', '#34209E', [ + 'en' => 'Waiting for payment', + 'fr' => 'En attente de paiement', + 'es' => 'Esperando el pago', + 'it' => 'In attesa di pagamento', + 'nl' => 'Wachten op betaling', + 'de' => 'Warten auf Zahlung', + 'pl' => 'Oczekiwanie na płatność', + 'pt' => 'Aguardando pagamento', + ]); + break; + case 'PS_CHECKOUT_STATE_WAITING_CAPTURE': + ps_checkout_create_order_state_6_3_4_0( + 'PS_CHECKOUT_STATE_WAITING_CAPTURE', + '#3498D8', + [ + 'en' => 'Waiting capture', + 'fr' => 'En attente de capture', + 'es' => 'Esperando la captura', + 'it' => 'In attesa di essere acquisito', + 'nl' => 'Wachten op registratie', + 'de' => 'Warten auf Erfassung', + 'pl' => 'Oczekiwanie na transfer', + 'pt' => 'Aguardando a captura', + ] + ); + break; + } + } + } + } catch (Exception $exception) { + PrestaShopLogger::addLog($exception->getMessage(), 3, $exception->getCode(), 'Module', $module->id); + + return false; } - ps_checkout_create_order_state_6_3_4_0('PS_CHECKOUT_STATE_WAITING_PAYMENT', '#34209E', [ - 'en' => 'Waiting for payment', - 'fr' => 'En attente de paiement', - 'es' => 'Esperando el pago', - 'it' => 'In attesa di pagamento', - 'nl' => 'Wachten op betaling', - 'de' => 'Warten auf Zahlung', - 'pl' => 'Oczekiwanie na płatność', - 'pt' => 'Aguardando pagamento', - ]); + // Restore initial PrestaShop shop context + if (Shop::CONTEXT_SHOP === $savedShopContext) { + Shop::setContext($savedShopContext, $savedShopId); + } elseif (Shop::CONTEXT_GROUP === $savedShopContext) { + Shop::setContext($savedShopContext, $savedGroupShopId); + } else { + Shop::setContext($savedShopContext); + } return true; } From 1f0d186f2443f62da5ce36db72ea11379c71b5ed Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:57:10 +0200 Subject: [PATCH 13/31] Bump version to 6.3.4.0 --- config.xml | 2 +- ps_checkout.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.xml b/config.xml index e837ef16e..4702fad01 100644 --- a/config.xml +++ b/config.xml @@ -2,7 +2,7 @@ ps_checkout - + diff --git a/ps_checkout.php b/ps_checkout.php index c02d049b1..2f5a893bd 100755 --- a/ps_checkout.php +++ b/ps_checkout.php @@ -123,7 +123,7 @@ class Ps_checkout extends PaymentModule // Needed in order to retrieve the module version easier (in api call headers) than instanciate // the module each time to get the version - const VERSION = '6.3.3.1'; + const VERSION = '6.3.4.0'; const INTEGRATION_DATE = '2022-14-06'; @@ -142,7 +142,7 @@ public function __construct() // We cannot use the const VERSION because the const is not computed by addons marketplace // when the zip is uploaded - $this->version = '6.3.3.1'; + $this->version = '6.3.4.0'; $this->author = 'PrestaShop'; $this->currencies = true; $this->currencies_mode = 'checkbox'; From 61f5c2cd4cc26fd17ef203be71e76ee5cb934cf4 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Thu, 13 Jul 2023 19:26:56 +0200 Subject: [PATCH 14/31] Create new order status --- config/admin/services.yml | 16 - .../AdminAjaxPrestashopCheckoutController.php | 126 ++++--- ps_checkout.php | 3 +- .../CreateOrderCommandHandler.php | 8 +- ...etOrderForApprovalReversedQueryHandler.php | 2 +- .../GetOrderForPaymentDeniedQueryHandler.php | 4 +- .../GetOrderForPaymentPendingQueryHandler.php | 24 +- .../State/OrderStateConfigurationKeys.php | 38 +- src/Order/State/OrderStateInstaller.php | 212 +++++++++++ src/Order/State/Service/OrderStateMapper.php | 50 ++- src/OrderStates.php | 267 -------------- .../PayPalCaptureEventSubscriber.php | 14 +- src/Presenter/Order/OrderPendingPresenter.php | 83 ----- .../Transaction/TransactionPresenter.php | 63 ---- src/Presenter/Transaction/index.php | 28 -- src/Translations/OrderStatesTranslations.php | 102 ------ src/ValidateOrder.php | 345 ------------------ upgrade/upgrade-1.2.10.php | 17 - upgrade/upgrade-1.3.0.php | 1 - upgrade/upgrade-1.4.0.php | 98 ----- 20 files changed, 365 insertions(+), 1136 deletions(-) create mode 100644 src/Order/State/OrderStateInstaller.php delete mode 100644 src/OrderStates.php delete mode 100644 src/Presenter/Order/OrderPendingPresenter.php delete mode 100644 src/Presenter/Transaction/TransactionPresenter.php delete mode 100755 src/Presenter/Transaction/index.php delete mode 100644 src/Translations/OrderStatesTranslations.php delete mode 100644 src/ValidateOrder.php diff --git a/config/admin/services.yml b/config/admin/services.yml index b90012678..21003a8d8 100644 --- a/config/admin/services.yml +++ b/config/admin/services.yml @@ -12,19 +12,3 @@ services: ps_checkout.logger.file.reader: class: 'PrestaShop\Module\PrestashopCheckout\Logger\LoggerFileReader' public: true - - ps_checkout.repository.orderpayment: - class: 'PrestaShop\Module\PrestashopCheckout\Repository\OrderPaymentRepository' - public: true - - ps_checkout.repository.order: - class: 'PrestaShop\Module\PrestashopCheckout\Repository\OrderRepository' - public: true - - ps_checkout.presenter.order.pending: - class: 'PrestaShop\Module\PrestashopCheckout\Presenter\Order\OrderPendingPresenter' - public: true - - ps_checkout.presenter.transaction: - class: 'PrestaShop\Module\PrestashopCheckout\Presenter\Transaction\TransactionPresenter' - public: true diff --git a/controllers/admin/AdminAjaxPrestashopCheckoutController.php b/controllers/admin/AdminAjaxPrestashopCheckoutController.php index e410da135..3f9916616 100755 --- a/controllers/admin/AdminAjaxPrestashopCheckoutController.php +++ b/controllers/admin/AdminAjaxPrestashopCheckoutController.php @@ -20,14 +20,25 @@ use Monolog\Logger; use PrestaShop\Module\PrestashopCheckout\Configuration\BatchConfigurationProcessor; +use PrestaShop\Module\PrestashopCheckout\ExpressCheckout\ExpressCheckoutConfiguration; +use PrestaShop\Module\PrestashopCheckout\FundingSource\FundingSourceConfigurationRepository; +use PrestaShop\Module\PrestashopCheckout\FundingSource\FundingSourceTranslationProvider; use PrestaShop\Module\PrestashopCheckout\Logger\LoggerDirectory; use PrestaShop\Module\PrestashopCheckout\Logger\LoggerFactory; use PrestaShop\Module\PrestashopCheckout\Logger\LoggerFileFinder; use PrestaShop\Module\PrestashopCheckout\Logger\LoggerFileReader; -use PrestaShop\Module\PrestashopCheckout\OrderStates; +use PrestaShop\Module\PrestashopCheckout\OnBoarding\Step\LiveStep; +use PrestaShop\Module\PrestashopCheckout\OnBoarding\Step\ValueBanner; +use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateConfigurationKeys; +use PrestaShop\Module\PrestashopCheckout\Order\State\Service\OrderStateMapper; +use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration; +use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalOrderProvider; +use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalPayLaterConfiguration; use PrestaShop\Module\PrestashopCheckout\Presenter\Order\OrderPresenter; +use PrestaShop\Module\PrestashopCheckout\Repository\PsAccountRepository; use PrestaShop\Module\PrestashopCheckout\Settings\RoundingSettings; use PrestaShop\Module\PrestashopCheckout\Validator\BatchConfigurationValidator; +use PrestaShop\Module\PrestashopCheckout\Webhook\WebhookSecretTokenService; use Psr\SimpleCache\CacheInterface; class AdminAjaxPrestashopCheckoutController extends ModuleAdminController @@ -72,7 +83,7 @@ public function postProcess() public function ajaxProcessUpdatePaymentMethodsOrder() { $paymentOptions = json_decode(Tools::getValue('paymentMethods'), true); - /** @var PrestaShop\Module\PrestashopCheckout\FundingSource\FundingSourceConfigurationRepository $fundingSourceConfigurationRepository */ + /** @var FundingSourceConfigurationRepository $fundingSourceConfigurationRepository */ $fundingSourceConfigurationRepository = $this->module->getService('ps_checkout.funding_source.configuration.repository'); foreach ($paymentOptions as $key => $paymentOption) { @@ -100,7 +111,7 @@ public function ajaxProcessUpdatePaymentMode() */ public function ajaxProcessLiveStepConfirmed() { - /** @var \PrestaShop\Module\PrestashopCheckout\OnBoarding\Step\LiveStep $stepLive */ + /** @var LiveStep $stepLive */ $stepLive = $this->module->getService('ps_checkout.step.live'); $stepLive->confirmed(true); @@ -112,7 +123,7 @@ public function ajaxProcessLiveStepConfirmed() */ public function ajaxProcessLiveStepViewed() { - /** @var \PrestaShop\Module\PrestashopCheckout\OnBoarding\Step\LiveStep $stepLive */ + /** @var LiveStep $stepLive */ $stepLive = $this->module->getService('ps_checkout.step.live'); $stepLive->viewed(true); @@ -124,7 +135,7 @@ public function ajaxProcessLiveStepViewed() */ public function ajaxProcessValueBannerClosed() { - /** @var \PrestaShop\Module\PrestashopCheckout\OnBoarding\Step\ValueBanner $valueBanner */ + /** @var ValueBanner $valueBanner */ $valueBanner = $this->module->getService('ps_checkout.step.value'); $valueBanner->closed(true); @@ -139,7 +150,7 @@ public function ajaxProcessValueBannerClosed() */ public function ajaxProcessEditRoundingSettings() { - /** @var PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration $paypalConfiguration */ + /** @var PayPalConfiguration $paypalConfiguration */ $paypalConfiguration = $this->module->getService('ps_checkout.paypal.configuration'); $paypalConfiguration->setRoundType(RoundingSettings::ROUND_ON_EACH_ITEM); $paypalConfiguration->setPriceRoundMode(RoundingSettings::ROUND_UP_AWAY_FROM_ZERO); @@ -148,25 +159,16 @@ public function ajaxProcessEditRoundingSettings() } /** - * AJAX: Retrieve Reporting informations + * @deprecated No more used */ public function ajaxProcessGetReportingDatas() { - try { - /** @var PrestaShop\Module\PrestashopCheckout\Presenter\Order\OrderPendingPresenter $pendingOrder */ - $pendingOrder = $this->module->getService('ps_checkout.presenter.order.pending'); - /** @var PrestaShop\Module\PrestashopCheckout\Presenter\Transaction\TransactionPresenter $transactionOrder */ - $transactionOrder = $this->module->getService('ps_checkout.presenter.transaction'); - $this->ajaxDie( - json_encode([ - 'orders' => $pendingOrder->present(), - 'transactions' => $transactionOrder->present(), - ]) - ); - } catch (Exception $exception) { - http_response_code(500); - $this->ajaxDie(json_encode(strip_tags($exception->getMessage()))); - } + $this->ajaxDie( + json_encode([ + 'orders' => [], + 'transactions' => [], + ]) + ); } /** @@ -176,7 +178,7 @@ public function ajaxProcessTogglePaymentOptionAvailability() { $paymentOption = json_decode(Tools::getValue('paymentOption'), true); - /** @var PrestaShop\Module\PrestashopCheckout\FundingSource\FundingSourceConfigurationRepository $fundingSourceConfigurationRepository */ + /** @var FundingSourceConfigurationRepository $fundingSourceConfigurationRepository */ $fundingSourceConfigurationRepository = $this->module->getService('ps_checkout.funding_source.configuration.repository'); $fundingSourceConfigurationRepository->save($paymentOption); @@ -189,7 +191,7 @@ public function ajaxProcessTogglePaymentOptionAvailability() */ public function ajaxProcessUpdateCreditCardFields() { - /** @var PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration $paypalConfiguration */ + /** @var PayPalConfiguration $paypalConfiguration */ $paypalConfiguration = $this->module->getService('ps_checkout.paypal.configuration'); $paypalConfiguration->setCardPaymentEnabled((bool) Tools::getValue('hostedFieldsEnabled')); @@ -202,7 +204,7 @@ public function ajaxProcessUpdateCreditCardFields() */ public function ajaxProcessToggleECOrderPage() { - /** @var \PrestaShop\Module\PrestashopCheckout\ExpressCheckout\ExpressCheckoutConfiguration $ecConfiguration */ + /** @var ExpressCheckoutConfiguration $ecConfiguration */ $ecConfiguration = $this->module->getService('ps_checkout.express_checkout.configuration'); $ecConfiguration->setOrderPage((bool) Tools::getValue('status')); @@ -216,7 +218,7 @@ public function ajaxProcessToggleECOrderPage() */ public function ajaxProcessToggleECCheckoutPage() { - /** @var \PrestaShop\Module\PrestashopCheckout\ExpressCheckout\ExpressCheckoutConfiguration $ecConfiguration */ + /** @var ExpressCheckoutConfiguration $ecConfiguration */ $ecConfiguration = $this->module->getService('ps_checkout.express_checkout.configuration'); $ecConfiguration->setCheckoutPage(Tools::getValue('status') ? true : false); @@ -230,7 +232,7 @@ public function ajaxProcessToggleECCheckoutPage() */ public function ajaxProcessToggleECProductPage() { - /** @var \PrestaShop\Module\PrestashopCheckout\ExpressCheckout\ExpressCheckoutConfiguration $ecConfiguration */ + /** @var ExpressCheckoutConfiguration $ecConfiguration */ $ecConfiguration = $this->module->getService('ps_checkout.express_checkout.configuration'); $ecConfiguration->setProductPage(Tools::getValue('status') ? true : false); @@ -374,7 +376,7 @@ public function ajaxProcessFetchOrder() } } - /** @var \PrestaShop\Module\PrestashopCheckout\PayPal\PayPalOrderProvider $paypalOrderProvider */ + /** @var PayPalOrderProvider $paypalOrderProvider */ $paypalOrderProvider = $this->module->getService('ps_checkout.paypal.provider.order'); $paypalOrder = $paypalOrderProvider->getById($psCheckoutCart->paypal_order); @@ -382,7 +384,7 @@ public function ajaxProcessFetchOrder() $paypalOrder = []; } - /** @var \PrestaShop\Module\PrestashopCheckout\FundingSource\FundingSourceTranslationProvider $fundingSourceTranslationProvider */ + /** @var FundingSourceTranslationProvider $fundingSourceTranslationProvider */ $fundingSourceTranslationProvider = $this->module->getService('ps_checkout.funding_source.translation'); $presenter = new OrderPresenter($this->module, $paypalOrder); @@ -456,7 +458,7 @@ public function ajaxProcessRefundOrder() ])); } - /** @var \PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration $configurationPayPal */ + /** @var PayPalConfiguration $configurationPayPal */ $configurationPayPal = $this->module->getService('ps_checkout.paypal.configuration'); $response = (new PrestaShop\Module\PrestashopCheckout\Api\Payment\Order($this->context->link))->refund([ @@ -726,7 +728,7 @@ public function ajaxProcessSavePaypalButtonConfiguration() */ public function ajaxProcessGetOrRefreshToken() { - /** @var \PrestaShop\Module\PrestashopCheckout\Repository\PsAccountRepository $psAccountRepository */ + /** @var PsAccountRepository $psAccountRepository */ $psAccountRepository = $this->module->getService('ps_checkout.repository.prestashop.account'); try { @@ -794,7 +796,7 @@ public function display() private function togglePayLaterConfiguration($method) { - /** @var \PrestaShop\Module\PrestashopCheckout\PayPal\PayPalPayLaterConfiguration $payLaterConfiguration */ + /** @var PayPalPayLaterConfiguration $payLaterConfiguration */ $payLaterConfiguration = $this->module->getService('ps_checkout.pay_later.configuration'); $payLaterConfiguration->$method(Tools::getValue('status') ? true : false); @@ -803,7 +805,7 @@ private function togglePayLaterConfiguration($method) public function ajaxProcessUpsertSecretToken() { - /** @var \PrestaShop\Module\PrestashopCheckout\Webhook\WebhookSecretTokenService $webhookSecretTokenService */ + /** @var WebhookSecretTokenService $webhookSecretTokenService */ $webhookSecretTokenService = $this->module->getService('ps_checkout.webhook.service.secret_token'); $secret = (string) Tools::getValue('body'); @@ -855,8 +857,6 @@ public function ajaxProcessCheckConfiguration() public function ajaxProcessFetchConfiguration() { - $response = []; - $query = new DbQuery(); $query->select('name, value, date_add, date_upd'); $query->from('configuration'); @@ -888,47 +888,45 @@ public function ajaxProcessFetchConfiguration() public function ajaxProcessGetMappedOrderStates() { - /** @var \PrestaShop\Module\PrestashopCheckout\Configuration\PrestaShopConfiguration $configuration */ - $configuration = $this->module->getService('ps_checkout.configuration'); + /** @var OrderStateMapper $orderStateMapper */ + $orderStateMapper = $this->module->getService('ps_checkout.order.state.service.order_state_mapper'); - $mappedOrderStates = [ - OrderStates::PS_CHECKOUT_STATE_PENDING => [ + $this->exitWithResponse([ + 'status' => true, + 'mappedOrderStates' => [ + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING => [ 'default' => '0', - 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_PENDING, ['default' => '0']), + 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING), ], - OrderStates::PS_CHECKOUT_STATE_COMPLETED => [ - 'default' => $configuration->get('PS_OS_PAYMENT'), - 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_COMPLETED, ['default' => '0']), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED => [ + 'default' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_OS_PAYMENT), + 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED), ], - OrderStates::PS_CHECKOUT_STATE_CANCELED => [ - 'default' => $configuration->get('PS_OS_CANCELED'), - 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_CANCELED, ['default' => '0']), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED => [ + 'default' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_OS_CANCELED), + 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED), ], - OrderStates::PS_CHECKOUT_STATE_ERROR => [ - 'default' => $configuration->get('PS_OS_ERROR'), - 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_ERROR, ['default' => '0']), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR => [ + 'default' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_OS_ERROR), + 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR), ], - OrderStates::PS_CHECKOUT_STATE_REFUNDED => [ - 'default' => $configuration->get('PS_OS_REFUND'), - 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_REFUNDED, ['default' => '0']), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED => [ + 'default' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_OS_REFUND), + 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED), ], - OrderStates::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED => [ + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED => [ 'default' => '0', - 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED, ['default' => '0']), + 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED), ], - OrderStates::PS_CHECKOUT_STATE_PARTIALLY_PAID => [ + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID => [ 'default' => '0', - 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_PARTIALLY_PAID, ['default' => '0']), + 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID), ], - OrderStates::PS_CHECKOUT_STATE_AUTHORIZED => [ + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_AUTHORIZED => [ 'default' => '0', - 'value' => $configuration->get(OrderStates::PS_CHECKOUT_STATE_AUTHORIZED, ['default' => '0']), + 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_AUTHORIZED), ], - ]; - - $this->exitWithResponse([ - 'status' => true, - 'mappedOrderStates' => $mappedOrderStates, + ], ]); } @@ -958,7 +956,7 @@ public function ajaxProcessBatchSaveConfiguration() public function ajaxProcessGetOrderStates() { - $orderStates = OrderState::getOrderStates(Context::getContext()->language->id); + $orderStates = OrderState::getOrderStates($this->context->language->id); $this->exitWithResponse([ 'status' => true, diff --git a/ps_checkout.php b/ps_checkout.php index 2f5a893bd..37abbe001 100755 --- a/ps_checkout.php +++ b/ps_checkout.php @@ -179,13 +179,14 @@ public function install() $result = parent::install() && $this->installConfiguration() && $this->installHooks() && - (new PrestaShop\Module\PrestashopCheckout\OrderStates())->installPaypalStates() && (new PrestaShop\Module\PrestashopCheckout\Database\TableManager())->createTable() && (new PrestaShop\Module\PrestashopCheckout\FundingSource\FundingSourceInstaller())->createFundingSources() && $this->installTabs() && $this->disableIncompatibleCountries() && $this->disableIncompatibleCurrencies(); + (new \PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateInstaller())->install(); + // Restore initial PrestaShop shop context if (Shop::CONTEXT_SHOP === $savedShopContext) { Shop::setContext($savedShopContext, $savedShopId); diff --git a/src/Order/CommandHandler/CreateOrderCommandHandler.php b/src/Order/CommandHandler/CreateOrderCommandHandler.php index ce8055023..efa930e00 100644 --- a/src/Order/CommandHandler/CreateOrderCommandHandler.php +++ b/src/Order/CommandHandler/CreateOrderCommandHandler.php @@ -146,16 +146,16 @@ public function handle(CreateOrderCommand $command) if ($paidAmount) { switch ($this->checkOrderAmount->checkAmount((string) $paidAmount, (string) $cart->getOrderTotal(true, \Cart::BOTH))) { case CheckOrderAmount::ORDER_NOT_FULL_PAID: - $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PARTIALLY_PAID); + $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID); break; case CheckOrderAmount::ORDER_FULL_PAID: - $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PAYMENT_ACCEPTED); + $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED); break; case CheckOrderAmount::ORDER_TO_MUCH_PAID: - $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PAYMENT_ACCEPTED); + $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED); } } else { - $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::WAITING_PAYMENT); + $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING); } /** @var FundingSourceTranslationProvider $fundingSourceTranslationProvider */ diff --git a/src/Order/QueryHandler/GetOrderForApprovalReversedQueryHandler.php b/src/Order/QueryHandler/GetOrderForApprovalReversedQueryHandler.php index 4c394c044..461fdd10c 100644 --- a/src/Order/QueryHandler/GetOrderForApprovalReversedQueryHandler.php +++ b/src/Order/QueryHandler/GetOrderForApprovalReversedQueryHandler.php @@ -80,7 +80,7 @@ public function handle(GetOrderForApprovalReversedQuery $query) throw new OrderNotFoundException('No PrestaShop Order associated to this PayPal Order at this time.'); } - $hasBeenCanceled = count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::CANCELED))); + $hasBeenCanceled = count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED))); return new GetOrderForApprovalReversedQueryResult( (int) $order->id, diff --git a/src/Order/QueryHandler/GetOrderForPaymentDeniedQueryHandler.php b/src/Order/QueryHandler/GetOrderForPaymentDeniedQueryHandler.php index ea66ca0d7..8e8046718 100644 --- a/src/Order/QueryHandler/GetOrderForPaymentDeniedQueryHandler.php +++ b/src/Order/QueryHandler/GetOrderForPaymentDeniedQueryHandler.php @@ -94,7 +94,7 @@ public function handle(GetOrderForPaymentDeniedQuery $query) */ private function hasBeenError(Order $order) { - return count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::PAYMENT_ERROR))) - || count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::CANCELED))); + return count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR))) + || count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED))); } } diff --git a/src/Order/QueryHandler/GetOrderForPaymentPendingQueryHandler.php b/src/Order/QueryHandler/GetOrderForPaymentPendingQueryHandler.php index b04b6f19a..5f87d43ef 100644 --- a/src/Order/QueryHandler/GetOrderForPaymentPendingQueryHandler.php +++ b/src/Order/QueryHandler/GetOrderForPaymentPendingQueryHandler.php @@ -95,9 +95,25 @@ public function handle(GetOrderForPaymentPendingQuery $query) */ private function isInPending(Order $order) { - return count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::WAITING_PAYMENT))) - || count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::WAITING_CREDIT_CARD_PAYMENT))) - || count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::WAITING_PAYPAL_PAYMENT))) - || count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::WAITING_LOCAL_PAYMENT))); + if (count($order->getHistory($order->id_lang, (int) Configuration::getGlobalValue(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING)))) { + return true; + } + + // Check deprecated states + $deprecatedStates = [ + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT, + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT, + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT, + ]; + + foreach ($deprecatedStates as $deprecatedState) { + $deprecatedStateId = (int) Configuration::getGlobalValue($deprecatedState); + + if ($deprecatedStateId && count($order->getHistory($order->id_lang, $deprecatedStateId))) { + return true; + } + } + + return false; } } diff --git a/src/Order/State/OrderStateConfigurationKeys.php b/src/Order/State/OrderStateConfigurationKeys.php index acaf1cdd4..9cf8d6868 100644 --- a/src/Order/State/OrderStateConfigurationKeys.php +++ b/src/Order/State/OrderStateConfigurationKeys.php @@ -22,20 +22,28 @@ class OrderStateConfigurationKeys { - const CANCELED = 'PS_OS_CANCELED'; - const PAYMENT_ERROR = 'PS_OS_ERROR'; - const OUT_OF_STOCK_UNPAID = 'PS_OS_OUTOFSTOCK_UNPAID'; - const OUT_OF_STOCK_PAID = 'PS_OS_OUTOFSTOCK_PAID'; - const PAYMENT_ACCEPTED = 'PS_OS_PAYMENT'; - const REFUNDED = 'PS_OS_REFUND'; + // PrestaShop native order statuses + const PS_OS_CANCELED = 'PS_OS_CANCELED'; + const PS_OS_ERROR = 'PS_OS_ERROR'; + const PS_OS_OUTOFSTOCK_UNPAID = 'PS_OS_OUTOFSTOCK_UNPAID'; + const PS_OS_OUTOFSTOCK_PAID = 'PS_OS_OUTOFSTOCK_PAID'; + const PS_OS_PAYMENT = 'PS_OS_PAYMENT'; + const PS_OS_REFUND = 'PS_OS_REFUND'; - const AUTHORIZED = 'PS_CHECKOUT_STATE_AUTHORIZED'; - //const PARTIALLY_PAID = 'PS_CHECKOUT_STATE_PARTIAL_PAYMENT'; @todo Create a Partial payment state - const PARTIALLY_PAID = 'PS_OS_PAYMENT'; - const PARTIALLY_REFUNDED = 'PS_CHECKOUT_STATE_PARTIAL_REFUND'; - const WAITING_CAPTURE = 'PS_CHECKOUT_STATE_WAITING_CAPTURE'; - const WAITING_CREDIT_CARD_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT'; - const WAITING_LOCAL_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT'; - const WAITING_PAYPAL_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT'; - const WAITING_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_PAYMENT'; + // PrestaShop Checkout order statuses + const PS_CHECKOUT_STATE_PENDING = 'PS_CHECKOUT_STATE_PENDING'; + const PS_CHECKOUT_STATE_COMPLETED = 'PS_CHECKOUT_STATE_COMPLETED'; + const PS_CHECKOUT_STATE_CANCELED = 'PS_CHECKOUT_STATE_CANCELED'; + const PS_CHECKOUT_STATE_ERROR = 'PS_CHECKOUT_STATE_ERROR'; + const PS_CHECKOUT_STATE_REFUNDED = 'PS_CHECKOUT_STATE_REFUNDED'; + const PS_CHECKOUT_STATE_PARTIALLY_REFUNDED = 'PS_CHECKOUT_STATE_PARTIALLY_REFUNDED'; + const PS_CHECKOUT_STATE_PARTIALLY_PAID = 'PS_CHECKOUT_STATE_PARTIALLY_PAID'; + const PS_CHECKOUT_STATE_AUTHORIZED = 'PS_CHECKOUT_STATE_AUTHORIZED'; + + // PrestaShop Checkout deprecated order statuses + const PS_CHECKOUT_STATE_PARTIAL_REFUND = 'PS_CHECKOUT_STATE_PARTIAL_REFUND'; + const PS_CHECKOUT_STATE_WAITING_CAPTURE = 'PS_CHECKOUT_STATE_WAITING_CAPTURE'; + const PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT'; + const PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT'; + const PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT = 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT'; } diff --git a/src/Order/State/OrderStateInstaller.php b/src/Order/State/OrderStateInstaller.php new file mode 100644 index 000000000..d3ad86868 --- /dev/null +++ b/src/Order/State/OrderStateInstaller.php @@ -0,0 +1,212 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 + */ + +namespace PrestaShop\Module\PrestashopCheckout\Order\State; + +use Configuration; +use Language; +use OrderState; +use Tools; +use Validate; + +class OrderStateInstaller +{ + /** + * @var array + */ + private $languages; + + public function __construct() + { + $this->languages = Language::getLanguages(false); + } + + public function install() + { + Configuration::updateGlobalValue(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED, Configuration::getGlobalValue(OrderStateConfigurationKeys::PS_OS_PAYMENT)); + Configuration::updateGlobalValue(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED, Configuration::getGlobalValue(OrderStateConfigurationKeys::PS_OS_CANCELED)); + Configuration::updateGlobalValue(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR, Configuration::getGlobalValue(OrderStateConfigurationKeys::PS_OS_ERROR)); + Configuration::updateGlobalValue(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED, Configuration::getGlobalValue(OrderStateConfigurationKeys::PS_OS_REFUND)); + + if (!$this->checkAlreadyInstalled(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING)) { + $this->createOrderState( + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING, + '#34209E', + [ + 'en' => 'Waiting for payment', + 'fr' => 'En attente de paiement', + 'es' => 'Esperando el pago', + 'it' => 'In attesa di pagamento', + 'nl' => 'Wachten op betaling', + 'de' => 'Warten auf Zahlung', + 'pl' => 'Oczekiwanie na płatność', + 'pt' => 'Aguardando pagamento', + ] + ); + } + + if (!$this->checkAlreadyInstalled(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED)) { + $this->createOrderState( + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED, + '#01B887', + [ + 'en' => 'Partial refund', + 'fr' => 'Remboursement partiel', + 'es' => 'Reembolso parcial', + 'it' => 'Rimborso parziale', + 'nl' => 'Gedeeltelijke terugbetaling', + 'de' => 'Teilweise Rückerstattung', + 'pl' => 'Częściowy zwrot', + 'pt' => 'Reembolso parcial', + ] + ); + } + + if (!$this->checkAlreadyInstalled(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID)) { + $this->createOrderState( + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID, + '#3498D8', + [ + 'en' => 'Partial payment', + 'fr' => 'Paiement partiel', + 'es' => 'Pago parcial', + 'it' => 'Pagamento parziale', + 'nl' => 'Gedeeltelijke betaling', + 'de' => 'Teilweise Zahlung', + 'pl' => 'Częściowa płatność', + 'pt' => 'Pagamento parcial', + ] + ); + } + + if (!$this->checkAlreadyInstalled(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_AUTHORIZED)) { + $this->createOrderState( + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_AUTHORIZED, + '#3498D8', + [ + 'en' => 'Authorized. To be captured by merchant', + 'fr' => 'Autorisation. A capturer par le marchand', + 'es' => 'Autorizado. El vendedor lo capturará', + 'it' => 'Autorizzato. Sarà acquisito dal commerciante', + 'nl' => 'Goedgekeurd. Door retailer te registreren.', + 'de' => 'Autorisiert. Wird von Händler erfasst.', + 'pl' => 'Pomyślna autoryzacja. Transfer do przeprowadzenia przez sklep', + 'pt' => 'Autorizado. A ser capturado pelo comerciante', + ] + ); + } + } + + /** + * @param string $configuration_key + * @param string $color + * @param array $nameByLangIsoCode + */ + private function createOrderState($configuration_key, $color, array $nameByLangIsoCode) + { + $orderState = new OrderState(); + $orderState->name = $this->fillOrderStateName($nameByLangIsoCode); + $orderState->module_name = 'ps_checkout'; + $orderState->unremovable = true; + $orderState->color = $color; + $orderState->delivery = false; + $orderState->shipped = false; + $orderState->pdf_delivery = false; + $orderState->pdf_invoice = false; + $orderState->hidden = false; + $orderState->invoice = false; + $orderState->send_email = false; + $orderState->paid = false; + $orderState->logable = false; + $orderState->deleted = false; + $orderState->template = []; + $orderState->save(); + + Configuration::updateGlobalValue($configuration_key, $orderState->id); + $this->setStateIcons($configuration_key, $orderState->id); + } + + /** + * @param array $nameByLangIsoCode + * + * @return array + */ + private function fillOrderStateName(array $nameByLangIsoCode) + { + $orderStateNameByLangId = []; + + foreach ($nameByLangIsoCode as $langIsoCode => $name) { + foreach ($this->languages as $language) { + if (Tools::strtolower($language['iso_code']) === $langIsoCode) { + $orderStateNameByLangId[(int) $language['id_lang']] = $name; + } elseif (isset($nameByLangIsoCode['en'])) { + $orderStateNameByLangId[(int) $language['id_lang']] = $nameByLangIsoCode['en']; + } + } + } + + return $orderStateNameByLangId; + } + + /** + * @param string $orderStateKey + * + * @return bool + */ + private function checkAlreadyInstalled($orderStateKey) + { + $orderStateId = (int) Configuration::getGlobalValue($orderStateKey); + + if (!$orderStateId) { + return false; + } + + $orderState = new OrderState($orderStateId); + + if (!Validate::isLoadedObject($orderState)) { + return false; + } + + if ($orderState->module_name !== 'ps_checkout' || $orderState->deleted) { + return false; + } + + return true; + } + + /** + * @param string $orderStateKey + * @param int $orderStateId + */ + private function setStateIcons($orderStateKey, $orderStateId) + { + $orderStateImage = $orderStateKey === OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED ? 'refund.gif' : 'waiting.gif'; + $moduleOrderStateImgPath = _PS_MODULE_DIR_ . 'ps_checkout/views/img/OrderStatesIcons/' . $orderStateImage; + $coreOrderStateImgPath = _PS_IMG_DIR_ . 'os/' . $orderStateId . '.gif'; + + if ( + Tools::file_exists_cache($moduleOrderStateImgPath) + && !Tools::file_exists_cache($coreOrderStateImgPath) + && is_writable(_PS_IMG_DIR_ . 'os/') + ) { + Tools::copy($moduleOrderStateImgPath, $coreOrderStateImgPath); + } + } +} diff --git a/src/Order/State/Service/OrderStateMapper.php b/src/Order/State/Service/OrderStateMapper.php index f11782f68..9d773e9e1 100644 --- a/src/Order/State/Service/OrderStateMapper.php +++ b/src/Order/State/Service/OrderStateMapper.php @@ -20,6 +20,7 @@ namespace PrestaShop\Module\PrestashopCheckout\Order\State\Service; +use InvalidArgumentException; use PrestaShop\Module\PrestashopCheckout\Configuration\PrestaShopConfiguration; use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateConfigurationKeys; @@ -41,22 +42,7 @@ class OrderStateMapper public function __construct(PrestaShopConfiguration $configuration) { $this->configuration = $configuration; - $this->orderStateMapping = [ - OrderStateConfigurationKeys::CANCELED => (int) $this->configuration->get(OrderStateConfigurationKeys::CANCELED, ['global' => true]), - OrderStateConfigurationKeys::PAYMENT_ERROR => (int) $this->configuration->get(OrderStateConfigurationKeys::PAYMENT_ERROR, ['global' => true]), - OrderStateConfigurationKeys::OUT_OF_STOCK_UNPAID => (int) $this->configuration->get(OrderStateConfigurationKeys::OUT_OF_STOCK_UNPAID, ['global' => true]), - OrderStateConfigurationKeys::OUT_OF_STOCK_PAID => (int) $this->configuration->get(OrderStateConfigurationKeys::OUT_OF_STOCK_PAID, ['global' => true]), - OrderStateConfigurationKeys::PAYMENT_ACCEPTED => (int) $this->configuration->get(OrderStateConfigurationKeys::PAYMENT_ACCEPTED, ['global' => true]), /* @phpstan-ignore-line */ - OrderStateConfigurationKeys::REFUNDED => (int) $this->configuration->get(OrderStateConfigurationKeys::REFUNDED, ['global' => true]), - OrderStateConfigurationKeys::AUTHORIZED => (int) $this->configuration->get(OrderStateConfigurationKeys::AUTHORIZED, ['global' => true]), - OrderStateConfigurationKeys::PARTIALLY_PAID => (int) $this->configuration->get(OrderStateConfigurationKeys::PARTIALLY_PAID, ['global' => true]), /* @phpstan-ignore-line */ - OrderStateConfigurationKeys::PARTIALLY_REFUNDED => (int) $this->configuration->get(OrderStateConfigurationKeys::PARTIALLY_REFUNDED, ['global' => true]), - OrderStateConfigurationKeys::WAITING_CAPTURE => (int) $this->configuration->get(OrderStateConfigurationKeys::WAITING_CAPTURE, ['global' => true]), - OrderStateConfigurationKeys::WAITING_CREDIT_CARD_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::WAITING_CREDIT_CARD_PAYMENT, ['global' => true]), - OrderStateConfigurationKeys::WAITING_PAYPAL_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::WAITING_PAYPAL_PAYMENT, ['global' => true]), - OrderStateConfigurationKeys::WAITING_LOCAL_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::WAITING_LOCAL_PAYMENT, ['global' => true]), - OrderStateConfigurationKeys::WAITING_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::WAITING_PAYMENT, ['global' => true]), - ]; + $this->initialize(); } /** @@ -70,7 +56,7 @@ public function getIdByKey($key) return $this->orderStateMapping[$key]; } - throw new \InvalidArgumentException(sprintf('Order state key "%s" is not mapped', var_export($key, true))); + throw new InvalidArgumentException(sprintf('Order state key "%s" is not mapped', var_export($key, true))); } /** @@ -94,6 +80,34 @@ public function getKeyById($orderCurrentState) return $orderStateMapping[$orderCurrentState]; } - throw new \InvalidArgumentException(sprintf('Order state id "%s" is not mapped', var_export($orderCurrentState, true))); + throw new InvalidArgumentException(sprintf('Order state id "%s" is not mapped', var_export($orderCurrentState, true))); + } + + private function initialize() + { + $this->orderStateMapping = [ + // PrestaShop native order statuses + OrderStateConfigurationKeys::PS_OS_CANCELED => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_OS_CANCELED, ['global' => true]), + OrderStateConfigurationKeys::PS_OS_ERROR => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_OS_ERROR, ['global' => true]), + OrderStateConfigurationKeys::PS_OS_OUTOFSTOCK_UNPAID => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_OS_OUTOFSTOCK_UNPAID, ['global' => true]), + OrderStateConfigurationKeys::PS_OS_OUTOFSTOCK_PAID => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_OS_OUTOFSTOCK_PAID, ['global' => true]), + OrderStateConfigurationKeys::PS_OS_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_OS_PAYMENT, ['global' => true]), + OrderStateConfigurationKeys::PS_OS_REFUND => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_OS_REFUND, ['global' => true]), + // PrestaShop Checkout order statuses + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_AUTHORIZED => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_AUTHORIZED, ['global' => true]), + // PrestaShop Checkout deprecated order statuses + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIAL_REFUND => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIAL_REFUND, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_CAPTURE => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_CAPTURE, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT, ['global' => true]), + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT => (int) $this->configuration->get(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT, ['global' => true]), + ]; } } diff --git a/src/OrderStates.php b/src/OrderStates.php deleted file mode 100644 index 0b2e796d1..000000000 --- a/src/OrderStates.php +++ /dev/null @@ -1,267 +0,0 @@ - - * @copyright Since 2007 PrestaShop SA and Contributors - * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 - */ - -namespace PrestaShop\Module\PrestashopCheckout; - -use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException; -use PrestaShop\Module\PrestashopCheckout\Translations\OrderStatesTranslations; - -class OrderStates -{ - const MODULE_NAME = 'ps_checkout'; - const ORDER_STATE_TEMPLATE = 'payment'; - const ORDER_TABLE = 'orders'; - const ORDER_HISTORY_TABLE = 'order_history'; - const ORDER_STATE_TABLE = 'order_state'; - const ORDER_STATE_LANG_TABLE = 'order_state_lang'; - const DARK_BLUE_HEXA_COLOR = '#34209E'; - const BLUE_HEXA_COLOR = '#3498D8'; - const GREEN_HEXA_COLOR = '#01B887'; - - const PS_CHECKOUT_STATE_PENDING = 'PS_CHECKOUT_STATE_PENDING'; - const PS_CHECKOUT_STATE_COMPLETED = 'PS_CHECKOUT_STATE_COMPLETED'; - const PS_CHECKOUT_STATE_CANCELED = 'PS_CHECKOUT_STATE_CANCELED'; - const PS_CHECKOUT_STATE_ERROR = 'PS_CHECKOUT_STATE_ERROR'; - const PS_CHECKOUT_STATE_PARTIALLY_REFUNDED = 'PS_CHECKOUT_STATE_PARTIALLY_REFUNDED'; - const PS_CHECKOUT_STATE_REFUNDED = 'PS_CHECKOUT_STATE_REFUNDED'; - const PS_CHECKOUT_STATE_PARTIALLY_PAID = 'PS_CHECKOUT_STATE_PARTIALLY_PAID'; - const PS_CHECKOUT_STATE_AUTHORIZED = 'PS_CHECKOUT_STATE_AUTHORIZED'; - const ORDER_STATES = [ - 'PS_CHECKOUT_STATE_WAITING_PAYMENT' => self::DARK_BLUE_HEXA_COLOR, - 'PS_CHECKOUT_STATE_AUTHORIZED' => self::BLUE_HEXA_COLOR, - 'PS_CHECKOUT_STATE_PARTIAL_REFUND' => self::GREEN_HEXA_COLOR, - 'PS_CHECKOUT_STATE_WAITING_CAPTURE' => self::BLUE_HEXA_COLOR, - ]; - - const REFUND_STATE = 'PS_CHECKOUT_STATE_PARTIAL_REFUND'; - - /** - * Insert the new paypal states if it does not exists - * Create a new order state for each ps_checkout new order states - * - * FYI: this method is also used in the upgrade-1.2.14.php file - * - * @return bool - * - * @throws PsCheckoutException - * @throws \PrestaShopDatabaseException - */ - public function installPaypalStates() - { - foreach (self::ORDER_STATES as $state => $color) { - $orderStateId = $this->getPaypalStateId($state, $color); - $this->createPaypalStateLangs($state, $orderStateId); - $this->setStateIcons($state, $orderStateId); - } - - return true; - } - - /** - * Get the paypal state id if it already exist. - * Get the paypal state id if it doesn't exist by creating it - * - * @param string $state - * @param string $color - * - * @return int - * - * @throws PsCheckoutException - * @throws \PrestaShopDatabaseException - */ - private function getPaypalStateId($state, $color) - { - $stateId = (int) \Configuration::getGlobalValue($state); - - // Is state ID already existing in the Configuration table ? - if (0 === $stateId || false === $this->stateAlreadyExists($stateId)) { - return $this->createPaypalStateId($state, $color); - } - - return (int) $stateId; - } - - /** - * Create the Paypal State id - * - * @param string $state - * @param string $color - * - * @return int orderStateId - * - * @throws PsCheckoutException - * @throws \PrestaShopDatabaseException - */ - private function createPaypalStateId($state, $color) - { - $data = [ - 'module_name' => self::MODULE_NAME, - 'color' => $color, - 'unremovable' => 1, - ]; - - if (true === \Db::getInstance()->insert(self::ORDER_STATE_TABLE, $data)) { - $insertedId = (int) \Db::getInstance()->Insert_ID(); - \Configuration::updateGlobalValue($state, $insertedId); - - return $insertedId; - } - - throw new PsCheckoutException('Not able to insert the new order state', PsCheckoutException::PRESTASHOP_ORDER_STATE_ERROR); - } - - /** - * Create the Paypal States Lang - * - * @param string $state - * @param int $orderStateId - * - * @throws PsCheckoutException - * @throws \PrestaShopDatabaseException - */ - private function createPaypalStateLangs($state, $orderStateId) - { - $languagesList = \Language::getLanguages(); - $orderStatesTranslations = new OrderStatesTranslations(); - - // For each languages in the shop, we insert a new order state name - foreach ($languagesList as $key => $lang) { - if (true === $this->stateLangAlreadyExists($orderStateId, (int) $lang['id_lang'])) { - continue; - } - - $statesTranslations = $orderStatesTranslations->getTranslations($lang['iso_code']); - $this->insertNewStateLang($orderStateId, $statesTranslations[$state], (int) $lang['id_lang']); - } - } - - /** - * Check if Paypal State language already exists in the table ORDEr_STATE_LANG_TABLE - * - * @param int $orderStateId - * @param int $langId - * - * @return bool - */ - private function stateLangAlreadyExists($orderStateId, $langId) - { - return (bool) \Db::getInstance()->getValue( - 'SELECT id_order_state - FROM `' . _DB_PREFIX_ . self::ORDER_STATE_LANG_TABLE . '` - WHERE - id_order_state = ' . (int) $orderStateId . ' - AND id_lang = ' . (int) $langId - ); - } - - /** - * Create the Paypal States Lang - * - * @param int $orderStateId - * @param string $translations - * @param int $langId - * - * @throws PsCheckoutException - * @throws \PrestaShopDatabaseException - */ - private function insertNewStateLang($orderStateId, $translations, $langId) - { - $data = [ - 'id_order_state' => $orderStateId, - 'id_lang' => (int) $langId, - 'name' => pSQL($translations), - 'template' => self::ORDER_STATE_TEMPLATE, - ]; - - if (false === \Db::getInstance()->insert(self::ORDER_STATE_LANG_TABLE, $data)) { - throw new PsCheckoutException('Not able to insert the new order state language', PsCheckoutException::PRESTASHOP_ORDER_STATE_ERROR); - } - } - - /** - * Set an icon for the current State Id - * - * @param string $state - * @param int $orderStateId - * - * @return bool - */ - private function setStateIcons($state, $orderStateId) - { - /** @var \Ps_checkout $module */ - $module = \Module::getInstanceByName('ps_checkout'); - $iconExtension = '.gif'; - $iconToPaste = _PS_ORDER_STATE_IMG_DIR_ . $orderStateId . $iconExtension; - - if (true === file_exists($iconToPaste)) { - if (true !== is_writable($iconToPaste)) { - $module->getLogger()->error( - '[PSPInstall] file is not writable', - [ - 'file' => $iconToPaste, - ] - ); - - return false; - } - } - - if ($state === static::REFUND_STATE) { - $iconName = 'refund'; - } else { - $iconName = 'waiting'; - } - - $iconsFolderOrigin = _PS_MODULE_DIR_ . self::MODULE_NAME . '/views/img/OrderStatesIcons/'; - $iconToCopy = $iconsFolderOrigin . $iconName . $iconExtension; - - if (false === copy($iconToCopy, $iconToPaste)) { - $module->getLogger()->error( - '[PSPInstall] not able to copy icon', - [ - 'icon' => $iconName, - 'id_order_state' => $orderStateId, - ] - ); - - return false; - } - - return true; - } - - /** - * Check if OrderState already exists in the table - * - * @param int $orderStateId - * - * @return bool - */ - private function stateAlreadyExists($orderStateId) - { - $query = new \DbQuery(); - $query->select('id_order_state'); - $query->from(self::ORDER_STATE_TABLE); - $query->where('id_order_state = ' . (int) $orderStateId); - $query->where('module_name = "' . self::MODULE_NAME . '"'); - - return (bool) \Db::getInstance()->getValue($query); - } -} diff --git a/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php b/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php index e7c4693c0..a70254804 100644 --- a/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php +++ b/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php @@ -167,10 +167,10 @@ public function setPaymentCompletedOrderStatus(PayPalCaptureCompletedEvent $even switch ($this->checkOrderAmount->checkAmount((string) $order->getTotalAmount(), (string) $event->getCapture()['amount']['value'])) { case CheckOrderAmount::ORDER_FULL_PAID: case CheckOrderAmount::ORDER_TO_MUCH_PAID: - $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PAYMENT_ACCEPTED))); + $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED))); break; case CheckOrderAmount::ORDER_NOT_FULL_PAID: - $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PARTIALLY_PAID))); + $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID))); break; } } @@ -184,7 +184,7 @@ public function setPaymentPendingOrderStatus(PayPalCapturePendingEvent $event) return; } - $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::WAITING_PAYMENT))); + $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING))); } public function setPaymentDeclinedOrderStatus(PayPalCaptureDeclinedEvent $event) @@ -196,7 +196,7 @@ public function setPaymentDeclinedOrderStatus(PayPalCaptureDeclinedEvent $event) return; } - $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PAYMENT_ERROR))); + $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR))); } public function setPaymentRefundedOrderStatus(PayPalCaptureRefundedEvent $event) @@ -209,9 +209,9 @@ public function setPaymentRefundedOrderStatus(PayPalCaptureRefundedEvent $event) } if ($this->checkOrderAmount->checkAmount($order->getTotalAmount(), $order->getTotalRefund()) == CheckOrderAmount::ORDER_NOT_FULL_PAID) { - $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PARTIALLY_REFUNDED))); + $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED))); } else { - $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::REFUNDED))); + $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED))); } } @@ -224,7 +224,7 @@ public function setPaymentReversedOrderStatus(PayPalCaptureReversedEvent $event) return; } - $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::REFUNDED))); + $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED))); } public function updateCache(PayPalCaptureEvent $event) diff --git a/src/Presenter/Order/OrderPendingPresenter.php b/src/Presenter/Order/OrderPendingPresenter.php deleted file mode 100644 index 0089891c7..000000000 --- a/src/Presenter/Order/OrderPendingPresenter.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @copyright Since 2007 PrestaShop SA and Contributors - * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 - */ - -namespace PrestaShop\Module\PrestashopCheckout\Presenter\Order; - -use PrestaShop\Module\PrestashopCheckout\Adapter\LinkAdapter; -use PrestaShop\Module\PrestashopCheckout\OrderStates; -use PrestaShop\Module\PrestashopCheckout\Presenter\PresenterInterface; -use PrestaShop\Module\PrestashopCheckout\Repository\OrderRepository; -use PrestaShop\Module\PrestashopCheckout\Translations\OrderStatesTranslations; - -/** - * Present the pending orders for the reporting - */ -class OrderPendingPresenter implements PresenterInterface -{ - /** - * present pending orders - * - * @return array - * - * @throws \PrestaShopDatabaseException - */ - public function present() - { - $link = new LinkAdapter(); - $context = \Context::getContext(); - - $orderStates = []; - $orderTranslations = new OrderStatesTranslations(); - $orderTranslations = $orderTranslations->getTranslations($context->language->iso_code); - foreach (OrderStates::ORDER_STATES as $key => $value) { - if ($key == 'PS_CHECKOUT_STATE_WAITING_PAYMENT' || - $key == 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT' || - $key == 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT' || - $key == 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT' || - $key == 'PS_CHECKOUT_STATE_WAITING_CAPTURE' - ) { - $idState = (int) \Configuration::getGlobalValue($key); - $orderStates[$idState]['color'] = $value; - $orderStates[$idState]['name'] = $orderTranslations[$key]; - } - } - - $idStates = array_map('intval', $orderStates); - - /** @var \Ps_checkout $module */ - $module = \Module::getInstanceByName('ps_checkout'); - /** @var OrderRepository $repository */ - $repository = $module->getService('ps_checkout.repository.order'); - $orders = $repository->findByStates(\Context::getContext()->shop->id, $idStates); - - foreach ($orders as &$order) { - $order['username'] = substr($order['firstname'], 0, 1) . '. ' . $order['lastname']; - $order['userProfileLink'] = $link->getAdminLink('AdminCustomers', true, [], ['id_customer' => $order['id_customer'], 'viewcustomer' => 1]); - $order['orderLink'] = $link->getAdminLink('AdminOrders', true, [], ['id_order' => $order['id_order'], 'vieworder' => 1]); - $order['state'] = $orderStates[$order['current_state']]; - $order['before_commission'] = \Tools::displayPrice($order['total_paid'], \Currency::getCurrencyInstance($order['id_currency'])); - // TODO: Waiting for paypal infos (reporting lot 2) - $order['commission'] = '-'; - $order['total_paid'] = '-'; - } - - return $orders; - } -} diff --git a/src/Presenter/Transaction/TransactionPresenter.php b/src/Presenter/Transaction/TransactionPresenter.php deleted file mode 100644 index 318423c08..000000000 --- a/src/Presenter/Transaction/TransactionPresenter.php +++ /dev/null @@ -1,63 +0,0 @@ - - * @copyright Since 2007 PrestaShop SA and Contributors - * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 - */ - -namespace PrestaShop\Module\PrestashopCheckout\Presenter\Transaction; - -use PrestaShop\Module\PrestashopCheckout\Adapter\LinkAdapter; -use PrestaShop\Module\PrestashopCheckout\Presenter\PresenterInterface; -use PrestaShop\Module\PrestashopCheckout\Repository\OrderPaymentRepository; - -/** - * Present the pending orders for the reporting - */ -class TransactionPresenter implements PresenterInterface -{ - /** - * present pending orders - * - * @return array - * - * @throws \PrestaShopDatabaseException - */ - public function present() - { - $link = new LinkAdapter(); - /** @var \Ps_checkout $module */ - $module = \Module::getInstanceByName('ps_checkout'); - /** @var OrderPaymentRepository $repository */ - $repository = $module->getService('ps_checkout.repository.orderpayment'); - $transactions = $repository->findAllPSCheckoutModule((int) \Context::getContext()->shop->id); - - foreach ($transactions as &$transaction) { - $transaction['transactionID'] = $transaction['transaction_id']; - $transaction['order_id'] = $transaction['id_order']; - $transaction['orderLink'] = $link->getAdminLink('AdminOrders', true, [], ['id_order' => $transaction['id_order'], 'vieworder' => 1]); - $transaction['username'] = substr($transaction['firstname'], 0, 1) . '. ' . $transaction['lastname']; - $transaction['userProfileLink'] = $link->getAdminLink('AdminCustomers', true, [], ['id_customer' => $transaction['id_customer'], 'viewcustomer' => 1]); - $transaction['before_commission'] = \Tools::displayPrice($transaction['amount'], \Currency::getCurrencyInstance((int) $transaction['id_currency'])); - $transaction['type'] = strpos($transaction['amount'], '-') !== false ? 'Refund' : 'Payment'; - $transaction['typeForDisplay'] = ($transaction['type'] === 'Refund') ? $module->l('Refund', 'transactionpresenter') : $module->l('Payment', 'transactionpresenter'); - $transaction['commission'] = '-'; - $transaction['total_paid'] = '-'; - } - - return $transactions; - } -} diff --git a/src/Presenter/Transaction/index.php b/src/Presenter/Transaction/index.php deleted file mode 100755 index 296d682e8..000000000 --- a/src/Presenter/Transaction/index.php +++ /dev/null @@ -1,28 +0,0 @@ - - * @copyright Since 2007 PrestaShop SA and Contributors - * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 - */ -header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); -header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); - -header('Cache-Control: no-store, no-cache, must-revalidate'); -header('Cache-Control: post-check=0, pre-check=0', false); -header('Pragma: no-cache'); - -header('Location: ../'); -exit; diff --git a/src/Translations/OrderStatesTranslations.php b/src/Translations/OrderStatesTranslations.php deleted file mode 100644 index a60265521..000000000 --- a/src/Translations/OrderStatesTranslations.php +++ /dev/null @@ -1,102 +0,0 @@ - - * @copyright Since 2007 PrestaShop SA and Contributors - * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 - */ - -namespace PrestaShop\Module\PrestashopCheckout\Translations; - -class OrderStatesTranslations -{ - const STANDARD_ISO_CODE = 'en'; - const PS_CHECKOUT_STATE_WAITING_PAYMENT = [ - 'en' => 'Waiting for payment', - 'fr' => 'En attente de paiement', - 'es' => 'Esperando el pago', - 'it' => 'In attesa di pagamento', - 'nl' => 'Wachten op betaling', - 'de' => 'Warten auf Zahlung', - 'pl' => 'Oczekiwanie na płatność', - 'pt' => 'Aguardando pagamento', - ]; - const PS_CHECKOUT_STATE_AUTHORIZED = [ - 'en' => 'Authorized. To be captured by merchant', - 'fr' => 'Autorisation. A capturer par le marchand', - 'es' => 'Autorizado. El vendedor lo capturará', - 'it' => 'Autorizzato. Sarà acquisito dal commerciante', - 'nl' => 'Goedgekeurd. Door retailer te registreren.', - 'de' => 'Autorisiert. Wird von Händler erfasst.', - 'pl' => 'Pomyślna autoryzacja. Transfer do przeprowadzenia przez sklep', - 'pt' => 'Autorizado. A ser capturado pelo comerciante', - ]; - const PS_CHECKOUT_STATE_PARTIAL_REFUND = [ - 'en' => 'Partial refund', - 'fr' => 'Remboursement partiel', - 'es' => 'Reembolso parcial', - 'it' => 'Rimborso parziale', - 'nl' => 'Gedeeltelijke terugbetaling', - 'de' => 'Teilweise Rückerstattung', - 'pl' => 'Częściowy zwrot', - 'pt' => 'Reembolso parcial', - ]; - const PS_CHECKOUT_STATE_WAITING_CAPTURE = [ - 'en' => 'Waiting capture', - 'fr' => 'En attente de capture', - 'es' => 'Esperando la captura', - 'it' => 'In attesa di essere acquisito', - 'nl' => 'Wachten op registratie', - 'de' => 'Warten auf Erfassung', - 'pl' => 'Oczekiwanie na transfer', - 'pt' => 'Aguardando a captura', - ]; - - /** - * Get the States Translations for the table order_state_lang - * - * @return array translation list - */ - public function getTranslations($isoCode) - { - $isoCode = $this->confirmIsoCode($isoCode); - - return [ - 'PS_CHECKOUT_STATE_WAITING_PAYMENT' => self::PS_CHECKOUT_STATE_WAITING_PAYMENT[$isoCode], - 'PS_CHECKOUT_STATE_AUTHORIZED' => self::PS_CHECKOUT_STATE_AUTHORIZED[$isoCode], - 'PS_CHECKOUT_STATE_PARTIAL_REFUND' => self::PS_CHECKOUT_STATE_PARTIAL_REFUND[$isoCode], - 'PS_CHECKOUT_STATE_WAITING_CAPTURE' => self::PS_CHECKOUT_STATE_WAITING_CAPTURE[$isoCode], - ]; - } - - /** - * Return an ISO which can get a result in the translations arrays - * - * @param string $isoCode - * - * @return string - */ - private function confirmIsoCode($isoCode) - { - if (!array_key_exists($isoCode, self::PS_CHECKOUT_STATE_WAITING_PAYMENT) || - !array_key_exists($isoCode, self::PS_CHECKOUT_STATE_AUTHORIZED) || - !array_key_exists($isoCode, self::PS_CHECKOUT_STATE_PARTIAL_REFUND) || - !array_key_exists($isoCode, self::PS_CHECKOUT_STATE_WAITING_CAPTURE)) { - return self::STANDARD_ISO_CODE; - } - - return (string) $isoCode; - } -} diff --git a/src/ValidateOrder.php b/src/ValidateOrder.php deleted file mode 100644 index beaf555c5..000000000 --- a/src/ValidateOrder.php +++ /dev/null @@ -1,345 +0,0 @@ - - * @copyright Since 2007 PrestaShop SA and Contributors - * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 - */ - -namespace PrestaShop\Module\PrestashopCheckout; - -use PrestaShop\Module\PrestashopCheckout\Api\Payment\Order; -use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException; -use PrestaShop\Module\PrestashopCheckout\Order\Exception\OrderNotFoundException; -use PrestaShop\Module\PrestashopCheckout\PayPal\Card3DSecure; -use Psr\SimpleCache\CacheInterface; - -/** - * @deprecated This file will be removed - * - * Class that allow to validate an order - */ -class ValidateOrder -{ - const INTENT_CAPTURE = 'CAPTURE'; - const INTENT_AUTHORIZE = 'AUTHORIZE'; - - const CAPTURE_STATUS_PENDING = 'PENDING'; - const CAPTURE_STATUS_DENIED = 'DENIED'; - const CAPTURE_STATUS_VOIDED = 'VOIDED'; - const CAPTURE_STATUS_COMPLETED = 'COMPLETED'; - const CAPTURE_STATUS_DECLINED = 'DECLINED'; - - const PAYMENT_METHOD_PAYPAL = 'paypal'; - const PAYMENT_METHOD_CARD = 'card'; - - /** - * @var string - */ - private $paypalOrderId; - - /** - * @var string - */ - private $merchantId; - - /** - * @var \Context - */ - private $context; - - /** - * @param string $paypalOrderId - * @param string $merchantId - */ - public function __construct($paypalOrderId, $merchantId) - { - $this->merchantId = $merchantId; - $this->paypalOrderId = $paypalOrderId; - $this->context = \Context::getContext(); - } - - /** - * @param array{cartId: int, amount: float, currencyId: int, secureKey: string, isExpressCheckout: bool, isHostedFields: bool, fundingSource: string, liabilityShift: string, liabilityShifted: bool, authenticationStatus: string, authenticationReason: string} $payload - */ - public function validateOrder($payload) - { - /** @var \Ps_checkout $module */ - $module = \Module::getInstanceByName('ps_checkout'); - - // API call here - $paypalOrder = new PaypalOrder($this->paypalOrderId); - $order = $paypalOrder->getOrder(); - - if (empty($order)) { - throw new OrderNotFoundException(sprintf('Unable to retrieve Paypal Order for %s', $this->paypalOrderId), OrderNotFoundException::NOT_FOUND); - } - - if ($payload['isHostedFields']) { - $card3DSecure = (new Card3DSecure())->continueWithAuthorization($order); - - $module->getLogger()->info( - '3D Secure authentication result', - [ - 'authentication_result' => isset($order['payment_source']['card']['authentication_result']) ? $order['payment_source']['card']['authentication_result'] : null, - 'decision' => str_replace( - [ - (string) Card3DSecure::NO_DECISION, - (string) Card3DSecure::PROCEED, - (string) Card3DSecure::REJECT, - (string) Card3DSecure::RETRY, - ], - [ - \Configuration::get('PS_CHECKOUT_LIABILITY_SHIFT_REQ') ? 'Rejected, no liability shift' : 'Proceed, without liability shift', - 'Proceed, liability shift is possible', - 'Rejected', - 'Retry, ask customer to retry', - ], - (string) $card3DSecure - ), - ] - ); - - if (Card3DSecure::REJECT === $card3DSecure) { - throw new PsCheckoutException('Card Strong Customer Authentication failure', PsCheckoutException::PAYPAL_PAYMENT_CARD_SCA_FAILURE); - } - - if (Card3DSecure::RETRY === $card3DSecure) { - throw new PsCheckoutException('Card Strong Customer Authentication must be retried.', PsCheckoutException::PAYPAL_PAYMENT_CARD_SCA_UNKNOWN); - } - - if (Card3DSecure::NO_DECISION === $card3DSecure && \Configuration::get('PS_CHECKOUT_LIABILITY_SHIFT_REQ')) { - throw new PsCheckoutException('No liability shift to card issuer', PsCheckoutException::PAYPAL_PAYMENT_CARD_SCA_UNKNOWN); - } - } - - $transactionIdentifier = false === empty($order['purchase_units'][0]['payments']['captures'][0]['id']) ? $order['purchase_units'][0]['payments']['captures'][0]['id'] : ''; - $transactionStatus = false === empty($order['purchase_units'][0]['payments']['captures'][0]['status']) ? $order['purchase_units'][0]['payments']['captures'][0]['status'] : ''; - - // @todo To be refactored in v2.0.0 with Service Container - if (true === empty($order['purchase_units'][0]['payments']['captures'])) { - /** @var \Ps_checkout $module */ - $module = \Module::getInstanceByName('ps_checkout'); - - /** @var \PrestaShop\Module\PrestashopCheckout\FundingSource\FundingSourceTranslationProvider $fundingSourceTranslationProvider */ - $fundingSourceTranslationProvider = $module->getService('ps_checkout.funding_source.translation'); - - /** @var \PrestaShop\Module\PrestashopCheckout\Repository\PsCheckoutCartRepository $psCheckoutCartRepository */ - $psCheckoutCartRepository = $module->getService('ps_checkout.repository.pscheckoutcart'); - - /** @var \PsCheckoutCart|false $psCheckoutCart */ - $psCheckoutCart = $psCheckoutCartRepository->findOneByCartId((int) $payload['cartId']); - - // Check if the PayPal order amount is the same than the cart amount - // We tolerate a difference of more or less 0.05 - $paypalOrderAmount = sprintf('%01.2f', $order['purchase_units'][0]['amount']['value']); - $cartAmount = sprintf('%01.2f', $this->context->cart->getOrderTotal(true, \Cart::BOTH)); - - if ($paypalOrderAmount + 0.05 < $cartAmount || $paypalOrderAmount - 0.05 > $cartAmount) { - throw new PsCheckoutException('The transaction amount doesn\'t match with the cart amount.', PsCheckoutException::DIFFERENCE_BETWEEN_TRANSACTION_AND_CART); - } - - $apiOrder = new Order($this->context->link); - - $fundingSource = false === $psCheckoutCart ? 'paypal' : $psCheckoutCart->paypal_funding; - - if ($fundingSource === 'card') { - $fundingSource .= $psCheckoutCart->isHostedFields ? '_hosted' : '_inline'; - } - - $response = $apiOrder->capture( - $order['id'], - $this->merchantId, - $fundingSource - ); // API call here - - if (false === $response['status']) { - if (false === empty($response['body']['message'])) { - (new PayPalError($response['body']['message']))->throwException(); - } - - if (false === empty($response['exceptionMessage']) && false === empty($response['exceptionCode'])) { - throw new PsCheckoutException($response['exceptionMessage'], (int) $response['exceptionCode']); - } - - throw new PsCheckoutException(isset($response['body']['error']) ? $response['body']['error'] : 'Unknown error', PsCheckoutException::UNKNOWN); - } - - if (false === empty($response['body']['purchase_units'][0]['payments']['captures'])) { - $transactionIdentifier = $response['body']['purchase_units'][0]['payments']['captures'][0]['id']; - $transactionStatus = $response['body']['purchase_units'][0]['payments']['captures'][0]['status']; - - if ( - self::CAPTURE_STATUS_DECLINED === $transactionStatus - && false === empty($response['body']['payment_source']) - && false === empty($response['body']['payment_source'][0]['card']) - && false === empty($response['body']['purchase_units'][0]['payments']['captures'][0]['processor_response']) - ) { - $payPalProcessorResponse = new PayPalProcessorResponse( - isset($response['body']['payment_source'][0]['card']['brand']) ? $response['body']['payment_source'][0]['card']['brand'] : null, - isset($response['body']['payment_source'][0]['card']['type']) ? $response['body']['payment_source'][0]['card']['type'] : null, - isset($response['body']['purchase_units'][0]['payments']['captures'][0]['processor_response']['avs_code']) ? $response['body']['purchase_units'][0]['payments']['captures'][0]['processor_response']['avs_code'] : null, - isset($response['body']['purchase_units'][0]['payments']['captures'][0]['processor_response']['cvv_code']) ? $response['body']['purchase_units'][0]['payments']['captures'][0]['processor_response']['cvv_code'] : null, - isset($response['body']['purchase_units'][0]['payments']['captures'][0]['processor_response']['response_code']) ? $response['body']['purchase_units'][0]['payments']['captures'][0]['processor_response']['response_code'] : null - ); - $payPalProcessorResponse->throwException(); - } - } - /** @var CacheInterface $orderPayPalCache */ - $orderPayPalCache = $module->getService('ps_checkout.cache.paypal.order'); - $orderPayPalCache->set($response['body']['id'], $response['body']); - - if (false === $psCheckoutCart) { - $psCheckoutCart = new \PsCheckoutCart(); - $psCheckoutCart->id_cart = (int) $payload['cartId']; - $psCheckoutCart->paypal_intent = $paypalOrder->getOrderIntent(); - $psCheckoutCart->paypal_order = $response['body']['id']; - $psCheckoutCart->paypal_status = $response['body']['status']; - $psCheckoutCartRepository->save($psCheckoutCart); - } else { - $psCheckoutCart->paypal_order = $response['body']['id']; - $psCheckoutCart->paypal_status = $response['body']['status']; - $psCheckoutCartRepository->save($psCheckoutCart); - } - - if (self::CAPTURE_STATUS_DECLINED === $transactionStatus) { - throw new PsCheckoutException(sprintf('Transaction declined by PayPal : %s', false === empty($response['body']['details']['description']) ? $response['body']['details']['description'] : 'No detail'), PsCheckoutException::PAYPAL_PAYMENT_CAPTURE_DECLINED); - } - - try { - $module->validateOrder( - $payload['cartId'], - (int) $this->getOrderState($psCheckoutCart->paypal_funding), - 0, - $fundingSourceTranslationProvider->getPaymentMethodName($psCheckoutCart->paypal_funding), - null, - [ - 'transaction_id' => $transactionIdentifier, - ], - $payload['currencyId'], - false, - $payload['secureKey'] - ); - } catch (\ErrorException $exception) { - // Notice or warning from PHP - } catch (\Exception $exception) { - throw new PsCheckoutException('PrestaShop cannot validate order', PsCheckoutException::PRESTASHOP_VALIDATE_ORDER, $exception); - } - - if (empty($module->currentOrder)) { - throw new PsCheckoutException(sprintf('PrestaShop was unable to returns Prestashop Order ID for Prestashop Cart ID : %s - Paypal Order ID : %s. This happens when PrestaShop take too long time to create an Order due to heavy processes in hooks actionValidateOrder and/or actionOrderStatusUpdate and/or actionOrderStatusPostUpdate', $payload['cartId'], $this->paypalOrderId), PsCheckoutException::PRESTASHOP_ORDER_ID_MISSING); - } - - if (false === $this->setOrdersMatrice($module->currentOrder, $this->paypalOrderId)) { - throw new PsCheckoutException(sprintf('Set Order Matrice error for Prestashop Order ID : %s and Paypal Order ID : %s', $module->currentOrder, $this->paypalOrderId), PsCheckoutException::PSCHECKOUT_ORDER_MATRICE_ERROR); - } - - if (in_array($transactionStatus, [static::CAPTURE_STATUS_COMPLETED, static::CAPTURE_STATUS_DECLINED])) { - $newOrderState = static::CAPTURE_STATUS_COMPLETED === $transactionStatus ? $this->getPaidStatusId($module->currentOrder) : (int) \Configuration::getGlobalValue('PS_OS_ERROR'); - - $orderPS = new \Order($module->currentOrder); - $currentOrderStateId = (int) $orderPS->getCurrentState(); - - // If have to change current OrderState from Waiting to Paid or Canceled - if ($currentOrderStateId !== $newOrderState) { - $orderHistory = new \OrderHistory(); - $orderHistory->id_order = $module->currentOrder; - try { - $orderHistory->changeIdOrderState($newOrderState, $module->currentOrder); - $orderHistory->addWithemail(); - } catch (\ErrorException $exception) { - // Notice or warning from PHP - // For example : https://github.com/PrestaShop/PrestaShop/issues/18837 - } catch (\Exception $exception) { - throw new PsCheckoutException('Unable to change PrestaShop OrderState', PsCheckoutException::PRESTASHOP_ORDER_STATE_ERROR, $exception); - } - } - } - } - - return [ - 'status' => false === empty($response) ? $response['body']['status'] : $order['status'], - 'paypalOrderId' => false === empty($response) ? $response['body']['id'] : $this->paypalOrderId, - 'transactionIdentifier' => $transactionIdentifier, - ]; - } - - /** - * @todo To remove when need of fallback on previous version is gone - * - * Set the matrice order values - * - * @param int $orderPrestashopId from prestashop - * @param string $orderPaypalId paypal order id - * - * @return bool - * - * @throws \PrestaShopDatabaseException - * @throws \PrestaShopException - */ - private function setOrdersMatrice($orderPrestashopId, $orderPaypalId) - { - $orderMatrice = new \OrderMatrice(); - $orderMatrice->id_order_prestashop = $orderPrestashopId; - $orderMatrice->id_order_paypal = $orderPaypalId; - - return $orderMatrice->add(); - } - - /** - * @param int $orderId Order identifier - * - * @return int OrderState identifier - * - * @throws \PrestaShopDatabaseException - * @throws \PrestaShopException - */ - private function getPaidStatusId($orderId) - { - $order = new \Order($orderId); - - if (\Validate::isLoadedObject($order) && $order->getCurrentState() == \Configuration::getGlobalValue('PS_OS_OUTOFSTOCK_UNPAID')) { - return (int) \Configuration::getGlobalValue('PS_OS_OUTOFSTOCK_PAID'); - } - - return (int) \Configuration::getGlobalValue('PS_OS_PAYMENT'); - } - - /** - * Get OrderState identifier - * - * @todo Move to a dedicated Service - * - * @param string $fundingSource - * - * @return int - */ - private function getOrderState($fundingSource) - { - switch ($fundingSource) { - case 'card': - $orderStateId = (int) \Configuration::get('PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT'); - break; - case 'paypal': - $orderStateId = (int) \Configuration::get('PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT'); - break; - default: - $orderStateId = (int) \Configuration::get('PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT'); - } - - return $orderStateId; - } -} diff --git a/upgrade/upgrade-1.2.10.php b/upgrade/upgrade-1.2.10.php index aa7afbd74..17f36da44 100644 --- a/upgrade/upgrade-1.2.10.php +++ b/upgrade/upgrade-1.2.10.php @@ -17,9 +17,6 @@ * @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 */ - -use PrestaShop\Module\PrestashopCheckout\OrderStates; - if (!defined('_PS_VERSION_')) { exit; } @@ -33,20 +30,6 @@ */ function upgrade_module_1_2_10($module) { - foreach (OrderStates::ORDER_STATES as $key => $value) { - $idState = \Configuration::getGlobalValue($key); - - $update = \Db::getInstance()->update( - OrderStates::ORDER_STATE_TABLE, - ['color' => $value], - 'module_name = "ps_checkout" AND id_order_state = ' . (int) $idState - ); - - if ($update !== true) { - return false; - } - } - // Force PrestaShop to upgrade for all shop to avoid issues $savedShopContext = Shop::getContext(); $savedShopId = Shop::getContextShopID(); diff --git a/upgrade/upgrade-1.3.0.php b/upgrade/upgrade-1.3.0.php index 5ca60d4c1..520ab5f70 100644 --- a/upgrade/upgrade-1.3.0.php +++ b/upgrade/upgrade-1.3.0.php @@ -36,7 +36,6 @@ function upgrade_module_1_3_0($module) $savedGroupShopId = Shop::getContextShopGroupID(); Shop::setContext(Shop::CONTEXT_ALL); - (new PrestaShop\Module\PrestashopCheckout\OrderStates())->installPaypalStates(); $module->registerHook('actionObjectShopAddAfter'); // Restore initial PrestaShop shop context diff --git a/upgrade/upgrade-1.4.0.php b/upgrade/upgrade-1.4.0.php index 88aa59148..4c80779c0 100644 --- a/upgrade/upgrade-1.4.0.php +++ b/upgrade/upgrade-1.4.0.php @@ -59,104 +59,6 @@ function upgrade_module_1_4_0($module) } } - // Fix multiple OrderState created in multishop before 1.3.0 - $queryConfigurationResults = $db->executeS(' - SELECT c.id_configuration, c.name, c.value, c.id_shop, c.id_shop_group, os.id_order_state - FROM `' . _DB_PREFIX_ . 'configuration` AS c - LEFT JOIN `' . _DB_PREFIX_ . 'order_state` AS os ON (c.value = os.id_order_state) - WHERE c.name LIKE "PS_CHECKOUT_STATE_%" - '); - - $orderStatesToClean = [ - 'PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT', - 'PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT', - 'PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT', - 'PS_CHECKOUT_STATE_AUTHORIZED', - 'PS_CHECKOUT_STATE_PARTIAL_REFUND', - 'PS_CHECKOUT_STATE_WAITING_CAPTURE', - ]; - $orderStateRows = []; - - if (false === empty($queryConfigurationResults)) { - foreach ($queryConfigurationResults as $queryConfigurationResult) { - if (false === in_array($queryConfigurationResult['name'], $orderStatesToClean, true)) { - continue; - } - - $orderStateRows[$queryConfigurationResult['name']][] = [ - 'id_configuration' => $queryConfigurationResult['id_configuration'], - 'id_order_state' => $queryConfigurationResult['id_order_state'], - ]; - } - } - - foreach ($orderStateRows as $orderStateRow) { - $isGlobalValueSaved = false; - foreach ($orderStateRow as $index => $data) { - if (false === empty($data['id_order_state'])) { - if (false === $isGlobalValueSaved) { - // Set value global for all shops - $result = $db->update( - 'configuration', - [ - 'id_shop' => null, - 'id_shop_group' => null, - ], - 'id_configuration = ' . (int) $data['id_configuration'], - 0, - true - ); - - if ($result) { - $isGlobalValueSaved = true; - // Skip deletion of this configuration - continue; - } - } else { - // Mark this duplicated OrderState as deleted - $db->update( - 'order_state', - [ - 'deleted' => 1, - ], - 'id_order_state = ' . (int) $data['id_order_state'] - ); - } - } - - // Remove this OrderState identifier from Configuration - $db->delete( - 'configuration', - 'id_configuration = ' . (int) $data['id_configuration'] - ); - } - } - - // Mark OrderState created by older module installation who failed as deleted - $queryOrderState = new \DbQuery(); - $queryOrderState->select('id_order_state'); - $queryOrderState->from('order_state'); - $queryOrderState->where('module_name = "' . $module->name . '"'); - $queryOrderState->where('deleted = 0'); - - if (false === empty($queryConfigurationResults)) { - $queryOrderState->where('`id_order_state` NOT IN (' . implode(',', array_column($queryConfigurationResults, 'id_order_state')) . ')'); - } - - $queryOrderStateResults = $db->executeS($queryOrderState); - - if (false === empty($queryOrderStateResults)) { - foreach ($queryOrderStateResults as $queryOrderStateResult) { - $db->update( - 'order_state', - [ - 'deleted' => 1, - ], - 'id_order_state = ' . (int) $queryOrderStateResult['id_order_state'] - ); - } - } - $module->registerHook('displayAdminOrderLeft'); $module->registerHook('displayAdminOrderMainBottom'); $module->registerHook('actionAdminControllerSetMedia'); From b983ad6d2445ded5ed2695e680478b3cc0a37d24 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Thu, 13 Jul 2023 19:58:04 +0200 Subject: [PATCH 15/31] Update upgrade script --- upgrade/upgrade-6.3.4.0.php | 52 +++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/upgrade/upgrade-6.3.4.0.php b/upgrade/upgrade-6.3.4.0.php index 33acdb790..ffaac93b2 100644 --- a/upgrade/upgrade-6.3.4.0.php +++ b/upgrade/upgrade-6.3.4.0.php @@ -92,16 +92,21 @@ function upgrade_module_6_3_4_0($module) // Check module OrderState $moduleOrderStates = [ + 'PS_CHECKOUT_STATE_PENDING' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_PENDING'), + 'PS_CHECKOUT_STATE_COMPLETED' => (int) Configuration::getGlobalValue('PS_OS_PAYMENT'), + 'PS_CHECKOUT_STATE_CANCELED' => (int) Configuration::getGlobalValue('PS_OS_CANCELED'), + 'PS_CHECKOUT_STATE_ERROR' => (int) Configuration::getGlobalValue('PS_OS_ERROR'), + 'PS_CHECKOUT_STATE_REFUNDED' => (int) Configuration::getGlobalValue('PS_OS_REFUND'), + 'PS_CHECKOUT_STATE_PARTIALLY_REFUNDED' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_PARTIAL_REFUND'), + 'PS_CHECKOUT_STATE_PARTIALLY_PAID' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_PARTIALLY_PAID'), 'PS_CHECKOUT_STATE_AUTHORIZED' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_AUTHORIZED'), - 'PS_CHECKOUT_STATE_PARTIAL_REFUND' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_PARTIAL_REFUND'), - 'PS_CHECKOUT_STATE_WAITING_CAPTURE' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_CAPTURE'), - 'PS_CHECKOUT_STATE_WAITING_PAYMENT' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_PAYMENT'), ]; $moduleOrderStatesId = array_values($moduleOrderStates); $moduleOrderStatesIdToDelete = [ (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_PAYPAL_PAYMENT'), (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_CREDIT_CARD_PAYMENT'), (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_LOCAL_PAYMENT'), + (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_WAITING_CAPTURE'), ]; $orderStateCollection = new PrestaShopCollection(OrderState::class); @@ -149,9 +154,9 @@ function upgrade_module_6_3_4_0($module) ] ); break; - case 'PS_CHECKOUT_STATE_PARTIAL_REFUND': + case 'PS_CHECKOUT_STATE_PARTIALLY_REFUNDED': ps_checkout_create_order_state_6_3_4_0( - 'PS_CHECKOUT_STATE_PARTIAL_REFUND', + 'PS_CHECKOUT_STATE_PARTIALLY_REFUNDED', '#01B887', [ 'en' => 'Partial refund', @@ -165,8 +170,8 @@ function upgrade_module_6_3_4_0($module) ] ); break; - case 'PS_CHECKOUT_STATE_WAITING_PAYMENT': - ps_checkout_create_order_state_6_3_4_0('PS_CHECKOUT_STATE_WAITING_PAYMENT', '#34209E', [ + case 'PS_CHECKOUT_STATE_PENDING': + ps_checkout_create_order_state_6_3_4_0('PS_CHECKOUT_STATE_PENDING', '#34209E', [ 'en' => 'Waiting for payment', 'fr' => 'En attente de paiement', 'es' => 'Esperando el pago', @@ -177,23 +182,25 @@ function upgrade_module_6_3_4_0($module) 'pt' => 'Aguardando pagamento', ]); break; - case 'PS_CHECKOUT_STATE_WAITING_CAPTURE': + case 'PS_CHECKOUT_STATE_PARTIALLY_PAID': ps_checkout_create_order_state_6_3_4_0( - 'PS_CHECKOUT_STATE_WAITING_CAPTURE', + 'PS_CHECKOUT_STATE_PARTIALLY_PAID', '#3498D8', [ - 'en' => 'Waiting capture', - 'fr' => 'En attente de capture', - 'es' => 'Esperando la captura', - 'it' => 'In attesa di essere acquisito', - 'nl' => 'Wachten op registratie', - 'de' => 'Warten auf Erfassung', - 'pl' => 'Oczekiwanie na transfer', - 'pt' => 'Aguardando a captura', + 'en' => 'Partial payment', + 'fr' => 'Paiement partiel', + 'es' => 'Pago parcial', + 'it' => 'Pagamento parziale', + 'nl' => 'Gedeeltelijke betaling', + 'de' => 'Teilweise Zahlung', + 'pl' => 'Częściowa płatność', + 'pt' => 'Pagamento parcial', ] ); break; } + } else { + Configuration::updateGlobalValue($configuration_key, $id_order_state); } } } catch (Exception $exception) { @@ -245,4 +252,15 @@ function ps_checkout_create_order_state_6_3_4_0($configuration_key, $color, $nam $orderState->template = []; $orderState->save(); Configuration::updateGlobalValue($configuration_key, $orderState->id); + $orderStateImage = $configuration_key === 'PS_CHECKOUT_STATE_PARTIALLY_REFUNDED' ? 'refund.gif' : 'waiting.gif'; + $moduleOrderStateImgPath = _PS_MODULE_DIR_ . 'ps_checkout/views/img/OrderStatesIcons/' . $orderStateImage; + $coreOrderStateImgPath = _PS_IMG_DIR_ . 'os/' . $orderState->id . '.gif'; + + if ( + Tools::file_exists_cache($moduleOrderStateImgPath) + && !Tools::file_exists_cache($coreOrderStateImgPath) + && is_writable(_PS_IMG_DIR_ . 'os/') + ) { + Tools::copy($moduleOrderStateImgPath, $coreOrderStateImgPath); + } } From 194603c58544da44603430e56746f94b3c651593 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:03:08 +0200 Subject: [PATCH 16/31] Avoid throw exception for bad request --- controllers/front/ExpressCheckout.php | 15 ++++++++++++--- controllers/front/cancel.php | 21 ++++++++++++++++----- controllers/front/check.php | 20 ++++++++++++++++---- controllers/front/create.php | 5 ++++- controllers/front/token.php | 6 ++++-- controllers/front/validate.php | 20 ++++++++++++++++---- 6 files changed, 68 insertions(+), 19 deletions(-) diff --git a/controllers/front/ExpressCheckout.php b/controllers/front/ExpressCheckout.php index 996595a17..8d8615732 100644 --- a/controllers/front/ExpressCheckout.php +++ b/controllers/front/ExpressCheckout.php @@ -52,17 +52,26 @@ public function postProcess() $bodyContent = file_get_contents('php://input'); if (empty($bodyContent)) { - throw new PsCheckoutException('Body cannot be empty', PsCheckoutException::PSCHECKOUT_VALIDATE_BODY_EMPTY); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Payload invalid', + ]); } $this->payload = json_decode($bodyContent, true); if (empty($this->payload)) { - throw new PsCheckoutException('Body cannot be empty', PsCheckoutException::PSCHECKOUT_VALIDATE_BODY_EMPTY); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Payload invalid', + ]); } if (empty($this->payload['orderID']) || false === Validate::isGenericName($this->payload['orderID'])) { - throw new PsCheckoutException('PayPal Order identifier missing or invalid', PsCheckoutException::PAYPAL_ORDER_IDENTIFIER_MISSING); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Payload invalid', + ]); } /** @var PsCheckoutCartRepository $psCheckoutCartRepository */ diff --git a/controllers/front/cancel.php b/controllers/front/cancel.php index bf4affa6e..bccd1d7fe 100644 --- a/controllers/front/cancel.php +++ b/controllers/front/cancel.php @@ -19,7 +19,6 @@ */ use PrestaShop\Module\PrestashopCheckout\Controller\AbstractFrontController; -use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException; use PrestaShop\Module\PrestashopCheckout\Repository\PsCheckoutCartRepository; /** @@ -41,19 +40,28 @@ public function postProcess() { try { if (false === Validate::isLoadedObject($this->context->cart)) { - throw new PsCheckoutException('No cart found.', PsCheckoutException::PRESTASHOP_CONTEXT_INVALID); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'No cart found.', + ]); } $bodyContent = file_get_contents('php://input'); if (empty($bodyContent)) { - throw new PsCheckoutException('Payload invalid', PsCheckoutException::PSCHECKOUT_WEBHOOK_BODY_EMPTY); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Payload invalid', + ]); } $bodyValues = json_decode($bodyContent, true); if (empty($bodyValues)) { - throw new PsCheckoutException('Payload invalid', PsCheckoutException::PSCHECKOUT_WEBHOOK_BODY_EMPTY); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Payload invalid', + ]); } $orderId = isset($bodyValues['orderID']) ? $bodyValues['orderID'] : null; @@ -62,7 +70,10 @@ public function postProcess() $isHostedFields = isset($bodyValues['isHostedFields']) && $bodyValues['isHostedFields']; if (empty($orderId)) { - throw new PsCheckoutException('Missing PayPal Order Id', PsCheckoutException::PAYPAL_ORDER_IDENTIFIER_MISSING); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Missing PayPal Order Id', + ]); } /** @var PsCheckoutCartRepository $psCheckoutCartRepository */ diff --git a/controllers/front/check.php b/controllers/front/check.php index 69aadbe5f..bb439d5d7 100644 --- a/controllers/front/check.php +++ b/controllers/front/check.php @@ -42,19 +42,28 @@ public function postProcess() { try { if (false === Validate::isLoadedObject($this->context->cart)) { - throw new PsCheckoutException('No cart found.', PsCheckoutException::PRESTASHOP_CONTEXT_INVALID); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'No cart found.', + ]); } $bodyContent = file_get_contents('php://input'); if (empty($bodyContent)) { - throw new PsCheckoutException('Payload invalid', PsCheckoutException::PSCHECKOUT_WEBHOOK_BODY_EMPTY); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Payload invalid', + ]); } $bodyValues = json_decode($bodyContent, true); if (empty($bodyValues)) { - throw new PsCheckoutException('Payload invalid', PsCheckoutException::PSCHECKOUT_WEBHOOK_BODY_EMPTY); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Payload invalid', + ]); } $fundingSource = isset($bodyValues['fundingSource']) ? $bodyValues['fundingSource'] : 'paypal'; @@ -63,7 +72,10 @@ public function postProcess() $isHostedFields = isset($bodyValues['isHostedFields']) && $bodyValues['isHostedFields']; if (empty($orderId)) { - throw new PsCheckoutException('Missing PayPal Order Id', PsCheckoutException::PAYPAL_ORDER_IDENTIFIER_MISSING); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Missing PayPal Order Id', + ]); } /** @var PsCheckoutCartRepository $psCheckoutCartRepository */ diff --git a/controllers/front/create.php b/controllers/front/create.php index 6decffa68..15b6639d6 100644 --- a/controllers/front/create.php +++ b/controllers/front/create.php @@ -93,7 +93,10 @@ public function postProcess() // END Express Checkout if (false === Validate::isLoadedObject($this->context->cart)) { - throw new PsCheckoutException('No cart found.', PsCheckoutException::PRESTASHOP_CONTEXT_INVALID); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'No cart found.', + ]); } /** @var PsCheckoutCartRepository $psCheckoutCartRepository */ diff --git a/controllers/front/token.php b/controllers/front/token.php index b779ab261..e315d37be 100644 --- a/controllers/front/token.php +++ b/controllers/front/token.php @@ -19,7 +19,6 @@ */ use PrestaShop\Module\PrestashopCheckout\Controller\AbstractFrontController; -use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException; use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalClientTokenProvider; /** @@ -41,7 +40,10 @@ public function postProcess() { try { if (false === Validate::isLoadedObject($this->context->cart)) { - throw new PsCheckoutException('No cart found.', PsCheckoutException::PRESTASHOP_CONTEXT_INVALID); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'No cart found.', + ]); } /** @var PayPalClientTokenProvider $clientTokenProvider */ diff --git a/controllers/front/validate.php b/controllers/front/validate.php index fe9d3f1a5..0f6c8ea8a 100644 --- a/controllers/front/validate.php +++ b/controllers/front/validate.php @@ -53,17 +53,26 @@ public function postProcess() $bodyContent = file_get_contents('php://input'); if (empty($bodyContent)) { - throw new PsCheckoutException('Body cannot be empty', PsCheckoutException::PSCHECKOUT_VALIDATE_BODY_EMPTY); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Payload invalid', + ]); } $bodyValues = json_decode($bodyContent, true); if (empty($bodyValues)) { - throw new PsCheckoutException('Body cannot be empty', PsCheckoutException::PSCHECKOUT_VALIDATE_BODY_EMPTY); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Payload invalid', + ]); } if (empty($bodyValues['orderID']) || false === Validate::isGenericName($bodyValues['orderID'])) { - throw new PsCheckoutException('PayPal Order identifier invalid', PsCheckoutException::PAYPAL_ORDER_IDENTIFIER_MISSING); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'Missing PayPal Order Id', + ]); } $this->paypalOrderId = $bodyValues['orderID']; @@ -73,7 +82,10 @@ public function postProcess() $psCheckoutCart = $psCheckoutCartRepository->findOneByPayPalOrderId($this->paypalOrderId); if (!Validate::isLoadedObject($psCheckoutCart)) { - throw new PsCheckoutException('The cart cannot be found', PsCheckoutException::PRESTASHOP_CART_NOT_FOUND); + $this->exitWithResponse([ + 'httpCode' => 400, + 'body' => 'No cart found.', + ]); } /** @var EventDispatcherInterface $eventDispatcher */ From db9fac8b96c0628dfce908da534edede68a4725b Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:08:24 +0200 Subject: [PATCH 17/31] Fix undefined constant --- src/PayPal/Order/EventSubscriber/PayPalOrderEventSubscriber.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PayPal/Order/EventSubscriber/PayPalOrderEventSubscriber.php b/src/PayPal/Order/EventSubscriber/PayPalOrderEventSubscriber.php index 9d74b1b9c..f27f134e7 100644 --- a/src/PayPal/Order/EventSubscriber/PayPalOrderEventSubscriber.php +++ b/src/PayPal/Order/EventSubscriber/PayPalOrderEventSubscriber.php @@ -248,7 +248,7 @@ public function setApprovalReversedOrderStatus(PayPalOrderApprovalReversedEvent $this->commandBus->handle( new UpdateOrderStatusCommand( $order->getOrderId()->getValue(), - $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::CANCELED) + $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED) ) ); } From 93f374636a73ac4d04273dd49f8a1051f1782391 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Wed, 19 Jul 2023 12:01:38 +0200 Subject: [PATCH 18/31] Catch order status mapping exception --- .../AdminAjaxPrestashopCheckoutController.php | 53 +++++++------------ .../State/Exception/OrderStateException.php | 2 +- src/Order/State/Service/OrderStateMapper.php | 49 +++++++++++++++-- 3 files changed, 63 insertions(+), 41 deletions(-) diff --git a/controllers/admin/AdminAjaxPrestashopCheckoutController.php b/controllers/admin/AdminAjaxPrestashopCheckoutController.php index 3f9916616..b5f61f205 100755 --- a/controllers/admin/AdminAjaxPrestashopCheckoutController.php +++ b/controllers/admin/AdminAjaxPrestashopCheckoutController.php @@ -29,7 +29,8 @@ use PrestaShop\Module\PrestashopCheckout\Logger\LoggerFileReader; use PrestaShop\Module\PrestashopCheckout\OnBoarding\Step\LiveStep; use PrestaShop\Module\PrestashopCheckout\OnBoarding\Step\ValueBanner; -use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateConfigurationKeys; +use PrestaShop\Module\PrestashopCheckout\Order\State\Exception\OrderStateException; +use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateInstaller; use PrestaShop\Module\PrestashopCheckout\Order\State\Service\OrderStateMapper; use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration; use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalOrderProvider; @@ -890,43 +891,25 @@ public function ajaxProcessGetMappedOrderStates() { /** @var OrderStateMapper $orderStateMapper */ $orderStateMapper = $this->module->getService('ps_checkout.order.state.service.order_state_mapper'); + $mappedOrderStates = []; + + try { + $mappedOrderStates = $orderStateMapper->getMappedOrderStates(); + } catch (OrderStateException $exception) { + if ($exception->getCode() === OrderStateException::INVALID_MAPPING) { + (new OrderStateInstaller())->install(); + } + + $this->exitWithResponse([ + 'httpCode' => 500, + 'status' => false, + 'error' => $exception->getMessage(), + ]); + } $this->exitWithResponse([ 'status' => true, - 'mappedOrderStates' => [ - OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING => [ - 'default' => '0', - 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING), - ], - OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED => [ - 'default' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_OS_PAYMENT), - 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED), - ], - OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED => [ - 'default' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_OS_CANCELED), - 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED), - ], - OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR => [ - 'default' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_OS_ERROR), - 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR), - ], - OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED => [ - 'default' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_OS_REFUND), - 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED), - ], - OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED => [ - 'default' => '0', - 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED), - ], - OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID => [ - 'default' => '0', - 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID), - ], - OrderStateConfigurationKeys::PS_CHECKOUT_STATE_AUTHORIZED => [ - 'default' => '0', - 'value' => (string) $orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_AUTHORIZED), - ], - ], + 'mappedOrderStates' => $mappedOrderStates, ]); } diff --git a/src/Order/State/Exception/OrderStateException.php b/src/Order/State/Exception/OrderStateException.php index a932c2bbc..bfb7748c4 100644 --- a/src/Order/State/Exception/OrderStateException.php +++ b/src/Order/State/Exception/OrderStateException.php @@ -25,5 +25,5 @@ class OrderStateException extends PsCheckoutException { const INVALID_ID = 1; - const TRANSITION_UNAVAILABLE = 2; + const INVALID_MAPPING = 2; } diff --git a/src/Order/State/Service/OrderStateMapper.php b/src/Order/State/Service/OrderStateMapper.php index 9d773e9e1..7d609e0f3 100644 --- a/src/Order/State/Service/OrderStateMapper.php +++ b/src/Order/State/Service/OrderStateMapper.php @@ -20,8 +20,8 @@ namespace PrestaShop\Module\PrestashopCheckout\Order\State\Service; -use InvalidArgumentException; use PrestaShop\Module\PrestashopCheckout\Configuration\PrestaShopConfiguration; +use PrestaShop\Module\PrestashopCheckout\Order\State\Exception\OrderStateException; use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateConfigurationKeys; class OrderStateMapper @@ -49,6 +49,8 @@ public function __construct(PrestaShopConfiguration $configuration) * @param string $key * * @return int + * + * @throws OrderStateException */ public function getIdByKey($key) { @@ -56,21 +58,58 @@ public function getIdByKey($key) return $this->orderStateMapping[$key]; } - throw new InvalidArgumentException(sprintf('Order state key "%s" is not mapped', var_export($key, true))); + throw new OrderStateException(sprintf('Order state key "%s" is not mapped', var_export($key, true)), OrderStateException::INVALID_MAPPING); } /** * @return array + * + * @throws OrderStateException */ - public function getOrderStateMapping() + public function getMappedOrderStates() { - return $this->orderStateMapping; + return [ + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING => [ + 'default' => '0', + 'value' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING), + ], + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED => [ + 'default' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_OS_PAYMENT), + 'value' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED), + ], + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED => [ + 'default' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_OS_CANCELED), + 'value' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED), + ], + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR => [ + 'default' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_OS_ERROR), + 'value' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_ERROR), + ], + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED => [ + 'default' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_OS_REFUND), + 'value' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED), + ], + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED => [ + 'default' => '0', + 'value' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED), + ], + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID => [ + 'default' => '0', + 'value' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID), + ], + OrderStateConfigurationKeys::PS_CHECKOUT_STATE_AUTHORIZED => [ + 'default' => '0', + 'value' => (string) $this->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_AUTHORIZED), + ], + ]; } /** * @param int $orderCurrentState * * @return string + * + * @throws OrderStateException */ public function getKeyById($orderCurrentState) { @@ -80,7 +119,7 @@ public function getKeyById($orderCurrentState) return $orderStateMapping[$orderCurrentState]; } - throw new InvalidArgumentException(sprintf('Order state id "%s" is not mapped', var_export($orderCurrentState, true))); + throw new OrderStateException(sprintf('Order state id "%s" is not mapped', var_export($orderCurrentState, true)), OrderStateException::INVALID_MAPPING); } private function initialize() From fe5d85766318cae44a9673a42399c9e427ea6c26 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Wed, 19 Jul 2023 12:15:06 +0200 Subject: [PATCH 19/31] Fix upgrade script --- upgrade/upgrade-6.3.4.0.php | 86 ++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/upgrade/upgrade-6.3.4.0.php b/upgrade/upgrade-6.3.4.0.php index ffaac93b2..717f4fc9b 100644 --- a/upgrade/upgrade-6.3.4.0.php +++ b/upgrade/upgrade-6.3.4.0.php @@ -47,49 +47,6 @@ function upgrade_module_6_3_4_0($module) $db = Db::getInstance(); - // Installing FundingSource if table pscheckout_funding_source is empty or incomplete - including BLIK - $fundingSources = ['paypal', 'paylater', 'card', 'bancontact', 'eps', 'giropay', 'ideal', 'mybank', 'p24', 'sofort', 'blik']; - $availableFundingSourcesByShops = []; - $maxPositionByShops = []; - $availableFundingSources = $db->executeS('SELECT * FROM ' . _DB_PREFIX_ . 'pscheckout_funding_source'); - - if (!empty($availableFundingSources)) { - foreach ($availableFundingSources as $availableFundingSource) { - $currentPosition = (int) $availableFundingSource['position']; - $shopId = (int) $availableFundingSource['id_shop']; - - if ( - !isset($maxPositionByShops[$shopId]) - || $maxPositionByShops[$shopId] < $currentPosition - ) { - $maxPositionByShops[$shopId] = $currentPosition; - } - - $availableFundingSourcesByShops[$shopId][] = $availableFundingSource['name']; - } - } - - foreach (Shop::getShops(false, null, true) as $shopId) { - $currentPosition = isset($maxPositionByShops[(int) $shopId]) ? $maxPositionByShops[(int) $shopId] + 1 : 1; - foreach ($fundingSources as $fundingSource) { - if ( - !isset($availableFundingSourcesByShops[(int) $shopId]) - || !in_array($fundingSource, $availableFundingSourcesByShops[(int) $shopId], true) - ) { - $db->insert( - 'pscheckout_funding_source', - [ - 'name' => pSQL($fundingSource), - 'active' => 1, - 'position' => (int) $currentPosition, - 'id_shop' => (int) $savedShopId, - ] - ); - ++$currentPosition; - } - } - } - // Check module OrderState $moduleOrderStates = [ 'PS_CHECKOUT_STATE_PENDING' => (int) Configuration::getGlobalValue('PS_CHECKOUT_STATE_PENDING'), @@ -203,6 +160,49 @@ function upgrade_module_6_3_4_0($module) Configuration::updateGlobalValue($configuration_key, $id_order_state); } } + + // Installing FundingSource if table pscheckout_funding_source is empty or incomplete - including BLIK + $fundingSources = ['paypal', 'paylater', 'card', 'bancontact', 'eps', 'giropay', 'ideal', 'mybank', 'p24', 'sofort', 'blik']; + $availableFundingSourcesByShops = []; + $maxPositionByShops = []; + $availableFundingSources = $db->executeS('SELECT * FROM ' . _DB_PREFIX_ . 'pscheckout_funding_source'); + + if (!empty($availableFundingSources)) { + foreach ($availableFundingSources as $availableFundingSource) { + $currentPosition = (int) $availableFundingSource['position']; + $shopId = (int) $availableFundingSource['id_shop']; + + if ( + !isset($maxPositionByShops[$shopId]) + || $maxPositionByShops[$shopId] < $currentPosition + ) { + $maxPositionByShops[$shopId] = $currentPosition; + } + + $availableFundingSourcesByShops[$shopId][] = $availableFundingSource['name']; + } + } + + foreach ($shopsList as $shopId) { + $currentPosition = isset($maxPositionByShops[(int) $shopId]) ? $maxPositionByShops[(int) $shopId] + 1 : 1; + foreach ($fundingSources as $fundingSource) { + if ( + !isset($availableFundingSourcesByShops[(int) $shopId]) + || !in_array($fundingSource, $availableFundingSourcesByShops[(int) $shopId], true) + ) { + $db->insert( + 'pscheckout_funding_source', + [ + 'name' => pSQL($fundingSource), + 'active' => 1, + 'position' => (int) $currentPosition, + 'id_shop' => (int) $shopId, + ] + ); + ++$currentPosition; + } + } + } } catch (Exception $exception) { PrestaShopLogger::addLog($exception->getMessage(), 3, $exception->getCode(), 'Module', $module->id); From 7461d93c58194b09787ea7c947d99704d9757e4a Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:26:28 +0200 Subject: [PATCH 20/31] Guzzle 5 Exception --- src/Api/GenericClient.php | 9 +++++++++ src/Api/Payment/Client/PaymentClient.php | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/src/Api/GenericClient.php b/src/Api/GenericClient.php index e390867e8..bfc17d677 100755 --- a/src/Api/GenericClient.php +++ b/src/Api/GenericClient.php @@ -29,6 +29,7 @@ use PrestaShop\Module\PrestashopCheckout\Handler\Response\ResponseApiHandler; use PrestaShop\Module\PrestashopCheckout\Repository\PsAccountRepository; use Ps_checkout; +use RuntimeException; /** * Construct the client used to make call to maasland @@ -112,6 +113,14 @@ protected function post(array $options = []) $exception ) ); + } catch (RuntimeException $exception) { + return $this->handleException( + new PsCheckoutException( + $exception->getMessage(), + PsCheckoutException::PSCHECKOUT_HTTP_EXCEPTION, + $exception + ) + ); } catch (Exception $exception) { return $this->handleException($exception); } diff --git a/src/Api/Payment/Client/PaymentClient.php b/src/Api/Payment/Client/PaymentClient.php index 5d41af166..39af3a458 100755 --- a/src/Api/Payment/Client/PaymentClient.php +++ b/src/Api/Payment/Client/PaymentClient.php @@ -164,6 +164,11 @@ private function postWithRetry(array $options, $delay = 2, $retries = 2) && false !== strpos($response['exceptionMessage'], 'cURL error 28') ) { throw new HttpTimeoutException($response['exceptionMessage'], PsCheckoutException::PSL_TIMEOUT); + } elseif ( + isset($response['exceptionCode']) + && $response['exceptionCode'] === PsCheckoutException::PSCHECKOUT_HTTP_EXCEPTION + ) { + throw new PsCheckoutException($response['exceptionMessage'], PsCheckoutException::PSCHECKOUT_HTTP_EXCEPTION); } if ( From 74442ca1560a78ce54abf49259c402017b571cbf Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:36:56 +0200 Subject: [PATCH 21/31] Http Unauthorized --- src/Api/Payment/Client/PaymentClient.php | 5 +++++ src/Exception/PsCheckoutException.php | 1 + 2 files changed, 6 insertions(+) diff --git a/src/Api/Payment/Client/PaymentClient.php b/src/Api/Payment/Client/PaymentClient.php index 5d41af166..d3f9946be 100755 --- a/src/Api/Payment/Client/PaymentClient.php +++ b/src/Api/Payment/Client/PaymentClient.php @@ -148,12 +148,17 @@ protected function post(array $options = []) * @return array * * @throws HttpTimeoutException + * @throws PsCheckoutException */ private function postWithRetry(array $options, $delay = 2, $retries = 2) { try { $response = parent::post($options); + if ($response['httpCode'] === 401) { + throw new PsCheckoutException('Unauthorized', PsCheckoutException::PSCHECKOUT_HTTP_UNAUTHORIZED); + } + if (false !== $response['status']) { return $response; } diff --git a/src/Exception/PsCheckoutException.php b/src/Exception/PsCheckoutException.php index 7272f508e..627675825 100644 --- a/src/Exception/PsCheckoutException.php +++ b/src/Exception/PsCheckoutException.php @@ -88,4 +88,5 @@ class PsCheckoutException extends \Exception const CART_ADDRESS_INVOICE_INVALID = 56; const CART_ADDRESS_DELIVERY_INVALID = 57; const CART_DELIVERY_OPTION_INVALID = 58; + const PSCHECKOUT_HTTP_UNAUTHORIZED = 59; } From 5bfaaa68adeb2d98f75fb4a19f157b959d806219 Mon Sep 17 00:00:00 2001 From: Bastien Tafforeau Date: Mon, 31 Jul 2023 15:49:16 +0200 Subject: [PATCH 22/31] Improve error display when card payment is refused --- controllers/front/validate.php | 5 -- .../CapturePayPalOrderCommandHandler.php | 39 +++++++++------ .../PayPalCaptureEventSubscriber.php | 49 ++++++++++++++----- 3 files changed, 60 insertions(+), 33 deletions(-) diff --git a/controllers/front/validate.php b/controllers/front/validate.php index fe9d3f1a5..87a2cdf33 100644 --- a/controllers/front/validate.php +++ b/controllers/front/validate.php @@ -89,11 +89,6 @@ public function postProcess() $this->sendOkResponse($this->generateResponse()); } catch (Exception $exception) { - $this->module->getLogger()->error('CheckoutCompletedEvent failed', [ - 'exception_class' => get_class($exception), - 'exception_message' => $exception->getMessage(), - 'exception_code' => $exception->getCode(), - ]); $response = $this->generateResponse(); if (!empty($response)) { diff --git a/src/PayPal/Order/CommandHandler/CapturePayPalOrderCommandHandler.php b/src/PayPal/Order/CommandHandler/CapturePayPalOrderCommandHandler.php index 07be2921d..fef3eb10f 100644 --- a/src/PayPal/Order/CommandHandler/CapturePayPalOrderCommandHandler.php +++ b/src/PayPal/Order/CommandHandler/CapturePayPalOrderCommandHandler.php @@ -30,6 +30,7 @@ use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Event\PayPalOrderCompletedEvent; use PrestaShop\Module\PrestashopCheckout\PayPal\Order\PayPalOrderStatus; use PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Capture\Event\PayPalCaptureCompletedEvent; +use PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Capture\Event\PayPalCaptureDeclinedEvent; use PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Capture\Event\PayPalCapturePendingEvent; use PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Capture\PayPalCaptureStatus; use PrestaShop\Module\PrestashopCheckout\PayPalError; @@ -77,22 +78,6 @@ public function handle(CapturePayPalOrderCommand $capturePayPalOrderCommand) $orderPayPal = $response['body']; $capturePayPal = $orderPayPal['purchase_units'][0]['payments']['captures'][0]; - if ( - 'DECLINED' === $capturePayPal['status'] - && false === empty($response['body']['payment_source']) - && false === empty($response['body']['payment_source'][0]['card']) - && false === empty($capturePayPal['processor_response']) - ) { - $payPalProcessorResponse = new PayPalProcessorResponse( - isset($response['body']['payment_source'][0]['card']['brand']) ? $response['body']['payment_source'][0]['card']['brand'] : null, - isset($response['body']['payment_source'][0]['card']['type']) ? $response['body']['payment_source'][0]['card']['type'] : null, - isset($capturePayPal['processor_response']['avs_code']) ? $capturePayPal['processor_response']['avs_code'] : null, - isset($capturePayPal['processor_response']['cvv_code']) ? $capturePayPal['processor_response']['cvv_code'] : null, - isset($capturePayPal['processor_response']['response_code']) ? $capturePayPal['processor_response']['response_code'] : null - ); - $payPalProcessorResponse->throwException(); - } - if ($orderPayPal['status'] === PayPalOrderStatus::COMPLETED) { $this->eventDispatcher->dispatch(new PayPalOrderCompletedEvent($orderPayPal['id'], $orderPayPal)); } @@ -104,5 +89,27 @@ public function handle(CapturePayPalOrderCommand $capturePayPalOrderCommand) if ($capturePayPal['status'] === PayPalCaptureStatus::COMPLETED) { $this->eventDispatcher->dispatch(new PayPalCaptureCompletedEvent($capturePayPal['id'], $orderPayPal['id'], $capturePayPal)); } + + if ($capturePayPal['status'] === PayPalCaptureStatus::DECLINED || $capturePayPal['status'] === PayPalCaptureStatus::FAILED) { + $this->eventDispatcher->dispatch(new PayPalCaptureDeclinedEvent($capturePayPal['id'], $orderPayPal['id'], $capturePayPal)); + } + + if ( + PayPalCaptureStatus::DECLINED === $capturePayPal['status'] + && false === empty($orderPayPal['payment_source']) + && false === empty($orderPayPal['payment_source']['card']) + && false === empty($capturePayPal['processor_response']) + ) { + $payPalProcessorResponse = new PayPalProcessorResponse( + isset($orderPayPal['payment_source']['card']['brand']) ? $orderPayPal['payment_source']['card']['brand'] : null, + isset($orderPayPal['payment_source']['card']['type']) ? $orderPayPal['payment_source']['card']['type'] : null, + isset($capturePayPal['processor_response']['avs_code']) ? $capturePayPal['processor_response']['avs_code'] : null, + isset($capturePayPal['processor_response']['cvv_code']) ? $capturePayPal['processor_response']['cvv_code'] : null, + isset($capturePayPal['processor_response']['response_code']) ? $capturePayPal['processor_response']['response_code'] : null + ); + $payPalProcessorResponse->throwException(); + } elseif (PayPalCaptureStatus::DECLINED === $capturePayPal['status'] || PayPalCaptureStatus::FAILED === $capturePayPal['status']) { + throw new PsCheckoutException('PayPal declined the capture', PsCheckoutException::PAYPAL_PAYMENT_CAPTURE_DECLINED); + } } } diff --git a/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php b/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php index 59b1df49b..265faa609 100644 --- a/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php +++ b/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php @@ -24,6 +24,7 @@ use PrestaShop\Module\PrestashopCheckout\Order\Command\AddOrderPaymentCommand; use PrestaShop\Module\PrestashopCheckout\Order\Command\CreateOrderCommand; use PrestaShop\Module\PrestashopCheckout\Order\Command\UpdateOrderStatusCommand; +use PrestaShop\Module\PrestashopCheckout\Order\Exception\OrderNotFoundException; use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForPaymentCompletedQuery; use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForPaymentCompletedQueryResult; use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForPaymentDeniedQuery; @@ -136,8 +137,12 @@ public function createOrder(PayPalCaptureEvent $event) public function createOrderPayment(PayPalCaptureCompletedEvent $event) { - /** @var GetOrderForPaymentCompletedQueryResult $order */ - $order = $this->commandBus->handle(new GetOrderForPaymentCompletedQuery($event->getPayPalOrderId()->getValue(), $event->getPayPalCaptureId()->getValue())); + try { + /** @var GetOrderForPaymentCompletedQueryResult $order */ + $order = $this->commandBus->handle(new GetOrderForPaymentCompletedQuery($event->getPayPalOrderId()->getValue(), $event->getPayPalCaptureId()->getValue())); + } catch (OrderNotFoundException $exception) { + return; + } if ($order->getOrderPaymentId()) { return; @@ -157,8 +162,12 @@ public function createOrderPayment(PayPalCaptureCompletedEvent $event) public function setPaymentCompletedOrderStatus(PayPalCaptureCompletedEvent $event) { - /** @var GetOrderForPaymentCompletedQueryResult $order */ - $order = $this->commandBus->handle(new GetOrderForPaymentCompletedQuery($event->getPayPalOrderId()->getValue(), $event->getPayPalCaptureId()->getValue())); + try { + /** @var GetOrderForPaymentCompletedQueryResult $order */ + $order = $this->commandBus->handle(new GetOrderForPaymentCompletedQuery($event->getPayPalOrderId()->getValue(), $event->getPayPalCaptureId()->getValue())); + } catch (OrderNotFoundException $exception) { + return; + } if ($order->hasBeenPaid()) { return; @@ -177,8 +186,12 @@ public function setPaymentCompletedOrderStatus(PayPalCaptureCompletedEvent $even public function setPaymentPendingOrderStatus(PayPalCapturePendingEvent $event) { - /** @var GetOrderForPaymentPendingQueryResult $order */ - $order = $this->commandBus->handle(new GetOrderForPaymentPendingQuery($event->getPayPalOrderId()->getValue())); + try { + /** @var GetOrderForPaymentPendingQueryResult $order */ + $order = $this->commandBus->handle(new GetOrderForPaymentPendingQuery($event->getPayPalOrderId()->getValue())); + } catch (OrderNotFoundException $exception) { + return; + } if ($order->isInPending()) { return; @@ -200,8 +213,12 @@ public function setPaymentPendingOrderStatus(PayPalCapturePendingEvent $event) public function setPaymentDeclinedOrderStatus(PayPalCaptureDeclinedEvent $event) { - /** @var GetOrderForPaymentDeniedQueryResult $order */ - $order = $this->commandBus->handle(new GetOrderForPaymentDeniedQuery($event->getPayPalOrderId()->getValue())); + try { + /** @var GetOrderForPaymentDeniedQueryResult $order */ + $order = $this->commandBus->handle(new GetOrderForPaymentDeniedQuery($event->getPayPalOrderId()->getValue())); + } catch (OrderNotFoundException $exception) { + return; + } if ($order->hasBeenError()) { return; @@ -212,8 +229,12 @@ public function setPaymentDeclinedOrderStatus(PayPalCaptureDeclinedEvent $event) public function setPaymentRefundedOrderStatus(PayPalCaptureRefundedEvent $event) { - /** @var GetOrderForPaymentRefundedQueryResult $order */ - $order = $this->commandBus->handle(new GetOrderForPaymentRefundedQuery($event->getPayPalOrderId()->getValue())); + try { + /** @var GetOrderForPaymentRefundedQueryResult $order */ + $order = $this->commandBus->handle(new GetOrderForPaymentRefundedQuery($event->getPayPalOrderId()->getValue())); + } catch (OrderNotFoundException $exception) { + return; + } if (!$order->hasBeenPaid() || $order->hasBeenTotallyRefund()) { return; @@ -228,8 +249,12 @@ public function setPaymentRefundedOrderStatus(PayPalCaptureRefundedEvent $event) public function setPaymentReversedOrderStatus(PayPalCaptureReversedEvent $event) { - /** @var GetOrderForPaymentReversedQueryResult $order */ - $order = $this->commandBus->handle(new GetOrderForPaymentReversedQuery($event->getPayPalOrderId()->getValue(), $event->getPayPalCaptureId()->getValue())); + try { + /** @var GetOrderForPaymentReversedQueryResult $order */ + $order = $this->commandBus->handle(new GetOrderForPaymentReversedQuery($event->getPayPalOrderId()->getValue(), $event->getPayPalCaptureId()->getValue())); + } catch (OrderNotFoundException $exception) { + return; + } if (!$order->hasBeenPaid() || $order->hasBeenTotallyRefund()) { return; From 42beffcc539a09a897536b3cdacc396aeb5b8272 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Tue, 1 Aug 2023 10:55:41 +0200 Subject: [PATCH 23/31] Fix order state translations at install --- src/Order/State/OrderStateInstaller.php | 14 +++++++------- upgrade/upgrade-6.3.4.0.php | 15 ++++++++------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/Order/State/OrderStateInstaller.php b/src/Order/State/OrderStateInstaller.php index d3ad86868..cba98672a 100644 --- a/src/Order/State/OrderStateInstaller.php +++ b/src/Order/State/OrderStateInstaller.php @@ -152,13 +152,13 @@ private function fillOrderStateName(array $nameByLangIsoCode) { $orderStateNameByLangId = []; - foreach ($nameByLangIsoCode as $langIsoCode => $name) { - foreach ($this->languages as $language) { - if (Tools::strtolower($language['iso_code']) === $langIsoCode) { - $orderStateNameByLangId[(int) $language['id_lang']] = $name; - } elseif (isset($nameByLangIsoCode['en'])) { - $orderStateNameByLangId[(int) $language['id_lang']] = $nameByLangIsoCode['en']; - } + foreach ($this->languages as $language) { + $languageIsoCode = Tools::strtolower($language['iso_code']); + + if (isset($nameByLangIsoCode[$languageIsoCode])) { + $orderStateNameByLangId[(int) $language['id_lang']] = $nameByLangIsoCode[$languageIsoCode]; + } elseif (isset($nameByLangIsoCode['en'])) { + $orderStateNameByLangId[(int) $language['id_lang']] = $nameByLangIsoCode['en']; } } diff --git a/upgrade/upgrade-6.3.4.0.php b/upgrade/upgrade-6.3.4.0.php index 717f4fc9b..f82d3b04f 100644 --- a/upgrade/upgrade-6.3.4.0.php +++ b/upgrade/upgrade-6.3.4.0.php @@ -224,13 +224,14 @@ function upgrade_module_6_3_4_0($module) function ps_checkout_create_order_state_6_3_4_0($configuration_key, $color, $nameByLangIsoCode) { $orderStateNameByLangId = []; - foreach ($nameByLangIsoCode as $langIsoCode => $name) { - foreach (Language::getLanguages(false) as $language) { - if (Tools::strtolower($language['iso_code']) === $langIsoCode) { - $orderStateNameByLangId[(int) $language['id_lang']] = $name; - } elseif (isset($nameByLangIsoCode['en'])) { - $orderStateNameByLangId[(int) $language['id_lang']] = $nameByLangIsoCode['en']; - } + + foreach (Language::getLanguages(false) as $language) { + $languageIsoCode = Tools::strtolower($language['iso_code']); + + if (isset($nameByLangIsoCode[$languageIsoCode])) { + $orderStateNameByLangId[(int) $language['id_lang']] = $nameByLangIsoCode[$languageIsoCode]; + } elseif (isset($nameByLangIsoCode['en'])) { + $orderStateNameByLangId[(int) $language['id_lang']] = $nameByLangIsoCode['en']; } } From f1cbc52e82f269d97132172d1156028ea77b15c4 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Tue, 1 Aug 2023 09:29:07 +0200 Subject: [PATCH 24/31] Avoid fatal error on payment due to OS mapping --- .../CreateOrderCommandHandler.php | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Order/CommandHandler/CreateOrderCommandHandler.php b/src/Order/CommandHandler/CreateOrderCommandHandler.php index efa930e00..4a7e7921d 100644 --- a/src/Order/CommandHandler/CreateOrderCommandHandler.php +++ b/src/Order/CommandHandler/CreateOrderCommandHandler.php @@ -34,7 +34,9 @@ use PrestaShop\Module\PrestashopCheckout\Order\Exception\OrderException; use PrestaShop\Module\PrestashopCheckout\Order\Exception\OrderNotFoundException; use PrestaShop\Module\PrestashopCheckout\Order\Service\CheckOrderAmount; +use PrestaShop\Module\PrestashopCheckout\Order\State\Exception\OrderStateException; use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateConfigurationKeys; +use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateInstaller; use PrestaShop\Module\PrestashopCheckout\Order\State\Service\OrderStateMapper; use PrestaShop\Module\PrestashopCheckout\Repository\PsCheckoutCartRepository; use PrestaShopCollection; @@ -143,18 +145,25 @@ public function handle(CreateOrderCommand $command) $currencyId = Currency::getIdByIsoCode($capture['amount']['currency_code'], (int) $cart->id_shop); } - if ($paidAmount) { - switch ($this->checkOrderAmount->checkAmount((string) $paidAmount, (string) $cart->getOrderTotal(true, \Cart::BOTH))) { - case CheckOrderAmount::ORDER_NOT_FULL_PAID: - $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID); - break; - case CheckOrderAmount::ORDER_FULL_PAID: - $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED); - break; - case CheckOrderAmount::ORDER_TO_MUCH_PAID: - $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED); + try { + if ($paidAmount) { + switch ($this->checkOrderAmount->checkAmount((string) $paidAmount, (string) $cart->getOrderTotal(true, \Cart::BOTH))) { + case CheckOrderAmount::ORDER_NOT_FULL_PAID: + $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_PAID); + break; + case CheckOrderAmount::ORDER_FULL_PAID: + $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED); + break; + case CheckOrderAmount::ORDER_TO_MUCH_PAID: + $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_COMPLETED); + } + } else { + $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING); + } + } catch (OrderStateException $exception) { + if ($exception->getCode() === OrderStateException::INVALID_MAPPING) { + (new OrderStateInstaller())->install(); } - } else { $orderStateId = $this->psOrderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PENDING); } From 6e4a5f7cc1f0a0231011912af7c6522acf9a6bea Mon Sep 17 00:00:00 2001 From: Laurynas Date: Tue, 1 Aug 2023 12:40:15 +0300 Subject: [PATCH 25/31] Added maintenance link --- src/Adapter/LinkAdapter.php | 14 ++++++++++++-- src/Presenter/Store/Modules/ContextModule.php | 3 ++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Adapter/LinkAdapter.php b/src/Adapter/LinkAdapter.php index 9a377e65e..7eaefcdda 100644 --- a/src/Adapter/LinkAdapter.php +++ b/src/Adapter/LinkAdapter.php @@ -60,9 +60,19 @@ public function getAdminLink($controller, $withToken = true, $sfRouteParams = [] $shop = \Context::getContext()->shop; if ((new ShopContext())->isShop17()) { - $link = $this->link->getAdminLink($controller, $withToken, $sfRouteParams, $params); + $adminLink = $this->link->getAdminLink($controller, $withToken, $sfRouteParams, $params); - return $shop->virtual_uri !== '' ? str_replace($shop->physical_uri . $shop->virtual_uri, $shop->physical_uri, $link) : $link; + if ($shop->virtual_uri !== '') { + $adminLink = str_replace($shop->physical_uri . $shop->virtual_uri, $shop->physical_uri, $adminLink); + } + + // We have problems with links in our zoid application, since some links generated don't have domain they redirect to CDN domain + // Routes that use new symfony router are returned without the domain + if (strpos($adminLink, 'http') !== 0) { + return \Tools::getShopDomainSsl(true) . $adminLink; + } + + return $adminLink; } $paramsAsString = ''; diff --git a/src/Presenter/Store/Modules/ContextModule.php b/src/Presenter/Store/Modules/ContextModule.php index b28bf5ab1..0d1bb4119 100644 --- a/src/Presenter/Store/Modules/ContextModule.php +++ b/src/Presenter/Store/Modules/ContextModule.php @@ -154,7 +154,7 @@ public function present() 'shopsTree' => $this->getShopsTree(), 'faq' => $this->getFaq(), 'language' => $this->psContext->getLanguage(), - 'prestashopCheckoutAjax' => (new LinkAdapter($this->psContext->getLink()))->getAdminLink('AdminAjaxPrestashopCheckout'), + 'prestashopCheckoutAjax' => $this->getGeneratedLink('AdminAjaxPrestashopCheckout'), 'translations' => $this->translations->getTranslations(), 'readmeUrl' => $this->getReadme(), 'cguUrl' => $this->getCgu(), @@ -170,6 +170,7 @@ public function present() 'countriesLink' => $this->getGeneratedLink('AdminCountries'), 'currenciesLink' => $this->getGeneratedLink('AdminCurrencies'), 'paymentPreferencesLink' => $this->getGeneratedLink($this->shopContext->isShop17() ? 'AdminPaymentPreferences' : 'AdminPayment'), + 'maintenanceLink' => $this->getGeneratedLink('AdminMaintenance'), 'overridesExist' => $this->overridesExist(), 'submitIdeaLink' => $this->getSubmitIdeaLink(), 'orderTotal' => (new OrderRepository())->count($this->psContext->getShopId()), From 2c2ecd9fe722dcf5b7cdae95e702f087cadb7595 Mon Sep 17 00:00:00 2001 From: boubkerbribri Date: Wed, 2 Aug 2023 16:38:13 +0200 Subject: [PATCH 26/31] test: add data-test for E2E tests on ajaxPaypalOrder.tpl --- views/templates/admin/ajaxPayPalOrder.tpl | 12 ++++++------ views/templates/admin/ajaxPayPalOrderLegacy.tpl | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/views/templates/admin/ajaxPayPalOrder.tpl b/views/templates/admin/ajaxPayPalOrder.tpl index 2b446fcfe..397ffd403 100644 --- a/views/templates/admin/ajaxPayPalOrder.tpl +++ b/views/templates/admin/ajaxPayPalOrder.tpl @@ -16,7 +16,7 @@ * @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 *} -
+
{if !$orderPayPal}
@@ -50,22 +50,22 @@

{l s='PayPal Order' mod='ps_checkout'}

{l s='Reference' mod='ps_checkout'}
-
{$orderPayPal.id|escape:'html':'UTF-8'}
+
{$orderPayPal.id|escape:'html':'UTF-8'}
{l s='Status' mod='ps_checkout'}
-
+
{$orderPayPal.status.translated|escape:'html':'UTF-8'}
{l s='Total' mod='ps_checkout'}
-
{$orderPayPal.total}
+
{$orderPayPal.total}
{l s='Balance' mod='ps_checkout'}
-
{$orderPayPal.balance}
+
{$orderPayPal.balance}
{l s='Payment mode' mod='ps_checkout'}
-
{$orderPaymentDisplayName|escape:'html':'UTF-8'} {$orderPaymentDisplayName|escape:'html':'UTF-8'}
+
{$orderPaymentDisplayName|escape:'html':'UTF-8'} {$orderPaymentDisplayName|escape:'html':'UTF-8'}
diff --git a/views/templates/admin/ajaxPayPalOrderLegacy.tpl b/views/templates/admin/ajaxPayPalOrderLegacy.tpl index 698ff896d..e0388a11a 100644 --- a/views/templates/admin/ajaxPayPalOrderLegacy.tpl +++ b/views/templates/admin/ajaxPayPalOrderLegacy.tpl @@ -16,7 +16,7 @@ * @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0 *} -
+
{if !$orderPayPal}
@@ -50,22 +50,22 @@

{l s='PayPal Order' mod='ps_checkout'}

{l s='Reference' mod='ps_checkout'}
-
{$orderPayPal.id|escape:'html':'UTF-8'}
+
{$orderPayPal.id|escape:'html':'UTF-8'}
{l s='Status' mod='ps_checkout'}
-
+
{$orderPayPal.status.translated|escape:'html':'UTF-8'}
{l s='Total' mod='ps_checkout'}
-
{$orderPayPal.total}
+
{$orderPayPal.total}
{l s='Balance' mod='ps_checkout'}
-
{$orderPayPal.balance}
+
{$orderPayPal.balance}
{l s='Payment mode' mod='ps_checkout'}
-
{$orderPaymentDisplayName|escape:'html':'UTF-8'} {$orderPaymentDisplayName|escape:'html':'UTF-8'}
+
{$orderPaymentDisplayName|escape:'html':'UTF-8'} {$orderPaymentDisplayName|escape:'html':'UTF-8'}
From bfe76e0bd19b24f94a80ae8ec6449c195480c457 Mon Sep 17 00:00:00 2001 From: boubkerbribri Date: Tue, 4 Jul 2023 16:55:16 +0200 Subject: [PATCH 27/31] test: add data-test on payment methods block --- views/templates/hook/adminAfterHeader/promotionBlock.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/templates/hook/adminAfterHeader/promotionBlock.tpl b/views/templates/hook/adminAfterHeader/promotionBlock.tpl index b737bfa5b..5255ee179 100644 --- a/views/templates/hook/adminAfterHeader/promotionBlock.tpl +++ b/views/templates/hook/adminAfterHeader/promotionBlock.tpl @@ -20,7 +20,7 @@
-
+

extension {l s='One module, all payments methods.' mod='ps_checkout'}

From f8c58babda73a63043a82104996316b162bf442b Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Tue, 8 Aug 2023 11:12:22 +0200 Subject: [PATCH 28/31] PAYSHIP-2420 --- .../QueryHandler/GetOrderForPaymentRefundedQueryHandler.php | 2 +- .../EventSubscriber/PayPalCaptureEventSubscriber.php | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Order/QueryHandler/GetOrderForPaymentRefundedQueryHandler.php b/src/Order/QueryHandler/GetOrderForPaymentRefundedQueryHandler.php index 4f1c51a39..3ba5b28b5 100644 --- a/src/Order/QueryHandler/GetOrderForPaymentRefundedQueryHandler.php +++ b/src/Order/QueryHandler/GetOrderForPaymentRefundedQueryHandler.php @@ -86,7 +86,7 @@ public function handle(GetOrderForPaymentRefundedQuery $query) (int) $order->getCurrentState(), (bool) $order->hasBeenPaid(), $this->hasBeenTotallyRefunded($totalRefund, $order), - (string) $order->getTotalProductsWithTaxes(), /* @phpstan-ignore-line */ + (string) $order->getTotalPaid(), (string) $totalRefund, (int) $order->id_currency ); diff --git a/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php b/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php index 4242e7683..c4979cc41 100644 --- a/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php +++ b/src/PayPal/Payment/Capture/EventSubscriber/PayPalCaptureEventSubscriber.php @@ -229,7 +229,11 @@ public function setPaymentRefundedOrderStatus(PayPalCaptureRefundedEvent $event) return; } - if ($this->checkOrderAmount->checkAmount($order->getTotalAmount(), $order->getTotalRefund()) == CheckOrderAmount::ORDER_NOT_FULL_PAID) { + $capture = $event->getCapture(); + // In case there no OrderSlip for this refund, we use the refund amount from payload + $totalRefunded = $order->getTotalRefund() ? $order->getTotalRefund() : $capture['amount']['value']; + + if ($this->checkOrderAmount->checkAmount($order->getTotalAmount(), $totalRefunded) === CheckOrderAmount::ORDER_NOT_FULL_PAID) { $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_PARTIALLY_REFUNDED))); } else { $this->commandBus->handle(new UpdateOrderStatusCommand($order->getOrderId()->getValue(), $this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_REFUNDED))); From d66f98c0ea705cdbb1b16a6d22b172087afdc9c0 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Tue, 8 Aug 2023 11:13:34 +0200 Subject: [PATCH 29/31] Http Unauthorized PS8 --- src/Api/Payment/Client/PaymentClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api/Payment/Client/PaymentClient.php b/src/Api/Payment/Client/PaymentClient.php index 4e8023412..ccb7781d2 100755 --- a/src/Api/Payment/Client/PaymentClient.php +++ b/src/Api/Payment/Client/PaymentClient.php @@ -155,7 +155,7 @@ private function postWithRetry(array $options, $delay = 2, $retries = 2) try { $response = parent::post($options); - if ($response['httpCode'] === 401) { + if ($response['httpCode'] === 401 || false !== strpos($response['exceptionMessage'], 'Unauthorized')) { throw new PsCheckoutException('Unauthorized', PsCheckoutException::PSCHECKOUT_HTTP_UNAUTHORIZED); } From 40184e0be7c0eca86ce2dca7c211e1a56084582e Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Wed, 9 Aug 2023 16:38:14 +0200 Subject: [PATCH 30/31] Fix CheckoutChecker --- src/Checkout/CheckoutChecker.php | 37 ++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/Checkout/CheckoutChecker.php b/src/Checkout/CheckoutChecker.php index 5fe0dd87f..e52f6190e 100644 --- a/src/Checkout/CheckoutChecker.php +++ b/src/Checkout/CheckoutChecker.php @@ -108,7 +108,10 @@ public function continueWithAuthorization($cartId, $orderPayPal) throw new PsCheckoutException(sprintf('Cart with id %s has no product. Cannot capture the order.', var_export($cart->id, true)), PsCheckoutException::CART_PRODUCT_MISSING); } - if (!$this->isAllProductsInStock($cart)) { + if (!$this->isAllProductsInStock($cart) + || !$this->checkAllProductsAreStillAvailableInThisState($cart) + || !$this->checkAllProductsHaveMinimalQuantities($cart) + ) { throw new PsCheckoutException(sprintf('Cart with id %s contains products unavailable. Cannot capture the order.', var_export($cart->id, true)), PsCheckoutException::CART_PRODUCT_UNAVAILABLE); } @@ -140,9 +143,7 @@ private function isAllProductsInStock(Cart $cart) } if (version_compare(_PS_VERSION_, '1.7.3.2', '>=')) { - return $cart->isAllProductsInStock() !== true || - (method_exists($cart, 'checkAllProductsAreStillAvailableInThisState') && $cart->checkAllProductsAreStillAvailableInThisState() !== true) || - (method_exists($cart, 'checkAllProductsHaveMinimalQuantities') && $cart->checkAllProductsHaveMinimalQuantities() !== true); + return $cart->isAllProductsInStock(); } foreach ($cart->getProducts() as $product) { @@ -159,4 +160,32 @@ private function isAllProductsInStock(Cart $cart) return true; } + + /** + * @param Cart $cart + * + * @return bool + */ + private function checkAllProductsAreStillAvailableInThisState(Cart $cart) + { + if (method_exists($cart, 'checkAllProductsAreStillAvailableInThisState')) { + return $cart->checkAllProductsAreStillAvailableInThisState(); + } + + return true; + } + + /** + * @param Cart $cart + * + * @return bool + */ + private function checkAllProductsHaveMinimalQuantities(Cart $cart) + { + if (method_exists($cart, 'checkAllProductsHaveMinimalQuantities')) { + return $cart->checkAllProductsHaveMinimalQuantities(); + } + + return true; + } } From d56c27d8fe097125b61a6f5549da3c340ff0ecc4 Mon Sep 17 00:00:00 2001 From: Matt75 <5262628+Matt75@users.noreply.github.com> Date: Wed, 9 Aug 2023 17:19:46 +0200 Subject: [PATCH 31/31] Fix upgrade script --- upgrade/upgrade-6.3.4.0.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/upgrade/upgrade-6.3.4.0.php b/upgrade/upgrade-6.3.4.0.php index f82d3b04f..48658a795 100644 --- a/upgrade/upgrade-6.3.4.0.php +++ b/upgrade/upgrade-6.3.4.0.php @@ -155,6 +155,8 @@ function upgrade_module_6_3_4_0($module) ] ); break; + default: + Configuration::updateGlobalValue($configuration_key, $id_order_state); } } else { Configuration::updateGlobalValue($configuration_key, $id_order_state);