From 2edeac55442a91353a6b4a8ee6d759635f060ecb Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 5 Aug 2024 17:36:56 +0200 Subject: [PATCH 01/29] Add new create order endpoint (WIP) --- modules/ppcp-api-client/services.php | 7 ++ .../ppcp-api-client/src/Endpoint/Orders.php | 76 +++++++++++++++++++ .../ppcp-wc-gateway/src/WCGatewayModule.php | 1 + .../PHPUnit/ApiClient/Endpoint/OrdersTest.php | 26 +++++++ tests/e2e/PHPUnit/OrdersTest.php | 49 ++++++++++++ 5 files changed, 159 insertions(+) create mode 100644 modules/ppcp-api-client/src/Endpoint/Orders.php create mode 100644 tests/PHPUnit/ApiClient/Endpoint/OrdersTest.php create mode 100644 tests/e2e/PHPUnit/OrdersTest.php diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index 241240ce2..5b60c7720 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient; use WooCommerce\PayPalCommerce\ApiClient\Authentication\SdkClientToken; use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult; @@ -239,6 +240,12 @@ return array( $bn_code ); }, + 'api.endpoint.orders' => static function (ContainerInterface $container): Orders { + return new Orders( + $container->get( 'api.host' ), + $container->get( 'api.bearer' ) + ); + }, 'api.endpoint.billing-agreements' => static function ( ContainerInterface $container ): BillingAgreementsEndpoint { return new BillingAgreementsEndpoint( $container->get( 'api.host' ), diff --git a/modules/ppcp-api-client/src/Endpoint/Orders.php b/modules/ppcp-api-client/src/Endpoint/Orders.php new file mode 100644 index 000000000..51d01a24d --- /dev/null +++ b/modules/ppcp-api-client/src/Endpoint/Orders.php @@ -0,0 +1,76 @@ +host = $host; + $this->bearer = $bearer; + } + + public function create(array $request_body, array $headers = array()): array { + $bearer = $this->bearer->bearer(); + $url = trailingslashit( $this->host ) . 'v2/checkout/orders'; + + $default_headers = array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + ); + $headers = array_merge( + $default_headers, + $headers + ); + + $args = array( + 'method' => 'POST', + 'headers' => $headers, + 'body' => wp_json_encode( $request_body ), + ); + + $response = wp_remote_get( $url, $args ); + if ( $response instanceof WP_Error ) { + throw new RuntimeException( $response->get_error_message() ); + } + + return $response; + } +} diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index 0b1315376..f01084da9 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway; use Psr\Log\LoggerInterface; use Throwable; use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; diff --git a/tests/PHPUnit/ApiClient/Endpoint/OrdersTest.php b/tests/PHPUnit/ApiClient/Endpoint/OrdersTest.php new file mode 100644 index 000000000..1033a015b --- /dev/null +++ b/tests/PHPUnit/ApiClient/Endpoint/OrdersTest.php @@ -0,0 +1,26 @@ +shouldReceive('token')->andReturn(''); + $bearer->shouldReceive('bearer')->andReturn($token); + + $sut = new Orders('', $bearer); + + expect('wp_remote_get')->andReturn([]); + + $this->assertEquals([], $sut->create([])); + } +} diff --git a/tests/e2e/PHPUnit/OrdersTest.php b/tests/e2e/PHPUnit/OrdersTest.php new file mode 100644 index 000000000..da9dc990e --- /dev/null +++ b/tests/e2e/PHPUnit/OrdersTest.php @@ -0,0 +1,49 @@ +getContainer(); + + $orders = new Orders($host, $container->get('api.bearer')); + + $requestBody = [ + "intent" => "CAPTURE", + "payment_source" => [ + "bancontact" => [ + "country_code" => "BE", + "name" => "John Doe" + ] + ], + "processing_instruction" => "ORDER_COMPLETE_ON_PAYMENT_APPROVAL", + "purchase_units" => [ + [ + "reference_id" => "d9f80740-38f0-11e8-b467-0ed5f89f718b", + "amount" => [ + "currency_code" => "EUR", + "value" => "1.00" + ], + ] + ], + "application_context" => [ + "locale" => "en-BE", + "return_url" => "https://example.com/returnUrl", + "cancel_url" => "https://example.com/cancelUrl" + ] + ]; + + $headers = array( + 'PayPal-Request-Id' => uniqid( 'ppcp-', true ), + ); + + $result = $orders->create($requestBody, $headers); + + $this->assertEquals(200, $result['response']['code']); + } +} From 7b22040710411f2327d0640a6cf9975a88c4dbdf Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Thu, 8 Aug 2024 12:43:29 +0200 Subject: [PATCH 02/29] Add module boilerplate --- modules.php | 7 ++++ .../composer.json | 17 +++++++++ .../extensions.php | 12 +++++++ .../module.php | 16 +++++++++ .../services.php | 14 ++++++++ .../LocalAlternativePaymentMethodsModule.php | 35 +++++++++++++++++++ 6 files changed, 101 insertions(+) create mode 100644 modules/ppcp-local-alternative-payment-methods/composer.json create mode 100644 modules/ppcp-local-alternative-payment-methods/extensions.php create mode 100644 modules/ppcp-local-alternative-payment-methods/module.php create mode 100644 modules/ppcp-local-alternative-payment-methods/services.php create mode 100644 modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php diff --git a/modules.php b/modules.php index aa73fb6ad..ee5830d5b 100644 --- a/modules.php +++ b/modules.php @@ -88,5 +88,12 @@ return function ( string $root_dir ): iterable { $modules[] = ( require "$modules_dir/ppcp-axo/module.php" )(); } + if ( apply_filters( + 'woocommerce.feature-flags.woocommerce_paypal_payments.local_apms_enabled', + getenv( 'PCP_LOCAL_APMS_ENABLED' ) === '1' + ) ) { + $modules[] = ( require "$modules_dir/ppcp-local-alternative-payment-methods/module.php" )(); + } + return $modules; }; diff --git a/modules/ppcp-local-alternative-payment-methods/composer.json b/modules/ppcp-local-alternative-payment-methods/composer.json new file mode 100644 index 000000000..278244301 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/composer.json @@ -0,0 +1,17 @@ +{ + "name": "woocommerce/ppcp-local-alternative-payment-methods", + "type": "dhii-mod", + "description": "Country based Alternative Payment Methods module", + "license": "GPL-2.0", + "require": { + "php": "^7.2 | ^8.0", + "dhii/module-interface": "^0.3.0-alpha1" + }, + "autoload": { + "psr-4": { + "WooCommerce\\PayPalCommerce\\LocalAlternativePaymentMethods\\": "src" + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/modules/ppcp-local-alternative-payment-methods/extensions.php b/modules/ppcp-local-alternative-payment-methods/extensions.php new file mode 100644 index 000000000..a57b7fba6 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/extensions.php @@ -0,0 +1,12 @@ + Date: Thu, 8 Aug 2024 14:24:47 +0200 Subject: [PATCH 03/29] Add wc payment gateway boilerplate --- .../services.php | 6 +- .../src/BancontactGateway.php | 72 +++++++++++++++++++ .../LocalAlternativePaymentMethodsModule.php | 4 ++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index 412f93edf..167916ae0 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -9,6 +9,10 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; -return array( +use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +return array( + 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { + return new BancontactGateway(); + }, ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php new file mode 100644 index 000000000..54735b999 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php @@ -0,0 +1,72 @@ +id = self::ID; + + $this->method_title = __( 'Bancontact', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'Bancontact', 'woocommerce-paypal-payments' ); + + $this->title = $this->get_option( 'title', __( 'Bancontact', 'woocommerce-paypal-payments' ) ); + $this->description = $this->get_option( 'description', '' ); + + $this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_bancontact_color.svg' ); + + $this->init_form_fields(); + $this->init_settings(); + + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + } + + public function init_form_fields() { + $this->form_fields = array( + 'enabled' => array( + 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'Bancontact', 'woocommerce-paypal-payments' ), + 'default' => 'no', + 'desc_tip' => true, + 'description' => __( 'Enable/Disable Bancontact payment gateway.', 'woocommerce-paypal-payments' ), + ), + 'title' => array( + 'title' => __( 'Title', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->title, + 'desc_tip' => true, + 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + 'description' => array( + 'title' => __( 'Description', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->description, + 'desc_tip' => true, + 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + ); + } + + public function process_payment( $order_id ) { + $wc_order = wc_get_order( $order_id ); + + + + return array( + 'result' => 'success', + 'redirect' => $this->get_return_url( $wc_order ), + ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index c8887bf5d..5674d90ae 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -30,6 +30,10 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { } public function run(ContainerInterface $c): void { + add_filter('woocommerce_payment_gateways', function ($methods) use ($c) { + $methods[] = $c->get('ppcp-local-apms.bancontact.wc-gateway'); + return $methods; + }); } } From 633ae1aed0ce7b49eb67d2c08c75f5db334a116a Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Fri, 9 Aug 2024 17:21:38 +0200 Subject: [PATCH 04/29] Add process payment for bancontact gateway (WIP) --- modules/ppcp-api-client/services.php | 5 +- .../ppcp-api-client/src/Endpoint/Orders.php | 39 +++++++-- .../services.php | 7 +- .../src/BancontactGateway.php | 87 ++++++++++++++++++- 4 files changed, 123 insertions(+), 15 deletions(-) diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index 0173031c0..f05db4c3f 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -241,10 +241,11 @@ return array( $bn_code ); }, - 'api.endpoint.orders' => static function (ContainerInterface $container): Orders { + 'api.endpoint.orders' => static function ( ContainerInterface $container ): Orders { return new Orders( $container->get( 'api.host' ), - $container->get( 'api.bearer' ) + $container->get( 'api.bearer' ), + $container->get( 'woocommerce.logger.woocommerce' ) ); }, 'api.endpoint.billing-agreements' => static function ( ContainerInterface $container ): BillingAgreementsEndpoint { diff --git a/modules/ppcp-api-client/src/Endpoint/Orders.php b/modules/ppcp-api-client/src/Endpoint/Orders.php index 51d01a24d..555404b21 100644 --- a/modules/ppcp-api-client/src/Endpoint/Orders.php +++ b/modules/ppcp-api-client/src/Endpoint/Orders.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint; +use Psr\Log\LoggerInterface; use RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WP_Error; @@ -19,6 +20,8 @@ use WP_Error; */ class Orders { + use RequestTrait; + /** * The host. * @@ -33,29 +36,47 @@ class Orders { */ private $bearer; + /** + * The logger. + * + * @var LoggerInterface + */ + private $logger; + /** * Orders constructor. * - * @param string $host - * @param Bearer $bearer + * @param string $host The host. + * @param Bearer $bearer The bearer. + * @param LoggerInterface $logger The logger. */ public function __construct( string $host, - Bearer $bearer + Bearer $bearer, + LoggerInterface $logger ) { - $this->host = $host; + $this->host = $host; $this->bearer = $bearer; + $this->logger = $logger; } - public function create(array $request_body, array $headers = array()): array { + /** + * Creates a PayPal order. + * + * @param array $request_body The request body. + * @param array $headers The request headers. + * @return array + * @throws RuntimeException If something is wrong with the request. + */ + public function create( array $request_body, array $headers = array() ): array { $bearer = $this->bearer->bearer(); - $url = trailingslashit( $this->host ) . 'v2/checkout/orders'; + $url = trailingslashit( $this->host ) . 'v2/checkout/orders'; $default_headers = array( 'Authorization' => 'Bearer ' . $bearer->token(), - 'Content-Type' => 'application/json', + 'Content-Type' => 'application/json', ); - $headers = array_merge( + $headers = array_merge( $default_headers, $headers ); @@ -66,7 +87,7 @@ class Orders { 'body' => wp_json_encode( $request_body ), ); - $response = wp_remote_get( $url, $args ); + $response = $this->request( $url, $args ); if ( $response instanceof WP_Error ) { throw new RuntimeException( $response->get_error_message() ); } diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index 167916ae0..8e2431005 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -12,7 +12,10 @@ namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; return array( - 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { - return new BancontactGateway(); + 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { + return new BancontactGateway( + $container->get( 'api.endpoint.orders' ), + $container->get( 'api.factory.purchase-unit' ) + ); }, ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php index 54735b999..e013fcfc1 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php @@ -10,12 +10,40 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; use WC_Payment_Gateway; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; +use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; +/** + * Class BancontactGateway + */ class BancontactGateway extends WC_Payment_Gateway { const ID = 'ppcp-bancontact'; - public function __construct() { + /** + * PayPal Orders endpoint. + * + * @var Orders + */ + private $orders_endpoint; + + /** + * Purchase unit factory. + * + * @var PurchaseUnitFactory + */ + private $purchase_unit_factory; + + /** + * BancontactGateway constructor. + * + * @param Orders $orders_endpoint PayPal Orders endpoint. + * @param PurchaseUnitFactory $purchase_unit_factory Purchase unit factory. + */ + public function __construct( + Orders $orders_endpoint, + PurchaseUnitFactory $purchase_unit_factory + ) { $this->id = self::ID; $this->method_title = __( 'Bancontact', 'woocommerce-paypal-payments' ); @@ -30,8 +58,14 @@ class BancontactGateway extends WC_Payment_Gateway { $this->init_settings(); add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + + $this->orders_endpoint = $orders_endpoint; + $this->purchase_unit_factory = $purchase_unit_factory; } + /** + * Initialize the form fields. + */ public function init_form_fields() { $this->form_fields = array( 'enabled' => array( @@ -59,14 +93,63 @@ class BancontactGateway extends WC_Payment_Gateway { ); } + /** + * Processes the order. + * + * @param int $order_id The WC order ID. + * @return array + */ public function process_payment( $order_id ) { $wc_order = wc_get_order( $order_id ); + $wc_order->update_status( 'on-hold', __( 'Awaiting Bancontact to confirm the payment.', 'woocommerce-paypal-payments' ) ); + $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); + $amount = $purchase_unit->amount()->to_array(); + $request_body = array( + 'intent' => 'CAPTURE', + 'payment_source' => array( + 'bancontact' => array( + 'country_code' => 'BE', + 'name' => 'John Doe', + ), + ), + 'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL', + 'purchase_units' => array( + array( + 'reference_id' => $purchase_unit->reference_id(), + 'amount' => array( + 'currency_code' => $amount['currency_code'], + 'value' => $amount['value'], + ), + 'custom_id' => $purchase_unit->custom_id(), + 'invoice_id' => $purchase_unit->invoice_id(), + ), + ), + 'application_context' => array( + 'locale' => 'en-BE', + 'return_url' => $this->get_return_url( $wc_order ), + 'cancel_url' => $this->get_return_url( $wc_order ), + ), + ); + + $headers = array( + 'PayPal-Request-Id' => uniqid( 'ppcp-', true ), + ); + + $response = $this->orders_endpoint->create( $request_body, $headers ); + $body = json_decode( $response['body'] ); + + $payer_action = ''; + foreach ( $body->links as $link ) { + if ( $link->rel === 'payer-action' ) { + $payer_action = $link->href; + } + } return array( 'result' => 'success', - 'redirect' => $this->get_return_url( $wc_order ), + 'redirect' => esc_url( $payer_action ), ); } } From 60885b2ad9d0f97b38f3b01ebc0d2551a813863b Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Fri, 9 Aug 2024 18:27:00 +0200 Subject: [PATCH 05/29] Add bancontact block checkout boilerplate --- .../.babelrc | 14 + .../.gitignore | 3 + .../package.json | 33 + .../resources/js/bancontact-checkout-block.js | 18 + .../services.php | 18 + .../src/BancontactPaymentMethod.php | 86 + .../LocalAlternativePaymentMethodsModule.php | 8 + .../webpack.config.js | 42 + .../yarn.lock | 2247 +++++++++++++++++ package.json | 3 + 10 files changed, 2472 insertions(+) create mode 100644 modules/ppcp-local-alternative-payment-methods/.babelrc create mode 100644 modules/ppcp-local-alternative-payment-methods/.gitignore create mode 100644 modules/ppcp-local-alternative-payment-methods/package.json create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-checkout-block.js create mode 100644 modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php create mode 100644 modules/ppcp-local-alternative-payment-methods/webpack.config.js create mode 100644 modules/ppcp-local-alternative-payment-methods/yarn.lock diff --git a/modules/ppcp-local-alternative-payment-methods/.babelrc b/modules/ppcp-local-alternative-payment-methods/.babelrc new file mode 100644 index 000000000..822778e6c --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "useBuiltIns": "usage", + "corejs": "3.25.0" + } + ], + [ + "@babel/preset-react" + ] + ] +} diff --git a/modules/ppcp-local-alternative-payment-methods/.gitignore b/modules/ppcp-local-alternative-payment-methods/.gitignore new file mode 100644 index 000000000..0bd2b9f58 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/.gitignore @@ -0,0 +1,3 @@ +node_modules +assets/js +assets/css diff --git a/modules/ppcp-local-alternative-payment-methods/package.json b/modules/ppcp-local-alternative-payment-methods/package.json new file mode 100644 index 000000000..a00a17bea --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/package.json @@ -0,0 +1,33 @@ +{ + "name": "ppcp-local-alternative-payment-methods", + "version": "1.0.0", + "license": "GPL-3.0-or-later", + "browserslist": [ + "> 0.5%", + "Safari >= 8", + "Chrome >= 41", + "Firefox >= 43", + "Edge >= 14" + ], + "dependencies": { + "core-js": "^3.25.0" + }, + "devDependencies": { + "@babel/core": "^7.19", + "@babel/preset-env": "^7.19", + "@babel/preset-react": "^7.18.6", + "@woocommerce/dependency-extraction-webpack-plugin": "2.2.0", + "babel-loader": "^8.2", + "cross-env": "^7.0.3", + "file-loader": "^6.2.0", + "sass": "^1.42.1", + "sass-loader": "^12.1.0", + "webpack": "^5.76", + "webpack-cli": "^4.10" + }, + "scripts": { + "build": "cross-env BABEL_ENV=default NODE_ENV=production webpack", + "watch": "cross-env BABEL_ENV=default NODE_ENV=production webpack --watch", + "dev": "cross-env BABEL_ENV=default webpack --watch" + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-checkout-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-checkout-block.js new file mode 100644 index 000000000..910f7fb0c --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-checkout-block.js @@ -0,0 +1,18 @@ +import { registerPaymentMethod } from '@woocommerce/blocks-registry'; + +const config = wc.wcSettings.getSetting( 'ppcp-bancontact_data' ); +console.log( config ); + +registerPaymentMethod( { + name: config.id, + label:
, + content:
Hi there!
, + edit:
, + ariaLabel: config.title, + canMakePayment: () => { + return true; + }, + supports: { + features: config.supports, + }, +} ); diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index 8e2431005..c42709949 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -12,10 +12,28 @@ namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; return array( + 'ppcp-local-apms.url' => static function ( ContainerInterface $container ): string { + /** + * The path cannot be false. + * + * @psalm-suppress PossiblyFalseArgument + */ + return plugins_url( + '/modules/ppcp-local-alternative-payment-methods/', + dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php' + ); + }, 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { return new BancontactGateway( $container->get( 'api.endpoint.orders' ), $container->get( 'api.factory.purchase-unit' ) ); }, + 'ppcp-local-apms.bancontact.payment-method' => static function(ContainerInterface $container): BancontactPaymentMethod { + return new BancontactPaymentMethod( + $container->get('ppcp-local-apms.url'), + $container->get( 'ppcp.asset-version' ), + $container->get('ppcp-local-apms.bancontact.wc-gateway') + ); + } ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php new file mode 100644 index 000000000..935bfff78 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php @@ -0,0 +1,86 @@ +module_url = $module_url; + $this->version = $version; + $this->gateway = $gateway; + + $this->name = BancontactGateway::ID; + } + + /** + * {@inheritDoc} + */ + public function initialize() {} + + /** + * {@inheritDoc} + */ + public function is_active() { + return true; + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_script_handles() { + wp_register_script( + 'ppcp-bancontact-checkout-block', + trailingslashit( $this->module_url ) . 'assets/js/bancontact-checkout-block.js', + array(), + $this->version, + true + ); + + return array( 'ppcp-bancontact-checkout-block' ); + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_data() { + return array( + 'id' => $this->name, + 'title' => $this->gateway->title, + 'description' => $this->gateway->description, + ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 5674d90ae..7c794f5cc 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; +use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; @@ -35,5 +36,12 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { return $methods; }); + + add_action( + 'woocommerce_blocks_payment_method_type_registration', + function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void { + $payment_method_registry->register( $c->get( 'ppcp-local-apms.bancontact.payment-method' ) ); + } + ); } } diff --git a/modules/ppcp-local-alternative-payment-methods/webpack.config.js b/modules/ppcp-local-alternative-payment-methods/webpack.config.js new file mode 100644 index 000000000..65053736f --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/webpack.config.js @@ -0,0 +1,42 @@ +const path = require( 'path' ); +const isProduction = process.env.NODE_ENV === 'production'; + +const DependencyExtractionWebpackPlugin = require( '@woocommerce/dependency-extraction-webpack-plugin' ); + +module.exports = { + devtool: isProduction ? 'source-map' : 'eval-source-map', + mode: isProduction ? 'production' : 'development', + target: 'web', + plugins: [ new DependencyExtractionWebpackPlugin() ], + entry: { + 'bancontact-checkout-block': path.resolve( + './resources/js/bancontact-checkout-block.js' + ), + }, + output: { + path: path.resolve( __dirname, 'assets/' ), + filename: 'js/[name].js', + }, + module: { + rules: [ + { + test: /\.js?$/, + exclude: /node_modules/, + loader: 'babel-loader', + }, + { + test: /\.scss$/, + exclude: /node_modules/, + use: [ + { + loader: 'file-loader', + options: { + name: 'css/[name].css', + }, + }, + { loader: 'sass-loader' }, + ], + }, + ], + }, +}; diff --git a/modules/ppcp-local-alternative-payment-methods/yarn.lock b/modules/ppcp-local-alternative-payment-methods/yarn.lock new file mode 100644 index 000000000..9cde0f01c --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/yarn.lock @@ -0,0 +1,2247 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@babel/code-frame@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + dependencies: + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" + +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.2.tgz#e41928bd33475305c586f6acbbb7e3ade7a6f7f5" + integrity sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ== + +"@babel/core@^7.19": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.25.2.tgz#ed8eec275118d7613e77a352894cd12ded8eba77" + integrity sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.25.0" + "@babel/helper-compilation-targets" "^7.25.2" + "@babel/helper-module-transforms" "^7.25.2" + "@babel/helpers" "^7.25.0" + "@babel/parser" "^7.25.0" + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.2" + "@babel/types" "^7.25.2" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.25.0.tgz#f858ddfa984350bc3d3b7f125073c9af6988f18e" + integrity sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw== + dependencies: + "@babel/types" "^7.25.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" + integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3" + integrity sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.7", "@babel/helper-compilation-targets@^7.24.8", "@babel/helper-compilation-targets@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz#e1d9410a90974a3a5a66e84ff55ef62e3c02d06c" + integrity sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw== + dependencies: + "@babel/compat-data" "^7.25.2" + "@babel/helper-validator-option" "^7.24.8" + browserslist "^4.23.1" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.24.7": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz#a109bf9c3d58dfed83aaf42e85633c89f43a6253" + integrity sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.8" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/helper-replace-supers" "^7.25.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/traverse" "^7.25.0" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7", "@babel/helper-create-regexp-features-plugin@^7.25.0": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz#24c75974ed74183797ffd5f134169316cd1808d9" + integrity sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + regexpu-core "^5.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + +"@babel/helper-member-expression-to-functions@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz#6155e079c913357d24a4c20480db7c712a5c3fb6" + integrity sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA== + dependencies: + "@babel/traverse" "^7.24.8" + "@babel/types" "^7.24.8" + +"@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-module-transforms@^7.24.7", "@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.25.0", "@babel/helper-module-transforms@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz#ee713c29768100f2776edf04d4eb23b8d27a66e6" + integrity sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + "@babel/traverse" "^7.25.2" + +"@babel/helper-optimise-call-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f" + integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.24.8", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878" + integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== + +"@babel/helper-remap-async-to-generator@^7.24.7", "@babel/helper-remap-async-to-generator@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz#d2f0fbba059a42d68e5e378feaf181ef6055365e" + integrity sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-wrap-function" "^7.25.0" + "@babel/traverse" "^7.25.0" + +"@babel/helper-replace-supers@^7.24.7", "@babel/helper-replace-supers@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz#ff44deac1c9f619523fe2ca1fd650773792000a9" + integrity sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.24.8" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/traverse" "^7.25.0" + +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9" + integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-string-parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" + integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.24.7", "@babel/helper-validator-option@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" + integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== + +"@babel/helper-wrap-function@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz#dab12f0f593d6ca48c0062c28bcfb14ebe812f81" + integrity sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ== + dependencies: + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/helpers@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.25.0.tgz#e69beb7841cb93a6505531ede34f34e6a073650a" + integrity sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw== + dependencies: + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.25.0", "@babel/parser@^7.25.3": + version "7.25.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.3.tgz#91fb126768d944966263f0657ab222a642b82065" + integrity sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw== + dependencies: + "@babel/types" "^7.25.2" + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.3": + version "7.25.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz#dca427b45a6c0f5c095a1c639dfe2476a3daba7f" + integrity sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.3" + +"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz#cd0c583e01369ef51676bdb3d7b603e17d2b3f73" + integrity sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz#749bde80356b295390954643de7635e0dffabe73" + integrity sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz#e4eabdd5109acc399b38d7999b2ef66fc2022f89" + integrity sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz#3a82a70e7cb7294ad2559465ebcb871dfbf078fb" + integrity sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.0" + +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-import-assertions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz#2a0b406b5871a20a841240586b1300ce2088a778" + integrity sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz#b4f9ea95a79e6912480c4b626739f86a076624ca" + integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d" + integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz#4f6886c11e423bd69f3ce51dbf42424a5f275514" + integrity sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-async-generator-functions@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz#b785cf35d73437f6276b1e30439a57a50747bddf" + integrity sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-remap-async-to-generator" "^7.25.0" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/traverse" "^7.25.0" + +"@babel/plugin-transform-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz#72a3af6c451d575842a7e9b5a02863414355bdcc" + integrity sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" + +"@babel/plugin-transform-block-scoped-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz#a4251d98ea0c0f399dafe1a35801eaba455bbf1f" + integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-block-scoping@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz#23a6ed92e6b006d26b1869b1c91d1b917c2ea2ac" + integrity sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-class-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz#256879467b57b0b68c7ddfc5b76584f398cd6834" + integrity sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-class-static-block@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d" + integrity sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-transform-classes@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz#63122366527d88e0ef61b612554fe3f8c793991e" + integrity sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-replace-supers" "^7.25.0" + "@babel/traverse" "^7.25.0" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz#4cab3214e80bc71fae3853238d13d097b004c707" + integrity sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/template" "^7.24.7" + +"@babel/plugin-transform-destructuring@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz#c828e814dbe42a2718a838c2a2e16a408e055550" + integrity sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-dotall-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz#5f8bf8a680f2116a7207e16288a5f974ad47a7a0" + integrity sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-duplicate-keys@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz#dd20102897c9a2324e5adfffb67ff3610359a8ee" + integrity sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz#809af7e3339466b49c034c683964ee8afb3e2604" + integrity sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.0" + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-dynamic-import@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz#4d8b95e3bae2b037673091aa09cd33fecd6419f4" + integrity sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz#b629ee22645f412024297d5245bce425c31f9b0d" + integrity sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-export-namespace-from@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz#176d52d8d8ed516aeae7013ee9556d540c53f197" + integrity sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-transform-for-of@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz#f25b33f72df1d8be76399e1b8f3f9d366eb5bc70" + integrity sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + +"@babel/plugin-transform-function-name@^7.25.1": + version "7.25.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz#b85e773097526c1a4fc4ba27322748643f26fc37" + integrity sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA== + dependencies: + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.1" + +"@babel/plugin-transform-json-strings@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz#f3e9c37c0a373fee86e36880d45b3664cedaf73a" + integrity sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-transform-literals@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz#deb1ad14fc5490b9a65ed830e025bca849d8b5f3" + integrity sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-logical-assignment-operators@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz#a58fb6eda16c9dc8f9ff1c7b1ba6deb7f4694cb0" + integrity sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz#3b4454fb0e302e18ba4945ba3246acb1248315df" + integrity sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-modules-amd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz#65090ed493c4a834976a3ca1cde776e6ccff32d7" + integrity sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-modules-commonjs@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz#ab6421e564b717cb475d6fff70ae7f103536ea3c" + integrity sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA== + dependencies: + "@babel/helper-module-transforms" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-simple-access" "^7.24.7" + +"@babel/plugin-transform-modules-systemjs@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz#8f46cdc5f9e5af74f3bd019485a6cbe59685ea33" + integrity sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw== + dependencies: + "@babel/helper-module-transforms" "^7.25.0" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + "@babel/traverse" "^7.25.0" + +"@babel/plugin-transform-modules-umd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz#edd9f43ec549099620df7df24e7ba13b5c76efc8" + integrity sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz#9042e9b856bc6b3688c0c2e4060e9e10b1460923" + integrity sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-new-target@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz#31ff54c4e0555cc549d5816e4ab39241dfb6ab00" + integrity sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz#1de4534c590af9596f53d67f52a92f12db984120" + integrity sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz#bea62b538c80605d8a0fac9b40f48e97efa7de63" + integrity sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz#d13a2b93435aeb8a197e115221cab266ba6e55d6" + integrity sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q== + dependencies: + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.24.7" + +"@babel/plugin-transform-object-super@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz#66eeaff7830bba945dd8989b632a40c04ed625be" + integrity sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + +"@babel/plugin-transform-optional-catch-binding@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz#00eabd883d0dd6a60c1c557548785919b6e717b4" + integrity sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.24.7", "@babel/plugin-transform-optional-chaining@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz#bb02a67b60ff0406085c13d104c99a835cdf365d" + integrity sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz#5881f0ae21018400e320fc7eb817e529d1254b68" + integrity sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-methods@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz#e6318746b2ae70a59d023d5cc1344a2ba7a75f5e" + integrity sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-property-in-object@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz#4eec6bc701288c1fab5f72e6a4bbc9d67faca061" + integrity sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz#f0d2ed8380dfbed949c42d4d790266525d63bbdc" + integrity sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-react-display-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz#9caff79836803bc666bcfe210aeb6626230c293b" + integrity sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-react-jsx-development@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz#eaee12f15a93f6496d852509a850085e6361470b" + integrity sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.24.7" + +"@babel/plugin-transform-react-jsx@^7.24.7": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz#e37e8ebfa77e9f0b16ba07fadcb6adb47412227a" + integrity sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/types" "^7.25.2" + +"@babel/plugin-transform-react-pure-annotations@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz#bdd9d140d1c318b4f28b29a00fb94f97ecab1595" + integrity sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-regenerator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz#021562de4534d8b4b1851759fd7af4e05d2c47f8" + integrity sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-reserved-words@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz#80037fe4fbf031fc1125022178ff3938bb3743a4" + integrity sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-shorthand-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz#85448c6b996e122fa9e289746140aaa99da64e73" + integrity sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz#e8a38c0fde7882e0fb8f160378f74bd885cc7bb3" + integrity sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + +"@babel/plugin-transform-sticky-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz#96ae80d7a7e5251f657b5cf18f1ea6bf926f5feb" + integrity sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-template-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz#a05debb4a9072ae8f985bcf77f3f215434c8f8c8" + integrity sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-typeof-symbol@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz#383dab37fb073f5bfe6e60c654caac309f92ba1c" + integrity sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-unicode-escapes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz#2023a82ced1fb4971630a2e079764502c4148e0e" + integrity sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-property-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz#9073a4cd13b86ea71c3264659590ac086605bbcd" + integrity sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz#dfc3d4a51127108099b19817c0963be6a2adf19f" + integrity sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-sets-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz#d40705d67523803a576e29c63cef6e516b858ed9" + integrity sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/preset-env@^7.19": + version "7.25.3" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.25.3.tgz#0bf4769d84ac51d1073ab4a86f00f30a3a83c67c" + integrity sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g== + dependencies: + "@babel/compat-data" "^7.25.2" + "@babel/helper-compilation-targets" "^7.25.2" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-validator-option" "^7.24.8" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.25.3" + "@babel/plugin-bugfix-safari-class-field-initializer-scope" "^7.25.0" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.25.0" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.7" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.25.0" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.24.7" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.24.7" + "@babel/plugin-transform-async-generator-functions" "^7.25.0" + "@babel/plugin-transform-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoped-functions" "^7.24.7" + "@babel/plugin-transform-block-scoping" "^7.25.0" + "@babel/plugin-transform-class-properties" "^7.24.7" + "@babel/plugin-transform-class-static-block" "^7.24.7" + "@babel/plugin-transform-classes" "^7.25.0" + "@babel/plugin-transform-computed-properties" "^7.24.7" + "@babel/plugin-transform-destructuring" "^7.24.8" + "@babel/plugin-transform-dotall-regex" "^7.24.7" + "@babel/plugin-transform-duplicate-keys" "^7.24.7" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.25.0" + "@babel/plugin-transform-dynamic-import" "^7.24.7" + "@babel/plugin-transform-exponentiation-operator" "^7.24.7" + "@babel/plugin-transform-export-namespace-from" "^7.24.7" + "@babel/plugin-transform-for-of" "^7.24.7" + "@babel/plugin-transform-function-name" "^7.25.1" + "@babel/plugin-transform-json-strings" "^7.24.7" + "@babel/plugin-transform-literals" "^7.25.2" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" + "@babel/plugin-transform-member-expression-literals" "^7.24.7" + "@babel/plugin-transform-modules-amd" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.8" + "@babel/plugin-transform-modules-systemjs" "^7.25.0" + "@babel/plugin-transform-modules-umd" "^7.24.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" + "@babel/plugin-transform-new-target" "^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" + "@babel/plugin-transform-numeric-separator" "^7.24.7" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-object-super" "^7.24.7" + "@babel/plugin-transform-optional-catch-binding" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.8" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-property-literals" "^7.24.7" + "@babel/plugin-transform-regenerator" "^7.24.7" + "@babel/plugin-transform-reserved-words" "^7.24.7" + "@babel/plugin-transform-shorthand-properties" "^7.24.7" + "@babel/plugin-transform-spread" "^7.24.7" + "@babel/plugin-transform-sticky-regex" "^7.24.7" + "@babel/plugin-transform-template-literals" "^7.24.7" + "@babel/plugin-transform-typeof-symbol" "^7.24.8" + "@babel/plugin-transform-unicode-escapes" "^7.24.7" + "@babel/plugin-transform-unicode-property-regex" "^7.24.7" + "@babel/plugin-transform-unicode-regex" "^7.24.7" + "@babel/plugin-transform-unicode-sets-regex" "^7.24.7" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.4" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.37.1" + semver "^6.3.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@^7.18.6": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.7.tgz#480aeb389b2a798880bf1f889199e3641cbb22dc" + integrity sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-transform-react-display-name" "^7.24.7" + "@babel/plugin-transform-react-jsx" "^7.24.7" + "@babel/plugin-transform-react-jsx-development" "^7.24.7" + "@babel/plugin-transform-react-pure-annotations" "^7.24.7" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + +"@babel/runtime@^7.8.4": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb" + integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.24.7", "@babel/template@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.0.tgz#e733dc3134b4fede528c15bc95e89cb98c52592a" + integrity sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3": + version "7.25.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.3.tgz#f1b901951c83eda2f3e29450ce92743783373490" + integrity sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.25.0" + "@babel/parser" "^7.25.3" + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.2" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.4.4": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.2.tgz#55fb231f7dc958cd69ea141a4c2997e819646125" + integrity sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q== + dependencies: + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + to-fast-properties "^2.0.0" + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@types/eslint-scope@^3.7.3": + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.0.tgz#51d4fe4d0316da9e9f2c80884f2c20ed5fb022ff" + integrity sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== + +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/node@*": + version "22.1.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.1.0.tgz#6d6adc648b5e03f0e83c78dc788c2b037d0ad94b" + integrity sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw== + dependencies: + undici-types "~6.13.0" + +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== + +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== + +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== + +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== + +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" + +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== + +"@webpack-cli/info@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== + +"@woocommerce/dependency-extraction-webpack-plugin@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@woocommerce/dependency-extraction-webpack-plugin/-/dependency-extraction-webpack-plugin-2.2.0.tgz#230d674a67585bc32e31bc28485bec99b41dbd1f" + integrity sha512-0wDY3EIUwWrPm0KrWvt1cf2SZDSX7CzBXvv4TyCqWOPuVPvC/ajyY8kD1HTFI80q6/RHoxWf3BYCmhuBzPbe9A== + dependencies: + "@wordpress/dependency-extraction-webpack-plugin" "^3.3.0" + +"@wordpress/dependency-extraction-webpack-plugin@^3.3.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@wordpress/dependency-extraction-webpack-plugin/-/dependency-extraction-webpack-plugin-3.7.0.tgz#e52ef31f66b8c4add3d773a87e11007375127b04" + integrity sha512-SHyp88D1ICSaRVMfs/kKEicjKXWf1y2wecUeZIiMtkfAi8Bnk3JsnUo11LH7drJIXfjmDoer2B2rrBMZmRm8VA== + dependencies: + json2php "^0.0.4" + webpack-sources "^3.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== + +acorn@^8.7.1, acorn@^8.8.2: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +babel-loader@^8.2: + version "8.3.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" + integrity sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q== + dependencies: + find-cache-dir "^3.3.1" + loader-utils "^2.0.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" + +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.11" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.2" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.10.4: + version "0.10.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" + integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + core-js-compat "^3.38.0" + +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.21.10, browserslist@^4.23.1, browserslist@^4.23.3: + version "4.23.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800" + integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA== + dependencies: + caniuse-lite "^1.0.30001646" + electron-to-chromium "^1.5.4" + node-releases "^2.0.18" + update-browserslist-db "^1.1.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +caniuse-lite@^1.0.30001646: + version "1.0.30001651" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz#52de59529e8b02b1aedcaaf5c05d9e23c0c28138" + integrity sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +"chokidar@>=3.0.0 <4.0.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chrome-trace-event@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +colorette@^2.0.14: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +core-js-compat@^3.37.1, core-js-compat@^3.38.0: + version "3.38.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.38.0.tgz#d93393b1aa346b6ee683377b0c31172ccfe607aa" + integrity sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A== + dependencies: + browserslist "^4.23.3" + +core-js@^3.25.0: + version "3.38.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.38.0.tgz#8acb7c050bf2ccbb35f938c0d040132f6110f636" + integrity sha512-XPpwqEodRljce9KswjZShh95qJ1URisBeKCjUdq27YdenkslVe7OO0ZJhlYXAChW7OhXaRLl8AAba7IBfoIHug== + +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^7.0.1, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== + dependencies: + ms "2.1.2" + +electron-to-chromium@^1.5.4: + version "1.5.5" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.5.tgz#03bfdf422bdd2c05ee2657efedde21264a1a566b" + integrity sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +enhanced-resolve@^5.17.0: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.7.3: + version "7.13.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.13.0.tgz#81fbb81e5da35d74e814941aeab7c325a606fb31" + integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== + +es-module-lexer@^1.2.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== + +escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +file-loader@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-cache-dir@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +immutable@^4.0.0: + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + +import-local@^3.0.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.13.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea" + integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA== + dependencies: + hasown "^2.0.2" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json2php@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/json2php/-/json2php-0.0.4.tgz#6bd85a1dda6a5dd7e91022bb24403cc1b7c2ee34" + integrity sha512-hFzejhs28f70sGnutcsRS459MnAsjRVI85RgPAL1KQIZEpjiDitc27CZv4IgOtaR86vrqOVlu9vJNew2XyTH4g== + +json5@^2.1.2, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klona@^2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" + integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +loader-utils@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.27: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pkg-dir@^4.1.0, pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + +regenerate-unicode-properties@^10.1.0: + version "10.1.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + dependencies: + "@babel/runtime" "^7.8.4" + +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== + dependencies: + "@babel/regjsgen" "^0.8.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== + dependencies: + jsesc "~0.5.0" + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.14.2, resolve@^1.9.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +sass-loader@^12.1.0: + version "12.6.0" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.6.0.tgz#5148362c8e2cdd4b950f3c63ac5d16dbfed37bcb" + integrity sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA== + dependencies: + klona "^2.0.4" + neo-async "^2.6.2" + +sass@^1.42.1: + version "1.77.8" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.8.tgz#9f18b449ea401759ef7ec1752a16373e296b52bd" + integrity sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + +schema-utils@^2.6.5: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +semver@^6.0.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +"source-map-js@>=0.6.2 <2.0.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + +terser@^5.26.0: + version "5.31.5" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.5.tgz#e48b7c65f32d2808e7dad803e4586a0bc3829b87" + integrity sha512-YPmas0L0rE1UyLL/llTWA0SiDOqIcAQYLeUj7cJYzXHlRTAnMSg9pPe4VJ5PlKvTrPQsdVFuiRiwyeNlYgwh2Q== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +undici-types@~6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.13.0.tgz#e3e79220ab8c81ed1496b5812471afd7cf075ea5" + integrity sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg== + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== + +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +watchpack@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +webpack-cli@^4.10: + version "4.10.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" + integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.2.0" + "@webpack-cli/info" "^1.5.0" + "@webpack-cli/serve" "^1.7.0" + colorette "^2.0.14" + commander "^7.0.0" + cross-spawn "^7.0.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + +webpack-merge@^5.7.3: + version "5.10.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.0" + +webpack-sources@^3.2.2, webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^5.76: + version "5.93.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.93.0.tgz#2e89ec7035579bdfba9760d26c63ac5c3462a5e5" + integrity sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" + acorn "^8.7.1" + acorn-import-attributes "^1.9.5" + browserslist "^4.21.10" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.17.0" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.11" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" + webpack-sources "^3.2.3" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== diff --git a/package.json b/package.json index 72aad99db..7432a44da 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "install:modules:ppcp-paylater-configurator": "cd modules/ppcp-paylater-configurator && yarn install", "install:modules:ppcp-button": "cd modules/ppcp-button && yarn install", "install:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn install", + "install:modules:ppcp-local-alternative-payment-methods": "cd modules/ppcp-local-alternative-payment-methods && yarn install", "install:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn install", "install:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn install", "install:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn install", @@ -30,6 +31,7 @@ "build:modules:ppcp-paylater-configurator": "cd modules/ppcp-paylater-configurator && yarn run build", "build:modules:ppcp-button": "cd modules/ppcp-button && yarn run build", "build:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn run build", + "build:modules:ppcp-local-alternative-payment-methods": "cd modules/ppcp-local-alternative-payment-methods && yarn run build", "build:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run build", "build:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run build", "build:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run build", @@ -47,6 +49,7 @@ "watch:modules:ppcp-paylater-configurator": "cd modules/ppcp-paylater-configurator && yarn run watch", "watch:modules:ppcp-button": "cd modules/ppcp-button && yarn run watch", "watch:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn run watch", + "watch:modules:ppcp-local-alternative-payment-methods": "cd modules/ppcp-local-alternative-payment-methods && yarn run watch", "watch:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run watch", "watch:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run watch", "watch:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run watch", From ce25dee734475ef81ddb7a23fcf2ebf0f909b91c Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 12 Aug 2024 11:54:14 +0200 Subject: [PATCH 06/29] Add bancontact component --- .../resources/js/bancontact-block.js | 9 +++++++++ ...ct-checkout-block.js => bancontact-payment-method.js} | 4 ++-- .../src/BancontactPaymentMethod.php | 7 ++++--- .../webpack.config.js | 4 ++-- 4 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-block.js rename modules/ppcp-local-alternative-payment-methods/resources/js/{bancontact-checkout-block.js => bancontact-payment-method.js} (80%) diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-block.js new file mode 100644 index 000000000..e66ab88c3 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-block.js @@ -0,0 +1,9 @@ +export function Bancontact( { config, components } ) { + const { PaymentMethodIcons } = components; + + return ( +
+ +
+ ); +} diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-checkout-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-payment-method.js similarity index 80% rename from modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-checkout-block.js rename to modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-payment-method.js index 910f7fb0c..f8e1d7e25 100644 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-checkout-block.js +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-payment-method.js @@ -1,12 +1,12 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry'; +import { Bancontact } from './bancontact-block'; const config = wc.wcSettings.getSetting( 'ppcp-bancontact_data' ); -console.log( config ); registerPaymentMethod( { name: config.id, label:
, - content:
Hi there!
, + content: , edit:
, ariaLabel: config.title, canMakePayment: () => { diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php index 935bfff78..1430956f8 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php @@ -63,14 +63,14 @@ class BancontactPaymentMethod extends AbstractPaymentMethodType { */ public function get_payment_method_script_handles() { wp_register_script( - 'ppcp-bancontact-checkout-block', - trailingslashit( $this->module_url ) . 'assets/js/bancontact-checkout-block.js', + 'ppcp-bancontact-payment-method', + trailingslashit( $this->module_url ) . 'assets/js/bancontact-payment-method.js', array(), $this->version, true ); - return array( 'ppcp-bancontact-checkout-block' ); + return array( 'ppcp-bancontact-payment-method' ); } /** @@ -81,6 +81,7 @@ class BancontactPaymentMethod extends AbstractPaymentMethodType { 'id' => $this->name, 'title' => $this->gateway->title, 'description' => $this->gateway->description, + 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_bancontact_color.svg' ), ); } } diff --git a/modules/ppcp-local-alternative-payment-methods/webpack.config.js b/modules/ppcp-local-alternative-payment-methods/webpack.config.js index 65053736f..bf41e6d06 100644 --- a/modules/ppcp-local-alternative-payment-methods/webpack.config.js +++ b/modules/ppcp-local-alternative-payment-methods/webpack.config.js @@ -9,8 +9,8 @@ module.exports = { target: 'web', plugins: [ new DependencyExtractionWebpackPlugin() ], entry: { - 'bancontact-checkout-block': path.resolve( - './resources/js/bancontact-checkout-block.js' + 'bancontact-payment-method': path.resolve( + './resources/js/bancontact-payment-method.js' ), }, output: { From 76c723029d51077743bbd0b0f6d2508d621003fc Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 12 Aug 2024 16:06:44 +0200 Subject: [PATCH 07/29] Show bancontact payment gateway only if match eligibility --- .../LocalAlternativePaymentMethodsModule.php | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 7c794f5cc..ab6956728 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -30,12 +30,22 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { ); } - public function run(ContainerInterface $c): void { - add_filter('woocommerce_payment_gateways', function ($methods) use ($c) { - $methods[] = $c->get('ppcp-local-apms.bancontact.wc-gateway'); + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): void { + add_filter( + 'woocommerce_available_payment_gateways', + function ( $methods ) use ( $c ) { + $customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country(); + $site_currency = get_woocommerce_currency(); + if ( $customer_country === 'BE' && $site_currency === 'EUR' ) { + $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); + } - return $methods; - }); + return $methods; + } + ); add_action( 'woocommerce_blocks_payment_method_type_registration', From 86acc00f853599cb2d32db36ae9e5e86b6ffc2d1 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 12 Aug 2024 17:19:40 +0200 Subject: [PATCH 08/29] Hide bancontact from PayPal buttons --- modules/ppcp-api-client/src/Endpoint/Orders.php | 5 +++-- .../src/BancontactGateway.php | 8 ++------ .../src/LocalAlternativePaymentMethodsModule.php | 11 +++++++++++ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/modules/ppcp-api-client/src/Endpoint/Orders.php b/modules/ppcp-api-client/src/Endpoint/Orders.php index 555404b21..82da943c3 100644 --- a/modules/ppcp-api-client/src/Endpoint/Orders.php +++ b/modules/ppcp-api-client/src/Endpoint/Orders.php @@ -73,8 +73,9 @@ class Orders { $url = trailingslashit( $this->host ) . 'v2/checkout/orders'; $default_headers = array( - 'Authorization' => 'Bearer ' . $bearer->token(), - 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + 'PayPal-Request-Id' => uniqid( 'ppcp-', true ), ); $headers = array_merge( $default_headers, diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php index e013fcfc1..e6d511ee0 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php @@ -129,15 +129,11 @@ class BancontactGateway extends WC_Payment_Gateway { 'application_context' => array( 'locale' => 'en-BE', 'return_url' => $this->get_return_url( $wc_order ), - 'cancel_url' => $this->get_return_url( $wc_order ), + 'cancel_url' => wc_get_checkout_url(), ), ); - $headers = array( - 'PayPal-Request-Id' => uniqid( 'ppcp-', true ), - ); - - $response = $this->orders_endpoint->create( $request_body, $headers ); + $response = $this->orders_endpoint->create( $request_body ); $body = json_decode( $response['body'] ); $payer_action = ''; diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index ab6956728..9450929bf 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -53,5 +53,16 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { $payment_method_registry->register( $c->get( 'ppcp-local-apms.bancontact.payment-method' ) ); } ); + + add_filter( + 'woocommerce_paypal_payments_localized_script_data', + function ( array $data ) { + $default_disable_funding = $data['url_params']['disable-funding'] ?? ''; + $disable_funding = array_merge( array( 'bancontact' ), array_filter( explode( ',', $default_disable_funding ) ) ); + $data['url_params']['disable-funding'] = implode( ',', array_unique( $disable_funding ) ); + + return $data; + } + ); } } From 10172907df1450dce9cead447df2779c9d48143d Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 13 Aug 2024 16:14:15 +0200 Subject: [PATCH 09/29] Handle errors from PayPal response --- .../src/BancontactGateway.php | 24 ++++++++++-- .../LocalAlternativePaymentMethodsModule.php | 38 ++++++++++++++++++- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php index e6d511ee0..6cc62875a 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php @@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; +use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException; /** * Class BancontactGateway @@ -111,7 +112,7 @@ class BancontactGateway extends WC_Payment_Gateway { 'payment_source' => array( 'bancontact' => array( 'country_code' => 'BE', - 'name' => 'John Doe', + 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), ), ), 'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL', @@ -129,12 +130,25 @@ class BancontactGateway extends WC_Payment_Gateway { 'application_context' => array( 'locale' => 'en-BE', 'return_url' => $this->get_return_url( $wc_order ), - 'cancel_url' => wc_get_checkout_url(), + 'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ), ), ); - $response = $this->orders_endpoint->create( $request_body ); - $body = json_decode( $response['body'] ); + try { + $response = $this->orders_endpoint->create( $request_body ); + } catch ( RuntimeException $exception ) { + $wc_order->update_status( + 'failed', + $exception->getMessage() + ); + + return array( + 'result' => 'failure', + 'redirect' => wc_get_checkout_url(), + ); + } + + $body = json_decode( $response['body'] ); $payer_action = ''; foreach ( $body->links as $link ) { @@ -143,6 +157,8 @@ class BancontactGateway extends WC_Payment_Gateway { } } + WC()->cart->empty_cart(); + return array( 'result' => 'success', 'redirect' => esc_url( $payer_action ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 9450929bf..10981bd6a 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry; +use WC_Order; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; @@ -37,10 +38,14 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { add_filter( 'woocommerce_available_payment_gateways', function ( $methods ) use ( $c ) { + if ( is_admin() ) { + return $methods; + } + $customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country(); $site_currency = get_woocommerce_currency(); if ( $customer_country === 'BE' && $site_currency === 'EUR' ) { - $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); + $methods[ BancontactGateway::ID ] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); } return $methods; @@ -64,5 +69,36 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { return $data; } ); + + add_action( + 'woocommerce_before_thankyou', + function( $order_id ) { + $order = wc_get_order( $order_id ); + if ( ! $order instanceof WC_Order ) { + return; + } + + // phpcs:disable WordPress.Security.NonceVerification.Recommended + $cancelled = wc_clean( wp_unslash( $_GET['cancelled'] ?? '' ) ); + $order_key = wc_clean( wp_unslash( $_GET['key'] ?? '' ) ); + // phpcs:enable + + if ( + $order->get_payment_method() !== BancontactGateway::ID + || ! $cancelled + || $order->get_order_key() !== $order_key + ) { + return; + } + + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $error_code = wc_clean( wp_unslash( $_GET['errorcode'] ?? '' ) ); + if ( $error_code === 'processing_error' || $error_code === 'payment_error' ) { + $order->update_status( 'failed', __( "The payment can't be processed because of an error.", 'woocommerce-paypal-payments' ) ); + + add_filter( 'woocommerce_order_has_status', '__return_true' ); + } + } + ); } } From 4879425e1d23d5d7660462cabbeb2cb2328c8f2e Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Mon, 19 Aug 2024 15:47:38 +0200 Subject: [PATCH 10/29] Show or hide bancontact in checkout page based on country and currency --- .../LocalAlternativePaymentMethodsModule.php | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 10981bd6a..13e6323df 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -36,16 +36,27 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { */ public function run( ContainerInterface $c ): void { add_filter( - 'woocommerce_available_payment_gateways', + 'woocommerce_payment_gateways', function ( $methods ) use ( $c ) { if ( is_admin() ) { + $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); return $methods; } - $customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country(); - $site_currency = get_woocommerce_currency(); - if ( $customer_country === 'BE' && $site_currency === 'EUR' ) { - $methods[ BancontactGateway::ID ] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); + return $methods; + } + ); + + add_filter( + 'woocommerce_available_payment_gateways', + function ( $methods ) use ( $c ) { + if ( ! is_admin() ) { + $customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country(); + $site_currency = get_woocommerce_currency(); + if ( $customer_country === 'BE' && $site_currency === 'EUR' ) { + $methods[ BancontactGateway::ID ] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); + return $methods; + } } return $methods; From 01275125350cebe76443dcfbc5d7175de7d89f3e Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 20 Aug 2024 11:08:03 +0200 Subject: [PATCH 11/29] Fix show payment based on country --- .../src/LocalAlternativePaymentMethodsModule.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 13e6323df..cb3c55ef6 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -38,10 +38,7 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { add_filter( 'woocommerce_payment_gateways', function ( $methods ) use ( $c ) { - if ( is_admin() ) { - $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); - return $methods; - } + $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); return $methods; } @@ -49,7 +46,16 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { add_filter( 'woocommerce_available_payment_gateways', + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ function ( $methods ) use ( $c ) { + if ( ! is_array( $methods ) ) { + return $methods; + } + if ( ! is_admin() ) { $customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country(); $site_currency = get_woocommerce_currency(); From 27fd033393f4832b8c813c315e4084b2ab9f34f0 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 20 Aug 2024 11:24:10 +0200 Subject: [PATCH 12/29] Fix show payment based on country --- .../src/LocalAlternativePaymentMethodsModule.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index cb3c55ef6..897821c56 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -38,7 +38,9 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { add_filter( 'woocommerce_payment_gateways', function ( $methods ) use ( $c ) { - $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); + if ( is_admin() ) { + $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); + } return $methods; } From fee2b0ff0f5b8eb73897afe28b094c8e9c2d8563 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 20 Aug 2024 11:42:29 +0200 Subject: [PATCH 13/29] Throw api exception if wrong response code --- modules/ppcp-api-client/src/Endpoint/Orders.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-api-client/src/Endpoint/Orders.php b/modules/ppcp-api-client/src/Endpoint/Orders.php index 82da943c3..568a16705 100644 --- a/modules/ppcp-api-client/src/Endpoint/Orders.php +++ b/modules/ppcp-api-client/src/Endpoint/Orders.php @@ -13,6 +13,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint; use Psr\Log\LoggerInterface; use RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; +use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WP_Error; /** @@ -66,7 +67,8 @@ class Orders { * @param array $request_body The request body. * @param array $headers The request headers. * @return array - * @throws RuntimeException If something is wrong with the request. + * @throws RuntimeException If something went wrong with the request. + * @throws PayPalApiException If something went wrong with the PayPal API request. */ public function create( array $request_body, array $headers = array() ): array { $bearer = $this->bearer->bearer(); @@ -93,6 +95,14 @@ class Orders { throw new RuntimeException( $response->get_error_message() ); } + $status_code = (int) wp_remote_retrieve_response_code( $response ); + if ( $status_code !== 200 ) { + throw new PayPalApiException( + json_decode( $response['body'] ), + $status_code + ); + } + return $response; } } From 3dc3026c2956788c5ec267ff24c53527801a54f7 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 20 Aug 2024 12:25:22 +0200 Subject: [PATCH 14/29] Add refunds support for bancontact gateway and fix tests --- .../ppcp-googlepay/src/GooglePayGateway.php | 5 ++ .../services.php | 16 +++-- .../src/BancontactGateway.php | 69 +++++++++++++++++-- .../PHPUnit/ApiClient/Endpoint/OrdersTest.php | 26 ------- tests/e2e/PHPUnit/OrdersTest.php | 12 ++-- 5 files changed, 84 insertions(+), 44 deletions(-) delete mode 100644 tests/PHPUnit/ApiClient/Endpoint/OrdersTest.php diff --git a/modules/ppcp-googlepay/src/GooglePayGateway.php b/modules/ppcp-googlepay/src/GooglePayGateway.php index 26a84f326..235a67a85 100644 --- a/modules/ppcp-googlepay/src/GooglePayGateway.php +++ b/modules/ppcp-googlepay/src/GooglePayGateway.php @@ -92,6 +92,11 @@ class GooglePayGateway extends WC_Payment_Gateway { ) { $this->id = self::ID; + $this->supports = array( + 'refunds', + 'products', + ); + $this->method_title = __( 'Google Pay (via PayPal) ', 'woocommerce-paypal-payments' ); $this->method_description = __( 'The separate payment gateway with the Google Pay button. If disabled, the button is included in the PayPal gateway.', 'woocommerce-paypal-payments' ); diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index c42709949..77205f622 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -12,7 +12,7 @@ namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; return array( - 'ppcp-local-apms.url' => static function ( ContainerInterface $container ): string { + 'ppcp-local-apms.url' => static function ( ContainerInterface $container ): string { /** * The path cannot be false. * @@ -23,17 +23,19 @@ return array( dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php' ); }, - 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { + 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { return new BancontactGateway( $container->get( 'api.endpoint.orders' ), - $container->get( 'api.factory.purchase-unit' ) + $container->get( 'api.factory.purchase-unit' ), + $container->get( 'wcgateway.processor.refunds' ), + $container->get( 'wcgateway.transaction-url-provider' ) ); }, - 'ppcp-local-apms.bancontact.payment-method' => static function(ContainerInterface $container): BancontactPaymentMethod { + 'ppcp-local-apms.bancontact.payment-method' => static function( ContainerInterface $container ): BancontactPaymentMethod { return new BancontactPaymentMethod( - $container->get('ppcp-local-apms.url'), + $container->get( 'ppcp-local-apms.url' ), $container->get( 'ppcp.asset-version' ), - $container->get('ppcp-local-apms.bancontact.wc-gateway') + $container->get( 'ppcp-local-apms.bancontact.wc-gateway' ) ); - } + }, ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php index 6cc62875a..29c8c35d4 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php @@ -13,6 +13,8 @@ use WC_Payment_Gateway; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; +use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; /** * Class BancontactGateway @@ -35,18 +37,41 @@ class BancontactGateway extends WC_Payment_Gateway { */ private $purchase_unit_factory; + /** + * The Refund Processor. + * + * @var RefundProcessor + */ + private $refund_processor; + + /** + * Service able to provide transaction url for an order. + * + * @var TransactionUrlProvider + */ + protected $transaction_url_provider; + /** * BancontactGateway constructor. * - * @param Orders $orders_endpoint PayPal Orders endpoint. - * @param PurchaseUnitFactory $purchase_unit_factory Purchase unit factory. + * @param Orders $orders_endpoint PayPal Orders endpoint. + * @param PurchaseUnitFactory $purchase_unit_factory Purchase unit factory. + * @param RefundProcessor $refund_processor The Refund Processor. + * @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order. */ public function __construct( Orders $orders_endpoint, - PurchaseUnitFactory $purchase_unit_factory + PurchaseUnitFactory $purchase_unit_factory, + RefundProcessor $refund_processor, + TransactionUrlProvider $transaction_url_provider ) { $this->id = self::ID; + $this->supports = array( + 'refunds', + 'products', + ); + $this->method_title = __( 'Bancontact', 'woocommerce-paypal-payments' ); $this->method_description = __( 'Bancontact', 'woocommerce-paypal-payments' ); @@ -60,8 +85,10 @@ class BancontactGateway extends WC_Payment_Gateway { add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); - $this->orders_endpoint = $orders_endpoint; - $this->purchase_unit_factory = $purchase_unit_factory; + $this->orders_endpoint = $orders_endpoint; + $this->purchase_unit_factory = $purchase_unit_factory; + $this->refund_processor = $refund_processor; + $this->transaction_url_provider = $transaction_url_provider; } /** @@ -164,4 +191,36 @@ class BancontactGateway extends WC_Payment_Gateway { 'redirect' => esc_url( $payer_action ), ); } + + /** + * Process refund. + * + * If the gateway declares 'refunds' support, this will allow it to refund. + * a passed in amount. + * + * @param int $order_id Order ID. + * @param float $amount Refund amount. + * @param string $reason Refund reason. + * @return boolean True or false based on success, or a WP_Error object. + */ + public function process_refund( $order_id, $amount = null, $reason = '' ) { + $order = wc_get_order( $order_id ); + if ( ! is_a( $order, \WC_Order::class ) ) { + return false; + } + return $this->refund_processor->process( $order, (float) $amount, (string) $reason ); + } + + /** + * Return transaction url for this gateway and given order. + * + * @param \WC_Order $order WC order to get transaction url by. + * + * @return string + */ + public function get_transaction_url( $order ): string { + $this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order ); + + return parent::get_transaction_url( $order ); + } } diff --git a/tests/PHPUnit/ApiClient/Endpoint/OrdersTest.php b/tests/PHPUnit/ApiClient/Endpoint/OrdersTest.php deleted file mode 100644 index 1033a015b..000000000 --- a/tests/PHPUnit/ApiClient/Endpoint/OrdersTest.php +++ /dev/null @@ -1,26 +0,0 @@ -shouldReceive('token')->andReturn(''); - $bearer->shouldReceive('bearer')->andReturn($token); - - $sut = new Orders('', $bearer); - - expect('wp_remote_get')->andReturn([]); - - $this->assertEquals([], $sut->create([])); - } -} diff --git a/tests/e2e/PHPUnit/OrdersTest.php b/tests/e2e/PHPUnit/OrdersTest.php index da9dc990e..c5b0a78c8 100644 --- a/tests/e2e/PHPUnit/OrdersTest.php +++ b/tests/e2e/PHPUnit/OrdersTest.php @@ -11,7 +11,11 @@ class OrdersTest extends TestCase $host = 'https://api-m.sandbox.paypal.com'; $container = $this->getContainer(); - $orders = new Orders($host, $container->get('api.bearer')); + $orders = new Orders( + $host, + $container->get('api.bearer'), + $container->get( 'woocommerce.logger.woocommerce' ) + ); $requestBody = [ "intent" => "CAPTURE", @@ -38,11 +42,7 @@ class OrdersTest extends TestCase ] ]; - $headers = array( - 'PayPal-Request-Id' => uniqid( 'ppcp-', true ), - ); - - $result = $orders->create($requestBody, $headers); + $result = $orders->create($requestBody); $this->assertEquals(200, $result['response']['code']); } From 0a3aa70ea94a27cf2a86990b11d96b5e88862d04 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 20 Aug 2024 15:00:06 +0200 Subject: [PATCH 15/29] Add blik gateway for classic checkout --- .../services.php | 8 + .../src/BlikGateway.php | 227 ++++++++++++++++++ .../LocalAlternativePaymentMethodsModule.php | 12 +- 3 files changed, 241 insertions(+), 6 deletions(-) create mode 100644 modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index 77205f622..f36370668 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -31,6 +31,14 @@ return array( $container->get( 'wcgateway.transaction-url-provider' ) ); }, + 'ppcp-local-apms.blik.wc-gateway' => static function ( ContainerInterface $container ): BlikGateway { + return new BlikGateway( + $container->get( 'api.endpoint.orders' ), + $container->get( 'api.factory.purchase-unit' ), + $container->get( 'wcgateway.processor.refunds' ), + $container->get( 'wcgateway.transaction-url-provider' ) + ); + }, 'ppcp-local-apms.bancontact.payment-method' => static function( ContainerInterface $container ): BancontactPaymentMethod { return new BancontactPaymentMethod( $container->get( 'ppcp-local-apms.url' ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php new file mode 100644 index 000000000..39284e8bd --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php @@ -0,0 +1,227 @@ +id = self::ID; + + $this->supports = array( + 'refunds', + 'products', + ); + + $this->method_title = __( 'Blik', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'Blik', 'woocommerce-paypal-payments' ); + + $this->title = $this->get_option( 'title', __( 'Blik', 'woocommerce-paypal-payments' ) ); + $this->description = $this->get_option( 'description', '' ); + + $this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_blik_color.svg' ); + + $this->init_form_fields(); + $this->init_settings(); + + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + + $this->orders_endpoint = $orders_endpoint; + $this->purchase_unit_factory = $purchase_unit_factory; + $this->refund_processor = $refund_processor; + $this->transaction_url_provider = $transaction_url_provider; + } + + /** + * Initialize the form fields. + */ + public function init_form_fields() { + $this->form_fields = array( + 'enabled' => array( + 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'Blik', 'woocommerce-paypal-payments' ), + 'default' => 'no', + 'desc_tip' => true, + 'description' => __( 'Enable/Disable Blik payment gateway.', 'woocommerce-paypal-payments' ), + ), + 'title' => array( + 'title' => __( 'Title', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->title, + 'desc_tip' => true, + 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + 'description' => array( + 'title' => __( 'Description', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->description, + 'desc_tip' => true, + 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + ); + } + + /** + * Processes the order. + * + * @param int $order_id The WC order ID. + * @return array + */ + public function process_payment( $order_id ) { + $wc_order = wc_get_order( $order_id ); + $wc_order->update_status( 'on-hold', __( 'Awaiting Blik to confirm the payment.', 'woocommerce-paypal-payments' ) ); + + $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); + $amount = $purchase_unit->amount()->to_array(); + + $request_body = array( + 'intent' => 'CAPTURE', + 'payment_source' => array( + 'blik' => array( + 'country_code' => 'PL', + 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), + 'email' => $wc_order->get_billing_email(), + ), + ), + 'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL', + 'purchase_units' => array( + array( + 'reference_id' => $purchase_unit->reference_id(), + 'amount' => array( + 'currency_code' => $amount['currency_code'], + 'value' => $amount['value'], + ), + 'custom_id' => $purchase_unit->custom_id(), + 'invoice_id' => $purchase_unit->invoice_id(), + ), + ), + 'application_context' => array( + 'locale' => 'en-PL', + 'return_url' => $this->get_return_url( $wc_order ), + 'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ), + ), + ); + + try { + $response = $this->orders_endpoint->create( $request_body ); + } catch ( RuntimeException $exception ) { + $wc_order->update_status( + 'failed', + $exception->getMessage() + ); + + return array( + 'result' => 'failure', + 'redirect' => wc_get_checkout_url(), + ); + } + + $body = json_decode( $response['body'] ); + + $payer_action = ''; + foreach ( $body->links as $link ) { + if ( $link->rel === 'payer-action' ) { + $payer_action = $link->href; + } + } + + WC()->cart->empty_cart(); + + return array( + 'result' => 'success', + 'redirect' => esc_url( $payer_action ), + ); + } + + /** + * Process refund. + * + * If the gateway declares 'refunds' support, this will allow it to refund. + * a passed in amount. + * + * @param int $order_id Order ID. + * @param float $amount Refund amount. + * @param string $reason Refund reason. + * @return boolean True or false based on success, or a WP_Error object. + */ + public function process_refund( $order_id, $amount = null, $reason = '' ) { + $order = wc_get_order( $order_id ); + if ( ! is_a( $order, \WC_Order::class ) ) { + return false; + } + return $this->refund_processor->process( $order, (float) $amount, (string) $reason ); + } + + /** + * Return transaction url for this gateway and given order. + * + * @param \WC_Order $order WC order to get transaction url by. + * + * @return string + */ + public function get_transaction_url( $order ): string { + $this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order ); + + return parent::get_transaction_url( $order ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 897821c56..6443e6277 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -40,6 +40,7 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { function ( $methods ) use ( $c ) { if ( is_admin() ) { $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); + $methods[] = $c->get( 'ppcp-local-apms.blik.wc-gateway' ); } return $methods; @@ -54,16 +55,15 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { * @psalm-suppress MissingClosureParamType */ function ( $methods ) use ( $c ) { - if ( ! is_array( $methods ) ) { - return $methods; - } - if ( ! is_admin() ) { $customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country(); $site_currency = get_woocommerce_currency(); + if ( $customer_country === 'BE' && $site_currency === 'EUR' ) { $methods[ BancontactGateway::ID ] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); - return $methods; + } + if ( $customer_country === 'PL' && $site_currency === 'PLN' ) { + $methods[ BlikGateway::ID ] = $c->get( 'ppcp-local-apms.blik.wc-gateway' ); } } @@ -82,7 +82,7 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { 'woocommerce_paypal_payments_localized_script_data', function ( array $data ) { $default_disable_funding = $data['url_params']['disable-funding'] ?? ''; - $disable_funding = array_merge( array( 'bancontact' ), array_filter( explode( ',', $default_disable_funding ) ) ); + $disable_funding = array_merge( array( 'bancontact', 'blik' ), array_filter( explode( ',', $default_disable_funding ) ) ); $data['url_params']['disable-funding'] = implode( ',', array_unique( $disable_funding ) ); return $data; From 11693c8df2ea7bca0e60f8f68ca97d93255679b9 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 20 Aug 2024 16:02:35 +0200 Subject: [PATCH 16/29] Add blik payment --- .../resources/js/blik-block.js | 9 ++ .../resources/js/blik-payment-method.js | 18 ++++ .../services.php | 7 ++ .../src/BancontactPaymentMethod.php | 24 +++-- .../src/BlikPaymentMethod.php | 97 +++++++++++++++++++ .../LocalAlternativePaymentMethodsModule.php | 26 +++-- .../webpack.config.js | 3 + 7 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/blik-block.js create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/blik-payment-method.js create mode 100644 modules/ppcp-local-alternative-payment-methods/src/BlikPaymentMethod.php diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/blik-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/blik-block.js new file mode 100644 index 000000000..7075487bf --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/blik-block.js @@ -0,0 +1,9 @@ +export function Blik( { config, components } ) { + const { PaymentMethodIcons } = components; + + return ( +
+ +
+ ); +} diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/blik-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/blik-payment-method.js new file mode 100644 index 000000000..2f4c7e252 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/blik-payment-method.js @@ -0,0 +1,18 @@ +import { registerPaymentMethod } from '@woocommerce/blocks-registry'; +import { Blik } from './blik-block'; + +const config = wc.wcSettings.getSetting( 'ppcp-blik_data' ); + +registerPaymentMethod( { + name: config.id, + label:
, + content: , + edit:
, + ariaLabel: config.title, + canMakePayment: () => { + return true; + }, + supports: { + features: config.supports, + }, +} ); diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index f36370668..d3589dc73 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -46,4 +46,11 @@ return array( $container->get( 'ppcp-local-apms.bancontact.wc-gateway' ) ); }, + 'ppcp-local-apms.blik.payment-method' => static function( ContainerInterface $container ): BlikPaymentMethod { + return new BlikPaymentMethod( + $container->get( 'ppcp-local-apms.url' ), + $container->get( 'ppcp.asset-version' ), + $container->get( 'ppcp-local-apms.blik.wc-gateway' ) + ); + }, ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php index 1430956f8..d26285df7 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactPaymentMethod.php @@ -11,6 +11,9 @@ namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods; use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType; +/** + * Class BancontactPaymentMethod + */ class BancontactPaymentMethod extends AbstractPaymentMethodType { /** @@ -34,16 +37,23 @@ class BancontactPaymentMethod extends AbstractPaymentMethodType { */ private $gateway; + /** + * BancontactPaymentMethod constructor. + * + * @param string $module_url The URL of this module. + * @param string $version The assets version. + * @param BancontactGateway $gateway Bancontact WC gateway. + */ public function __construct( string $module_url, string $version, BancontactGateway $gateway ) { $this->module_url = $module_url; - $this->version = $version; - $this->gateway = $gateway; + $this->version = $version; + $this->gateway = $gateway; - $this->name = BancontactGateway::ID; + $this->name = BancontactGateway::ID; } /** @@ -78,10 +88,10 @@ class BancontactPaymentMethod extends AbstractPaymentMethodType { */ public function get_payment_method_data() { return array( - 'id' => $this->name, - 'title' => $this->gateway->title, - 'description' => $this->gateway->description, - 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_bancontact_color.svg' ), + 'id' => $this->name, + 'title' => $this->gateway->title, + 'description' => $this->gateway->description, + 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_bancontact_color.svg' ), ); } } diff --git a/modules/ppcp-local-alternative-payment-methods/src/BlikPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/BlikPaymentMethod.php new file mode 100644 index 000000000..073df2de0 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/BlikPaymentMethod.php @@ -0,0 +1,97 @@ +module_url = $module_url; + $this->version = $version; + $this->gateway = $gateway; + + $this->name = BlikGateway::ID; + } + + /** + * {@inheritDoc} + */ + public function initialize() {} + + /** + * {@inheritDoc} + */ + public function is_active() { + return true; + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_script_handles() { + wp_register_script( + 'ppcp-blick-payment-method', + trailingslashit( $this->module_url ) . 'assets/js/blik-payment-method.js', + array(), + $this->version, + true + ); + + return array( 'ppcp-blick-payment-method' ); + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_data() { + return array( + 'id' => $this->name, + 'title' => $this->gateway->title, + 'description' => $this->gateway->description, + 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_blik_color.svg' ), + ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 6443e6277..e0d19b01f 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -37,12 +37,19 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { public function run( ContainerInterface $c ): void { add_filter( 'woocommerce_payment_gateways', + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ function ( $methods ) use ( $c ) { - if ( is_admin() ) { - $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); - $methods[] = $c->get( 'ppcp-local-apms.blik.wc-gateway' ); + if ( ! is_array( $methods ) ) { + return $methods; } + $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); + $methods[] = $c->get( 'ppcp-local-apms.blik.wc-gateway' ); + return $methods; } ); @@ -55,15 +62,19 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { * @psalm-suppress MissingClosureParamType */ function ( $methods ) use ( $c ) { + if ( ! is_array( $methods ) ) { + return $methods; + } + if ( ! is_admin() ) { $customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country(); $site_currency = get_woocommerce_currency(); - if ( $customer_country === 'BE' && $site_currency === 'EUR' ) { - $methods[ BancontactGateway::ID ] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); + if ( $customer_country !== 'BE' || $site_currency !== 'EUR' ) { + unset( $methods[ BancontactGateway::ID ] ); } - if ( $customer_country === 'PL' && $site_currency === 'PLN' ) { - $methods[ BlikGateway::ID ] = $c->get( 'ppcp-local-apms.blik.wc-gateway' ); + if ( $customer_country !== 'PL' || $site_currency !== 'PLN' ) { + unset( $methods[ BlikGateway::ID ] ); } } @@ -75,6 +86,7 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { 'woocommerce_blocks_payment_method_type_registration', function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void { $payment_method_registry->register( $c->get( 'ppcp-local-apms.bancontact.payment-method' ) ); + $payment_method_registry->register( $c->get( 'ppcp-local-apms.blik.payment-method' ) ); } ); diff --git a/modules/ppcp-local-alternative-payment-methods/webpack.config.js b/modules/ppcp-local-alternative-payment-methods/webpack.config.js index bf41e6d06..4e57fe054 100644 --- a/modules/ppcp-local-alternative-payment-methods/webpack.config.js +++ b/modules/ppcp-local-alternative-payment-methods/webpack.config.js @@ -12,6 +12,9 @@ module.exports = { 'bancontact-payment-method': path.resolve( './resources/js/bancontact-payment-method.js' ), + 'blik-payment-method': path.resolve( + './resources/js/blik-payment-method.js' + ), }, output: { path: path.resolve( __dirname, 'assets/' ), From f36d6d08df19232770faf131d50d40112974802c Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 20 Aug 2024 17:27:03 +0200 Subject: [PATCH 17/29] Add eps payment --- .../resources/js/eps-block.js | 9 + .../resources/js/eps-payment-method.js | 18 ++ .../services.php | 15 ++ .../src/EPSGateway.php | 226 ++++++++++++++++++ .../src/EPSPaymentMethod.php | 97 ++++++++ .../LocalAlternativePaymentMethodsModule.php | 7 +- .../webpack.config.js | 3 + 7 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/eps-block.js create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/eps-payment-method.js create mode 100644 modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php create mode 100644 modules/ppcp-local-alternative-payment-methods/src/EPSPaymentMethod.php diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/eps-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/eps-block.js new file mode 100644 index 000000000..051ec8730 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/eps-block.js @@ -0,0 +1,9 @@ +export function EPS( { config, components } ) { + const { PaymentMethodIcons } = components; + + return ( +
+ +
+ ); +} diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/eps-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/eps-payment-method.js new file mode 100644 index 000000000..19d26d971 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/eps-payment-method.js @@ -0,0 +1,18 @@ +import { registerPaymentMethod } from '@woocommerce/blocks-registry'; +import { EPS } from './eps-block'; + +const config = wc.wcSettings.getSetting( 'ppcp-eps_data' ); + +registerPaymentMethod( { + name: config.id, + label:
, + content: , + edit:
, + ariaLabel: config.title, + canMakePayment: () => { + return true; + }, + supports: { + features: config.supports, + }, +} ); diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index d3589dc73..38806ac5e 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -39,6 +39,14 @@ return array( $container->get( 'wcgateway.transaction-url-provider' ) ); }, + 'ppcp-local-apms.eps.wc-gateway' => static function ( ContainerInterface $container ): EPSGateway { + return new EPSGateway( + $container->get( 'api.endpoint.orders' ), + $container->get( 'api.factory.purchase-unit' ), + $container->get( 'wcgateway.processor.refunds' ), + $container->get( 'wcgateway.transaction-url-provider' ) + ); + }, 'ppcp-local-apms.bancontact.payment-method' => static function( ContainerInterface $container ): BancontactPaymentMethod { return new BancontactPaymentMethod( $container->get( 'ppcp-local-apms.url' ), @@ -53,4 +61,11 @@ return array( $container->get( 'ppcp-local-apms.blik.wc-gateway' ) ); }, + 'ppcp-local-apms.eps.payment-method' => static function( ContainerInterface $container ): EPSPaymentMethod { + return new EPSPaymentMethod( + $container->get( 'ppcp-local-apms.url' ), + $container->get( 'ppcp.asset-version' ), + $container->get( 'ppcp-local-apms.eps.wc-gateway' ) + ); + }, ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php b/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php new file mode 100644 index 000000000..ef3094463 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php @@ -0,0 +1,226 @@ +id = self::ID; + + $this->supports = array( + 'refunds', + 'products', + ); + + $this->method_title = __( 'EPS', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'EPS', 'woocommerce-paypal-payments' ); + + $this->title = $this->get_option( 'title', __( 'EPS', 'woocommerce-paypal-payments' ) ); + $this->description = $this->get_option( 'description', '' ); + + $this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_eps_color.svg' ); + + $this->init_form_fields(); + $this->init_settings(); + + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + + $this->orders_endpoint = $orders_endpoint; + $this->purchase_unit_factory = $purchase_unit_factory; + $this->refund_processor = $refund_processor; + $this->transaction_url_provider = $transaction_url_provider; + } + + /** + * Initialize the form fields. + */ + public function init_form_fields() { + $this->form_fields = array( + 'enabled' => array( + 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'EPS', 'woocommerce-paypal-payments' ), + 'default' => 'no', + 'desc_tip' => true, + 'description' => __( 'Enable/Disable EPS payment gateway.', 'woocommerce-paypal-payments' ), + ), + 'title' => array( + 'title' => __( 'Title', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->title, + 'desc_tip' => true, + 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + 'description' => array( + 'title' => __( 'Description', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->description, + 'desc_tip' => true, + 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + ); + } + + /** + * Processes the order. + * + * @param int $order_id The WC order ID. + * @return array + */ + public function process_payment( $order_id ) { + $wc_order = wc_get_order( $order_id ); + $wc_order->update_status( 'on-hold', __( 'Awaiting EPS to confirm the payment.', 'woocommerce-paypal-payments' ) ); + + $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); + $amount = $purchase_unit->amount()->to_array(); + + $request_body = array( + 'intent' => 'CAPTURE', + 'payment_source' => array( + 'eps' => array( + 'country_code' => 'AT', + 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), + ), + ), + 'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL', + 'purchase_units' => array( + array( + 'reference_id' => $purchase_unit->reference_id(), + 'amount' => array( + 'currency_code' => $amount['currency_code'], + 'value' => $amount['value'], + ), + 'custom_id' => $purchase_unit->custom_id(), + 'invoice_id' => $purchase_unit->invoice_id(), + ), + ), + 'application_context' => array( + 'locale' => 'en-AT', + 'return_url' => $this->get_return_url( $wc_order ), + 'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ), + ), + ); + + try { + $response = $this->orders_endpoint->create( $request_body ); + } catch ( RuntimeException $exception ) { + $wc_order->update_status( + 'failed', + $exception->getMessage() + ); + + return array( + 'result' => 'failure', + 'redirect' => wc_get_checkout_url(), + ); + } + + $body = json_decode( $response['body'] ); + + $payer_action = ''; + foreach ( $body->links as $link ) { + if ( $link->rel === 'payer-action' ) { + $payer_action = $link->href; + } + } + + WC()->cart->empty_cart(); + + return array( + 'result' => 'success', + 'redirect' => esc_url( $payer_action ), + ); + } + + /** + * Process refund. + * + * If the gateway declares 'refunds' support, this will allow it to refund. + * a passed in amount. + * + * @param int $order_id Order ID. + * @param float $amount Refund amount. + * @param string $reason Refund reason. + * @return boolean True or false based on success, or a WP_Error object. + */ + public function process_refund( $order_id, $amount = null, $reason = '' ) { + $order = wc_get_order( $order_id ); + if ( ! is_a( $order, \WC_Order::class ) ) { + return false; + } + return $this->refund_processor->process( $order, (float) $amount, (string) $reason ); + } + + /** + * Return transaction url for this gateway and given order. + * + * @param \WC_Order $order WC order to get transaction url by. + * + * @return string + */ + public function get_transaction_url( $order ): string { + $this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order ); + + return parent::get_transaction_url( $order ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/EPSPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/EPSPaymentMethod.php new file mode 100644 index 000000000..c00abdb7d --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/EPSPaymentMethod.php @@ -0,0 +1,97 @@ +module_url = $module_url; + $this->version = $version; + $this->gateway = $gateway; + + $this->name = EPSGateway::ID; + } + + /** + * {@inheritDoc} + */ + public function initialize() {} + + /** + * {@inheritDoc} + */ + public function is_active() { + return true; + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_script_handles() { + wp_register_script( + 'ppcp-eps-payment-method', + trailingslashit( $this->module_url ) . 'assets/js/eps-payment-method.js', + array(), + $this->version, + true + ); + + return array( 'ppcp-eps-payment-method' ); + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_data() { + return array( + 'id' => $this->name, + 'title' => $this->gateway->title, + 'description' => $this->gateway->description, + 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_eps_color.svg' ), + ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index e0d19b01f..d921458f9 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -49,6 +49,7 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); $methods[] = $c->get( 'ppcp-local-apms.blik.wc-gateway' ); + $methods[] = $c->get( 'ppcp-local-apms.eps.wc-gateway' ); return $methods; } @@ -76,6 +77,9 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { if ( $customer_country !== 'PL' || $site_currency !== 'PLN' ) { unset( $methods[ BlikGateway::ID ] ); } + if ( $customer_country !== 'AT' || $site_currency !== 'EUR' ) { + unset( $methods[ EPSGateway::ID ] ); + } } return $methods; @@ -87,6 +91,7 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void { $payment_method_registry->register( $c->get( 'ppcp-local-apms.bancontact.payment-method' ) ); $payment_method_registry->register( $c->get( 'ppcp-local-apms.blik.payment-method' ) ); + $payment_method_registry->register( $c->get( 'ppcp-local-apms.eps.payment-method' ) ); } ); @@ -94,7 +99,7 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { 'woocommerce_paypal_payments_localized_script_data', function ( array $data ) { $default_disable_funding = $data['url_params']['disable-funding'] ?? ''; - $disable_funding = array_merge( array( 'bancontact', 'blik' ), array_filter( explode( ',', $default_disable_funding ) ) ); + $disable_funding = array_merge( array( 'bancontact', 'blik', 'eps' ), array_filter( explode( ',', $default_disable_funding ) ) ); $data['url_params']['disable-funding'] = implode( ',', array_unique( $disable_funding ) ); return $data; diff --git a/modules/ppcp-local-alternative-payment-methods/webpack.config.js b/modules/ppcp-local-alternative-payment-methods/webpack.config.js index 4e57fe054..c44f4d81d 100644 --- a/modules/ppcp-local-alternative-payment-methods/webpack.config.js +++ b/modules/ppcp-local-alternative-payment-methods/webpack.config.js @@ -15,6 +15,9 @@ module.exports = { 'blik-payment-method': path.resolve( './resources/js/blik-payment-method.js' ), + 'eps-payment-method': path.resolve( + './resources/js/eps-payment-method.js' + ), }, output: { path: path.resolve( __dirname, 'assets/' ), From 8df754fc35bfca6ae320c3f4b1f157594bb99f89 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 11:15:12 +0200 Subject: [PATCH 18/29] Add blik and eps payments to error handler --- .../src/LocalAlternativePaymentMethodsModule.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index d921458f9..65c1c692d 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -120,9 +120,9 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { // phpcs:enable if ( - $order->get_payment_method() !== BancontactGateway::ID - || ! $cancelled - || $order->get_order_key() !== $order_key + ! in_array( $order->get_payment_method(), array( BancontactGateway::ID, BlikGateway::ID, EPSGateway::ID ), true ) + || ! $cancelled + || $order->get_order_key() !== $order_key ) { return; } From 5923aeb8b2e1bc85b22d9b193d305a51a341a550 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 11:46:29 +0200 Subject: [PATCH 19/29] Fix psalm --- .../src/LocalAlternativePaymentMethodsModule.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 65c1c692d..46ca5e8df 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -108,6 +108,11 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { add_action( 'woocommerce_before_thankyou', + /** + * Activate is_checkout() on woocommerce/classic-shortcode checkout blocks. + * + * @psalm-suppress MissingClosureParamType + */ function( $order_id ) { $order = wc_get_order( $order_id ); if ( ! $order instanceof WC_Order ) { From 907656ca8838dd0ddb83a24d4e460d579113f81a Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 12:22:08 +0200 Subject: [PATCH 20/29] Refactor to loop list of payment methods --- .../services.php | 19 +++++++ .../LocalAlternativePaymentMethodsModule.php | 55 +++++++++++++------ 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index 38806ac5e..917d4b44c 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -23,6 +23,25 @@ return array( dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php' ); }, + 'ppcp-local-apms.payment-methods' => static function( ContainerInterface $container): array { + return [ + 'bancontact' => array( + 'id' => BancontactGateway::ID, + 'country' => 'BE', + 'currency' => 'EUR', + ), + 'blik' => array( + 'id' => BlikGateway::ID, + 'country' => 'PL', + 'currency' => 'PLN', + ), + 'eps' => array( + 'id' => EPSGateway::ID, + 'country' => 'AT', + 'currency' => 'EUR', + ), + ]; + }, 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { return new BancontactGateway( $container->get( 'api.endpoint.orders' ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 46ca5e8df..2ff5ed729 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -47,9 +47,10 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { return $methods; } - $methods[] = $c->get( 'ppcp-local-apms.bancontact.wc-gateway' ); - $methods[] = $c->get( 'ppcp-local-apms.blik.wc-gateway' ); - $methods[] = $c->get( 'ppcp-local-apms.eps.wc-gateway' ); + $payment_methods = $c->get('ppcp-local-apms.payment-methods'); + foreach ($payment_methods as $key => $value) { + $methods[] = $c->get( 'ppcp-local-apms.' . $key . '.wc-gateway' ); + } return $methods; } @@ -71,14 +72,11 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { $customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country(); $site_currency = get_woocommerce_currency(); - if ( $customer_country !== 'BE' || $site_currency !== 'EUR' ) { - unset( $methods[ BancontactGateway::ID ] ); - } - if ( $customer_country !== 'PL' || $site_currency !== 'PLN' ) { - unset( $methods[ BlikGateway::ID ] ); - } - if ( $customer_country !== 'AT' || $site_currency !== 'EUR' ) { - unset( $methods[ EPSGateway::ID ] ); + $payment_methods = $c->get('ppcp-local-apms.payment-methods'); + foreach ($payment_methods as $payment_method) { + if ( $customer_country !== $payment_method['country'] || $site_currency !== $payment_method['currency'] ) { + unset( $methods[ $payment_method['id'] ] ); + } } } @@ -89,17 +87,20 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { add_action( 'woocommerce_blocks_payment_method_type_registration', function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void { - $payment_method_registry->register( $c->get( 'ppcp-local-apms.bancontact.payment-method' ) ); - $payment_method_registry->register( $c->get( 'ppcp-local-apms.blik.payment-method' ) ); - $payment_method_registry->register( $c->get( 'ppcp-local-apms.eps.payment-method' ) ); + $payment_methods = $c->get('ppcp-local-apms.payment-methods'); + foreach ($payment_methods as $key => $value) { + $payment_method_registry->register( $c->get( 'ppcp-local-apms.' . $key . '.payment-method' ) ); + } } ); add_filter( 'woocommerce_paypal_payments_localized_script_data', - function ( array $data ) { + function ( array $data ) use ($c) { + $payment_methods = $c->get('ppcp-local-apms.payment-methods'); + $default_disable_funding = $data['url_params']['disable-funding'] ?? ''; - $disable_funding = array_merge( array( 'bancontact', 'blik', 'eps' ), array_filter( explode( ',', $default_disable_funding ) ) ); + $disable_funding = array_merge( array_keys( $payment_methods ), array_filter( explode( ',', $default_disable_funding ) ) ); $data['url_params']['disable-funding'] = implode( ',', array_unique( $disable_funding ) ); return $data; @@ -113,7 +114,7 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { * * @psalm-suppress MissingClosureParamType */ - function( $order_id ) { + function( $order_id ) use($c) { $order = wc_get_order( $order_id ); if ( ! $order instanceof WC_Order ) { return; @@ -124,8 +125,9 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { $order_key = wc_clean( wp_unslash( $_GET['key'] ?? '' ) ); // phpcs:enable + $payment_methods = $c->get('ppcp-local-apms.payment-methods'); if ( - ! in_array( $order->get_payment_method(), array( BancontactGateway::ID, BlikGateway::ID, EPSGateway::ID ), true ) + ! $this->is_local_apm($order->get_payment_method(), $payment_methods) || ! $cancelled || $order->get_order_key() !== $order_key ) { @@ -142,4 +144,21 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { } ); } + + /** + * Check if given payment method is a local APM. + * + * @param string $selected_payment_method Selected payment method. + * @param array $payment_methods Available local APMs. + * @return bool + */ + private function is_local_apm(string $selected_payment_method, array $payment_methods): bool { + foreach ($payment_methods as $payment_method) { + if($payment_method['id'] === $selected_payment_method) { + return true; + } + } + + return false; + } } From 6dee62747c7c37a1e95f5cd920e2fa4cdeb6190e Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 13:04:16 +0200 Subject: [PATCH 21/29] Add ideal gateway --- .../resources/js/ideal-block.js | 9 + .../resources/js/ideal-payment-method.js | 18 ++ .../services.php | 20 ++ .../src/IDealGateway.php | 230 ++++++++++++++++++ .../src/IDealPaymentMethod.php | 97 ++++++++ .../webpack.config.js | 3 + 6 files changed, 377 insertions(+) create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/ideal-block.js create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js create mode 100644 modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php create mode 100644 modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-block.js new file mode 100644 index 000000000..8cb989da3 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-block.js @@ -0,0 +1,9 @@ +export function IDeal( { config, components } ) { + const { PaymentMethodIcons } = components; + + return ( +
+ +
+ ); +} diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js new file mode 100644 index 000000000..8a7d335fd --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js @@ -0,0 +1,18 @@ +import { registerPaymentMethod } from '@woocommerce/blocks-registry'; +import { IDeal } from './ideal-block'; + +const config = wc.wcSettings.getSetting( 'ppcp-eps_data' ); + +registerPaymentMethod( { + name: config.id, + label:
, + content: , + edit:
, + ariaLabel: config.title, + canMakePayment: () => { + return true; + }, + supports: { + features: config.supports, + }, +} ); diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index 917d4b44c..f71b20594 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -40,6 +40,11 @@ return array( 'country' => 'AT', 'currency' => 'EUR', ), + 'ideal' => array( + 'id' => IDealGateway::ID, + 'country' => 'NL', + 'currency' => 'EUR', + ), ]; }, 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { @@ -66,6 +71,14 @@ return array( $container->get( 'wcgateway.transaction-url-provider' ) ); }, + 'ppcp-local-apms.ideal.wc-gateway' => static function ( ContainerInterface $container ): IDealGateway { + return new IDealGateway( + $container->get( 'api.endpoint.orders' ), + $container->get( 'api.factory.purchase-unit' ), + $container->get( 'wcgateway.processor.refunds' ), + $container->get( 'wcgateway.transaction-url-provider' ) + ); + }, 'ppcp-local-apms.bancontact.payment-method' => static function( ContainerInterface $container ): BancontactPaymentMethod { return new BancontactPaymentMethod( $container->get( 'ppcp-local-apms.url' ), @@ -87,4 +100,11 @@ return array( $container->get( 'ppcp-local-apms.eps.wc-gateway' ) ); }, + 'ppcp-local-apms.ideal.payment-method' => static function( ContainerInterface $container ): IDealPaymentMethod { + return new IDealPaymentMethod( + $container->get( 'ppcp-local-apms.url' ), + $container->get( 'ppcp.asset-version' ), + $container->get( 'ppcp-local-apms.ideal.wc-gateway' ) + ); + }, ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php b/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php new file mode 100644 index 000000000..2b52bef28 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php @@ -0,0 +1,230 @@ +id = self::ID; + + $this->supports = array( + 'refunds', + 'products', + ); + + $this->method_title = __( 'iDeal', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'iDeal', 'woocommerce-paypal-payments' ); + + $this->title = $this->get_option( 'title', __( 'iDeal', 'woocommerce-paypal-payments' ) ); + $this->description = $this->get_option( 'description', '' ); + + $this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_ideal_color.svg' ); + + $this->init_form_fields(); + $this->init_settings(); + + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + + $this->orders_endpoint = $orders_endpoint; + $this->purchase_unit_factory = $purchase_unit_factory; + $this->refund_processor = $refund_processor; + $this->transaction_url_provider = $transaction_url_provider; + } + + /** + * Initialize the form fields. + */ + public function init_form_fields() { + $this->form_fields = array( + 'enabled' => array( + 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'iDeal', 'woocommerce-paypal-payments' ), + 'default' => 'no', + 'desc_tip' => true, + 'description' => __( 'Enable/Disable iDeal payment gateway.', 'woocommerce-paypal-payments' ), + ), + 'title' => array( + 'title' => __( 'Title', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->title, + 'desc_tip' => true, + 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + 'description' => array( + 'title' => __( 'Description', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->description, + 'desc_tip' => true, + 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + ); + } + + /** + * Processes the order. + * + * @param int $order_id The WC order ID. + * @return array + */ + public function process_payment( $order_id ) { + $wc_order = wc_get_order( $order_id ); + $wc_order->update_status( 'on-hold', __( 'Awaiting iDeal to confirm the payment.', 'woocommerce-paypal-payments' ) ); + + $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); + $amount = $purchase_unit->amount()->to_array(); + + $payment_source = array( + 'country_code' => 'NL', + 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), + ); + // TODO get "bic" from gateway settings. + + + $request_body = array( + 'intent' => 'CAPTURE', + 'payment_source' => array( + 'ideal' => $payment_source, + ), + 'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL', + 'purchase_units' => array( + array( + 'reference_id' => $purchase_unit->reference_id(), + 'amount' => array( + 'currency_code' => $amount['currency_code'], + 'value' => $amount['value'], + ), + 'custom_id' => $purchase_unit->custom_id(), + 'invoice_id' => $purchase_unit->invoice_id(), + ), + ), + 'application_context' => array( + //'locale' => 'en-AT', + 'return_url' => $this->get_return_url( $wc_order ), + 'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ), + ), + ); + + try { + $response = $this->orders_endpoint->create( $request_body ); + } catch ( RuntimeException $exception ) { + $wc_order->update_status( + 'failed', + $exception->getMessage() + ); + + return array( + 'result' => 'failure', + 'redirect' => wc_get_checkout_url(), + ); + } + + $body = json_decode( $response['body'] ); + + $payer_action = ''; + foreach ( $body->links as $link ) { + if ( $link->rel === 'payer-action' ) { + $payer_action = $link->href; + } + } + + WC()->cart->empty_cart(); + + return array( + 'result' => 'success', + 'redirect' => esc_url( $payer_action ), + ); + } + + /** + * Process refund. + * + * If the gateway declares 'refunds' support, this will allow it to refund. + * a passed in amount. + * + * @param int $order_id Order ID. + * @param float $amount Refund amount. + * @param string $reason Refund reason. + * @return boolean True or false based on success, or a WP_Error object. + */ + public function process_refund( $order_id, $amount = null, $reason = '' ) { + $order = wc_get_order( $order_id ); + if ( ! is_a( $order, \WC_Order::class ) ) { + return false; + } + return $this->refund_processor->process( $order, (float) $amount, (string) $reason ); + } + + /** + * Return transaction url for this gateway and given order. + * + * @param \WC_Order $order WC order to get transaction url by. + * + * @return string + */ + public function get_transaction_url( $order ): string { + $this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order ); + + return parent::get_transaction_url( $order ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php new file mode 100644 index 000000000..19032cd04 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php @@ -0,0 +1,97 @@ +module_url = $module_url; + $this->version = $version; + $this->gateway = $gateway; + + $this->name = IDealGateway::ID; + } + + /** + * {@inheritDoc} + */ + public function initialize() {} + + /** + * {@inheritDoc} + */ + public function is_active() { + return true; + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_script_handles() { + wp_register_script( + 'ppcp-ideal-payment-method', + trailingslashit( $this->module_url ) . 'assets/js/ideal-payment-method.js', + array(), + $this->version, + true + ); + + return array( 'ppcp-ideal-payment-method' ); + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_data() { + return array( + 'id' => $this->name, + 'title' => $this->gateway->title, + 'description' => $this->gateway->description, + 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_ideal_color.svg' ), + ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/webpack.config.js b/modules/ppcp-local-alternative-payment-methods/webpack.config.js index c44f4d81d..a3b1cb762 100644 --- a/modules/ppcp-local-alternative-payment-methods/webpack.config.js +++ b/modules/ppcp-local-alternative-payment-methods/webpack.config.js @@ -18,6 +18,9 @@ module.exports = { 'eps-payment-method': path.resolve( './resources/js/eps-payment-method.js' ), + 'ideal-payment-method': path.resolve( + './resources/js/ideal-payment-method.js' + ), }, output: { path: path.resolve( __dirname, 'assets/' ), From 2350a87f6ce14a192909d975c79e45729c4ac3ab Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 14:34:55 +0200 Subject: [PATCH 22/29] Fix typo in ideal payment method register --- .../resources/js/ideal-payment-method.js | 2 +- .../src/LocalAlternativePaymentMethodsModule.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js index 8a7d335fd..fd5ba73b3 100644 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js @@ -1,7 +1,7 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry'; import { IDeal } from './ideal-block'; -const config = wc.wcSettings.getSetting( 'ppcp-eps_data' ); +const config = wc.wcSettings.getSetting( 'ppcp-ideal_data' ); registerPaymentMethod( { name: config.id, diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 2ff5ed729..b496a5c0c 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -91,6 +91,7 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { foreach ($payment_methods as $key => $value) { $payment_method_registry->register( $c->get( 'ppcp-local-apms.' . $key . '.payment-method' ) ); } + $a = 1; } ); From cf97f0becde1d6f897121d84250038422dd8eb0a Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 15:05:11 +0200 Subject: [PATCH 23/29] Add mybank gateway --- .../resources/js/mybank-block.js | 9 + .../resources/js/mybank-payment-method.js | 18 ++ .../services.php | 20 ++ .../src/MyBankGateway.php | 226 ++++++++++++++++++ .../src/MyBankPaymentMethod.php | 97 ++++++++ .../webpack.config.js | 3 + 6 files changed, 373 insertions(+) create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/mybank-block.js create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/mybank-payment-method.js create mode 100644 modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php create mode 100644 modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-block.js new file mode 100644 index 000000000..d4544be4d --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-block.js @@ -0,0 +1,9 @@ +export function MyBank( { config, components } ) { + const { PaymentMethodIcons } = components; + + return ( +
+ +
+ ); +} diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-payment-method.js new file mode 100644 index 000000000..c49d27f22 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-payment-method.js @@ -0,0 +1,18 @@ +import { registerPaymentMethod } from '@woocommerce/blocks-registry'; +import { MyBank } from './mybank-block'; + +const config = wc.wcSettings.getSetting( 'ppcp-mybank_data' ); + +registerPaymentMethod( { + name: config.id, + label:
, + content: , + edit:
, + ariaLabel: config.title, + canMakePayment: () => { + return true; + }, + supports: { + features: config.supports, + }, +} ); diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index f71b20594..d3efb2bc4 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -45,6 +45,11 @@ return array( 'country' => 'NL', 'currency' => 'EUR', ), + 'mybank' => array( + 'id' => MyBankGateway::ID, + 'country' => 'IT', + 'currency' => 'EUR', + ), ]; }, 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { @@ -79,6 +84,14 @@ return array( $container->get( 'wcgateway.transaction-url-provider' ) ); }, + 'ppcp-local-apms.mybank.wc-gateway' => static function ( ContainerInterface $container ): MyBankGateway { + return new MyBankGateway( + $container->get( 'api.endpoint.orders' ), + $container->get( 'api.factory.purchase-unit' ), + $container->get( 'wcgateway.processor.refunds' ), + $container->get( 'wcgateway.transaction-url-provider' ) + ); + }, 'ppcp-local-apms.bancontact.payment-method' => static function( ContainerInterface $container ): BancontactPaymentMethod { return new BancontactPaymentMethod( $container->get( 'ppcp-local-apms.url' ), @@ -107,4 +120,11 @@ return array( $container->get( 'ppcp-local-apms.ideal.wc-gateway' ) ); }, + 'ppcp-local-apms.mybank.payment-method' => static function( ContainerInterface $container ): MyBankPaymentMethod { + return new MyBankPaymentMethod( + $container->get( 'ppcp-local-apms.url' ), + $container->get( 'ppcp.asset-version' ), + $container->get( 'ppcp-local-apms.mybank.wc-gateway' ) + ); + }, ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php b/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php new file mode 100644 index 000000000..f89a9fe05 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php @@ -0,0 +1,226 @@ +id = self::ID; + + $this->supports = array( + 'refunds', + 'products', + ); + + $this->method_title = __( 'MyBank', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'MyBank', 'woocommerce-paypal-payments' ); + + $this->title = $this->get_option( 'title', __( 'MyBank', 'woocommerce-paypal-payments' ) ); + $this->description = $this->get_option( 'description', '' ); + + $this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_mybank_color.svg' ); + + $this->init_form_fields(); + $this->init_settings(); + + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + + $this->orders_endpoint = $orders_endpoint; + $this->purchase_unit_factory = $purchase_unit_factory; + $this->refund_processor = $refund_processor; + $this->transaction_url_provider = $transaction_url_provider; + } + + /** + * Initialize the form fields. + */ + public function init_form_fields() { + $this->form_fields = array( + 'enabled' => array( + 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'MyBank', 'woocommerce-paypal-payments' ), + 'default' => 'no', + 'desc_tip' => true, + 'description' => __( 'Enable/Disable MyBank payment gateway.', 'woocommerce-paypal-payments' ), + ), + 'title' => array( + 'title' => __( 'Title', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->title, + 'desc_tip' => true, + 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + 'description' => array( + 'title' => __( 'Description', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->description, + 'desc_tip' => true, + 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + ); + } + + /** + * Processes the order. + * + * @param int $order_id The WC order ID. + * @return array + */ + public function process_payment( $order_id ) { + $wc_order = wc_get_order( $order_id ); + $wc_order->update_status( 'on-hold', __( 'Awaiting MyBank to confirm the payment.', 'woocommerce-paypal-payments' ) ); + + $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); + $amount = $purchase_unit->amount()->to_array(); + + $request_body = array( + 'intent' => 'CAPTURE', + 'payment_source' => array( + 'mybank' => array( + 'country_code' => 'IT', + 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), + ), + ), + 'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL', + 'purchase_units' => array( + array( + 'reference_id' => $purchase_unit->reference_id(), + 'amount' => array( + 'currency_code' => $amount['currency_code'], + 'value' => $amount['value'], + ), + 'custom_id' => $purchase_unit->custom_id(), + 'invoice_id' => $purchase_unit->invoice_id(), + ), + ), + 'application_context' => array( + 'locale' => 'en-IT', + 'return_url' => $this->get_return_url( $wc_order ), + 'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ), + ), + ); + + try { + $response = $this->orders_endpoint->create( $request_body ); + } catch ( RuntimeException $exception ) { + $wc_order->update_status( + 'failed', + $exception->getMessage() + ); + + return array( + 'result' => 'failure', + 'redirect' => wc_get_checkout_url(), + ); + } + + $body = json_decode( $response['body'] ); + + $payer_action = ''; + foreach ( $body->links as $link ) { + if ( $link->rel === 'payer-action' ) { + $payer_action = $link->href; + } + } + + WC()->cart->empty_cart(); + + return array( + 'result' => 'success', + 'redirect' => esc_url( $payer_action ), + ); + } + + /** + * Process refund. + * + * If the gateway declares 'refunds' support, this will allow it to refund. + * a passed in amount. + * + * @param int $order_id Order ID. + * @param float $amount Refund amount. + * @param string $reason Refund reason. + * @return boolean True or false based on success, or a WP_Error object. + */ + public function process_refund( $order_id, $amount = null, $reason = '' ) { + $order = wc_get_order( $order_id ); + if ( ! is_a( $order, \WC_Order::class ) ) { + return false; + } + return $this->refund_processor->process( $order, (float) $amount, (string) $reason ); + } + + /** + * Return transaction url for this gateway and given order. + * + * @param \WC_Order $order WC order to get transaction url by. + * + * @return string + */ + public function get_transaction_url( $order ): string { + $this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order ); + + return parent::get_transaction_url( $order ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php new file mode 100644 index 000000000..11ffa6afa --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php @@ -0,0 +1,97 @@ +module_url = $module_url; + $this->version = $version; + $this->gateway = $gateway; + + $this->name = MyBankGateway::ID; + } + + /** + * {@inheritDoc} + */ + public function initialize() {} + + /** + * {@inheritDoc} + */ + public function is_active() { + return true; + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_script_handles() { + wp_register_script( + 'ppcp-mybank-payment-method', + trailingslashit( $this->module_url ) . 'assets/js/mybank-payment-method.js', + array(), + $this->version, + true + ); + + return array( 'ppcp-mybank-payment-method' ); + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_data() { + return array( + 'id' => $this->name, + 'title' => $this->gateway->title, + 'description' => $this->gateway->description, + 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_mybank_color.svg' ), + ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/webpack.config.js b/modules/ppcp-local-alternative-payment-methods/webpack.config.js index a3b1cb762..d6e7bbb92 100644 --- a/modules/ppcp-local-alternative-payment-methods/webpack.config.js +++ b/modules/ppcp-local-alternative-payment-methods/webpack.config.js @@ -21,6 +21,9 @@ module.exports = { 'ideal-payment-method': path.resolve( './resources/js/ideal-payment-method.js' ), + 'mybank-payment-method': path.resolve( + './resources/js/mybank-payment-method.js' + ), }, output: { path: path.resolve( __dirname, 'assets/' ), From 83cb9d607ad7c09416842466d764c405dc3de782 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 15:47:23 +0200 Subject: [PATCH 24/29] Add p24 gateway --- .../js/{eps-block.js => apm-block.js} | 2 +- .../resources/js/bancontact-block.js | 9 - .../resources/js/bancontact-payment-method.js | 4 +- .../resources/js/blik-block.js | 9 - .../resources/js/blik-payment-method.js | 4 +- .../resources/js/eps-payment-method.js | 4 +- .../resources/js/ideal-block.js | 9 - .../resources/js/ideal-payment-method.js | 4 +- .../resources/js/mybank-block.js | 9 - .../resources/js/mybank-payment-method.js | 4 +- .../resources/js/p24-payment-method.js | 18 ++ .../services.php | 24 +- .../src/P24Gateway.php | 227 ++++++++++++++++++ .../src/P24PaymentMethod.php | 97 ++++++++ .../webpack.config.js | 3 + 15 files changed, 378 insertions(+), 49 deletions(-) rename modules/ppcp-local-alternative-payment-methods/resources/js/{eps-block.js => apm-block.js} (75%) delete mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-block.js delete mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/blik-block.js delete mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/ideal-block.js delete mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/mybank-block.js create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/p24-payment-method.js create mode 100644 modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php create mode 100644 modules/ppcp-local-alternative-payment-methods/src/P24PaymentMethod.php diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/eps-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/apm-block.js similarity index 75% rename from modules/ppcp-local-alternative-payment-methods/resources/js/eps-block.js rename to modules/ppcp-local-alternative-payment-methods/resources/js/apm-block.js index 051ec8730..6f280772b 100644 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/eps-block.js +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/apm-block.js @@ -1,4 +1,4 @@ -export function EPS( { config, components } ) { +export function APM( { config, components } ) { const { PaymentMethodIcons } = components; return ( diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-block.js deleted file mode 100644 index e66ab88c3..000000000 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-block.js +++ /dev/null @@ -1,9 +0,0 @@ -export function Bancontact( { config, components } ) { - const { PaymentMethodIcons } = components; - - return ( -
- -
- ); -} diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-payment-method.js index f8e1d7e25..d8ff3bdcd 100644 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-payment-method.js +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/bancontact-payment-method.js @@ -1,12 +1,12 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry'; -import { Bancontact } from './bancontact-block'; +import { APM } from './apm-block'; const config = wc.wcSettings.getSetting( 'ppcp-bancontact_data' ); registerPaymentMethod( { name: config.id, label:
, - content: , + content: , edit:
, ariaLabel: config.title, canMakePayment: () => { diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/blik-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/blik-block.js deleted file mode 100644 index 7075487bf..000000000 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/blik-block.js +++ /dev/null @@ -1,9 +0,0 @@ -export function Blik( { config, components } ) { - const { PaymentMethodIcons } = components; - - return ( -
- -
- ); -} diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/blik-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/blik-payment-method.js index 2f4c7e252..39a979ae7 100644 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/blik-payment-method.js +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/blik-payment-method.js @@ -1,12 +1,12 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry'; -import { Blik } from './blik-block'; +import { APM } from './apm-block'; const config = wc.wcSettings.getSetting( 'ppcp-blik_data' ); registerPaymentMethod( { name: config.id, label:
, - content: , + content: , edit:
, ariaLabel: config.title, canMakePayment: () => { diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/eps-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/eps-payment-method.js index 19d26d971..b1df57547 100644 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/eps-payment-method.js +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/eps-payment-method.js @@ -1,12 +1,12 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry'; -import { EPS } from './eps-block'; +import { APM } from './apm-block'; const config = wc.wcSettings.getSetting( 'ppcp-eps_data' ); registerPaymentMethod( { name: config.id, label:
, - content: , + content: , edit:
, ariaLabel: config.title, canMakePayment: () => { diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-block.js deleted file mode 100644 index 8cb989da3..000000000 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-block.js +++ /dev/null @@ -1,9 +0,0 @@ -export function IDeal( { config, components } ) { - const { PaymentMethodIcons } = components; - - return ( -
- -
- ); -} diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js index fd5ba73b3..3acb86060 100644 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/ideal-payment-method.js @@ -1,12 +1,12 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry'; -import { IDeal } from './ideal-block'; +import { APM } from './apm-block'; const config = wc.wcSettings.getSetting( 'ppcp-ideal_data' ); registerPaymentMethod( { name: config.id, label:
, - content: , + content: , edit:
, ariaLabel: config.title, canMakePayment: () => { diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-block.js b/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-block.js deleted file mode 100644 index d4544be4d..000000000 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-block.js +++ /dev/null @@ -1,9 +0,0 @@ -export function MyBank( { config, components } ) { - const { PaymentMethodIcons } = components; - - return ( -
- -
- ); -} diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-payment-method.js index c49d27f22..27c593481 100644 --- a/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-payment-method.js +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/mybank-payment-method.js @@ -1,12 +1,12 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry'; -import { MyBank } from './mybank-block'; +import { APM } from './apm-block'; const config = wc.wcSettings.getSetting( 'ppcp-mybank_data' ); registerPaymentMethod( { name: config.id, label:
, - content: , + content: , edit:
, ariaLabel: config.title, canMakePayment: () => { diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/p24-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/p24-payment-method.js new file mode 100644 index 000000000..0ba214de1 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/p24-payment-method.js @@ -0,0 +1,18 @@ +import { registerPaymentMethod } from '@woocommerce/blocks-registry'; +import { APM } from './apm-block'; + +const config = wc.wcSettings.getSetting( 'ppcp-p24_data' ); + +registerPaymentMethod( { + name: config.id, + label:
, + content: , + edit:
, + ariaLabel: config.title, + canMakePayment: () => { + return true; + }, + supports: { + features: config.supports, + }, +} ); diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index d3efb2bc4..48d3004b3 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -24,7 +24,7 @@ return array( ); }, 'ppcp-local-apms.payment-methods' => static function( ContainerInterface $container): array { - return [ + return array( 'bancontact' => array( 'id' => BancontactGateway::ID, 'country' => 'BE', @@ -50,7 +50,12 @@ return array( 'country' => 'IT', 'currency' => 'EUR', ), - ]; + 'p24' => array( + 'id' => P24Gateway::ID, + 'country' => 'PL', + 'currency' => 'EUR', + ), + ); }, 'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway { return new BancontactGateway( @@ -92,6 +97,14 @@ return array( $container->get( 'wcgateway.transaction-url-provider' ) ); }, + 'ppcp-local-apms.p24.wc-gateway' => static function ( ContainerInterface $container ): P24Gateway { + return new P24Gateway( + $container->get( 'api.endpoint.orders' ), + $container->get( 'api.factory.purchase-unit' ), + $container->get( 'wcgateway.processor.refunds' ), + $container->get( 'wcgateway.transaction-url-provider' ) + ); + }, 'ppcp-local-apms.bancontact.payment-method' => static function( ContainerInterface $container ): BancontactPaymentMethod { return new BancontactPaymentMethod( $container->get( 'ppcp-local-apms.url' ), @@ -127,4 +140,11 @@ return array( $container->get( 'ppcp-local-apms.mybank.wc-gateway' ) ); }, + 'ppcp-local-apms.p24.payment-method' => static function( ContainerInterface $container ): P24PaymentMethod { + return new P24PaymentMethod( + $container->get( 'ppcp-local-apms.url' ), + $container->get( 'ppcp.asset-version' ), + $container->get( 'ppcp-local-apms.p24.wc-gateway' ) + ); + }, ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php b/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php new file mode 100644 index 000000000..c38b8df1d --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php @@ -0,0 +1,227 @@ +id = self::ID; + + $this->supports = array( + 'refunds', + 'products', + ); + + $this->method_title = __( 'Przelewy24', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'Przelewy24', 'woocommerce-paypal-payments' ); + + $this->title = $this->get_option( 'title', __( 'Przelewy24', 'woocommerce-paypal-payments' ) ); + $this->description = $this->get_option( 'description', '' ); + + $this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_przelewy24_color.svg' ); + + $this->init_form_fields(); + $this->init_settings(); + + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + + $this->orders_endpoint = $orders_endpoint; + $this->purchase_unit_factory = $purchase_unit_factory; + $this->refund_processor = $refund_processor; + $this->transaction_url_provider = $transaction_url_provider; + } + + /** + * Initialize the form fields. + */ + public function init_form_fields() { + $this->form_fields = array( + 'enabled' => array( + 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'Przelewy24', 'woocommerce-paypal-payments' ), + 'default' => 'no', + 'desc_tip' => true, + 'description' => __( 'Enable/Disable Przelewy24 payment gateway.', 'woocommerce-paypal-payments' ), + ), + 'title' => array( + 'title' => __( 'Title', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->title, + 'desc_tip' => true, + 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + 'description' => array( + 'title' => __( 'Description', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->description, + 'desc_tip' => true, + 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + ); + } + + /** + * Processes the order. + * + * @param int $order_id The WC order ID. + * @return array + */ + public function process_payment( $order_id ) { + $wc_order = wc_get_order( $order_id ); + $wc_order->update_status( 'on-hold', __( 'Awaiting Przelewy24 to confirm the payment.', 'woocommerce-paypal-payments' ) ); + + $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); + $amount = $purchase_unit->amount()->to_array(); + + $request_body = array( + 'intent' => 'CAPTURE', + 'payment_source' => array( + 'p24' => array( + 'country_code' => 'PL', + 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), + 'email' => $wc_order->get_billing_email(), + ), + ), + 'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL', + 'purchase_units' => array( + array( + 'reference_id' => $purchase_unit->reference_id(), + 'amount' => array( + 'currency_code' => $amount['currency_code'], + 'value' => $amount['value'], + ), + 'custom_id' => $purchase_unit->custom_id(), + 'invoice_id' => $purchase_unit->invoice_id(), + ), + ), + 'application_context' => array( + 'locale' => 'en-PL', + 'return_url' => $this->get_return_url( $wc_order ), + 'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ), + ), + ); + + try { + $response = $this->orders_endpoint->create( $request_body ); + } catch ( RuntimeException $exception ) { + $wc_order->update_status( + 'failed', + $exception->getMessage() + ); + + return array( + 'result' => 'failure', + 'redirect' => wc_get_checkout_url(), + ); + } + + $body = json_decode( $response['body'] ); + + $payer_action = ''; + foreach ( $body->links as $link ) { + if ( $link->rel === 'payer-action' ) { + $payer_action = $link->href; + } + } + + WC()->cart->empty_cart(); + + return array( + 'result' => 'success', + 'redirect' => esc_url( $payer_action ), + ); + } + + /** + * Process refund. + * + * If the gateway declares 'refunds' support, this will allow it to refund. + * a passed in amount. + * + * @param int $order_id Order ID. + * @param float $amount Refund amount. + * @param string $reason Refund reason. + * @return boolean True or false based on success, or a WP_Error object. + */ + public function process_refund( $order_id, $amount = null, $reason = '' ) { + $order = wc_get_order( $order_id ); + if ( ! is_a( $order, \WC_Order::class ) ) { + return false; + } + return $this->refund_processor->process( $order, (float) $amount, (string) $reason ); + } + + /** + * Return transaction url for this gateway and given order. + * + * @param \WC_Order $order WC order to get transaction url by. + * + * @return string + */ + public function get_transaction_url( $order ): string { + $this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order ); + + return parent::get_transaction_url( $order ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/P24PaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/P24PaymentMethod.php new file mode 100644 index 000000000..d9fe2b3b8 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/P24PaymentMethod.php @@ -0,0 +1,97 @@ +module_url = $module_url; + $this->version = $version; + $this->gateway = $gateway; + + $this->name = P24Gateway::ID; + } + + /** + * {@inheritDoc} + */ + public function initialize() {} + + /** + * {@inheritDoc} + */ + public function is_active() { + return true; + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_script_handles() { + wp_register_script( + 'ppcp-p24-payment-method', + trailingslashit( $this->module_url ) . 'assets/js/p24-payment-method.js', + array(), + $this->version, + true + ); + + return array( 'ppcp-p24-payment-method' ); + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_data() { + return array( + 'id' => $this->name, + 'title' => $this->gateway->title, + 'description' => $this->gateway->description, + 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_przelewy24_color.svg' ), + ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/webpack.config.js b/modules/ppcp-local-alternative-payment-methods/webpack.config.js index d6e7bbb92..3c59b9f67 100644 --- a/modules/ppcp-local-alternative-payment-methods/webpack.config.js +++ b/modules/ppcp-local-alternative-payment-methods/webpack.config.js @@ -24,6 +24,9 @@ module.exports = { 'mybank-payment-method': path.resolve( './resources/js/mybank-payment-method.js' ), + 'p24-payment-method': path.resolve( + './resources/js/p24-payment-method.js' + ), }, output: { path: path.resolve( __dirname, 'assets/' ), From 98536361af95d07f2d9dff80e8fb4407c3ea607e Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 15:55:36 +0200 Subject: [PATCH 25/29] Add support for multiple currencies and countries --- .../services.php | 24 +++++++++---------- .../LocalAlternativePaymentMethodsModule.php | 6 +++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index 48d3004b3..8cdb7e2b5 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -27,33 +27,33 @@ return array( return array( 'bancontact' => array( 'id' => BancontactGateway::ID, - 'country' => 'BE', - 'currency' => 'EUR', + 'countries' => array('BE'), + 'currencies' => array('EUR'), ), 'blik' => array( 'id' => BlikGateway::ID, - 'country' => 'PL', - 'currency' => 'PLN', + 'countries' => array('PL'), + 'currencies' => array('PLN'), ), 'eps' => array( 'id' => EPSGateway::ID, - 'country' => 'AT', - 'currency' => 'EUR', + 'countries' => array('AT'), + 'currencies' => array('EUR'), ), 'ideal' => array( 'id' => IDealGateway::ID, - 'country' => 'NL', - 'currency' => 'EUR', + 'countries' => array('NL'), + 'currencies' => array('EUR'), ), 'mybank' => array( 'id' => MyBankGateway::ID, - 'country' => 'IT', - 'currency' => 'EUR', + 'countries' => array('IT'), + 'currencies' => array('EUR'), ), 'p24' => array( 'id' => P24Gateway::ID, - 'country' => 'PL', - 'currency' => 'EUR', + 'countries' => array('PL'), + 'currencies' => array('EUR', 'PLN'), ), ); }, diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index b496a5c0c..809cfe5a5 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -74,7 +74,10 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { $payment_methods = $c->get('ppcp-local-apms.payment-methods'); foreach ($payment_methods as $payment_method) { - if ( $customer_country !== $payment_method['country'] || $site_currency !== $payment_method['currency'] ) { + if ( + ! in_array($customer_country, $payment_method['countries'], true) + || ! in_array($site_currency, $payment_method['currencies'], true) + ) { unset( $methods[ $payment_method['id'] ] ); } } @@ -91,7 +94,6 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { foreach ($payment_methods as $key => $value) { $payment_method_registry->register( $c->get( 'ppcp-local-apms.' . $key . '.payment-method' ) ); } - $a = 1; } ); From dd990ca44a225ec3a081ceaa37b611aa048b19a3 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 16:24:37 +0200 Subject: [PATCH 26/29] Add trustly gateway --- .../resources/js/trustly-payment-method.js | 18 ++ .../services.php | 44 +++- .../src/BancontactGateway.php | 2 +- .../src/BlikGateway.php | 2 +- .../src/EPSGateway.php | 2 +- .../src/IDealGateway.php | 3 +- .../src/MyBankGateway.php | 2 +- .../src/P24Gateway.php | 2 +- .../src/TrustlyGateway.php | 249 ++++++++++++++++++ .../src/TrustlyPaymentMethod.php | 97 +++++++ .../webpack.config.js | 3 + 11 files changed, 405 insertions(+), 19 deletions(-) create mode 100644 modules/ppcp-local-alternative-payment-methods/resources/js/trustly-payment-method.js create mode 100644 modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php create mode 100644 modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php diff --git a/modules/ppcp-local-alternative-payment-methods/resources/js/trustly-payment-method.js b/modules/ppcp-local-alternative-payment-methods/resources/js/trustly-payment-method.js new file mode 100644 index 000000000..92caace56 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/resources/js/trustly-payment-method.js @@ -0,0 +1,18 @@ +import { registerPaymentMethod } from '@woocommerce/blocks-registry'; +import { APM } from './apm-block'; + +const config = wc.wcSettings.getSetting( 'ppcp-trustly_data' ); + +registerPaymentMethod( { + name: config.id, + label:
, + content: , + edit:
, + ariaLabel: config.title, + canMakePayment: () => { + return true; + }, + supports: { + features: config.supports, + }, +} ); diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index 8cdb7e2b5..325f19ffa 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -27,33 +27,38 @@ return array( return array( 'bancontact' => array( 'id' => BancontactGateway::ID, - 'countries' => array('BE'), - 'currencies' => array('EUR'), + 'countries' => array('BE',), + 'currencies' => array('EUR',), ), 'blik' => array( 'id' => BlikGateway::ID, - 'countries' => array('PL'), - 'currencies' => array('PLN'), + 'countries' => array('PL',), + 'currencies' => array('PLN',), ), 'eps' => array( 'id' => EPSGateway::ID, - 'countries' => array('AT'), - 'currencies' => array('EUR'), + 'countries' => array('AT',), + 'currencies' => array('EUR',), ), 'ideal' => array( 'id' => IDealGateway::ID, - 'countries' => array('NL'), - 'currencies' => array('EUR'), + 'countries' => array('NL',), + 'currencies' => array('EUR',), ), 'mybank' => array( 'id' => MyBankGateway::ID, - 'countries' => array('IT'), - 'currencies' => array('EUR'), + 'countries' => array('IT',), + 'currencies' => array('EUR',), ), 'p24' => array( 'id' => P24Gateway::ID, - 'countries' => array('PL'), - 'currencies' => array('EUR', 'PLN'), + 'countries' => array('PL',), + 'currencies' => array('EUR', 'PLN',), + ), + 'trustly' => array( + 'id' => TrustlyGateway::ID, + 'countries' => array('AT', 'DE', 'DK', 'EE', 'ES', 'FI', 'GB', 'LT', 'LV', 'NL', 'NO', 'SE',), + 'currencies' => array('EUR', 'DKK', 'SEK', 'GBP', 'NOK',), ), ); }, @@ -105,6 +110,14 @@ return array( $container->get( 'wcgateway.transaction-url-provider' ) ); }, + 'ppcp-local-apms.trustly.wc-gateway' => static function ( ContainerInterface $container ): TrustlyGateway { + return new TrustlyGateway( + $container->get( 'api.endpoint.orders' ), + $container->get( 'api.factory.purchase-unit' ), + $container->get( 'wcgateway.processor.refunds' ), + $container->get( 'wcgateway.transaction-url-provider' ) + ); + }, 'ppcp-local-apms.bancontact.payment-method' => static function( ContainerInterface $container ): BancontactPaymentMethod { return new BancontactPaymentMethod( $container->get( 'ppcp-local-apms.url' ), @@ -147,4 +160,11 @@ return array( $container->get( 'ppcp-local-apms.p24.wc-gateway' ) ); }, + 'ppcp-local-apms.trustly.payment-method' => static function( ContainerInterface $container ): TrustlyPaymentMethod { + return new TrustlyPaymentMethod( + $container->get( 'ppcp-local-apms.url' ), + $container->get( 'ppcp.asset-version' ), + $container->get( 'ppcp-local-apms.trustly.wc-gateway' ) + ); + }, ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php index 29c8c35d4..f2bb039d2 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php @@ -138,7 +138,7 @@ class BancontactGateway extends WC_Payment_Gateway { 'intent' => 'CAPTURE', 'payment_source' => array( 'bancontact' => array( - 'country_code' => 'BE', + 'country_code' => $wc_order->get_billing_country(), 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), ), ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php index 39284e8bd..5eeea02c9 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php @@ -138,7 +138,7 @@ class BlikGateway extends WC_Payment_Gateway { 'intent' => 'CAPTURE', 'payment_source' => array( 'blik' => array( - 'country_code' => 'PL', + 'country_code' => $wc_order->get_billing_country(), 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), 'email' => $wc_order->get_billing_email(), ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php b/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php index ef3094463..a8dc07c20 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php @@ -138,7 +138,7 @@ class EPSGateway extends WC_Payment_Gateway { 'intent' => 'CAPTURE', 'payment_source' => array( 'eps' => array( - 'country_code' => 'AT', + 'country_code' => $wc_order->get_billing_country(), 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), ), ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php b/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php index 2b52bef28..02b58db8f 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php @@ -135,7 +135,7 @@ class IDealGateway extends WC_Payment_Gateway { $amount = $purchase_unit->amount()->to_array(); $payment_source = array( - 'country_code' => 'NL', + 'country_code' => $wc_order->get_billing_country(), 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), ); // TODO get "bic" from gateway settings. @@ -159,7 +159,6 @@ class IDealGateway extends WC_Payment_Gateway { ), ), 'application_context' => array( - //'locale' => 'en-AT', 'return_url' => $this->get_return_url( $wc_order ), 'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ), ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php b/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php index f89a9fe05..28c66d80b 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php @@ -138,7 +138,7 @@ class MyBankGateway extends WC_Payment_Gateway { 'intent' => 'CAPTURE', 'payment_source' => array( 'mybank' => array( - 'country_code' => 'IT', + 'country_code' => $wc_order->get_billing_country(), 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), ), ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php b/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php index c38b8df1d..e219f611e 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php @@ -138,7 +138,7 @@ class P24Gateway extends WC_Payment_Gateway { 'intent' => 'CAPTURE', 'payment_source' => array( 'p24' => array( - 'country_code' => 'PL', + 'country_code' => $wc_order->get_billing_country(), 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), 'email' => $wc_order->get_billing_email(), ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php b/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php new file mode 100644 index 000000000..71f97d608 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php @@ -0,0 +1,249 @@ +id = self::ID; + + $this->supports = array( + 'refunds', + 'products', + ); + + $this->method_title = __( 'Trustly', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'Trustly', 'woocommerce-paypal-payments' ); + + $this->title = $this->get_option( 'title', __( 'Trustly', 'woocommerce-paypal-payments' ) ); + $this->description = $this->get_option( 'description', '' ); + + $this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_trustly_color.svg' ); + + $this->init_form_fields(); + $this->init_settings(); + + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + + $this->orders_endpoint = $orders_endpoint; + $this->purchase_unit_factory = $purchase_unit_factory; + $this->refund_processor = $refund_processor; + $this->transaction_url_provider = $transaction_url_provider; + } + + /** + * Initialize the form fields. + */ + public function init_form_fields() { + $this->form_fields = array( + 'enabled' => array( + 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'Trustly', 'woocommerce-paypal-payments' ), + 'default' => 'no', + 'desc_tip' => true, + 'description' => __( 'Enable/Disable Trustly payment gateway.', 'woocommerce-paypal-payments' ), + ), + 'title' => array( + 'title' => __( 'Title', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->title, + 'desc_tip' => true, + 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + 'description' => array( + 'title' => __( 'Description', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => $this->description, + 'desc_tip' => true, + 'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ), + ), + ); + } + + /** + * Processes the order. + * + * @param int $order_id The WC order ID. + * @return array + */ + public function process_payment( $order_id ) { + $wc_order = wc_get_order( $order_id ); + $wc_order->update_status( 'on-hold', __( 'Awaiting Trustly to confirm the payment.', 'woocommerce-paypal-payments' ) ); + + $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); + $amount = $purchase_unit->amount()->to_array(); + + $request_body = array( + 'intent' => 'CAPTURE', + 'payment_source' => array( + 'trustly' => array( + 'country_code' => $wc_order->get_billing_country(), + 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), + ), + ), + 'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL', + 'purchase_units' => array( + array( + 'reference_id' => $purchase_unit->reference_id(), + 'amount' => array( + 'currency_code' => $amount['currency_code'], + 'value' => $amount['value'], + ), + 'custom_id' => $purchase_unit->custom_id(), + 'invoice_id' => $purchase_unit->invoice_id(), + ), + ), + 'application_context' => array( + 'locale' => $this->valid_bcp47_code(), + 'return_url' => $this->get_return_url( $wc_order ), + 'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ), + ), + ); + + try { + $response = $this->orders_endpoint->create( $request_body ); + } catch ( RuntimeException $exception ) { + $wc_order->update_status( + 'failed', + $exception->getMessage() + ); + + return array( + 'result' => 'failure', + 'redirect' => wc_get_checkout_url(), + ); + } + + $body = json_decode( $response['body'] ); + + $payer_action = ''; + foreach ( $body->links as $link ) { + if ( $link->rel === 'payer-action' ) { + $payer_action = $link->href; + } + } + + WC()->cart->empty_cart(); + + return array( + 'result' => 'success', + 'redirect' => esc_url( $payer_action ), + ); + } + + /** + * Process refund. + * + * If the gateway declares 'refunds' support, this will allow it to refund. + * a passed in amount. + * + * @param int $order_id Order ID. + * @param float $amount Refund amount. + * @param string $reason Refund reason. + * @return boolean True or false based on success, or a WP_Error object. + */ + public function process_refund( $order_id, $amount = null, $reason = '' ) { + $order = wc_get_order( $order_id ); + if ( ! is_a( $order, \WC_Order::class ) ) { + return false; + } + return $this->refund_processor->process( $order, (float) $amount, (string) $reason ); + } + + /** + * Return transaction url for this gateway and given order. + * + * @param \WC_Order $order WC order to get transaction url by. + * + * @return string + */ + public function get_transaction_url( $order ): string { + $this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order ); + + return parent::get_transaction_url( $order ); + } + + /** + * Returns a PayPal-supported BCP-47 code, for example de-DE-formal becomes de-DE. + * + * @return string + */ + private function valid_bcp47_code() { + $locale = str_replace( '_', '-', get_user_locale() ); + + if ( preg_match( '/^[a-z]{2}(?:-[A-Z][a-z]{3})?(?:-(?:[A-Z]{2}))?$/', $locale ) ) { + return $locale; + } + + $parts = explode( '-', $locale ); + if ( count( $parts ) === 3 ) { + $ret = substr( $locale, 0, strrpos( $locale, '-' ) ); + if ( false !== $ret ) { + return $ret; + } + } + + return 'en'; + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php new file mode 100644 index 000000000..8cbda2ac9 --- /dev/null +++ b/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php @@ -0,0 +1,97 @@ +module_url = $module_url; + $this->version = $version; + $this->gateway = $gateway; + + $this->name = TrustlyGateway::ID; + } + + /** + * {@inheritDoc} + */ + public function initialize() {} + + /** + * {@inheritDoc} + */ + public function is_active() { + return true; + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_script_handles() { + wp_register_script( + 'ppcp-trustly-payment-method', + trailingslashit( $this->module_url ) . 'assets/js/trustly-payment-method.js', + array(), + $this->version, + true + ); + + return array( 'ppcp-trustly-payment-method' ); + } + + /** + * {@inheritDoc} + */ + public function get_payment_method_data() { + return array( + 'id' => $this->name, + 'title' => $this->gateway->title, + 'description' => $this->gateway->description, + 'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_trustly_color.svg' ), + ); + } +} diff --git a/modules/ppcp-local-alternative-payment-methods/webpack.config.js b/modules/ppcp-local-alternative-payment-methods/webpack.config.js index 3c59b9f67..a4366ebd8 100644 --- a/modules/ppcp-local-alternative-payment-methods/webpack.config.js +++ b/modules/ppcp-local-alternative-payment-methods/webpack.config.js @@ -27,6 +27,9 @@ module.exports = { 'p24-payment-method': path.resolve( './resources/js/p24-payment-method.js' ), + 'trustly-payment-method': path.resolve( + './resources/js/trustly-payment-method.js' + ), }, output: { path: path.resolve( __dirname, 'assets/' ), From 2e524b53ea24212a3aed98bf8d7445911b34e4ed Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 16:33:44 +0200 Subject: [PATCH 27/29] Fix phpcs --- .../services.php | 68 +++++++++---------- .../src/IDealGateway.php | 3 +- .../src/IDealPaymentMethod.php | 8 +-- .../LocalAlternativePaymentMethodsModule.php | 36 +++++----- .../src/MyBankPaymentMethod.php | 4 +- .../src/TrustlyPaymentMethod.php | 4 +- 6 files changed, 61 insertions(+), 62 deletions(-) diff --git a/modules/ppcp-local-alternative-payment-methods/services.php b/modules/ppcp-local-alternative-payment-methods/services.php index 325f19ffa..74796c712 100644 --- a/modules/ppcp-local-alternative-payment-methods/services.php +++ b/modules/ppcp-local-alternative-payment-methods/services.php @@ -23,42 +23,42 @@ return array( dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php' ); }, - 'ppcp-local-apms.payment-methods' => static function( ContainerInterface $container): array { + 'ppcp-local-apms.payment-methods' => static function( ContainerInterface $container ): array { return array( 'bancontact' => array( - 'id' => BancontactGateway::ID, - 'countries' => array('BE',), - 'currencies' => array('EUR',), + 'id' => BancontactGateway::ID, + 'countries' => array( 'BE' ), + 'currencies' => array( 'EUR' ), ), - 'blik' => array( - 'id' => BlikGateway::ID, - 'countries' => array('PL',), - 'currencies' => array('PLN',), + 'blik' => array( + 'id' => BlikGateway::ID, + 'countries' => array( 'PL' ), + 'currencies' => array( 'PLN' ), ), - 'eps' => array( - 'id' => EPSGateway::ID, - 'countries' => array('AT',), - 'currencies' => array('EUR',), + 'eps' => array( + 'id' => EPSGateway::ID, + 'countries' => array( 'AT' ), + 'currencies' => array( 'EUR' ), ), - 'ideal' => array( - 'id' => IDealGateway::ID, - 'countries' => array('NL',), - 'currencies' => array('EUR',), + 'ideal' => array( + 'id' => IDealGateway::ID, + 'countries' => array( 'NL' ), + 'currencies' => array( 'EUR' ), ), - 'mybank' => array( - 'id' => MyBankGateway::ID, - 'countries' => array('IT',), - 'currencies' => array('EUR',), + 'mybank' => array( + 'id' => MyBankGateway::ID, + 'countries' => array( 'IT' ), + 'currencies' => array( 'EUR' ), ), - 'p24' => array( - 'id' => P24Gateway::ID, - 'countries' => array('PL',), - 'currencies' => array('EUR', 'PLN',), + 'p24' => array( + 'id' => P24Gateway::ID, + 'countries' => array( 'PL' ), + 'currencies' => array( 'EUR', 'PLN' ), ), - 'trustly' => array( - 'id' => TrustlyGateway::ID, - 'countries' => array('AT', 'DE', 'DK', 'EE', 'ES', 'FI', 'GB', 'LT', 'LV', 'NL', 'NO', 'SE',), - 'currencies' => array('EUR', 'DKK', 'SEK', 'GBP', 'NOK',), + 'trustly' => array( + 'id' => TrustlyGateway::ID, + 'countries' => array( 'AT', 'DE', 'DK', 'EE', 'ES', 'FI', 'GB', 'LT', 'LV', 'NL', 'NO', 'SE' ), + 'currencies' => array( 'EUR', 'DKK', 'SEK', 'GBP', 'NOK' ), ), ); }, @@ -86,7 +86,7 @@ return array( $container->get( 'wcgateway.transaction-url-provider' ) ); }, - 'ppcp-local-apms.ideal.wc-gateway' => static function ( ContainerInterface $container ): IDealGateway { + 'ppcp-local-apms.ideal.wc-gateway' => static function ( ContainerInterface $container ): IDealGateway { return new IDealGateway( $container->get( 'api.endpoint.orders' ), $container->get( 'api.factory.purchase-unit' ), @@ -94,7 +94,7 @@ return array( $container->get( 'wcgateway.transaction-url-provider' ) ); }, - 'ppcp-local-apms.mybank.wc-gateway' => static function ( ContainerInterface $container ): MyBankGateway { + 'ppcp-local-apms.mybank.wc-gateway' => static function ( ContainerInterface $container ): MyBankGateway { return new MyBankGateway( $container->get( 'api.endpoint.orders' ), $container->get( 'api.factory.purchase-unit' ), @@ -110,7 +110,7 @@ return array( $container->get( 'wcgateway.transaction-url-provider' ) ); }, - 'ppcp-local-apms.trustly.wc-gateway' => static function ( ContainerInterface $container ): TrustlyGateway { + 'ppcp-local-apms.trustly.wc-gateway' => static function ( ContainerInterface $container ): TrustlyGateway { return new TrustlyGateway( $container->get( 'api.endpoint.orders' ), $container->get( 'api.factory.purchase-unit' ), @@ -139,14 +139,14 @@ return array( $container->get( 'ppcp-local-apms.eps.wc-gateway' ) ); }, - 'ppcp-local-apms.ideal.payment-method' => static function( ContainerInterface $container ): IDealPaymentMethod { + 'ppcp-local-apms.ideal.payment-method' => static function( ContainerInterface $container ): IDealPaymentMethod { return new IDealPaymentMethod( $container->get( 'ppcp-local-apms.url' ), $container->get( 'ppcp.asset-version' ), $container->get( 'ppcp-local-apms.ideal.wc-gateway' ) ); }, - 'ppcp-local-apms.mybank.payment-method' => static function( ContainerInterface $container ): MyBankPaymentMethod { + 'ppcp-local-apms.mybank.payment-method' => static function( ContainerInterface $container ): MyBankPaymentMethod { return new MyBankPaymentMethod( $container->get( 'ppcp-local-apms.url' ), $container->get( 'ppcp.asset-version' ), @@ -160,7 +160,7 @@ return array( $container->get( 'ppcp-local-apms.p24.wc-gateway' ) ); }, - 'ppcp-local-apms.trustly.payment-method' => static function( ContainerInterface $container ): TrustlyPaymentMethod { + 'ppcp-local-apms.trustly.payment-method' => static function( ContainerInterface $container ): TrustlyPaymentMethod { return new TrustlyPaymentMethod( $container->get( 'ppcp-local-apms.url' ), $container->get( 'ppcp.asset-version' ), diff --git a/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php b/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php index 02b58db8f..0d6ece5e7 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php @@ -136,11 +136,10 @@ class IDealGateway extends WC_Payment_Gateway { $payment_source = array( 'country_code' => $wc_order->get_billing_country(), - 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), + 'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(), ); // TODO get "bic" from gateway settings. - $request_body = array( 'intent' => 'CAPTURE', 'payment_source' => array( diff --git a/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php index 19032cd04..7f40e90f9 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/IDealPaymentMethod.php @@ -1,6 +1,6 @@ get('ppcp-local-apms.payment-methods'); - foreach ($payment_methods as $key => $value) { - $methods[] = $c->get( 'ppcp-local-apms.' . $key . '.wc-gateway' ); + $payment_methods = $c->get( 'ppcp-local-apms.payment-methods' ); + foreach ( $payment_methods as $key => $value ) { + $methods[] = $c->get( 'ppcp-local-apms.' . $key . '.wc-gateway' ); } return $methods; @@ -72,11 +72,11 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { $customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country(); $site_currency = get_woocommerce_currency(); - $payment_methods = $c->get('ppcp-local-apms.payment-methods'); - foreach ($payment_methods as $payment_method) { + $payment_methods = $c->get( 'ppcp-local-apms.payment-methods' ); + foreach ( $payment_methods as $payment_method ) { if ( - ! in_array($customer_country, $payment_method['countries'], true) - || ! in_array($site_currency, $payment_method['currencies'], true) + ! in_array( $customer_country, $payment_method['countries'], true ) + || ! in_array( $site_currency, $payment_method['currencies'], true ) ) { unset( $methods[ $payment_method['id'] ] ); } @@ -90,8 +90,8 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { add_action( 'woocommerce_blocks_payment_method_type_registration', function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void { - $payment_methods = $c->get('ppcp-local-apms.payment-methods'); - foreach ($payment_methods as $key => $value) { + $payment_methods = $c->get( 'ppcp-local-apms.payment-methods' ); + foreach ( $payment_methods as $key => $value ) { $payment_method_registry->register( $c->get( 'ppcp-local-apms.' . $key . '.payment-method' ) ); } } @@ -99,8 +99,8 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { add_filter( 'woocommerce_paypal_payments_localized_script_data', - function ( array $data ) use ($c) { - $payment_methods = $c->get('ppcp-local-apms.payment-methods'); + function ( array $data ) use ( $c ) { + $payment_methods = $c->get( 'ppcp-local-apms.payment-methods' ); $default_disable_funding = $data['url_params']['disable-funding'] ?? ''; $disable_funding = array_merge( array_keys( $payment_methods ), array_filter( explode( ',', $default_disable_funding ) ) ); @@ -117,7 +117,7 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { * * @psalm-suppress MissingClosureParamType */ - function( $order_id ) use($c) { + function( $order_id ) use ( $c ) { $order = wc_get_order( $order_id ); if ( ! $order instanceof WC_Order ) { return; @@ -128,9 +128,9 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { $order_key = wc_clean( wp_unslash( $_GET['key'] ?? '' ) ); // phpcs:enable - $payment_methods = $c->get('ppcp-local-apms.payment-methods'); + $payment_methods = $c->get( 'ppcp-local-apms.payment-methods' ); if ( - ! $this->is_local_apm($order->get_payment_method(), $payment_methods) + ! $this->is_local_apm( $order->get_payment_method(), $payment_methods ) || ! $cancelled || $order->get_order_key() !== $order_key ) { @@ -152,12 +152,12 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { * Check if given payment method is a local APM. * * @param string $selected_payment_method Selected payment method. - * @param array $payment_methods Available local APMs. + * @param array $payment_methods Available local APMs. * @return bool */ - private function is_local_apm(string $selected_payment_method, array $payment_methods): bool { - foreach ($payment_methods as $payment_method) { - if($payment_method['id'] === $selected_payment_method) { + private function is_local_apm( string $selected_payment_method, array $payment_methods ): bool { + foreach ( $payment_methods as $payment_method ) { + if ( $payment_method['id'] === $selected_payment_method ) { return true; } } diff --git a/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php index 11ffa6afa..132f918ac 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/MyBankPaymentMethod.php @@ -40,8 +40,8 @@ class MyBankPaymentMethod extends AbstractPaymentMethodType { /** * MyBankPaymentMethod constructor. * - * @param string $module_url The URL of this module. - * @param string $version The assets version. + * @param string $module_url The URL of this module. + * @param string $version The assets version. * @param MyBankGateway $gateway MyBank WC gateway. */ public function __construct( diff --git a/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php b/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php index 8cbda2ac9..87ba625a2 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php +++ b/modules/ppcp-local-alternative-payment-methods/src/TrustlyPaymentMethod.php @@ -40,8 +40,8 @@ class TrustlyPaymentMethod extends AbstractPaymentMethodType { /** * TrustlyPaymentMethod constructor. * - * @param string $module_url The URL of this module. - * @param string $version The assets version. + * @param string $module_url The URL of this module. + * @param string $version The assets version. * @param TrustlyGateway $gateway Trustly WC gateway. */ public function __construct( From 2c13266e8cc2be987f2671fdd95465490a9c4c34 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 17:47:48 +0200 Subject: [PATCH 28/29] Update descriptions --- .../src/BancontactGateway.php | 2 +- .../ppcp-local-alternative-payment-methods/src/BlikGateway.php | 2 +- .../ppcp-local-alternative-payment-methods/src/EPSGateway.php | 2 +- .../ppcp-local-alternative-payment-methods/src/IDealGateway.php | 2 +- .../src/MyBankGateway.php | 2 +- .../ppcp-local-alternative-payment-methods/src/P24Gateway.php | 2 +- .../src/TrustlyGateway.php | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php index f2bb039d2..c37be41ec 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BancontactGateway.php @@ -73,7 +73,7 @@ class BancontactGateway extends WC_Payment_Gateway { ); $this->method_title = __( 'Bancontact', 'woocommerce-paypal-payments' ); - $this->method_description = __( 'Bancontact', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'A popular and trusted electronic payment method in Belgium, used by Belgian customers with Bancontact cards issued by local banks. Transactions are processed in EUR.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'Bancontact', 'woocommerce-paypal-payments' ) ); $this->description = $this->get_option( 'description', '' ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php b/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php index 5eeea02c9..ec49df338 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/BlikGateway.php @@ -73,7 +73,7 @@ class BlikGateway extends WC_Payment_Gateway { ); $this->method_title = __( 'Blik', 'woocommerce-paypal-payments' ); - $this->method_description = __( 'Blik', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'A widely used mobile payment method in Poland, allowing Polish customers to pay directly via their banking apps. Transactions are processed in PLN.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'Blik', 'woocommerce-paypal-payments' ) ); $this->description = $this->get_option( 'description', '' ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php b/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php index a8dc07c20..4bc74985f 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/EPSGateway.php @@ -73,7 +73,7 @@ class EPSGateway extends WC_Payment_Gateway { ); $this->method_title = __( 'EPS', 'woocommerce-paypal-payments' ); - $this->method_description = __( 'EPS', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'An online payment method in Austria, enabling Austrian buyers to make secure payments directly through their bank accounts. Transactions are processed in EUR.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'EPS', 'woocommerce-paypal-payments' ) ); $this->description = $this->get_option( 'description', '' ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php b/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php index 0d6ece5e7..7c1d65436 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/IDealGateway.php @@ -73,7 +73,7 @@ class IDealGateway extends WC_Payment_Gateway { ); $this->method_title = __( 'iDeal', 'woocommerce-paypal-payments' ); - $this->method_description = __( 'iDeal', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'The most common payment method in the Netherlands, allowing Dutch buyers to pay directly through their preferred bank. Transactions are processed in EUR.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'iDeal', 'woocommerce-paypal-payments' ) ); $this->description = $this->get_option( 'description', '' ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php b/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php index 28c66d80b..ec33430b8 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/MyBankGateway.php @@ -73,7 +73,7 @@ class MyBankGateway extends WC_Payment_Gateway { ); $this->method_title = __( 'MyBank', 'woocommerce-paypal-payments' ); - $this->method_description = __( 'MyBank', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'A European online banking payment solution primarily used in Italy, enabling customers to make secure bank transfers during checkout. Transactions are processed in EUR.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'MyBank', 'woocommerce-paypal-payments' ) ); $this->description = $this->get_option( 'description', '' ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php b/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php index e219f611e..97e23f7c0 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/P24Gateway.php @@ -73,7 +73,7 @@ class P24Gateway extends WC_Payment_Gateway { ); $this->method_title = __( 'Przelewy24', 'woocommerce-paypal-payments' ); - $this->method_description = __( 'Przelewy24', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'A popular online payment gateway in Poland, offering various payment options for Polish customers. Transactions can be processed in PLN or EUR.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'Przelewy24', 'woocommerce-paypal-payments' ) ); $this->description = $this->get_option( 'description', '' ); diff --git a/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php b/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php index 71f97d608..7d34e02d7 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php +++ b/modules/ppcp-local-alternative-payment-methods/src/TrustlyGateway.php @@ -73,7 +73,7 @@ class TrustlyGateway extends WC_Payment_Gateway { ); $this->method_title = __( 'Trustly', 'woocommerce-paypal-payments' ); - $this->method_description = __( 'Trustly', 'woocommerce-paypal-payments' ); + $this->method_description = __( 'A European payment method that allows buyers to make payments directly from their bank accounts, suitable for customers across multiple European countries. Supported currencies include EUR, DKK, SEK, GBP, and NOK.', 'woocommerce-paypal-payments' ); $this->title = $this->get_option( 'title', __( 'Trustly', 'woocommerce-paypal-payments' ) ); $this->description = $this->get_option( 'description', '' ); From cdc02f1c380f194c320b26ff99dc5ed3c9181ceb Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 21 Aug 2024 18:00:03 +0200 Subject: [PATCH 29/29] Ensuse wc customer exist before using it --- .../src/LocalAlternativePaymentMethodsModule.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php index 4f7b8e497..88edf6b31 100644 --- a/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php +++ b/modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php @@ -69,6 +69,10 @@ class LocalAlternativePaymentMethodsModule implements ModuleInterface { } if ( ! is_admin() ) { + if ( ! isset( WC()->customer ) ) { + return $methods; + } + $customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country(); $site_currency = get_woocommerce_currency();