From b8810bc5de05b040671517da467f25f045525bf9 Mon Sep 17 00:00:00 2001 From: toomas puur Date: Wed, 20 Sep 2023 18:48:40 +0200 Subject: [PATCH 1/3] shopware 6.5 compatibility --- composer.json | 7 +- src/Components/CustomObjectNormalizer.php | 6 +- src/Controller/Api/ApiTestController.php | 12 ++- .../Controller/IvyPaymentController.php | 71 +++++++---------- src/Core/IvyPayment/IvyCheckoutSession.php | 16 ++-- src/Express/Controller/ExpressController.php | 79 ++++++++++--------- src/Express/Service/ExpressService.php | 22 +++++- src/PaymentHandler/IvyPaymentHandler.php | 6 +- .../storefront/js/wizmo-gmbh-ivy-payment.js | 2 +- src/Resources/config/services.xml | 9 +-- .../config/{ => services}/components.xml | 3 +- .../config/{ => services}/controllers.xml | 3 +- .../config/{ => services}/loggers.xml | 2 +- .../config/{ => services}/subscribers.xml | 2 +- src/Services/IvyPaymentService.php | 27 +------ src/Setup/Uninstaller.php | 4 +- src/Subscriber/ButtonSubscriber.php | 3 +- src/Subscriber/ConfigSubscriber.php | 22 ++++-- src/WizmoGmbhIvyPayment.php | 27 ++++--- 19 files changed, 151 insertions(+), 172 deletions(-) rename src/Resources/config/{ => services}/components.xml (92%) rename src/Resources/config/{ => services}/controllers.xml (92%) rename src/Resources/config/{ => services}/loggers.xml (95%) rename src/Resources/config/{ => services}/subscribers.xml (96%) diff --git a/composer.json b/composer.json index c1c7ef5..d31ccfe 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "wizmogmbh/ivy-payment", "description": "Ivy - Sustainable Shopping", - "version": "1.2.6", + "version": "2.0.0", "type": "shopware-platform-plugin", "license": "proprietary", "authors": [ @@ -49,10 +49,7 @@ } }, "require": { - "php": "^7.4 || ^8.0", - "guzzlehttp/guzzle": ">=7.3", - "symfony/serializer": ">=5.0", - "shopware/core": ">=6.4.0,<6.5.0" + "shopware/core": "^6.5.0" }, "conflict": { "ivy/shopware-payment-plugin": "*" diff --git a/src/Components/CustomObjectNormalizer.php b/src/Components/CustomObjectNormalizer.php index f99ea2c..fdc16fd 100644 --- a/src/Components/CustomObjectNormalizer.php +++ b/src/Components/CustomObjectNormalizer.php @@ -4,17 +4,15 @@ namespace WizmoGmbh\IvyPayment\Components; -use Symfony\Component\Serializer\Exception\ExceptionInterface; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; class CustomObjectNormalizer extends ObjectNormalizer { /** * @param $object - * @param string|null $format - * @param array|null $context + * @param null $format + * @param array $context * @return array - * @throws ExceptionInterface */ public function normalize($object, $format = null, array $context = []): array { diff --git a/src/Controller/Api/ApiTestController.php b/src/Controller/Api/ApiTestController.php index 7e0a5d5..f28c19a 100644 --- a/src/Controller/Api/ApiTestController.php +++ b/src/Controller/Api/ApiTestController.php @@ -17,14 +17,12 @@ use Symfony\Component\Routing\Annotation\Route; use WizmoGmbh\IvyPayment\Components\Config\ConfigHandler; -/** - * @Route(defaults={"_routeScope"={"administration"}}) - */ +#[Route( + defaults: ["_routeScope" => ["administration"]] +)] class ApiTestController { - /** - * @Route(path="/api/_action/ivy-api-test/verify") - */ + #[Route('/api/_action/ivy-api-test/verify')] public function check(RequestDataBag $dataBag): JsonResponse { $env = $dataBag->get('environment'); @@ -70,7 +68,7 @@ private function checkIntegrationReady(string $url, string $apikey): array $ivyResponse = $client->post('merchant/app/check-integration-ready', $options); if ($ivyResponse->getStatusCode() === 200) { - $ivyResponseArray = \json_decode((string) $ivyResponse->getBody(), true); + $ivyResponseArray = \json_decode((string)$ivyResponse->getBody(), true); $response['success'] = $ivyResponseArray['ready']; $response['message'] = ''; diff --git a/src/Core/Checkout/Payment/Controller/IvyPaymentController.php b/src/Core/Checkout/Payment/Controller/IvyPaymentController.php index d79969b..046940f 100644 --- a/src/Core/Checkout/Payment/Controller/IvyPaymentController.php +++ b/src/Core/Checkout/Payment/Controller/IvyPaymentController.php @@ -9,6 +9,7 @@ namespace WizmoGmbh\IvyPayment\Core\Checkout\Payment\Controller; +use Doctrine\DBAL\Exception; use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Checkout\Payment\Cart\Token\TokenFactoryInterfaceV2; @@ -27,15 +28,13 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use WizmoGmbh\IvyPayment\Exception\IvyException; use WizmoGmbh\IvyPayment\Logger\IvyLogger; use WizmoGmbh\IvyPayment\Services\IvyPaymentService; use WizmoGmbh\IvyPayment\Express\Service\ExpressService; -use WizmoGmbh\IvyPayment\Components\Config\ConfigHandler; -use WizmoGmbh\IvyPayment\IvyApi\ApiClient; -/** - * @Route(defaults={"_routeScope"={"storefront"}}) - */ + +#[Route(defaults: ["_routeScope" => ["storefront"]])] class IvyPaymentController extends StorefrontController { private IvyPaymentService $paymentService; @@ -46,39 +45,32 @@ class IvyPaymentController extends StorefrontController private ExpressService $expressService; - private ConfigHandler $configHandler; - - private ApiClient $ivyApiClient; - /** * @param IvyPaymentService $paymentService * @param TokenFactoryInterfaceV2 $tokenFactoryInterfaceV2 * @param IvyLogger $logger * @param ExpressService $expressService - * @param ConfigHandler $configHandler - * @param ApiClient $ivyApiClient */ public function __construct( - IvyPaymentService $paymentService, + IvyPaymentService $paymentService, TokenFactoryInterfaceV2 $tokenFactoryInterfaceV2, - IvyLogger $logger, - ExpressService $expressService, - ConfigHandler $configHandler, - ApiClient $ivyApiClient - ) { + IvyLogger $logger, + ExpressService $expressService + ) + { $this->paymentService = $paymentService; - $this->configHandler = $configHandler; $this->tokenFactoryInterfaceV2 = $tokenFactoryInterfaceV2; $this->logger = $logger; $this->logger->setName('WEBHOOK'); $this->expressService = $expressService; - $this->ivyApiClient = $ivyApiClient; } + #[Route('/ivypayment/failed-transaction', + name: 'frontend.ivypayment.failed.transaction', + defaults: ["XmlHttpRequest" => true], + methods: ['POST', 'GET'] + )] /** - * @Since("6.0.0.0") - * @Route("/ivypayment/failed-transaction", name="frontend.ivypayment.failed.transaction", methods={"GET", "POST"}, defaults={"XmlHttpRequest"=true}) - * * @throws AsyncPaymentFinalizeException * @throws CustomerCanceledAsyncPaymentException * @throws InvalidTransactionException @@ -110,19 +102,22 @@ public function failedTransaction(Request $request, SalesChannelContext $salesCh return new RedirectResponse($finishUrl); } + #[Route('/ivypayment/update-transaction', + name: 'frontend.ivypayment.update.transaction', + defaults: ["XmlHttpRequest" => true, 'csrf_protected' => false, 'auth_required' => false], + methods: ['POST', 'GET'] + )] /** - * @Since("6.0.0.0") - * @Route("/ivypayment/update-transaction", name="ivypayment.update.transaction", methods={"GET", "POST"}, defaults={"XmlHttpRequest"=true,"csrf_protected"=false,"auth_required"=false}) - * * @throws AsyncPaymentFinalizeException * @throws CustomerCanceledAsyncPaymentException * @throws InvalidTransactionException * @throws TokenExpiredException - * @throws UnknownPaymentMethodException|\Doctrine\DBAL\Exception|\WizmoGmbh\IvyPayment\Exception\IvyException + * @throws UnknownPaymentMethodException|Exception|IvyException * @psalm-suppress InvalidArrayAccess */ public function updateTransaction(Request $request, RequestDataBag $inputData, SalesChannelContext $salesChannelContext): Response { + $this->logger->setName('WEBHOOK'); $type = $request->request->get('type'); /** @var array $payload */ $payload = $request->request->get('payload'); @@ -204,20 +199,6 @@ public function updateTransaction(Request $request, RequestDataBag $inputData, S /** @var OrderEntity $order */ [$order, $token] = $this->expressService->checkoutConfirm($inputData, $payload, $salesChannelContext); - $config = $this->configHandler->getFullConfig($salesChannelContext); - - $this->logger->info('update order over ivy api'); - $ivyResponse = $this->ivyApiClient->sendApiRequest('order/update', $config, \json_encode([ - 'id' => $ivyOrderId, - 'displayId' => $order->getOrderNumber(), - 'referenceId' => $order->getId(), - 'metadata' => [ - '_sw_payment_token' => $token, - 'shopwareOrderId' => $order->getOrderNumber() - ] - ])); - $this->logger->info('ivy response: ' . \print_r($ivyResponse, true)); - $outputData = [ "success" => true ]; @@ -242,14 +223,16 @@ public function updateTransaction(Request $request, RequestDataBag $inputData, S } $this->logger->debug('webhook finished <== ' . $type); - + return new JsonResponse(null, Response::HTTP_OK); } + #[Route('/ivypayment/finalize-transaction', + name: 'frontend.ivypayment.finalize.transaction', + defaults: ["XmlHttpRequest" => true], + methods: ['POST', 'GET'] + )] /** - * @Since("6.0.0.0") - * @Route("/ivypayment/finalize-transaction", name="frontend.ivypayment.finalize.transaction", methods={"GET", "POST"}, defaults={"XmlHttpRequest"=true}) - * * @throws AsyncPaymentFinalizeException * @throws CustomerCanceledAsyncPaymentException * @throws InvalidTransactionException diff --git a/src/Core/IvyPayment/IvyCheckoutSession.php b/src/Core/IvyPayment/IvyCheckoutSession.php index 967b3f1..23e0cef 100644 --- a/src/Core/IvyPayment/IvyCheckoutSession.php +++ b/src/Core/IvyPayment/IvyCheckoutSession.php @@ -13,8 +13,6 @@ use Shopware\Core\Framework\Uuid\Uuid; use Shopware\Core\PlatformRequest; use Shopware\Core\System\SalesChannel\SalesChannelContext; -use Shopware\Storefront\Framework\Routing\Router; -use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Serializer; @@ -34,17 +32,14 @@ class IvyCheckoutSession private string $version; - private RouterInterface $router; - public function __construct( - EntityRepository $pluginRepository, - ConfigHandler $configHandler, + EntityRepository $pluginRepository, + ConfigHandler $configHandler, createIvyOrderData $createIvyOrderData, - ApiClient $ivyApiClient, - RouterInterface $router - ) { + ApiClient $ivyApiClient, + ) + { $this->configHandler = $configHandler; - $this->router = $router; $this->createIvyOrderData = $createIvyOrderData; $this->ivyApiClient = $ivyApiClient; $encoders = [new XmlEncoder(), new JsonEncoder()]; @@ -62,6 +57,7 @@ public function __construct( * @param SalesChannelContext $salesChannelContext * @param bool $express * @param OrderEntity|null $order + * @param Cart|null $cart * @return string * @throws Exception * @throws IvyApiException diff --git a/src/Express/Controller/ExpressController.php b/src/Express/Controller/ExpressController.php index fa0818a..c062c78 100644 --- a/src/Express/Controller/ExpressController.php +++ b/src/Express/Controller/ExpressController.php @@ -24,9 +24,9 @@ use WizmoGmbh\IvyPayment\IvyApi\ApiClient; use WizmoGmbh\IvyPayment\Logger\IvyLogger; -/** - * @Route(defaults={"_routeScope"={"storefront"}}) - */ +#[Route( + defaults: ["_routeScope" => ["storefront"]] +)] class ExpressController extends StorefrontController { @@ -52,12 +52,12 @@ class ExpressController extends StorefrontController */ public function __construct ( - ExpressService $expressService, - ConfigHandler $configHandler, - IvyLogger $logger, + ExpressService $expressService, + ConfigHandler $configHandler, + IvyLogger $logger, IvyCheckoutSession $ivyCheckoutSession, - CartService $cartService, - ApiClient $ivyApiClient + CartService $cartService, + ApiClient $ivyApiClient ) { $this->expressService = $expressService; @@ -68,17 +68,21 @@ public function __construct $this->ivyApiClient = $ivyApiClient; } - /** - * @Route("/ivycheckout/start", name="frontend.ivycheckout.start", methods={"GET"}, defaults={"XmlHttpRequest"=true}) - */ + #[Route('/ivycheckout/start', + name: 'frontend.ivycheckout.start', + defaults: ["XmlHttpRequest" => true], + methods: ['GET'] + )] public function checkoutStart(Request $request, SalesChannelContext $salesChannelContext): Response { return $this->_checkoutStart($request->getSession()->get(PlatformRequest::HEADER_CONTEXT_TOKEN), $salesChannelContext, false); } - /** - * @Route("/ivyexpress/start", name="frontend.ivyexpress.start", methods={"GET"}, defaults={"XmlHttpRequest"=true}) - */ + #[Route('/ivyexpress/start', + name: 'frontend.ivyexpress.start', + defaults: ["XmlHttpRequest" => true], + methods: ['GET'] + )] public function expressStart(Request $request, SalesChannelContext $salesChannelContext): Response { return $this->_checkoutStart($request->getSession()->get(PlatformRequest::HEADER_CONTEXT_TOKEN), $salesChannelContext, true); @@ -109,13 +113,12 @@ public function _checkoutStart(string $contextToken, SalesChannelContext $salesC return new IvyJsonResponse($data); } + #[Route('/ivyexpress/callback', + name: 'frontend.ivyexpress.callback', + defaults: ["XmlHttpRequest" => true, 'csrf_protected' => false, 'auth_required' => false], + methods: ['POST', 'GET'] + )] /** - * @Route("/ivyexpress/callback", name="frontend.ivyexpress.callback", methods={"POST", "GET"}, - * defaults={ - * "XmlHttpRequest"=true, - * "csrf_protected"=false, - * "auth_required"=false, - * }) * @throws Exception */ public function callback(Request $request, RequestDataBag $inputData, SalesChannelContext $salesChannelContext): Response @@ -139,8 +142,7 @@ public function callback(Request $request, RequestDataBag $inputData, SalesChann $this->logger->info('found context token ' . $contextToken); $salesChannelContext = $this->expressService->reloadContext($salesChannelContext, $contextToken); $this->logger->info( - 'loaded context with token : ' . $salesChannelContext->getToken( - ) . ' customerId: ' . $this->getCustomerIdFromContext($salesChannelContext) + 'loaded context with token : ' . $salesChannelContext->getToken() . ' customerId: ' . $this->getCustomerIdFromContext($salesChannelContext) ); if (\is_array($shipping) && isset($shipping['shippingAddress'])) { @@ -161,8 +163,7 @@ public function callback(Request $request, RequestDataBag $inputData, SalesChann $contextToken ); $this->logger->info( - 'loaded new context. Token: ' . $salesChannelContext->getToken( - ) . ', customerId: ' . $this->getCustomerIdFromContext($salesChannelContext) + 'loaded new context. Token: ' . $salesChannelContext->getToken() . ', customerId: ' . $this->getCustomerIdFromContext($salesChannelContext) ); $this->logger->info('save new context token'); @@ -201,7 +202,7 @@ public function callback(Request $request, RequestDataBag $inputData, SalesChann $discount = $data['discount'] ?? null; if (\is_array($discount) && isset($discount['voucher'])) { - $voucherCode = (string) $discount['voucher']; + $voucherCode = (string)$discount['voucher']; try { $this->expressService->addPromotion($voucherCode, $salesChannelContext, $outputData); } catch (\Exception $e) { @@ -230,7 +231,7 @@ public function callback(Request $request, RequestDataBag $inputData, SalesChann \ini_set('serialize_precision', '-1'); $response = new IvyJsonResponse($outputData); - $signature = $this->expressService->sign((string) $response->getContent(), $salesChannelContext); + $signature = $this->expressService->sign((string)$response->getContent(), $salesChannelContext); $response->headers->set('X-Ivy-Signature', $signature); $this->logger->info('output body:' . $response->getContent()); @@ -239,13 +240,12 @@ public function callback(Request $request, RequestDataBag $inputData, SalesChann } + #[Route('/ivyexpress/confirm', + name: 'frontend.ivyexpress.confirm', + defaults: ["XmlHttpRequest" => true, 'csrf_protected' => false, 'auth_required' => false], + methods: ['POST', 'GET'] + )] /** - * @Route("/ivyexpress/confirm", name="frontend.ivyexpress.confirm", methods={"POST", "GET"}, - * defaults={ - * "XmlHttpRequest"=true, - * "csrf_protected"=false, - * "auth_required"=false, - * }) * @throws Exception */ public function confirmAction(Request $request, RequestDataBag $inputData, SalesChannelContext $salesChannelContext): Response @@ -281,7 +281,7 @@ public function confirmAction(Request $request, RequestDataBag $inputData, Sales 'displayId' => $existingOrder->getOrderNumber(), 'metadata' => $payload['metadata'], ]); - $signature = $this->expressService->sign(\stripslashes((string) $response->getContent()), $salesChannelContext); + $signature = $this->expressService->sign(\stripslashes((string)$response->getContent()), $salesChannelContext); $response->headers->set('X-Ivy-Signature', $signature); return $response; } @@ -319,7 +319,7 @@ public function confirmAction(Request $request, RequestDataBag $inputData, Sales \ini_set('serialize_precision', '-1'); $response = new IvyJsonResponse($outputData); - $signature = $this->expressService->sign(\stripslashes((string) $response->getContent()), $salesChannelContext); + $signature = $this->expressService->sign(\stripslashes((string)$response->getContent()), $salesChannelContext); if ($errorStatus !== null) { $response->setStatusCode($errorStatus); } @@ -329,9 +329,10 @@ public function confirmAction(Request $request, RequestDataBag $inputData, Sales return $response; } - /** - * @Route("/ivyexpress/finish", name="frontend.ivyexpress.finish", methods={"GET"}) - */ + #[Route('/ivyexpress/finish', + name: 'frontend.ivyexpress.finish', + methods: ['GET'] + )] public function finishAction(Request $request, RequestDataBag $inputData, SalesChannelContext $salesChannelContext): Response { $this->logger->setLevel($this->configHandler->getLogLevel($salesChannelContext)); @@ -362,7 +363,7 @@ public function finishAction(Request $request, RequestDataBag $inputData, SalesC switch ($status) { case 'paid'; case 'waiting_for_payment': - [ $swOrder, $token ] = $this->expressService->checkoutConfirm($inputData, $payload, $salesChannelContext); + [$swOrder, $token] = $this->expressService->checkoutConfirm($inputData, $payload, $salesChannelContext); break; case 'canceled': case 'failed': @@ -373,7 +374,7 @@ public function finishAction(Request $request, RequestDataBag $inputData, SalesC } if ($swOrder instanceof OrderEntity) { - return $this->redirectToRoute('frontend.checkout.finish.page',['orderId' => $swOrder->getId()]); + return $this->redirectToRoute('frontend.checkout.finish.page', ['orderId' => $swOrder->getId()]); } $this->logger->info('order is not created'); } catch (\Throwable $e) { diff --git a/src/Express/Service/ExpressService.php b/src/Express/Service/ExpressService.php index d37eac4..7ca81fc 100644 --- a/src/Express/Service/ExpressService.php +++ b/src/Express/Service/ExpressService.php @@ -41,6 +41,7 @@ use WizmoGmbh\IvyPayment\Components\Config\ConfigHandler; use WizmoGmbh\IvyPayment\Core\IvyPayment\createIvyOrderData; use WizmoGmbh\IvyPayment\Exception\IvyException; +use WizmoGmbh\IvyPayment\IvyApi\ApiClient; use WizmoGmbh\IvyPayment\PaymentHandler\IvyPaymentHandler; use function hash_hmac; use function json_decode; @@ -85,6 +86,8 @@ class ExpressService private RegisterRoute $registerRoute; + private ApiClient $ivyApiClient; + /** * @param EntityRepository $salesChannelRepo * @param EntityRepository $paymentRepository @@ -123,7 +126,8 @@ public function __construct( AbstractShippingMethodRoute $shippingMethodRoute, SalesChannelProxyController $salesChannelProxyController, Logger $logger, - AbstractRegisterRoute $registerRoute + AbstractRegisterRoute $registerRoute, + ApiClient $ivyApiClient ) { $this->systemConfigService = $systemConfigService; $this->salesChannelRepo = $salesChannelRepo; @@ -147,6 +151,7 @@ public function __construct( $plugin = $pluginRepository->search($criteria, Context::createDefaultContext())->first(); $this->version = $plugin->getVersion(); $this->registerRoute = $registerRoute; + $this->ivyApiClient = $ivyApiClient; } /** @@ -534,6 +539,21 @@ public function checkoutConfirm( $this->logger->info('created order: '. $order->getOrderNumber()); $this->logger->info('update ivy order with new referenceId: ' . $order->getId()); + $config = $this->configHandler->getFullConfig($salesChannelContext); + + $this->logger->info('update order over ivy api'); + $ivyOrderId = $payload['id']; + $ivyResponse = $this->ivyApiClient->sendApiRequest('order/update', $config, \json_encode([ + 'id' => $ivyOrderId, + 'displayId' => $order->getOrderNumber(), + 'referenceId' => $order->getId(), + 'metadata' => [ + '_sw_payment_token' => $paymentToken, + 'shopwareOrderId' => $order->getOrderNumber() + ] + ])); + $this->logger->info('ivy response: ' . \print_r($ivyResponse, true)); + return [ $order, $paymentToken diff --git a/src/PaymentHandler/IvyPaymentHandler.php b/src/PaymentHandler/IvyPaymentHandler.php index 2881a71..3f5a8eb 100644 --- a/src/PaymentHandler/IvyPaymentHandler.php +++ b/src/PaymentHandler/IvyPaymentHandler.php @@ -207,7 +207,9 @@ private function getToken(string $returnUrl): ?string } /** - * @return OrderEntity|null + * @param string $id + * @param SalesChannelContext $salesChannelContext + * @return OrderEntity */ private function getOrderById(string $id, SalesChannelContext $salesChannelContext): OrderEntity { @@ -216,9 +218,7 @@ private function getOrderById(string $id, SalesChannelContext $salesChannelConte ->addAssociation('transactions.paymentMethod') ->addAssociation('deliveries.shippingMethod') ->addAssociation('orderCustomer.customer') - ->addAssociation('lineItems') ->addAssociation('lineItems.cover') - ->addAssociation('addresses') ->addAssociation('currency') ->addAssociation('addresses.country') ->addAssociation('addresses.countryState') diff --git a/src/Resources/app/storefront/dist/storefront/js/wizmo-gmbh-ivy-payment.js b/src/Resources/app/storefront/dist/storefront/js/wizmo-gmbh-ivy-payment.js index b7496ae..debc379 100644 --- a/src/Resources/app/storefront/dist/storefront/js/wizmo-gmbh-ivy-payment.js +++ b/src/Resources/app/storefront/dist/storefront/js/wizmo-gmbh-ivy-payment.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([["wizmo-gmbh-ivy-payment"],{VEPr:function(t,e,n){"use strict";function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;n0}},{key:"_openOffcanvas",value:function(e,n){c.a.isActive("v6.5.0.0")?setTimeout((function(){t.bsOffcanvas.show(),window.history.pushState("offcanvas-open",""),"function"==typeof n&&n()}),75):setTimeout((function(){i.c.create((function(){e.classList.add(p),window.history.pushState("offcanvas-open",""),"function"==typeof n&&n()}))}),75)}},{key:"_registerEvents",value:function(e,n){var r=this,u=o.a.isTouchDevice()?"touchend":"click";if(c.a.isActive("v6.5.0.0")){var f=this.getOffCanvas();e||(t.bsOffcanvas._backdrop._config.clickCallback=function(){}),a.a.iterate(f,(function(t){t.addEventListener("hide.bs.offcanvas",(function e(){setTimeout((function(){r._removeExistingOffCanvas(),r.$emitter.publish("onCloseOffcanvas",{offCanvasContent:f})}),n),t.removeEventListener("hide.bs.offcanvas",e)}))}))}else if(e){document.addEventListener(i.a.ON_CLICK,(function t(){r.close(n),document.removeEventListener(i.a.ON_CLICK,t)}))}window.addEventListener("popstate",this.close.bind(this,n),{once:!0});var s=document.querySelectorAll(".".concat("js-offcanvas-close"));a.a.iterate(s,(function(t){return t.addEventListener(u,r.close.bind(r,n))}))}},{key:"_removeExistingOffCanvas",value:function(){var t=this.getOffCanvas();return a.a.iterate(t,(function(t){return t.remove()}))}},{key:"_getPositionClass",value:function(t){return c.a.isActive("v6.5.0.0")?"left"===t?"offcanvas-start":"right"===t?"offcanvas-end":"offcanvas-".concat(t):"is-".concat(t)}},{key:"_createOffCanvas",value:function(e,n,o){var r=document.createElement("div");if(r.classList.add(y),r.classList.add(this._getPositionClass(e)),!0===n&&r.classList.add("is-fullwidth"),o){var i=u(o);if("string"===i)r.classList.add(o);else{if(!Array.isArray(o))throw new Error('The type "'.concat(i,'" is not supported. Please pass an array or a string.'));o.forEach((function(t){r.classList.add(t)}))}}return document.body.appendChild(r),c.a.isActive("v6.5.0.0")&&(t.bsOffcanvas=new bootstrap.Offcanvas(r)),r}}]),t}(),h=Object.freeze(new d),b=function(){function t(){f(this,t)}return l(t,null,[{key:"open",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"left",o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:v,i=arguments.length>5&&void 0!==arguments[5]&&arguments[5],a=arguments.length>6&&void 0!==arguments[6]?arguments[6]:"";h.open(t,e,n,o,r,i,a)}},{key:"setContent",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:v;h.setContent(t,e,n)}},{key:"setAdditionalClassName",value:function(t){h.setAdditionalClassName(t)}},{key:"close",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:v;h.close(t)}},{key:"exists",value:function(){return h.exists()}},{key:"getOffCanvas",value:function(){return h.getOffCanvas()}},{key:"REMOVE_OFF_CANVAS_DELAY",value:function(){return v}}]),t}()},lpb5:function(t,e,n){"use strict";n.d(e,"a",(function(){return v}));var o=n("bK22"),r=n("k8s9"),i=n("5lm9");function a(t){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function c(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function u(t,e){for(var n=0;n0&&void 0!==arguments[0]&&arguments[0],e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"left",i=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],a=arguments.length>5&&void 0!==arguments[5]?arguments[5]:o.b.REMOVE_OFF_CANVAS_DELAY(),c=arguments.length>6&&void 0!==arguments[6]&&arguments[6],u=arguments.length>7&&void 0!==arguments[7]?arguments[7]:"";if(!t)throw new Error("A url must be given!");o.a._removeExistingOffCanvas();var f=o.a._createOffCanvas(r,c,u);this.setContent(t,e,n,i,a),o.a._openOffcanvas(f)}},{key:"setContent",value:function(t,n,o,a,c){var u=this,f=new r.a;s(l(e),"setContent",this).call(this,'
'.concat(i.a.getTemplate(),"
"),a,c),p&&p.abort();var y=function(t){s(l(e),"setContent",u).call(u,t,a,c),"function"==typeof o&&o(t)};p=n?f.post(t,n,e.executeCallback.bind(this,y)):f.get(t,e.executeCallback.bind(this,y))}},{key:"executeCallback",value:function(t,e){"function"==typeof t&&t(e),window.PluginManager.initializePlugins()}}],(a=null)&&u(n.prototype,a),v&&u(n,v),e}(o.b)}},[["VEPr","runtime","vendor-node","vendor-shared"]]]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([["wizmo-gmbh-ivy-payment"],{4608:(t,e,s)=>{var n=s(6285);class a extends n.Z{init(){var t=this.el.getElementsByTagName("template");Array.from(t).forEach((t=>{let e=Array.from(document.querySelectorAll("script")).map((t=>t.src));t.dataset.src&&(e.includes(t.dataset.src)?this.docLoaded():this.loadScript(t,this.docLoaded))}))}loadScript(t,e){var s=document.createElement("script");s.defer=!0,s.type="text/javascript",s.onreadystatechange=e,s.onload=e,s.src=t.dataset.src,document.head.append(s)}docLoaded(){window.document.dispatchEvent(new Event("DOMContentLoaded",{bubbles:!0,cancelable:!0}))}}var o=s(8254),i=s(1966),r=s(2615),c=s(4690);var d=s(3206);const f=window.PluginManager;f.register("IvyPaymentOffcanvasCart",a,"#IvyOffcanvasCart"),f.register("IvyExpressCheckoutPlugin",class extends a{init(){super.init(),this._client=new o.Z,this.addEventListeners()}addEventListeners(){this.el.addEventListener("click",this.createSession.bind(this))}createSession(){if(c.Z.create(document.body),r.Z.close(),this.el.dataset.addToIvycart){const t=document.querySelector("#productDetailPageBuyProductForm");t&&fetch(t.action,{method:t.method,body:new FormData(t)}).then(function(t){t.ok?(this._fetchCartWidgets(),this.openIviPopup()):c.Z.remove(document.body)}.bind(this))}else this.openIviPopup()}_fetchCartWidgets(){const t=PluginManager.getPluginInstances("CartWidget");i.Z.iterate(t,(t=>t.fetch())),this.$emitter.publish("fetchCartWidgets")}openIviPopup(){this._client.get(this.el.dataset.action,(function(t){c.Z.remove(document.body);let e=JSON.parse(t);e.redirectUrl?"function"==typeof startIvyCheckout?startIvyCheckout(e.redirectUrl,"popup"):console.error("startIvyCheckout is not defined"):(console.error("cannot create ivy session"),location.reload())}))}},".ivy--express-checkout-btn"),f.register("IvyCheckoutConfirmPlugin",class extends a{init(){super.init(),this._client=new o.Z,this.confirmOrderForm=d.Z.querySelector(document,"#confirmOrderForm"),this.confirmFormSubmit=d.Z.querySelector(document,'#confirmOrderForm button[type="submit"]'),this.confirmFormSubmit.addEventListener("click",this.onConfirmOrderSubmit.bind(this))}onConfirmOrderSubmit(){this.confirmOrderForm.checkValidity()&&(event.preventDefault(),this.createSession())}createSession(){c.Z.create(document.body),r.Z.close(),this._client.get(this.el.dataset.action,(function(t){c.Z.remove(document.body);let e=JSON.parse(t);e.redirectUrl?"function"==typeof startIvyCheckout?startIvyCheckout(e.redirectUrl,"popup"):console.error("startIvyCheckout is not defined"):(console.error("cannot create ivy session"),location.reload())}))}},'[data-ivy-checkout="true"]'),f.register("IvyPaymentMethod",a,"#ivy-payment-method")},2615:(t,e,s)=>{s.d(e,{Z:()=>r});var n=s(3637),a=s(8254),o=s(7906);let i=null;class r extends n.Z{static open(t=!1,e=!1,s=null,a="left",o=!0,i=n.Z.REMOVE_OFF_CANVAS_DELAY(),r=!1,c=""){if(!t)throw new Error("A url must be given!");n.r._removeExistingOffCanvas();const d=n.r._createOffCanvas(a,r,c,o);this.setContent(t,e,s,o,i),n.r._openOffcanvas(d)}static setContent(t,e,s,n,c){const d=new a.Z;super.setContent(`
${o.Z.getTemplate()}
`,n,c),i&&i.abort();const f=t=>{super.setContent(t,n,c),"function"==typeof s&&s(t)};i=e?d.post(t,e,r.executeCallback.bind(this,f)):d.get(t,r.executeCallback.bind(this,f))}static executeCallback(t,e){"function"==typeof t&&t(e),window.PluginManager.initializePlugins()}}},3637:(t,e,s)=>{s.d(e,{Z:()=>f,r:()=>d});var n=s(9658),a=s(2005),o=s(1966);const i="offcanvas",r=350;class c{constructor(){this.$emitter=new a.Z}open(t,e,s,n,a,o,i){this._removeExistingOffCanvas();const r=this._createOffCanvas(s,o,i,n);this.setContent(t,n,a),this._openOffcanvas(r,e)}setContent(t,e,s){const n=this.getOffCanvas();n[0]&&(n[0].innerHTML=t,this._registerEvents(s))}setAdditionalClassName(t){this.getOffCanvas()[0].classList.add(t)}getOffCanvas(){return document.querySelectorAll(`.${i}`)}close(t){const e=this.getOffCanvas();o.Z.iterate(e,(t=>{bootstrap.Offcanvas.getInstance(t).hide()})),setTimeout((()=>{this.$emitter.publish("onCloseOffcanvas",{offCanvasContent:e})}),t)}goBackInHistory(){window.history.back()}exists(){return this.getOffCanvas().length>0}_openOffcanvas(t,e){c.bsOffcanvas.show(),window.history.pushState("offcanvas-open",""),"function"==typeof e&&e()}_registerEvents(t){const e=n.Z.isTouchDevice()?"touchend":"click",s=this.getOffCanvas();o.Z.iterate(s,(e=>{const n=()=>{setTimeout((()=>{e.remove(),this.$emitter.publish("onCloseOffcanvas",{offCanvasContent:s})}),t),e.removeEventListener("hide.bs.offcanvas",n)};e.addEventListener("hide.bs.offcanvas",n)})),window.addEventListener("popstate",this.close.bind(this,t),{once:!0});const a=document.querySelectorAll(".js-offcanvas-close");o.Z.iterate(a,(s=>s.addEventListener(e,this.close.bind(this,t))))}_removeExistingOffCanvas(){c.bsOffcanvas=null;const t=this.getOffCanvas();return o.Z.iterate(t,(t=>t.remove()))}_getPositionClass(t){return"left"===t?"offcanvas-start":"right"===t?"offcanvas-end":`offcanvas-${t}`}_createOffCanvas(t,e,s,n){const a=document.createElement("div");if(a.classList.add(i),a.classList.add(this._getPositionClass(t)),!0===e&&a.classList.add("is-fullwidth"),s){const t=typeof s;if("string"===t)a.classList.add(s);else{if(!Array.isArray(s))throw new Error(`The type "${t}" is not supported. Please pass an array or a string.`);s.forEach((t=>{a.classList.add(t)}))}}return document.body.appendChild(a),c.bsOffcanvas=new bootstrap.Offcanvas(a,{backdrop:!1!==n||"static"}),a}}const d=Object.freeze(new c);class f{static open(t,e=null,s="left",n=!0,a=350,o=!1,i=""){d.open(t,e,s,n,a,o,i)}static setContent(t,e=!0,s=350){d.setContent(t,e,s)}static setAdditionalClassName(t){d.setAdditionalClassName(t)}static close(t=350){d.close(t)}static exists(){return d.exists()}static getOffCanvas(){return d.getOffCanvas()}static REMOVE_OFF_CANVAS_DELAY(){return r}}}},t=>{t.O(0,["vendor-node","vendor-shared"],(()=>{return e=4608,t(t.s=e);var e}));t.O()}]); \ No newline at end of file diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index eacffb3..2b5e60b 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -2,13 +2,10 @@ + xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd"> - - - - + @@ -19,7 +16,6 @@ - @@ -47,6 +43,7 @@ + diff --git a/src/Resources/config/components.xml b/src/Resources/config/services/components.xml similarity index 92% rename from src/Resources/config/components.xml rename to src/Resources/config/services/components.xml index 5afee1d..3d0d40c 100644 --- a/src/Resources/config/components.xml +++ b/src/Resources/config/services/components.xml @@ -2,7 +2,7 @@ + xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd"> @@ -24,7 +24,6 @@ - diff --git a/src/Resources/config/controllers.xml b/src/Resources/config/services/controllers.xml similarity index 92% rename from src/Resources/config/controllers.xml rename to src/Resources/config/services/controllers.xml index ac6227b..6006652 100644 --- a/src/Resources/config/controllers.xml +++ b/src/Resources/config/services/controllers.xml @@ -2,7 +2,7 @@ + xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd"> @@ -16,7 +16,6 @@ - diff --git a/src/Resources/config/loggers.xml b/src/Resources/config/services/loggers.xml similarity index 95% rename from src/Resources/config/loggers.xml rename to src/Resources/config/services/loggers.xml index b85ea89..19d18b1 100644 --- a/src/Resources/config/loggers.xml +++ b/src/Resources/config/services/loggers.xml @@ -2,7 +2,7 @@ + xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd"> diff --git a/src/Resources/config/subscribers.xml b/src/Resources/config/services/subscribers.xml similarity index 96% rename from src/Resources/config/subscribers.xml rename to src/Resources/config/services/subscribers.xml index 88f8881..5590b21 100644 --- a/src/Resources/config/subscribers.xml +++ b/src/Resources/config/services/subscribers.xml @@ -2,7 +2,7 @@ + xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd"> diff --git a/src/Services/IvyPaymentService.php b/src/Services/IvyPaymentService.php index b829294..39f5da5 100644 --- a/src/Services/IvyPaymentService.php +++ b/src/Services/IvyPaymentService.php @@ -17,12 +17,10 @@ use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\PaymentHandlerRegistry; use Shopware\Core\Checkout\Payment\Exception\AsyncPaymentFinalizeException; use Shopware\Core\Checkout\Payment\Exception\AsyncPaymentProcessException; -use Shopware\Core\Checkout\Payment\Exception\CustomerCanceledAsyncPaymentException; use Shopware\Core\Checkout\Payment\Exception\InvalidTransactionException; use Shopware\Core\Checkout\Payment\Exception\PaymentProcessException; use Shopware\Core\Checkout\Payment\Exception\TokenExpiredException; use Shopware\Core\Checkout\Payment\Exception\UnknownPaymentMethodException; -use Shopware\Core\Checkout\Payment\PaymentMethodEntity; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; @@ -33,8 +31,6 @@ class IvyPaymentService { - private EntityRepository $paymentMethodRepository; - private PaymentHandlerRegistry $paymentHandlerRegistry; private EntityRepository $orderTransactionRepository; @@ -44,13 +40,11 @@ class IvyPaymentService private LoggerInterface $logger; public function __construct( - EntityRepository $paymentMethodRepository, PaymentHandlerRegistry $paymentHandlerRegistry, EntityRepository $orderTransactionRepository, OrderTransactionStateHandler $transactionStateHandler, LoggerInterface $logger ) { - $this->paymentMethodRepository = $paymentMethodRepository; $this->paymentHandlerRegistry = $paymentHandlerRegistry; $this->orderTransactionRepository = $orderTransactionRepository; $this->transactionStateHandler = $transactionStateHandler; @@ -68,14 +62,14 @@ public function __construct( */ public function updateTransaction(string $transactionId, string $paymentMethodId, Request $request, SalesChannelContext $context): void { - if ($transactionId === null || !Uuid::isValid($transactionId)) { + if (!Uuid::isValid($transactionId)) { throw new AsyncPaymentProcessException((string) $transactionId, "No valid orderTransactionId was provided."); } $transaction = $this->getPaymentTransactionStruct($transactionId, $context->getContext()); /** @var IvyPaymentHandler $paymentHandler */ - $paymentHandler = $this->getPaymentHandlerById($paymentMethodId ?? '', $context->getContext()); + $paymentHandler = $this->paymentHandlerRegistry->getAsyncPaymentHandler($paymentMethodId); if ($paymentHandler === null) { throw new UnknownPaymentMethodException($paymentMethodId); @@ -93,23 +87,6 @@ public function cancelPayment(string $transactionId, SalesChannelContext $contex $this->transactionStateHandler->cancel($transactionId, $context->getContext()); } - /** - * @throws UnknownPaymentMethodException - */ - private function getPaymentHandlerById(string $paymentMethodId, Context $context): ?AsynchronousPaymentHandlerInterface - { - $criteria = new Criteria([$paymentMethodId]); - $criteria->addAssociation('appPaymentMethod.app'); - $paymentMethods = $this->paymentMethodRepository->search($criteria, $context); - - /** @var PaymentMethodEntity|null $paymentMethod */ - $paymentMethod = $paymentMethods->get($paymentMethodId); - if ($paymentMethod === null) { - throw new UnknownPaymentMethodException($paymentMethodId); - } - - return $this->paymentHandlerRegistry->getAsyncHandlerForPaymentMethod($paymentMethod); - } /** * @throws InvalidTransactionException diff --git a/src/Setup/Uninstaller.php b/src/Setup/Uninstaller.php index 589d556..d7d7af8 100644 --- a/src/Setup/Uninstaller.php +++ b/src/Setup/Uninstaller.php @@ -29,8 +29,8 @@ public function uninstall(UninstallContext $context, array $tables): void } foreach ($tables as $table) { - if ($this->connection->getSchemaManager()->tablesExist([$table])) { - $this->connection->getSchemaManager()->dropTable($table); + if ($this->connection->createSchemaManager()->tablesExist([$table])) { + $this->connection->createSchemaManager()->dropTable($table); } } } diff --git a/src/Subscriber/ButtonSubscriber.php b/src/Subscriber/ButtonSubscriber.php index 38c7706..994f04d 100644 --- a/src/Subscriber/ButtonSubscriber.php +++ b/src/Subscriber/ButtonSubscriber.php @@ -10,6 +10,7 @@ namespace WizmoGmbh\IvyPayment\Subscriber; +use Doctrine\DBAL\Exception; use Shopware\Core\Checkout\Payment\PaymentMethodEntity; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; @@ -51,7 +52,7 @@ public static function getSubscribedEvents(): array /** * @param PageLoadedEvent $event * @return void - * @throws \Doctrine\DBAL\Exception + * @throws Exception */ public function onIvyButtonLoaded(PageLoadedEvent $event): void { diff --git a/src/Subscriber/ConfigSubscriber.php b/src/Subscriber/ConfigSubscriber.php index 6ba7543..8cd6dd1 100644 --- a/src/Subscriber/ConfigSubscriber.php +++ b/src/Subscriber/ConfigSubscriber.php @@ -88,7 +88,13 @@ public function onResponse(ResponseEvent $event): void try { $this->updateMerchant($salesChannelId, false); } catch (\Exception $e) { - $errors[] = $e->getMessage(); + $errors[] = [ + 'code' => 'message-default', + 'detail' => $e->getMessage(), + 'source' => $e->getTrace(), + 'status' => $e->getCode(), + 'title' => $e->getMessage() + ]; } } @@ -96,13 +102,19 @@ public function onResponse(ResponseEvent $event): void try { $this->updateMerchant($salesChannelId, true); } catch (\Exception $e) { - $errors[] = $e->getMessage(); + $errors[] = [ + 'code' => 'message-default', + 'detail' => $e->getMessage(), + 'source' => $e->getTrace(), + 'status' => $e->getCode(), + 'title' => $e->getMessage() + ]; } } if (!empty($errors)) { $event->setResponse(new JsonResponse([ - 'errors' => \implode('; ', $errors), - ], Response::HTTP_BAD_REQUEST)); + 'errors' => json_encode($errors), + ], Response::HTTP_UNAUTHORIZED)); } } } @@ -120,7 +132,7 @@ private function updateMerchant(?string $salesChannelId, bool $isSandBox): void $quoteCallbackUrl = $this->router->generate('frontend.ivyexpress.callback', [], Router::ABSOLUTE_URL); $successCallbackUrl = $this->router->generate('frontend.ivypayment.finalize.transaction', [], Router::ABSOLUTE_URL); $errorCallbackUrl = $this->router->generate('frontend.ivypayment.failed.transaction', [], Router::ABSOLUTE_URL); - $webhookUrl = $this->router->generate('ivypayment.update.transaction', [], Router::ABSOLUTE_URL); + $webhookUrl = $this->router->generate('frontend.ivypayment.update.transaction', [], Router::ABSOLUTE_URL); $privacyUrl = $this->router->generate('frontend.cms.page', ['id' => $config['privacyPage']], Router::ABSOLUTE_URL); $tosUrl = $this->router->generate('frontend.cms.page', ['id' => $config['tosPage']], Router::ABSOLUTE_URL); $completeCallbackUrl = $this->router->generate('frontend.ivyexpress.confirm', [], Router::ABSOLUTE_URL); diff --git a/src/WizmoGmbhIvyPayment.php b/src/WizmoGmbhIvyPayment.php index 286f5b9..b376879 100644 --- a/src/WizmoGmbhIvyPayment.php +++ b/src/WizmoGmbhIvyPayment.php @@ -20,42 +20,43 @@ use Shopware\Core\Framework\Plugin\Context\DeactivateContext; use Shopware\Core\Framework\Plugin\Context\InstallContext; use Shopware\Core\Framework\Plugin\Context\UninstallContext; -use Shopware\Core\Framework\Plugin\Context\UpdateContext; use Shopware\Core\Framework\Plugin\Util\PluginIdProvider; -use Symfony\Component\DependencyInjection\ContainerBuilder; use WizmoGmbh\IvyPayment\PaymentHandler\IvyPaymentHandler; use WizmoGmbh\IvyPayment\Setup\DataHolder\Tables; use WizmoGmbh\IvyPayment\Setup\Uninstaller; class WizmoGmbhIvyPayment extends Plugin { - public function install(InstallContext $context): void + public function install(InstallContext $installContext): void { - $this->addPaymentMethod($context->getContext()); + $this->addPaymentMethod($installContext->getContext()); } - public function activate(ActivateContext $context): void + public function activate(ActivateContext $activateContext): void { - $this->setPaymentMethodIsActive(true, $context->getContext()); - parent::activate($context); + $this->setPaymentMethodIsActive(true, $activateContext->getContext()); + parent::activate($activateContext); } - public function deactivate(DeactivateContext $context): void + public function deactivate(DeactivateContext $deactivateContext): void { - $this->setPaymentMethodIsActive(false, $context->getContext()); - parent::deactivate($context); + $this->setPaymentMethodIsActive(false, $deactivateContext->getContext()); + parent::deactivate($deactivateContext); } - public function uninstall(UninstallContext $context): void + public function uninstall(UninstallContext $uninstallContext): void { $tables = Tables::$tables; - $this->getUninstaller()->uninstall($context, $tables); + $this->getUninstaller()->uninstall($uninstallContext, $tables); // Only set the payment method to inactive when uninstalling. Removing the payment method would // cause data consistency issues, since the payment method might have been used in several orders - $this->setPaymentMethodIsActive(false, $context->getContext()); + $this->setPaymentMethodIsActive(false, $uninstallContext->getContext()); } + /** + * @throws \Exception + */ private function getUninstaller(): Uninstaller { return new Uninstaller($this->getConnection()); From 36d79657b2c9bbf917aefe5493e977243fa5ab64 Mon Sep 17 00:00:00 2001 From: toomas puur Date: Thu, 21 Sep 2023 21:18:18 +0200 Subject: [PATCH 2/3] fixed webhook update transaction --- .../Payment/Controller/IvyPaymentController.php | 17 ++++++++++++----- src/PaymentHandler/IvyPaymentHandler.php | 2 +- src/Resources/config/services/controllers.xml | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Core/Checkout/Payment/Controller/IvyPaymentController.php b/src/Core/Checkout/Payment/Controller/IvyPaymentController.php index 046940f..01cba43 100644 --- a/src/Core/Checkout/Payment/Controller/IvyPaymentController.php +++ b/src/Core/Checkout/Payment/Controller/IvyPaymentController.php @@ -18,7 +18,6 @@ use Shopware\Core\Checkout\Payment\Exception\InvalidTransactionException; use Shopware\Core\Checkout\Payment\Exception\TokenExpiredException; use Shopware\Core\Checkout\Payment\Exception\UnknownPaymentMethodException; -use Shopware\Core\Framework\Routing\Annotation\Since; use Shopware\Core\Framework\ShopwareHttpException; use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; use Shopware\Core\System\SalesChannel\SalesChannelContext; @@ -45,17 +44,21 @@ class IvyPaymentController extends StorefrontController private ExpressService $expressService; + private mixed $privateDir; + /** * @param IvyPaymentService $paymentService * @param TokenFactoryInterfaceV2 $tokenFactoryInterfaceV2 * @param IvyLogger $logger * @param ExpressService $expressService + * @param array $privatePath */ public function __construct( IvyPaymentService $paymentService, TokenFactoryInterfaceV2 $tokenFactoryInterfaceV2, IvyLogger $logger, - ExpressService $expressService + ExpressService $expressService, + array $privatePath ) { $this->paymentService = $paymentService; @@ -63,6 +66,7 @@ public function __construct( $this->logger = $logger; $this->logger->setName('WEBHOOK'); $this->expressService = $expressService; + $this->privateDir = $privatePath['config']['root'];; } #[Route('/ivypayment/failed-transaction', @@ -118,9 +122,10 @@ public function failedTransaction(Request $request, SalesChannelContext $salesCh public function updateTransaction(Request $request, RequestDataBag $inputData, SalesChannelContext $salesChannelContext): Response { $this->logger->setName('WEBHOOK'); + $this->logger->info('recieved new webhook'); $type = $request->request->get('type'); /** @var array $payload */ - $payload = $request->request->get('payload'); + $payload = $inputData->get('payload')?->all(); if (empty($type) || empty($payload)) { $this->logger->error('bad webhook request'); @@ -142,7 +147,7 @@ public function updateTransaction(Request $request, RequestDataBag $inputData, S } if (!isset($payload['status'])) { - $this->logger->error('bad webhook request'); + $this->logger->error('bad webhook request, status not set'); return new JsonResponse(['success' => false, 'error' => 'bad webhook request'], Response::HTTP_BAD_REQUEST); } @@ -157,7 +162,8 @@ public function updateTransaction(Request $request, RequestDataBag $inputData, S $referenceId = $payload['referenceId']; $ivyOrderId = $payload['id']; $lockName = 'ivylock_' . $ivyOrderId . '.lock'; - $tmpdir = \sys_get_temp_dir(); + $tmpdir = $this->privateDir; + $fp = \fopen($tmpdir . $lockName, 'wb'); $count = 0; @@ -224,6 +230,7 @@ public function updateTransaction(Request $request, RequestDataBag $inputData, S $this->logger->debug('webhook finished <== ' . $type); + unlink($tmpdir . $lockName); return new JsonResponse(null, Response::HTTP_OK); } diff --git a/src/PaymentHandler/IvyPaymentHandler.php b/src/PaymentHandler/IvyPaymentHandler.php index 3f5a8eb..626fd84 100644 --- a/src/PaymentHandler/IvyPaymentHandler.php +++ b/src/PaymentHandler/IvyPaymentHandler.php @@ -153,7 +153,7 @@ public function finalize(AsyncPaymentTransactionStruct $transaction, Request $re $transactionId = $transaction->getOrderTransaction()->getId(); /** @var array $payload */ - $payload = $request->request->get('payload'); + $payload = $request->request->all()['payload'] ?? []; $paymentState = $payload['status'] ?? null; $this->logger->debug("paymentState: $paymentState"); diff --git a/src/Resources/config/services/controllers.xml b/src/Resources/config/services/controllers.xml index 6006652..caa79a3 100644 --- a/src/Resources/config/services/controllers.xml +++ b/src/Resources/config/services/controllers.xml @@ -12,7 +12,7 @@ - + %shopware.filesystem.private% From 09716547e87aab9597d93592fbb3a21606c5474f Mon Sep 17 00:00:00 2001 From: toomas puur Date: Thu, 21 Sep 2023 21:19:32 +0200 Subject: [PATCH 3/3] fixed private shopware dir --- src/Core/Checkout/Payment/Controller/IvyPaymentController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Checkout/Payment/Controller/IvyPaymentController.php b/src/Core/Checkout/Payment/Controller/IvyPaymentController.php index 01cba43..08e8e91 100644 --- a/src/Core/Checkout/Payment/Controller/IvyPaymentController.php +++ b/src/Core/Checkout/Payment/Controller/IvyPaymentController.php @@ -44,7 +44,7 @@ class IvyPaymentController extends StorefrontController private ExpressService $expressService; - private mixed $privateDir; + private string $privateDir; /** * @param IvyPaymentService $paymentService