diff --git a/Model/AdditionalDataProvider.php b/Model/AdditionalDataProvider.php index 5d96bf4..7c6054b 100644 --- a/Model/AdditionalDataProvider.php +++ b/Model/AdditionalDataProvider.php @@ -21,6 +21,7 @@ namespace Buckaroo\Magento2Graphql\Model; +use Buckaroo\Magento2\Gateway\Http\TransactionBuilder\AbstractTransactionBuilder; use Buckaroo\Magento2Graphql\Plugin\AdditionalDataProviderPool; use Buckaroo\Magento2Graphql\Model\Payment\Method\ConfigFactory; use Magento\QuoteGraphQl\Model\Cart\Payment\AdditionalDataProviderInterface; @@ -59,4 +60,28 @@ public function getData(array $args): array return $args; } + + /** + * @param AdditionalDataProvider $subject + * @param array $result + * @param array $args + * @return array + * @suppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetData(AdditionalDataProvider $subject, array $result, array $args): array + { + if (isset($args['buckaroo_additional']['return_url'])) { + $result[AbstractTransactionBuilder::ADDITIONAL_RETURN_URL] = $args['buckaroo_additional']['return_url']; + } + if (isset($args['buckaroo_additional']['cancel_url'])) { + $result[AbstractTransactionBuilder::ADDITIONAL_CANCEL_URL] = $args['buckaroo_additional']['cancel_url']; + } + if (isset($args['buckaroo_additional']['error_url'])) { + $result[AbstractTransactionBuilder::ADDITIONAL_ERROR_URL] = $args['buckaroo_additional']['error_url']; + } + if (isset($args['buckaroo_additional']['reject_url'])) { + $result[AbstractTransactionBuilder::ADDITIONAL_REJECT_URL] = $args['buckaroo_additional']['reject_url']; + } + return $result; + } } diff --git a/Model/Payment/Method/AbstractMethodPlugin.php b/Model/Payment/Method/AbstractMethodPlugin.php new file mode 100644 index 0000000..36b3c1a --- /dev/null +++ b/Model/Payment/Method/AbstractMethodPlugin.php @@ -0,0 +1,54 @@ +getAdditionalData(); + + if (isset($additionalSkip['buckaroo_return_url'])) { + $subject->getInfoInstance()->setAdditionalInformation( + 'buckaroo_return_url', + $additionalSkip['buckaroo_return_url'] + ); + } + if (isset($additionalSkip['buckaroo_cancel_url'])) { + $subject->getInfoInstance()->setAdditionalInformation( + 'buckaroo_cancel_url', + $additionalSkip['buckaroo_cancel_url'] + ); + } + if (isset($additionalSkip['buckaroo_error_url'])) { + $subject->getInfoInstance()->setAdditionalInformation( + 'buckaroo_error_url', + $additionalSkip['buckaroo_error_url'] + ); + } + if (isset($additionalSkip['buckaroo_reject_url'])) { + $subject->getInfoInstance()->setAdditionalInformation( + 'buckaroo_reject_url', + $additionalSkip['buckaroo_reject_url'] + ); + } + return $result; + } +} diff --git a/Model/Payment/Method/Config/ReturnUrl.php b/Model/Payment/Method/Config/ReturnUrl.php new file mode 100644 index 0000000..5402748 --- /dev/null +++ b/Model/Payment/Method/Config/ReturnUrl.php @@ -0,0 +1,27 @@ +returnUrl = $scopeConfig->getValue( + 'payment/buckaroo/return_url', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ); + + // Or you can set a default URL if not configured + if (!$this->returnUrl) { + $this->returnUrl = "https://default-return-url.com"; + } + } + + public function getReturnUrl() + { + return $this->returnUrl; + } +} \ No newline at end of file diff --git a/Plugin/FixSession.php b/Plugin/FixSession.php index e2c0cc1..315a922 100644 --- a/Plugin/FixSession.php +++ b/Plugin/FixSession.php @@ -63,4 +63,4 @@ public function beforeSetPublicCookie( } return [$name, $value, $metadata]; } -} +} \ No newline at end of file diff --git a/Plugin/OrderTransactionBuilderPlugin.php b/Plugin/OrderTransactionBuilderPlugin.php new file mode 100644 index 0000000..d5f42dd --- /dev/null +++ b/Plugin/OrderTransactionBuilderPlugin.php @@ -0,0 +1,185 @@ +getReturnUrl($subject); + return $returnUrl . '?' . http_build_query([ + 'orderId' => $subject->getOrder()->getIncrementId(), + ]); + } + + /** + * When a specific returnURl is set on the payment, use that one. + * Otherwise, use the default return url. + * + * @param OrderTransactionBuilder $subject + * @return string + */ + protected function getReturnUrl(OrderTransactionBuilder $subject): string + { + $payment = $subject->getOrder()->getPayment(); + $additionalInfo = $payment->getAdditionalInformation(); + if (isset($additionalInfo[AbstractTransactionBuilder::ADDITIONAL_RETURN_URL])) { + return $additionalInfo[AbstractTransactionBuilder::ADDITIONAL_RETURN_URL]; + } + + return $this->getDefaultUrl(); + + } + /** + * Overwrite the return url to include the order_id and maskedId, + * There is an issue with `setReturnUrl` mutation not working, and we don't want to do extra mutations anyway. + * + * @param OrderTransactionBuilder $subject + * @param string $result + * @return string + * @throws Exception + * @suppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetCancelUrl( + OrderTransactionBuilder $subject, + string $result + ): string { + $cancelUrl = $this->getCancelUrl($subject); + return $cancelUrl . '?' . http_build_query([ + 'orderId' => $subject->getOrder()->getIncrementId(), + ]); + } + + /** + * When a specific returnURl is set on the payment, use that one. + * Otherwise, use the default return url. + * + * @param OrderTransactionBuilder $subject + * @return string + */ + protected function getCancelUrl(OrderTransactionBuilder $subject): string + { + $payment = $subject->getOrder()->getPayment(); + $additionalInfo = $payment->getAdditionalInformation(); + if (isset($additionalInfo[AbstractTransactionBuilder::ADDITIONAL_CANCEL_URL])) { + return $additionalInfo[AbstractTransactionBuilder::ADDITIONAL_CANCEL_URL]; + } + + return $this->getDefaultUrl(); + } + + /** + * Overwrite the return url to include the order_id and maskedId, + * There is an issue with `setReturnUrl` mutation not working, and we don't want to do extra mutations anyway. + * + * @param OrderTransactionBuilder $subject + * @param string $result + * @return string + * @throws Exception + * @suppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetErrorUrl( + OrderTransactionBuilder $subject, + string $result + ): string { + $errorUrl = $this->getErrorUrl($subject); + return $errorUrl . '?' . http_build_query([ + 'orderId' => $subject->getOrder()->getIncrementId(), + ]); + } + + /** + * When a specific returnURl is set on the payment, use that one. + * Otherwise, use the default return url. + * + * @param OrderTransactionBuilder $subject + * @return string + */ + protected function getErrorUrl(OrderTransactionBuilder $subject): string + { + $payment = $subject->getOrder()->getPayment(); + $additionalInfo = $payment->getAdditionalInformation(); + if (isset($additionalInfo[AbstractTransactionBuilder::ADDITIONAL_ERROR_URL])) { + return $additionalInfo[AbstractTransactionBuilder::ADDITIONAL_ERROR_URL]; + } + + return $this->getDefaultUrl(); + } + + /** + * Overwrite the return url to include the order_id and maskedId, + * There is an issue with `setReturnUrl` mutation not working, and we don't want to do extra mutations anyway. + * + * @param OrderTransactionBuilder $subject + * @param string $result + * @return string + * @throws Exception + * @suppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetRejectUrl( + OrderTransactionBuilder $subject, + string $result + ): string { + $rejectUrl = $this->getRejectUrl($subject); + return $rejectUrl . '?' . http_build_query([ + 'orderId' => $subject->getOrder()->getIncrementId(), + ]); + } + + /** + * When a specific returnURl is set on the payment, use that one. + * Otherwise, use the default return url. + * + * @param OrderTransactionBuilder $subject + * @return string + */ + protected function getRejectUrl(OrderTransactionBuilder $subject): string + { + $payment = $subject->getOrder()->getPayment(); + $additionalInfo = $payment->getAdditionalInformation(); + if (isset($additionalInfo[AbstractTransactionBuilder::ADDITIONAL_REJECT_URL])) { + return $additionalInfo[AbstractTransactionBuilder::ADDITIONAL_REJECT_URL]; + } + + return $this->getDefaultUrl(); + } + + protected function getDefaultUrl(){ + $returnUrl = $this->scopeConfig->getValue('web/secure/frontend_base_link_url'); + try { + /** @var Account $accountConfig */ + $accountConfig = $this->configProviderFactory->get('account'); + $returnUrl .= $accountConfig->getSuccessRedirect(); + } catch (Exception $e) { + $returnUrl .= self::DEFAULT_REDIRECT_PATH; + } + return $returnUrl; + } +} diff --git a/README.md b/README.md index 4c91162..51ba822 100644 --- a/README.md +++ b/README.md @@ -19,15 +19,15 @@ This plugin is needed for our [Hÿva React checkout extension](https://github.co ### Requirements -To use the plugin you must use: +To use the plugin you must use: - Magento Open Source version 2.4.x - Buckaroo Magento 2 Payment module 1.43.0 or higher. ## Installation - - Install the module composer by running the following command: `composer require buckaroo/magento2graphql` - - Enable the module by running the following command: `php bin/magento module:enable Buckaroo_Magento2Graphql` - - Apply database updates by running the following command: `php bin/magento setup:upgrade` - - Flush the cache by running the following command: `php bin/magento cache:flush` +- Install the module composer by running the following command: `composer require buckaroo/magento2graphql` +- Enable the module by running the following command: `php bin/magento module:enable Buckaroo_Magento2Graphql` +- Apply database updates by running the following command: `php bin/magento setup:upgrade` +- Flush the cache by running the following command: `php bin/magento cache:flush` ## Usage @@ -36,21 +36,21 @@ To use the plugin you must use: - Get the available payments methods with additional data for gateways: ```graphql query { - cart(cart_id: "{ CART_ID }") { - available_payment_methods { - code - title - buckaroo_additional { - key - values { - name - code - img - } - value - } + cart(cart_id: "{ CART_ID }") { + available_payment_methods { + code + title + buckaroo_additional { + key + values { + name + code + img } + value + } } + } } ``` @@ -111,8 +111,8 @@ In order to get the payment status after the user is redirected back we will use ```graphql mutation buckarooPaymentTransactionStatus(input: { transaction_id: "E397CF4C24E64AA299F45246F9906F45" }) { - payment_status, - status_code +payment_status, +status_code } ``` @@ -201,18 +201,19 @@ mutation buckarooPaymentTransactionStatus(input: { transaction_id: "E397CF4C24E6 - **Contact:** [support@buckaroo.nl](mailto:support@buckaroo.nl) or [+31 (0)30 711 50 50](tel:+310307115050) ### Contribute -We really appreciate it when developers contribute to improve the Buckaroo plugins. +We really appreciate it when ers contribute to improve the Buckaroo plugins. If you want to contribute as well, then please follow our [Contribution Guidelines](CONTRIBUTING.md). > ### Community is the :green_heart: of open source > Developing beautiful products is not possible without the input of a community. We thank everyone who actively contributes to this. -> +> > [![florinel-chis's avatar](https://github.com/florinel-chis.png?size=50)](https://github.com/florinel-chis) [![peterkoppenaal's avatar](https://github.com/peterkoppenaal.png?size=50)](https://github.com/peterkoppenaal) [![serpentscode's avatar](https://github.com/serpentscode.png?size=50)](https://github.com/serpentscode) [![paales's avatar](https://github.com/paales.png?size=50)](https://github.com/paales) [![raoulguillermo's avatar](https://github.com/raoulguillermo.png?size=50)](https://github.com/raoulguillermo) ### Versioning +

Please note:
-This file has been prepared with the greatest possible care and is subject to language and/or spelling errors. +This file has been prepared with the greatest possible care and is subject to language and/or spelling errors. \ No newline at end of file diff --git a/Resolver/Cart/OrderOutput.php b/Resolver/Cart/OrderOutput.php index 4b1dc8d..65c0f75 100644 --- a/Resolver/Cart/OrderOutput.php +++ b/Resolver/Cart/OrderOutput.php @@ -12,6 +12,7 @@ */ class OrderOutput implements ResolverInterface { + protected Registry $registry; public function __construct(Registry $registry) { diff --git a/Resolver/Cart/SetCancelUrl.php b/Resolver/Cart/SetCancelUrl.php new file mode 100644 index 0000000..880cd58 --- /dev/null +++ b/Resolver/Cart/SetCancelUrl.php @@ -0,0 +1,90 @@ +logger = $logger; + } + + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + + + parent::resolve($field, $context, $info, $value, $args); + + if (empty($args['input']['cancel_url'])) { + throw new GraphQlInputException( + __('Required parameter "cancel_url" is missing') + ); + } + + $cancelUrl = $args['input']['cancel_url']; + $cartId = $args['input']['cart_id']; + if ( + filter_var($cancelUrl, FILTER_VALIDATE_URL) === false || + !in_array(parse_url($cancelUrl, PHP_URL_SCHEME), ['http', 'https']) + ) { + throw new GraphQlInputException( + __('A valid "cancel_url" is required ') + ); + } + + try { + $quote = $this->getQuote($cartId, $context); + $quote->getPayment()->setAdditionalInformation(self::ADDITIONAL_CANCEL_URL, "{$cancelUrl}/{$cartId}"); + } catch (\Throwable $th) { + $this->logger->addDebug((string)$th); + throw new GraphQlInputException( + __('Unknown buckaroo error occurred') + ); + } + + return [ + "success" => true + ]; + } +} diff --git a/Resolver/Cart/SetErrorUrl.php b/Resolver/Cart/SetErrorUrl.php new file mode 100644 index 0000000..272bf54 --- /dev/null +++ b/Resolver/Cart/SetErrorUrl.php @@ -0,0 +1,90 @@ +logger = $logger; + } + + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + + + parent::resolve($field, $context, $info, $value, $args); + + if (empty($args['input']['error_url'])) { + throw new GraphQlInputException( + __('Required parameter "error_url" is missing') + ); + } + + $errorUrl = $args['input']['error_url']; + $cartId = $args['input']['cart_id']; + if ( + filter_var($errorUrl, FILTER_VALIDATE_URL) === false || + !in_array(parse_url($errorUrl, PHP_URL_SCHEME), ['http', 'https']) + ) { + throw new GraphQlInputException( + __('A valid "error_url" is required ') + ); + } + + try { + $quote = $this->getQuote($cartId, $context); + $quote->getPayment()->setAdditionalInformation(self::ADDITIONAL_ERROR_URL, "{$errorUrl}/{$cartId}"); + } catch (\Throwable $th) { + $this->logger->addDebug((string)$th); + throw new GraphQlInputException( + __('Unknown buckaroo error occurred') + ); + } + + return [ + "success" => true + ]; + } +} diff --git a/Resolver/Cart/SetRejectUrl.php b/Resolver/Cart/SetRejectUrl.php new file mode 100644 index 0000000..dad1320 --- /dev/null +++ b/Resolver/Cart/SetRejectUrl.php @@ -0,0 +1,90 @@ +logger = $logger; + } + + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + + + parent::resolve($field, $context, $info, $value, $args); + + if (empty($args['input']['reject_url'])) { + throw new GraphQlInputException( + __('Required parameter "reject_url" is missing') + ); + } + + $rejectUrl = $args['input']['reject_url']; + $cartId = $args['input']['cart_id']; + if ( + filter_var($rejectUrl, FILTER_VALIDATE_URL) === false || + !in_array(parse_url($rejectUrl, PHP_URL_SCHEME), ['http', 'https']) + ) { + throw new GraphQlInputException( + __('A valid "reject_url" is required ') + ); + } + + try { + $quote = $this->getQuote($cartId, $context); + $quote->getPayment()->setAdditionalInformation(self::ADDITIONAL_REJECT_URL, "{$rejectUrl}/{$cartId}"); + } catch (\Throwable $th) { + $this->logger->addDebug((string)$th); + throw new GraphQlInputException( + __('Unknown buckaroo error occurred') + ); + } + + return [ + "success" => true + ]; + } +} diff --git a/Resolver/Cart/SetReturnUrl.php b/Resolver/Cart/SetReturnUrl.php index ca6db25..6c98f1c 100644 --- a/Resolver/Cart/SetReturnUrl.php +++ b/Resolver/Cart/SetReturnUrl.php @@ -87,4 +87,4 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value "success" => true ]; } -} +} \ No newline at end of file diff --git a/Resolver/VoucherTransactionResolver.php b/Resolver/VoucherTransactionResolver.php index bc7ca9d..0a7859d 100644 --- a/Resolver/VoucherTransactionResolver.php +++ b/Resolver/VoucherTransactionResolver.php @@ -137,4 +137,4 @@ protected function argumentExists($args, $name) is_string($args['input'][$name]) && strlen(trim($args['input'][$name])) > 0; } -} +} \ No newline at end of file diff --git a/etc/graphql/di.xml b/etc/graphql/di.xml index f9c8b81..7e0276e 100644 --- a/etc/graphql/di.xml +++ b/etc/graphql/di.xml @@ -30,4 +30,16 @@ + + + + + + + + + diff --git a/etc/schema.graphqls b/etc/schema.graphqls index e776f2b..25ed5d8 100644 --- a/etc/schema.graphqls +++ b/etc/schema.graphqls @@ -22,6 +22,18 @@ type Mutation { input: BuckarooReturnUrlInput! ): BuckarooReturnUrl @resolver(class: "Buckaroo\\Magento2Graphql\\Resolver\\Cart\\SetReturnUrl") + setBuckarooCancelUrl( + input: BuckarooCancelUrlInput! + ): BuckarooCancelUrl @resolver(class: "Buckaroo\\Magento2Graphql\\Resolver\\Cart\\SetCancelUrl") + + setBuckarooErrorUrl( + input: BuckarooErrorUrlInput! + ): BuckarooErrorUrl @resolver(class: "Buckaroo\\Magento2Graphql\\Resolver\\Cart\\SetErrorUrl") + + setBuckarooRejectUrl( + input: BuckarooRejectUrlInput! + ): BuckarooRejectUrl @resolver(class: "Buckaroo\\Magento2Graphql\\Resolver\\Cart\\SetRejectUrl") + buckarooProcessGiftcardTransaction( input: BuckarooProcessGiftcardTransactionInput ): BuckarooProcessGiftcardTransactionOutput @resolver(class: "Buckaroo\\Magento2Graphql\\Resolver\\GiftcardTransactionResolver") @@ -31,13 +43,37 @@ type Mutation { ): BuckarooProcessGiftcardTransactionOutput @resolver(class: "Buckaroo\\Magento2Graphql\\Resolver\\VoucherTransactionResolver") } input BuckarooReturnUrlInput { - return_url: String! @doc(description: "Link to the success/failed order page"), + return_url: String! @doc(description: "Link to the success order page"), cart_id: String! @doc(description: "Cart id") } type BuckarooReturnUrl { success:Boolean } +input BuckarooCancelUrlInput { + cancel_url: String! @doc(description: "Link to the page after a cancellation"), + cart_id: String! @doc(description: "Cart id") +} +type BuckarooCancelUrl { + success:Boolean +} + +input BuckarooErrorUrlInput { + error_url: String! @doc(description: "Link to the page when an error occurs"), + cart_id: String! @doc(description: "Cart id") +} +type BuckarooErrorUrl { + success:Boolean +} + +input BuckarooRejectUrlInput { + reject_url: String! @doc(description: "Link to the page when the transaction gets rejected"), + cart_id: String! @doc(description: "Cart id") +} +type BuckarooRejectUrl { + success:Boolean +} + input BuckarooProcessVoucherTransactionInput { cart_id: String! @doc(description: "Cart id") voucher_code: String! @doc(description: "Voucher code") @@ -125,7 +161,11 @@ input BuckarooAdditionalInput { buckaroo_magento2_sepadirectdebit: BuckarooSepaDirectDebitInput buckaroo_magento2_tinka: BuckarooTinkaInput, buckaroo_magento2_klarna: BuckarooKlarnaInput, - buckaroo_magento2_klarnain: BuckarooKlarnaInput + buckaroo_magento2_klarnain: BuckarooKlarnaInput, + return_url: String @doc(description: "The URL to which the customer will be redirected after the payment has been completed. without query params") + cancel_url: String @doc(description: "The URL to which the customer will be redirected after the payment has been cancelled. without query params"), + error_url: String @doc(description: "The URL to which the customer will be redirected after the payment failed with due to an error. without query params"), + reject_url: String @doc(description: "The URL to which the customer will be redirected after the payment has been rejected. without query params"), } input BuckarooKlarnaInput {