diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index e47208e50..e78269a31 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -1,6 +1,6 @@ name: e2e tests -on: [push] +on: workflow_dispatch jobs: build: diff --git a/api/order-functions.php b/api/order-functions.php index 340be8585..cbfa42968 100644 --- a/api/order-functions.php +++ b/api/order-functions.php @@ -87,6 +87,32 @@ function ppcp_capture_order( WC_Order $wc_order ): void { } } +/** + * Reauthorizes the PayPal order. + * + * @param WC_Order $wc_order The WC order. + * @throws InvalidArgumentException When the order cannot be captured. + * @throws Exception When the operation fails. + */ +function ppcp_reauthorize_order( WC_Order $wc_order ): void { + $intent = strtoupper( (string) $wc_order->get_meta( PayPalGateway::INTENT_META_KEY ) ); + + if ( $intent !== 'AUTHORIZE' ) { + throw new InvalidArgumentException( 'Only orders with "authorize" intent can be reauthorized.' ); + } + $captured = wc_string_to_bool( $wc_order->get_meta( AuthorizedPaymentsProcessor::CAPTURED_META_KEY ) ); + if ( $captured ) { + throw new InvalidArgumentException( 'The order is already captured.' ); + } + + $authorized_payment_processor = PPCP::container()->get( 'wcgateway.processor.authorized-payments' ); + assert( $authorized_payment_processor instanceof AuthorizedPaymentsProcessor ); + + if ( $authorized_payment_processor->reauthorize_payment( $wc_order ) !== AuthorizedPaymentsProcessor::SUCCESSFUL ) { + throw new RuntimeException( $authorized_payment_processor->reauthorization_failure_reason() ?: 'Reauthorization failed.' ); + } +} + /** * Refunds the PayPal order. * Note that you can use wc_refund_payment() to trigger the refund in WC and PayPal. diff --git a/changelog.txt b/changelog.txt index 8fad1f0f0..ad4695527 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,107 @@ *** Changelog *** -= 2.4.2 - xxx-xx-xx = += 2.6.1 - 2024-04-09 = +* Fix - Payment tokens fixes and adjustments #2106 +* Fix - Pay upon Invoice: Add input validation to Experience Context fields #2092 +* Fix - Disable markup in get_plugin_data() returns to fix an issue with wptexturize() #2094 +* Fix - Problem changing the shipping option in block pages #2142 +* Fix - Saved payment token deleted after payment with another saved payment token #2146 +* Enhancement - Pay later messaging configurator improvements #2107 +* Enhancement - Replace the middleware URL from connect.woocommerce.com to api.woocommerce.com/integrations #2130 +* Enhancement - Remove all Sofort references as it has been deprecated #2124 +* Enhancement - Improve funding source names #2118 +* Enhancement - More fraud prevention capabilities by storing additional data in the order #2125 +* Enhancement - Update ACDC currency eligibility for AMEX #2129 +* Enhancement - Sync shipping options with Venmo when skipping final confirmation on Checkout #2108 +* Enhancement - Card Fields: Add a filter for the CVC field and update the placeholder to match the label #2089 +* Enhancement - Product Title: Sanitize before sending to PayPal #2090 +* Enhancement - Add filter for disabling permit_multiple_payment_tokens vault attribute #2136 +* Enhancement - Filter to hide PayPal email address not working on order detail #2137 + += 2.6.0 - 2024-03-20 = +* Fix - invoice_id not included in API call when creating payment with saved card #2086 +* Fix - Typo in SCA indicators for ACDC Vault transactions #2083 +* Fix - Payments with saved card tokens use Capture intent when Authorize is configured #2069 +* Fix - WooPayments multi-currency causing currency mismatch error on Block Cart & Checkout pages #2054 +* Fix - "Must pass createSubscription with intent=subscription" error with PayPal Subscriptions mode #2058 +* Fix - "Proceed to PayPal" button displayed for Free trial PayPal Subscription products when payment token is saved #2041 +* Fix - ACDC payments with new credit card may fail when debugging is enabled (JSON malformed by warning) #2051 +* Enhancement - Add Pay Later Messaging block #1897 +* Enhancement - Submit the form instead of refreshing the page to show the save notice #2081 +* Enhancement - Integrate pay later messaging block with the messaging configurator #2080 +* Enhancement - Reauthorize authorized payments #2062 +* Enhancement - Do not handle VAULT.PAYMENT-TOKEN.CREATED webhook for Vault v3 #2079 +* Enhancement - Improve the messaging configurator styles #2053 +* Enhancement - Ensure PayPal Vaulting is not selected as Subscriptions Mode when Reference Transactions are disabled #2057 +* Enhancement - Pay later messaging configurator & messaging block adjustments #2096 + += 2.5.4 - 2024-02-27 = +* Fix - Cannot enable Apple Pay when API credentials were manually created #2015 +* Fix - Cart simulation type error #1943 +* Enhancement - Apple Pay recurring payments #1986 +* Enhancement - Real Time Account Updater (RTAU) integration #2027 +* Enhancement - Prepare the SKU for sending to PayPal #2033 +* Enhancement - Store the Card Brand in Address Verification Result instead of 3DS authentication result #2026 +* Enhancement - Update country eligibility for AdvancedCard Processing, Apple Pay, Google Pay #2019 +* Enhancement - Disable PayPal Vaulting setting instead of hiding it when Reference Transactions not available #2029 +* Enhancement - Store three d secure enrollment status and authentication status responses in wc order #1980 +* Enhancement - Add more checks to prevent "PayPal order ID not found" errors #2038 +* Enhancement - Disable messaging configurator when vault is enabled #2042 +* Feature preview - Pay Later Messaging configurator #1924 + += 2.5.3 - 2024-02-06 = +* Fix - Free trial subscription products using PayPal Vaulting when PayPal Subscriptions configured as Subscriptions Mode #1979 +* Fix - Pay by link - Germany - PayPal buttons are not visible on Pay for order page #2014 +* Enhancement - Extend Apple Pay, Google Pay, Vault v3 (& RTAU) country availability #1992 +* Enhancement - Enable card fields for ACDC and Vault v3 supported countries/currencies #2007 +* Enhancement - Update ACDC supported currencies list #1991 +* Enhancement - Check if the $wpdb->wc_orders exists before query #1996 +* Enhancement - Remove MercadoPago from disable funding sources #2003 +* Enhancement - Improve onboarding notice text #2002 + += 2.5.2 - 2024-02-01 = +* Fix - NOT_ENABLED_TO_VAULT_PAYMENT_SOURCE error for merchants without reference transactions #1984 +* Fix - Fatal error in WooCommerce PayPal Payments plugin after 2.5.0 update #1985 +* Fix - Can not refund order purchased with Vault v3 Card payment #1997 +* Fix - PayPal Vaulting Subscriptions mode setting visible when merchant not enabled for Reference Transactions #1999 +* Fix - card-fields parameter included in button script despite Advanced Card Processing disabled #2005 +* Enhancement - Add setup URL for reference transactions #1964 +* Enhancement - Improve PUI performance for variable products #1950 + += 2.5.1 - 2024-01-24 = +* Temporary revert Vaulting integration changes introduced in 2.5.0 + += 2.5.0 - 2024-01-22 = +* Fix - WC Subscriptions change subscription payment #1953 +* Fix - GooglePay and ApplePay buttons disappear from the minicart when adding a product to the cart on the shop page #1915 +* Enhancement - Enable Vault v3 and Card Fields by default for US merchants #1967 +* Enhancement - Vault v3 WC Subscriptions integration #1920 +* Enhancement - Implement early WC validation for Hosted Card Fields #1925 +* Enhancement - Rename button locations #1946 +* Enhancement - Improve Apple Pay validation notice text #1938 +* Enhancement - Improve feature availability check UX #1941 +* Enhancement - Make all hosted card fields strings translatable #1926 +* Enhancement - PHP 8.2 deprecations #1939 +* Enhancement - Subscription support on Block Cart & Block Express Checkout #1956 +* Enhancement - Venmo Vaulting integration #1958 +* Enhancement - Add package tracking support for UK #1970 + += 2.4.3 - 2024-01-04 = +* Fix - PayPal Subscription initiated without a WooCommerce order #1907 +* Fix - Block Checkout reloads when submitting order with empty fields #1904 +* Fix - "Send checkout billing and shipping data to Apple Pay" displayed when Apple Pay is disabled #1883 +* Fix - "Order does not contain intent" error for ACDC renewals when triggering 3D Secure #1888 +* Fix - PayPal Subscriptions button greyed out (inactive) on Checkout page for variable subscription products #1914 +* Enhancement - Add button to reload feature eligibility status from Connection tab #1902 +* Enhancement - Apple Pay validation message improvements #1901 +* Enhancement - Improve support for Classic Cart & Classic Checkout blocks #1894 +* Enhancement - Ensure uniform button appearance for PayPal, Google Pay, and Apple Pay buttons #1900 +* Enhancement - remove string translations for package tracking carriers from repository #1885 +* Enhancement - Incorrect margins when PayPal buttons are rendered as separate gateways. #1908 +* Enhancement - Improved button spacing when Apple Pay is enabled but current buyer is not eligible #1922 +* Feature preview - Save payment methods (Vault v3) integration #1779 + += 2.4.2 - 2023-12-04 = * Fix - Action callback arguments count in ShipStation tracking integration #1841 * Fix - Google Pay scripts loading on unrelated admin pages #1834 * Fix - Do not ignore disabled APMs list in blocks #1865 @@ -112,7 +213,7 @@ * Feature preview - Google Pay integration #1654 = 2.2.2 - 2023-08-29 = -* Fix - High rate of auth voids on vaulted subscriptions for guest users #1529 +* Fix - High rate of auth voids on vaulted subscriptions for guest users #1529 * Enhancement - HPOS compatibility issues #1594 * Feature preview - PayPal Subscriptions API fixes and improvements #1600 #1607 diff --git a/composer.lock b/composer.lock index 450c96e96..9bd08ba42 100644 --- a/composer.lock +++ b/composer.lock @@ -8,20 +8,20 @@ "packages": [ { "name": "container-interop/service-provider", - "version": "v0.4.0", + "version": "v0.4.1", "source": { "type": "git", "url": "https://github.com/container-interop/service-provider.git", - "reference": "4969b9e49460690b7430b3f1a87cab07be61418a" + "reference": "e04441ca21ef03e10dce70b0af29269281eec6dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/container-interop/service-provider/zipball/4969b9e49460690b7430b3f1a87cab07be61418a", - "reference": "4969b9e49460690b7430b3f1a87cab07be61418a", + "url": "https://api.github.com/repos/container-interop/service-provider/zipball/e04441ca21ef03e10dce70b0af29269281eec6dc", + "reference": "e04441ca21ef03e10dce70b0af29269281eec6dc", "shasum": "" }, "require": { - "psr/container": "^1.0" + "psr/container": "^1.0 || ^2.0" }, "type": "library", "autoload": { @@ -37,9 +37,9 @@ "homepage": "https://github.com/container-interop/service-provider", "support": { "issues": "https://github.com/container-interop/service-provider/issues", - "source": "https://github.com/container-interop/service-provider/tree/master" + "source": "https://github.com/container-interop/service-provider/tree/v0.4.1" }, - "time": "2017-09-20T14:13:36+00:00" + "time": "2023-12-14T14:50:12+00:00" }, { "name": "dhii/human-readable-interface", @@ -438,16 +438,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", "shasum": "" }, "require": { @@ -455,9 +455,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -501,7 +498,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" }, "funding": [ { @@ -517,7 +514,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "wikimedia/composer-merge-plugin", @@ -797,16 +794,16 @@ }, { "name": "antecedent/patchwork", - "version": "2.1.25", + "version": "2.1.28", "source": { "type": "git", "url": "https://github.com/antecedent/patchwork.git", - "reference": "17314e042d45e0dacb0a494c2d1ef50e7621136a" + "reference": "6b30aff81ebadf0f2feb9268d3e08385cebcc08d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/antecedent/patchwork/zipball/17314e042d45e0dacb0a494c2d1ef50e7621136a", - "reference": "17314e042d45e0dacb0a494c2d1ef50e7621136a", + "url": "https://api.github.com/repos/antecedent/patchwork/zipball/6b30aff81ebadf0f2feb9268d3e08385cebcc08d", + "reference": "6b30aff81ebadf0f2feb9268d3e08385cebcc08d", "shasum": "" }, "require": { @@ -827,7 +824,7 @@ } ], "description": "Method redefinition (monkey-patching) functionality for PHP.", - "homepage": "http://patchwork2.org/", + "homepage": "https://antecedent.github.io/patchwork/", "keywords": [ "aop", "aspect", @@ -839,9 +836,9 @@ ], "support": { "issues": "https://github.com/antecedent/patchwork/issues", - "source": "https://github.com/antecedent/patchwork/tree/2.1.25" + "source": "https://github.com/antecedent/patchwork/tree/2.1.28" }, - "time": "2023-02-19T12:51:24+00:00" + "time": "2024-02-06T09:26:11+00:00" }, { "name": "brain/monkey", @@ -988,16 +985,16 @@ }, { "name": "composer/pcre", - "version": "2.1.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "3fdb2807b31a78a40ad89570e30ec77466c98717" + "reference": "b439557066cd445732fa57cbc8d905394b4db8a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/3fdb2807b31a78a40ad89570e30ec77466c98717", - "reference": "3fdb2807b31a78a40ad89570e30ec77466c98717", + "url": "https://api.github.com/repos/composer/pcre/zipball/b439557066cd445732fa57cbc8d905394b4db8a0", + "reference": "b439557066cd445732fa57cbc8d905394b4db8a0", "shasum": "" }, "require": { @@ -1039,7 +1036,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/2.1.0" + "source": "https://github.com/composer/pcre/tree/2.1.1" }, "funding": [ { @@ -1055,20 +1052,20 @@ "type": "tidelift" } ], - "time": "2022-11-16T18:32:04+00:00" + "time": "2023-10-11T07:10:55+00:00" }, { "name": "composer/semver", - "version": "3.3.2", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", "shasum": "" }, "require": { @@ -1118,9 +1115,9 @@ "versioning" ], "support": { - "irc": "irc://irc.freenode.org/composer", + "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" + "source": "https://github.com/composer/semver/tree/3.4.0" }, "funding": [ { @@ -1136,7 +1133,7 @@ "type": "tidelift" } ], - "time": "2022-04-01T19:23:25+00:00" + "time": "2023-08-31T09:50:34+00:00" }, { "name": "composer/xdebug-handler", @@ -1604,24 +1601,24 @@ }, { "name": "graham-campbell/result-type", - "version": "v1.1.1", + "version": "v1.1.2", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831" + "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", - "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862", + "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.1" + "phpoption/phpoption": "^1.9.2" }, "require-dev": { - "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" }, "type": "library", "autoload": { @@ -1650,7 +1647,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.1" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.2" }, "funding": [ { @@ -1662,7 +1659,7 @@ "type": "tidelift" } ], - "time": "2023-02-25T20:23:15+00:00" + "time": "2023-11-12T22:16:48+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -1845,16 +1842,16 @@ }, { "name": "netresearch/jsonmapper", - "version": "v4.2.0", + "version": "v4.4.1", "source": { "type": "git", "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956" + "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/132c75c7dd83e45353ebb9c6c9f591952995bbf0", + "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0", "shasum": "" }, "require": { @@ -1865,7 +1862,7 @@ "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0", "squizlabs/php_codesniffer": "~3.5" }, "type": "library", @@ -1890,22 +1887,22 @@ "support": { "email": "cweiske@cweiske.de", "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0" + "source": "https://github.com/cweiske/jsonmapper/tree/v4.4.1" }, - "time": "2023-04-09T17:37:40+00:00" + "time": "2024-01-31T06:18:54+00:00" }, { "name": "nikic/php-parser", - "version": "v4.16.0", + "version": "v4.18.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "19526a33fb561ef417e822e85f08a00db4059c17" + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", - "reference": "19526a33fb561ef417e822e85f08a00db4059c17", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", "shasum": "" }, "require": { @@ -1946,9 +1943,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" }, - "time": "2023-06-25T14:52:30+00:00" + "time": "2023-12-10T21:03:43+00:00" }, { "name": "openlss/lib-array2xml", @@ -2539,16 +2536,16 @@ }, { "name": "phpoption/phpoption", - "version": "1.9.1", + "version": "1.9.2", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e" + "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e", - "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820", + "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820", "shasum": "" }, "require": { @@ -2556,7 +2553,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" }, "type": "library", "extra": { @@ -2598,7 +2595,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.1" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" }, "funding": [ { @@ -2610,7 +2607,7 @@ "type": "tidelift" } ], - "time": "2023-02-25T19:38:58+00:00" + "time": "2023-11-12T21:59:55+00:00" }, { "name": "phpunit/php-code-coverage", @@ -2911,16 +2908,16 @@ }, { "name": "phpunit/phpunit", - "version": "8.5.33", + "version": "8.5.36", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "7d1ff0e8c6b35db78ff13e3e05517d7cbf7aa32e" + "reference": "9652df58e06a681429d8cfdaec3c43d6de581d5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7d1ff0e8c6b35db78ff13e3e05517d7cbf7aa32e", - "reference": "7d1ff0e8c6b35db78ff13e3e05517d7cbf7aa32e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9652df58e06a681429d8cfdaec3c43d6de581d5a", + "reference": "9652df58e06a681429d8cfdaec3c43d6de581d5a", "shasum": "" }, "require": { @@ -2950,9 +2947,9 @@ "sebastian/version": "^2.0.1" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0.0" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage", + "phpunit/php-invoker": "To allow enforcing time limits" }, "bin": [ "phpunit" @@ -2988,7 +2985,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.33" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.36" }, "funding": [ { @@ -3004,7 +3002,7 @@ "type": "tidelift" } ], - "time": "2023-02-27T13:04:50+00:00" + "time": "2023-12-01T16:52:15+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -3343,16 +3341,16 @@ }, { "name": "sebastian/global-state", - "version": "3.0.2", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "de036ec91d55d2a9e0db2ba975b512cdb1c23921" + "reference": "66783ce213de415b451b904bfef9dda0cf9aeae0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/de036ec91d55d2a9e0db2ba975b512cdb1c23921", - "reference": "de036ec91d55d2a9e0db2ba975b512cdb1c23921", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/66783ce213de415b451b904bfef9dda0cf9aeae0", + "reference": "66783ce213de415b451b904bfef9dda0cf9aeae0", "shasum": "" }, "require": { @@ -3395,7 +3393,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.3" }, "funding": [ { @@ -3403,7 +3401,7 @@ "type": "github" } ], - "time": "2022-02-10T06:55:38+00:00" + "time": "2023-08-02T09:23:32+00:00" }, { "name": "sebastian/object-enumerator", @@ -3737,16 +3735,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.7.2", + "version": "3.8.1", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "14f5fff1e64118595db5408e946f3a22c75807f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", - "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/14f5fff1e64118595db5408e946f3a22c75807f7", + "reference": "14f5fff1e64118595db5408e946f3a22c75807f7", "shasum": "" }, "require": { @@ -3756,11 +3754,11 @@ "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "bin": [ - "bin/phpcs", - "bin/phpcbf" + "bin/phpcbf", + "bin/phpcs" ], "type": "library", "extra": { @@ -3775,35 +3773,58 @@ "authors": [ { "name": "Greg Sherwood", - "role": "lead" + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ "phpcs", "standards", "static analysis" ], "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, - "time": "2023-02-22T23:07:41+00:00" + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], + "time": "2024-01-11T20:47:48+00:00" }, { "name": "symfony/console", - "version": "v5.4.26", + "version": "v5.4.35", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "b504a3d266ad2bb632f196c0936ef2af5ff6e273" + "reference": "dbdf6adcb88d5f83790e1efb57ef4074309d3931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/b504a3d266ad2bb632f196c0936ef2af5ff6e273", - "reference": "b504a3d266ad2bb632f196c0936ef2af5ff6e273", + "url": "https://api.github.com/repos/symfony/console/zipball/dbdf6adcb88d5f83790e1efb57ef4074309d3931", + "reference": "dbdf6adcb88d5f83790e1efb57ef4074309d3931", "shasum": "" }, "require": { @@ -3873,7 +3894,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.26" + "source": "https://github.com/symfony/console/tree/v5.4.35" }, "funding": [ { @@ -3889,7 +3910,7 @@ "type": "tidelift" } ], - "time": "2023-07-19T20:11:33+00:00" + "time": "2024-01-23T14:28:09+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3960,16 +3981,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", "shasum": "" }, "require": { @@ -3983,9 +4004,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4022,7 +4040,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" }, "funding": [ { @@ -4038,20 +4056,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", "shasum": "" }, "require": { @@ -4062,9 +4080,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4103,7 +4118,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" }, "funding": [ { @@ -4119,20 +4134,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", "shasum": "" }, "require": { @@ -4143,9 +4158,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4187,7 +4199,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" }, "funding": [ { @@ -4203,20 +4215,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "shasum": "" }, "require": { @@ -4230,9 +4242,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4270,7 +4279,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" }, "funding": [ { @@ -4286,20 +4295,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.27.0", + "version": "v1.29.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", "shasum": "" }, "require": { @@ -4307,9 +4316,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -4349,7 +4355,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.29.0" }, "funding": [ { @@ -4365,7 +4371,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-01-29T20:11:03+00:00" }, { "name": "symfony/service-contracts", @@ -4452,16 +4458,16 @@ }, { "name": "symfony/string", - "version": "v5.4.26", + "version": "v5.4.35", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "1181fe9270e373537475e826873b5867b863883c" + "reference": "c209c4d0559acce1c9a2067612cfb5d35756edc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/1181fe9270e373537475e826873b5867b863883c", - "reference": "1181fe9270e373537475e826873b5867b863883c", + "url": "https://api.github.com/repos/symfony/string/zipball/c209c4d0559acce1c9a2067612cfb5d35756edc2", + "reference": "c209c4d0559acce1c9a2067612cfb5d35756edc2", "shasum": "" }, "require": { @@ -4518,7 +4524,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.26" + "source": "https://github.com/symfony/string/tree/v5.4.35" }, "funding": [ { @@ -4534,20 +4540,20 @@ "type": "tidelift" } ], - "time": "2023-06-28T12:46:07+00:00" + "time": "2024-01-23T13:51:25+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", "shasum": "" }, "require": { @@ -4576,7 +4582,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" }, "funding": [ { @@ -4584,7 +4590,7 @@ "type": "github" } ], - "time": "2021-07-28T10:34:58+00:00" + "time": "2023-11-20T00:12:19+00:00" }, { "name": "vimeo/psalm", @@ -4696,31 +4702,31 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.5.0", + "version": "v5.6.0", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7" + "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", - "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.0.2", - "php": "^7.1.3 || ^8.0", - "phpoption/phpoption": "^1.8", - "symfony/polyfill-ctype": "^1.23", - "symfony/polyfill-mbstring": "^1.23.1", - "symfony/polyfill-php80": "^1.23.1" + "graham-campbell/result-type": "^1.1.2", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.2", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-filter": "*", - "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25" + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" }, "suggest": { "ext-filter": "Required to use the boolean validator." @@ -4732,7 +4738,7 @@ "forward-command": true }, "branch-alias": { - "dev-master": "5.5-dev" + "dev-master": "5.6-dev" } }, "autoload": { @@ -4764,7 +4770,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.5.0" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0" }, "funding": [ { @@ -4776,7 +4782,7 @@ "type": "tidelift" } ], - "time": "2022-10-16T01:01:54+00:00" + "time": "2023-11-12T22:43:29+00:00" }, { "name": "webmozart/assert", @@ -4996,5 +5002,5 @@ "ext-json": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/modules.php b/modules.php index b386df62a..c6840d8ab 100644 --- a/modules.php +++ b/modules.php @@ -5,6 +5,8 @@ * @package WooCommerce\PayPalCommerce */ +use WooCommerce\PayPalCommerce\PayLaterBlock\PayLaterBlockModule; +use WooCommerce\PayPalCommerce\PayLaterConfigurator\PayLaterConfiguratorModule; use WooCommerce\PayPalCommerce\PluginModule; return function ( string $root_dir ): iterable { @@ -20,16 +22,18 @@ return function ( string $root_dir ): iterable { ( require "$modules_dir/ppcp-onboarding/module.php" )(), ( require "$modules_dir/ppcp-session/module.php" )(), ( require "$modules_dir/ppcp-status-report/module.php" )(), - ( require "$modules_dir/ppcp-subscription/module.php" )(), + ( require "$modules_dir/ppcp-wc-subscriptions/module.php" )(), ( require "$modules_dir/ppcp-wc-gateway/module.php" )(), ( require "$modules_dir/ppcp-webhooks/module.php" )(), ( require "$modules_dir/ppcp-vaulting/module.php" )(), ( require "$modules_dir/ppcp-order-tracking/module.php" )(), ( require "$modules_dir/ppcp-uninstall/module.php" )(), ( require "$modules_dir/ppcp-blocks/module.php" )(), + ( require "$modules_dir/ppcp-paypal-subscriptions/module.php" )(), ); + // phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores + if ( apply_filters( - // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores 'woocommerce.feature-flags.woocommerce_paypal_payments.applepay_enabled', getenv( 'PCP_APPLEPAY_ENABLED' ) !== '0' ) ) { @@ -37,7 +41,6 @@ return function ( string $root_dir ): iterable { } if ( apply_filters( - //phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores 'woocommerce.feature-flags.woocommerce_paypal_payments.googlepay_enabled', getenv( 'PCP_GOOGLEPAY_ENABLED' ) !== '0' ) ) { @@ -45,7 +48,6 @@ return function ( string $root_dir ): iterable { } if ( apply_filters( - //phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores 'woocommerce.deprecated_flags.woocommerce_paypal_payments.saved_payment_checker_enabled', getenv( 'PCP_SAVED_PAYMENT_CHECKER_ENABLED' ) === '1' ) ) { @@ -53,12 +55,26 @@ return function ( string $root_dir ): iterable { } if ( apply_filters( - //phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores 'woocommerce.feature-flags.woocommerce_paypal_payments.card_fields_enabled', - getenv( 'PCP_CARD_FIELDS_ENABLED' ) === '1' + getenv( 'PCP_CARD_FIELDS_ENABLED' ) !== '0' ) ) { $modules[] = ( require "$modules_dir/ppcp-card-fields/module.php" )(); } + if ( apply_filters( + 'woocommerce.feature-flags.woocommerce_paypal_payments.save_payment_methods_enabled', + getenv( 'PCP_SAVE_PAYMENT_METHODS' ) !== '0' + ) ) { + $modules[] = ( require "$modules_dir/ppcp-save-payment-methods/module.php" )(); + } + + if ( PayLaterBlockModule::is_module_loading_required() ) { + $modules[] = ( require "$modules_dir/ppcp-paylater-block/module.php" )(); + } + + if ( PayLaterConfiguratorModule::is_enabled() ) { + $modules[] = ( require "$modules_dir/ppcp-paylater-configurator/module.php" )(); + } + return $modules; }; diff --git a/modules/ppcp-admin-notices/src/AdminNotices.php b/modules/ppcp-admin-notices/src/AdminNotices.php index 73fe24b71..0489df02c 100644 --- a/modules/ppcp-admin-notices/src/AdminNotices.php +++ b/modules/ppcp-admin-notices/src/AdminNotices.php @@ -9,6 +9,8 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\AdminNotices; +use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message; +use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; @@ -40,6 +42,34 @@ class AdminNotices implements ModuleInterface { $renderer->render(); } ); + + add_action( + Repository::NOTICES_FILTER, + /** + * Adds persisted notices to the notices array. + * + * @param array $notices The notices. + * @return array + * + * @psalm-suppress MissingClosureParamType + */ + function ( $notices ) use ( $c ) { + if ( ! is_array( $notices ) ) { + return $notices; + } + + $admin_notices = $c->get( 'admin-notices.repository' ); + assert( $admin_notices instanceof Repository ); + + $persisted_notices = $admin_notices->get_persisted_and_clear(); + + if ( $persisted_notices ) { + $notices = array_merge( $notices, $persisted_notices ); + } + + return $notices; + } + ); } /** diff --git a/modules/ppcp-admin-notices/src/Entity/Message.php b/modules/ppcp-admin-notices/src/Entity/Message.php index 0e8bc959e..97624d872 100644 --- a/modules/ppcp-admin-notices/src/Entity/Message.php +++ b/modules/ppcp-admin-notices/src/Entity/Message.php @@ -92,4 +92,18 @@ class Message { public function wrapper(): string { return $this->wrapper; } + + /** + * Returns the object as array. + * + * @return array + */ + public function to_array(): array { + return array( + 'type' => $this->type, + 'message' => $this->message, + 'dismissable' => $this->dismissable, + 'wrapper' => $this->wrapper, + ); + } } diff --git a/modules/ppcp-admin-notices/src/Repository/Repository.php b/modules/ppcp-admin-notices/src/Repository/Repository.php index e13a5dd6c..9573a81a4 100644 --- a/modules/ppcp-admin-notices/src/Repository/Repository.php +++ b/modules/ppcp-admin-notices/src/Repository/Repository.php @@ -16,7 +16,8 @@ use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message; */ class Repository implements RepositoryInterface { - const NOTICES_FILTER = 'ppcp.admin-notices.current-notices'; + const NOTICES_FILTER = 'ppcp.admin-notices.current-notices'; + const PERSISTED_NOTICES_OPTION = 'woocommerce_ppcp-admin-notices'; /** * Returns the current messages. @@ -37,4 +38,40 @@ class Repository implements RepositoryInterface { } ); } + + /** + * Adds a message to persist between page reloads. + * + * @param Message $message The message. + * @return void + */ + public function persist( Message $message ): void { + $persisted_notices = get_option( self::PERSISTED_NOTICES_OPTION ) ?: array(); + + $persisted_notices[] = $message->to_array(); + + update_option( self::PERSISTED_NOTICES_OPTION, $persisted_notices ); + } + + /** + * Adds a message to persist between page reloads. + * + * @return array|Message[] + */ + public function get_persisted_and_clear(): array { + $notices = array(); + + $persisted_data = get_option( self::PERSISTED_NOTICES_OPTION ) ?: array(); + foreach ( $persisted_data as $notice_data ) { + $notices[] = new Message( + (string) ( $notice_data['message'] ?? '' ), + (string) ( $notice_data['type'] ?? '' ), + (bool) ( $notice_data['dismissable'] ?? true ), + (string) ( $notice_data['wrapper'] ?? '' ) + ); + } + + update_option( self::PERSISTED_NOTICES_OPTION, array(), true ); + return $notices; + } } diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index 076782081..225530ec2 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -9,12 +9,16 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\ApiClient; +use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; +use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult; +use WooCommerce\PayPalCommerce\ApiClient\Factory\CardAuthenticationResultFactory; use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry; use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\CatalogProducts; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingPlans; -use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerPayableBreakdown; use WooCommerce\PayPalCommerce\ApiClient\Factory\BillingCycleFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentPreferencesFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\RefundFactory; @@ -50,7 +54,6 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PatchCollectionFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayeeFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentsFactory; -use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentSourceFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenActionLinksFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PlatformFeeFactory; @@ -74,39 +77,40 @@ use WooCommerce\PayPalCommerce\ApiClient\Repository\PayeeRepository; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; return array( - 'api.host' => function( ContainerInterface $container ) : string { + 'api.host' => function( ContainerInterface $container ) : string { return PAYPAL_API_URL; }, - 'api.paypal-host' => function( ContainerInterface $container ) : string { + 'api.paypal-host' => function( ContainerInterface $container ) : string { return PAYPAL_API_URL; }, - 'api.paypal-website-url' => function( ContainerInterface $container ) : string { + // It seems this 'api.paypal-website-url' key is always overridden in ppcp-onboarding/services.php. + 'api.paypal-website-url' => function( ContainerInterface $container ) : string { return PAYPAL_URL; }, - 'api.factory.paypal-checkout-url' => function( ContainerInterface $container ) : callable { + 'api.factory.paypal-checkout-url' => function( ContainerInterface $container ) : callable { return function ( string $id ) use ( $container ): string { return $container->get( 'api.paypal-website-url' ) . '/checkoutnow?token=' . $id; }; }, - 'api.partner_merchant_id' => static function () : string { + 'api.partner_merchant_id' => static function () : string { return ''; }, - 'api.merchant_email' => function () : string { + 'api.merchant_email' => function () : string { return ''; }, - 'api.merchant_id' => function () : string { + 'api.merchant_id' => function () : string { return ''; }, - 'api.key' => static function (): string { + 'api.key' => static function (): string { return ''; }, - 'api.secret' => static function (): string { + 'api.secret' => static function (): string { return ''; }, - 'api.prefix' => static function (): string { + 'api.prefix' => static function (): string { return 'WC-'; }, - 'api.bearer' => static function ( ContainerInterface $container ): Bearer { + 'api.bearer' => static function ( ContainerInterface $container ): Bearer { $cache = new Cache( 'ppcp-paypal-bearer' ); $key = $container->get( 'api.key' ); $secret = $container->get( 'api.secret' ); @@ -122,7 +126,7 @@ return array( $settings ); }, - 'api.endpoint.partners' => static function ( ContainerInterface $container ) : PartnersEndpoint { + 'api.endpoint.partners' => static function ( ContainerInterface $container ) : PartnersEndpoint { return new PartnersEndpoint( $container->get( 'api.host' ), $container->get( 'api.bearer' ), @@ -133,10 +137,10 @@ return array( $container->get( 'api.helper.failure-registry' ) ); }, - 'api.factory.sellerstatus' => static function ( ContainerInterface $container ) : SellerStatusFactory { + 'api.factory.sellerstatus' => static function ( ContainerInterface $container ) : SellerStatusFactory { return new SellerStatusFactory(); }, - 'api.endpoint.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenEndpoint { + 'api.endpoint.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenEndpoint { return new PaymentTokenEndpoint( $container->get( 'api.host' ), $container->get( 'api.bearer' ), @@ -146,7 +150,14 @@ return array( $container->get( 'api.repository.customer' ) ); }, - 'api.endpoint.webhook' => static function ( ContainerInterface $container ) : WebhookEndpoint { + 'api.endpoint.payment-tokens' => static function( ContainerInterface $container ) : PaymentTokensEndpoint { + return new PaymentTokensEndpoint( + $container->get( 'api.host' ), + $container->get( 'api.bearer' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, + 'api.endpoint.webhook' => static function ( ContainerInterface $container ) : WebhookEndpoint { return new WebhookEndpoint( $container->get( 'api.host' ), @@ -156,7 +167,7 @@ return array( $container->get( 'woocommerce.logger.woocommerce' ) ); }, - 'api.endpoint.partner-referrals' => static function ( ContainerInterface $container ) : PartnerReferrals { + 'api.endpoint.partner-referrals' => static function ( ContainerInterface $container ) : PartnerReferrals { return new PartnerReferrals( $container->get( 'api.host' ), @@ -164,7 +175,7 @@ return array( $container->get( 'woocommerce.logger.woocommerce' ) ); }, - 'api.endpoint.identity-token' => static function ( ContainerInterface $container ) : IdentityToken { + 'api.endpoint.identity-token' => static function ( ContainerInterface $container ) : IdentityToken { $logger = $container->get( 'woocommerce.logger.woocommerce' ); $settings = $container->get( 'wcgateway.settings' ); $customer_repository = $container->get( 'api.repository.customer' ); @@ -176,7 +187,7 @@ return array( $customer_repository ); }, - 'api.endpoint.payments' => static function ( ContainerInterface $container ): PaymentsEndpoint { + 'api.endpoint.payments' => static function ( ContainerInterface $container ): PaymentsEndpoint { $authorizations_factory = $container->get( 'api.factory.authorization' ); $capture_factory = $container->get( 'api.factory.capture' ); $logger = $container->get( 'woocommerce.logger.woocommerce' ); @@ -189,7 +200,7 @@ return array( $logger ); }, - 'api.endpoint.login-seller' => static function ( ContainerInterface $container ) : LoginSeller { + 'api.endpoint.login-seller' => static function ( ContainerInterface $container ) : LoginSeller { $logger = $container->get( 'woocommerce.logger.woocommerce' ); return new LoginSeller( @@ -198,7 +209,7 @@ return array( $logger ); }, - 'api.endpoint.order' => static function ( ContainerInterface $container ): OrderEndpoint { + 'api.endpoint.order' => static function ( ContainerInterface $container ): OrderEndpoint { $order_factory = $container->get( 'api.factory.order' ); $patch_collection_factory = $container->get( 'api.factory.patch-collection-factory' ); $logger = $container->get( 'woocommerce.logger.woocommerce' ); @@ -212,7 +223,7 @@ return array( $intent = $settings->has( 'intent' ) && strtoupper( (string) $settings->get( 'intent' ) ) === 'AUTHORIZE' ? 'AUTHORIZE' : 'CAPTURE'; $application_context_repository = $container->get( 'api.repository.application-context' ); - $subscription_helper = $container->get( 'subscription.helper' ); + $subscription_helper = $container->get( 'wc-subscriptions.helper' ); return new OrderEndpoint( $container->get( 'api.host' ), $container->get( 'api.bearer' ), @@ -227,14 +238,14 @@ return array( $bn_code ); }, - 'api.endpoint.billing-agreements' => static function ( ContainerInterface $container ): BillingAgreementsEndpoint { + 'api.endpoint.billing-agreements' => static function ( ContainerInterface $container ): BillingAgreementsEndpoint { return new BillingAgreementsEndpoint( $container->get( 'api.host' ), $container->get( 'api.bearer' ), $container->get( 'woocommerce.logger.woocommerce' ) ); }, - 'api.endpoint.catalog-products' => static function ( ContainerInterface $container ): CatalogProducts { + 'api.endpoint.catalog-products' => static function ( ContainerInterface $container ): CatalogProducts { return new CatalogProducts( $container->get( 'api.host' ), $container->get( 'api.bearer' ), @@ -242,7 +253,7 @@ return array( $container->get( 'woocommerce.logger.woocommerce' ) ); }, - 'api.endpoint.billing-plans' => static function( ContainerInterface $container ): BillingPlans { + 'api.endpoint.billing-plans' => static function( ContainerInterface $container ): BillingPlans { return new BillingPlans( $container->get( 'api.host' ), $container->get( 'api.bearer' ), @@ -251,53 +262,60 @@ return array( $container->get( 'woocommerce.logger.woocommerce' ) ); }, - 'api.endpoint.billing-subscriptions' => static function( ContainerInterface $container ): BillingSubscriptions { + 'api.endpoint.billing-subscriptions' => static function( ContainerInterface $container ): BillingSubscriptions { return new BillingSubscriptions( $container->get( 'api.host' ), $container->get( 'api.bearer' ), $container->get( 'woocommerce.logger.woocommerce' ) ); }, - 'api.repository.application-context' => static function( ContainerInterface $container ) : ApplicationContextRepository { + 'api.endpoint.payment-method-tokens' => static function( ContainerInterface $container ): PaymentMethodTokensEndpoint { + return new PaymentMethodTokensEndpoint( + $container->get( 'api.host' ), + $container->get( 'api.bearer' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, + 'api.repository.application-context' => static function( ContainerInterface $container ) : ApplicationContextRepository { $settings = $container->get( 'wcgateway.settings' ); return new ApplicationContextRepository( $settings ); }, - 'api.repository.partner-referrals-data' => static function ( ContainerInterface $container ) : PartnerReferralsData { + 'api.repository.partner-referrals-data' => static function ( ContainerInterface $container ) : PartnerReferralsData { $dcc_applies = $container->get( 'api.helpers.dccapplies' ); return new PartnerReferralsData( $dcc_applies ); }, - 'api.repository.payee' => static function ( ContainerInterface $container ): PayeeRepository { + 'api.repository.payee' => static function ( ContainerInterface $container ): PayeeRepository { $merchant_email = $container->get( 'api.merchant_email' ); $merchant_id = $container->get( 'api.merchant_id' ); return new PayeeRepository( $merchant_email, $merchant_id ); }, - 'api.repository.customer' => static function( ContainerInterface $container ): CustomerRepository { + 'api.repository.customer' => static function( ContainerInterface $container ): CustomerRepository { $prefix = $container->get( 'api.prefix' ); return new CustomerRepository( $prefix ); }, - 'api.repository.order' => static function( ContainerInterface $container ): OrderRepository { + 'api.repository.order' => static function( ContainerInterface $container ): OrderRepository { return new OrderRepository( $container->get( 'api.endpoint.order' ) ); }, - 'api.factory.application-context' => static function ( ContainerInterface $container ) : ApplicationContextFactory { + 'api.factory.application-context' => static function ( ContainerInterface $container ) : ApplicationContextFactory { return new ApplicationContextFactory(); }, - 'api.factory.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenFactory { + 'api.factory.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenFactory { return new PaymentTokenFactory(); }, - 'api.factory.payment-token-action-links' => static function ( ContainerInterface $container ) : PaymentTokenActionLinksFactory { + 'api.factory.payment-token-action-links' => static function ( ContainerInterface $container ) : PaymentTokenActionLinksFactory { return new PaymentTokenActionLinksFactory(); }, - 'api.factory.webhook' => static function ( ContainerInterface $container ): WebhookFactory { + 'api.factory.webhook' => static function ( ContainerInterface $container ): WebhookFactory { return new WebhookFactory(); }, - 'api.factory.webhook-event' => static function ( ContainerInterface $container ): WebhookEventFactory { + 'api.factory.webhook-event' => static function ( ContainerInterface $container ): WebhookEventFactory { return new WebhookEventFactory(); }, - 'api.factory.capture' => static function ( ContainerInterface $container ): CaptureFactory { + 'api.factory.capture' => static function ( ContainerInterface $container ): CaptureFactory { $amount_factory = $container->get( 'api.factory.amount' ); return new CaptureFactory( @@ -306,7 +324,7 @@ return array( $container->get( 'api.factory.fraud-processor-response' ) ); }, - 'api.factory.refund' => static function ( ContainerInterface $container ): RefundFactory { + 'api.factory.refund' => static function ( ContainerInterface $container ): RefundFactory { $amount_factory = $container->get( 'api.factory.amount' ); return new RefundFactory( $amount_factory, @@ -314,7 +332,7 @@ return array( $container->get( 'api.factory.refund_payer' ) ); }, - 'api.factory.purchase-unit' => static function ( ContainerInterface $container ): PurchaseUnitFactory { + 'api.factory.purchase-unit' => static function ( ContainerInterface $container ): PurchaseUnitFactory { $amount_factory = $container->get( 'api.factory.amount' ); $item_factory = $container->get( 'api.factory.item' ); @@ -334,32 +352,32 @@ return array( $sanitizer ); }, - 'api.factory.patch-collection-factory' => static function ( ContainerInterface $container ): PatchCollectionFactory { + 'api.factory.patch-collection-factory' => static function ( ContainerInterface $container ): PatchCollectionFactory { return new PatchCollectionFactory(); }, - 'api.factory.payee' => static function ( ContainerInterface $container ): PayeeFactory { + 'api.factory.payee' => static function ( ContainerInterface $container ): PayeeFactory { return new PayeeFactory(); }, - 'api.factory.item' => static function ( ContainerInterface $container ): ItemFactory { + 'api.factory.item' => static function ( ContainerInterface $container ): ItemFactory { return new ItemFactory( $container->get( 'api.shop.currency' ) ); }, - 'api.factory.shipping' => static function ( ContainerInterface $container ): ShippingFactory { + 'api.factory.shipping' => static function ( ContainerInterface $container ): ShippingFactory { return new ShippingFactory( $container->get( 'api.factory.address' ), $container->get( 'api.factory.shipping-option' ) ); }, - 'api.factory.shipping-preference' => static function ( ContainerInterface $container ): ShippingPreferenceFactory { + 'api.factory.shipping-preference' => static function ( ContainerInterface $container ): ShippingPreferenceFactory { return new ShippingPreferenceFactory(); }, - 'api.factory.shipping-option' => static function ( ContainerInterface $container ): ShippingOptionFactory { + 'api.factory.shipping-option' => static function ( ContainerInterface $container ): ShippingOptionFactory { return new ShippingOptionFactory( $container->get( 'api.factory.money' ) ); }, - 'api.factory.amount' => static function ( ContainerInterface $container ): AmountFactory { + 'api.factory.amount' => static function ( ContainerInterface $container ): AmountFactory { $item_factory = $container->get( 'api.factory.item' ); return new AmountFactory( $item_factory, @@ -367,86 +385,84 @@ return array( $container->get( 'api.shop.currency' ) ); }, - 'api.factory.money' => static function ( ContainerInterface $container ): MoneyFactory { + 'api.factory.money' => static function ( ContainerInterface $container ): MoneyFactory { return new MoneyFactory(); }, - 'api.factory.payer' => static function ( ContainerInterface $container ): PayerFactory { + 'api.factory.payer' => static function ( ContainerInterface $container ): PayerFactory { $address_factory = $container->get( 'api.factory.address' ); return new PayerFactory( $address_factory ); }, - 'api.factory.refund_payer' => static function ( ContainerInterface $container ): RefundPayerFactory { + 'api.factory.refund_payer' => static function ( ContainerInterface $container ): RefundPayerFactory { return new RefundPayerFactory(); }, - 'api.factory.address' => static function ( ContainerInterface $container ): AddressFactory { + 'api.factory.address' => static function ( ContainerInterface $container ): AddressFactory { return new AddressFactory(); }, - 'api.factory.payment-source' => static function ( ContainerInterface $container ): PaymentSourceFactory { - return new PaymentSourceFactory(); - }, - 'api.factory.order' => static function ( ContainerInterface $container ): OrderFactory { + 'api.factory.order' => static function ( ContainerInterface $container ): OrderFactory { $purchase_unit_factory = $container->get( 'api.factory.purchase-unit' ); $payer_factory = $container->get( 'api.factory.payer' ); $application_context_repository = $container->get( 'api.repository.application-context' ); $application_context_factory = $container->get( 'api.factory.application-context' ); - $payment_source_factory = $container->get( 'api.factory.payment-source' ); return new OrderFactory( $purchase_unit_factory, $payer_factory, $application_context_repository, - $application_context_factory, - $payment_source_factory + $application_context_factory ); }, - 'api.factory.payments' => static function ( ContainerInterface $container ): PaymentsFactory { + 'api.factory.payments' => static function ( ContainerInterface $container ): PaymentsFactory { $authorizations_factory = $container->get( 'api.factory.authorization' ); $capture_factory = $container->get( 'api.factory.capture' ); $refund_factory = $container->get( 'api.factory.refund' ); return new PaymentsFactory( $authorizations_factory, $capture_factory, $refund_factory ); }, - 'api.factory.authorization' => static function ( ContainerInterface $container ): AuthorizationFactory { - return new AuthorizationFactory(); + 'api.factory.authorization' => static function ( ContainerInterface $container ): AuthorizationFactory { + return new AuthorizationFactory( $container->get( 'api.factory.fraud-processor-response' ) ); }, - 'api.factory.exchange-rate' => static function ( ContainerInterface $container ): ExchangeRateFactory { + 'api.factory.exchange-rate' => static function ( ContainerInterface $container ): ExchangeRateFactory { return new ExchangeRateFactory(); }, - 'api.factory.platform-fee' => static function ( ContainerInterface $container ): PlatformFeeFactory { + 'api.factory.platform-fee' => static function ( ContainerInterface $container ): PlatformFeeFactory { return new PlatformFeeFactory( $container->get( 'api.factory.money' ), $container->get( 'api.factory.payee' ) ); }, - 'api.factory.seller-receivable-breakdown' => static function ( ContainerInterface $container ): SellerReceivableBreakdownFactory { + 'api.factory.seller-receivable-breakdown' => static function ( ContainerInterface $container ): SellerReceivableBreakdownFactory { return new SellerReceivableBreakdownFactory( $container->get( 'api.factory.money' ), $container->get( 'api.factory.exchange-rate' ), $container->get( 'api.factory.platform-fee' ) ); }, - 'api.factory.seller-payable-breakdown' => static function ( ContainerInterface $container ): SellerPayableBreakdownFactory { + 'api.factory.seller-payable-breakdown' => static function ( ContainerInterface $container ): SellerPayableBreakdownFactory { return new SellerPayableBreakdownFactory( $container->get( 'api.factory.money' ), $container->get( 'api.factory.platform-fee' ) ); }, - 'api.factory.fraud-processor-response' => static function ( ContainerInterface $container ): FraudProcessorResponseFactory { + 'api.factory.fraud-processor-response' => static function ( ContainerInterface $container ): FraudProcessorResponseFactory { return new FraudProcessorResponseFactory(); }, - 'api.factory.product' => static function( ContainerInterface $container ): ProductFactory { + 'api.factory.product' => static function( ContainerInterface $container ): ProductFactory { return new ProductFactory(); }, - 'api.factory.billing-cycle' => static function( ContainerInterface $container ): BillingCycleFactory { + 'api.factory.billing-cycle' => static function( ContainerInterface $container ): BillingCycleFactory { return new BillingCycleFactory( $container->get( 'api.shop.currency' ) ); }, - 'api.factory.payment-preferences' => static function( ContainerInterface $container ):PaymentPreferencesFactory { + 'api.factory.payment-preferences' => static function( ContainerInterface $container ):PaymentPreferencesFactory { return new PaymentPreferencesFactory( $container->get( 'api.shop.currency' ) ); }, - 'api.factory.plan' => static function( ContainerInterface $container ): PlanFactory { + 'api.factory.plan' => static function( ContainerInterface $container ): PlanFactory { return new PlanFactory( $container->get( 'api.factory.billing-cycle' ), $container->get( 'api.factory.payment-preferences' ) ); }, - 'api.helpers.dccapplies' => static function ( ContainerInterface $container ) : DccApplies { + 'api.factory.card-authentication-result-factory' => static function( ContainerInterface $container ): CardAuthenticationResultFactory { + return new CardAuthenticationResultFactory(); + }, + 'api.helpers.dccapplies' => static function ( ContainerInterface $container ) : DccApplies { return new DccApplies( $container->get( 'api.dcc-supported-country-currency-matrix' ), $container->get( 'api.dcc-supported-country-card-matrix' ), @@ -455,7 +471,7 @@ return array( ); }, - 'api.shop.currency' => static function ( ContainerInterface $container ) : string { + 'api.shop.currency' => static function ( ContainerInterface $container ) : string { $currency = get_woocommerce_currency(); if ( $currency ) { return $currency; @@ -468,18 +484,18 @@ return array( return $currency; }, - 'api.shop.country' => static function ( ContainerInterface $container ) : string { + 'api.shop.country' => static function ( ContainerInterface $container ) : string { $location = wc_get_base_location(); return $location['country']; }, - 'api.shop.is-psd2-country' => static function ( ContainerInterface $container ) : bool { + 'api.shop.is-psd2-country' => static function ( ContainerInterface $container ) : bool { return in_array( $container->get( 'api.shop.country' ), $container->get( 'api.psd2-countries' ), true ); }, - 'api.shop.is-currency-supported' => static function ( ContainerInterface $container ) : bool { + 'api.shop.is-currency-supported' => static function ( ContainerInterface $container ) : bool { return in_array( $container->get( 'api.shop.currency' ), $container->get( 'api.supported-currencies' ), @@ -488,7 +504,7 @@ return array( }, - 'api.shop.is-latin-america' => static function ( ContainerInterface $container ): bool { + 'api.shop.is-latin-america' => static function ( ContainerInterface $container ): bool { return in_array( $container->get( 'api.shop.country' ), array( @@ -546,7 +562,7 @@ return array( * * From https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies/ */ - 'api.supported-currencies' => static function ( ContainerInterface $container ) : array { + 'api.supported-currencies' => static function ( ContainerInterface $container ) : array { return array( 'AUD', 'BRL', @@ -579,7 +595,7 @@ return array( /** * The matrix which countries and currency combinations can be used for DCC. */ - 'api.dcc-supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array { + 'api.dcc-supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array { /** * Returns which countries and currency combinations can be used for DCC. */ @@ -588,6 +604,7 @@ return array( array( 'AU' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -596,47 +613,118 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'AT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', 'USD', ), 'BE' => array( - 'EUR', - 'USD', + 'AUD', + 'BRL', 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', 'PLN', 'SEK', - 'CHF', + 'SGD', + 'THB', + 'TWD', + 'USD', ), 'BG' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CA' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', 'USD', ), 'CY' => array( - 'EUR', - 'USD', - 'CAD', - 'GBP', - 'AUD', - 'CZK', - 'DKK', - 'NOK', - 'PLN', - 'SEK', - 'CHF', - ), - 'CZ' => array( - 'EUR', - 'USD', - 'CZK', - ), - 'DE' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -645,26 +733,46 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CZ' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', 'USD', ), 'DK' => array( - 'EUR', - 'USD', - 'DKK', - 'NOK', - ), - 'EE' => array( - 'EUR', - 'USD', - ), - 'ES' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -673,20 +781,70 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'EE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', 'USD', ), 'FI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', 'USD', ), 'FR' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -695,16 +853,481 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'DE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'GR' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'HU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'IE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'IT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'JP' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LV' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'MT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'MX' => array( + 'MXN', + ), + 'NL' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'PL' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'PT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'RO' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SK' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'ES' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', 'USD', ), 'GB' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -713,68 +1336,19 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', 'USD', ), - 'GR' => array( - 'EUR', - 'USD', - 'GBP', - ), - 'HU' => array( - 'EUR', - 'USD', - 'HUF', - ), - 'IT' => array( - 'AUD', - 'CAD', - 'CHF', - 'CZK', - 'DKK', - 'EUR', - 'GBP', - 'HKD', - 'HUF', - 'JPY', - 'NOK', - 'NZD', - 'PLN', - 'SEK', - 'SGD', - 'USD', - ), - 'LT' => array( - 'EUR', - 'USD', - 'CAD', - 'GBP', - 'JPY', - 'AUD', - 'CZK', - 'DKK', - 'HUF', - 'PLN', - 'SEK', - 'CHF', - 'NZD', - 'NOK', - ), - 'LU' => array( - 'EUR', - 'USD', - ), - 'LV' => array( - 'EUR', - 'USD', - 'CAD', - 'GBP', - ), 'US' => array( 'AUD', 'CAD', @@ -783,101 +1357,9 @@ return array( 'JPY', 'USD', ), - 'CA' => array( - 'AUD', - 'CAD', - 'CHF', - 'CZK', - 'DKK', - 'EUR', - 'GBP', - 'HKD', - 'HUF', - 'JPY', - 'NOK', - 'NZD', - 'PLN', - 'SEK', - 'SGD', - 'USD', - ), - 'MT' => array( - 'EUR', - 'USD', - 'CAD', - 'GBP', - 'JPY', - 'AUD', - 'CZK', - 'DKK', - 'HUF', - 'NOK', - 'PLN', - 'SEK', - 'CHF', - ), - 'MX' => array( - 'MXN', - ), - 'NL' => array( - 'EUR', - 'GBP', - 'AUD', - 'CZK', - 'HUF', - 'CHF', - 'CAD', - 'USD', - ), 'NO' => array( - 'EUR', - 'USD', - 'CAD', - 'GBP', - 'NOK', - ), - 'PL' => array( - 'EUR', - 'USD', - 'CAD', - 'GBP', - 'AUD', - 'DKK', - 'PLN', - 'SEK', - 'CZK', - ), - 'PT' => array( - 'EUR', - 'USD', - 'CAD', - 'GBP', - 'CZK', - ), - 'RO' => array( - 'EUR', - 'USD', - 'GBP', - ), - 'SE' => array( - 'EUR', - 'USD', - 'NOK', - 'SEK', - ), - 'SI' => array( - 'EUR', - 'USD', - ), - 'SK' => array( - 'EUR', - 'USD', - 'GBP', - 'CZK', - 'HUF', - ), - 'JP' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -886,12 +1368,17 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', 'USD', ), ) @@ -901,7 +1388,7 @@ return array( /** * Which countries support which credit cards. Empty credit card arrays mean no restriction on currency. */ - 'api.dcc-supported-country-card-matrix' => static function ( ContainerInterface $container ) : array { + 'api.dcc-supported-country-card-matrix' => static function ( ContainerInterface $container ) : array { /** * Returns which countries support which credit cards. Empty credit card arrays mean no restriction on currency. */ @@ -913,35 +1400,40 @@ return array( 'visa' => array(), 'amex' => array( 'AUD' ), ), + 'AT' => array( + 'mastercard' => array(), + 'visa' => array(), + 'amex' => array(), + ), 'BE' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR', 'USD', 'CAD' ), + 'amex' => array(), ), 'BG' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'CY' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'CZ' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'CZK' ), + 'amex' => array(), ), 'DE' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'DK' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'DKK' ), + 'amex' => array(), ), 'EE' => array( 'mastercard' => array(), @@ -951,37 +1443,42 @@ return array( 'ES' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'FI' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'FR' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'GB' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'GBP', 'USD' ), + 'amex' => array(), ), 'GR' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'HU' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'HUF' ), + 'amex' => array(), + ), + 'IE' => array( + 'mastercard' => array(), + 'visa' => array(), + 'amex' => array(), ), 'IT' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'US' => array( 'mastercard' => array(), @@ -992,28 +1489,33 @@ return array( 'CA' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'CAD' ), + 'amex' => array( 'CAD', 'USD' ), 'jcb' => array( 'CAD' ), ), + 'LI' => array( + 'mastercard' => array(), + 'visa' => array(), + 'amex' => array(), + ), 'LT' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'LU' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'LV' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR', 'USD' ), + 'amex' => array(), ), 'MT' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'MX' => array( 'mastercard' => array(), @@ -1023,42 +1525,42 @@ return array( 'NL' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR', 'USD' ), + 'amex' => array(), ), 'NO' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'NOK' ), + 'amex' => array(), ), 'PL' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR', 'USD', 'GBP', 'PLN' ), + 'amex' => array(), ), 'PT' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR', 'USD', 'CAD', 'GBP' ), + 'amex' => array(), ), 'RO' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR', 'USD' ), + 'amex' => array(), ), 'SE' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR', 'SEK' ), + 'amex' => array(), ), 'SI' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR' ), + 'amex' => array(), ), 'SK' => array( 'mastercard' => array(), 'visa' => array(), - 'amex' => array( 'EUR', 'GBP' ), + 'amex' => array(), ), 'JP' => array( 'mastercard' => array(), @@ -1070,7 +1572,7 @@ return array( ); }, - 'api.psd2-countries' => static function ( ContainerInterface $container ) : array { + 'api.psd2-countries' => static function ( ContainerInterface $container ) : array { return array( 'AT', 'BE', @@ -1102,19 +1604,19 @@ return array( 'SE', ); }, - 'api.order-helper' => static function( ContainerInterface $container ): OrderHelper { + 'api.order-helper' => static function( ContainerInterface $container ): OrderHelper { return new OrderHelper(); }, - 'api.helper.order-transient' => static function( ContainerInterface $container ): OrderTransient { + 'api.helper.order-transient' => static function( ContainerInterface $container ): OrderTransient { $cache = new Cache( 'ppcp-paypal-bearer' ); $purchase_unit_sanitizer = $container->get( 'api.helper.purchase-unit-sanitizer' ); return new OrderTransient( $cache, $purchase_unit_sanitizer ); }, - 'api.helper.failure-registry' => static function( ContainerInterface $container ): FailureRegistry { + 'api.helper.failure-registry' => static function( ContainerInterface $container ): FailureRegistry { $cache = new Cache( 'ppcp-paypal-api-status-cache' ); return new FailureRegistry( $cache ); }, - 'api.helper.purchase-unit-sanitizer' => SingletonDecorator::make( + 'api.helper.purchase-unit-sanitizer' => SingletonDecorator::make( static function( ContainerInterface $container ): PurchaseUnitSanitizer { $settings = $container->get( 'wcgateway.settings' ); assert( $settings instanceof Settings ); @@ -1124,4 +1626,11 @@ return array( return new PurchaseUnitSanitizer( $behavior, $line_name ); } ), + 'api.user-id-token' => static function( ContainerInterface $container ): UserIdToken { + return new UserIdToken( + $container->get( 'api.host' ), + $container->get( 'api.bearer' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, ); diff --git a/modules/ppcp-api-client/src/Authentication/UserIdToken.php b/modules/ppcp-api-client/src/Authentication/UserIdToken.php new file mode 100644 index 000000000..cae8cb58a --- /dev/null +++ b/modules/ppcp-api-client/src/Authentication/UserIdToken.php @@ -0,0 +1,105 @@ +host = $host; + $this->bearer = $bearer; + $this->logger = $logger; + } + + /** + * Returns `id_token` which uniquely identifies the payer. + * + * @param string $target_customer_id Vaulted customer id. + * + * @return string + * + * @throws PayPalApiException If the request fails. + * @throws RuntimeException If something unexpected happens. + */ + public function id_token( string $target_customer_id = '' ): string { + $bearer = $this->bearer->bearer(); + + $url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials&response_type=id_token'; + if ( $target_customer_id ) { + $url = add_query_arg( + array( + 'target_customer_id' => $target_customer_id, + ), + $url + ); + } + + $args = array( + 'method' => 'POST', + 'headers' => array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/x-www-form-urlencoded', + ), + ); + + $response = $this->request( $url, $args ); + if ( $response instanceof WP_Error ) { + throw new RuntimeException( $response->get_error_message() ); + } + + $json = json_decode( $response['body'] ); + $status_code = (int) wp_remote_retrieve_response_code( $response ); + if ( 200 !== $status_code ) { + throw new PayPalApiException( $json, $status_code ); + } + + return $json->id_token; + } +} diff --git a/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php b/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php index abba2c182..91b45d550 100644 --- a/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php +++ b/modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php @@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; use WooCommerce\PayPalCommerce\ApiClient\Entity\PatchCollection; use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer; +use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken; use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; @@ -27,7 +28,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PatchCollectionFactory; use WooCommerce\PayPalCommerce\ApiClient\Helper\ErrorResponse; use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository; use Psr\Log\LoggerInterface; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNet; use WP_Error; @@ -174,12 +175,15 @@ class OrderEndpoint { /** * Creates an order. * - * @param PurchaseUnit[] $items The purchase unit items for the order. - * @param string $shipping_preference One of ApplicationContext::SHIPPING_PREFERENCE_ values. - * @param Payer|null $payer The payer off the order. - * @param PaymentToken|null $payment_token The payment token. - * @param string $paypal_request_id The paypal request id. - * @param string $user_action The user action. + * @param PurchaseUnit[] $items The purchase unit items for the order. + * @param string $shipping_preference One of ApplicationContext::SHIPPING_PREFERENCE_ values. + * @param Payer|null $payer The payer off the order. + * @param PaymentToken|null $payment_token The payment token. + * @param string $paypal_request_id The PayPal request id. + * @param string $user_action The user action. + * @param string $payment_method WC payment method. + * @param array $request_data Request data. + * @param PaymentSource|null $payment_source The payment source. * * @return Order * @throws RuntimeException If the request fails. @@ -190,7 +194,10 @@ class OrderEndpoint { Payer $payer = null, PaymentToken $payment_token = null, string $paypal_request_id = '', - string $user_action = ApplicationContext::USER_ACTION_CONTINUE + string $user_action = ApplicationContext::USER_ACTION_CONTINUE, + string $payment_method = '', + array $request_data = array(), + PaymentSource $payment_source = null ): Order { $bearer = $this->bearer->bearer(); $data = array( @@ -217,11 +224,16 @@ class OrderEndpoint { if ( $payment_token ) { $data['payment_source']['token'] = $payment_token->to_array(); } + if ( $payment_source ) { + $data['payment_source'] = array( + $payment_source->name() => $payment_source->properties(), + ); + } /** * The filter can be used to modify the order creation request body data. */ - $data = apply_filters( 'ppcp_create_order_request_body_data', $data ); + $data = apply_filters( 'ppcp_create_order_request_body_data', $data, $payment_method, $request_data ); $url = trailingslashit( $this->host ) . 'v2/checkout/orders'; $args = array( 'method' => 'POST', @@ -260,26 +272,25 @@ class OrderEndpoint { ); throw $error; } + $json = json_decode( $response['body'] ); $status_code = (int) wp_remote_retrieve_response_code( $response ); - if ( 201 !== $status_code ) { + if ( ! in_array( $status_code, array( 200, 201 ), true ) ) { $error = new PayPalApiException( $json, $status_code ); - $this->logger->log( - 'warning', + + $this->logger->warning( sprintf( 'Failed to create order. PayPal API response: %1$s', $error->getMessage() - ), - array( - 'args' => $args, - 'response' => $response, ) ); + throw $error; } + $order = $this->order_factory->from_paypal_response( $json ); do_action( 'woocommerce_paypal_payments_paypal_order_created', $order ); diff --git a/modules/ppcp-api-client/src/Endpoint/PaymentMethodTokensEndpoint.php b/modules/ppcp-api-client/src/Endpoint/PaymentMethodTokensEndpoint.php new file mode 100644 index 000000000..538ca224d --- /dev/null +++ b/modules/ppcp-api-client/src/Endpoint/PaymentMethodTokensEndpoint.php @@ -0,0 +1,155 @@ +host = $host; + $this->bearer = $bearer; + $this->logger = $logger; + } + + /** + * Creates a setup token. + * + * @param PaymentSource $payment_source The payment source. + * + * @return stdClass + * + * @throws RuntimeException When something when wrong with the request. + * @throws PayPalApiException When something when wrong setting up the token. + */ + public function setup_tokens( PaymentSource $payment_source ): stdClass { + $data = array( + 'payment_source' => array( + $payment_source->name() => $payment_source->properties(), + ), + ); + + $bearer = $this->bearer->bearer(); + $url = trailingslashit( $this->host ) . 'v3/vault/setup-tokens'; + + $args = array( + 'method' => 'POST', + 'headers' => array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + 'PayPal-Request-Id' => uniqid( 'ppcp-', true ), + ), + 'body' => wp_json_encode( $data ), + ); + + $response = $this->request( $url, $args ); + + if ( is_wp_error( $response ) || ! is_array( $response ) ) { + throw new RuntimeException( 'Not able to create setup token.' ); + } + + $json = json_decode( $response['body'] ); + $status_code = (int) wp_remote_retrieve_response_code( $response ); + if ( ! in_array( $status_code, array( 200, 201 ), true ) ) { + throw new PayPalApiException( + $json, + $status_code + ); + } + + return $json; + } + + /** + * Creates a payment token for the given payment source. + * + * @param PaymentSource $payment_source The payment source. + * + * @return stdClass + * + * @throws RuntimeException When something when wrong with the request. + * @throws PayPalApiException When something when wrong setting up the token. + */ + public function create_payment_token( PaymentSource $payment_source ): stdClass { + $data = array( + 'payment_source' => array( + $payment_source->name() => $payment_source->properties(), + ), + ); + + $bearer = $this->bearer->bearer(); + $url = trailingslashit( $this->host ) . 'v3/vault/payment-tokens'; + + $args = array( + 'method' => 'POST', + 'headers' => array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + 'PayPal-Request-Id' => uniqid( 'ppcp-', true ), + ), + 'body' => wp_json_encode( $data ), + ); + + $response = $this->request( $url, $args ); + + if ( is_wp_error( $response ) || ! is_array( $response ) ) { + throw new RuntimeException( 'Not able to create setup token.' ); + } + + $json = json_decode( $response['body'] ); + $status_code = (int) wp_remote_retrieve_response_code( $response ); + if ( ! in_array( $status_code, array( 200, 201 ), true ) ) { + throw new PayPalApiException( + $json, + $status_code + ); + } + + return $json; + } +} diff --git a/modules/ppcp-api-client/src/Endpoint/PaymentTokensEndpoint.php b/modules/ppcp-api-client/src/Endpoint/PaymentTokensEndpoint.php new file mode 100644 index 000000000..284bc887f --- /dev/null +++ b/modules/ppcp-api-client/src/Endpoint/PaymentTokensEndpoint.php @@ -0,0 +1,145 @@ +host = $host; + $this->bearer = $bearer; + $this->logger = $logger; + } + + /** + * Deletes a payment token with the given id. + * + * @param string $id Payment token id. + * + * @return void + * + * @throws RuntimeException When something went wrong with the request. + * @throws PayPalApiException When something went wrong deleting the payment token. + */ + public function delete( string $id ): void { + $bearer = $this->bearer->bearer(); + $url = trailingslashit( $this->host ) . 'v3/vault/payment-tokens/' . $id; + $args = array( + 'method' => 'DELETE', + 'headers' => array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + ), + ); + + $response = $this->request( $url, $args ); + if ( $response instanceof WP_Error ) { + throw new RuntimeException( $response->get_error_message() ); + } + + $json = json_decode( $response['body'] ); + $status_code = (int) wp_remote_retrieve_response_code( $response ); + if ( 204 !== $status_code ) { + throw new PayPalApiException( $json, $status_code ); + } + } + + /** + * Returns all payment tokens for the given customer. + * + * @param string $customer_id PayPal customer id. + * @return array + * + * @throws RuntimeException When something went wrong with the request. + * @throws PayPalApiException When something went wrong getting the payment tokens. + */ + public function payment_tokens_for_customer( string $customer_id ): array { + $bearer = $this->bearer->bearer(); + $url = trailingslashit( $this->host ) . 'v3/vault/payment-tokens?customer_id=' . $customer_id; + $args = array( + 'method' => 'GET', + 'headers' => array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + ), + ); + + $response = $this->request( $url, $args ); + if ( $response instanceof WP_Error ) { + throw new RuntimeException( $response->get_error_message() ); + } + + $json = json_decode( $response['body'] ); + $status_code = (int) wp_remote_retrieve_response_code( $response ); + if ( 200 !== $status_code ) { + throw new PayPalApiException( $json, $status_code ); + } + + $tokens = array(); + $payment_tokens = $json->payment_tokens ?? array(); + foreach ( $payment_tokens as $payment_token ) { + $name = array_key_first( (array) $payment_token->payment_source ) ?? ''; + if ( $name ) { + $tokens[] = array( + 'id' => $payment_token->id, + 'payment_source' => new PaymentSource( + $name, + $payment_token->payment_source->$name + ), + ); + } + } + + return $tokens; + } +} diff --git a/modules/ppcp-api-client/src/Endpoint/PaymentsEndpoint.php b/modules/ppcp-api-client/src/Endpoint/PaymentsEndpoint.php index 210beae16..484b89a94 100644 --- a/modules/ppcp-api-client/src/Endpoint/PaymentsEndpoint.php +++ b/modules/ppcp-api-client/src/Endpoint/PaymentsEndpoint.php @@ -193,6 +193,53 @@ class PaymentsEndpoint { return $this->capture_factory->from_paypal_response( $json ); } + /** + * Reauthorizes an order. + * + * @param string $authorization_id The id. + * @param Money|null $amount The amount to capture. If not specified, the whole authorized amount is captured. + * + * @return string + * @throws RuntimeException If the request fails. + * @throws PayPalApiException If the request fails. + */ + public function reauthorize( string $authorization_id, ?Money $amount = null ) : string { + $bearer = $this->bearer->bearer(); + $url = trailingslashit( $this->host ) . 'v2/payments/authorizations/' . $authorization_id . '/reauthorize'; + + $data = array(); + if ( $amount ) { + $data['amount'] = $amount->to_array(); + } + + $args = array( + 'method' => 'POST', + 'headers' => array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + 'Prefer' => 'return=representation', + ), + 'body' => wp_json_encode( $data, JSON_FORCE_OBJECT ), + ); + + $response = $this->request( $url, $args ); + $json = json_decode( $response['body'] ); + + if ( is_wp_error( $response ) ) { + throw new RuntimeException( 'Could not reauthorize authorized payment.' ); + } + + $status_code = (int) wp_remote_retrieve_response_code( $response ); + if ( 201 !== $status_code || ! is_object( $json ) ) { + throw new PayPalApiException( + $json, + $status_code + ); + } + + return $json->id; + } + /** * Refunds a payment. * diff --git a/modules/ppcp-api-client/src/Entity/Authorization.php b/modules/ppcp-api-client/src/Entity/Authorization.php index ae8e8f591..007e12475 100644 --- a/modules/ppcp-api-client/src/Entity/Authorization.php +++ b/modules/ppcp-api-client/src/Entity/Authorization.php @@ -28,19 +28,29 @@ class Authorization { */ private $authorization_status; + /** + * The fraud processor response (AVS, CVV ...). + * + * @var FraudProcessorResponse|null + */ + protected $fraud_processor_response; + /** * Authorization constructor. * - * @param string $id The id. - * @param AuthorizationStatus $authorization_status The status. + * @param string $id The id. + * @param AuthorizationStatus $authorization_status The status. + * @param FraudProcessorResponse|null $fraud_processor_response The fraud processor response (AVS, CVV ...). */ public function __construct( string $id, - AuthorizationStatus $authorization_status + AuthorizationStatus $authorization_status, + ?FraudProcessorResponse $fraud_processor_response ) { - $this->id = $id; - $this->authorization_status = $authorization_status; + $this->id = $id; + $this->authorization_status = $authorization_status; + $this->fraud_processor_response = $fraud_processor_response; } /** @@ -71,15 +81,30 @@ class Authorization { $this->authorization_status->is( AuthorizationStatus::PENDING ); } + /** + * Returns the fraud processor response (AVS, CVV ...). + * + * @return FraudProcessorResponse|null + */ + public function fraud_processor_response() : ?FraudProcessorResponse { + return $this->fraud_processor_response; + } + /** * Returns the object as array. * * @return array */ public function to_array(): array { - return array( + $data = array( 'id' => $this->id, 'status' => $this->authorization_status->name(), ); + + if ( $this->fraud_processor_response ) { + $data['fraud_processor_response'] = $this->fraud_processor_response->to_array(); + } + + return $data; } } diff --git a/modules/ppcp-api-client/src/Entity/CardAuthenticationResult.php b/modules/ppcp-api-client/src/Entity/CardAuthenticationResult.php index 7eedf7d56..e4d969c5f 100644 --- a/modules/ppcp-api-client/src/Entity/CardAuthenticationResult.php +++ b/modules/ppcp-api-client/src/Entity/CardAuthenticationResult.php @@ -14,7 +14,6 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Entity; */ class CardAuthenticationResult { - const LIABILITY_SHIFT_POSSIBLE = 'POSSIBLE'; const LIABILITY_SHIFT_NO = 'NO'; const LIABILITY_SHIFT_UNKNOWN = 'UNKNOWN'; diff --git a/modules/ppcp-api-client/src/Entity/Order.php b/modules/ppcp-api-client/src/Entity/Order.php index 67eb982a3..d40e7a4e6 100644 --- a/modules/ppcp-api-client/src/Entity/Order.php +++ b/modules/ppcp-api-client/src/Entity/Order.php @@ -107,14 +107,6 @@ class Order { $this->id = $id; $this->application_context = $application_context; - $this->purchase_units = array_values( - array_filter( - $purchase_units, - static function ( $unit ): bool { - return is_a( $unit, PurchaseUnit::class ); - } - ) - ); $this->payer = $payer; $this->order_status = $order_status; $this->intent = ( 'CAPTURE' === $intent ) ? 'CAPTURE' : 'AUTHORIZE'; @@ -236,9 +228,6 @@ class Order { if ( $this->application_context() ) { $order['application_context'] = $this->application_context()->to_array(); } - if ( $this->payment_source() ) { - $order['payment_source'] = $this->payment_source()->to_array(); - } return $order; } diff --git a/modules/ppcp-api-client/src/Entity/OrderStatus.php b/modules/ppcp-api-client/src/Entity/OrderStatus.php index e2dec053b..387830dd3 100644 --- a/modules/ppcp-api-client/src/Entity/OrderStatus.php +++ b/modules/ppcp-api-client/src/Entity/OrderStatus.php @@ -15,14 +15,15 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; * Class OrderStatus */ class OrderStatus { - const INTERNAL = 'INTERNAL'; - const CREATED = 'CREATED'; - const SAVED = 'SAVED'; - const APPROVED = 'APPROVED'; - const VOIDED = 'VOIDED'; - const COMPLETED = 'COMPLETED'; - const PENDING_APPROVAL = 'PENDING_APPROVAL'; - const VALID_STATUS = array( + const INTERNAL = 'INTERNAL'; + const CREATED = 'CREATED'; + const SAVED = 'SAVED'; + const APPROVED = 'APPROVED'; + const VOIDED = 'VOIDED'; + const COMPLETED = 'COMPLETED'; + const PENDING_APPROVAL = 'PENDING_APPROVAL'; + const PAYER_ACTION_REQUIRED = 'PAYER_ACTION_REQUIRED'; + const VALID_STATUS = array( self::INTERNAL, self::CREATED, self::SAVED, @@ -30,6 +31,7 @@ class OrderStatus { self::VOIDED, self::COMPLETED, self::PENDING_APPROVAL, + self::PAYER_ACTION_REQUIRED, ); /** diff --git a/modules/ppcp-api-client/src/Entity/PaymentSource.php b/modules/ppcp-api-client/src/Entity/PaymentSource.php index dcac61108..d3f1a8cc7 100644 --- a/modules/ppcp-api-client/src/Entity/PaymentSource.php +++ b/modules/ppcp-api-client/src/Entity/PaymentSource.php @@ -9,74 +9,53 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\ApiClient\Entity; +use stdClass; + /** * Class PaymentSource */ class PaymentSource { /** - * The card. + * Payment source name. * - * @var PaymentSourceCard|null + * @var string */ - private $card; + private $name; /** - * The wallet. + * Payment source properties. * - * @var PaymentSourceWallet|null + * @var object */ - private $wallet; + private $properties; /** * PaymentSource constructor. * - * @param PaymentSourceCard|null $card The card. - * @param PaymentSourceWallet|null $wallet The wallet. + * @param string $name Payment source name. + * @param object $properties Payment source properties. */ - public function __construct( - PaymentSourceCard $card = null, - PaymentSourceWallet $wallet = null - ) { - - $this->card = $card; - $this->wallet = $wallet; + public function __construct( string $name, object $properties ) { + $this->name = $name; + $this->properties = $properties; } /** - * Returns the card. + * Payment source name. * - * @return PaymentSourceCard|null + * @return string */ - public function card() { - - return $this->card; + public function name(): string { + return $this->name; } /** - * Returns the wallet. + * Payment source properties. * - * @return PaymentSourceWallet|null + * @return object */ - public function wallet() { - - return $this->wallet; - } - - /** - * Returns the array of the object. - * - * @return array - */ - public function to_array(): array { - - $data = array(); - if ( $this->card() ) { - $data['card'] = $this->card()->to_array(); - } - if ( $this->wallet() ) { - $data['wallet'] = $this->wallet()->to_array(); - } - return $data; + public function properties(): object { + return $this->properties; } } diff --git a/modules/ppcp-api-client/src/Entity/PaymentSourceCard.php b/modules/ppcp-api-client/src/Entity/PaymentSourceCard.php deleted file mode 100644 index 1edc7eb37..000000000 --- a/modules/ppcp-api-client/src/Entity/PaymentSourceCard.php +++ /dev/null @@ -1,123 +0,0 @@ -last_digits = $last_digits; - $this->brand = $brand; - $this->type = $type; - $this->authentication_result = $authentication_result; - } - - /** - * Returns the last digits. - * - * @return string - */ - public function last_digits(): string { - - return $this->last_digits; - } - - /** - * Returns the brand. - * - * @return string - */ - public function brand(): string { - - return $this->brand; - } - - /** - * Returns the type. - * - * @return string - */ - public function type(): string { - - return $this->type; - } - - /** - * Returns the authentication result. - * - * @return CardAuthenticationResult|null - */ - public function authentication_result() { - - return $this->authentication_result; - } - - /** - * Returns the object as array. - * - * @return array - */ - public function to_array(): array { - - $data = array( - 'last_digits' => $this->last_digits(), - 'brand' => $this->brand(), - 'type' => $this->type(), - ); - if ( $this->authentication_result() ) { - $data['authentication_result'] = $this->authentication_result()->to_array(); - } - return $data; - } -} diff --git a/modules/ppcp-api-client/src/Entity/PaymentSourceWallet.php b/modules/ppcp-api-client/src/Entity/PaymentSourceWallet.php deleted file mode 100644 index 18a5a7742..000000000 --- a/modules/ppcp-api-client/src/Entity/PaymentSourceWallet.php +++ /dev/null @@ -1,25 +0,0 @@ - $product ) { if ( is_a( $product, SellerStatusProduct::class ) ) { continue; } unset( $products[ $key ] ); } - $this->products = $products; + foreach ( $capabilities as $key => $capability ) { + if ( is_a( $capability, SellerStatusCapability::class ) ) { + continue; + } + unset( $capabilities[ $key ] ); + } + + $this->products = $products; + $this->capabilities = $capabilities; } /** @@ -45,6 +63,15 @@ class SellerStatus { return $this->products; } + /** + * Returns the capabilities. + * + * @return SellerStatusCapability[] + */ + public function capabilities() : array { + return $this->capabilities; + } + /** * Returns the enitity as array. * @@ -58,8 +85,16 @@ class SellerStatus { $this->products() ); + $capabilities = array_map( + function( SellerStatusCapability $capability ) : array { + return $capability->to_array(); + }, + $this->capabilities() + ); + return array( - 'products' => $products, + 'products' => $products, + 'capabilities' => $capabilities, ); } } diff --git a/modules/ppcp-api-client/src/Entity/SellerStatusCapability.php b/modules/ppcp-api-client/src/Entity/SellerStatusCapability.php new file mode 100644 index 000000000..7fdb7df04 --- /dev/null +++ b/modules/ppcp-api-client/src/Entity/SellerStatusCapability.php @@ -0,0 +1,77 @@ +name = $name; + $this->status = $status; + } + + /** + * Returns the name of the product. + * + * @return string + */ + public function name() : string { + return $this->name; + } + + /** + * Returns the status for this capability. + * + * @return string + */ + public function status() : string { + return $this->status; + } + + /** + * Returns the entity as array. + * + * @return array + */ + public function to_array() : array { + return array( + 'name' => $this->name(), + 'status' => $this->status(), + ); + } + +} diff --git a/modules/ppcp-api-client/src/Factory/AmountFactory.php b/modules/ppcp-api-client/src/Factory/AmountFactory.php index 51a6d8c11..236fff360 100644 --- a/modules/ppcp-api-client/src/Factory/AmountFactory.php +++ b/modules/ppcp-api-client/src/Factory/AmountFactory.php @@ -14,7 +14,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\AmountBreakdown; use WooCommerce\PayPalCommerce\ApiClient\Entity\Item; use WooCommerce\PayPalCommerce\ApiClient\Entity\Money; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; -use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; diff --git a/modules/ppcp-api-client/src/Factory/AuthorizationFactory.php b/modules/ppcp-api-client/src/Factory/AuthorizationFactory.php index c65e764af..d16aee2fb 100644 --- a/modules/ppcp-api-client/src/Factory/AuthorizationFactory.php +++ b/modules/ppcp-api-client/src/Factory/AuthorizationFactory.php @@ -19,6 +19,22 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; */ class AuthorizationFactory { + /** + * The FraudProcessorResponseFactory factory. + * + * @var FraudProcessorResponseFactory + */ + protected $fraud_processor_response_factory; + + /** + * AuthorizationFactory constructor. + * + * @param FraudProcessorResponseFactory $fraud_processor_response_factory The FraudProcessorResponseFactory factory. + */ + public function __construct( FraudProcessorResponseFactory $fraud_processor_response_factory ) { + $this->fraud_processor_response_factory = $fraud_processor_response_factory; + } + /** * Returns an Authorization based off a PayPal response. * @@ -42,12 +58,17 @@ class AuthorizationFactory { $reason = $data->status_details->reason ?? null; + $fraud_processor_response = isset( $data->processor_response ) ? + $this->fraud_processor_response_factory->from_paypal_response( $data->processor_response ) + : null; + return new Authorization( $data->id, new AuthorizationStatus( $data->status, $reason ? new AuthorizationStatusDetails( $reason ) : null - ) + ), + $fraud_processor_response ); } } diff --git a/modules/ppcp-api-client/src/Factory/CardAuthenticationResultFactory.php b/modules/ppcp-api-client/src/Factory/CardAuthenticationResultFactory.php new file mode 100644 index 000000000..33e0fe562 --- /dev/null +++ b/modules/ppcp-api-client/src/Factory/CardAuthenticationResultFactory.php @@ -0,0 +1,33 @@ +liability_shift ?? '', + $authentication_result->three_d_secure->enrollment_status ?? '', + $authentication_result->three_d_secure->authentication_status ?? '' + ); + } +} diff --git a/modules/ppcp-api-client/src/Factory/FraudProcessorResponseFactory.php b/modules/ppcp-api-client/src/Factory/FraudProcessorResponseFactory.php index e48d7fd3e..2a2e0b68c 100644 --- a/modules/ppcp-api-client/src/Factory/FraudProcessorResponseFactory.php +++ b/modules/ppcp-api-client/src/Factory/FraudProcessorResponseFactory.php @@ -25,8 +25,8 @@ class FraudProcessorResponseFactory { * @return FraudProcessorResponse */ public function from_paypal_response( stdClass $data ): FraudProcessorResponse { - $avs_code = $data->avs_code ?: null; - $cvv_code = $data->cvv_code ?: null; + $avs_code = ( $data->avs_code ?? null ) ?: null; + $cvv_code = ( $data->cvv_code ?? null ) ?: null; return new FraudProcessorResponse( $avs_code, $cvv_code ); } diff --git a/modules/ppcp-api-client/src/Factory/ItemFactory.php b/modules/ppcp-api-client/src/Factory/ItemFactory.php index ff44e6014..c2b14d0e1 100644 --- a/modules/ppcp-api-client/src/Factory/ItemFactory.php +++ b/modules/ppcp-api-client/src/Factory/ItemFactory.php @@ -61,12 +61,12 @@ class ItemFactory { $price = (float) $item['line_subtotal'] / (float) $item['quantity']; return new Item( - mb_substr( $product->get_name(), 0, 127 ), + $this->prepare_item_string( $product->get_name() ), new Money( $price, $this->currency ), $quantity, - $this->prepare_description( $product->get_description() ), + $this->prepare_item_string( $product->get_description() ), null, - $product->get_sku(), + $this->prepare_sku( $product->get_sku() ), ( $product->is_virtual() ) ? Item::DIGITAL_GOODS : Item::PHYSICAL_GOODS, $product->get_permalink(), $image[0] ?? '', @@ -138,12 +138,12 @@ class ItemFactory { $image = $product instanceof WC_Product ? wp_get_attachment_image_src( (int) $product->get_image_id(), 'full' ) : ''; return new Item( - mb_substr( $item->get_name(), 0, 127 ), + $this->prepare_item_string( $item->get_name() ), new Money( $price_without_tax_rounded, $currency ), $quantity, - $product instanceof WC_Product ? $this->prepare_description( $product->get_description() ) : '', + $product instanceof WC_Product ? $this->prepare_item_string( $product->get_description() ) : '', null, - $product instanceof WC_Product ? $product->get_sku() : '', + $product instanceof WC_Product ? $this->prepare_sku( $product->get_sku() ) : '', ( $product instanceof WC_Product && $product->is_virtual() ) ? Item::DIGITAL_GOODS : Item::PHYSICAL_GOODS, $product instanceof WC_Product ? $product->get_permalink() : '', $image[0] ?? '' @@ -160,7 +160,7 @@ class ItemFactory { */ private function from_wc_order_fee( \WC_Order_Item_Fee $item, \WC_Order $order ): Item { return new Item( - $item->get_name(), + $this->prepare_item_string( $item->get_name() ), new Money( (float) $item->get_amount(), $order->get_currency() ), $item->get_quantity(), '', diff --git a/modules/ppcp-api-client/src/Factory/OrderFactory.php b/modules/ppcp-api-client/src/Factory/OrderFactory.php index 7a7f057db..0b8876594 100644 --- a/modules/ppcp-api-client/src/Factory/OrderFactory.php +++ b/modules/ppcp-api-client/src/Factory/OrderFactory.php @@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Factory; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; +use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource; use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository; @@ -48,13 +49,6 @@ class OrderFactory { */ private $application_context_factory; - /** - * The PaymentSource factory. - * - * @var PaymentSourceFactory - */ - private $payment_source_factory; - /** * OrderFactory constructor. * @@ -62,21 +56,18 @@ class OrderFactory { * @param PayerFactory $payer_factory The Payer factory. * @param ApplicationContextRepository $application_context_repository The Application Context repository. * @param ApplicationContextFactory $application_context_factory The Application Context factory. - * @param PaymentSourceFactory $payment_source_factory The Payment Source factory. */ public function __construct( PurchaseUnitFactory $purchase_unit_factory, PayerFactory $payer_factory, ApplicationContextRepository $application_context_repository, - ApplicationContextFactory $application_context_factory, - PaymentSourceFactory $payment_source_factory + ApplicationContextFactory $application_context_factory ) { $this->purchase_unit_factory = $purchase_unit_factory; $this->payer_factory = $payer_factory; $this->application_context_repository = $application_context_repository; $this->application_context_factory = $application_context_factory; - $this->payment_source_factory = $payment_source_factory; } /** @@ -152,9 +143,23 @@ class OrderFactory { $application_context = ( isset( $order_data->application_context ) ) ? $this->application_context_factory->from_paypal_response( $order_data->application_context ) : null; - $payment_source = ( isset( $order_data->payment_source ) ) ? - $this->payment_source_factory->from_paypal_response( $order_data->payment_source ) : - null; + + $payment_source = null; + if ( isset( $order_data->payment_source ) ) { + $json_encoded_payment_source = wp_json_encode( $order_data->payment_source ); + if ( $json_encoded_payment_source ) { + $payment_source_as_array = json_decode( $json_encoded_payment_source, true ); + if ( $payment_source_as_array ) { + $name = array_key_first( $payment_source_as_array ); + if ( $name ) { + $payment_source = new PaymentSource( + $name, + $order_data->payment_source->$name + ); + } + } + } + } return new Order( $order_data->id, diff --git a/modules/ppcp-api-client/src/Factory/PaymentSourceFactory.php b/modules/ppcp-api-client/src/Factory/PaymentSourceFactory.php deleted file mode 100644 index b4efffb0e..000000000 --- a/modules/ppcp-api-client/src/Factory/PaymentSourceFactory.php +++ /dev/null @@ -1,53 +0,0 @@ -card ) ) { - $authentication_result = null; - if ( isset( $data->card->authentication_result ) ) { - $authentication_result = new CardAuthenticationResult( - isset( $data->card->authentication_result->liability_shift ) ? - (string) $data->card->authentication_result->liability_shift : '', - isset( $data->card->authentication_result->three_d_secure->enrollment_status ) ? - (string) $data->card->authentication_result->three_d_secure->enrollment_status : '', - isset( $data->card->authentication_result->three_d_secure->authentication_status ) ? - (string) $data->card->authentication_result->three_d_secure->authentication_status : '' - ); - } - $card = new PaymentSourceCard( - isset( $data->card->last_digits ) ? (string) $data->card->last_digits : '', - isset( $data->card->brand ) ? (string) $data->card->brand : '', - isset( $data->card->type ) ? (string) $data->card->type : '', - $authentication_result - ); - } - return new PaymentSource( $card, $wallet ); - } -} diff --git a/modules/ppcp-api-client/src/Factory/SellerStatusFactory.php b/modules/ppcp-api-client/src/Factory/SellerStatusFactory.php index 8b723a60f..9f1ff31f4 100644 --- a/modules/ppcp-api-client/src/Factory/SellerStatusFactory.php +++ b/modules/ppcp-api-client/src/Factory/SellerStatusFactory.php @@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Factory; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatus; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct; +use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusCapability; /** * Class SellerStatusFactory @@ -37,6 +38,17 @@ class SellerStatusFactory { isset( $json->products ) ? (array) $json->products : array() ); - return new SellerStatus( $products ); + $capabilities = array_map( + function( $json ) : SellerStatusCapability { + $capability = new SellerStatusCapability( + isset( $json->name ) ? (string) $json->name : '', + isset( $json->status ) ? (string) $json->status : '' + ); + return $capability; + }, + isset( $json->capabilities ) ? (array) $json->capabilities : array() + ); + + return new SellerStatus( $products, $capabilities ); } } diff --git a/modules/ppcp-api-client/src/Helper/ItemTrait.php b/modules/ppcp-api-client/src/Helper/ItemTrait.php index 09f687328..289889290 100644 --- a/modules/ppcp-api-client/src/Helper/ItemTrait.php +++ b/modules/ppcp-api-client/src/Helper/ItemTrait.php @@ -12,13 +12,23 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Helper; trait ItemTrait { /** - * Cleanups the description and prepares it for sending to PayPal. + * Cleans up item strings (title and description for example) and prepares them for sending to PayPal. * - * @param string $description Item description. + * @param string $string Item string. * @return string */ - protected function prepare_description( string $description ): string { - $description = strip_shortcodes( wp_strip_all_tags( $description ) ); - return substr( $description, 0, 127 ) ?: ''; + protected function prepare_item_string( string $string ): string { + $string = strip_shortcodes( wp_strip_all_tags( $string ) ); + return substr( $string, 0, 127 ) ?: ''; + } + + /** + * Prepares the sku for sending to PayPal. + * + * @param string $sku Item sku. + * @return string + */ + protected function prepare_sku( string $sku ): string { + return substr( wp_strip_all_tags( $sku ), 0, 127 ) ?: ''; } } diff --git a/modules/ppcp-api-client/src/Repository/ApplicationContextRepository.php b/modules/ppcp-api-client/src/Repository/ApplicationContextRepository.php index 244b955a0..8a10aca9d 100644 --- a/modules/ppcp-api-client/src/Repository/ApplicationContextRepository.php +++ b/modules/ppcp-api-client/src/Repository/ApplicationContextRepository.php @@ -54,7 +54,7 @@ class ApplicationContextRepository { $payment_preference = $this->settings->has( 'payee_preferred' ) && $this->settings->get( 'payee_preferred' ) ? ApplicationContext::PAYMENT_METHOD_IMMEDIATE_PAYMENT_REQUIRED : ApplicationContext::PAYMENT_METHOD_UNRESTRICTED; $context = new ApplicationContext( - network_home_url( \WC_AJAX::get_endpoint( ReturnUrlEndpoint::ENDPOINT ) ), + home_url( \WC_AJAX::get_endpoint( ReturnUrlEndpoint::ENDPOINT ) ), (string) wc_get_checkout_url(), (string) $brand_name, $locale, diff --git a/modules/ppcp-applepay/extensions.php b/modules/ppcp-applepay/extensions.php index 694a7b8a9..302095e3a 100644 --- a/modules/ppcp-applepay/extensions.php +++ b/modules/ppcp-applepay/extensions.php @@ -49,7 +49,9 @@ return array( // Domain validation. $domain_validation_text = __( 'Status: Domain validation failed ❌', 'woocommerce-paypal-payments' ); - if ( $container->get( 'applepay.is_validated' ) ) { + if ( ! $container->get( 'applepay.has_validated' ) ) { + $domain_validation_text = __( 'The domain has not yet been validated. Use the Apple Pay button to validate the domain ❌', 'woocommerce-paypal-payments' ); + } elseif ( $container->get( 'applepay.is_validated' ) ) { $domain_validation_text = __( 'Status: Domain successfully validated ✔️', 'woocommerce-paypal-payments' ); } @@ -69,7 +71,7 @@ return array( // Connection tab fields. $fields = $insert_after( $fields, - 'ppcp_dcc_status', + 'ppcp_reference_transactions_status', array( 'applepay_status' => array( 'title' => __( 'Apple Pay Payments', 'woocommerce-paypal-payments' ), @@ -157,6 +159,7 @@ return array( ->action_visible( 'applepay_button_color' ) ->action_visible( 'applepay_button_type' ) ->action_visible( 'applepay_button_language' ) + ->action_visible( 'applepay_checkout_data_mode' ) ->to_array(), ) ), diff --git a/modules/ppcp-applepay/resources/css/styles.scss b/modules/ppcp-applepay/resources/css/styles.scss index 215a7888e..858094433 100644 --- a/modules/ppcp-applepay/resources/css/styles.scss +++ b/modules/ppcp-applepay/resources/css/styles.scss @@ -1,58 +1,44 @@ -#applepay-container, .ppcp-button-applepay { +.ppcp-button-applepay { + // Should replicate apm-button.scss sizes. --apple-pay-button-height: 45px; - --apple-pay-button-min-height: 40px; + --apple-pay-button-min-height: 35px; --apple-pay-button-width: 100%; --apple-pay-button-max-width: 750px; --apple-pay-button-border-radius: 4px; --apple-pay-button-overflow: hidden; - margin:7px 0; + + .ppcp-width-min & { + --apple-pay-button-height: 35px; + } + .ppcp-width-300 & { + --apple-pay-button-height: 45px; + } + .ppcp-width-500 & { + --apple-pay-button-height: 55px; + } + &.ppcp-button-pill { --apple-pay-button-border-radius: 50px; } &.ppcp-button-minicart { --apple-pay-button-display: block; - --apple-pay-button-height: 40px; } } -.woocommerce-checkout { - #applepay-container, .ppcp-button-applepay { - margin-top: 0; - --apple-pay-button-border-radius: 4px; - --apple-pay-button-height: 45px; - &.ppcp-button-pill { - --apple-pay-button-border-radius: 50px; - } - } -} +.wp-block-woocommerce-checkout, .wp-block-woocommerce-cart { + .ppcp-button-applepay { + --apple-pay-button-margin: 0; -.ppcp-has-applepay-block { - - .wp-block-woocommerce-checkout { - #applepay-container, .ppcp-button-applepay { - margin: 0; - --apple-pay-button-margin: 0; - --apple-pay-button-height: 48px; - &.ppcp-button-pill { - --apple-pay-button-border-radius: 50px; - } - } - } - - .wp-block-woocommerce-cart { - #applepay-container, .ppcp-button-applepay { - margin: 0; - --apple-pay-button-margin: 0; - --apple-pay-button-height: 48px; + apple-pay-button { + min-width: 0; + width: 100%; + --apple-pay-button-width-default: 100%; } } } .wp-admin { - .ppcp-button-applepay { - pointer-events: none; - } &.ppcp-non-ios-device { .ppcp-button-applepay { apple-pay-button { diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index c6e05cf35..3526a0f03 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -5,10 +5,13 @@ import {setEnabled} from '../../../ppcp-button/resources/js/modules/Helper/Butto import FormValidator from "../../../ppcp-button/resources/js/modules/Helper/FormValidator"; import ErrorHandler from '../../../ppcp-button/resources/js/modules/ErrorHandler'; import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder"; +import {apmButtonsInit} from "../../../ppcp-button/resources/js/modules/Helper/ApmButtons"; class ApplepayButton { constructor(context, externalHandler, buttonConfig, ppcpConfig) { + apmButtonsInit(ppcpConfig); + this.isInitialized = false; this.context = context; @@ -31,6 +34,9 @@ class ApplepayButton { // Stores initialization data sent to the button. this.initialPaymentRequest = null; + // Default eligibility status. + this.isEligible = true; + this.log = function() { if ( this.buttonConfig.is_debug ) { console.log('[ApplePayButton]', ...arguments); @@ -60,14 +66,10 @@ class ApplepayButton { this.initEventHandlers(); this.isInitialized = true; this.applePayConfig = config; - const isEligible = this.applePayConfig.isEligible; + this.isEligible = (this.applePayConfig.isEligible && window.ApplePaySession) || this.buttonConfig.is_admin; - if (isEligible) { + if (this.isEligible) { this.fetchTransactionInfo().then(() => { - const isSubscriptionProduct = this.ppcpConfig?.data_client_id?.has_subscriptions === true; - if (isSubscriptionProduct) { - return; - } this.addButton(); const id_minicart = "#apple-" + this.buttonConfig.button.mini_cart_wrapper; const id = "#apple-" + this.buttonConfig.button.wrapper; @@ -84,6 +86,10 @@ class ApplepayButton { }); } }); + } else { + jQuery('#' + this.buttonConfig.button.wrapper).hide(); + jQuery('#' + this.buttonConfig.button.mini_cart_wrapper).hide(); + jQuery('#express-payment-method-ppcp-applepay').hide(); } } @@ -130,6 +136,10 @@ class ApplepayButton { const wrapper_id = '#' + wrapper; const syncButtonVisibility = () => { + if (!this.isEligible) { + return; + } + const $ppcpButtonWrapper = jQuery(ppcpButtonWrapper); setVisible(wrapper_id, $ppcpButtonWrapper.is(':visible')); setEnabled(wrapper_id, !$ppcpButtonWrapper.hasClass('ppcp-disabled')); @@ -179,13 +189,13 @@ class ApplepayButton { appleContainer.innerHTML = ``; } - jQuery('#' + wrapper).addClass('ppcp-button-' + ppcpStyle.shape); + const $wrapper = jQuery('#' + wrapper); + $wrapper.addClass('ppcp-button-' + ppcpStyle.shape); if (ppcpStyle.height) { - jQuery('#' + wrapper).css('--apple-pay-button-height', `${ppcpStyle.height}px`) + $wrapper.css('--apple-pay-button-height', `${ppcpStyle.height}px`) + $wrapper.css('height', `${ppcpStyle.height}px`) } - - jQuery(wrapper).append(appleContainer); } //------------------------ @@ -200,6 +210,8 @@ class ApplepayButton { const paymentRequest = this.paymentRequest(); + window.ppcpFundingSource = 'apple_pay'; // Do this on another place like on create order endpoint handler. + // Trigger woocommerce validation if we are in the checkout page. if (this.context === 'checkout') { const checkoutFormSelector = 'form.woocommerce-checkout'; diff --git a/modules/ppcp-applepay/resources/js/Context/BaseHandler.js b/modules/ppcp-applepay/resources/js/Context/BaseHandler.js index 61d614ab9..69745082e 100644 --- a/modules/ppcp-applepay/resources/js/Context/BaseHandler.js +++ b/modules/ppcp-applepay/resources/js/Context/BaseHandler.js @@ -1,6 +1,7 @@ import ErrorHandler from "../../../../ppcp-button/resources/js/modules/ErrorHandler"; import CartActionHandler from "../../../../ppcp-button/resources/js/modules/ActionHandler/CartActionHandler"; +import {isPayPalSubscription} from "../../../../ppcp-blocks/resources/js/Helper/Subscription"; class BaseHandler { @@ -9,9 +10,15 @@ class BaseHandler { this.ppcpConfig = ppcpConfig; } + isVaultV3Mode() { + return this.ppcpConfig?.save_payment_methods?.id_token // vault v3 + && ! this.ppcpConfig?.data_client_id?.paypal_subscriptions_enabled // not PayPal Subscriptions mode + && this.ppcpConfig?.can_save_vault_token; // vault is enabled + } + validateContext() { if ( this.ppcpConfig?.locations_with_subscription_product?.cart ) { - return false; + return this.isVaultV3Mode(); } return true; } diff --git a/modules/ppcp-applepay/resources/js/Context/PayNowHandler.js b/modules/ppcp-applepay/resources/js/Context/PayNowHandler.js index a580c4084..a12fd3636 100644 --- a/modules/ppcp-applepay/resources/js/Context/PayNowHandler.js +++ b/modules/ppcp-applepay/resources/js/Context/PayNowHandler.js @@ -7,7 +7,7 @@ class PayNowHandler extends BaseHandler { validateContext() { if ( this.ppcpConfig?.locations_with_subscription_product?.payorder ) { - return false; + return this.isVaultV3Mode(); } return true; } diff --git a/modules/ppcp-applepay/resources/js/Context/SingleProductHandler.js b/modules/ppcp-applepay/resources/js/Context/SingleProductHandler.js index 5825a1f2c..5ad5857be 100644 --- a/modules/ppcp-applepay/resources/js/Context/SingleProductHandler.js +++ b/modules/ppcp-applepay/resources/js/Context/SingleProductHandler.js @@ -9,7 +9,7 @@ class SingleProductHandler extends BaseHandler { validateContext() { if ( this.ppcpConfig?.locations_with_subscription_product?.product ) { - return false; + return this.isVaultV3Mode(); } return true; } diff --git a/modules/ppcp-applepay/resources/js/boot-admin.js b/modules/ppcp-applepay/resources/js/boot-admin.js index 30032f56b..f584ce41b 100644 --- a/modules/ppcp-applepay/resources/js/boot-admin.js +++ b/modules/ppcp-applepay/resources/js/boot-admin.js @@ -65,7 +65,7 @@ import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/Wi buttonConfig.button.wrapper = selector.replace('#', ''); applyConfigOptions(buttonConfig); - const wrapperElement = `
`; + const wrapperElement = `
`; if (!jQuery(selector).length) { jQuery(ppcpConfig.button.wrapper).after(wrapperElement); diff --git a/modules/ppcp-applepay/resources/js/boot-block.js b/modules/ppcp-applepay/resources/js/boot-block.js index 2e6b99124..b1d29c9c9 100644 --- a/modules/ppcp-applepay/resources/js/boot-block.js +++ b/modules/ppcp-applepay/resources/js/boot-block.js @@ -1,8 +1,10 @@ import {useEffect, useState} from '@wordpress/element'; -import {registerExpressPaymentMethod, registerPaymentMethod} from '@woocommerce/blocks-registry'; +import {registerExpressPaymentMethod} from '@woocommerce/blocks-registry'; import {loadPaypalScript} from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading' +import {cartHasSubscriptionProducts} from '../../../ppcp-blocks/resources/js/Helper/Subscription' import ApplepayManager from "./ApplepayManager"; import {loadCustomScript} from "@paypal/paypal-js"; +import CheckoutHandler from "./Context/CheckoutHandler"; const ppcpData = wc.wcSettings.getSetting('ppcp-gateway_data'); const ppcpConfig = ppcpData.scriptData; @@ -23,12 +25,6 @@ const ApplePayComponent = () => { const manager = new ApplepayManager(buttonConfig, ppcpConfig); manager.init(); }; - useEffect(() => { - const bodyClass = 'ppcp-has-applepay-block'; - if (!document.body.classList.contains(bodyClass)) { - document.body.classList.add(bodyClass); - } - }, []); useEffect(() => { // Load ApplePay SDK @@ -50,12 +46,19 @@ const ApplePayComponent = () => { }, [paypalLoaded, applePayLoaded]); return ( -
+
); } const features = ['products']; +if ( + cartHasSubscriptionProducts(ppcpConfig) + && (new CheckoutHandler(buttonConfig, ppcpConfig)).isVaultV3Mode() +) { + features.push('subscriptions'); +} + registerExpressPaymentMethod({ name: buttonData.id, label:
, diff --git a/modules/ppcp-applepay/resources/js/boot.js b/modules/ppcp-applepay/resources/js/boot.js index b28df3ce9..b4b19cde5 100644 --- a/modules/ppcp-applepay/resources/js/boot.js +++ b/modules/ppcp-applepay/resources/js/boot.js @@ -21,6 +21,15 @@ import ApplepayManager from "./ApplepayManager"; } }); + // Use set timeout as it's unnecessary to refresh upon Minicart initial render. + setTimeout(() => { + jQuery(document.body).on('wc_fragments_loaded wc_fragments_refreshed', () => { + if (manager) { + manager.reinit(); + } + }); + }, 1000); + document.addEventListener( 'DOMContentLoaded', () => { diff --git a/modules/ppcp-applepay/services.php b/modules/ppcp-applepay/services.php index 0f1266006..003c8226c 100644 --- a/modules/ppcp-applepay/services.php +++ b/modules/ppcp-applepay/services.php @@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\Applepay\Assets\BlocksPaymentMethod; use WooCommerce\PayPalCommerce\Applepay\Assets\PropertiesDictionary; use WooCommerce\PayPalCommerce\Applepay\Helper\ApmApplies; use WooCommerce\PayPalCommerce\Applepay\Helper\AvailabilityNotice; +use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; @@ -62,19 +63,26 @@ return array( ); }, + 'applepay.has_validated' => static function ( ContainerInterface $container ): bool { + $settings = $container->get( 'wcgateway.settings' ); + return $settings->has( 'applepay_validated' ); + }, + 'applepay.is_validated' => static function ( ContainerInterface $container ): bool { $settings = $container->get( 'wcgateway.settings' ); return $settings->has( 'applepay_validated' ) ? $settings->get( 'applepay_validated' ) === true : false; }, - 'applepay.apple-product-status' => static function( ContainerInterface $container ): AppleProductStatus { - return new AppleProductStatus( - $container->get( 'wcgateway.settings' ), - $container->get( 'api.endpoint.partners' ), - $container->get( 'onboarding.state' ), - $container->get( 'api.helper.failure-registry' ) - ); - }, + 'applepay.apple-product-status' => SingletonDecorator::make( + static function( ContainerInterface $container ): AppleProductStatus { + return new AppleProductStatus( + $container->get( 'wcgateway.settings' ), + $container->get( 'api.endpoint.partners' ), + $container->get( 'onboarding.state' ), + $container->get( 'api.helper.failure-registry' ) + ); + } + ), 'applepay.available' => static function ( ContainerInterface $container ): bool { if ( apply_filters( 'woocommerce_paypal_payments_applepay_validate_product_status', true ) ) { $status = $container->get( 'applepay.apple-product-status' ); @@ -166,8 +174,9 @@ return array( return apply_filters( 'woocommerce_paypal_payments_applepay_supported_country_currency_matrix', array( - 'CA' => array( + 'AU' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -176,16 +185,22 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', 'USD', ), - 'GB' => array( + 'AT' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -194,16 +209,334 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'BE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'BG' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CA' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CY' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CZ' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'DK' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'EE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'FI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'FR' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'DE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'GR' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'HU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'IE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', 'USD', ), 'IT' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -212,12 +545,377 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LV' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'MT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'NO' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'NL' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'PL' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'PT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'RO' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SK' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'ES' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'GB' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', 'USD', ), 'US' => array( diff --git a/modules/ppcp-applepay/src/Assets/ApplePayButton.php b/modules/ppcp-applepay/src/Assets/ApplePayButton.php index c34a9fc6c..f8ce67bd6 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -968,7 +968,7 @@ class ApplePayButton implements ButtonInterface { add_action( $render_placeholder, function () { - echo ''; + echo ''; }, 21 ); @@ -981,7 +981,7 @@ class ApplePayButton implements ButtonInterface { */ protected function applepay_button(): void { ?> -
+
current_status ) { return $this->current_status; @@ -128,21 +134,32 @@ class AppleProductStatus { } // Check the seller status for the intended capability. + $has_capability = false; foreach ( $seller_status->products() as $product ) { if ( $product->name() !== 'PAYMENT_METHODS' ) { continue; } if ( in_array( self::CAPABILITY_NAME, $product->capabilities(), true ) ) { - // Capability found, persist status and return true. - $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); - $this->settings->persist(); - - $this->current_status = true; - return $this->current_status; + $has_capability = true; } } + foreach ( $seller_status->capabilities() as $capability ) { + if ( $capability->name() === self::CAPABILITY_NAME && $capability->status() === SellerStatusCapability::STATUS_ACTIVE ) { + $has_capability = true; + } + } + + if ( $has_capability ) { + // Capability found, persist status and return true. + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); + $this->settings->persist(); + + $this->current_status = true; + return $this->current_status; + } + // Capability not found, persist status and return false. $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); $this->settings->persist(); diff --git a/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php b/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php index 6c29c726d..cdbe2062b 100644 --- a/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php +++ b/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php @@ -149,6 +149,7 @@ class DataToAppleButtonScripts { return array( 'sdk_url' => $this->sdk_url, 'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false, + 'is_admin' => false, 'preferences' => array( 'checkout_data_mode' => $checkout_data_mode, ), @@ -204,6 +205,7 @@ class DataToAppleButtonScripts { return array( 'sdk_url' => $this->sdk_url, 'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false, + 'is_admin' => false, 'preferences' => array( 'checkout_data_mode' => $checkout_data_mode, ), @@ -252,6 +254,7 @@ class DataToAppleButtonScripts { return array( 'sdk_url' => $this->sdk_url, 'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false, + 'is_admin' => true, 'preferences' => array( 'checkout_data_mode' => $checkout_data_mode, ), diff --git a/modules/ppcp-applepay/src/Helper/ApmApplies.php b/modules/ppcp-applepay/src/Helper/ApmApplies.php index dec9b1a08..0fa12420b 100644 --- a/modules/ppcp-applepay/src/Helper/ApmApplies.php +++ b/modules/ppcp-applepay/src/Helper/ApmApplies.php @@ -1,6 +1,7 @@ tag for the well-known file, %3$s and %4$s are the opening and closing of HTML tag for the help document. __( - 'Apple Pay Validation Error. Please ensure the presentment of the correct %1$sdomain association file%2$s for Apple to validate your domain. %3$sLearn more%4$s about the Apple Pay requirements', + 'Apple Pay has not yet been validated. Use the Apple Pay button in your shop for Apple to validate your domain. If this message persists after using the button, please verify your website displays the correct %1$sdomain association file%2$s. More details about the Apple Pay setup can be found in the %3$sPayPal Payments documentation%4$s.', 'woocommerce-paypal-payments' ), '', diff --git a/modules/ppcp-blocks/extensions.php b/modules/ppcp-blocks/extensions.php index 31f90576d..a75957eec 100644 --- a/modules/ppcp-blocks/extensions.php +++ b/modules/ppcp-blocks/extensions.php @@ -17,8 +17,8 @@ return array( return array_merge( $locations, array( - 'checkout-block-express' => _x( 'Block Express Checkout', 'Name of Buttons Location', 'woocommerce-paypal-payments' ), - 'cart-block' => _x( 'Block Cart', 'Name of Buttons Location', 'woocommerce-paypal-payments' ), + 'checkout-block-express' => _x( 'Express Checkout', 'Name of Buttons Location', 'woocommerce-paypal-payments' ), + 'cart-block' => _x( 'Cart', 'Name of Buttons Location', 'woocommerce-paypal-payments' ), ) ); }, @@ -45,7 +45,7 @@ return array( 'title' => __( 'Require final confirmation on checkout', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( - 'Require customers to confirm express payments from the Block Cart and Block Express Checkout on the checkout page. + 'Require customers to confirm express payments from the Cart and Express Checkout on the checkout page.

If this setting is not enabled, payment confirmation on the checkout will be skipped. Skipping the final confirmation on the checkout page may impact the buyer experience during the PayPal payment process.

', 'woocommerce-paypal-payments' diff --git a/modules/ppcp-blocks/resources/css/gateway.scss b/modules/ppcp-blocks/resources/css/gateway.scss new file mode 100644 index 000000000..1268f6379 --- /dev/null +++ b/modules/ppcp-blocks/resources/css/gateway.scss @@ -0,0 +1,15 @@ +@use "../../../ppcp-button/resources/css/mixins/apm-button" as apm-button; + +li[id^="express-payment-method-ppcp-"] { + line-height: 0; + + // Set min-width to 0 as the buttons need to fit in a tight grid. + .paypal-buttons { + min-width: 0 !important; + } +} + +.ppcp-button-apm { + @include apm-button.button; +} + diff --git a/modules/ppcp-blocks/resources/js/Bootstrap/BlockCheckoutMessagesBootstrap.js b/modules/ppcp-blocks/resources/js/Bootstrap/BlockCheckoutMessagesBootstrap.js new file mode 100644 index 000000000..6d301451d --- /dev/null +++ b/modules/ppcp-blocks/resources/js/Bootstrap/BlockCheckoutMessagesBootstrap.js @@ -0,0 +1,55 @@ +import MessagesBootstrap from "../../../../ppcp-button/resources/js/modules/ContextBootstrap/MessagesBootstap"; +import {debounce} from "../Helper/debounce"; + +class BlockCheckoutMessagesBootstrap { + constructor(scriptData) { + this.messagesBootstrap = new MessagesBootstrap(scriptData, null); + this.lastCartTotal = null; + } + + init() { + this.messagesBootstrap.init(); + + this._updateCartTotal(); + + if (wp.data?.subscribe) { + wp.data.subscribe(debounce(() => { + this._updateCartTotal(); + }, 300)); + } + } + + /** + * @private + */ + _getCartTotal() { + if (!wp.data.select) { + return null; + } + + const cart = wp.data.select('wc/store/cart') + if (!cart) { + return null; + } + + const totals = cart.getCartTotals(); + return parseInt(totals.total_price, 10) / 10 ** totals.currency_minor_unit; + } + + /** + * @private + */ + _updateCartTotal() { + const currentTotal = this._getCartTotal(); + if (currentTotal === null) { + return; + } + + if (currentTotal !== this.lastCartTotal) { + this.lastCartTotal = currentTotal; + jQuery(document.body).trigger('ppcp_block_cart_total_updated', [currentTotal]); + } + } +} + +export default BlockCheckoutMessagesBootstrap; diff --git a/modules/ppcp-blocks/resources/js/Helper/Address.js b/modules/ppcp-blocks/resources/js/Helper/Address.js index 6a999f141..19ca36fdd 100644 --- a/modules/ppcp-blocks/resources/js/Helper/Address.js +++ b/modules/ppcp-blocks/resources/js/Helper/Address.js @@ -63,7 +63,7 @@ export const paypalAddressToWc = (address) => { * @returns {Object} */ export const paypalShippingToWc = (shipping) => { - const [firstName, lastName] = splitFullName(shipping.name.full_name); + const [firstName, lastName] = (shipping.name ? splitFullName(shipping.name.full_name) : ['','']); return { ...paypalAddressToWc(shipping.address), first_name: firstName, @@ -76,8 +76,8 @@ export const paypalShippingToWc = (shipping) => { * @returns {Object} */ export const paypalPayerToWc = (payer) => { - const firstName = payer.name.given_name; - const lastName = payer.name.surname; + const firstName = payer?.name?.given_name ?? ''; + const lastName = payer?.name?.surname ?? ''; const address = payer.address ? paypalAddressToWc(payer.address) : {}; return { ...address, @@ -87,6 +87,22 @@ export const paypalPayerToWc = (payer) => { } } +/** + * @param {Object} subscriber + * @returns {Object} + */ +export const paypalSubscriberToWc = (subscriber) => { + const firstName = subscriber?.name?.given_name ?? ''; + const lastName = subscriber?.name?.surname ?? ''; + const address = subscriber.address ? paypalAddressToWc(subscriber.shipping_address.address) : {}; + return { + ...address, + first_name: firstName, + last_name: lastName, + email: subscriber.email_address, + } +} + /** * @param {Object} order * @returns {Object} @@ -100,10 +116,12 @@ export const paypalOrderToWcShippingAddress = (order) => { const res = paypalShippingToWc(shipping); // use the name from billing if the same, to avoid possible mistakes when splitting full_name - const billingAddress = paypalPayerToWc(order.payer); - if (`${res.first_name} ${res.last_name}` === `${billingAddress.first_name} ${billingAddress.last_name}`) { - res.first_name = billingAddress.first_name; - res.last_name = billingAddress.last_name; + if (order.payer) { + const billingAddress = paypalPayerToWc(order.payer); + if (`${res.first_name} ${res.last_name}` === `${billingAddress.first_name} ${billingAddress.last_name}`) { + res.first_name = billingAddress.first_name; + res.last_name = billingAddress.last_name; + } } return res; @@ -116,15 +134,29 @@ export const paypalOrderToWcShippingAddress = (order) => { */ export const paypalOrderToWcAddresses = (order) => { const shippingAddress = paypalOrderToWcShippingAddress(order); - let billingAddress = paypalPayerToWc(order.payer); - // no billing address, such as if billing address retrieval is not allowed in the merchant account - if (!billingAddress.address_line_1) { - billingAddress = {...shippingAddress, ...paypalPayerToWc(order.payer)}; + let billingAddress = shippingAddress; + if (order.payer) { + billingAddress = paypalPayerToWc(order.payer); + // no billing address, such as if billing address retrieval is not allowed in the merchant account + if (!billingAddress.address_line_1) { + billingAddress = {...shippingAddress, ...paypalPayerToWc(order.payer)}; + } } return {billingAddress, shippingAddress}; } +/** + * + * @param subscription + * @returns {{shippingAddress: Object, billingAddress: Object}} + */ +export const paypalSubscriptionToWcAddresses = (subscription) => { + const shippingAddress = paypalSubscriberToWc(subscription.subscriber); + let billingAddress = shippingAddress; + return {billingAddress, shippingAddress}; +} + /** * Merges two WC addresses. * The objects can contain either the WC form fields or billingAddress, shippingAddress objects. diff --git a/modules/ppcp-blocks/resources/js/Helper/Helper.js b/modules/ppcp-blocks/resources/js/Helper/Helper.js new file mode 100644 index 000000000..379c88a49 --- /dev/null +++ b/modules/ppcp-blocks/resources/js/Helper/Helper.js @@ -0,0 +1,22 @@ +/** + * @param str + * @returns {string} + */ +export const toSnakeCase = (str) => { + return str.replace(/[\w]([A-Z])/g, function(m) { + return m[0] + "_" + m[1]; + }).toLowerCase(); +} + +/** + * @param obj + * @returns {{}} + */ +export const convertKeysToSnakeCase = (obj) => { + const newObj = {}; + Object.keys(obj).forEach((key) => { + const newKey = toSnakeCase(key); + newObj[newKey] = obj[key]; + }); + return newObj; +} diff --git a/modules/ppcp-blocks/resources/js/Helper/Subscription.js b/modules/ppcp-blocks/resources/js/Helper/Subscription.js new file mode 100644 index 000000000..b274fea5e --- /dev/null +++ b/modules/ppcp-blocks/resources/js/Helper/Subscription.js @@ -0,0 +1,16 @@ +/** + * @param {Object} scriptData + * @returns {Boolean} + */ +export const isPayPalSubscription = (scriptData) => { + return scriptData.data_client_id.has_subscriptions + && scriptData.data_client_id.paypal_subscriptions_enabled; +} + +/** + * @param {Object} scriptData + * @returns {Boolean} + */ +export const cartHasSubscriptionProducts = (scriptData) => { + return !! scriptData?.locations_with_subscription_product?.cart; +} diff --git a/modules/ppcp-blocks/resources/js/Helper/debounce.js b/modules/ppcp-blocks/resources/js/Helper/debounce.js new file mode 100644 index 000000000..68a34e771 --- /dev/null +++ b/modules/ppcp-blocks/resources/js/Helper/debounce.js @@ -0,0 +1,9 @@ +export const debounce = (callback, delayMs) => { + let timeoutId = null; + return (...args) => { + window.clearTimeout(timeoutId); + timeoutId = window.setTimeout(() => { + callback.apply(null, args); + }, delayMs); + }; +}; diff --git a/modules/ppcp-blocks/resources/js/checkout-block.js b/modules/ppcp-blocks/resources/js/checkout-block.js index 215e92a35..1a10ddc7c 100644 --- a/modules/ppcp-blocks/resources/js/checkout-block.js +++ b/modules/ppcp-blocks/resources/js/checkout-block.js @@ -1,6 +1,18 @@ import {useEffect, useState} from '@wordpress/element'; import {registerExpressPaymentMethod, registerPaymentMethod} from '@woocommerce/blocks-registry'; -import {mergeWcAddress, paypalAddressToWc, paypalOrderToWcAddresses} from "./Helper/Address"; +import { + mergeWcAddress, + paypalAddressToWc, + paypalOrderToWcAddresses, + paypalSubscriptionToWcAddresses +} from "./Helper/Address"; +import { + convertKeysToSnakeCase +} from "./Helper/Helper"; +import { + cartHasSubscriptionProducts, + isPayPalSubscription +} from "./Helper/Subscription"; import { loadPaypalScriptPromise } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading' @@ -8,13 +20,16 @@ import { normalizeStyleForFundingSource } from '../../../ppcp-button/resources/js/modules/Helper/Style' import buttonModuleWatcher from "../../../ppcp-button/resources/js/modules/ButtonModuleWatcher"; - +import BlockCheckoutMessagesBootstrap from "./Bootstrap/BlockCheckoutMessagesBootstrap"; +import {keysToCamelCase} from "../../../ppcp-button/resources/js/modules/Helper/Utils"; const config = wc.wcSettings.getSetting('ppcp-gateway_data'); window.ppcpFundingSource = config.fundingSource; let registeredContext = false; +let paypalScriptPromise = null; + const PayPalComponent = ({ onClick, onClose, @@ -31,6 +46,17 @@ const PayPalComponent = ({ const {responseTypes} = emitResponse; const [paypalOrder, setPaypalOrder] = useState(null); + const [gotoContinuationOnError, setGotoContinuationOnError] = useState(false); + + const [paypalScriptLoaded, setPaypalScriptLoaded] = useState(false); + + if (!paypalScriptLoaded) { + if (!paypalScriptPromise) { + // for editor, since canMakePayment was not called + paypalScriptPromise = loadPaypalScriptPromise(config.scriptData) + } + paypalScriptPromise.then(() => setPaypalScriptLoaded(true)); + } const methodId = fundingSource ? `${config.id}-${fundingSource}` : config.id; @@ -39,12 +65,17 @@ const PayPalComponent = ({ if (!config.scriptData.continuation || !config.scriptData.continuation.order || window.ppcpContinuationFilled) { return; } - const paypalAddresses = paypalOrderToWcAddresses(config.scriptData.continuation.order); - const wcAddresses = wp.data.select('wc/store/cart').getCustomerData(); - const addresses = mergeWcAddress(wcAddresses, paypalAddresses); - wp.data.dispatch('wc/store/cart').setBillingAddress(addresses.billingAddress); - if (shippingData.needsShipping) { - wp.data.dispatch('wc/store/cart').setShippingAddress(addresses.shippingAddress); + try { + const paypalAddresses = paypalOrderToWcAddresses(config.scriptData.continuation.order); + const wcAddresses = wp.data.select('wc/store/cart').getCustomerData(); + const addresses = mergeWcAddress(wcAddresses, paypalAddresses); + wp.data.dispatch('wc/store/cart').setBillingAddress(addresses.billingAddress); + if (shippingData.needsShipping) { + wp.data.dispatch('wc/store/cart').setShippingAddress(addresses.shippingAddress); + } + } catch (err) { + // sometimes the PayPal address is missing, skip in this case. + console.log(err); } // this useEffect should run only once, but adding this in case of some kind of full re-rendering window.ppcpContinuationFilled = true; @@ -60,6 +91,7 @@ const PayPalComponent = ({ bn_code: '', context: config.scriptData.context, payment_method: 'ppcp-gateway', + funding_source: window.ppcpFundingSource ?? 'paypal', createaccount: false }), }); @@ -87,6 +119,83 @@ const PayPalComponent = ({ } }; + const createSubscription = async (data, actions) => { + let planId = config.scriptData.subscription_plan_id; + if (config.scriptData.variable_paypal_subscription_variation_from_cart !== '') { + planId = config.scriptData.variable_paypal_subscription_variation_from_cart; + } + + return actions.subscription.create({ + 'plan_id': planId + }); + }; + + const handleApproveSubscription = async (data, actions) => { + try { + const subscription = await actions.subscription.get(); + + if (subscription) { + const addresses = paypalSubscriptionToWcAddresses(subscription); + + let promises = [ + // save address on server + wp.data.dispatch('wc/store/cart').updateCustomerData({ + billing_address: addresses.billingAddress, + shipping_address: addresses.shippingAddress, + }), + ]; + if (!config.finalReviewEnabled) { + // set address in UI + promises.push(wp.data.dispatch('wc/store/cart').setBillingAddress(addresses.billingAddress)); + if (shippingData.needsShipping) { + promises.push(wp.data.dispatch('wc/store/cart').setShippingAddress(addresses.shippingAddress)) + } + } + await Promise.all(promises); + } + + setPaypalOrder(subscription); + + const res = await fetch(config.scriptData.ajax.approve_subscription.endpoint, { + method: 'POST', + credentials: 'same-origin', + body: JSON.stringify({ + nonce: config.scriptData.ajax.approve_subscription.nonce, + order_id: data.orderID, + subscription_id: data.subscriptionID + }) + }); + + const json = await res.json(); + + if (!json.success) { + if (typeof actions !== 'undefined' && typeof actions.restart !== 'undefined') { + return actions.restart(); + } + if (json.data?.message) { + throw new Error(json.data.message); + } + + throw new Error(config.scriptData.labels.error.generic) + } + + if (config.finalReviewEnabled) { + location.href = getCheckoutRedirectUrl(); + } else { + setGotoContinuationOnError(true); + onSubmit(); + } + } catch (err) { + console.error(err); + + onError(err.message); + + onClose(); + + throw err; + } + }; + const getCheckoutRedirectUrl = () => { const checkoutUrl = new URL(config.scriptData.redirect); // sometimes some browsers may load some kind of cached version of the page, @@ -147,6 +256,7 @@ const PayPalComponent = ({ if (config.finalReviewEnabled) { location.href = getCheckoutRedirectUrl(); } else { + setGotoContinuationOnError(true); onSubmit(); } } catch (err) { @@ -165,7 +275,7 @@ const PayPalComponent = ({ if (config.scriptData.continuation) { return true; } - if (wp.data.select('wc/store/validation').hasValidationErrors()) { + if (gotoContinuationOnError && wp.data.select('wc/store/validation').hasValidationErrors()) { location.href = getCheckoutRedirectUrl(); return { type: responseTypes.ERROR }; } @@ -173,7 +283,7 @@ const PayPalComponent = ({ return true; }); return unsubscribe; - }, [onCheckoutValidation] ); + }, [onCheckoutValidation, gotoContinuationOnError] ); const handleClick = (data, actions) => { if (isEditing) { @@ -185,16 +295,43 @@ const PayPalComponent = ({ onClick(); }; - let handleShippingChange = null; + let handleShippingOptionsChange = null; + let handleShippingAddressChange = null; + let handleSubscriptionShippingOptionsChange = null; + let handleSubscriptionShippingAddressChange = null; if (shippingData.needsShipping && !config.finalReviewEnabled) { - handleShippingChange = async (data, actions) => { + handleShippingOptionsChange = async (data, actions) => { try { - const shippingOptionId = data.selected_shipping_option?.id; + const shippingOptionId = data.selectedShippingOption?.id; if (shippingOptionId) { + await wp.data.dispatch('wc/store/cart').selectShippingRate(shippingOptionId); await shippingData.setSelectedRates(shippingOptionId); } - const address = paypalAddressToWc(data.shipping_address); + const res = await fetch(config.ajax.update_shipping.endpoint, { + method: 'POST', + credentials: 'same-origin', + body: JSON.stringify({ + nonce: config.ajax.update_shipping.nonce, + order_id: data.orderID, + }) + }); + + const json = await res.json(); + + if (!json.success) { + throw new Error(json.data.message); + } + } catch (e) { + console.error(e); + + actions.reject(); + } + }; + + handleShippingAddressChange = async (data, actions) => { + try { + const address = paypalAddressToWc(convertKeysToSnakeCase(data.shippingAddress)); await wp.data.dispatch('wc/store/cart').updateCustomerData({ shipping_address: address, @@ -222,6 +359,37 @@ const PayPalComponent = ({ actions.reject(); } }; + + handleSubscriptionShippingOptionsChange = async (data, actions) => { + try { + const shippingOptionId = data.selectedShippingOption?.id; + if (shippingOptionId) { + await wp.data.dispatch('wc/store/cart').selectShippingRate(shippingOptionId); + await shippingData.setSelectedRates(shippingOptionId); + } + } catch (e) { + console.error(e); + + actions.reject(); + } + }; + + handleSubscriptionShippingAddressChange = async (data, actions) => { + try { + const address = paypalAddressToWc(convertKeysToSnakeCase(data.shippingAddress)); + + await wp.data.dispatch('wc/store/cart').updateCustomerData({ + shipping_address: address, + }); + + await shippingData.setShippingAddress(address); + + } catch (e) { + console.error(e); + + actions.reject(); + } + }; } useEffect(() => { @@ -302,7 +470,27 @@ const PayPalComponent = ({ const style = normalizeStyleForFundingSource(config.scriptData.button.style, fundingSource); - const PayPalButton = window.paypal.Buttons.driver("react", { React, ReactDOM }); + if (!paypalScriptLoaded) { + return null; + } + + const PayPalButton = paypal.Buttons.driver("react", { React, ReactDOM }); + + if(isPayPalSubscription(config.scriptData)) { + return ( + + ); + } return ( ); } const features = ['products']; +let block_enabled = true; -if ((config.addPlaceOrderMethod || config.usePlaceOrder) && !config.scriptData.continuation) { - registerPaymentMethod({ - name: config.id, - label:
, - content:
, - edit:
, - placeOrderButtonLabel: config.placeOrderButtonText, - ariaLabel: config.title, - canMakePayment: () => config.enabled, - supports: { - features: features, - }, - }); +if(cartHasSubscriptionProducts(config.scriptData)) { + // Don't show buttons on block cart page if using vault v2 and user is not logged in + if ( + ! config.scriptData.user.is_logged + && config.scriptData.context === "cart-block" + && ! isPayPalSubscription(config.scriptData) // using vaulting + && ! config.scriptData?.save_payment_methods?.id_token // not vault v3 + ) { + block_enabled = false; + } + + // Don't render if vaulting disabled and is in vault subscription mode + if( + ! isPayPalSubscription(config.scriptData) + && ! config.scriptData.can_save_vault_token + ) { + block_enabled = false; + } + + // Don't render buttons if in subscription mode and product not associated with a PayPal subscription + if( + isPayPalSubscription(config.scriptData) + && !config.scriptData.subscription_product_allowed + ) { + block_enabled = false; + } + + features.push('subscriptions'); } -if (config.scriptData.continuation) { - registerPaymentMethod({ - name: config.id, - label:
, - content: , - edit: , - ariaLabel: config.title, - canMakePayment: () => true, - supports: { - features: [...features, 'ppcp_continuation'], - }, - }); -} else if (!config.usePlaceOrder) { - const paypalScriptPromise = loadPaypalScriptPromise(config.scriptData); +if (block_enabled) { + if ((config.addPlaceOrderMethod || config.usePlaceOrder) && !config.scriptData.continuation) { + let descriptionElement =
; + if (config.placeOrderButtonDescription) { + descriptionElement =
+

+

+
; + } - for (const fundingSource of ['paypal', ...config.enabledFundingSources]) { - registerExpressPaymentMethod({ - name: `${config.id}-${fundingSource}`, - paymentMethodId: config.id, + registerPaymentMethod({ + name: config.id, label:
, - content: , - edit: , + content: descriptionElement, + edit: descriptionElement, + placeOrderButtonLabel: config.placeOrderButtonText, ariaLabel: config.title, - canMakePayment: async () => { - await paypalScriptPromise; - - return paypal.Buttons({fundingSource}).isEligible(); + canMakePayment: () => { + return config.enabled; }, supports: { features: features, }, }); } + + if (config.scriptData.continuation) { + registerPaymentMethod({ + name: config.id, + label:
, + content: , + edit: , + ariaLabel: config.title, + canMakePayment: () => { + return true; + }, + supports: { + features: [...features, 'ppcp_continuation'], + }, + }); + } else if (!config.usePlaceOrder) { + for (const fundingSource of ['paypal', ...config.enabledFundingSources]) { + registerExpressPaymentMethod({ + name: `${config.id}-${fundingSource}`, + paymentMethodId: config.id, + label:
, + content: , + edit: , + ariaLabel: config.title, + canMakePayment: async () => { + if (!paypalScriptPromise) { + paypalScriptPromise = loadPaypalScriptPromise(config.scriptData); + paypalScriptPromise.then(() => { + const messagesBootstrap = new BlockCheckoutMessagesBootstrap(config.scriptData); + messagesBootstrap.init(); + }); + } + await paypalScriptPromise; + + return paypal.Buttons({fundingSource}).isEligible(); + }, + supports: { + features: features, + }, + }); + } + } } diff --git a/modules/ppcp-blocks/services.php b/modules/ppcp-blocks/services.php index 8ccd41724..a841e97b9 100644 --- a/modules/ppcp-blocks/services.php +++ b/modules/ppcp-blocks/services.php @@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\Blocks; use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; return array( 'blocks.url' => static function ( ContainerInterface $container ): string { @@ -28,7 +29,9 @@ return array( return new PayPalPaymentMethod( $container->get( 'blocks.url' ), $container->get( 'ppcp.asset-version' ), - $container->get( 'button.smart-button' ), + function () use ( $container ): SmartButtonInterface { + return $container->get( 'button.smart-button' ); + }, $container->get( 'wcgateway.settings' ), $container->get( 'wcgateway.settings.status' ), $container->get( 'wcgateway.paypal-gateway' ), @@ -38,6 +41,7 @@ return array( $container->get( 'blocks.add-place-order-method' ), $container->get( 'wcgateway.use-place-order-button' ), $container->get( 'wcgateway.place-order-button-text' ), + $container->get( 'wcgateway.place-order-button-description' ), $container->get( 'wcgateway.all-funding-sources' ) ); }, diff --git a/modules/ppcp-blocks/src/BlocksModule.php b/modules/ppcp-blocks/src/BlocksModule.php index 1766806b7..9b00d61bc 100644 --- a/modules/ppcp-blocks/src/BlocksModule.php +++ b/modules/ppcp-blocks/src/BlocksModule.php @@ -88,6 +88,28 @@ class BlocksModule implements ModuleInterface { $endpoint->handle_request(); } ); + + // Enqueue frontend scripts. + add_action( + 'wp_enqueue_scripts', + static function () use ( $c ) { + if ( ! has_block( 'woocommerce/checkout' ) && ! has_block( 'woocommerce/cart' ) ) { + return; + } + + $module_url = $c->get( 'blocks.url' ); + $asset_version = $c->get( 'ppcp.asset-version' ); + + wp_register_style( + 'wc-ppcp-blocks', + untrailingslashit( $module_url ) . '/assets/css/gateway.css', + array(), + $asset_version + ); + wp_enqueue_style( 'wc-ppcp-blocks' ); + } + ); + } /** diff --git a/modules/ppcp-blocks/src/PayPalPaymentMethod.php b/modules/ppcp-blocks/src/PayPalPaymentMethod.php index fe0a381c6..d94eec53d 100644 --- a/modules/ppcp-blocks/src/PayPalPaymentMethod.php +++ b/modules/ppcp-blocks/src/PayPalPaymentMethod.php @@ -41,7 +41,7 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType { /** * The smart button script loading handler. * - * @var SmartButtonInterface + * @var SmartButtonInterface|callable */ private $smart_button; @@ -108,6 +108,13 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType { */ protected $place_order_button_text; + /** + * The text for additional "Place order" description. + * + * @var string + */ + protected $place_order_button_description; + /** * All existing funding sources for PayPal buttons. * @@ -118,24 +125,25 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType { /** * Assets constructor. * - * @param string $module_url The url of this module. - * @param string $version The assets version. - * @param SmartButtonInterface $smart_button The smart button script loading handler. - * @param Settings $plugin_settings The settings. - * @param SettingsStatus $settings_status The Settings status helper. - * @param PayPalGateway $gateway The WC gateway. - * @param bool $final_review_enabled Whether the final review is enabled. - * @param CancelView $cancellation_view The cancellation view. - * @param SessionHandler $session_handler The Session handler. - * @param bool $add_place_order_method Whether to create a non-express method with the standard "Place order" button. - * @param bool $use_place_order Whether to use the standard "Place order" button instead of PayPal buttons. - * @param string $place_order_button_text The text for the standard "Place order" button. - * @param array $all_funding_sources All existing funding sources for PayPal buttons. + * @param string $module_url The url of this module. + * @param string $version The assets version. + * @param SmartButtonInterface|callable $smart_button The smart button script loading handler. + * @param Settings $plugin_settings The settings. + * @param SettingsStatus $settings_status The Settings status helper. + * @param PayPalGateway $gateway The WC gateway. + * @param bool $final_review_enabled Whether the final review is enabled. + * @param CancelView $cancellation_view The cancellation view. + * @param SessionHandler $session_handler The Session handler. + * @param bool $add_place_order_method Whether to create a non-express method with the standard "Place order" button. + * @param bool $use_place_order Whether to use the standard "Place order" button instead of PayPal buttons. + * @param string $place_order_button_text The text for the standard "Place order" button. + * @param string $place_order_button_description The text for additional "Place order" description. + * @param array $all_funding_sources All existing funding sources for PayPal buttons. */ public function __construct( string $module_url, string $version, - SmartButtonInterface $smart_button, + $smart_button, Settings $plugin_settings, SettingsStatus $settings_status, PayPalGateway $gateway, @@ -145,22 +153,24 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType { bool $add_place_order_method, bool $use_place_order, string $place_order_button_text, + string $place_order_button_description, array $all_funding_sources ) { - $this->name = PayPalGateway::ID; - $this->module_url = $module_url; - $this->version = $version; - $this->smart_button = $smart_button; - $this->plugin_settings = $plugin_settings; - $this->settings_status = $settings_status; - $this->gateway = $gateway; - $this->final_review_enabled = $final_review_enabled; - $this->cancellation_view = $cancellation_view; - $this->session_handler = $session_handler; - $this->add_place_order_method = $add_place_order_method; - $this->use_place_order = $use_place_order; - $this->place_order_button_text = $place_order_button_text; - $this->all_funding_sources = $all_funding_sources; + $this->name = PayPalGateway::ID; + $this->module_url = $module_url; + $this->version = $version; + $this->smart_button = $smart_button; + $this->plugin_settings = $plugin_settings; + $this->settings_status = $settings_status; + $this->gateway = $gateway; + $this->final_review_enabled = $final_review_enabled; + $this->cancellation_view = $cancellation_view; + $this->session_handler = $session_handler; + $this->add_place_order_method = $add_place_order_method; + $this->use_place_order = $use_place_order; + $this->place_order_button_text = $place_order_button_text; + $this->place_order_button_description = $place_order_button_description; + $this->all_funding_sources = $all_funding_sources; } /** @@ -199,7 +209,7 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType { * {@inheritDoc} */ public function get_payment_method_data() { - $script_data = $this->smart_button->script_data(); + $script_data = $this->smart_button()->script_data(); if ( isset( $script_data['continuation'] ) ) { $url = add_query_arg( array( CancelController::NONCE => wp_create_nonce( CancelController::NONCE ) ), wc_get_checkout_url() ); @@ -214,32 +224,64 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType { } } - $disabled_funding_sources = explode( ',', $script_data['url_params']['disable-funding'] ) ?: array(); - $funding_sources = array_values( - array_diff( - array_keys( $this->all_funding_sources ), - $disabled_funding_sources - ) - ); + $funding_sources = array(); + if ( ! $this->is_editing() ) { + $disabled_funding_sources = explode( ',', $script_data['url_params']['disable-funding'] ?? '' ) ?: array(); + $funding_sources = array_values( + array_diff( + array_keys( $this->all_funding_sources ), + $disabled_funding_sources + ) + ); + } return array( - 'id' => $this->gateway->id, - 'title' => $this->gateway->title, - 'description' => $this->gateway->description, - 'enabled' => $this->settings_status->is_smart_button_enabled_for_location( $script_data['context'] ), - 'fundingSource' => $this->session_handler->funding_source(), - 'finalReviewEnabled' => $this->final_review_enabled, - 'addPlaceOrderMethod' => $this->add_place_order_method, - 'usePlaceOrder' => $this->use_place_order, - 'placeOrderButtonText' => $this->place_order_button_text, - 'enabledFundingSources' => $funding_sources, - 'ajax' => array( + 'id' => $this->gateway->id, + 'title' => $this->gateway->title, + 'description' => $this->gateway->description, + 'enabled' => $this->settings_status->is_smart_button_enabled_for_location( $script_data['context'] ?? 'checkout' ), + 'fundingSource' => $this->session_handler->funding_source(), + 'finalReviewEnabled' => $this->final_review_enabled, + 'addPlaceOrderMethod' => $this->add_place_order_method, + 'usePlaceOrder' => $this->use_place_order, + 'placeOrderButtonText' => $this->place_order_button_text, + 'placeOrderButtonDescription' => $this->place_order_button_description, + 'enabledFundingSources' => $funding_sources, + 'ajax' => array( 'update_shipping' => array( 'endpoint' => WC_AJAX::get_endpoint( UpdateShippingEndpoint::ENDPOINT ), 'nonce' => wp_create_nonce( UpdateShippingEndpoint::nonce() ), ), ), - 'scriptData' => $script_data, + 'scriptData' => $script_data, ); } + + /** + * Checks if it is the block editing mode. + */ + private function is_editing(): bool { + if ( ! function_exists( 'get_current_screen' ) ) { + return false; + } + $screen = get_current_screen(); + return $screen && $screen->is_block_editor(); + } + + /** + * The smart button. + * + * @return SmartButtonInterface + */ + private function smart_button(): SmartButtonInterface { + if ( $this->smart_button instanceof SmartButtonInterface ) { + return $this->smart_button; + } + + if ( is_callable( $this->smart_button ) ) { + $this->smart_button = ( $this->smart_button )(); + } + + return $this->smart_button; + } } diff --git a/modules/ppcp-blocks/webpack.config.js b/modules/ppcp-blocks/webpack.config.js index 4695769ed..bdf508fba 100644 --- a/modules/ppcp-blocks/webpack.config.js +++ b/modules/ppcp-blocks/webpack.config.js @@ -9,7 +9,8 @@ module.exports = { target: 'web', plugins: [ new DependencyExtractionWebpackPlugin() ], entry: { - 'checkout-block': path.resolve('./resources/js/checkout-block.js') + 'checkout-block': path.resolve('./resources/js/checkout-block.js'), + "gateway": path.resolve('./resources/css/gateway.scss') }, output: { path: path.resolve(__dirname, 'assets/'), diff --git a/modules/ppcp-button/resources/css/gateway.scss b/modules/ppcp-button/resources/css/gateway.scss index 42b216e92..ee848f0cd 100644 --- a/modules/ppcp-button/resources/css/gateway.scss +++ b/modules/ppcp-button/resources/css/gateway.scss @@ -1,3 +1,5 @@ +@use "mixins/apm-button" as apm-button; + #place_order.ppcp-hidden { display: none !important; } @@ -15,3 +17,24 @@ .ppc-button-wrapper #ppcp-messages:first-child { padding-top: 10px; } + +// Prevents spacing after button group. +#ppc-button-ppcp-gateway { + line-height: 0; + + div[class^="item-"] { + margin-top: 14px; + &:first-child { + margin-top: 0; + } + } +} + +#ppc-button-minicart { + line-height: 0; + display: block; +} + +.ppcp-button-apm { + @include apm-button.button; +} diff --git a/modules/ppcp-button/resources/css/mixins/apm-button.scss b/modules/ppcp-button/resources/css/mixins/apm-button.scss new file mode 100644 index 000000000..5c9e73921 --- /dev/null +++ b/modules/ppcp-button/resources/css/mixins/apm-button.scss @@ -0,0 +1,42 @@ + +@mixin button { + overflow: hidden; + min-width: 0; + max-width: 750px; + line-height: 0; + border-radius: 4px; + + // Defaults + height: 45px; + margin-top: 14px; + + &.ppcp-button-pill { + border-radius: 50px; + } + + &.ppcp-button-minicart { + display: block; + } + + .ppcp-width-min & { + height: 35px; + } + + .ppcp-width-300 & { + height: 45px; + } + + .ppcp-width-500 & { + height: 55px; + } + + // No margin on block layout. + .wp-block-woocommerce-checkout &, .wp-block-woocommerce-cart & { + margin: 0; + min-width: 0; + } + + .wp-admin & { + pointer-events: none; + } +} diff --git a/modules/ppcp-button/resources/js/button.js b/modules/ppcp-button/resources/js/button.js index e0cd517ab..d0e1a8543 100644 --- a/modules/ppcp-button/resources/js/button.js +++ b/modules/ppcp-button/resources/js/button.js @@ -22,6 +22,7 @@ import FormValidator from "./modules/Helper/FormValidator"; import {loadPaypalScript} from "./modules/Helper/ScriptLoading"; import buttonModuleWatcher from "./modules/ButtonModuleWatcher"; import MessagesBootstrap from "./modules/ContextBootstrap/MessagesBootstap"; +import {apmButtonsInit} from "./modules/Helper/ApmButtons"; // TODO: could be a good idea to have a separate spinner for each gateway, // but I think we care mainly about the script loading, so one spinner should be enough. @@ -39,11 +40,6 @@ const bootstrap = () => { ); const spinner = new Spinner(); - let creditCardRenderer = new HostedFieldsRenderer(PayPalCommerceGateway, errorHandler, spinner); - if (typeof paypal.CardFields !== 'undefined') { - creditCardRenderer = new CardFieldsRenderer(PayPalCommerceGateway, errorHandler, spinner); - } - const formSaver = new FormSaver( PayPalCommerceGateway.ajax.save_checkout_form.endpoint, PayPalCommerceGateway.ajax.save_checkout_form.nonce, @@ -72,13 +68,7 @@ const bootstrap = () => { && document.querySelector(PayPalCommerceGateway.messages.wrapper); } - const onSmartButtonClick = async (data, actions) => { - window.ppcpFundingSource = data.fundingSource; - const requiredFields = jQuery('form.woocommerce-checkout .validate-required:visible :input'); - requiredFields.each((i, input) => { - jQuery(input).trigger('validate'); - }); - + const doBasicCheckoutValidation = () => { if (PayPalCommerceGateway.basic_checkout_validation_enabled) { // A quick fix to get the errors about empty form fields before attempting PayPal order, // it should solve #513 for most of the users, but it is not a proper solution. @@ -116,9 +106,26 @@ const bootstrap = () => { errorHandler.message(PayPalCommerceGateway.labels.error.required.generic); } - return actions.reject(); + return false; } } + return true; + }; + + const onCardFieldsBeforeSubmit = () => { + return doBasicCheckoutValidation(); + }; + + const onSmartButtonClick = async (data, actions) => { + window.ppcpFundingSource = data.fundingSource; + const requiredFields = jQuery('form.woocommerce-checkout .validate-required:visible :input'); + requiredFields.each((i, input) => { + jQuery(input).trigger('validate'); + }); + + if (!doBasicCheckoutValidation()) { + return actions.reject(); + } const form = document.querySelector(checkoutFormSelector); if (form) { @@ -130,7 +137,12 @@ const bootstrap = () => { } const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart; - if (isFreeTrial && data.fundingSource !== 'card') { + if ( + isFreeTrial + && data.fundingSource !== 'card' + && ! PayPalCommerceGateway.subscription_plan_id + && ! PayPalCommerceGateway.vault_v3_enabled + ) { freeTrialHandler.handle(); return actions.reject(); } @@ -145,8 +157,15 @@ const bootstrap = () => { }; const onSmartButtonsInit = () => { + jQuery(document).trigger('ppcp-smart-buttons-init', this); buttonsSpinner.unblock(); }; + + let creditCardRenderer = new HostedFieldsRenderer(PayPalCommerceGateway, errorHandler, spinner); + if (typeof paypal.CardFields !== 'undefined') { + creditCardRenderer = new CardFieldsRenderer(PayPalCommerceGateway, errorHandler, spinner, onCardFieldsBeforeSubmit); + } + const renderer = new Renderer(creditCardRenderer, PayPalCommerceGateway, onSmartButtonClick, onSmartButtonsInit); const messageRenderer = new MessageRenderer(PayPalCommerceGateway.messages); @@ -217,6 +236,8 @@ const bootstrap = () => { messageRenderer, ); messagesBootstrap.init(); + + apmButtonsInit(PayPalCommerceGateway); }; document.addEventListener( diff --git a/modules/ppcp-button/resources/js/modules/ActionHandler/CartActionHandler.js b/modules/ppcp-button/resources/js/modules/ActionHandler/CartActionHandler.js index 4b7b20e9e..0400c8013 100644 --- a/modules/ppcp-button/resources/js/modules/ActionHandler/CartActionHandler.js +++ b/modules/ppcp-button/resources/js/modules/ActionHandler/CartActionHandler.js @@ -9,11 +9,11 @@ class CartActionHandler { this.errorHandler = errorHandler; } - subscriptionsConfiguration() { + subscriptionsConfiguration(subscription_plan_id) { return { createSubscription: (data, actions) => { return actions.subscription.create({ - 'plan_id': this.config.subscription_plan_id + 'plan_id': subscription_plan_id }); }, onApprove: (data, actions) => { diff --git a/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js b/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js index b6882ff3f..923c0b772 100644 --- a/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js +++ b/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js @@ -2,6 +2,7 @@ import 'formdata-polyfill'; import onApprove from '../OnApproveHandler/onApproveForPayNow.js'; import {payerData} from "../Helper/PayerData"; import {getCurrentPaymentMethod} from "../Helper/CheckoutMethodState"; +import validateCheckoutForm from "../Helper/CheckoutFormValidation"; class CheckoutActionHandler { @@ -11,11 +12,17 @@ class CheckoutActionHandler { this.spinner = spinner; } - subscriptionsConfiguration() { + subscriptionsConfiguration(subscription_plan_id) { return { - createSubscription: (data, actions) => { + createSubscription: async (data, actions) => { + try { + await validateCheckoutForm(this.config); + } catch (error) { + throw {type: 'form-validation-error'}; + } + return actions.subscription.create({ - 'plan_id': this.config.subscription_plan_id + 'plan_id': subscription_plan_id }); }, onApprove: (data, actions) => { @@ -56,6 +63,8 @@ class CheckoutActionHandler { const paymentMethod = getCurrentPaymentMethod(); const fundingSource = window.ppcpFundingSource; + const savePaymentMethod = !!document.getElementById('wc-ppcp-credit-card-gateway-new-payment-method')?.checked; + return fetch(this.config.ajax.create_order.endpoint, { method: 'POST', headers: { @@ -72,7 +81,8 @@ class CheckoutActionHandler { funding_source: fundingSource, // send as urlencoded string to handle complex fields via PHP functions the same as normal form submit form_encoded: new URLSearchParams(formData).toString(), - createaccount: createaccount + createaccount: createaccount, + save_payment_method: savePaymentMethod }) }).then(function (res) { return res.json(); @@ -134,6 +144,54 @@ class CheckoutActionHandler { } } } + + addPaymentMethodConfiguration() { + return { + createVaultSetupToken: async () => { + const response = await fetch(this.config.ajax.create_setup_token.endpoint, { + method: "POST", + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + nonce: this.config.ajax.create_setup_token.nonce, + }) + }); + + const result = await response.json() + if (result.data.id) { + return result.data.id + } + + console.error(result) + }, + onApprove: async ({vaultSetupToken}) => { + const response = await fetch(this.config.ajax.create_payment_token_for_guest.endpoint, { + method: "POST", + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + nonce: this.config.ajax.create_payment_token_for_guest.nonce, + vault_setup_token: vaultSetupToken, + }) + }) + + const result = await response.json(); + if (result.success === true) { + document.querySelector('#place_order').click() + return; + } + + console.error(result) + }, + onError: (error) => { + console.error(error) + } + } + } } export default CheckoutActionHandler; diff --git a/modules/ppcp-button/resources/js/modules/ButtonModuleWatcher.js b/modules/ppcp-button/resources/js/modules/ButtonModuleWatcher.js index c6165674a..3fccca178 100644 --- a/modules/ppcp-button/resources/js/modules/ButtonModuleWatcher.js +++ b/modules/ppcp-button/resources/js/modules/ButtonModuleWatcher.js @@ -7,7 +7,6 @@ class ButtonModuleWatcher { } watchContextBootstrap(callable) { - console.log('ButtonModuleWatcher.js: watchContextBootstrap', this.contextBootstrapRegistry) this.contextBootstrapWatchers.push(callable); Object.values(this.contextBootstrapRegistry).forEach(callable); } diff --git a/modules/ppcp-button/resources/js/modules/ContextBootstrap/CartBootstap.js b/modules/ppcp-button/resources/js/modules/ContextBootstrap/CartBootstap.js index c40e03ce1..bf8ad10ef 100644 --- a/modules/ppcp-button/resources/js/modules/ContextBootstrap/CartBootstap.js +++ b/modules/ppcp-button/resources/js/modules/ContextBootstrap/CartBootstap.js @@ -90,7 +90,12 @@ class CartBootstrap { PayPalCommerceGateway.data_client_id.has_subscriptions && PayPalCommerceGateway.data_client_id.paypal_subscriptions_enabled ) { - this.renderer.render(actionHandler.subscriptionsConfiguration()); + let subscription_plan_id = PayPalCommerceGateway.subscription_plan_id + if(PayPalCommerceGateway.variable_paypal_subscription_variation_from_cart !== '') { + subscription_plan_id = PayPalCommerceGateway.variable_paypal_subscription_variation_from_cart + } + + this.renderer.render(actionHandler.subscriptionsConfiguration(subscription_plan_id)); if(!PayPalCommerceGateway.subscription_product_allowed) { this.gateway.button.is_disabled = true; diff --git a/modules/ppcp-button/resources/js/modules/ContextBootstrap/CheckoutBootstap.js b/modules/ppcp-button/resources/js/modules/ContextBootstrap/CheckoutBootstap.js index e7fae33b0..a14fa2f4b 100644 --- a/modules/ppcp-button/resources/js/modules/ContextBootstrap/CheckoutBootstap.js +++ b/modules/ppcp-button/resources/js/modules/ContextBootstrap/CheckoutBootstap.js @@ -106,7 +106,11 @@ class CheckoutBootstap { PayPalCommerceGateway.data_client_id.has_subscriptions && PayPalCommerceGateway.data_client_id.paypal_subscriptions_enabled ) { - this.renderer.render(actionHandler.subscriptionsConfiguration(), {}, actionHandler.configuration()); + let subscription_plan_id = PayPalCommerceGateway.subscription_plan_id + if(PayPalCommerceGateway.variable_paypal_subscription_variation_from_cart !== '') { + subscription_plan_id = PayPalCommerceGateway.variable_paypal_subscription_variation_from_cart + } + this.renderer.render(actionHandler.subscriptionsConfiguration(subscription_plan_id), {}, actionHandler.configuration()); if(!PayPalCommerceGateway.subscription_product_allowed) { this.gateway.button.is_disabled = true; @@ -116,6 +120,14 @@ class CheckoutBootstap { return; } + if( + PayPalCommerceGateway.is_free_trial_cart + && PayPalCommerceGateway.vault_v3_enabled + ) { + this.renderer.render(actionHandler.addPaymentMethodConfiguration(), {}, actionHandler.configuration()); + return; + } + this.renderer.render(actionHandler.configuration(), {}, actionHandler.configuration()); } diff --git a/modules/ppcp-button/resources/js/modules/ContextBootstrap/MessagesBootstap.js b/modules/ppcp-button/resources/js/modules/ContextBootstrap/MessagesBootstap.js index fe1c49438..1c20e871b 100644 --- a/modules/ppcp-button/resources/js/modules/ContextBootstrap/MessagesBootstap.js +++ b/modules/ppcp-button/resources/js/modules/ContextBootstrap/MessagesBootstap.js @@ -1,13 +1,20 @@ import {setVisible} from "../Helper/Hiding"; +import MessageRenderer from "../Renderer/MessageRenderer"; class MessagesBootstrap { constructor(gateway, messageRenderer) { this.gateway = gateway; - this.renderer = messageRenderer; + this.renderers = []; this.lastAmount = this.gateway.messages.amount; + if (messageRenderer) { + this.renderers.push(messageRenderer); + } } init() { + if (this.gateway.messages?.block?.enabled) { + this.discoverBlocks(); + } jQuery(document.body).on('ppcp_cart_rendered ppcp_checkout_rendered', () => { this.render(); }); @@ -16,7 +23,7 @@ class MessagesBootstrap { this.render(); }); - jQuery(document.body).on('ppcp_cart_total_updated ppcp_checkout_total_updated ppcp_product_total_updated', (e, amount) => { + jQuery(document.body).on('ppcp_cart_total_updated ppcp_checkout_total_updated ppcp_product_total_updated ppcp_block_cart_total_updated', (e, amount) => { if (this.lastAmount !== amount) { this.lastAmount = amount; @@ -27,28 +34,40 @@ class MessagesBootstrap { this.render(); } - shouldShow() { + discoverBlocks() { + Array.from(document.querySelectorAll('.ppcp-paylater-message-block')).forEach(blockElement => { + const config = {wrapper: '#' + blockElement.id}; + if (!blockElement.getAttribute('data-pp-placement')) { + config.placement = this.gateway.messages.placement; + } + this.renderers.push(new MessageRenderer(config)); + }); + } + + shouldShow(renderer) { if (this.gateway.messages.is_hidden === true) { return false; } const eventData = {result: true} - jQuery(document.body).trigger('ppcp_should_show_messages', [eventData]); + jQuery(document.body).trigger('ppcp_should_show_messages', [eventData, renderer.config.wrapper]); return eventData.result; } - shouldRender() { - return this.shouldShow() && this.renderer.shouldRender(); - } - render() { - setVisible(this.gateway.messages.wrapper, this.shouldShow()); + this.renderers.forEach(renderer => { + const shouldShow = this.shouldShow(renderer); + setVisible(renderer.config.wrapper, shouldShow); + if (!shouldShow) { + return; + } - if (!this.shouldRender()) { - return; - } + if (!renderer.shouldRender()) { + return; + } - this.renderer.renderWithAmount(this.lastAmount); + renderer.renderWithAmount(this.lastAmount); + }); } } diff --git a/modules/ppcp-button/resources/js/modules/Helper/ApmButtons.js b/modules/ppcp-button/resources/js/modules/Helper/ApmButtons.js new file mode 100644 index 000000000..d6512723e --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/Helper/ApmButtons.js @@ -0,0 +1,120 @@ + +export const apmButtonsInit = (config, selector = '.ppcp-button-apm') => { + let selectorInContainer = selector; + + if (window.ppcpApmButtons) { + return; + } + + if (config && config.button) { + + // If it's separate gateways, modify wrapper to account for the individual buttons as individual APMs. + const wrapper = config.button.wrapper; + const isSeparateGateways = jQuery(wrapper).children('div[class^="item-"]').length > 0; + + if (isSeparateGateways) { + selector += `, ${wrapper} div[class^="item-"]`; + selectorInContainer += `, div[class^="item-"]`; + } + } + + window.ppcpApmButtons = new ApmButtons(selector, selectorInContainer); +} + +export class ApmButtons { + + constructor(selector, selectorInContainer) { + this.selector = selector; + this.selectorInContainer = selectorInContainer; + this.containers = []; + + // Reloads button containers. + this.reloadContainers(); + + // Refresh button layout. + jQuery(window).resize(() => { + this.refresh(); + }).resize(); + + jQuery(document).on('ppcp-smart-buttons-init', () => { + this.refresh(); + }); + + jQuery(document).on('ppcp-shown ppcp-hidden ppcp-enabled ppcp-disabled', (ev, data) => { + this.refresh(); + setTimeout(this.refresh.bind(this), 200); + }); + + // Observes for new buttons. + (new MutationObserver(this.observeElementsCallback.bind(this))) + .observe(document.body, { childList: true, subtree: true }); + } + + observeElementsCallback(mutationsList, observer) { + const observeSelector = this.selector + ', .widget_shopping_cart, .widget_shopping_cart_content'; + + let shouldReload = false; + for (let mutation of mutationsList) { + if (mutation.type === 'childList') { + mutation.addedNodes.forEach(node => { + if (node.matches && node.matches(observeSelector)) { + shouldReload = true; + } + }); + } + } + + if (shouldReload) { + this.reloadContainers(); + this.refresh(); + } + }; + + reloadContainers() { + jQuery(this.selector).each((index, el) => { + const parent = jQuery(el).parent(); + if (!this.containers.some($el => $el.is(parent))) { + this.containers.push(parent); + } + }); + } + + refresh() { + for (const container of this.containers) { + const $container = jQuery(container); + + // Check width and add classes + const width = $container.width(); + + $container.removeClass('ppcp-width-500 ppcp-width-300 ppcp-width-min'); + + if (width >= 500) { + $container.addClass('ppcp-width-500'); + } else if (width >= 300) { + $container.addClass('ppcp-width-300'); + } else { + $container.addClass('ppcp-width-min'); + } + + // Check first apm button + const $firstElement = $container.children(':visible').first(); + + // Assign margins to buttons + $container.find(this.selectorInContainer).each((index, el) => { + const $el = jQuery(el); + + if ($el.is($firstElement)) { + $el.css('margin-top', `0px`); + return true; + } + + const minMargin = 11; // Minimum margin. + const height = $el.height(); + const margin = Math.max(minMargin, Math.round(height * 0.3)); + $el.css('margin-top', `${margin}px`); + }); + + } + } + +} diff --git a/modules/ppcp-button/resources/js/modules/Helper/CardFieldsHelper.js b/modules/ppcp-button/resources/js/modules/Helper/CardFieldsHelper.js new file mode 100644 index 000000000..5dc02d3d6 --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/Helper/CardFieldsHelper.js @@ -0,0 +1,50 @@ +export const cardFieldStyles = (field) => { + const allowedProperties = [ + 'appearance', + 'color', + 'direction', + 'font', + 'font-family', + 'font-size', + 'font-size-adjust', + 'font-stretch', + 'font-style', + 'font-variant', + 'font-variant-alternates', + 'font-variant-caps', + 'font-variant-east-asian', + 'font-variant-ligatures', + 'font-variant-numeric', + 'font-weight', + 'letter-spacing', + 'line-height', + 'opacity', + 'outline', + 'padding', + 'padding-bottom', + 'padding-left', + 'padding-right', + 'padding-top', + 'text-shadow', + 'transition', + '-moz-appearance', + '-moz-osx-font-smoothing', + '-moz-tap-highlight-color', + '-moz-transition', + '-webkit-appearance', + '-webkit-osx-font-smoothing', + '-webkit-tap-highlight-color', + '-webkit-transition', + ]; + + const stylesRaw = window.getComputedStyle(field); + const styles = {}; + Object.values(stylesRaw).forEach((prop) => { + if (!stylesRaw[prop] || !allowedProperties.includes(prop)) { + return; + } + styles[prop] = '' + stylesRaw[prop]; + }); + + return styles; +} diff --git a/modules/ppcp-button/resources/js/modules/Helper/CheckoutFormValidation.js b/modules/ppcp-button/resources/js/modules/Helper/CheckoutFormValidation.js new file mode 100644 index 000000000..092d0f148 --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/Helper/CheckoutFormValidation.js @@ -0,0 +1,48 @@ +import Spinner from "./Spinner"; +import FormValidator from "./FormValidator"; +import ErrorHandler from "../ErrorHandler"; + +const validateCheckoutForm = function (config) { + return new Promise(async (resolve, reject) => { + try { + const spinner = new Spinner(); + const errorHandler = new ErrorHandler( + config.labels.error.generic, + document.querySelector('.woocommerce-notices-wrapper') + ); + + const formSelector = config.context === 'checkout' ? 'form.checkout' : 'form#order_review'; + const formValidator = config.early_checkout_validation_enabled ? + new FormValidator( + config.ajax.validate_checkout.endpoint, + config.ajax.validate_checkout.nonce, + ) : null; + + if (!formValidator) { + resolve(); + return; + } + + formValidator.validate(document.querySelector(formSelector)).then((errors) => { + if (errors.length > 0) { + spinner.unblock(); + errorHandler.clear(); + errorHandler.messages(errors); + + // fire WC event for other plugins + jQuery( document.body ).trigger( 'checkout_error' , [ errorHandler.currentHtml() ] ); + + reject(); + } else { + resolve(); + } + }); + + } catch (error) { + console.error(error); + reject(); + } + }); +} + +export default validateCheckoutForm; diff --git a/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js b/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js index 15906b1b0..cbe867ae6 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js +++ b/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js @@ -56,14 +56,22 @@ export const loadPaypalScript = (config, onLoaded, onError = null) => { // Build the PayPal script options. let scriptOptions = keysToCamelCase(config.url_params); - scriptOptions = merge(scriptOptions, config.script_attributes); + if (config.script_attributes) { + scriptOptions = merge(scriptOptions, config.script_attributes); + } // Load PayPal script for special case with data-client-token - if (config.data_client_id.set_attribute) { + if (config.data_client_id?.set_attribute) { dataClientIdAttributeHandler(scriptOptions, config.data_client_id, callback, errorCallback); return; } + // Adds data-user-id-token to script options. + const userIdToken = config?.save_payment_methods?.id_token; + if(userIdToken) { + scriptOptions['data-user-id-token'] = userIdToken; + } + // Load PayPal script loadScript(scriptOptions) .then(callback) @@ -81,3 +89,11 @@ export const loadPaypalJsScript = (options, buttons, container) => { paypal.Buttons(buttons).render(container); }); } + +export const loadPaypalJsScriptPromise = (options) => { + return new Promise((resolve, reject) => { + loadScript(options) + .then(resolve) + .catch(reject); + }); +} diff --git a/modules/ppcp-button/resources/js/modules/Renderer/CardFieldsRenderer.js b/modules/ppcp-button/resources/js/modules/Renderer/CardFieldsRenderer.js index 29514186a..73532a727 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/CardFieldsRenderer.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/CardFieldsRenderer.js @@ -1,8 +1,9 @@ import {show} from "../Helper/Hiding"; +import {cardFieldStyles} from "../Helper/CardFieldsHelper"; class CardFieldsRenderer { - constructor(defaultConfig, errorHandler, spinner) { + constructor(defaultConfig, errorHandler, spinner, onCardFieldsBeforeSubmit) { this.defaultConfig = defaultConfig; this.errorHandler = errorHandler; this.spinner = spinner; @@ -10,6 +11,7 @@ class CardFieldsRenderer { this.formValid = false; this.emptyFields = new Set(['number', 'cvv', 'expirationDate']); this.currentHostedFieldsInstance = null; + this.onCardFieldsBeforeSubmit = onCardFieldsBeforeSubmit; } render(wrapper, contextConfig) { @@ -53,29 +55,53 @@ class CardFieldsRenderer { if (cardField.isEligible()) { const nameField = document.getElementById('ppcp-credit-card-gateway-card-name'); if (nameField) { - let styles = this.cardFieldStyles(nameField); - cardField.NameField({style: {'input': styles}}).render(nameField.parentNode); + let styles = cardFieldStyles(nameField); + let fieldOptions = { + style: { 'input': styles } + } + if (nameField.getAttribute('placeholder')) { + fieldOptions.placeholder = nameField.getAttribute('placeholder'); + } + cardField.NameField(fieldOptions).render(nameField.parentNode); nameField.remove(); } const numberField = document.getElementById('ppcp-credit-card-gateway-card-number'); if (numberField) { - let styles = this.cardFieldStyles(numberField); - cardField.NumberField({style: {'input': styles}}).render(numberField.parentNode); + let styles = cardFieldStyles(numberField); + let fieldOptions = { + style: { 'input': styles } + } + if (numberField.getAttribute('placeholder')) { + fieldOptions.placeholder = numberField.getAttribute('placeholder'); + } + cardField.NumberField(fieldOptions).render(numberField.parentNode); numberField.remove(); } const expiryField = document.getElementById('ppcp-credit-card-gateway-card-expiry'); if (expiryField) { - let styles = this.cardFieldStyles(expiryField); - cardField.ExpiryField({style: {'input': styles}}).render(expiryField.parentNode); + let styles = cardFieldStyles(expiryField); + let fieldOptions = { + style: { 'input': styles } + } + if (expiryField.getAttribute('placeholder')) { + fieldOptions.placeholder = expiryField.getAttribute('placeholder'); + } + cardField.ExpiryField(fieldOptions).render(expiryField.parentNode); expiryField.remove(); } const cvvField = document.getElementById('ppcp-credit-card-gateway-card-cvc'); if (cvvField) { - let styles = this.cardFieldStyles(cvvField); - cardField.CVVField({style: {'input': styles}}).render(cvvField.parentNode); + let styles = cardFieldStyles(cvvField); + let fieldOptions = { + style: { 'input': styles } + } + if (cvvField.getAttribute('placeholder')) { + fieldOptions.placeholder = cvvField.getAttribute('placeholder'); + } + cardField.CVVField(fieldOptions).render(cvvField.parentNode); cvvField.remove(); } @@ -86,70 +112,41 @@ class CardFieldsRenderer { show(buttonSelector); + if(this.defaultConfig.cart_contains_subscription) { + const saveToAccount = document.querySelector('#wc-ppcp-credit-card-gateway-new-payment-method'); + if(saveToAccount) { + saveToAccount.checked = true; + saveToAccount.disabled = true; + } + } + document.querySelector(buttonSelector).addEventListener("click", (event) => { event.preventDefault(); this.spinner.block(); this.errorHandler.clear(); + const paymentToken = document.querySelector('input[name="wc-ppcp-credit-card-gateway-payment-token"]:checked')?.value + if(paymentToken && paymentToken !== 'new') { + document.querySelector('#place_order').click(); + return; + } + + if (typeof this.onCardFieldsBeforeSubmit === 'function' && !this.onCardFieldsBeforeSubmit()) { + this.spinner.unblock(); + return; + } + cardField.submit() .catch((error) => { this.spinner.unblock(); console.error(error) this.errorHandler.message(this.defaultConfig.hosted_fields.labels.fields_not_valid); - }) + }); }); } - cardFieldStyles(field) { - const allowedProperties = [ - 'appearance', - 'color', - 'direction', - 'font', - 'font-family', - 'font-size', - 'font-size-adjust', - 'font-stretch', - 'font-style', - 'font-variant', - 'font-variant-alternates', - 'font-variant-caps', - 'font-variant-east-asian', - 'font-variant-ligatures', - 'font-variant-numeric', - 'font-weight', - 'letter-spacing', - 'line-height', - 'opacity', - 'outline', - 'padding', - 'padding-bottom', - 'padding-left', - 'padding-right', - 'padding-top', - 'text-shadow', - 'transition', - '-moz-appearance', - '-moz-osx-font-smoothing', - '-moz-tap-highlight-color', - '-moz-transition', - '-webkit-appearance', - '-webkit-osx-font-smoothing', - '-webkit-tap-highlight-color', - '-webkit-transition', - ]; - - const stylesRaw = window.getComputedStyle(field); - const styles = {}; - Object.values(stylesRaw).forEach((prop) => { - if (!stylesRaw[prop] || !allowedProperties.includes(prop)) { - return; - } - styles[prop] = '' + stylesRaw[prop]; - }); - - return styles; - } + disableFields() {} + enableFields() {} } export default CardFieldsRenderer; diff --git a/modules/ppcp-button/resources/js/modules/Renderer/MessageRenderer.js b/modules/ppcp-button/resources/js/modules/Renderer/MessageRenderer.js index b1261a466..489202e56 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/MessageRenderer.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/MessageRenderer.js @@ -15,9 +15,13 @@ class MessageRenderer { const options = { amount, - placement: this.config.placement, - style: this.config.style }; + if (this.config.placement) { + options.placement = this.config.placement; + } + if (this.config.style) { + options.style = this.config.style; + } // sometimes the element is destroyed while the options stay the same if (document.querySelector(this.config.wrapper).getAttribute('data-render-number') !== this.currentNumber.toString()) { diff --git a/modules/ppcp-button/services.php b/modules/ppcp-button/services.php index cae843039..6f781911b 100644 --- a/modules/ppcp-button/services.php +++ b/modules/ppcp-button/services.php @@ -119,7 +119,7 @@ return array( $request_data = $container->get( 'button.request-data' ); $client_id = $container->get( 'button.client_id' ); $dcc_applies = $container->get( 'api.helpers.dccapplies' ); - $subscription_helper = $container->get( 'subscription.helper' ); + $subscription_helper = $container->get( 'wc-subscriptions.helper' ); $messages_apply = $container->get( 'button.helper.messages-apply' ); $environment = $container->get( 'onboarding.environment' ); $payment_token_repository = $container->get( 'vaulting.repository.payment-token' ); @@ -145,6 +145,8 @@ return array( $container->get( 'button.early-wc-checkout-validation-enabled' ), $container->get( 'button.pay-now-contexts' ), $container->get( 'wcgateway.funding-sources-without-redirect' ), + $container->get( 'vaulting.vault-v3-enabled' ), + $container->get( 'api.endpoint.payment-tokens' ), $container->get( 'woocommerce.logger.woocommerce' ) ); }, @@ -294,8 +296,10 @@ return array( }, 'button.helper.three-d-secure' => static function ( ContainerInterface $container ): ThreeDSecure { - $logger = $container->get( 'woocommerce.logger.woocommerce' ); - return new ThreeDSecure( $logger ); + return new ThreeDSecure( + $container->get( 'api.factory.card-authentication-result-factory' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); }, 'button.helper.messages-apply' => static function ( ContainerInterface $container ): MessagesApply { return new MessagesApply( diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 1d1ab5ce6..83b8a3c3c 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -14,6 +14,7 @@ use Psr\Log\LoggerInterface; use WC_Order; use WC_Product; use WC_Product_Variation; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\Money; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; @@ -32,9 +33,13 @@ use WooCommerce\PayPalCommerce\Button\Endpoint\ValidateCheckoutEndpoint; use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait; use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply; use WooCommerce\PayPalCommerce\Onboarding\Environment; +use WooCommerce\PayPalCommerce\PayLaterBlock\PayLaterBlockModule; +use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken; +use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken; +use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentTokenForGuest; use WooCommerce\PayPalCommerce\Session\SessionHandler; -use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; @@ -183,13 +188,6 @@ class SmartButton implements SmartButtonInterface { */ private $funding_sources_without_redirect; - /** - * The logger. - * - * @var LoggerInterface - */ - private $logger; - /** * Session handler. * @@ -197,6 +195,27 @@ class SmartButton implements SmartButtonInterface { */ private $session_handler; + /** + * Whether Vault v3 module is enabled. + * + * @var bool + */ + private $vault_v3_enabled; + + /** + * Payment tokens endpoint. + * + * @var PaymentTokensEndpoint + */ + private $payment_tokens_endpoint; + + /** + * The logger. + * + * @var LoggerInterface + */ + private $logger; + /** * SmartButton constructor. * @@ -219,6 +238,8 @@ class SmartButton implements SmartButtonInterface { * @param bool $early_validation_enabled Whether to execute WC validation of the checkout form. * @param array $pay_now_contexts The contexts that should have the Pay Now button. * @param string[] $funding_sources_without_redirect The sources that do not cause issues about redirecting (on mobile, ...) and sometimes not returning back. + * @param bool $vault_v3_enabled Whether Vault v3 module is enabled. + * @param PaymentTokensEndpoint $payment_tokens_endpoint Payment tokens endpoint. * @param LoggerInterface $logger The logger. */ public function __construct( @@ -241,6 +262,8 @@ class SmartButton implements SmartButtonInterface { bool $early_validation_enabled, array $pay_now_contexts, array $funding_sources_without_redirect, + bool $vault_v3_enabled, + PaymentTokensEndpoint $payment_tokens_endpoint, LoggerInterface $logger ) { @@ -263,7 +286,9 @@ class SmartButton implements SmartButtonInterface { $this->early_validation_enabled = $early_validation_enabled; $this->pay_now_contexts = $pay_now_contexts; $this->funding_sources_without_redirect = $funding_sources_without_redirect; + $this->vault_v3_enabled = $vault_v3_enabled; $this->logger = $logger; + $this->payment_tokens_endpoint = $payment_tokens_endpoint; } /** @@ -272,6 +297,8 @@ class SmartButton implements SmartButtonInterface { * @return bool */ public function render_wrapper(): bool { + $this->init_context(); + if ( $this->settings->has( 'enabled' ) && $this->settings->get( 'enabled' ) ) { $this->render_button_wrapper_registrar(); $this->render_message_wrapper_registrar(); @@ -303,7 +330,13 @@ class SmartButton implements SmartButtonInterface { add_filter( 'woocommerce_credit_card_form_fields', function ( array $default_fields, $id ) use ( $subscription_helper ) : array { - if ( is_user_logged_in() && $this->settings->has( 'vault_enabled_dcc' ) && $this->settings->get( 'vault_enabled_dcc' ) && CreditCardGateway::ID === $id ) { + if ( + is_user_logged_in() + && $this->settings->has( 'vault_enabled_dcc' ) + && $this->settings->get( 'vault_enabled_dcc' ) + && CreditCardGateway::ID === $id + && apply_filters( 'woocommerce_paypal_payments_should_render_card_custom_fields', true ) + ) { $default_fields['card-vault'] = sprintf( '

', @@ -385,7 +418,7 @@ class SmartButton implements SmartButtonInterface { * @return bool */ private function render_message_wrapper_registrar(): bool { - if ( ! $this->settings_status->is_pay_later_messaging_enabled() ) { + if ( ! $this->settings_status->is_pay_later_messaging_enabled() || ! $this->settings_status->has_pay_later_messaging_locations() ) { return false; } @@ -597,7 +630,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages case 'product': return $smart_button_enabled_for_current_location || $smart_button_enabled_for_mini_cart; default: - return $smart_button_enabled_for_mini_cart; + return $smart_button_enabled_for_mini_cart || $this->is_block_editor(); } } @@ -610,6 +643,10 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages return false; } + if ( ! $this->settings_status->is_pay_later_messaging_enabled() ) { + return false; + } + if ( ! $this->messages_apply->for_country() || $this->is_free_trial_cart() ) { return false; } @@ -618,6 +655,8 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages $messaging_enabled_for_current_location = $this->settings_status->is_pay_later_messaging_enabled_for_location( $location ); + $has_paylater_block = has_block( 'woocommerce-paypal-payments/paylater-messages' ) && PayLaterBlockModule::is_block_enabled( $this->settings_status ); + switch ( $location ) { case 'checkout': case 'cart': @@ -626,8 +665,13 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages case 'shop': case 'home': return $messaging_enabled_for_current_location; + case 'block-editor': + return true; + case 'checkout-block': + case 'cart-block': + return $has_paylater_block || $this->is_block_editor(); default: - return false; + return $has_paylater_block; } } @@ -638,7 +682,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages return $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) && $this->settings->has( 'client_id' ) && $this->settings->get( 'client_id' ) && $this->dcc_applies->for_country_currency() - && in_array( $this->context(), array( 'checkout', 'pay-now' ), true ); + && in_array( $this->context(), array( 'checkout', 'pay-now', 'add-payment-method' ), true ); } /** @@ -835,9 +879,10 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages } $product = wc_get_product(); - $amount = ( is_a( $product, WC_Product::class ) ) ? wc_get_price_including_tax( $product ) : 0; - - if ( is_checkout() || is_cart() ) { + $amount = 0; + if ( is_a( $product, WC_Product::class ) ) { + $amount = wc_get_price_including_tax( $product ); + } elseif ( isset( WC()->cart ) ) { $amount = WC()->cart->get_total( 'raw' ); } @@ -851,10 +896,14 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages $text_color = $this->settings->has( "{$setting_name_prefix}_color" ) ? $this->settings->get( "{$setting_name_prefix}_color" ) : 'black'; $style_color = $this->settings->has( "{$setting_name_prefix}_flex_color" ) ? $this->settings->get( "{$setting_name_prefix}_flex_color" ) : 'blue'; $ratio = $this->settings->has( "{$setting_name_prefix}_flex_ratio" ) ? $this->settings->get( "{$setting_name_prefix}_flex_ratio" ) : '1x1'; + $text_size = $this->settings->has( "{$setting_name_prefix}_text_size" ) ? $this->settings->get( "{$setting_name_prefix}_text_size" ) : '12'; return array( 'wrapper' => '#ppcp-messages', 'is_hidden' => ! $this->is_pay_later_filter_enabled_for_location( $this->context() ), + 'block' => array( + 'enabled' => PayLaterBlockModule::is_block_enabled( $this->settings_status ), + ), 'amount' => $amount, 'placement' => $placement, 'style' => array( @@ -865,12 +914,12 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages ), 'text' => array( 'color' => $text_color, + 'size' => $text_size, ), 'color' => $style_color, 'ratio' => $ratio, ), ); - } /** @@ -925,7 +974,10 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages * @return bool */ private function has_subscriptions(): bool { - if ( ! $this->subscription_helper->accept_only_automatic_payment_gateways() ) { + if ( + ! $this->subscription_helper->accept_only_automatic_payment_gateways() + && $this->paypal_subscriptions_enabled() !== true + ) { return false; } if ( is_product() ) { @@ -962,11 +1014,21 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages if ( $this->settings->has( '3d_secure_contingency' ) ) { $value = $this->settings->get( '3d_secure_contingency' ); if ( $value ) { - return $value; + return $this->return_3ds_contingency( $value ); } } - return 'SCA_WHEN_REQUIRED'; + return $this->return_3ds_contingency( 'SCA_WHEN_REQUIRED' ); + } + + /** + * Processes and returns the 3D Secure contingency. + * + * @param string $contingency The ThreeD secure contingency. + * @return string + */ + private function return_3ds_contingency( string $contingency ): string { + return apply_filters( 'woocommerce_paypal_payments_three_d_secure_contingency', $contingency ); } /** @@ -997,44 +1059,59 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages 'redirect' => wc_get_checkout_url(), 'context' => $this->context(), 'ajax' => array( - 'simulate_cart' => array( + 'simulate_cart' => array( 'endpoint' => \WC_AJAX::get_endpoint( SimulateCartEndpoint::ENDPOINT ), 'nonce' => wp_create_nonce( SimulateCartEndpoint::nonce() ), ), - 'change_cart' => array( + 'change_cart' => array( 'endpoint' => \WC_AJAX::get_endpoint( ChangeCartEndpoint::ENDPOINT ), 'nonce' => wp_create_nonce( ChangeCartEndpoint::nonce() ), ), - 'create_order' => array( + 'create_order' => array( 'endpoint' => \WC_AJAX::get_endpoint( CreateOrderEndpoint::ENDPOINT ), 'nonce' => wp_create_nonce( CreateOrderEndpoint::nonce() ), ), - 'approve_order' => array( + 'approve_order' => array( 'endpoint' => \WC_AJAX::get_endpoint( ApproveOrderEndpoint::ENDPOINT ), 'nonce' => wp_create_nonce( ApproveOrderEndpoint::nonce() ), ), - 'approve_subscription' => array( + 'approve_subscription' => array( 'endpoint' => \WC_AJAX::get_endpoint( ApproveSubscriptionEndpoint::ENDPOINT ), 'nonce' => wp_create_nonce( ApproveSubscriptionEndpoint::nonce() ), ), - 'vault_paypal' => array( + 'vault_paypal' => array( 'endpoint' => \WC_AJAX::get_endpoint( StartPayPalVaultingEndpoint::ENDPOINT ), 'nonce' => wp_create_nonce( StartPayPalVaultingEndpoint::nonce() ), ), - 'save_checkout_form' => array( + 'save_checkout_form' => array( 'endpoint' => \WC_AJAX::get_endpoint( SaveCheckoutFormEndpoint::ENDPOINT ), 'nonce' => wp_create_nonce( SaveCheckoutFormEndpoint::nonce() ), ), - 'validate_checkout' => array( + 'validate_checkout' => array( 'endpoint' => \WC_AJAX::get_endpoint( ValidateCheckoutEndpoint::ENDPOINT ), 'nonce' => wp_create_nonce( ValidateCheckoutEndpoint::nonce() ), ), - 'cart_script_params' => array( + 'cart_script_params' => array( 'endpoint' => \WC_AJAX::get_endpoint( CartScriptParamsEndpoint::ENDPOINT ), ), + 'create_setup_token' => array( + 'endpoint' => \WC_AJAX::get_endpoint( CreateSetupToken::ENDPOINT ), + 'nonce' => wp_create_nonce( CreateSetupToken::nonce() ), + ), + 'create_payment_token' => array( + 'endpoint' => \WC_AJAX::get_endpoint( CreatePaymentToken::ENDPOINT ), + 'nonce' => wp_create_nonce( CreatePaymentToken::nonce() ), + ), + 'create_payment_token_for_guest' => array( + 'endpoint' => \WC_AJAX::get_endpoint( CreatePaymentTokenForGuest::ENDPOINT ), + 'nonce' => wp_create_nonce( CreatePaymentTokenForGuest::nonce() ), + ), ), + 'cart_contains_subscription' => $this->subscription_helper->cart_contains_subscription(), 'subscription_plan_id' => $this->subscription_helper->paypal_subscription_id(), + 'vault_v3_enabled' => $this->vault_v3_enabled, 'variable_paypal_subscription_variations' => $this->subscription_helper->variable_paypal_subscription_variations(), + 'variable_paypal_subscription_variation_from_cart' => $this->subscription_helper->paypal_subscription_variation_from_cart(), 'subscription_product_allowed' => $this->subscription_helper->checkout_subscription_product_allowed(), 'locations_with_subscription_product' => $this->subscription_helper->locations_with_subscription_product(), 'enforce_vault' => $this->has_subscriptions(), @@ -1146,6 +1223,9 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages 'basic_checkout_validation_enabled' => $this->basic_checkout_validation_enabled, 'early_checkout_validation_enabled' => $this->early_validation_enabled, 'funding_sources_without_redirect' => $this->funding_sources_without_redirect, + 'user' => array( + 'is_logged' => is_user_logged_in(), + ), ); if ( 'pay-now' === $this->context() ) { @@ -1162,7 +1242,8 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages } $this->request_data->dequeue_nonce_fix(); - return $localize; + + return apply_filters( 'woocommerce_paypal_payments_localized_script_data', $localize ); } /** @@ -1228,6 +1309,16 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages 'commit' => in_array( $context, $this->pay_now_contexts, true ) ? 'true' : 'false', 'intent' => $intent, ); + + if ( + $this->settings->has( 'subscriptions_mode' ) + && $this->settings->get( 'subscriptions_mode' ) === 'vaulting_api' + && apply_filters( 'woocommerce_paypal_payments_save_payment_methods_eligible', false ) + ) { + // Remove vault parameter to allow for Venmo with Save Payment Methods (Vault V3). + unset( $params['vault'] ); + } + if ( $this->environment->current_environment_is( Environment::SANDBOX ) && defined( 'WP_DEBUG' ) && \WP_DEBUG @@ -1275,7 +1366,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages $disable_funding, array_diff( array_keys( $this->all_funding_sources ), - array( 'venmo', 'paylater' ) + array( 'venmo', 'paylater', 'paypal' ) ) ); } @@ -1296,6 +1387,20 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages $disable_funding[] = 'paylater'; } + $disable_funding = array_filter( + $disable_funding, + /** + * Make sure paypal is not sent in disable funding. + * + * @param string $funding_source The funding_source. + * + * @psalm-suppress MissingClosureParamType + */ + function( $funding_source ) { + return $funding_source !== 'paypal'; + } + ); + if ( count( $disable_funding ) > 0 ) { $params['disable-funding'] = implode( ',', array_unique( $disable_funding ) ); } @@ -1438,8 +1543,8 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages $context = 'general'; } - return $this->get_style_value( "button_{$context}_${style}" ) - ?? $this->get_style_value( "button_${style}" ) + return $this->get_style_value( "button_{$context}_{$style}" ) + ?? $this->get_style_value( "button_{$style}" ) ?? ( $default ? $this->normalize_style_value( $default ) : null ) ?? $this->normalize_style_value( $defaults[ $style ] ?? '' ); } @@ -1454,7 +1559,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages * @return string|int */ private function style_for_apm( string $style, string $apm, $default = null ) { - return $this->get_style_value( "${apm}_button_${style}" ) + return $this->get_style_value( "{$apm}_button_{$style}" ) ?? ( $default ? $this->normalize_style_value( $default ) : null ) ?? $this->style_for_context( $style, 'checkout' ); } @@ -1575,14 +1680,14 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages * The filter returning the action name that will be used for rendering Pay Later messages. */ $hook = (string) apply_filters( - "woocommerce_paypal_payments_${location_hook}_messages_renderer_hook", + "woocommerce_paypal_payments_{$location_hook}_messages_renderer_hook", $default_hook ); /** * The filter returning the action priority that will be used for rendering Pay Later messages. */ $priority = (int) apply_filters( - "woocommerce_paypal_payments_${location_hook}_messages_renderer_priority", + "woocommerce_paypal_payments_{$location_hook}_messages_renderer_priority", $default_priority ); return array( @@ -1606,14 +1711,14 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages * The filter returning the action name that will be used for rendering Pay Later messages. */ $block_name = (string) apply_filters( - "woocommerce_paypal_payments_${location_hook}_messages_renderer_block", + "woocommerce_paypal_payments_{$location_hook}_messages_renderer_block", $default_block ); /** * The filter returning the action priority that will be used for rendering Pay Later messages. */ $priority = (int) apply_filters( - "woocommerce_paypal_payments_${location_hook}_messages_renderer_block_priority", + "woocommerce_paypal_payments_{$location_hook}_messages_renderer_block_priority", $default_priority ); return array( @@ -1837,8 +1942,18 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages */ private function get_vaulted_paypal_email(): string { try { - $tokens = $this->get_payment_tokens(); + $customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true ); + if ( $customer_id ) { + $customer_tokens = $this->payment_tokens_endpoint->payment_tokens_for_customer( $customer_id ); + foreach ( $customer_tokens as $token ) { + $email_address = $token['payment_source']->properties()->email_address ?? ''; + if ( $email_address ) { + return $email_address; + } + } + } + $tokens = $this->get_payment_tokens(); foreach ( $tokens as $token ) { if ( isset( $token->source()->paypal ) ) { return $token->source()->paypal->payer->email_address; @@ -1847,6 +1962,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages } catch ( Exception $exception ) { $this->logger->error( 'Failed to get PayPal vaulted email. ' . $exception->getMessage() ); } + return ''; } diff --git a/modules/ppcp-button/src/Endpoint/ApproveOrderEndpoint.php b/modules/ppcp-button/src/Endpoint/ApproveOrderEndpoint.php index 7e4f7c4ee..e33ab3b69 100644 --- a/modules/ppcp-button/src/Endpoint/ApproveOrderEndpoint.php +++ b/modules/ppcp-button/src/Endpoint/ApproveOrderEndpoint.php @@ -14,6 +14,7 @@ use Exception; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; +use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies; use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderHelper; @@ -144,10 +145,11 @@ class ApproveOrderEndpoint implements EndpointInterface { $order = $this->api_endpoint->order( $data['order_id'] ); - if ( $order->payment_source() && $order->payment_source()->card() ) { + $payment_source = $order->payment_source(); + if ( $payment_source && $payment_source->name() === 'card' ) { if ( $this->settings->has( 'disable_cards' ) ) { $disabled_cards = (array) $this->settings->get( 'disable_cards' ); - $card = strtolower( $order->payment_source()->card()->brand() ); + $card = strtolower( $payment_source->properties()->brand ?? '' ); if ( 'master_card' === $card ) { $card = 'mastercard'; } diff --git a/modules/ppcp-button/src/Endpoint/CartScriptParamsEndpoint.php b/modules/ppcp-button/src/Endpoint/CartScriptParamsEndpoint.php index 316d2c000..70309d907 100644 --- a/modules/ppcp-button/src/Endpoint/CartScriptParamsEndpoint.php +++ b/modules/ppcp-button/src/Endpoint/CartScriptParamsEndpoint.php @@ -13,6 +13,7 @@ use Psr\Log\LoggerInterface; use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Entity\Money; use WooCommerce\PayPalCommerce\Button\Assets\SmartButton; +use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; /** * Class CartScriptParamsEndpoint. @@ -25,7 +26,7 @@ class CartScriptParamsEndpoint implements EndpointInterface { /** * The SmartButton. * - * @var SmartButton + * @var SmartButtonInterface */ private $smart_button; @@ -39,11 +40,11 @@ class CartScriptParamsEndpoint implements EndpointInterface { /** * CartScriptParamsEndpoint constructor. * - * @param SmartButton $smart_button he SmartButton. - * @param LoggerInterface $logger The logger. + * @param SmartButtonInterface $smart_button he SmartButton. + * @param LoggerInterface $logger The logger. */ public function __construct( - SmartButton $smart_button, + SmartButtonInterface $smart_button, LoggerInterface $logger ) { $this->smart_button = $smart_button; @@ -66,6 +67,11 @@ class CartScriptParamsEndpoint implements EndpointInterface { */ public function handle_request(): bool { try { + if ( ! $this->smart_button instanceof SmartButton ) { + wp_send_json_error(); + return false; + } + if ( is_callable( 'wc_maybe_define_constant' ) ) { wc_maybe_define_constant( 'WOOCOMMERCE_CART', true ); } @@ -73,6 +79,10 @@ class CartScriptParamsEndpoint implements EndpointInterface { $include_shipping = (bool) wc_clean( wp_unslash( $_GET['shipping'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended $script_data = $this->smart_button->script_data(); + if ( ! $script_data ) { + wp_send_json_error(); + return false; + } $total = (float) WC()->cart->get_total( 'numeric' ); diff --git a/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php b/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php index 4ee88c3c7..1ef06c3be 100644 --- a/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php +++ b/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php @@ -25,12 +25,11 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory; -use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderTransient; use WooCommerce\PayPalCommerce\Button\Exception\ValidationException; use WooCommerce\PayPalCommerce\Button\Validation\CheckoutFormValidator; use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler; use WooCommerce\PayPalCommerce\Session\SessionHandler; -use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; use WooCommerce\PayPalCommerce\WcGateway\CardBillingMode; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; @@ -295,7 +294,7 @@ class CreateOrderEndpoint implements EndpointInterface { if ( $this->early_validation_enabled && $this->form && 'checkout' === $data['context'] - && in_array( $payment_method, array( PayPalGateway::ID, CardButtonGateway::ID ), true ) + && in_array( $payment_method, array( PayPalGateway::ID, CardButtonGateway::ID, CreditCardGateway::ID ), true ) ) { $this->validate_form( $this->form ); } @@ -305,7 +304,7 @@ class CreateOrderEndpoint implements EndpointInterface { } try { - $order = $this->create_paypal_order( $wc_order ); + $order = $this->create_paypal_order( $wc_order, $payment_method, $data ); } catch ( Exception $exception ) { $this->logger->error( 'Order creation failed: ' . $exception->getMessage() ); throw $exception; @@ -330,6 +329,21 @@ class CreateOrderEndpoint implements EndpointInterface { if ( 'pay-now' === $data['context'] && is_a( $wc_order, \WC_Order::class ) ) { $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $order->id() ); $wc_order->update_meta_data( PayPalGateway::INTENT_META_KEY, $order->intent() ); + + $payment_source = $order->payment_source(); + $payment_source_name = $payment_source ? $payment_source->name() : null; + $payer = $order->payer(); + if ( + $payer + && $payment_source_name + && in_array( $payment_source_name, PayPalGateway::PAYMENT_SOURCES_WITH_PAYER_EMAIL, true ) + ) { + $payer_email = $payer->email_address(); + if ( $payer_email ) { + $wc_order->update_meta_data( PayPalGateway::ORDER_PAYER_EMAIL_META_KEY, $payer_email ); + } + } + $wc_order->save_meta_data(); do_action( 'woocommerce_paypal_payments_woocommerce_order_created', $wc_order, $order ); @@ -416,14 +430,17 @@ class CreateOrderEndpoint implements EndpointInterface { * Creates the order in the PayPal, uses data from WC order if provided. * * @param \WC_Order|null $wc_order WC order to get data from. + * @param string $payment_method WC payment method. + * @param array $data Request data. * * @return Order Created PayPal order. * * @throws RuntimeException If create order request fails. * @throws PayPalApiException If create order request fails. + * * phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber */ - private function create_paypal_order( \WC_Order $wc_order = null ): Order { + private function create_paypal_order( \WC_Order $wc_order = null, string $payment_method = '', array $data = array() ): Order { assert( $this->purchase_unit instanceof PurchaseUnit ); $funding_source = $this->parsed_request_data['funding_source'] ?? ''; @@ -465,7 +482,9 @@ class CreateOrderEndpoint implements EndpointInterface { $payer, null, '', - $action + $action, + $payment_method, + $data ); } catch ( PayPalApiException $exception ) { // Looks like currently there is no proper way to validate the shipping address for PayPal, diff --git a/modules/ppcp-button/src/Endpoint/SimulateCartEndpoint.php b/modules/ppcp-button/src/Endpoint/SimulateCartEndpoint.php index 1040cc680..36069e463 100644 --- a/modules/ppcp-button/src/Endpoint/SimulateCartEndpoint.php +++ b/modules/ppcp-button/src/Endpoint/SimulateCartEndpoint.php @@ -13,6 +13,7 @@ use Exception; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\ApiClient\Entity\Money; use WooCommerce\PayPalCommerce\Button\Assets\SmartButton; +use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface; use WooCommerce\PayPalCommerce\Button\Helper\CartProductsHelper; /** @@ -25,7 +26,7 @@ class SimulateCartEndpoint extends AbstractCartEndpoint { /** * The SmartButton. * - * @var SmartButton + * @var SmartButtonInterface */ private $smart_button; @@ -39,14 +40,14 @@ class SimulateCartEndpoint extends AbstractCartEndpoint { /** * ChangeCartEndpoint constructor. * - * @param SmartButton $smart_button The SmartButton. - * @param \WC_Cart $cart The current WC cart object. - * @param RequestData $request_data The request data helper. - * @param CartProductsHelper $cart_products The cart products helper. - * @param LoggerInterface $logger The logger. + * @param SmartButtonInterface $smart_button The SmartButton. + * @param \WC_Cart $cart The current WC cart object. + * @param RequestData $request_data The request data helper. + * @param CartProductsHelper $cart_products The cart products helper. + * @param LoggerInterface $logger The logger. */ public function __construct( - SmartButton $smart_button, + SmartButtonInterface $smart_button, \WC_Cart $cart, RequestData $request_data, CartProductsHelper $cart_products, @@ -68,6 +69,11 @@ class SimulateCartEndpoint extends AbstractCartEndpoint { * @throws Exception On error. */ protected function handle_data(): bool { + if ( ! $this->smart_button instanceof SmartButton ) { + wp_send_json_error(); + return false; + } + $products = $this->products_from_request(); if ( ! $products ) { diff --git a/modules/ppcp-button/src/Helper/ContextTrait.php b/modules/ppcp-button/src/Helper/ContextTrait.php index db6735424..9b5874bfa 100644 --- a/modules/ppcp-button/src/Helper/ContextTrait.php +++ b/modules/ppcp-button/src/Helper/ContextTrait.php @@ -12,6 +12,39 @@ namespace WooCommerce\PayPalCommerce\Button\Helper; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; trait ContextTrait { + /** + * Initializes context preconditions like is_cart() and is_checkout(). + * + * @return void + */ + protected function init_context(): void { + if ( ! apply_filters( 'woocommerce_paypal_payments_block_classic_compat', true ) ) { + return; + } + + /** + * Activate is_checkout() on woocommerce/classic-shortcode checkout blocks. + * + * @psalm-suppress MissingClosureParamType + */ + add_filter( + 'woocommerce_is_checkout', + function ( $is_checkout ) { + if ( $is_checkout ) { + return $is_checkout; + } + return has_block( 'woocommerce/classic-shortcode {"shortcode":"checkout"}' ); + } + ); + + // Activate is_cart() on woocommerce/classic-shortcode cart blocks. + if ( ! is_cart() && is_callable( 'wc_maybe_define_constant' ) ) { + if ( has_block( 'woocommerce/classic-shortcode' ) && ! has_block( 'woocommerce/classic-shortcode {"shortcode":"checkout"}' ) ) { + wc_maybe_define_constant( 'WOOCOMMERCE_CART', true ); + } + } + } + /** * Checks WC is_checkout() + WC checkout ajax requests. */ @@ -94,6 +127,14 @@ trait ContextTrait { return 'checkout'; } + if ( $this->is_add_payment_method_page() ) { + return 'add-payment-method'; + } + + if ( $this->is_block_editor() ) { + return 'block-editor'; + } + return 'mini-cart'; } @@ -125,6 +166,11 @@ trait ContextTrait { * @return bool */ private function is_paypal_continuation(): bool { + /** + * Property is already defined in trait consumers. + * + * @psalm-suppress UndefinedThisPropertyFetch + */ $order = $this->session_handler->order(); if ( ! $order ) { return false; @@ -137,7 +183,7 @@ trait ContextTrait { } $source = $order->payment_source(); - if ( $source && $source->card() ) { + if ( $source && $source->name() === 'card' ) { return false; // Ignore for DCC. } @@ -147,4 +193,46 @@ trait ContextTrait { return true; } + + /** + * Checks whether current page is Add payment method. + * + * @return bool + */ + private function is_add_payment_method_page(): bool { + /** + * Needed for WordPress `query_vars`. + * + * @psalm-suppress InvalidGlobal + */ + global $wp; + + $page_id = wc_get_page_id( 'myaccount' ); + + return $page_id && is_page( $page_id ) && isset( $wp->query_vars['add-payment-method'] ); + } + + /** + * Checks whether this user is changing the payment method for a subscription. + * + * @return bool + */ + private function is_subscription_change_payment_method_page(): bool { + if ( isset( $_GET['change_payment_method'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification + return wcs_is_subscription( wc_clean( wp_unslash( $_GET['change_payment_method'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification + } + + return false; + } + + /** + * Checks if it is the block editor page. + */ + protected function is_block_editor(): bool { + if ( ! function_exists( 'get_current_screen' ) ) { + return false; + } + $screen = get_current_screen(); + return $screen && $screen->is_block_editor(); + } } diff --git a/modules/ppcp-button/src/Helper/EarlyOrderHandler.php b/modules/ppcp-button/src/Helper/EarlyOrderHandler.php index 03d8fbeed..46b4ddf41 100644 --- a/modules/ppcp-button/src/Helper/EarlyOrderHandler.php +++ b/modules/ppcp-button/src/Helper/EarlyOrderHandler.php @@ -159,6 +159,22 @@ class EarlyOrderHandler { $wc_order = wc_get_order( $order_id ); $wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $order->id() ); $wc_order->update_meta_data( PayPalGateway::INTENT_META_KEY, $order->intent() ); + + $payment_source = $order->payment_source(); + $payment_source_name = $payment_source ? $payment_source->name() : null; + $payer = $order->payer(); + if ( + $payer + && $payment_source_name + && in_array( $payment_source_name, PayPalGateway::PAYMENT_SOURCES_WITH_PAYER_EMAIL, true ) + && $wc_order instanceof \WC_Order + ) { + $payer_email = $payer->email_address(); + if ( $payer_email ) { + $wc_order->update_meta_data( PayPalGateway::ORDER_PAYER_EMAIL_META_KEY, $payer_email ); + } + } + $wc_order->save_meta_data(); /** diff --git a/modules/ppcp-button/src/Helper/ThreeDSecure.php b/modules/ppcp-button/src/Helper/ThreeDSecure.php index e2d8b9e49..1991112b5 100644 --- a/modules/ppcp-button/src/Helper/ThreeDSecure.php +++ b/modules/ppcp-button/src/Helper/ThreeDSecure.php @@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\Button\Helper; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult as AuthResult; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; +use WooCommerce\PayPalCommerce\ApiClient\Factory\CardAuthenticationResultFactory; /** * Class ThreeDSecure @@ -23,6 +24,13 @@ class ThreeDSecure { const REJECT = 2; const RETRY = 3; + /** + * Card authentication result factory. + * + * @var CardAuthenticationResultFactory + */ + private $card_authentication_result_factory; + /** * The logger. * @@ -33,10 +41,15 @@ class ThreeDSecure { /** * ThreeDSecure constructor. * - * @param LoggerInterface $logger The logger. + * @param CardAuthenticationResultFactory $card_authentication_result_factory Card authentication result factory. + * @param LoggerInterface $logger The logger. */ - public function __construct( LoggerInterface $logger ) { - $this->logger = $logger; + public function __construct( + CardAuthenticationResultFactory $card_authentication_result_factory, + LoggerInterface $logger + ) { + $this->logger = $logger; + $this->card_authentication_result_factory = $card_authentication_result_factory; } /** @@ -44,35 +57,58 @@ class ThreeDSecure { * * @link https://developer.paypal.com/docs/business/checkout/add-capabilities/3d-secure/#authenticationresult * - * @param Order $order The order for which the decission is needed. + * @param Order $order The order for which the decision is needed. * * @return int */ public function proceed_with_order( Order $order ): int { - if ( ! $order->payment_source() ) { - return self::NO_DECISION; - } - if ( ! $order->payment_source()->card() ) { - return self::NO_DECISION; - } - if ( ! $order->payment_source()->card()->authentication_result() ) { - return self::NO_DECISION; + + do_action( 'woocommerce_paypal_payments_three_d_secure_before_check', $order ); + + $payment_source = $order->payment_source(); + if ( ! $payment_source ) { + return $this->return_decision( self::NO_DECISION, $order ); } - $result = $order->payment_source()->card()->authentication_result(); - $this->logger->info( '3DS authentication result: ' . wc_print_r( $result->to_array(), true ) ); - - if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_POSSIBLE ) { - return self::PROCCEED; + if ( ! ( $payment_source->properties()->brand ?? '' ) ) { + return $this->return_decision( self::NO_DECISION, $order ); + } + if ( ! ( $payment_source->properties()->authentication_result ?? '' ) ) { + return $this->return_decision( self::NO_DECISION, $order ); } - if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_UNKNOWN ) { - return self::RETRY; + $authentication_result = $payment_source->properties()->authentication_result ?? null; + if ( $authentication_result ) { + $result = $this->card_authentication_result_factory->from_paypal_response( $authentication_result ); + + $this->logger->info( '3DS Authentication Result: ' . wc_print_r( $result->to_array(), true ) ); + + if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_POSSIBLE ) { + return $this->return_decision( self::PROCCEED, $order ); + } + + if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_UNKNOWN ) { + return $this->return_decision( self::RETRY, $order ); + } + if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_NO ) { + return $this->return_decision( $this->no_liability_shift( $result ), $order ); + } } - if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_NO ) { - return $this->no_liability_shift( $result ); - } - return self::NO_DECISION; + + return $this->return_decision( self::NO_DECISION, $order ); + } + + /** + * Processes and returns a ThreeD secure decision. + * + * @param int $decision The ThreeD secure decision. + * @param Order $order The PayPal Order object. + * @return int + */ + public function return_decision( int $decision, Order $order ) { + $decision = apply_filters( 'woocommerce_paypal_payments_three_d_secure_decision', $decision, $order ); + do_action( 'woocommerce_paypal_payments_three_d_secure_after_check', $order, $decision ); + return $decision; } /** diff --git a/modules/ppcp-card-fields/services.php b/modules/ppcp-card-fields/services.php index b6c18d977..5374a1c48 100644 --- a/modules/ppcp-card-fields/services.php +++ b/modules/ppcp-card-fields/services.php @@ -30,6 +30,726 @@ return array( return apply_filters( 'woocommerce_paypal_payments_card_fields_supported_country_currency_matrix', array( + 'AU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'AT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'BE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'BG' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CA' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CY' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CZ' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'DK' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'EE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'FI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'FR' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'DE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'GR' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'HU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'IE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'IT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LV' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'MT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'NL' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'PL' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'PT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'RO' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SK' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'ES' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'GB' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), 'US' => array( 'AUD', 'CAD', @@ -38,6 +758,30 @@ return array( 'JPY', 'USD', ), + 'NO' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), ) ); }, diff --git a/modules/ppcp-card-fields/src/CardFieldsModule.php b/modules/ppcp-card-fields/src/CardFieldsModule.php index 4471485aa..6835108c3 100644 --- a/modules/ppcp-card-fields/src/CardFieldsModule.php +++ b/modules/ppcp-card-fields/src/CardFieldsModule.php @@ -39,6 +39,12 @@ class CardFieldsModule implements ModuleInterface { return; } + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + if ( ! $settings->has( 'dcc_enabled' ) || ! $settings->get( 'dcc_enabled' ) ) { + return; + } + /** * Param types removed to avoid third-party issues. * @@ -80,6 +86,17 @@ class CardFieldsModule implements ModuleInterface { array_unshift( $default_fields, $new_field ); } + if ( apply_filters( 'woocommerce_paypal_payments_card_fields_translate_card_number', true ) ) { + if ( isset( $default_fields['card-number-field'] ) ) { + // Replaces the default card number placeholder with a translatable one. + $default_fields['card-number-field'] = str_replace( + '•••• •••• •••• ••••', + esc_attr__( 'Card number', 'woocommerce-paypal-payments' ), + $default_fields['card-number-field'] + ); + } + } + return $default_fields; }, 10, @@ -89,20 +106,28 @@ class CardFieldsModule implements ModuleInterface { add_filter( 'ppcp_create_order_request_body_data', function( array $data ) use ( $c ): array { + // phpcs:ignore WordPress.Security.NonceVerification.Missing + $payment_method = wc_clean( wp_unslash( $_POST['payment_method'] ?? '' ) ); + if ( $payment_method !== CreditCardGateway::ID ) { + return $data; + } + $settings = $c->get( 'wcgateway.settings' ); assert( $settings instanceof Settings ); + $three_d_secure_contingency = + $settings->has( '3d_secure_contingency' ) + ? apply_filters( 'woocommerce_paypal_payments_three_d_secure_contingency', $settings->get( '3d_secure_contingency' ) ) + : ''; + if ( - $settings->has( '3d_secure_contingency' ) - && ( - $settings->get( '3d_secure_contingency' ) === 'SCA_ALWAYS' - || $settings->get( '3d_secure_contingency' ) === 'SCA_WHEN_REQUIRED' - ) + $three_d_secure_contingency === 'SCA_ALWAYS' + || $three_d_secure_contingency === 'SCA_WHEN_REQUIRED' ) { $data['payment_source']['card'] = array( 'attributes' => array( 'verification' => array( - 'method' => $settings->get( '3d_secure_contingency' ), + 'method' => $three_d_secure_contingency, ), ), ); diff --git a/modules/ppcp-compat/services.php b/modules/ppcp-compat/services.php index 9907a15c0..364686a84 100644 --- a/modules/ppcp-compat/services.php +++ b/modules/ppcp-compat/services.php @@ -27,7 +27,7 @@ return array( }, 'compat.ppec.subscriptions-handler' => static function ( ContainerInterface $container ) { - $ppcp_renewal_handler = $container->get( 'subscription.renewal-handler' ); + $ppcp_renewal_handler = $container->get( 'wc-subscriptions.renewal-handler' ); $gateway = $container->get( 'compat.ppec.mock-gateway' ); return new PPEC\SubscriptionsHandler( $ppcp_renewal_handler, $gateway ); diff --git a/modules/ppcp-compat/src/PPEC/PPECHelper.php b/modules/ppcp-compat/src/PPEC/PPECHelper.php index 791cb7a22..a01c5eea7 100644 --- a/modules/ppcp-compat/src/PPEC/PPECHelper.php +++ b/modules/ppcp-compat/src/PPEC/PPECHelper.php @@ -75,7 +75,7 @@ class PPECHelper { } global $wpdb; - if ( class_exists( OrderUtil::class ) && OrderUtil::custom_orders_table_usage_is_enabled() ) { + if ( class_exists( OrderUtil::class ) && OrderUtil::custom_orders_table_usage_is_enabled() && isset( $wpdb->wc_orders ) ) { $result = $wpdb->get_var( $wpdb->prepare( "SELECT 1 FROM {$wpdb->wc_orders} WHERE payment_method = %s", diff --git a/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php b/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php index 90e2b5493..217374007 100644 --- a/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php +++ b/modules/ppcp-compat/src/PPEC/SubscriptionsHandler.php @@ -11,7 +11,7 @@ namespace WooCommerce\PayPalCommerce\Compat\PPEC; use Automattic\WooCommerce\Utilities\OrderUtil; use stdClass; -use WooCommerce\PayPalCommerce\Subscription\RenewalHandler; +use WooCommerce\PayPalCommerce\WcSubscriptions\RenewalHandler; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken; /** diff --git a/modules/ppcp-googlepay/extensions.php b/modules/ppcp-googlepay/extensions.php index 1583e5c6e..fe915aba4 100644 --- a/modules/ppcp-googlepay/extensions.php +++ b/modules/ppcp-googlepay/extensions.php @@ -42,7 +42,7 @@ return array( // Connection tab fields. $fields = $insert_after( $fields, - 'ppcp_dcc_status', + 'ppcp_reference_transactions_status', array( 'googlepay_status' => array( 'title' => __( 'Google Pay Payments', 'woocommerce-paypal-payments' ), diff --git a/modules/ppcp-googlepay/resources/css/styles.scss b/modules/ppcp-googlepay/resources/css/styles.scss index 82755efd8..0747a2a91 100644 --- a/modules/ppcp-googlepay/resources/css/styles.scss +++ b/modules/ppcp-googlepay/resources/css/styles.scss @@ -1,45 +1,9 @@ .ppcp-button-googlepay { - margin: 7px 0; - overflow: hidden; min-height: 40px; - height: 45px; - - &.ppcp-button-pill { - border-radius: 50px; - } - - &.ppcp-button-minicart { - display: block; - height: 40px; - } } -.woocommerce-checkout { - .ppcp-button-googlepay { - margin-top: 0; - } -} - -.ppcp-has-googlepay-block { - - .wp-block-woocommerce-checkout { - .ppcp-button-googlepay { - margin: 0; - height: 48px; - } - } - - .wp-block-woocommerce-cart { - .ppcp-button-googlepay { - margin: 0; - height: 48px; - } - } - -} - -.wp-admin { - .ppcp-button-googlepay { - pointer-events: none; +.wp-block-woocommerce-checkout, .wp-block-woocommerce-cart { + .gpay-button { + min-width: 0 !important; } } diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 9197cd5a5..3331a4d49 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -3,10 +3,13 @@ import {setVisible} from '../../../ppcp-button/resources/js/modules/Helper/Hidin import {setEnabled} from '../../../ppcp-button/resources/js/modules/Helper/ButtonDisabler'; import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder"; import UpdatePaymentData from "./Helper/UpdatePaymentData"; +import {apmButtonsInit} from "../../../ppcp-button/resources/js/modules/Helper/ApmButtons"; class GooglepayButton { constructor(context, externalHandler, buttonConfig, ppcpConfig) { + apmButtonsInit(ppcpConfig); + this.isInitialized = false; this.context = context; diff --git a/modules/ppcp-googlepay/resources/js/boot-admin.js b/modules/ppcp-googlepay/resources/js/boot-admin.js index 577733b6b..3b971986f 100644 --- a/modules/ppcp-googlepay/resources/js/boot-admin.js +++ b/modules/ppcp-googlepay/resources/js/boot-admin.js @@ -67,7 +67,7 @@ import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/Wi buttonConfig.button.wrapper = selector; applyConfigOptions(buttonConfig); - const wrapperElement = `
`; + const wrapperElement = `
`; if (!jQuery(selector).length) { jQuery(ppcpConfig.button.wrapper).after(wrapperElement); diff --git a/modules/ppcp-googlepay/resources/js/boot-block.js b/modules/ppcp-googlepay/resources/js/boot-block.js index 69baf2d5e..bc117357a 100644 --- a/modules/ppcp-googlepay/resources/js/boot-block.js +++ b/modules/ppcp-googlepay/resources/js/boot-block.js @@ -24,13 +24,6 @@ const GooglePayComponent = () => { manager.init(); }; - useEffect(() => { - const bodyClass = 'ppcp-has-googlepay-block'; - if (!document.body.classList.contains(bodyClass)) { - document.body.classList.add(bodyClass); - } - }, []); - useEffect(() => { // Load GooglePay SDK loadCustomScript({ url: buttonConfig.sdk_url }).then(() => { @@ -51,7 +44,7 @@ const GooglePayComponent = () => { }, [paypalLoaded, googlePayLoaded]); return ( -
+
); } diff --git a/modules/ppcp-googlepay/resources/js/boot.js b/modules/ppcp-googlepay/resources/js/boot.js index 731f78d80..f90655d5c 100644 --- a/modules/ppcp-googlepay/resources/js/boot.js +++ b/modules/ppcp-googlepay/resources/js/boot.js @@ -21,6 +21,15 @@ import GooglepayManager from "./GooglepayManager"; } }); + // Use set timeout as it's unnecessary to refresh upon Minicart initial render. + setTimeout(() => { + jQuery(document.body).on('wc_fragments_loaded wc_fragments_refreshed', () => { + if (manager) { + manager.reinit(); + } + }); + }, 1000); + document.addEventListener( 'DOMContentLoaded', () => { diff --git a/modules/ppcp-googlepay/services.php b/modules/ppcp-googlepay/services.php index 4d1ef8986..f7e195821 100644 --- a/modules/ppcp-googlepay/services.php +++ b/modules/ppcp-googlepay/services.php @@ -90,8 +90,9 @@ return array( return apply_filters( 'woocommerce_paypal_payments_googlepay_supported_country_currency_matrix', array( - 'CA' => array( + 'AU' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -100,16 +101,22 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', 'USD', ), - 'GB' => array( + 'AT' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -118,16 +125,334 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'BE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'BG' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CA' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CY' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CZ' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'DK' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'EE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'FI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'FR' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'DE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'GR' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'HU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'IE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', 'USD', ), 'IT' => array( 'AUD', + 'BRL', 'CAD', 'CHF', 'CZK', @@ -136,12 +461,377 @@ return array( 'GBP', 'HKD', 'HUF', + 'ILS', 'JPY', + 'MXN', 'NOK', 'NZD', + 'PHP', 'PLN', 'SEK', 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LV' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'MT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'NO' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'NL' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'PL' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'PT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'RO' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SK' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'ES' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'GB' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', 'USD', ), 'US' => array( diff --git a/modules/ppcp-googlepay/src/Assets/Button.php b/modules/ppcp-googlepay/src/Assets/Button.php index df482c73f..15f16e381 100644 --- a/modules/ppcp-googlepay/src/Assets/Button.php +++ b/modules/ppcp-googlepay/src/Assets/Button.php @@ -311,7 +311,7 @@ class Button implements ButtonInterface { add_action( $render_placeholder, function () { - echo ''; + echo ''; }, 21 ); @@ -325,7 +325,7 @@ class Button implements ButtonInterface { */ private function googlepay_button(): void { ?> -
+
current_status ) { return $this->current_status; @@ -128,21 +134,32 @@ class ApmProductStatus { } // Check the seller status for the intended capability. + $has_capability = false; foreach ( $seller_status->products() as $product ) { if ( $product->name() !== 'PAYMENT_METHODS' ) { continue; } if ( in_array( self::CAPABILITY_NAME, $product->capabilities(), true ) ) { - // Capability found, persist status and return true. - $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); - $this->settings->persist(); - - $this->current_status = true; - return $this->current_status; + $has_capability = true; } } + foreach ( $seller_status->capabilities() as $capability ) { + if ( $capability->name() === self::CAPABILITY_NAME && $capability->status() === SellerStatusCapability::STATUS_ACTIVE ) { + $has_capability = true; + } + } + + if ( $has_capability ) { + // Capability found, persist status and return true. + $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED ); + $this->settings->persist(); + + $this->current_status = true; + return $this->current_status; + } + // Capability not found, persist status and return false. $this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED ); $this->settings->persist(); diff --git a/modules/ppcp-onboarding/resources/js/settings.js b/modules/ppcp-onboarding/resources/js/settings.js index 89d9a1054..0ef811e2d 100644 --- a/modules/ppcp-onboarding/resources/js/settings.js +++ b/modules/ppcp-onboarding/resources/js/settings.js @@ -359,6 +359,20 @@ document.addEventListener( ); } + const referenceTransactionsCheck = () => { + if ( + typeof PayPalCommerceGatewaySettings !== 'undefined' + && PayPalCommerceGatewaySettings.reference_transaction_enabled !== '1' + ) { + document.getElementById('ppcp-vault_enabled')?.setAttribute('disabled', 'disabled'); + + const description = document.getElementById('field-vault_enabled')?.getElementsByClassName('description')[0]; + if (description) { + description.innerHTML = PayPalCommerceGatewaySettings.vaulting_must_enable_advanced_wallet_message; + } + } + } + (() => { removeDisabledCardIcons('select[name="ppcp[disable_cards][]"]', 'select[name="ppcp[card_icons][]"]'); @@ -408,6 +422,8 @@ document.addEventListener( ); togglePayLaterMessageFields(); + + referenceTransactionsCheck() })(); } ) diff --git a/modules/ppcp-order-tracking/carriers.php b/modules/ppcp-order-tracking/carriers.php index 429f12a51..07f84a174 100644 --- a/modules/ppcp-order-tracking/carriers.php +++ b/modules/ppcp-order-tracking/carriers.php @@ -9,1585 +9,1607 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\OrderTracking; +if ( ! function_exists( 'WooCommerce\PayPalCommerce\OrderTracking\tr' ) ) { + /** + * Prevent strings of being added to the .pot file but still be translatable via "gettext_with_context" filter if necessary. + * + * @param string $text Text to translate. + * @param string $context Context information for the translators. + * @param string $domain Text domain. Unique identifier for retrieving translated strings. + * @return string Translated context string without pipe. + */ + function tr( string $text, string $context, string $domain ): string { + // We want to call "_x" with variable arguments so the text isn't added to generated .pot translation files. + return _x( + // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText + $text, + // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralContext + $context, + // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralDomain + $domain + ); + } +} + return (array) apply_filters( 'woocommerce_paypal_payments_tracking_carriers', array( 'global' => array( 'name' => 'Global', 'items' => array( - '99MINUTOS' => _x( '99minutos', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'A2B_BA' => _x( 'A2B Express Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ABCUSTOM_SFTP' => _x( 'AB Custom Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ACILOGISTIX' => _x( 'ACI Logistix', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ACOMMERCE' => _x( 'ACOMMERCE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ACTIVOS24_API' => _x( 'Activos24', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ADS' => _x( 'ADS Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AEROFLASH' => _x( 'AEROFLASH', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AGEDISS_SFTP' => _x( 'Agediss', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AIR_21' => _x( 'AIR 21', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AIRSPEED' => _x( 'AIRSPEED', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AIRTERRA' => _x( 'Airterra', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AITWORLDWIDE_API' => _x( 'AIT', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AITWORLDWIDE_SFTP' => _x( 'AIT', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ALLIED_EXPRESS_FTP' => _x( 'Allied Express (FTP)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ALLJOY' => _x( 'ALLJOY SUPPLY CHAIN', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AMAZON_EMAIL_PUSH' => _x( 'Amazon', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AMAZON_ORDER' => _x( 'Amazon order', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AMAZON_UK_API' => _x( 'amazon_uk_api', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AMS_GRP' => _x( 'AMS Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ANDREANI_API' => _x( 'Andreani', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ANTERAJA' => _x( 'Anteraja', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ARAMEX' => _x( 'Aramex', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ARAMEX_API' => _x( 'Aramex', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ARASKARGO' => _x( 'Aras Cargo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ARGENTS_WEBHOOK' => _x( 'Argents Express Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ASENDIA_DE' => _x( 'asendia_de', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ATSHEALTHCARE_REFERENCE' => _x( 'ATS Healthcare', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ATSHEALTHCARE' => _x( 'ATS Healthcare', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AUEXPRESS' => _x( 'Au Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AUSTRALIA_POST_API' => _x( 'Australia Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AVERITT' => _x( 'Averitt Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AXLEHIRE_FTP' => _x( 'Axlehire', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AXLEHIRE' => _x( 'AxleHire', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BARQEXP' => _x( 'Barq', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BDMNET' => _x( 'BDMnet', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BEL_BELGIUM_POST' => _x( 'bel_belgium_post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BLR_BELPOST' => _x( 'Belpost', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BERT' => _x( 'BERT', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BESTTRANSPORT_SFTP' => _x( 'Best Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BETTERTRUCKS' => _x( 'Better Trucks', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BIGSMART' => _x( 'Big Smart', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BIOCAIR_FTP' => _x( 'BioCair', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BJSHOMEDELIVERY' => _x( 'BJS Distribution courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BJSHOMEDELIVERY_FTP' => _x( 'BJS Distribution, Storage & Couriers - FTP', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BLUEDART' => _x( 'BLUEDART', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BLUEDART_API' => _x( 'Bluedart', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BOLLORE_LOGISTICS' => _x( 'Bollore Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BOMI' => _x( 'Bomi Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BE_BPOST' => _x( 'Bpost (www.bpost.be)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BPOST_API' => _x( 'Bpost API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BPOST_INT' => _x( 'Bpost international', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BRT_IT_API' => _x( 'BRT Bartolini API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BUFFALO' => _x( 'BUFFALO', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BURD' => _x( 'Burd Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CHROBINSON' => _x( 'C.H. Robinson Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CAGO' => _x( 'Cago', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CANPAR' => _x( 'CANPAR', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CAPITAL' => _x( 'Capital Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CARRY_FLAP' => _x( 'Carry-Flap Co.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CBL_LOGISTICA_API' => _x( 'CBL Logistica (API)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CDLDELIVERS' => _x( 'CDL Last Mile', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CELERITAS' => _x( 'Celeritas Transporte', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CEVA' => _x( 'CEVA LOGISTICS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CEVA_TRACKING' => _x( 'CEVA Package', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CHAZKI' => _x( 'Chazki', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CHIENVENTURE_WEBHOOK' => _x( 'Chienventure', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CHILEXPRESS' => _x( 'Chile Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CITY56_WEBHOOK' => _x( 'City Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CJ_GLS' => _x( 'CJ GLS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CJ_LOGISTICS' => _x( 'CJ Logistics International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CJ_PHILIPPINES' => _x( 'cj_philippines', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CLICKLINK_SFTP' => _x( 'ClickLink', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_LOGISTICS' => _x( 'CN Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COLLECTPLUS' => _x( 'COLLECTPLUS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COM1EXPRESS' => _x( 'ComOne Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CONCISE' => _x( 'Concise', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CONCISE_WEBHOOK' => _x( 'Concise', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CONCISE_API' => _x( 'Concise', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COORDINADORA_API' => _x( 'Coordinadora', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COPA_COURIER' => _x( 'Copa Airlines Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CORREOS_DE_ESPANA' => _x( 'CORREOS DE ESPANA', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CORREOSEXPRESS_API' => _x( 'Correos Express (API)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CORREOS_ES' => _x( 'correos Express (www.correos.es)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COURANT_PLUS_API' => _x( 'Courant Plus', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COURIER_POST' => _x( 'COURIER POST', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COURIERPLUS' => _x( 'COURIERPLUS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CRLEXPRESS' => _x( 'CRL Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CROSSFLIGHT' => _x( 'Crossflight Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CRYOPDP_FTP' => _x( 'CryoPDP', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CESKAPOSTA_API' => _x( 'Czech Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DEXPRESS_WEBHOOK' => _x( 'D Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DACHSER' => _x( 'DACHSER', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DACHSER_WEB' => _x( 'DACHSER', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DAESHIN' => _x( 'Daeshin', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DAIICHI' => _x( 'Daiichi Freight System Inc', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DANNIAO' => _x( 'Danniao', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DAO365' => _x( 'DAO365', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DAYROSS' => _x( 'Day & Ross', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DYLT' => _x( 'Daylight Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DBSCHENKER_API' => _x( 'DB Schenker', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DBSCHENKER_B2B' => _x( 'DB Schenker B2B', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DBSCHENKER_ICELAND' => _x( 'DB Schenker Iceland', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DDEXPRESS' => _x( 'DD Express Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DE_DHL' => _x( 'DE DHL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DELCART_IN' => _x( 'delcart_in', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DELIVERYOURPARCEL_ZA' => _x( 'Deliver Your Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DELIVER_IT' => _x( 'Deliver-iT', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DELIVERE' => _x( 'delivere', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DELIVERR_SFTP' => _x( 'Deliverr', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DELTEC_DE' => _x( 'DELTEC DE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DEMANDSHIP' => _x( 'DemandShip', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DEUTSCHE_DE' => _x( 'deutsche_de', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_API' => _x( 'DHL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_REFERENCE_API' => _x( 'DHL (Reference number)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_ACTIVE_TRACING' => _x( 'DHL Active Tracing', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_ECOMMERCE_GC' => _x( 'DHL eCommerce Greater China', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_GLOBAL_MAIL_API' => _x( 'DHL eCommerce Solutions', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DE_DHL_EXPRESS' => _x( 'DHL Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_SFTP' => _x( 'DHL Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_FR' => _x( 'DHL France (www.dhl.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_FREIGHT' => _x( 'DHL Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL' => _x( 'dhl Global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_GLOBAL_FORWARDING_API' => _x( 'DHL Global Forwarding API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_GT_API' => _x( 'DHL Global Forwarding Guatemala', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_PA_API' => _x( 'DHL GLOBAL FORWARDING PANAMÁ', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IT_DHL_ECOMMERCE' => _x( 'DHL International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_JP' => _x( 'DHL Japan', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_PARCEL_NL' => _x( 'DHL Parcel NL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_SG' => _x( 'dhl Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_ES_SFTP' => _x( 'DHL Spain Domestic', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_SUPPLYCHAIN_IN' => _x( 'DHL supply chain India', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_SUPPLYCHAIN_ID' => _x( 'DHL Supply Chain Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_AT' => _x( 'dhl_at', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_GLOBAL_MAIL' => _x( 'dhl_global_mail', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_IT' => _x( 'dhl_it', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_PIECEID' => _x( 'dhl_pieceid', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_SUPPLY_CHAIN_AU' => _x( 'dhl_supply_chain_au', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHLPARCEL_UK' => _x( 'dhlparcel_uk', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DIALOGO_LOGISTICA_API' => _x( 'Dialogo Logistica', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DIALOGO_LOGISTICA' => _x( 'Dialogo Logistica', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DIRECTFREIGHT_AU_REF' => _x( 'Direct Freight Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DIREX' => _x( 'Direx', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DKSH' => _x( 'DKSH', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DMFGROUP' => _x( 'DMF', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DNJ_EXPRESS' => _x( 'DNJ Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DOTZOT' => _x( 'DOTZOT', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD' => _x( 'DPD', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_AT_SFTP' => _x( 'DPD Austria', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_DELISTRACK' => _x( 'DPD delistrack', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_NL' => _x( 'DPD Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_RU_API' => _x( 'DPD Russia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_SK_SFTP' => _x( 'DPD Slovakia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_CH_SFTP' => _x( 'DPD Switzerland', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_UK_SFTP' => _x( 'DPD UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_DE' => _x( 'dpd_de', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_FR_REFERENCE' => _x( 'dpd_fr_reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_UK' => _x( 'dpd_uk', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_DPEX' => _x( 'DPEX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPEX' => _x( 'DPEX (www.dpex.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DSV' => _x( 'DSV courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DSV_REFERENCE' => _x( 'DSV Futurewave', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DX' => _x( 'DX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DX_B2B_CONNUM' => _x( 'DX (B2B)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DX_FREIGHT' => _x( 'DX Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DYNALOGIC' => _x( 'Dynamic Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EASTWESTCOURIER_FTP' => _x( 'East West Courier Pte Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EC_CN' => _x( 'EC_CN', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ECARGO' => _x( 'ECARGO', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ECEXPRESS' => _x( 'ECexpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ECMS' => _x( 'ECMS International Logistics Co.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ECOFREIGHT' => _x( 'Eco Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ECOURIER' => _x( 'ecourier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ECOUTIER' => _x( 'eCoutier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EFS' => _x( 'EFS (E-commerce Fulfillment Service)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ELITE_CO' => _x( 'Elite Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ELOGISTICA' => _x( 'elogistica', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ELTA_GR' => _x( 'elta_gr', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ARE_EMIRATES_POST' => _x( 'Emirates Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EMS' => _x( 'EMS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EMS_CN' => _x( 'ems_cn', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ENSENDA' => _x( 'ENSENDA', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EFWNOW_API' => _x( 'Estes Forwarding Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ETOMARS' => _x( 'Etomars', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ETOTAL' => _x( 'eTotal Solution Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EDF_FTP' => _x( 'Eurodifarm', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EURODIS' => _x( 'eurodis', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EUROPAKET_API' => _x( 'Europacket+', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MYHERMES_UK_API' => _x( 'EVRi', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EWE' => _x( 'EWE Global Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EXELOT_FTP' => _x( 'Exelot Ltd.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EXPEDITORS' => _x( 'Expeditors', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EXPEDITORS_API_REF' => _x( 'Expeditors API Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EZSHIP' => _x( 'EZship', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FAIRSENDEN_API' => _x( 'fairsenden', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FXTRAN' => _x( 'Falcon Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FAN' => _x( 'FAN COURIER EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FNF_ZA' => _x( 'Fast & Furious', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FASTDESPATCH' => _x( 'Fast Despatch Logistics Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FASTBOX' => _x( 'Fastbox', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FASTSHIP' => _x( 'Fastship Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FASTTRACK' => _x( 'fasttrack', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FASTWAY_AU' => _x( 'fastway_au', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FASTWAY_UK' => _x( 'FASTWAY_UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FASTWAY_US' => _x( 'FASTWAY_US', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FASTWAY_ZA' => _x( 'fastway_za', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FAXECARGO' => _x( 'Faxe Cargo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FEDEX_FR' => _x( 'FedEx® Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FEDEX_API' => _x( 'FedEx®', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FERCAM_IT' => _x( 'fercam_it', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FETCHR' => _x( 'Fetchr', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FIRST_LOGISTICS_API' => _x( 'First Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FIRST_LOGISITCS' => _x( 'first_logisitcs', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FITZMARK_API' => _x( 'FitzMark', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FLASHEXPRESS_WEBHOOK' => _x( 'Flash Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FLIGHTLG' => _x( 'Flight Logistics Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FLIPXP' => _x( 'FlipXpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FLYTEXPRESS' => _x( 'FLYTEXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FORWARDAIR' => _x( 'Forward Air', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FOUR_PX_EXPRESS' => _x( 'FOUR PX EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FR_COLISSIMO' => _x( 'fr_colissimo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FR_MONDIAL' => _x( 'fr_mondial', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FRAGILEPAK_SFTP' => _x( 'FragilePAK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FRONTDOORCORP' => _x( 'FRONTdoor Collective', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FUJEXP' => _x( 'FUJIE EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GWLOGIS_API' => _x( 'G.I.G', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GAC' => _x( 'GAC', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GATI_KWE_API' => _x( 'Gati-KWE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GDPHARM' => _x( 'GDPharm Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GW_WORLD' => _x( 'Gebrüder Weiss', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GEODIS' => _x( 'GEODIS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GEODIS_API' => _x( 'GEODIS - Distribution & Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GPOST' => _x( 'Georgian Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GIAO_HANG' => _x( 'Giao hàng nhanh', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GIO_ECOURIER_API' => _x( 'GIO Express Ecourier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GIO_ECOURIER' => _x( 'GIO Express Inc', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GOGLOBALPOST' => _x( 'Global Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLOBEGISTICS' => _x( 'GLOBEGISTICS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLOVO' => _x( 'Glovo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLS' => _x( 'GLS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLS_SPAIN_API' => _x( 'GLS Spain', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLS_DE' => _x( 'GLS_DE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLS_ES' => _x( 'GLS_ES', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLS_FR' => _x( 'GLS_FR', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLS_ITALY_FTP' => _x( 'gls_italy_ftp', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLS_SPAIN' => _x( 'gls_spain', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GOLS' => _x( 'GO Logistics & Storage', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GOPEOPLE' => _x( 'Go People', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GORUSH' => _x( 'Go Rush', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GOJEK' => _x( 'Gojek', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GREYHOUND' => _x( 'GREYHOUND', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MAZET' => _x( 'Groupe Mazet', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HANJIN' => _x( 'HanJin', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HELLENIC_POST' => _x( 'Hellenic (Greece) Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HELLMANN' => _x( 'Hellmann Worldwide Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HELTHJEM_API' => _x( 'Helthjem', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HERMES_DE_FTP' => _x( 'Hermes Germany', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HERMES_UK_SFTP' => _x( 'Hermes UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HERMESWORLD_UK' => _x( 'hermesworld_uk', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HEROEXPRESS' => _x( 'Hero Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HFD' => _x( 'HFD', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HK_RPX' => _x( 'hk_rpx', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HOMELOGISTICS' => _x( 'Home Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HOMERUNNER' => _x( 'HomeRunner', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HERMES_IT' => _x( 'HR Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HSDEXPRESS' => _x( 'HSDEXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HSM_GLOBAL' => _x( 'HSM Global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HUANTONG' => _x( 'HuanTong', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HUBBED' => _x( 'HUBBED', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HUNTER_EXPRESS_SFTP' => _x( 'Hunter Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IBVENTURE_WEBHOOK' => _x( 'IB Venture', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTUR_IS' => _x( 'Iceland Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ICSCOURIER' => _x( 'ICS COURIER', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IDEXPRESS_ID' => _x( 'iDexpress Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IDN_POS' => _x( 'idn_pos', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IDS_LOGISTICS' => _x( 'ids_logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ILYANGLOGIS' => _x( 'Ilyang logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IMEXGLOBALSOLUTIONS' => _x( 'imexglobalsolutions', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IMILE_API' => _x( 'iMile', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IML' => _x( 'IML courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IMX' => _x( 'IMX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INDIA_POST' => _x( 'India Post Domestic', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INDIA_POST_INT' => _x( 'India Post International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INEXPOST' => _x( 'Inexpost', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INNTRALOG_SFTP' => _x( 'Inntralog GmbH', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INPOST_UK' => _x( 'InPost', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INSTABOX_WEBHOOK' => _x( 'Instabox', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTERNATIONAL_SEUR_API' => _x( 'International Seur API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTERSMARTTRANS' => _x( 'INTERSMARTTRANS & SOLUTIONS SL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTEX_DE' => _x( 'INTEX Paketdienst GmbH', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTIME_FTP' => _x( 'InTime', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ITHINKLOGISTICS' => _x( 'iThink Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JTCARGO' => _x( 'J&T CARGO', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JTEXPRESS_PH' => _x( 'J&T Express Philippines', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JTEXPRESS_SG_API' => _x( 'J&T Express Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JT_LOGISTICS' => _x( 'J&T International logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JAVIT' => _x( 'Javit', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_JCEX' => _x( 'JCEX courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JD_EXPRESS' => _x( 'JD Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JD_WORLDWIDE' => _x( 'JD Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JETSHIP_MY' => _x( 'jetship_my', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JNE_API' => _x( 'JNE (API)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IDN_JNE' => _x( 'JNE Express (Jalur Nugraha Ekakurir)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JOYINGBOX' => _x( 'joyingbox', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KARGOMKOLAY' => _x( 'KargomKolay (CargoMini)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KEDAEX' => _x( 'KedaEX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HK_TGX' => _x( 'Kerry Express Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KERRY_EXPRESS_TW_API' => _x( 'Kerry Express TaiWan', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'THA_KERRY' => _x( 'Kerry Express Thailand', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KERRY_EXPRESS_TH_WEBHOOK' => _x( 'Kerry Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KNG' => _x( 'Keuhne + Nagel Global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BE_KIALA' => _x( 'Kiala', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGISYSTEMS_SFTP' => _x( 'Kiitääjät', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KOMON_EXPRESS' => _x( 'Komon Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KRONOS_WEBHOOK' => _x( 'Kronos Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KRONOS' => _x( 'Kronos Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KUEHNE' => _x( 'Kuehne + Nagel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LALAMOVE_API' => _x( 'Lalamove', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LBCEXPRESS_FTP' => _x( 'LBC EXPRESS INC.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LBCEXPRESS_API' => _x( 'LBC EXPRESS INC.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LCTBR_API' => _x( 'LCT do Brasil', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LTU_LIETUVOS' => _x( 'Lietuvos pastas', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LINKBRIDGE' => _x( 'Link Bridge(BeiJing)international logistics co.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LION_PARCEL' => _x( 'LION PARCEL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LIVRAPIDE' => _x( 'Livrapide', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGGI' => _x( 'Loggi', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGISTICSWORLDWIDE_KR' => _x( 'LOGISTICSWORLDWIDE KR', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGISTICSWORLDWIDE_MY' => _x( 'LOGISTICSWORLDWIDE MY', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGWIN_LOGISTICS' => _x( 'Logwin Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGYSTO' => _x( 'Logysto', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LUWJISTIK' => _x( 'Luwjistik', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MX_CARGO' => _x( 'M&X cargo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'M3LOGISTICS' => _x( 'M3 Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'REIMAGINEDELIVERY' => _x( 'maergo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MAGYAR_POSTA_API' => _x( 'Magyar Posta', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MAIL_BOX_ETC' => _x( 'Mail Boxes Etc.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MYS_EMS' => _x( 'Malaysia Post EMS / Pos Laju', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MALCA_AMIT_API' => _x( 'Malca Amit', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MALCA_AMIT' => _x( 'Malca-Amit', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MARKEN' => _x( 'Marken', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MEDAFRICA' => _x( 'Med Africa Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MEEST' => _x( 'Meest', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MEGASAVE' => _x( 'megasave', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MENSAJEROSURBANOS_API' => _x( 'Mensajeros Urbanos', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MWD' => _x( 'Metropolitan Warehouse & Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MWD_API' => _x( 'Metropolitan Warehouse & Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MHI' => _x( 'Mhi', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MIKROPAKKET' => _x( 'Mikropakket', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MISUMI_CN' => _x( 'MISUMI Group Inc.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MNX' => _x( 'MNX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MOBI_BR' => _x( 'Mobi Logistica', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MONDIALRELAY_FR' => _x( 'Mondial Relay France', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MONDIALRELAY_ES' => _x( 'Mondial Relay Spain(Punto Pack)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MONDIAL_BE' => _x( 'MONDIAL_BE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MOOVA' => _x( 'Moova', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MORNINGLOBAL' => _x( 'Morning Global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MOTHERSHIP_API' => _x( 'Mothership', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MOVIANTO' => _x( 'Movianto', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MUDITA' => _x( 'MUDITA', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MYDYNALOGIC' => _x( 'My DynaLogic', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MYSENDLE_API' => _x( 'mySendle', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NMTRANSFER' => _x( 'N&M Transfer Co., Inc.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NACEX_SPAIN_REFERENCE' => _x( 'nacex_spain_reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NAEKO_FTP' => _x( 'Naeko Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NAQEL_EXPRESS' => _x( 'Naqel Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NEWZEALAND_COURIERS' => _x( 'NEW ZEALAND COURIERS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NEWGISTICS' => _x( 'Newgistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NEWGISTICSAPI' => _x( 'Newgistics API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NIGHTLINE_UK' => _x( 'nightline_uk', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NIMBUSPOST' => _x( 'NimbusPost', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NIPPON_EXPRESS_FTP' => _x( 'Nippon Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NIPPON_EXPRESS' => _x( 'Nippon Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NORTHLINE' => _x( 'Northline', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NOVA_POSHTA_API' => _x( 'Nova Poshta API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NOVOFARMA_WEBHOOK' => _x( 'Novofarma', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NTL' => _x( 'NTL logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NYTLOGISTICS' => _x( 'NYT SUPPLY CHAIN LOGISTICS Co., LTD', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OHI_WEBHOOK' => _x( 'Ohi', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHOPOLIVE' => _x( 'Olive', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OMLOGISTICS_API' => _x( 'OM LOGISTICS LTD', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OMNIRPS_WEBHOOK' => _x( 'Omni Returns', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ONTRAC' => _x( 'ONTRAC', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ORANGECONNEX' => _x( 'orangeconnex', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ORANGE_DS' => _x( 'OrangeDS (Orange Distribution Solutions Inc)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OSM_WORLDWIDE_SFTP' => _x( 'OSM Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OZEPARTS_SHIPPING' => _x( 'Ozeparts Shipping', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'P2P_TRC' => _x( 'P2P TrakPak', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PACKETA' => _x( 'Packeta', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PACKFLEET' => _x( 'PACKFLEET', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PACKS' => _x( 'Packs', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PAKAJO' => _x( 'Pakajo World', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PANDAGO_API' => _x( 'Pandago', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PANDION' => _x( 'Pandion', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PANDU' => _x( 'PANDU', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PANTHER_REFERENCE_API' => _x( 'Panther Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PANTHER_ORDER_NUMBER' => _x( 'panther_order_number', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PAPA_WEBHOOK' => _x( 'Papa', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCELRIGHT' => _x( 'Parcel Right', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCEL_2_POST' => _x( 'Parcel To Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCELFORCE' => _x( 'PARCELFORCE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCELSTARS_WEBHOOK' => _x( 'Parcelstars', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCLL' => _x( 'PARCLL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PASSPORTSHIPPING' => _x( 'Passport Shipping', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PATHEON' => _x( 'Patheon Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PAYO' => _x( 'Payo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PCHOME_API' => _x( 'Pchome Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PGEON_API' => _x( 'Pgeon', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PHSE_API' => _x( 'PHSE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PICKUPP_VNM' => _x( 'pickupp_vnm', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PIDGE' => _x( 'Pidge', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PIL_LOGISTICS' => _x( 'PIL Logistics (China) Co.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PLYCONGROUP' => _x( 'Plycon Transportation Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POLARSPEED' => _x( 'PolarSpeed Inc', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTONE' => _x( 'Post ONE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTAPLUS' => _x( 'Posta Plus', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTE_ITALIANE_PACCOCELERE' => _x( 'Poste Italiane Paccocelere', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTEN_NORGE' => _x( 'Posten Norge (www.posten.no)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTI_API' => _x( 'Posti API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTNL_INT_3_S' => _x( 'PostNL International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NLD_POSTNL' => _x( 'PostNL International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTNL_INTERNATIONAL' => _x( 'PostNL International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SWE_POSTNORD' => _x( 'Postnord sweden', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTPLUS' => _x( 'PostPlus', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PROCARRIER' => _x( 'Pro Carrier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PRODUCTCAREGROUP_SFTP' => _x( 'Product Care Services Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PROFESSIONAL_COURIERS' => _x( 'PROFESSIONAL COURIERS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PPL' => _x( 'Professional Parcel Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PROMEDDELIVERY' => _x( 'ProMed Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PUROLATOR' => _x( 'purolator', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PUROLATOR_INTERNATIONAL' => _x( 'Purolator International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'QTRACK' => _x( 'QTrack', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'QUALITYPOST' => _x( 'qualitypost', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'QINTL_API' => _x( 'Quickstat Courier LLC', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'QUIQUP' => _x( 'Quiqup', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RANSA_WEBHOOK' => _x( 'Ransa', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'REDJEPAKKETJE' => _x( 'Red je Pakketje', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RELAISCOLIS' => _x( 'Relais Colis', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RHENUS_GROUP' => _x( 'Rhenus Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RHENUS_UK_API' => _x( 'Rhenus Logistics UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AIR_CANADA' => _x( 'Rivo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RIXONHK_API' => _x( 'Rixon Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ROCHE_INTERNAL_SFTP' => _x( 'Roche Internal Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ROYAL_MAIL_FTP' => _x( 'Royal Mail', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ROYALSHIPMENTS' => _x( 'royalshipments', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RRDONNELLEY' => _x( 'rrdonnelley', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RUSSIAN_POST' => _x( 'Russian post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SAEE' => _x( 'saee', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SAGAWA' => _x( 'SAGAWA', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SAGAWA_API' => _x( 'Sagawa', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SBERLOGISTICS_RU' => _x( 'Sber Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SECRETLAB_WEBHOOK' => _x( 'Secretlab', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SEINO_API' => _x( 'Seino', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SEKO_SFTP' => _x( 'SEKO Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SENDING' => _x( 'Sending Transporte Urgente y Comunicacion', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHOWL' => _x( 'SENHONG INTERNATIONAL LOGISTICS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NOWLOG_API' => _x( 'Sequoialog', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SERVIENTREGA' => _x( 'Servientrega', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SERVIP_WEBHOOK' => _x( 'SerVIP', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SETEL' => _x( 'Setel Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SF_EX' => _x( 'SF Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SF_EXPRESS_CN' => _x( 'SF Express China', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SGT_IT' => _x( 'SGT_IT', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHADOWFAX' => _x( 'Shadowfax', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHENZHEN' => _x( 'shenzhen 1st International Logistics(Group)Co', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HOTSIN_CARGO' => _x( 'SHENZHEN HOTSIN CARGO INTL FORWARDING CO., LTD', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KWT' => _x( 'Shenzhen Jinghuada Logistics Co.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHERPA' => _x( 'Sherpa', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIPA' => _x( 'SHIPA', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIPPIE' => _x( 'Shippie', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIPPIFY' => _x( 'Shippify, Inc', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIPROCKET' => _x( 'Shiprocket X', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIPX' => _x( 'ShipX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIPXPRES' => _x( 'SHIPXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPX' => _x( 'Shopee Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPX_TH' => _x( 'Shopee Xpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHUNBANG_EXPRESS' => _x( 'ShunBang Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHYPLITE' => _x( 'Shypmax', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SIMPLETIRE_WEBHOOK' => _x( 'SimpleTire', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SIMSGLOBAL' => _x( 'Sims Global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SIODEMKA' => _x( 'SIODEMKA', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SKynet_WORLDWIDE' => _x( 'SkyNet Worldwide Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SKY_POSTAL' => _x( 'SkyPostal', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SK_POSTA' => _x( 'Slovenska pošta', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SMARTCAT' => _x( 'SMARTCAT', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SMARTKARGO' => _x( 'SmartKargo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SMG_EXPRESS' => _x( 'SMG Direct', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SMSA_EXPRESS_WEBHOOK' => _x( 'SMSA Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SNTGLOBAL_API' => _x( 'Snt Global Etrax', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SOLISTICA_API' => _x( 'solistica', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPANISH_SEUR_FTP' => _x( 'Spanish Seur', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPECTRAN' => _x( 'Spectran', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPEEDEX' => _x( 'speedex', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPEEDY' => _x( 'Speedy', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPREETAIL_API' => _x( 'Spreetail', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPRINT_PACK' => _x( 'SPRINT PACK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SRT_TRANSPORT' => _x( 'SRT Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STAR_TRACK_NEXT_FLIGHT' => _x( 'Star Track Next Flight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STARLINKS_API' => _x( 'Starlinks Global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STARTRACK' => _x( 'startrack', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STAR_TRACK_WEBHOOK' => _x( 'StarTrack', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STARTRACK_EXPRESS' => _x( 'startrack_express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STATOVERNIGHT' => _x( 'Stat Overnight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_STO' => _x( 'STO Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SWISHIP' => _x( 'Swiship', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SWISS_POST' => _x( 'SWISS POST', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'T_CAT' => _x( 'T-cat', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'T_CAT_API' => _x( 'T-cat', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGINEXT_WEBHOOK' => _x( 'T&W Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TW_TAIWAN_POST' => _x( 'Taiwan Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TAMERGROUP_WEBHOOK' => _x( 'Tamer Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TAQBIN_HK' => _x( 'TAQBIN Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TAQBIN_SG' => _x( 'taqbin_sg', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TCS_API' => _x( 'TCS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TECOR' => _x( 'tecor', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TELEPORT_WEBHOOK' => _x( 'Teleport', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SIC_TELIWAY' => _x( 'Teliway SIC Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TESTING_COURIER_WEBHOOK' => _x( 'Testing Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TESTING_COURIER' => _x( 'Testing Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TH_CJ' => _x( 'TH_CJ', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'THIJS_NL' => _x( 'Thijs Logistiek', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'THUNDEREXPRESS' => _x( 'Thunder Express Australia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TIPSA_API' => _x( 'Tipsa API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TIPSA_REF' => _x( 'Tipsa Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_FR_REFERENCE' => _x( 'TNT France Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_REFR' => _x( 'TNT Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_AU' => _x( 'tnt_au', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_CN' => _x( 'TNT_CN', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_DE' => _x( 'TNT_DE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_ES' => _x( 'TNT_ES', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_IT' => _x( 'tnt_it', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_JP' => _x( 'TNT_JP', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_PL' => _x( 'TNT_PL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOLL_WEBHOOK' => _x( 'Toll Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOLL_IPEC' => _x( 'TOLL IPEC', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOLL_PRIORITY' => _x( 'Toll Priority', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOMYDOOR' => _x( 'Tomydoor', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TONAMI_FTP' => _x( 'Tonami', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ESDEX' => _x( 'Top Ideal Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOTAL_EXPRESS_API' => _x( 'Total Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOURLINE_REFERENCE' => _x( 'Tourline Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'THAIPARCELS' => _x( 'TP Logistic', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TRANS2U' => _x( 'Trans2u', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TRANSMISSION' => _x( 'TRANSMISSION', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TANET' => _x( 'Transport Ambientales', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TRANSVIRTUAL' => _x( 'TransVirtual', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TRUNKRS' => _x( 'Trunkrs', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TRUSK' => _x( 'Trusk France', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TUSKLOGISTICS' => _x( 'Tusk Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TYP' => _x( 'TYP', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'U_ENVIOS' => _x( 'U-ENVIOS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UBER_WEBHOOK' => _x( 'Uber', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UCS' => _x( 'UCS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UDS' => _x( 'United Delivery Service', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UPS' => _x( 'United Parcel Service', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UP_EXPRESS' => _x( 'up_express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UPARCEL' => _x( 'uParcel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UPS_API' => _x( 'UPS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UPS_FREIGHT' => _x( 'UPS Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UPS_REFERENCE' => _x( 'UPS Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'URGENT_CARGUS' => _x( 'Urgent Cargus', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'US_APC' => _x( 'us_apc', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'USPS_API' => _x( 'USPS API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PB_USPSFLATS_FTP' => _x( 'USPS Flats (Pitney Bowes)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'USPS_WEBHOOK' => _x( 'USPS Informed Visibility - Webhook', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VALUE_WEBHOOK' => _x( 'Value Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VIAXPRESS' => _x( 'ViaXpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VNPOST_API' => _x( 'Vietnam Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VIRTRANSPORT_SFTP' => _x( 'Vir Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VNPOST_EMS' => _x( 'vnpost_ems', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VOX' => _x( 'VOX SOLUCION EMPRESARIAL SRL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WATKINS_SHEPARD' => _x( 'watkins_shepard', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WEWORLDEXPRESS' => _x( 'We World Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WESHIP_API' => _x( 'WeShip', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WESHIP' => _x( 'WeShip', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WHISTL_SFTP' => _x( 'Whistl', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WINESHIPPING_WEBHOOK' => _x( 'Wineshipping', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WISH_EMAIL_PUSH' => _x( 'Wish', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WOOYOUNG_LOGISTICS_SFTP' => _x( 'WOO YOUNG LOGISTICS CO., LTD.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WORLDCOURIER' => _x( 'World Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WORLDNET' => _x( 'Worldnet Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WSPEXPRESS' => _x( 'WSP Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XYY' => _x( 'Xingyunyi Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XPEDIGO' => _x( 'Xpedigo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XPRESSBEES' => _x( 'XPRESSBEES', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YAMATO' => _x( 'YAMATO', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TAQBIN_SG_API' => _x( 'Yamato Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YIFAN' => _x( 'YiFan Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YODEL' => _x( 'yodel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YODEL_API' => _x( 'Yodel API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YODEL_DIR' => _x( 'Yodel Direct', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YODEL_INTNL' => _x( 'Yodel International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YUSEN' => _x( 'Yusen Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YUSEN_SFTP' => _x( 'Yusen Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YYCOM' => _x( 'yycom', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YYEXPRESS' => _x( 'YYEXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZTO_DOMESTIC' => _x( 'ZTO Express China', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZUELLIGPHARMA_SFTP' => _x( 'Zuellig Pharma Korea', 'Name of carrier', 'woocommerce-paypal-payments' ), + '99MINUTOS' => tr( '99minutos', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'A2B_BA' => tr( 'A2B Express Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ABCUSTOM_SFTP' => tr( 'AB Custom Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ACILOGISTIX' => tr( 'ACI Logistix', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ACOMMERCE' => tr( 'ACOMMERCE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ACTIVOS24_API' => tr( 'Activos24', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ADS' => tr( 'ADS Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AEROFLASH' => tr( 'AEROFLASH', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AGEDISS_SFTP' => tr( 'Agediss', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AIR_21' => tr( 'AIR 21', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AIRSPEED' => tr( 'AIRSPEED', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AIRTERRA' => tr( 'Airterra', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AITWORLDWIDE_API' => tr( 'AIT', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AITWORLDWIDE_SFTP' => tr( 'AIT', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ALLIED_EXPRESS_FTP' => tr( 'Allied Express (FTP)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ALLJOY' => tr( 'ALLJOY SUPPLY CHAIN', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AMAZON_EMAIL_PUSH' => tr( 'Amazon', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AMAZON_ORDER' => tr( 'Amazon order', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AMAZON_UK_API' => tr( 'amazon_uk_api', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AMS_GRP' => tr( 'AMS Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ANDREANI_API' => tr( 'Andreani', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ANTERAJA' => tr( 'Anteraja', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ARAMEX' => tr( 'Aramex', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ARAMEX_API' => tr( 'Aramex', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ARASKARGO' => tr( 'Aras Cargo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ARGENTS_WEBHOOK' => tr( 'Argents Express Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ASENDIA_DE' => tr( 'asendia_de', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ATSHEALTHCARE_REFERENCE' => tr( 'ATS Healthcare', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ATSHEALTHCARE' => tr( 'ATS Healthcare', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AUEXPRESS' => tr( 'Au Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AUSTRALIA_POST_API' => tr( 'Australia Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AVERITT' => tr( 'Averitt Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AXLEHIRE_FTP' => tr( 'Axlehire', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AXLEHIRE' => tr( 'AxleHire', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BARQEXP' => tr( 'Barq', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BDMNET' => tr( 'BDMnet', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BEL_BELGIUM_POST' => tr( 'bel_belgium_post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BLR_BELPOST' => tr( 'Belpost', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BERT' => tr( 'BERT', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BESTTRANSPORT_SFTP' => tr( 'Best Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BETTERTRUCKS' => tr( 'Better Trucks', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BIGSMART' => tr( 'Big Smart', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BIOCAIR_FTP' => tr( 'BioCair', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BJSHOMEDELIVERY' => tr( 'BJS Distribution courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BJSHOMEDELIVERY_FTP' => tr( 'BJS Distribution, Storage & Couriers - FTP', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BLUEDART' => tr( 'BLUEDART', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BLUEDART_API' => tr( 'Bluedart', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BOLLORE_LOGISTICS' => tr( 'Bollore Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BOMI' => tr( 'Bomi Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BE_BPOST' => tr( 'Bpost (www.bpost.be)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BPOST_API' => tr( 'Bpost API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BPOST_INT' => tr( 'Bpost international', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BRT_IT_API' => tr( 'BRT Bartolini API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BUFFALO' => tr( 'BUFFALO', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BURD' => tr( 'Burd Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CHROBINSON' => tr( 'C.H. Robinson Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CAGO' => tr( 'Cago', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CANPAR' => tr( 'CANPAR', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CAPITAL' => tr( 'Capital Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CARRY_FLAP' => tr( 'Carry-Flap Co.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CBL_LOGISTICA_API' => tr( 'CBL Logistica (API)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CDLDELIVERS' => tr( 'CDL Last Mile', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CELERITAS' => tr( 'Celeritas Transporte', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CEVA' => tr( 'CEVA LOGISTICS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CEVA_TRACKING' => tr( 'CEVA Package', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CHAZKI' => tr( 'Chazki', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CHIENVENTURE_WEBHOOK' => tr( 'Chienventure', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CHILEXPRESS' => tr( 'Chile Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CITY56_WEBHOOK' => tr( 'City Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CJ_GLS' => tr( 'CJ GLS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CJ_LOGISTICS' => tr( 'CJ Logistics International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CJ_PHILIPPINES' => tr( 'cj_philippines', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CLICKLINK_SFTP' => tr( 'ClickLink', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_LOGISTICS' => tr( 'CN Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COLLECTPLUS' => tr( 'COLLECTPLUS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COM1EXPRESS' => tr( 'ComOne Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CONCISE' => tr( 'Concise', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CONCISE_WEBHOOK' => tr( 'Concise', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CONCISE_API' => tr( 'Concise', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COORDINADORA_API' => tr( 'Coordinadora', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COPA_COURIER' => tr( 'Copa Airlines Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CORREOS_DE_ESPANA' => tr( 'CORREOS DE ESPANA', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CORREOSEXPRESS_API' => tr( 'Correos Express (API)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CORREOS_ES' => tr( 'correos Express (www.correos.es)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COURANT_PLUS_API' => tr( 'Courant Plus', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COURIER_POST' => tr( 'COURIER POST', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COURIERPLUS' => tr( 'COURIERPLUS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CRLEXPRESS' => tr( 'CRL Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CROSSFLIGHT' => tr( 'Crossflight Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CRYOPDP_FTP' => tr( 'CryoPDP', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CESKAPOSTA_API' => tr( 'Czech Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DEXPRESS_WEBHOOK' => tr( 'D Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DACHSER' => tr( 'DACHSER', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DACHSER_WEB' => tr( 'DACHSER', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DAESHIN' => tr( 'Daeshin', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DAIICHI' => tr( 'Daiichi Freight System Inc', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DANNIAO' => tr( 'Danniao', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DAO365' => tr( 'DAO365', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DAYROSS' => tr( 'Day & Ross', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DYLT' => tr( 'Daylight Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DBSCHENKER_API' => tr( 'DB Schenker', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DBSCHENKER_B2B' => tr( 'DB Schenker B2B', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DBSCHENKER_ICELAND' => tr( 'DB Schenker Iceland', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DDEXPRESS' => tr( 'DD Express Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DE_DHL' => tr( 'DE DHL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DELCART_IN' => tr( 'delcart_in', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DELIVERYOURPARCEL_ZA' => tr( 'Deliver Your Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DELIVER_IT' => tr( 'Deliver-iT', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DELIVERE' => tr( 'delivere', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DELIVERR_SFTP' => tr( 'Deliverr', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DELTEC_DE' => tr( 'DELTEC DE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DEMANDSHIP' => tr( 'DemandShip', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DEUTSCHE_DE' => tr( 'deutsche_de', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_API' => tr( 'DHL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_REFERENCE_API' => tr( 'DHL (Reference number)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_ACTIVE_TRACING' => tr( 'DHL Active Tracing', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_ECOMMERCE_GC' => tr( 'DHL eCommerce Greater China', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_GLOBAL_MAIL_API' => tr( 'DHL eCommerce Solutions', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DE_DHL_EXPRESS' => tr( 'DHL Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_SFTP' => tr( 'DHL Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_FR' => tr( 'DHL France (www.dhl.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_FREIGHT' => tr( 'DHL Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL' => tr( 'dhl Global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_GLOBAL_FORWARDING_API' => tr( 'DHL Global Forwarding API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_GT_API' => tr( 'DHL Global Forwarding Guatemala', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_PA_API' => tr( 'DHL GLOBAL FORWARDING PANAMÁ', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IT_DHL_ECOMMERCE' => tr( 'DHL International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_JP' => tr( 'DHL Japan', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_PARCEL_NL' => tr( 'DHL Parcel NL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_SG' => tr( 'dhl Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_ES_SFTP' => tr( 'DHL Spain Domestic', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_SUPPLYCHAIN_IN' => tr( 'DHL supply chain India', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_SUPPLYCHAIN_ID' => tr( 'DHL Supply Chain Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_AT' => tr( 'dhl_at', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_GLOBAL_MAIL' => tr( 'dhl_global_mail', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_IT' => tr( 'dhl_it', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_PIECEID' => tr( 'dhl_pieceid', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_SUPPLY_CHAIN_AU' => tr( 'dhl_supply_chain_au', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHLPARCEL_UK' => tr( 'dhlparcel_uk', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DIALOGO_LOGISTICA_API' => tr( 'Dialogo Logistica', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DIALOGO_LOGISTICA' => tr( 'Dialogo Logistica', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DIRECTFREIGHT_AU_REF' => tr( 'Direct Freight Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DIREX' => tr( 'Direx', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DKSH' => tr( 'DKSH', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DMFGROUP' => tr( 'DMF', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DNJ_EXPRESS' => tr( 'DNJ Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DOTZOT' => tr( 'DOTZOT', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD' => tr( 'DPD', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_AT_SFTP' => tr( 'DPD Austria', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_DELISTRACK' => tr( 'DPD delistrack', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_NL' => tr( 'DPD Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_RU_API' => tr( 'DPD Russia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_SK_SFTP' => tr( 'DPD Slovakia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_CH_SFTP' => tr( 'DPD Switzerland', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_UK_SFTP' => tr( 'DPD UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_DE' => tr( 'dpd_de', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_FR_REFERENCE' => tr( 'dpd_fr_reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_UK' => tr( 'dpd_uk', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_DPEX' => tr( 'DPEX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPEX' => tr( 'DPEX (www.dpex.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DSV' => tr( 'DSV courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DSV_REFERENCE' => tr( 'DSV Futurewave', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DX' => tr( 'DX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DX_B2B_CONNUM' => tr( 'DX (B2B)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DX_FREIGHT' => tr( 'DX Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DYNALOGIC' => tr( 'Dynamic Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EASTWESTCOURIER_FTP' => tr( 'East West Courier Pte Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EC_CN' => tr( 'EC_CN', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ECARGO' => tr( 'ECARGO', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ECEXPRESS' => tr( 'ECexpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ECMS' => tr( 'ECMS International Logistics Co.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ECOFREIGHT' => tr( 'Eco Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ECOURIER' => tr( 'ecourier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ECOUTIER' => tr( 'eCoutier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EFS' => tr( 'EFS (E-commerce Fulfillment Service)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ELITE_CO' => tr( 'Elite Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ELOGISTICA' => tr( 'elogistica', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ELTA_GR' => tr( 'elta_gr', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ARE_EMIRATES_POST' => tr( 'Emirates Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EMS' => tr( 'EMS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EMS_CN' => tr( 'ems_cn', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ENSENDA' => tr( 'ENSENDA', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EFWNOW_API' => tr( 'Estes Forwarding Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ETOMARS' => tr( 'Etomars', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ETOTAL' => tr( 'eTotal Solution Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EDF_FTP' => tr( 'Eurodifarm', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EURODIS' => tr( 'eurodis', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EUROPAKET_API' => tr( 'Europacket+', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MYHERMES_UK_API' => tr( 'EVRi', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EWE' => tr( 'EWE Global Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EXELOT_FTP' => tr( 'Exelot Ltd.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EXPEDITORS' => tr( 'Expeditors', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EXPEDITORS_API_REF' => tr( 'Expeditors API Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EZSHIP' => tr( 'EZship', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FAIRSENDEN_API' => tr( 'fairsenden', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FXTRAN' => tr( 'Falcon Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FAN' => tr( 'FAN COURIER EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FNF_ZA' => tr( 'Fast & Furious', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTDESPATCH' => tr( 'Fast Despatch Logistics Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTBOX' => tr( 'Fastbox', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTSHIP' => tr( 'Fastship Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTTRACK' => tr( 'fasttrack', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTWAY_AU' => tr( 'fastway_au', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTWAY_UK' => tr( 'FASTWAY_UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTWAY_US' => tr( 'FASTWAY_US', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTWAY_ZA' => tr( 'fastway_za', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FAXECARGO' => tr( 'Faxe Cargo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FEDEX_FR' => tr( 'FedEx® Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FEDEX_API' => tr( 'FedEx®', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FERCAM_IT' => tr( 'fercam_it', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FETCHR' => tr( 'Fetchr', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FIRST_LOGISTICS_API' => tr( 'First Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FIRST_LOGISITCS' => tr( 'first_logisitcs', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FITZMARK_API' => tr( 'FitzMark', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FLASHEXPRESS_WEBHOOK' => tr( 'Flash Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FLIGHTLG' => tr( 'Flight Logistics Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FLIPXP' => tr( 'FlipXpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FLYTEXPRESS' => tr( 'FLYTEXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FORWARDAIR' => tr( 'Forward Air', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FOUR_PX_EXPRESS' => tr( 'FOUR PX EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FR_COLISSIMO' => tr( 'fr_colissimo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FR_MONDIAL' => tr( 'fr_mondial', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FRAGILEPAK_SFTP' => tr( 'FragilePAK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FRONTDOORCORP' => tr( 'FRONTdoor Collective', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FUJEXP' => tr( 'FUJIE EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GWLOGIS_API' => tr( 'G.I.G', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GAC' => tr( 'GAC', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GATI_KWE_API' => tr( 'Gati-KWE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GDPHARM' => tr( 'GDPharm Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GW_WORLD' => tr( 'Gebrüder Weiss', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GEODIS' => tr( 'GEODIS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GEODIS_API' => tr( 'GEODIS - Distribution & Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GPOST' => tr( 'Georgian Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GIAO_HANG' => tr( 'Giao hàng nhanh', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GIO_ECOURIER_API' => tr( 'GIO Express Ecourier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GIO_ECOURIER' => tr( 'GIO Express Inc', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GOGLOBALPOST' => tr( 'Global Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLOBEGISTICS' => tr( 'GLOBEGISTICS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLOVO' => tr( 'Glovo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS' => tr( 'GLS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_SPAIN_API' => tr( 'GLS Spain', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_DE' => tr( 'GLS_DE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_ES' => tr( 'GLS_ES', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_FR' => tr( 'GLS_FR', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_ITALY_FTP' => tr( 'gls_italy_ftp', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_SPAIN' => tr( 'gls_spain', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GOLS' => tr( 'GO Logistics & Storage', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GOPEOPLE' => tr( 'Go People', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GORUSH' => tr( 'Go Rush', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GOJEK' => tr( 'Gojek', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GREYHOUND' => tr( 'GREYHOUND', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MAZET' => tr( 'Groupe Mazet', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HANJIN' => tr( 'HanJin', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HELLENIC_POST' => tr( 'Hellenic (Greece) Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HELLMANN' => tr( 'Hellmann Worldwide Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HELTHJEM_API' => tr( 'Helthjem', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HERMES_DE_FTP' => tr( 'Hermes Germany', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HERMES_UK_SFTP' => tr( 'Hermes UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HERMESWORLD_UK' => tr( 'hermesworld_uk', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HEROEXPRESS' => tr( 'Hero Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HFD' => tr( 'HFD', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HK_RPX' => tr( 'hk_rpx', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HOMELOGISTICS' => tr( 'Home Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HOMERUNNER' => tr( 'HomeRunner', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HERMES_IT' => tr( 'HR Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HSDEXPRESS' => tr( 'HSDEXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HSM_GLOBAL' => tr( 'HSM Global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HUANTONG' => tr( 'HuanTong', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HUBBED' => tr( 'HUBBED', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HUNTER_EXPRESS_SFTP' => tr( 'Hunter Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IBVENTURE_WEBHOOK' => tr( 'IB Venture', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTUR_IS' => tr( 'Iceland Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ICSCOURIER' => tr( 'ICS COURIER', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IDEXPRESS_ID' => tr( 'iDexpress Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IDN_POS' => tr( 'idn_pos', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IDS_LOGISTICS' => tr( 'ids_logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ILYANGLOGIS' => tr( 'Ilyang logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IMEXGLOBALSOLUTIONS' => tr( 'imexglobalsolutions', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IMILE_API' => tr( 'iMile', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IML' => tr( 'IML courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IMX' => tr( 'IMX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INDIA_POST' => tr( 'India Post Domestic', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INDIA_POST_INT' => tr( 'India Post International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INEXPOST' => tr( 'Inexpost', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INNTRALOG_SFTP' => tr( 'Inntralog GmbH', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INPOST_UK' => tr( 'InPost', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INSTABOX_WEBHOOK' => tr( 'Instabox', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTERNATIONAL_SEUR_API' => tr( 'International Seur API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTERSMARTTRANS' => tr( 'INTERSMARTTRANS & SOLUTIONS SL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTEX_DE' => tr( 'INTEX Paketdienst GmbH', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTIME_FTP' => tr( 'InTime', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ITHINKLOGISTICS' => tr( 'iThink Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JTCARGO' => tr( 'J&T CARGO', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JTEXPRESS_PH' => tr( 'J&T Express Philippines', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JTEXPRESS_SG_API' => tr( 'J&T Express Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JT_LOGISTICS' => tr( 'J&T International logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JAVIT' => tr( 'Javit', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_JCEX' => tr( 'JCEX courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JD_EXPRESS' => tr( 'JD Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JD_WORLDWIDE' => tr( 'JD Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JETSHIP_MY' => tr( 'jetship_my', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JNE_API' => tr( 'JNE (API)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IDN_JNE' => tr( 'JNE Express (Jalur Nugraha Ekakurir)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JOYINGBOX' => tr( 'joyingbox', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KARGOMKOLAY' => tr( 'KargomKolay (CargoMini)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KEDAEX' => tr( 'KedaEX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HK_TGX' => tr( 'Kerry Express Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KERRY_EXPRESS_TW_API' => tr( 'Kerry Express TaiWan', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'THA_KERRY' => tr( 'Kerry Express Thailand', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KERRY_EXPRESS_TH_WEBHOOK' => tr( 'Kerry Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KNG' => tr( 'Keuhne + Nagel Global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BE_KIALA' => tr( 'Kiala', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGISYSTEMS_SFTP' => tr( 'Kiitääjät', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KOMON_EXPRESS' => tr( 'Komon Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KRONOS_WEBHOOK' => tr( 'Kronos Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KRONOS' => tr( 'Kronos Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KUEHNE' => tr( 'Kuehne + Nagel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LALAMOVE_API' => tr( 'Lalamove', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LBCEXPRESS_FTP' => tr( 'LBC EXPRESS INC.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LBCEXPRESS_API' => tr( 'LBC EXPRESS INC.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LCTBR_API' => tr( 'LCT do Brasil', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LTU_LIETUVOS' => tr( 'Lietuvos pastas', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LINKBRIDGE' => tr( 'Link Bridge(BeiJing)international logistics co.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LION_PARCEL' => tr( 'LION PARCEL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LIVRAPIDE' => tr( 'Livrapide', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGGI' => tr( 'Loggi', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGISTICSWORLDWIDE_KR' => tr( 'LOGISTICSWORLDWIDE KR', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGISTICSWORLDWIDE_MY' => tr( 'LOGISTICSWORLDWIDE MY', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGWIN_LOGISTICS' => tr( 'Logwin Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGYSTO' => tr( 'Logysto', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LUWJISTIK' => tr( 'Luwjistik', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MX_CARGO' => tr( 'M&X cargo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'M3LOGISTICS' => tr( 'M3 Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'REIMAGINEDELIVERY' => tr( 'maergo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MAGYAR_POSTA_API' => tr( 'Magyar Posta', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MAIL_BOX_ETC' => tr( 'Mail Boxes Etc.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MYS_EMS' => tr( 'Malaysia Post EMS / Pos Laju', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MALCA_AMIT_API' => tr( 'Malca Amit', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MALCA_AMIT' => tr( 'Malca-Amit', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MARKEN' => tr( 'Marken', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MEDAFRICA' => tr( 'Med Africa Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MEEST' => tr( 'Meest', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MEGASAVE' => tr( 'megasave', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MENSAJEROSURBANOS_API' => tr( 'Mensajeros Urbanos', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MWD' => tr( 'Metropolitan Warehouse & Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MWD_API' => tr( 'Metropolitan Warehouse & Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MHI' => tr( 'Mhi', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MIKROPAKKET' => tr( 'Mikropakket', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MISUMI_CN' => tr( 'MISUMI Group Inc.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MNX' => tr( 'MNX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MOBI_BR' => tr( 'Mobi Logistica', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MONDIALRELAY_FR' => tr( 'Mondial Relay France', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MONDIALRELAY_ES' => tr( 'Mondial Relay Spain(Punto Pack)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MONDIAL_BE' => tr( 'MONDIAL_BE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MOOVA' => tr( 'Moova', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MORNINGLOBAL' => tr( 'Morning Global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MOTHERSHIP_API' => tr( 'Mothership', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MOVIANTO' => tr( 'Movianto', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MUDITA' => tr( 'MUDITA', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MYDYNALOGIC' => tr( 'My DynaLogic', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MYSENDLE_API' => tr( 'mySendle', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NMTRANSFER' => tr( 'N&M Transfer Co., Inc.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NACEX_SPAIN_REFERENCE' => tr( 'nacex_spain_reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NAEKO_FTP' => tr( 'Naeko Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NAQEL_EXPRESS' => tr( 'Naqel Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NEWZEALAND_COURIERS' => tr( 'NEW ZEALAND COURIERS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NEWGISTICS' => tr( 'Newgistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NEWGISTICSAPI' => tr( 'Newgistics API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NIGHTLINE_UK' => tr( 'nightline_uk', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NIMBUSPOST' => tr( 'NimbusPost', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NIPPON_EXPRESS_FTP' => tr( 'Nippon Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NIPPON_EXPRESS' => tr( 'Nippon Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NORTHLINE' => tr( 'Northline', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NOVA_POSHTA_API' => tr( 'Nova Poshta API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NOVOFARMA_WEBHOOK' => tr( 'Novofarma', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NTL' => tr( 'NTL logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NYTLOGISTICS' => tr( 'NYT SUPPLY CHAIN LOGISTICS Co., LTD', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OHI_WEBHOOK' => tr( 'Ohi', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHOPOLIVE' => tr( 'Olive', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OMLOGISTICS_API' => tr( 'OM LOGISTICS LTD', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OMNIRPS_WEBHOOK' => tr( 'Omni Returns', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ONTRAC' => tr( 'ONTRAC', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ORANGECONNEX' => tr( 'orangeconnex', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ORANGE_DS' => tr( 'OrangeDS (Orange Distribution Solutions Inc)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OSM_WORLDWIDE_SFTP' => tr( 'OSM Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OZEPARTS_SHIPPING' => tr( 'Ozeparts Shipping', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'P2P_TRC' => tr( 'P2P TrakPak', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PACKETA' => tr( 'Packeta', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PACKFLEET' => tr( 'PACKFLEET', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PACKS' => tr( 'Packs', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PAKAJO' => tr( 'Pakajo World', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PANDAGO_API' => tr( 'Pandago', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PANDION' => tr( 'Pandion', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PANDU' => tr( 'PANDU', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PANTHER_REFERENCE_API' => tr( 'Panther Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PANTHER_ORDER_NUMBER' => tr( 'panther_order_number', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PAPA_WEBHOOK' => tr( 'Papa', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCELRIGHT' => tr( 'Parcel Right', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCEL_2_POST' => tr( 'Parcel To Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCELFORCE' => tr( 'PARCELFORCE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCELSTARS_WEBHOOK' => tr( 'Parcelstars', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCLL' => tr( 'PARCLL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PASSPORTSHIPPING' => tr( 'Passport Shipping', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PATHEON' => tr( 'Patheon Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PAYO' => tr( 'Payo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PCHOME_API' => tr( 'Pchome Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PGEON_API' => tr( 'Pgeon', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PHSE_API' => tr( 'PHSE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PICKUPP_VNM' => tr( 'pickupp_vnm', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PIDGE' => tr( 'Pidge', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PIL_LOGISTICS' => tr( 'PIL Logistics (China) Co.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PLYCONGROUP' => tr( 'Plycon Transportation Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POLARSPEED' => tr( 'PolarSpeed Inc', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTONE' => tr( 'Post ONE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTAPLUS' => tr( 'Posta Plus', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTE_ITALIANE_PACCOCELERE' => tr( 'Poste Italiane Paccocelere', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTEN_NORGE' => tr( 'Posten Norge (www.posten.no)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTI_API' => tr( 'Posti API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTNL_INT_3_S' => tr( 'PostNL International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NLD_POSTNL' => tr( 'PostNL International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTNL_INTERNATIONAL' => tr( 'PostNL International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SWE_POSTNORD' => tr( 'Postnord sweden', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTPLUS' => tr( 'PostPlus', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PROCARRIER' => tr( 'Pro Carrier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PRODUCTCAREGROUP_SFTP' => tr( 'Product Care Services Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PROFESSIONAL_COURIERS' => tr( 'PROFESSIONAL COURIERS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PPL' => tr( 'Professional Parcel Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PROMEDDELIVERY' => tr( 'ProMed Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PUROLATOR' => tr( 'purolator', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PUROLATOR_INTERNATIONAL' => tr( 'Purolator International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'QTRACK' => tr( 'QTrack', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'QUALITYPOST' => tr( 'qualitypost', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'QINTL_API' => tr( 'Quickstat Courier LLC', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'QUIQUP' => tr( 'Quiqup', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RANSA_WEBHOOK' => tr( 'Ransa', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'REDJEPAKKETJE' => tr( 'Red je Pakketje', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RELAISCOLIS' => tr( 'Relais Colis', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RHENUS_GROUP' => tr( 'Rhenus Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RHENUS_UK_API' => tr( 'Rhenus Logistics UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AIR_CANADA' => tr( 'Rivo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RIXONHK_API' => tr( 'Rixon Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ROCHE_INTERNAL_SFTP' => tr( 'Roche Internal Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ROYAL_MAIL_FTP' => tr( 'Royal Mail', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ROYALSHIPMENTS' => tr( 'royalshipments', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RRDONNELLEY' => tr( 'rrdonnelley', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RUSSIAN_POST' => tr( 'Russian post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SAEE' => tr( 'saee', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SAGAWA' => tr( 'SAGAWA', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SAGAWA_API' => tr( 'Sagawa', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SBERLOGISTICS_RU' => tr( 'Sber Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SECRETLAB_WEBHOOK' => tr( 'Secretlab', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SEINO_API' => tr( 'Seino', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SEKO_SFTP' => tr( 'SEKO Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SENDING' => tr( 'Sending Transporte Urgente y Comunicacion', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHOWL' => tr( 'SENHONG INTERNATIONAL LOGISTICS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NOWLOG_API' => tr( 'Sequoialog', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SERVIENTREGA' => tr( 'Servientrega', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SERVIP_WEBHOOK' => tr( 'SerVIP', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SETEL' => tr( 'Setel Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SF_EX' => tr( 'SF Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SF_EXPRESS_CN' => tr( 'SF Express China', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SGT_IT' => tr( 'SGT_IT', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHADOWFAX' => tr( 'Shadowfax', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHENZHEN' => tr( 'shenzhen 1st International Logistics(Group)Co', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HOTSIN_CARGO' => tr( 'SHENZHEN HOTSIN CARGO INTL FORWARDING CO., LTD', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KWT' => tr( 'Shenzhen Jinghuada Logistics Co.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHERPA' => tr( 'Sherpa', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIPA' => tr( 'SHIPA', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIPPIE' => tr( 'Shippie', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIPPIFY' => tr( 'Shippify, Inc', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIPROCKET' => tr( 'Shiprocket X', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIPX' => tr( 'ShipX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIPXPRES' => tr( 'SHIPXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPX' => tr( 'Shopee Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPX_TH' => tr( 'Shopee Xpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHUNBANG_EXPRESS' => tr( 'ShunBang Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHYPLITE' => tr( 'Shypmax', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SIMPLETIRE_WEBHOOK' => tr( 'SimpleTire', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SIMSGLOBAL' => tr( 'Sims Global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SIODEMKA' => tr( 'SIODEMKA', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SKynet_WORLDWIDE' => tr( 'SkyNet Worldwide Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SKY_POSTAL' => tr( 'SkyPostal', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SK_POSTA' => tr( 'Slovenska pošta', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SMARTCAT' => tr( 'SMARTCAT', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SMARTKARGO' => tr( 'SmartKargo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SMG_EXPRESS' => tr( 'SMG Direct', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SMSA_EXPRESS_WEBHOOK' => tr( 'SMSA Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SNTGLOBAL_API' => tr( 'Snt Global Etrax', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SOLISTICA_API' => tr( 'solistica', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPANISH_SEUR_FTP' => tr( 'Spanish Seur', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPECTRAN' => tr( 'Spectran', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPEEDEX' => tr( 'speedex', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPEEDY' => tr( 'Speedy', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPREETAIL_API' => tr( 'Spreetail', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPRINT_PACK' => tr( 'SPRINT PACK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SRT_TRANSPORT' => tr( 'SRT Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STAR_TRACK_NEXT_FLIGHT' => tr( 'Star Track Next Flight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STARLINKS_API' => tr( 'Starlinks Global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STARTRACK' => tr( 'startrack', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STAR_TRACK_WEBHOOK' => tr( 'StarTrack', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STARTRACK_EXPRESS' => tr( 'startrack_express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STATOVERNIGHT' => tr( 'Stat Overnight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_STO' => tr( 'STO Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SWISHIP' => tr( 'Swiship', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SWISS_POST' => tr( 'SWISS POST', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'T_CAT' => tr( 'T-cat', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'T_CAT_API' => tr( 'T-cat', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGINEXT_WEBHOOK' => tr( 'T&W Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TW_TAIWAN_POST' => tr( 'Taiwan Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TAMERGROUP_WEBHOOK' => tr( 'Tamer Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TAQBIN_HK' => tr( 'TAQBIN Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TAQBIN_SG' => tr( 'taqbin_sg', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TCS_API' => tr( 'TCS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TECOR' => tr( 'tecor', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TELEPORT_WEBHOOK' => tr( 'Teleport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SIC_TELIWAY' => tr( 'Teliway SIC Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TESTING_COURIER_WEBHOOK' => tr( 'Testing Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TESTING_COURIER' => tr( 'Testing Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TH_CJ' => tr( 'TH_CJ', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'THIJS_NL' => tr( 'Thijs Logistiek', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'THUNDEREXPRESS' => tr( 'Thunder Express Australia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TIPSA_API' => tr( 'Tipsa API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TIPSA_REF' => tr( 'Tipsa Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_FR_REFERENCE' => tr( 'TNT France Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_REFR' => tr( 'TNT Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_AU' => tr( 'tnt_au', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_CN' => tr( 'TNT_CN', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_DE' => tr( 'TNT_DE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_ES' => tr( 'TNT_ES', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_IT' => tr( 'tnt_it', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_JP' => tr( 'TNT_JP', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_PL' => tr( 'TNT_PL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOLL_WEBHOOK' => tr( 'Toll Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOLL_IPEC' => tr( 'TOLL IPEC', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOLL_PRIORITY' => tr( 'Toll Priority', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOMYDOOR' => tr( 'Tomydoor', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TONAMI_FTP' => tr( 'Tonami', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ESDEX' => tr( 'Top Ideal Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOTAL_EXPRESS_API' => tr( 'Total Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOURLINE_REFERENCE' => tr( 'Tourline Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'THAIPARCELS' => tr( 'TP Logistic', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TRANS2U' => tr( 'Trans2u', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TRANSMISSION' => tr( 'TRANSMISSION', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TANET' => tr( 'Transport Ambientales', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TRANSVIRTUAL' => tr( 'TransVirtual', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TRUNKRS' => tr( 'Trunkrs', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TRUSK' => tr( 'Trusk France', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TUSKLOGISTICS' => tr( 'Tusk Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TYP' => tr( 'TYP', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'U_ENVIOS' => tr( 'U-ENVIOS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UBER_WEBHOOK' => tr( 'Uber', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UCS' => tr( 'UCS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UDS' => tr( 'United Delivery Service', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UPS' => tr( 'United Parcel Service', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UP_EXPRESS' => tr( 'up_express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UPARCEL' => tr( 'uParcel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UPS_API' => tr( 'UPS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UPS_FREIGHT' => tr( 'UPS Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UPS_REFERENCE' => tr( 'UPS Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'URGENT_CARGUS' => tr( 'Urgent Cargus', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'US_APC' => tr( 'us_apc', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'USPS_API' => tr( 'USPS API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PB_USPSFLATS_FTP' => tr( 'USPS Flats (Pitney Bowes)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'USPS_WEBHOOK' => tr( 'USPS Informed Visibility - Webhook', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VALUE_WEBHOOK' => tr( 'Value Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VIAXPRESS' => tr( 'ViaXpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VNPOST_API' => tr( 'Vietnam Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VIRTRANSPORT_SFTP' => tr( 'Vir Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VNPOST_EMS' => tr( 'vnpost_ems', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VOX' => tr( 'VOX SOLUCION EMPRESARIAL SRL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WATKINS_SHEPARD' => tr( 'watkins_shepard', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WEWORLDEXPRESS' => tr( 'We World Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WESHIP_API' => tr( 'WeShip', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WESHIP' => tr( 'WeShip', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WHISTL_SFTP' => tr( 'Whistl', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WINESHIPPING_WEBHOOK' => tr( 'Wineshipping', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WISH_EMAIL_PUSH' => tr( 'Wish', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WOOYOUNG_LOGISTICS_SFTP' => tr( 'WOO YOUNG LOGISTICS CO., LTD.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WORLDCOURIER' => tr( 'World Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WORLDNET' => tr( 'Worldnet Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WSPEXPRESS' => tr( 'WSP Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XYY' => tr( 'Xingyunyi Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XPEDIGO' => tr( 'Xpedigo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XPRESSBEES' => tr( 'XPRESSBEES', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YAMATO' => tr( 'YAMATO', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TAQBIN_SG_API' => tr( 'Yamato Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YIFAN' => tr( 'YiFan Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YODEL' => tr( 'yodel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YODEL_API' => tr( 'Yodel API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YODEL_DIR' => tr( 'Yodel Direct', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YODEL_INTNL' => tr( 'Yodel International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YUSEN' => tr( 'Yusen Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YUSEN_SFTP' => tr( 'Yusen Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YYCOM' => tr( 'yycom', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YYEXPRESS' => tr( 'YYEXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZTO_DOMESTIC' => tr( 'ZTO Express China', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZUELLIGPHARMA_SFTP' => tr( 'Zuellig Pharma Korea', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'AG' => array( - 'name' => _x( 'Argentina', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Argentina', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'FASTRACK' => _x( 'Fasttrack', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ANDREANI' => _x( 'Grupo logistico Andreani', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ARG_OCA' => _x( 'OCA Argentina', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTRACK' => tr( 'Fasttrack', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ANDREANI' => tr( 'Grupo logistico Andreani', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ARG_OCA' => tr( 'OCA Argentina', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'AU' => array( - 'name' => _x( 'Australia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Australia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ADSONE' => _x( 'Adsone', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ALLIEDEXPRESS' => _x( 'Allied Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ARAMEX_AU' => _x( 'Aramex Australia (formerly Fastway AU)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AU_AU_POST' => _x( 'Australia Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BLUESTAR' => _x( 'Blue Star', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BONDSCOURIERS' => _x( 'Bonds Courier Service (bondscouriers.com.au)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BORDEREXPRESS' => _x( 'Border Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COPE' => _x( 'Cope Sensitive Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COURIERS_PLEASE' => _x( 'CouriersPlease (couriersplease.com.au)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DELIVERE' => _x( 'deliverE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DESIGNERTRANSPORT_WEBHOOK' => _x( 'Designer Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_AU' => _x( 'DHL Supply Chain Australia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DIRECTCOURIERS' => _x( 'Direct Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DTDC_AU' => _x( 'DTDC Australia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ENDEAVOUR_DELIVERY' => _x( 'Endeavour Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HUNTER_EXPRESS' => _x( 'Hunter Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ICUMULUS' => _x( 'iCumulus', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTERPARCEL_AU' => _x( 'Interparcel Australia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NEWAY' => _x( 'Neway Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCELPOINT' => _x( 'Parcelpoint', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PFLOGISTICS' => _x( 'PFL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SENDLE' => _x( 'Sendle', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIPPIT' => _x( 'Shippit', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'THENILE_WEBHOOK' => _x( 'SortHub courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STAR_TRACK_EXPRESS' => _x( 'Star Track Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AUS_STARTRACK' => _x( 'StarTrack (startrack.com.au)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TFM' => _x( 'TFM Xpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TIGFREIGHT' => _x( 'TIG Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOLL' => _x( 'Toll IPEC', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UBI_LOGISTICS' => _x( 'UBI Smart Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XL_EXPRESS' => _x( 'XL Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ADSONE' => tr( 'Adsone', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ALLIEDEXPRESS' => tr( 'Allied Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ARAMEX_AU' => tr( 'Aramex Australia (formerly Fastway AU)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AU_AU_POST' => tr( 'Australia Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BLUESTAR' => tr( 'Blue Star', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BONDSCOURIERS' => tr( 'Bonds Courier Service (bondscouriers.com.au)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BORDEREXPRESS' => tr( 'Border Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COPE' => tr( 'Cope Sensitive Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COURIERS_PLEASE' => tr( 'CouriersPlease (couriersplease.com.au)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DELIVERE' => tr( 'deliverE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DESIGNERTRANSPORT_WEBHOOK' => tr( 'Designer Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_AU' => tr( 'DHL Supply Chain Australia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DIRECTCOURIERS' => tr( 'Direct Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DTDC_AU' => tr( 'DTDC Australia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ENDEAVOUR_DELIVERY' => tr( 'Endeavour Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HUNTER_EXPRESS' => tr( 'Hunter Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ICUMULUS' => tr( 'iCumulus', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTERPARCEL_AU' => tr( 'Interparcel Australia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NEWAY' => tr( 'Neway Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCELPOINT' => tr( 'Parcelpoint', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PFLOGISTICS' => tr( 'PFL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SENDLE' => tr( 'Sendle', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIPPIT' => tr( 'Shippit', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'THENILE_WEBHOOK' => tr( 'SortHub courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STAR_TRACK_EXPRESS' => tr( 'Star Track Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AUS_STARTRACK' => tr( 'StarTrack (startrack.com.au)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TFM' => tr( 'TFM Xpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TIGFREIGHT' => tr( 'TIG Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOLL' => tr( 'Toll IPEC', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UBI_LOGISTICS' => tr( 'UBI Smart Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XL_EXPRESS' => tr( 'XL Express', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'AT' => array( - 'name' => _x( 'Austria', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Austria', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'AUSTRIAN_POST_EXPRESS' => _x( 'Austrian Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AU_AUSTRIAN_POST' => _x( 'Austrian Post (Registered)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AUSTRIAN_POST_EXPRESS' => tr( 'Austrian Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AU_AUSTRIAN_POST' => tr( 'Austrian Post (Registered)', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'BGD' => array( - 'name' => _x( 'Bangladesh', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Bangladesh', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'PAPERFLY' => _x( 'Paperfly Private Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PAPERFLY' => tr( 'Paperfly Private Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'BE' => array( - 'name' => _x( 'Belgium', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Belgium', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'B_TWO_C_EUROPE' => _x( 'B2C courier Europe', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_BENELUX' => _x( 'dhl benelux', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BEL_DHL' => _x( 'DHL Benelux', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LANDMARK_GLOBAL' => _x( 'Landmark Global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LANDMARK_GLOBAL_REFERENCE' => _x( 'Landmark Global Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MIKROPAKKET_BE' => _x( 'Mikropakket Belgium', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'B_TWO_C_EUROPE' => tr( 'B2C courier Europe', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_BENELUX' => tr( 'dhl benelux', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BEL_DHL' => tr( 'DHL Benelux', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LANDMARK_GLOBAL' => tr( 'Landmark Global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LANDMARK_GLOBAL_REFERENCE' => tr( 'Landmark Global Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MIKROPAKKET_BE' => tr( 'Mikropakket Belgium', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'BIH' => array( - 'name' => _x( 'Bosnia and Herzegovina', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Bosnia and Herzegovina', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'BH_POSTA' => _x( 'BH Posta (www.posta.ba)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BH_POSTA' => tr( 'BH Posta (www.posta.ba)', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'BR' => array( - 'name' => _x( 'Brazil', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Brazil', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'BRA_CORREIOS' => _x( 'Correios Brazil', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DIRECTLOG' => _x( 'Directlog', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FRETERAPIDO' => _x( 'Frete Rapido', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTELIPOST' => _x( 'Intelipost', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOTAL_EXPRESS' => _x( 'Total Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BRA_CORREIOS' => tr( 'Correios Brazil', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DIRECTLOG' => tr( 'Directlog', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FRETERAPIDO' => tr( 'Frete Rapido', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTELIPOST' => tr( 'Intelipost', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOTAL_EXPRESS' => tr( 'Total Express', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'BG' => array( - 'name' => _x( 'Bulgaria', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Bulgaria', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'A1POST' => _x( 'A1Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BG_BULGARIAN_POST' => _x( 'Bulgarian Posts', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'A1POST' => tr( 'A1Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BG_BULGARIAN_POST' => tr( 'Bulgarian Posts', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'KHM' => array( - 'name' => _x( 'Cambodia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Cambodia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'AFLLOG_FTP' => _x( 'AFL LOGISTICS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KHM_CAMBODIA_POST' => _x( 'Cambodia Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ROADRUNNER_FREIGHT' => _x( 'Roadbull Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AFLLOG_FTP' => tr( 'AFL LOGISTICS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KHM_CAMBODIA_POST' => tr( 'Cambodia Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ROADRUNNER_FREIGHT' => tr( 'Roadbull Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'CA' => array( - 'name' => _x( 'Canada', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Canada', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CA_CANADA_POST' => _x( 'Canada Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CHITCHATS' => _x( 'Chit Chats', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CORPORATECOURIERS_WEBHOOK' => _x( 'Corporate Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COURANT_PLUS' => _x( 'Courant Plus', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLOBAL_ESTES' => _x( 'Estes Express Lines', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DICOM' => _x( 'GLS Logistic Systems Canada Ltd./Dicom', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOCUS_WEBHOOK' => _x( 'Locus courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOOMIS_EXPRESS' => _x( 'Loomis Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MBW' => _x( 'MBW Courier Inc.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NATIONEX' => _x( 'Nationex courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCELPAL_WEBHOOK' => _x( 'ParcelPal', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AIR_CANADA_GLOBAL' => _x( 'Rivo (Air canada)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ROUTIFIC_WEBHOOK' => _x( 'Routific', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RPXLOGISTICS' => _x( 'RPX Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STALLIONEXPRESS' => _x( 'Stallion Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZIINGFINALMILE' => _x( 'Ziing Final Mile Inc', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CA_CANADA_POST' => tr( 'Canada Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CHITCHATS' => tr( 'Chit Chats', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CORPORATECOURIERS_WEBHOOK' => tr( 'Corporate Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COURANT_PLUS' => tr( 'Courant Plus', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLOBAL_ESTES' => tr( 'Estes Express Lines', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DICOM' => tr( 'GLS Logistic Systems Canada Ltd./Dicom', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOCUS_WEBHOOK' => tr( 'Locus courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOOMIS_EXPRESS' => tr( 'Loomis Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MBW' => tr( 'MBW Courier Inc.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NATIONEX' => tr( 'Nationex courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCELPAL_WEBHOOK' => tr( 'ParcelPal', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AIR_CANADA_GLOBAL' => tr( 'Rivo (Air canada)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ROUTIFIC_WEBHOOK' => tr( 'Routific', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RPXLOGISTICS' => tr( 'RPX Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STALLIONEXPRESS' => tr( 'Stallion Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZIINGFINALMILE' => tr( 'Ziing Final Mile Inc', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'CL' => array( - 'name' => _x( 'Chile', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Chile', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'BLUEX' => _x( 'Blue Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STARKEN' => _x( 'STARKEN couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BLUEX' => tr( 'Blue Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STARKEN' => tr( 'STARKEN couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'CN' => array( - 'name' => _x( 'China', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'China', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CN_17POST' => _x( '17 Post Service', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ACSWORLDWIDE' => _x( 'ACS Worldwide Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CAINIAO' => _x( 'AliExpress Standard Shipping', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ANJUN' => _x( 'Anjun couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ANSERX' => _x( 'ANSERX courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AUPOST_CN' => _x( 'AuPost China', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BEL_RS' => _x( 'BEL North Russia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_BESTEXPRESS' => _x( 'Best Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_BOXC' => _x( 'BoxC courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BUYLOGIC' => _x( 'buylogic', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CPEX' => _x( 'Captain Express International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CGS_EXPRESS' => _x( 'CGS Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_CHINA_POST_EMS' => _x( 'China Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CHUKOU1' => _x( 'Chukou1', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CJPACKET' => _x( 'CJ Packet', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CLEVY_LINKS' => _x( 'Clevy Links', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CNDEXPRESS' => _x( 'CND Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CNEXPS' => _x( 'CNE Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COMET_TECH' => _x( 'CometTech', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CPACKET' => _x( 'Cpacket couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CUCKOOEXPRESS' => _x( 'Cuckoo Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DEX_I' => _x( 'DEX-I courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DIDADI' => _x( 'DIDADI Logistics tech', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPE_EXPRESS' => _x( 'DPE Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DTD_EXPR' => _x( 'DTD Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EMPS_CN' => _x( 'EMPS Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_EQUICK' => _x( 'Equick China', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ESHIPPING' => _x( 'Eshipping', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZES_EXPRESS' => _x( 'Eshun international Logistic', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FAR_INTERNATIONAL' => _x( 'Far international', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FARGOOD' => _x( 'FarGood', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FULFILLME' => _x( 'Fulfillme', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GANGBAO' => _x( 'GANGBAO Supplychain', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GESWL' => _x( 'GESWL Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_GOFLY' => _x( 'GoFly', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HDB' => _x( 'Haidaibao', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HDB_BOX' => _x( 'Haidaibao (BOX)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HH_EXP' => _x( 'Hua Han Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HUAHAN_EXPRESS' => _x( 'HUAHANG EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HUODULL' => _x( 'Huodull', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HX_EXPRESS' => _x( 'HX Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IDEXPRESS' => _x( 'IDEX courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTEL_VALLEY' => _x( 'Intel-Valley Supply chain (ShenZhen) Co. Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'J_NET' => _x( 'J-Net', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JINDOUYUN' => _x( 'jindouyun courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JOOM_LOGIS' => _x( 'Joom Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JOYING_BOX' => _x( 'Joying Box', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'K1_EXPRESS' => _x( 'K1 Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KY_EXPRESS' => _x( 'Kua Yue Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LALAMOVE' => _x( 'Lalamove', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LEADER' => _x( 'leader', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SDH_SCM' => _x( 'lightning monkey', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGISTERS' => _x( 'Logisters', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LTIANEXP' => _x( 'LTIAN EXP', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LTL' => _x( 'LTL COURIER', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MORE_LINK' => _x( 'Morelink', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MXE' => _x( 'MXE Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NANJINGWOYUAN' => _x( 'Nanjing Woyuan', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ONEWORLDEXPRESS' => _x( 'One World Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PADTF' => _x( 'padtf.com', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PAGO' => _x( 'Pago Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PAN_ASIA' => _x( 'Pan-Asia International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_PAYPAL_PACKAGE' => _x( 'PayPal Package', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PFCEXPRESS' => _x( 'PFC Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_POST56' => _x( 'Post56', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HKD' => _x( 'Qingdao HKD International Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ETS_EXPRESS' => _x( 'RETS express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RUSTON' => _x( 'Ruston', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_SF_EXPRESS' => _x( 'SF Express (www.sf-express.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SFB2C' => _x( 'SF International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SFC_LOGISTICS' => _x( 'SFC', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SFCSERVICE' => _x( 'SFC Service', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DAJIN' => _x( 'Shanghai Aqrum Chemical Logistics Co.Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SINOTRANS' => _x( 'Sinotrans', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STONE3PL' => _x( 'STONE3PL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SYPOST' => _x( 'Sunyou Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TARRIVE' => _x( 'TONDA GLOBAL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOPHATTEREXPRESS' => _x( 'Tophatter Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOPYOU' => _x( 'TopYou', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UC_EXPRE' => _x( 'ucexpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VIWO' => _x( 'VIWO IoT', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WANBEXPRESS' => _x( 'WanbExpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WEASHIP' => _x( 'Weaship', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_WEDO' => _x( 'WeDo Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WINIT' => _x( 'WinIt', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WISE_EXPRESS' => _x( 'Wise Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_WISHPOST' => _x( 'WishPost', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XQ_EXPRESS' => _x( 'XQ Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YANWEN' => _x( 'Yanwen Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YDH_EXPRESS' => _x( 'YDH express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ELIAN_POST' => _x( 'Yilian (Elian) Supply Chain', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YINGNUO_LOGISTICS' => _x( 'yingnuo logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YTO' => _x( 'YTO Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CN_YUNDA' => _x( 'Yunda Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YUNEXPRESS' => _x( 'YunExpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZJS_EXPRESS' => _x( 'ZJS International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZTO_EXPRESS' => _x( 'ZTO Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_17POST' => tr( '17 Post Service', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ACSWORLDWIDE' => tr( 'ACS Worldwide Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CAINIAO' => tr( 'AliExpress Standard Shipping', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ANJUN' => tr( 'Anjun couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ANSERX' => tr( 'ANSERX courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AUPOST_CN' => tr( 'AuPost China', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BEL_RS' => tr( 'BEL North Russia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_BESTEXPRESS' => tr( 'Best Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_BOXC' => tr( 'BoxC courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BUYLOGIC' => tr( 'buylogic', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CPEX' => tr( 'Captain Express International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CGS_EXPRESS' => tr( 'CGS Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_CHINA_POST_EMS' => tr( 'China Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CHUKOU1' => tr( 'Chukou1', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CJPACKET' => tr( 'CJ Packet', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CLEVY_LINKS' => tr( 'Clevy Links', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CNDEXPRESS' => tr( 'CND Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CNEXPS' => tr( 'CNE Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COMET_TECH' => tr( 'CometTech', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CPACKET' => tr( 'Cpacket couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CUCKOOEXPRESS' => tr( 'Cuckoo Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DEX_I' => tr( 'DEX-I courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DIDADI' => tr( 'DIDADI Logistics tech', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPE_EXPRESS' => tr( 'DPE Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DTD_EXPR' => tr( 'DTD Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EMPS_CN' => tr( 'EMPS Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_EQUICK' => tr( 'Equick China', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ESHIPPING' => tr( 'Eshipping', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZES_EXPRESS' => tr( 'Eshun international Logistic', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FAR_INTERNATIONAL' => tr( 'Far international', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FARGOOD' => tr( 'FarGood', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FULFILLME' => tr( 'Fulfillme', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GANGBAO' => tr( 'GANGBAO Supplychain', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GESWL' => tr( 'GESWL Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_GOFLY' => tr( 'GoFly', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HDB' => tr( 'Haidaibao', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HDB_BOX' => tr( 'Haidaibao (BOX)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HH_EXP' => tr( 'Hua Han Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HUAHAN_EXPRESS' => tr( 'HUAHANG EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HUODULL' => tr( 'Huodull', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HX_EXPRESS' => tr( 'HX Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IDEXPRESS' => tr( 'IDEX courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTEL_VALLEY' => tr( 'Intel-Valley Supply chain (ShenZhen) Co. Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'J_NET' => tr( 'J-Net', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JINDOUYUN' => tr( 'jindouyun courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JOOM_LOGIS' => tr( 'Joom Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JOYING_BOX' => tr( 'Joying Box', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'K1_EXPRESS' => tr( 'K1 Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KY_EXPRESS' => tr( 'Kua Yue Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LALAMOVE' => tr( 'Lalamove', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LEADER' => tr( 'leader', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SDH_SCM' => tr( 'lightning monkey', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGISTERS' => tr( 'Logisters', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LTIANEXP' => tr( 'LTIAN EXP', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LTL' => tr( 'LTL COURIER', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MORE_LINK' => tr( 'Morelink', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MXE' => tr( 'MXE Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NANJINGWOYUAN' => tr( 'Nanjing Woyuan', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ONEWORLDEXPRESS' => tr( 'One World Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PADTF' => tr( 'padtf.com', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PAGO' => tr( 'Pago Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PAN_ASIA' => tr( 'Pan-Asia International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_PAYPAL_PACKAGE' => tr( 'PayPal Package', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PFCEXPRESS' => tr( 'PFC Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_POST56' => tr( 'Post56', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HKD' => tr( 'Qingdao HKD International Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ETS_EXPRESS' => tr( 'RETS express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RUSTON' => tr( 'Ruston', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_SF_EXPRESS' => tr( 'SF Express (www.sf-express.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SFB2C' => tr( 'SF International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SFC_LOGISTICS' => tr( 'SFC', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SFCSERVICE' => tr( 'SFC Service', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DAJIN' => tr( 'Shanghai Aqrum Chemical Logistics Co.Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SINOTRANS' => tr( 'Sinotrans', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STONE3PL' => tr( 'STONE3PL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SYPOST' => tr( 'Sunyou Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TARRIVE' => tr( 'TONDA GLOBAL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOPHATTEREXPRESS' => tr( 'Tophatter Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOPYOU' => tr( 'TopYou', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UC_EXPRE' => tr( 'ucexpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VIWO' => tr( 'VIWO IoT', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WANBEXPRESS' => tr( 'WanbExpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WEASHIP' => tr( 'Weaship', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_WEDO' => tr( 'WeDo Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WINIT' => tr( 'WinIt', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WISE_EXPRESS' => tr( 'Wise Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_WISHPOST' => tr( 'WishPost', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XQ_EXPRESS' => tr( 'XQ Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YANWEN' => tr( 'Yanwen Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YDH_EXPRESS' => tr( 'YDH express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ELIAN_POST' => tr( 'Yilian (Elian) Supply Chain', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YINGNUO_LOGISTICS' => tr( 'yingnuo logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YTO' => tr( 'YTO Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CN_YUNDA' => tr( 'Yunda Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YUNEXPRESS' => tr( 'YunExpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZJS_EXPRESS' => tr( 'ZJS International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZTO_EXPRESS' => tr( 'ZTO Express', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'COL' => array( - 'name' => _x( 'Colombia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Colombia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'COORDINADORA' => _x( 'Coordinadora', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COORDINADORA' => tr( 'Coordinadora', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'HRV' => array( - 'name' => _x( 'Croatia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Croatia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'GLS_CROTIA' => _x( 'GLS Croatia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HRV_HRVATSKA' => _x( 'Hrvatska posta', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OVERSE_EXP' => _x( 'Overseas Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_CROTIA' => tr( 'GLS Croatia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HRV_HRVATSKA' => tr( 'Hrvatska posta', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OVERSE_EXP' => tr( 'Overseas Express', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'CY' => array( - 'name' => _x( 'Cyprus', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Cyprus', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CYPRUS_POST_CYP' => _x( 'Cyprus Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CYPRUS_POST_CYP' => tr( 'Cyprus Post', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'CZ' => array( - 'name' => _x( 'Czech Republic', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Czech Republic', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CESKA_CZ' => _x( 'Ceska Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLS_CZ' => _x( 'GLS Czech Republic', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CESKA_CZ' => tr( 'Ceska Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_CZ' => tr( 'GLS Czech Republic', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'DNK' => array( - 'name' => _x( 'Denmark', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Denmark', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'BUDBEE_WEBHOOK' => _x( 'Budbee courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DANSKE_FRAGT' => _x( 'Danske Fragtaend', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTNORD_LOGISTICS_DK' => _x( 'ostnord denmark', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTNORD_LOGISTICS' => _x( 'PostNord Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XPRESSEN_DK' => _x( 'Xpressen courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BUDBEE_WEBHOOK' => tr( 'Budbee courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DANSKE_FRAGT' => tr( 'Danske Fragtaend', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTNORD_LOGISTICS_DK' => tr( 'ostnord denmark', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTNORD_LOGISTICS' => tr( 'PostNord Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XPRESSEN_DK' => tr( 'Xpressen courier', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'EST' => array( - 'name' => _x( 'Estonia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Estonia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'OMNIVA' => _x( 'Omniva', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OMNIVA' => tr( 'Omniva', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'FIN' => array( - 'name' => _x( 'Finland', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Finland', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'MATKAHUOLTO' => _x( 'Matkahuolto', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTI' => _x( 'Posti courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MATKAHUOLTO' => tr( 'Matkahuolto', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTI' => tr( 'Posti courier', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'FR' => array( - 'name' => _x( 'France', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'France', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CHRONOPOST_FR' => _x( 'Chronopost france (www.chronopost.fr)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COLIS_PRIVE' => _x( 'Colis Privé', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FR_COLIS' => _x( 'Colissimo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CUBYN' => _x( 'Cubyn', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_FR' => _x( 'DPD France', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FR_EXAPAQ' => _x( 'DPD France (formerly exapaq)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GEODIS_ESPACE' => _x( 'Geodis E-space', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HEPPNER_FR' => _x( 'Heppner France', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LA_POSTE_SUIVI' => _x( 'La Poste', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_FR' => _x( 'TNT France', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VIRTRANSPORT' => _x( 'VIR Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CHRONOPOST_FR' => tr( 'Chronopost france (www.chronopost.fr)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COLIS_PRIVE' => tr( 'Colis Privé', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FR_COLIS' => tr( 'Colissimo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CUBYN' => tr( 'Cubyn', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_FR' => tr( 'DPD France', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FR_EXAPAQ' => tr( 'DPD France (formerly exapaq)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GEODIS_ESPACE' => tr( 'Geodis E-space', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HEPPNER_FR' => tr( 'Heppner France', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LA_POSTE_SUIVI' => tr( 'La Poste', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_FR' => tr( 'TNT France', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VIRTRANSPORT' => tr( 'VIR Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'DE' => array( - 'name' => _x( 'Germany', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Germany', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'HERMES_DE' => _x( 'Hermes Germany', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AO_DEUTSCHLAND' => _x( 'AO Deutschland', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DE_DPD_DELISTRACK' => _x( 'DPD Germany', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FIEGE' => _x( 'Fiege Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GEIS' => _x( 'Geis CZ', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GEL_EXPRESS' => _x( 'Gel Express Logistik', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GENERAL_OVERNIGHT' => _x( 'Go!Express and logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HEPPNER' => _x( 'Heppner Internationale Spedition GmbH & Co.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HERMES_2MANN_HANDLING' => _x( 'Hermes Einrichtungs Service GmbH & Co. KG', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NOX_NACHTEXPRESS' => _x( 'Innight Express Germany GmbH (nox NachtExpress)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LIEFERY' => _x( 'liefery', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NOX_NIGHT_TIME_EXPRESS' => _x( 'NOX NightTimeExpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCELONE' => _x( 'PARCEL ONE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PRESSIODE' => _x( 'Pressio', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RABEN_GROUP' => _x( 'Raben Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STRECK_TRANSPORT' => _x( 'Streck Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SWISHIP_DE' => _x( 'Swiship DE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HERMES_DE' => tr( 'Hermes Germany', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AO_DEUTSCHLAND' => tr( 'AO Deutschland', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DE_DPD_DELISTRACK' => tr( 'DPD Germany', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FIEGE' => tr( 'Fiege Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GEIS' => tr( 'Geis CZ', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GEL_EXPRESS' => tr( 'Gel Express Logistik', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GENERAL_OVERNIGHT' => tr( 'Go!Express and logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HEPPNER' => tr( 'Heppner Internationale Spedition GmbH & Co.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HERMES_2MANN_HANDLING' => tr( 'Hermes Einrichtungs Service GmbH & Co. KG', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NOX_NACHTEXPRESS' => tr( 'Innight Express Germany GmbH (nox NachtExpress)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LIEFERY' => tr( 'liefery', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NOX_NIGHT_TIME_EXPRESS' => tr( 'NOX NightTimeExpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCELONE' => tr( 'PARCEL ONE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PRESSIODE' => tr( 'Pressio', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RABEN_GROUP' => tr( 'Raben Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STRECK_TRANSPORT' => tr( 'Streck Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SWISHIP_DE' => tr( 'Swiship DE', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'GR' => array( - 'name' => _x( 'Greece', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Greece', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ACS_GR' => _x( 'ACS Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EASY_MAIL' => _x( 'Easy Mail', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GENIKI_GR' => _x( 'Geniki Taxydromiki', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPEEDCOURIERS_GR' => _x( 'Speed Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPEEDEXCOURIER' => _x( 'SPEEDEX couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ACS_GR' => tr( 'ACS Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EASY_MAIL' => tr( 'Easy Mail', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GENIKI_GR' => tr( 'Geniki Taxydromiki', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPEEDCOURIERS_GR' => tr( 'Speed Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPEEDEXCOURIER' => tr( 'SPEEDEX couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'HK' => array( - 'name' => _x( 'Hong Kong', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Hong Kong', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CFL_LOGISTICS' => _x( 'CFL Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CJ_HK_INTERNATIONAL' => _x( 'CJ Logistics International(Hong Kong)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CLE_LOGISTICS' => _x( 'CL E-Logistics Solutions Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CONTINENTAL' => _x( 'Continental', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COSTMETICSNOW' => _x( 'Cosmetics Now', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DEALERSEND' => _x( 'DealerSend', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_ECOMERCE_ASA' => _x( 'DHL eCommerce Asia (API)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_GLOBAL_MAIL_ASIA' => _x( 'DHL Global Mail Asia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_HK' => _x( 'DHL Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_HK' => _x( 'DPD Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DTDC_EXPRESS' => _x( 'DTDC express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLOBAVEND' => _x( 'Globavend', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HK_POST' => _x( 'Hongkong Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JANCO' => _x( 'Janco Ecommerce', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JS_EXPRESS' => _x( 'JS EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KEC' => _x( 'KEC courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KERRY_ECOMMERCE' => _x( 'Kerry eCommerce', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LHT_EXPRESS' => _x( 'LHT Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGISTICSWORLDWIDE_HK' => _x( 'Logistic Worldwide Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MAINWAY' => _x( 'Mainway', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MORNING_EXPRESS' => _x( 'Morning Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OKAYPARCEL' => _x( 'OkayParcel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OMNIPARCEL' => _x( 'Omni Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PALEXPRESS' => _x( 'PAL Express Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PICKUP' => _x( 'Pickupp', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'QUANTIUM' => _x( 'Quantium', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RPX' => _x( 'RPX Online', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SEKOLOGISTICS' => _x( 'SEKO Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIP_IT_ASIA' => _x( 'Ship It Asia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SMOOTH' => _x( 'Smooth Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'STEPFORWARDFS' => _x( 'STEP FORWARD FREIGHT SERVICE CO LTD', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SFPLUS_WEBHOOK' => _x( 'Zeek courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZEEK_2_DOOR' => _x( 'Zeek2Door', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CFL_LOGISTICS' => tr( 'CFL Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CJ_HK_INTERNATIONAL' => tr( 'CJ Logistics International(Hong Kong)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CLE_LOGISTICS' => tr( 'CL E-Logistics Solutions Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CONTINENTAL' => tr( 'Continental', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COSTMETICSNOW' => tr( 'Cosmetics Now', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DEALERSEND' => tr( 'DealerSend', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_ECOMERCE_ASA' => tr( 'DHL eCommerce Asia (API)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_GLOBAL_MAIL_ASIA' => tr( 'DHL Global Mail Asia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_HK' => tr( 'DHL Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_HK' => tr( 'DPD Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DTDC_EXPRESS' => tr( 'DTDC express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLOBAVEND' => tr( 'Globavend', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HK_POST' => tr( 'Hongkong Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JANCO' => tr( 'Janco Ecommerce', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JS_EXPRESS' => tr( 'JS EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KEC' => tr( 'KEC courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KERRY_ECOMMERCE' => tr( 'Kerry eCommerce', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LHT_EXPRESS' => tr( 'LHT Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGISTICSWORLDWIDE_HK' => tr( 'Logistic Worldwide Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MAINWAY' => tr( 'Mainway', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MORNING_EXPRESS' => tr( 'Morning Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OKAYPARCEL' => tr( 'OkayParcel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OMNIPARCEL' => tr( 'Omni Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PALEXPRESS' => tr( 'PAL Express Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PICKUP' => tr( 'Pickupp', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'QUANTIUM' => tr( 'Quantium', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RPX' => tr( 'RPX Online', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SEKOLOGISTICS' => tr( 'SEKO Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIP_IT_ASIA' => tr( 'Ship It Asia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SMOOTH' => tr( 'Smooth Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'STEPFORWARDFS' => tr( 'STEP FORWARD FREIGHT SERVICE CO LTD', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SFPLUS_WEBHOOK' => tr( 'Zeek courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZEEK_2_DOOR' => tr( 'Zeek2Door', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'HU' => array( - 'name' => _x( 'Hungary', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Hungary', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'DPD_HGRY' => _x( 'DPD Hungary', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MAGYAR_HU' => _x( 'Magyar Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_HGRY' => tr( 'DPD Hungary', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MAGYAR_HU' => tr( 'Magyar Post', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'IN' => array( - 'name' => _x( 'India', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'India', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'BOMBINOEXP' => _x( 'Bombino Express Pvt', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IND_DELHIVERY' => _x( 'Delhivery India', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DELIVERYONTIME' => _x( 'DELIVERYONTIME LOGISTICS PVT LTD', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DTDC_IN' => _x( 'DTDC India', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IND_ECOM' => _x( 'Ecom Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EKART' => _x( 'Ekart logistics (ekartlogistics.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IND_FIRSTFLIGHT' => _x( 'First Flight Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IND_GATI' => _x( 'Gati-KWE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IND_GOJAVAS' => _x( 'GoJavas', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HOLISOL' => _x( 'Holisol', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LEXSHIP' => _x( 'LexShip', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OCS' => _x( 'OCS ANA Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCELLED_IN' => _x( 'Parcelled.in', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PICKRR' => _x( 'Pickrr', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IND_SAFEEXPRESS' => _x( 'Safexpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SCUDEX_EXPRESS' => _x( 'Scudex Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHREE_ANJANI_COURIER' => _x( 'Shree Anjani Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHREE_MARUTI' => _x( 'Shree Maruti Courier Services Pvt Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHREENANDANCOURIER' => _x( 'SHREE NANDAN COURIER', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHREETIRUPATI' => _x( 'SHREE TIRUPATI COURIER SERVICES PVT. LTD.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPOTON' => _x( 'SPOTON Logistics Pvt Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TRACKON' => _x( 'Trackon Couriers Pvt. Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BOMBINOEXP' => tr( 'Bombino Express Pvt', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IND_DELHIVERY' => tr( 'Delhivery India', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DELIVERYONTIME' => tr( 'DELIVERYONTIME LOGISTICS PVT LTD', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DTDC_IN' => tr( 'DTDC India', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IND_ECOM' => tr( 'Ecom Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EKART' => tr( 'Ekart logistics (ekartlogistics.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IND_FIRSTFLIGHT' => tr( 'First Flight Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IND_GATI' => tr( 'Gati-KWE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IND_GOJAVAS' => tr( 'GoJavas', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HOLISOL' => tr( 'Holisol', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LEXSHIP' => tr( 'LexShip', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OCS' => tr( 'OCS ANA Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCELLED_IN' => tr( 'Parcelled.in', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PICKRR' => tr( 'Pickrr', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IND_SAFEEXPRESS' => tr( 'Safexpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SCUDEX_EXPRESS' => tr( 'Scudex Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHREE_ANJANI_COURIER' => tr( 'Shree Anjani Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHREE_MARUTI' => tr( 'Shree Maruti Courier Services Pvt Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHREENANDANCOURIER' => tr( 'SHREE NANDAN COURIER', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHREETIRUPATI' => tr( 'SHREE TIRUPATI COURIER SERVICES PVT. LTD.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPOTON' => tr( 'SPOTON Logistics Pvt Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TRACKON' => tr( 'Trackon Couriers Pvt. Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'ID' => array( - 'name' => _x( 'Indonesia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Indonesia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ALFATREX' => _x( 'AlfaTrex', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CHOIR_EXP' => _x( 'Choir Express Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INDOPAKET' => _x( 'INDOPAKET', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JX' => _x( 'JX courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KURASI' => _x( 'KURASI', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NINJAVAN_ID' => _x( 'Ninja Van Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NINJAVAN_WB' => _x( 'Ninjavan Webhook', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MGLOBAL' => _x( 'PT MGLOBAL LOGISTICS INDONESIA', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PRIMAMULTICIPTA' => _x( 'PT Prima Multi Cipta', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RCL' => _x( 'Red Carpet Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RPX_ID' => _x( 'RPX Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SAP_EXPRESS' => _x( 'SAP EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SIN_GLBL' => _x( 'Sin Global Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TIKI_ID' => _x( 'Tiki shipment', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TRANS_KARGO' => _x( 'Trans Kargo Internasional', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WAHANA_ID' => _x( 'Wahana express (www.wahana.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ALFATREX' => tr( 'AlfaTrex', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CHOIR_EXP' => tr( 'Choir Express Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INDOPAKET' => tr( 'INDOPAKET', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JX' => tr( 'JX courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KURASI' => tr( 'KURASI', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NINJAVAN_ID' => tr( 'Ninja Van Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NINJAVAN_WB' => tr( 'Ninjavan Webhook', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MGLOBAL' => tr( 'PT MGLOBAL LOGISTICS INDONESIA', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PRIMAMULTICIPTA' => tr( 'PT Prima Multi Cipta', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RCL' => tr( 'Red Carpet Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RPX_ID' => tr( 'RPX Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SAP_EXPRESS' => tr( 'SAP EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SIN_GLBL' => tr( 'Sin Global Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TIKI_ID' => tr( 'Tiki shipment', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TRANS_KARGO' => tr( 'Trans Kargo Internasional', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WAHANA_ID' => tr( 'Wahana express (www.wahana.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'IE' => array( - 'name' => _x( 'Ireland', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Ireland', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'AN_POST' => _x( 'An Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_IR' => _x( 'DPD Ireland', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FASTWAY_IR' => _x( 'Fastway Ireland', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WISELOADS' => _x( 'Wiseloads', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AN_POST' => tr( 'An Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_IR' => tr( 'DPD Ireland', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTWAY_IR' => tr( 'Fastway Ireland', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WISELOADS' => tr( 'Wiseloads', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'IL' => array( - 'name' => _x( 'Israel', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Israel', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ISRAEL_POST' => _x( 'Israel Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ISR_POST_DOMESTIC' => _x( 'Israel Post Domestic', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ISRAEL_POST' => tr( 'Israel Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ISR_POST_DOMESTIC' => tr( 'Israel Post Domestic', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'IT' => array( - 'name' => _x( 'Italy', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Italy', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'BRT_IT_PARCELID' => _x( 'BRT Bartolini (Parcel ID)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BRT_IT' => _x( 'BRT Couriers Italy', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ARCO_SPEDIZIONI' => _x( 'Arco Spedizioni SP', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BLINKLASTMILE' => _x( 'Blink', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BRT_IT_SENDER_REF' => _x( 'BRT Bartolini (Sender Reference)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DMM_NETWORK' => _x( 'DMM Network', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLS_IT' => _x( 'GLS Italy', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HRPARCEL' => _x( 'HR Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'I_DIKA' => _x( 'i-dika', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LICCARDI_EXPRESS' => _x( 'LICCARDI EXPRESS COURIER', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MILKMAN' => _x( 'Milkman Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IT_NEXIVE' => _x( 'Nexive (TNT Post Italy)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IT_POSTE_ITALIA' => _x( 'Poste Italiane', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SAILPOST' => _x( 'SAILPOST', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SDA_IT' => _x( 'SDA Italy', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_CLICK_IT' => _x( 'TNT-Click Italy', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BRT_IT_PARCELID' => tr( 'BRT Bartolini (Parcel ID)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BRT_IT' => tr( 'BRT Couriers Italy', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ARCO_SPEDIZIONI' => tr( 'Arco Spedizioni SP', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BLINKLASTMILE' => tr( 'Blink', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BRT_IT_SENDER_REF' => tr( 'BRT Bartolini (Sender Reference)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DMM_NETWORK' => tr( 'DMM Network', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_IT' => tr( 'GLS Italy', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HRPARCEL' => tr( 'HR Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'I_DIKA' => tr( 'i-dika', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LICCARDI_EXPRESS' => tr( 'LICCARDI EXPRESS COURIER', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MILKMAN' => tr( 'Milkman Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IT_NEXIVE' => tr( 'Nexive (TNT Post Italy)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IT_POSTE_ITALIA' => tr( 'Poste Italiane', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SAILPOST' => tr( 'SAILPOST', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SDA_IT' => tr( 'SDA Italy', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_CLICK_IT' => tr( 'TNT-Click Italy', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'JP' => array( - 'name' => _x( 'Japan', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Japan', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'EFEX' => _x( 'eFEx (E-Commerce Fulfillment & Express)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JPN_JAPAN_POST' => _x( 'Japan Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KWE_GLOBAL' => _x( 'KWE Global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MAIL_PLUS' => _x( 'MailPlus', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MAILPLUS_JPN' => _x( 'MailPlus (Japan)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SEINO' => _x( 'Seino', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EFEX' => tr( 'eFEx (E-Commerce Fulfillment & Express)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JPN_JAPAN_POST' => tr( 'Japan Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KWE_GLOBAL' => tr( 'KWE Global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MAIL_PLUS' => tr( 'MailPlus', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MAILPLUS_JPN' => tr( 'MailPlus (Japan)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SEINO' => tr( 'Seino', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'JEY' => array( - 'name' => _x( 'Jersey', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Jersey', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'JERSEY_POST' => _x( 'Jersey Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JERSEY_POST' => tr( 'Jersey Post', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'KR' => array( - 'name' => _x( 'Korea', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Korea', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CELLO_SQUARE' => _x( 'Cello Square', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CROSHOT' => _x( 'Croshot', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DOORA' => _x( 'Doora Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EPARCEL_KR' => _x( 'eParcel Korea', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KPOST' => _x( 'Korea Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KR_KOREA_POST' => _x( 'Koreapost (www.koreapost.go.kr)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KYUNGDONG_PARCEL' => _x( 'Kyungdong Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOTTE' => _x( 'Lotte Global Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RINCOS' => _x( 'Rincos', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ROCKET_PARCEL' => _x( 'Rocket Parcel International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIP_GATE' => _x( 'ShipGate', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIPTER' => _x( 'SHIPTER', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SRE_KOREA' => _x( 'SRE Korea (www.srekorea.co.kr)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOLOS' => _x( 'Tolos courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CELLO_SQUARE' => tr( 'Cello Square', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CROSHOT' => tr( 'Croshot', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DOORA' => tr( 'Doora Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EPARCEL_KR' => tr( 'eParcel Korea', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KPOST' => tr( 'Korea Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KR_KOREA_POST' => tr( 'Koreapost (www.koreapost.go.kr)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KYUNGDONG_PARCEL' => tr( 'Kyungdong Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOTTE' => tr( 'Lotte Global Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RINCOS' => tr( 'Rincos', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ROCKET_PARCEL' => tr( 'Rocket Parcel International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIP_GATE' => tr( 'ShipGate', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIPTER' => tr( 'SHIPTER', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SRE_KOREA' => tr( 'SRE Korea (www.srekorea.co.kr)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOLOS' => tr( 'Tolos courier', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'KWT' => array( - 'name' => _x( 'Kuwait', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Kuwait', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'POSTA_PLUS' => _x( 'Posta Plus', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTA_PLUS' => tr( 'Posta Plus', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'LAO' => array( - 'name' => _x( "Lao People's Democratic Republic (the)", 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( "Lao People's Democratic Republic (the)", 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'LAO_POST' => _x( 'Lao Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LAO_POST' => tr( 'Lao Post', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'LVA' => array( - 'name' => _x( 'Latvia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Latvia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CDEK' => _x( 'CDEK courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LATVIJAS_PASTS' => _x( 'Latvijas Pasts', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CDEK' => tr( 'CDEK courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LATVIJAS_PASTS' => tr( 'Latvijas Pasts', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'LT' => array( - 'name' => _x( 'Lithuania', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Lithuania', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'VENIPAK' => _x( 'Venipak', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VENIPAK' => tr( 'Venipak', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'MY' => array( - 'name' => _x( 'Malaysia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Malaysia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ABXEXPRESS_MY' => _x( 'ABX Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MYS_AIRPAK' => _x( 'Airpak Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CITYLINK_MY' => _x( 'City-Link Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CJ_CENTURY' => _x( 'CJ Century', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CJ_INT_MY' => _x( 'CJ International Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COLLECTCO' => _x( 'CollectCo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FMX' => _x( 'FMX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MYS_GDEX' => _x( 'GDEX Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JTEXPRESS' => _x( 'J&T EXPRESS MALAYSIA', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JINSUNG' => _x( 'JINSUNG TRADING', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JOCOM' => _x( 'Jocom', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KANGAROO_MY' => _x( 'Kangaroo Worldwide Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LINE' => _x( 'Line Clear Express & Logistics Sdn Bhd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGISTIKA' => _x( 'Logistika', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'M_XPRESS' => _x( 'M Xpress Sdn Bhd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MYS_MYS_POST' => _x( 'Malaysia Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MATDESPATCH' => _x( 'Matdespatch', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MYS_MYPOST_ONLINE' => _x( 'Mypostonline', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NATIONWIDE_MY' => _x( 'Nationwide Express Courier Services Bhd (www.nationwide.com.my)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NINJAVAN_MY' => _x( 'Ninja Van (www.ninjavan.co)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PICKUPP_MYS' => _x( 'PICK UPP', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MYS_SKYNET' => _x( 'Skynet Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TAQBIN_MY' => _x( 'TAQBIN Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WEPOST' => _x( 'WePost Sdn Bhd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WYNGS' => _x( 'Wyngs', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZEPTO_EXPRESS' => _x( 'ZeptoExpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ABXEXPRESS_MY' => tr( 'ABX Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MYS_AIRPAK' => tr( 'Airpak Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CITYLINK_MY' => tr( 'City-Link Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CJ_CENTURY' => tr( 'CJ Century', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CJ_INT_MY' => tr( 'CJ International Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COLLECTCO' => tr( 'CollectCo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FMX' => tr( 'FMX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MYS_GDEX' => tr( 'GDEX Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JTEXPRESS' => tr( 'J&T EXPRESS MALAYSIA', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JINSUNG' => tr( 'JINSUNG TRADING', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JOCOM' => tr( 'Jocom', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KANGAROO_MY' => tr( 'Kangaroo Worldwide Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LINE' => tr( 'Line Clear Express & Logistics Sdn Bhd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGISTIKA' => tr( 'Logistika', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'M_XPRESS' => tr( 'M Xpress Sdn Bhd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MYS_MYS_POST' => tr( 'Malaysia Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MATDESPATCH' => tr( 'Matdespatch', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MYS_MYPOST_ONLINE' => tr( 'Mypostonline', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NATIONWIDE_MY' => tr( 'Nationwide Express Courier Services Bhd (www.nationwide.com.my)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NINJAVAN_MY' => tr( 'Ninja Van (www.ninjavan.co)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PICKUPP_MYS' => tr( 'PICK UPP', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MYS_SKYNET' => tr( 'Skynet Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TAQBIN_MY' => tr( 'TAQBIN Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WEPOST' => tr( 'WePost Sdn Bhd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WYNGS' => tr( 'Wyngs', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZEPTO_EXPRESS' => tr( 'ZeptoExpress', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'MX' => array( - 'name' => _x( 'Mexico', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Mexico', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CORREOS_DE_MEXICO' => _x( 'Correos Mexico', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MEX_ESTAFETA' => _x( 'Estafeta (www.estafeta.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GRUPO' => _x( 'Grupo ampm', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HOUNDEXPRESS' => _x( 'Hound Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IVOY_WEBHOOK' => _x( 'Ivoy courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MEX_SENDA' => _x( 'Mexico Senda Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PAQUETEXPRESS' => _x( 'Paquetexpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MEX_REDPACK' => _x( 'Redpack', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CORREOS_DE_MEXICO' => tr( 'Correos Mexico', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MEX_ESTAFETA' => tr( 'Estafeta (www.estafeta.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GRUPO' => tr( 'Grupo ampm', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HOUNDEXPRESS' => tr( 'Hound Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IVOY_WEBHOOK' => tr( 'Ivoy courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MEX_SENDA' => tr( 'Mexico Senda Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PAQUETEXPRESS' => tr( 'Paquetexpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MEX_REDPACK' => tr( 'Redpack', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'NL' => array( - 'name' => _x( 'Netherlands', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Netherlands', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'BROUWER_TRANSPORT' => _x( 'Brouwer Transport en Logistiek', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NLD_DHL' => _x( 'DHL Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FIEGE_NL' => _x( 'Fiege Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NLD_GLS' => _x( 'GLS Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HAPPY2POINT' => _x( 'Happy 2ThePoint', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PAPER_EXPRESS' => _x( 'Paper Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTNL_INTL_3S' => _x( 'PostNL International 3S', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TRUNKRS_WEBHOOK' => _x( 'Trunkrs courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BROUWER_TRANSPORT' => tr( 'Brouwer Transport en Logistiek', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NLD_DHL' => tr( 'DHL Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FIEGE_NL' => tr( 'Fiege Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NLD_GLS' => tr( 'GLS Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HAPPY2POINT' => tr( 'Happy 2ThePoint', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PAPER_EXPRESS' => tr( 'Paper Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTNL_INTL_3S' => tr( 'PostNL International 3S', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TRUNKRS_WEBHOOK' => tr( 'Trunkrs courier', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'NZ' => array( - 'name' => _x( 'New Zealand', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'New Zealand', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'FASTWAY_NZ' => _x( 'Fastway New Zealand', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTERPARCEL_NZ' => _x( 'Interparcel New Zealand', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MAINFREIGHT' => _x( 'Mainfreight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NZ_NZ_POST' => _x( 'New Zealand Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOLL_NZ' => _x( 'Toll New Zealand', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTWAY_NZ' => tr( 'Fastway New Zealand', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTERPARCEL_NZ' => tr( 'Interparcel New Zealand', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MAINFREIGHT' => tr( 'Mainfreight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NZ_NZ_POST' => tr( 'New Zealand Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOLL_NZ' => tr( 'Toll New Zealand', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'NG' => array( - 'name' => _x( 'Nigeria', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Nigeria', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'NIPOST_NG' => _x( 'NIpost (www.nipost.gov.ng)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NIPOST_NG' => tr( 'NIpost (www.nipost.gov.ng)', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'NO' => array( - 'name' => _x( 'Norway', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Norway', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'HELTHJEM' => _x( 'Helthjem', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HELTHJEM' => tr( 'Helthjem', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'PAK' => array( - 'name' => _x( 'Pakistan', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Pakistan', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'FORRUN' => _x( 'forrun Pvt Ltd (Arpatech Venture)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TCS' => _x( 'TCS courier ', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FORRUN' => tr( 'forrun Pvt Ltd (Arpatech Venture)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TCS' => tr( 'TCS courier ', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'PRY' => array( - 'name' => _x( 'Paraguay', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Paraguay', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'AEX' => _x( 'AEX Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AEX' => tr( 'AEX Group', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'PH' => array( - 'name' => _x( 'Philippines', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Philippines', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'TWO_GO' => _x( '2GO Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PHL_JAMEXPRESS' => _x( 'Jam Express Philippines', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PIXSELL' => _x( 'PIXSELL LOGISTICS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RAF_PH' => _x( 'RAF Philippines', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XDE_WEBHOOK' => _x( 'Ximex Delivery Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XPOST' => _x( 'Xpost.ph', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TWO_GO' => tr( '2GO Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PHL_JAMEXPRESS' => tr( 'Jam Express Philippines', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PIXSELL' => tr( 'PIXSELL LOGISTICS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RAF_PH' => tr( 'RAF Philippines', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XDE_WEBHOOK' => tr( 'Ximex Delivery Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XPOST' => tr( 'Xpost.ph', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'PL' => array( - 'name' => _x( 'Poland', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Poland', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'DHL_PL' => _x( 'DHL Poland', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_POLAND' => _x( 'DPD Poland', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FEDEX_POLAND' => _x( 'FedEx® Poland Domestic', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INPOST_PACZKOMATY' => _x( 'InPost Paczkomaty', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PL_POCZTA_POLSKA' => _x( 'Poczta Polska', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ROYAL_MAIL' => _x( 'Royal Mail', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_PL' => tr( 'DHL Poland', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_POLAND' => tr( 'DPD Poland', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FEDEX_POLAND' => tr( 'FedEx® Poland Domestic', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INPOST_PACZKOMATY' => tr( 'InPost Paczkomaty', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PL_POCZTA_POLSKA' => tr( 'Poczta Polska', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ROYAL_MAIL' => tr( 'Royal Mail', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'PT' => array( - 'name' => _x( 'Portugal', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Portugal', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ADICIONAL' => _x( 'Adicional Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BNEED' => _x( 'Bneed courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CARRIERS' => _x( 'Carriers courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PRT_CHRONOPOST' => _x( 'Chronopost Portugal', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PRT_CTT' => _x( 'CTT Portugal', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DELNEXT' => _x( 'Delnext', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ADICIONAL' => tr( 'Adicional Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BNEED' => tr( 'Bneed courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CARRIERS' => tr( 'Carriers courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PRT_CHRONOPOST' => tr( 'Chronopost Portugal', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PRT_CTT' => tr( 'CTT Portugal', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DELNEXT' => tr( 'Delnext', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'RO' => array( - 'name' => _x( 'Romania', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Romania', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'DPD_RO' => _x( 'DPD Romania', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTA_RO' => _x( 'Post Roman (www.posta-romana.ro)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_RO' => tr( 'DPD Romania', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTA_RO' => tr( 'Post Roman (www.posta-romana.ro)', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'RUS' => array( - 'name' => _x( 'Russia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Russia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'BOX_BERRY' => _x( 'Boxberry courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CSE' => _x( 'CSE courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_PARCEL_RU' => _x( 'DHL Parcel Russia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DOBROPOST' => _x( 'DobroPost', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_RU' => _x( 'DPD Russia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EXPRESSSALE' => _x( 'Expresssale', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GBS_BROKER' => _x( 'GBS-Broker', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PONY_EXPRESS' => _x( 'Pony express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHOPFANS' => _x( 'ShopfansRU LLC', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BOX_BERRY' => tr( 'Boxberry courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CSE' => tr( 'CSE courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_PARCEL_RU' => tr( 'DHL Parcel Russia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DOBROPOST' => tr( 'DobroPost', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_RU' => tr( 'DPD Russia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EXPRESSSALE' => tr( 'Expresssale', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GBS_BROKER' => tr( 'GBS-Broker', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PONY_EXPRESS' => tr( 'Pony express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHOPFANS' => tr( 'ShopfansRU LLC', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'SAU' => array( - 'name' => _x( 'Saudi Arabia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Saudi Arabia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'SAU_SAUDI_POST' => _x( 'Saudi Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SMSA_EXPRESS' => _x( 'SMSA Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'THABIT_LOGISTICS' => _x( 'Thabit Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZAJIL_EXPRESS' => _x( 'Zajil Express Company', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SAU_SAUDI_POST' => tr( 'Saudi Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SMSA_EXPRESS' => tr( 'SMSA Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'THABIT_LOGISTICS' => tr( 'Thabit Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZAJIL_EXPRESS' => tr( 'Zajil Express Company', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'SRB' => array( - 'name' => _x( 'Serbia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Serbia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'POST_SERBIA' => _x( 'Posta Serbia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POST_SERBIA' => tr( 'Posta Serbia', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'SG' => array( - 'name' => _x( 'Singapore', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Singapore', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CLOUDWISH_ASIA' => _x( 'Cloudwish Asia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SG_DETRACK' => _x( 'Detrack', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FONSEN' => _x( 'Fonsen Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GRAB_WEBHOOK' => _x( 'Grab courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SIMPLYPOST' => _x( 'J&T Express Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JANIO' => _x( 'Janio Asia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'IND_JAYONEXPRESS' => _x( 'Jayon Express (JEX)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'JET_SHIP' => _x( 'Jet-Ship Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KGMHUB' => _x( 'KGM Hub', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LEGION_EXPRESS' => _x( 'Legion Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NHANS_SOLUTIONS' => _x( 'Nhans Solutions', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NINJAVAN_SG' => _x( 'Ninja van Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCELPOST_SG' => _x( 'Parcel Post Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARKNPARCEL' => _x( 'Park N Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PICKUPP_SGP' => _x( 'PICK UPP (Singapore)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SG_QXPRESS' => _x( 'Qxpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RAIDEREX' => _x( 'RaidereX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ROADBULL' => _x( 'Red Carpet Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RZYEXPRESS' => _x( 'RZY Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SG_SG_POST' => _x( 'Singapore Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SG_SPEEDPOST' => _x( 'Singapore Speedpost', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TCK_EXPRESS' => _x( 'TCK Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COUREX' => _x( 'Urbanfox', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WMG' => _x( 'WMG Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZYLLEM' => _x( 'Zyllem', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CLOUDWISH_ASIA' => tr( 'Cloudwish Asia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SG_DETRACK' => tr( 'Detrack', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FONSEN' => tr( 'Fonsen Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GRAB_WEBHOOK' => tr( 'Grab courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SIMPLYPOST' => tr( 'J&T Express Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JANIO' => tr( 'Janio Asia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IND_JAYONEXPRESS' => tr( 'Jayon Express (JEX)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JET_SHIP' => tr( 'Jet-Ship Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KGMHUB' => tr( 'KGM Hub', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LEGION_EXPRESS' => tr( 'Legion Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NHANS_SOLUTIONS' => tr( 'Nhans Solutions', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NINJAVAN_SG' => tr( 'Ninja van Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCELPOST_SG' => tr( 'Parcel Post Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARKNPARCEL' => tr( 'Park N Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PICKUPP_SGP' => tr( 'PICK UPP (Singapore)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SG_QXPRESS' => tr( 'Qxpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RAIDEREX' => tr( 'RaidereX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ROADBULL' => tr( 'Red Carpet Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RZYEXPRESS' => tr( 'RZY Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SG_SG_POST' => tr( 'Singapore Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SG_SPEEDPOST' => tr( 'Singapore Speedpost', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TCK_EXPRESS' => tr( 'TCK Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COUREX' => tr( 'Urbanfox', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WMG' => tr( 'WMG Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZYLLEM' => tr( 'Zyllem', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'SVK' => array( - 'name' => _x( 'Slovakia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Slovakia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'GLS_SLOV' => _x( 'GLS General Logistics Systems Slovakia s.r.o.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_SLOV' => tr( 'GLS General Logistics Systems Slovakia s.r.o.', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'SVN' => array( - 'name' => _x( 'Slovenia', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Slovenia', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'GLS_SLOVEN' => _x( 'GLS Slovenia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POST_SLOVENIA' => _x( 'Post of Slovenia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLS_SLOVEN' => tr( 'GLS Slovenia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POST_SLOVENIA' => tr( 'Post of Slovenia', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'ZA' => array( - 'name' => _x( 'South Africa', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'South Africa', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ZA_COURIERIT' => _x( 'Courier IT', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DAWN_WING' => _x( 'Dawn Wing', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPE_SOUTH_AFRC' => _x( 'DPE South Africa', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTEXPRESS' => _x( 'Internet Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'COLLIVERY' => _x( 'MDS Collivery Pty (Ltd)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RAM' => _x( 'RAM courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SKYNET_ZA' => _x( 'Skynet World Wide Express South Africa', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SOUTH_AFRICAN_POST_OFFICE' => _x( 'South African Post Office', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZA_SPECIALISED_FREIGHT' => _x( 'Specialised Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'THECOURIERGUY' => _x( 'The Courier Guy', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZA_COURIERIT' => tr( 'Courier IT', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DAWN_WING' => tr( 'Dawn Wing', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPE_SOUTH_AFRC' => tr( 'DPE South Africa', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTEXPRESS' => tr( 'Internet Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'COLLIVERY' => tr( 'MDS Collivery Pty (Ltd)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RAM' => tr( 'RAM courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SKYNET_ZA' => tr( 'Skynet World Wide Express South Africa', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SOUTH_AFRICAN_POST_OFFICE' => tr( 'South African Post Office', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZA_SPECIALISED_FREIGHT' => tr( 'Specialised Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'THECOURIERGUY' => tr( 'The Courier Guy', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'ES' => array( - 'name' => _x( 'Spain', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Spain', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ABCUSTOM' => _x( 'AB Custom Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ADERONLINE' => _x( 'Ader couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ASIGNA' => _x( 'ASIGNA courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ESP_ASM' => _x( 'ASM(GLS Spain)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CBL_LOGISTICA' => _x( 'CBL Logistica', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CORREOS_EXPRESS' => _x( 'Correos Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_PARCEL_ES' => _x( 'DHL parcel Spain(www.dhl.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_ES' => _x( 'DHL Spain(www.dhl.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ECOSCOOTING' => _x( 'ECOSCOOTING', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ESP_ENVIALIA' => _x( 'Envialia', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ENVIALIA_REFERENCE' => _x( 'Envialia Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTEGRA2_FTP' => _x( 'Integra2', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MRW_FTP' => _x( 'MRW courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ESP_MRW' => _x( 'MRW spain', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NACEX' => _x( 'NACEX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NACEX_ES' => _x( 'NACEX Spain', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ESP_NACEX' => _x( 'NACEX Spain', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PAACK_WEBHOOK' => _x( 'Paack courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ESP_PACKLINK' => _x( 'Packlink', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ESP_REDUR' => _x( 'Redur Spain', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PRT_INT_SEUR' => _x( 'SEUR International', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PRT_SEUR' => _x( 'SEUR portugal', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SEUR_ES' => _x( 'Seur Spain', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SEUR_SP_API' => _x( 'Spanish Seur API', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPRING_GDS' => _x( 'Spring GDS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SZENDEX' => _x( 'SZENDEX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_NL' => _x( 'THT Netherland', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TIPSA' => _x( 'TIPSA courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT' => _x( 'TNT Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLOBAL_TNT' => _x( 'TNT global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TOURLINE' => _x( 'tourline', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VAMOX' => _x( 'VAMOX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VIA_EXPRESS' => _x( 'Viaxpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZELERIS' => _x( 'Zeleris', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ABCUSTOM' => tr( 'AB Custom Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ADERONLINE' => tr( 'Ader couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ASIGNA' => tr( 'ASIGNA courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ESP_ASM' => tr( 'ASM(GLS Spain)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CBL_LOGISTICA' => tr( 'CBL Logistica', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CORREOS_EXPRESS' => tr( 'Correos Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_PARCEL_ES' => tr( 'DHL parcel Spain(www.dhl.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_ES' => tr( 'DHL Spain(www.dhl.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ECOSCOOTING' => tr( 'ECOSCOOTING', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ESP_ENVIALIA' => tr( 'Envialia', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ENVIALIA_REFERENCE' => tr( 'Envialia Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTEGRA2_FTP' => tr( 'Integra2', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MRW_FTP' => tr( 'MRW courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ESP_MRW' => tr( 'MRW spain', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NACEX' => tr( 'NACEX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NACEX_ES' => tr( 'NACEX Spain', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ESP_NACEX' => tr( 'NACEX Spain', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PAACK_WEBHOOK' => tr( 'Paack courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ESP_PACKLINK' => tr( 'Packlink', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ESP_REDUR' => tr( 'Redur Spain', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PRT_INT_SEUR' => tr( 'SEUR International', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PRT_SEUR' => tr( 'SEUR portugal', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SEUR_ES' => tr( 'Seur Spain', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SEUR_SP_API' => tr( 'Spanish Seur API', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPRING_GDS' => tr( 'Spring GDS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SZENDEX' => tr( 'SZENDEX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_NL' => tr( 'THT Netherland', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TIPSA' => tr( 'TIPSA courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT' => tr( 'TNT Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLOBAL_TNT' => tr( 'TNT global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TOURLINE' => tr( 'tourline', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VAMOX' => tr( 'VAMOX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VIA_EXPRESS' => tr( 'Viaxpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZELERIS' => tr( 'Zeleris', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'SE' => array( - 'name' => _x( 'Sweden', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Sweden', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'AIRMEE_WEBHOOK' => _x( 'Airmee couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BRING' => _x( 'Bring', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DBSCHENKER_SE' => _x( 'DB Schenker (www.dbschenker.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DBSCHENKER_SV' => _x( 'DB Schenker Sweden', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AIRMEE_WEBHOOK' => tr( 'Airmee couriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BRING' => tr( 'Bring', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DBSCHENKER_SE' => tr( 'DB Schenker (www.dbschenker.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DBSCHENKER_SV' => tr( 'DB Schenker Sweden', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'CH' => array( - 'name' => _x( 'Switzerland', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Switzerland', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ASENDIA_HK' => _x( 'Asendia HonKong', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PLANZER' => _x( 'Planzer Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SWISS_POST_FTP' => _x( 'Swiss Post FTP', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VIAEUROPE' => _x( 'ViaEurope', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ASENDIA_HK' => tr( 'Asendia HonKong', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PLANZER' => tr( 'Planzer Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SWISS_POST_FTP' => tr( 'Swiss Post FTP', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VIAEUROPE' => tr( 'ViaEurope', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'TW' => array( - 'name' => _x( 'Taiwan', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Taiwan', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CNWANGTONG' => _x( 'cnwangtong', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CTC_EXPRESS' => _x( 'CTC Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DIMERCO' => _x( 'Dimerco Express Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HCT_LOGISTICS' => _x( 'HCT LOGISTICS CO.LTD.', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KERRYTJ' => _x( 'Kerry TJ Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PRESIDENT_TRANS' => _x( 'PRESIDENT TRANSNET CORP', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLOBAL_EXPRESS' => _x( 'Tai Wan Global Business', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CNWANGTONG' => tr( 'cnwangtong', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CTC_EXPRESS' => tr( 'CTC Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DIMERCO' => tr( 'Dimerco Express Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HCT_LOGISTICS' => tr( 'HCT LOGISTICS CO.LTD.', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KERRYTJ' => tr( 'Kerry TJ Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PRESIDENT_TRANS' => tr( 'PRESIDENT TRANSNET CORP', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLOBAL_EXPRESS' => tr( 'Tai Wan Global Business', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'TH' => array( - 'name' => _x( 'Thailand', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Thailand', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ALPHAFAST' => _x( 'Alphafast', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CJ_KR' => _x( 'CJ Korea Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'THA_DYNAMIC_LOGISTICS' => _x( 'Dynamic Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FASTRK_SERV' => _x( 'Fastrak Services', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FLASHEXPRESS' => _x( 'Flash Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NIM_EXPRESS' => _x( 'Nim Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NINJAVAN_THAI' => _x( 'Ninja van Thai', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SENDIT' => _x( 'Sendit', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SKYBOX' => _x( 'SKYBOX', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'THA_THAILAND_POST' => _x( 'Thailand Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ALPHAFAST' => tr( 'Alphafast', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CJ_KR' => tr( 'CJ Korea Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'THA_DYNAMIC_LOGISTICS' => tr( 'Dynamic Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FASTRK_SERV' => tr( 'Fastrak Services', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FLASHEXPRESS' => tr( 'Flash Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NIM_EXPRESS' => tr( 'Nim Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NINJAVAN_THAI' => tr( 'Ninja van Thai', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SENDIT' => tr( 'Sendit', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SKYBOX' => tr( 'SKYBOX', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'THA_THAILAND_POST' => tr( 'Thailand Post', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'TR' => array( - 'name' => _x( 'Turkey', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Turkey', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'ASE' => _x( 'ASE KARGO', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CDEK_TR' => _x( 'CDEK TR', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PTS' => _x( 'PTS courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PTT_POST' => _x( 'PTT Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIPENTEGRA' => _x( 'ShipEntegra', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YURTICI_KARGO' => _x( 'Yurtici Kargo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ASE' => tr( 'ASE KARGO', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CDEK_TR' => tr( 'CDEK TR', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PTS' => tr( 'PTS courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PTT_POST' => tr( 'PTT Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIPENTEGRA' => tr( 'ShipEntegra', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YURTICI_KARGO' => tr( 'Yurtici Kargo', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'UA' => array( - 'name' => _x( 'Ukraine', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Ukraine', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'NOVA_POSHTA_INT' => _x( 'Nova Poshta (International)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NOVA_POSHTA' => _x( 'Nova Poshta (novaposhta.ua)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'POSTA_UKR' => _x( 'UkrPoshta', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NOVA_POSHTA_INT' => tr( 'Nova Poshta (International)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NOVA_POSHTA' => tr( 'Nova Poshta (novaposhta.ua)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'POSTA_UKR' => tr( 'UkrPoshta', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'AE' => array( - 'name' => _x( 'United Arab Emirates', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'United Arab Emirates', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'IBEONE' => _x( 'Beone Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MARA_XPRESS' => _x( 'Mara Xpress', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FETCHR_WEBHOOK' => _x( 'Mena 360 (Fetchr)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ONECLICK' => _x( 'One click delivery services', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SKYNET_UAE' => _x( 'SKYNET UAE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'IBEONE' => tr( 'Beone Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MARA_XPRESS' => tr( 'Mara Xpress', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FETCHR_WEBHOOK' => tr( 'Mena 360 (Fetchr)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ONECLICK' => tr( 'One click delivery services', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SKYNET_UAE' => tr( 'SKYNET UAE', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'GB' => array( - 'name' => _x( 'United Kingdom', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'United Kingdom', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'AMAZON' => _x( 'Amazon Shipping', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AO_COURIER' => _x( 'AO Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'APC_OVERNIGHT' => _x( 'APC overnight (apc-overnight.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'APC_OVERNIGHT_CONNUM' => _x( 'APC Overnight Consignment', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'APG' => _x( 'APG eCommerce Solutions', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ARK_LOGISTICS' => _x( 'ARK Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GB_ARROW' => _x( 'Arrow XL', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ASENDIA_UK' => _x( 'Asendia UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BH_WORLDWIDE' => _x( 'B&H Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BIRDSYSTEM' => _x( 'BirdSystem', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'BLUECARE' => _x( 'Bluecare Express Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CAE_DELIVERS' => _x( 'CAE Delivers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'CARIBOU' => _x( 'Caribou', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DAIGLOBALTRACK' => _x( 'DAI Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DELTEC_UK' => _x( 'Deltec Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_REFR' => _x( 'DHl (Reference number)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DHL_UK' => _x( 'dhl UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DIAMOND_EUROGISTICS' => _x( 'Diamond Eurogistics Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DIRECTPARCELS' => _x( 'Direct Parcels', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DMS_MATRIX' => _x( 'DMSMatrix', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_LOCAL' => _x( 'DPD Local', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DPD_LOCAL_REF' => _x( 'DPD Local reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DX_SFTP' => _x( 'DX (SFTP)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'EU_FLEET_SOLUTIONS' => _x( 'EU Fleet Solutions', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FEDEX_UK' => _x( 'FedEx® UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'FURDECO' => _x( 'Furdeco', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GBA' => _x( 'GBA Services Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GEMWORLDWIDE' => _x( 'GEM Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HERMES' => _x( 'HermesWorld UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HOME_DELIVERY_SOLUTIONS' => _x( 'Home Delivery Solutions Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'INTERPARCEL_UK' => _x( 'Interparcel UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MYHERMES' => _x( 'MyHermes UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NATIONAL_SAMEDAY' => _x( 'National Sameday', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GB_NORSK' => _x( 'Norsk Global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OCS_WORLDWIDE' => _x( 'OCS WORLDWIDE', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PALLETWAYS' => _x( 'Palletways', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GB_PANTHER' => _x( 'Panther', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PANTHER_REFERENCE' => _x( 'Panther Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCEL2GO' => _x( 'Parcel2Go', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PARCELINKLOGISTICS' => _x( 'Parcelink Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PLUS_LOG_UK' => _x( 'Plus UK Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RPD2MAN' => _x( 'RPD2man Deliveries', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SKYNET_UK' => _x( 'Skynet UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'AMAZON_FBA_SWISHIP' => _x( 'Swiship UK', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'THEDELIVERYGROUP' => _x( 'TDG – The Delivery Group', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PALLET_NETWORK' => _x( 'The Pallet Network', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_UK' => _x( 'TNT UK Limited (www.tnt.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TNT_UK_REFR' => _x( 'TNT UK Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GB_TUFFNELLS' => _x( 'Tuffnells Parcels Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TUFFNELLS_REFERENCE' => _x( 'Tuffnells Parcels Express- Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UK_UK_MAIL' => _x( 'UK mail (ukmail.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WHISTL' => _x( 'Whistl', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WNDIRECT' => _x( 'wnDirect', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UK_XDP' => _x( 'XDP Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XDP_UK_REFERENCE' => _x( 'XDP Express Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XPERT_DELIVERY' => _x( 'Xpert Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UK_YODEL' => _x( 'Yodel (www.yodel.co.uk)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AMAZON' => tr( 'Amazon Shipping', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AO_COURIER' => tr( 'AO Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'APC_OVERNIGHT' => tr( 'APC overnight (apc-overnight.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'APC_OVERNIGHT_CONNUM' => tr( 'APC Overnight Consignment', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'APG' => tr( 'APG eCommerce Solutions', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ARK_LOGISTICS' => tr( 'ARK Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GB_ARROW' => tr( 'Arrow XL', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ASENDIA_UK' => tr( 'Asendia UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BH_WORLDWIDE' => tr( 'B&H Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BIRDSYSTEM' => tr( 'BirdSystem', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'BLUECARE' => tr( 'Bluecare Express Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CAE_DELIVERS' => tr( 'CAE Delivers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CARIBOU' => tr( 'Caribou', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DAIGLOBALTRACK' => tr( 'DAI Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DELTEC_UK' => tr( 'Deltec Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_REFR' => tr( 'DHl (Reference number)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DHL_UK' => tr( 'dhl UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DIAMOND_EUROGISTICS' => tr( 'Diamond Eurogistics Limited', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DIRECTPARCELS' => tr( 'Direct Parcels', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DMS_MATRIX' => tr( 'DMSMatrix', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_LOCAL' => tr( 'DPD Local', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DPD_LOCAL_REF' => tr( 'DPD Local reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DX_SFTP' => tr( 'DX (SFTP)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'EU_FLEET_SOLUTIONS' => tr( 'EU Fleet Solutions', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FEDEX_UK' => tr( 'FedEx® UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'FURDECO' => tr( 'Furdeco', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GBA' => tr( 'GBA Services Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GEMWORLDWIDE' => tr( 'GEM Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HERMES' => tr( 'HermesWorld UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HOME_DELIVERY_SOLUTIONS' => tr( 'Home Delivery Solutions Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'INTERPARCEL_UK' => tr( 'Interparcel UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MYHERMES' => tr( 'MyHermes UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NATIONAL_SAMEDAY' => tr( 'National Sameday', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GB_NORSK' => tr( 'Norsk Global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OCS_WORLDWIDE' => tr( 'OCS WORLDWIDE', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PALLETWAYS' => tr( 'Palletways', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GB_PANTHER' => tr( 'Panther', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PANTHER_REFERENCE' => tr( 'Panther Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCEL2GO' => tr( 'Parcel2Go', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PARCELINKLOGISTICS' => tr( 'Parcelink Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PLUS_LOG_UK' => tr( 'Plus UK Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RPD2MAN' => tr( 'RPD2man Deliveries', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SKYNET_UK' => tr( 'Skynet UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'AMAZON_FBA_SWISHIP' => tr( 'Swiship UK', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'THEDELIVERYGROUP' => tr( 'TDG – The Delivery Group', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PALLET_NETWORK' => tr( 'The Pallet Network', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_UK' => tr( 'TNT UK Limited (www.tnt.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TNT_UK_REFR' => tr( 'TNT UK Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GB_TUFFNELLS' => tr( 'Tuffnells Parcels Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TUFFNELLS_REFERENCE' => tr( 'Tuffnells Parcels Express- Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UK_UK_MAIL' => tr( 'UK mail (ukmail.com)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WHISTL' => tr( 'Whistl', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WNDIRECT' => tr( 'wnDirect', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UK_XDP' => tr( 'XDP Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XDP_UK_REFERENCE' => tr( 'XDP Express Reference', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XPERT_DELIVERY' => tr( 'Xpert Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UK_YODEL' => tr( 'Yodel (www.yodel.co.uk)', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'US' => array( - 'name' => _x( 'United States', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'United States', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'GIO_EXPRESS' => _x( 'Gio Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLOBALTRANZ' => _x( 'GlobalTranz', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GSI_EXPRESS' => _x( 'GSI EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GSO' => _x( 'GSO (GLS-USA)', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'HIPSHIPPER' => _x( 'Hipshipper', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'GLOBAL_IPARCEL' => _x( 'i-parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'DESCARTES' => _x( 'Innovel courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'US_LASERSHIP' => _x( 'LaserShip', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LONESTAR' => _x( 'Lone Star Overnight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'MAILAMERICAS' => _x( 'MailAmericas', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NEWEGGEXPRESS' => _x( 'Newegg Express', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'US_OLD_DOMINION' => _x( 'Old Dominion Freight Line', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'OSM_WORLDWIDE' => _x( 'OSM Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PCFCORP' => _x( 'PCF Final Mile', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PILOT_FREIGHT' => _x( 'Pilot Freight Services', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PITNEY_BOWES' => _x( 'Pitney Bowes', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'PITTOHIO' => _x( 'PITT OHIO', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'QWINTRY' => _x( 'Qwintry Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'RL_US' => _x( 'RL Carriers', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SAIA_FREIGHT' => _x( 'Saia LTL Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SHIPTOR' => _x( 'Shiptor', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SONICTL' => _x( 'Sonic Transportation & Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SEFL' => _x( 'Southeastern Freight Lines', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SPEEDEE' => _x( 'Spee-Dee Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'SUTTON' => _x( 'Sutton Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TAZMANIAN_FREIGHT' => _x( 'Tazmanian Freight Systems', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TFORCE_FINALMILE' => _x( 'TForce Final Mile', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'LOGISTYX_TRANSGROUP' => _x( 'Transgroup courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'TRUMPCARD' => _x( 'TRUMPCARD LLC', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'USPS' => _x( 'United States Postal Service', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'UPS_MAIL_INNOVATIONS' => _x( 'UPS Mail Innovations', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'USF_REDDAWAY' => _x( 'USF Reddaway', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'USHIP' => _x( 'uShip courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WESTBANK_COURIER' => _x( 'West Bank Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WESTGATE_GL' => _x( 'Westgate Global', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'WIZMO' => _x( 'Wizmo', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'XPO_LOGISTICS' => _x( 'XPO logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'YAKIT' => _x( 'Yakit courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'US_YRC' => _x( 'YRC courier', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'ZINC' => _x( 'Zinc courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GIO_EXPRESS' => tr( 'Gio Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLOBALTRANZ' => tr( 'GlobalTranz', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GSI_EXPRESS' => tr( 'GSI EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GSO' => tr( 'GSO (GLS-USA)', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'HIPSHIPPER' => tr( 'Hipshipper', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'GLOBAL_IPARCEL' => tr( 'i-parcel', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'DESCARTES' => tr( 'Innovel courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'US_LASERSHIP' => tr( 'LaserShip', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LONESTAR' => tr( 'Lone Star Overnight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'MAILAMERICAS' => tr( 'MailAmericas', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NEWEGGEXPRESS' => tr( 'Newegg Express', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'US_OLD_DOMINION' => tr( 'Old Dominion Freight Line', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'OSM_WORLDWIDE' => tr( 'OSM Worldwide', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PCFCORP' => tr( 'PCF Final Mile', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PILOT_FREIGHT' => tr( 'Pilot Freight Services', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PITNEY_BOWES' => tr( 'Pitney Bowes', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'PITTOHIO' => tr( 'PITT OHIO', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'QWINTRY' => tr( 'Qwintry Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'RL_US' => tr( 'RL Carriers', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SAIA_FREIGHT' => tr( 'Saia LTL Freight', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SHIPTOR' => tr( 'Shiptor', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SONICTL' => tr( 'Sonic Transportation & Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SEFL' => tr( 'Southeastern Freight Lines', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SPEEDEE' => tr( 'Spee-Dee Delivery', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'SUTTON' => tr( 'Sutton Transport', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TAZMANIAN_FREIGHT' => tr( 'Tazmanian Freight Systems', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TFORCE_FINALMILE' => tr( 'TForce Final Mile', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'LOGISTYX_TRANSGROUP' => tr( 'Transgroup courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'TRUMPCARD' => tr( 'TRUMPCARD LLC', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'USPS' => tr( 'United States Postal Service', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'UPS_MAIL_INNOVATIONS' => tr( 'UPS Mail Innovations', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'USF_REDDAWAY' => tr( 'USF Reddaway', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'USHIP' => tr( 'uShip courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WESTBANK_COURIER' => tr( 'West Bank Courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WESTGATE_GL' => tr( 'Westgate Global', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'WIZMO' => tr( 'Wizmo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'XPO_LOGISTICS' => tr( 'XPO logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'YAKIT' => tr( 'Yakit courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'US_YRC' => tr( 'YRC courier', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'ZINC' => tr( 'Zinc courier', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'URY' => array( - 'name' => _x( 'Uruguay', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Uruguay', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'CORREO_UY' => _x( 'Correo Uruguayo', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'CORREO_UY' => tr( 'Correo Uruguayo', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), 'VN' => array( - 'name' => _x( 'Vietnam', 'Name of carrier country', 'woocommerce-paypal-payments' ), + 'name' => tr( 'Vietnam', 'Name of carrier country', 'woocommerce-paypal-payments' ), 'items' => array( - 'JTEXPRESS_VN' => _x( 'J&T Express Vietnam', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'KERRYTTC_VN' => _x( 'Kerry Express (Vietnam) Co Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'NTLOGISTICS_VN' => _x( 'Nhat Tin Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VNM_VIETNAM_POST' => _x( 'Vietnam Post', 'Name of carrier', 'woocommerce-paypal-payments' ), - 'VNM_VIETTELPOST' => _x( 'ViettelPost', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'JTEXPRESS_VN' => tr( 'J&T Express Vietnam', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'KERRYTTC_VN' => tr( 'Kerry Express (Vietnam) Co Ltd', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'NTLOGISTICS_VN' => tr( 'Nhat Tin Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VNM_VIETNAM_POST' => tr( 'Vietnam Post', 'Name of carrier', 'woocommerce-paypal-payments' ), + 'VNM_VIETTELPOST' => tr( 'ViettelPost', 'Name of carrier', 'woocommerce-paypal-payments' ), ), ), ) diff --git a/modules/ppcp-order-tracking/services.php b/modules/ppcp-order-tracking/services.php index 8b52fa2fe..493f31644 100644 --- a/modules/ppcp-order-tracking/services.php +++ b/modules/ppcp-order-tracking/services.php @@ -100,7 +100,7 @@ return array( */ return apply_filters( 'woocommerce_paypal_payments_supported_country_codes_for_second_version_of_tracking_api', - array( 'US', 'AU', 'CA', 'FR', 'DE', 'IT', 'ES' ) + array( 'US', 'AU', 'CA', 'FR', 'DE', 'IT', 'ES', 'GB' ) ); }, 'order-tracking.should-use-second-version-of-api' => static function ( ContainerInterface $container ): bool { diff --git a/modules/ppcp-order-tracking/src/Shipment/Shipment.php b/modules/ppcp-order-tracking/src/Shipment/Shipment.php index 155931d19..9661d574c 100644 --- a/modules/ppcp-order-tracking/src/Shipment/Shipment.php +++ b/modules/ppcp-order-tracking/src/Shipment/Shipment.php @@ -14,6 +14,7 @@ use WC_Order_Item_Product; use WC_Product; use WooCommerce\PayPalCommerce\ApiClient\Entity\Item; use WooCommerce\PayPalCommerce\ApiClient\Entity\Money; +use WooCommerce\PayPalCommerce\ApiClient\Helper\ItemTrait; use WooCommerce\PayPalCommerce\OrderTracking\OrderTrackingModule; /** @@ -21,6 +22,8 @@ use WooCommerce\PayPalCommerce\OrderTracking\OrderTrackingModule; */ class Shipment implements ShipmentInterface { + use ItemTrait; + /** * The WC order ID. * @@ -166,12 +169,12 @@ class Shipment implements ShipmentInterface { $image = wp_get_attachment_image_src( (int) $product->get_image_id(), 'full' ); $ppcp_order_item = new Item( - mb_substr( $item->get_name(), 0, 127 ), + $this->prepare_item_string( $item->get_name() ), new Money( $price_without_tax_rounded, $currency ), $quantity, - $this->prepare_description( $product->get_description() ), + $this->prepare_item_string( $product->get_description() ), null, - $product->get_sku(), + $this->prepare_sku( $product->get_sku() ), $product->is_virtual() ? Item::DIGITAL_GOODS : Item::PHYSICAL_GOODS, $product->get_permalink(), $image[0] ?? '' @@ -239,17 +242,6 @@ class Shipment implements ShipmentInterface { return $shipment; } - /** - * Cleanups the description and prepares it for sending to PayPal. - * - * @param string $description Item description. - * @return string - */ - protected function prepare_description( string $description ): string { - $description = strip_shortcodes( wp_strip_all_tags( $description ) ); - return substr( $description, 0, 127 ) ?: ''; - } - /** * Renders the shipment line items info. * diff --git a/modules/ppcp-paylater-block/.babelrc b/modules/ppcp-paylater-block/.babelrc new file mode 100644 index 000000000..822778e6c --- /dev/null +++ b/modules/ppcp-paylater-block/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "useBuiltIns": "usage", + "corejs": "3.25.0" + } + ], + [ + "@babel/preset-react" + ] + ] +} diff --git a/modules/ppcp-paylater-block/.gitignore b/modules/ppcp-paylater-block/.gitignore new file mode 100644 index 000000000..0bd2b9f58 --- /dev/null +++ b/modules/ppcp-paylater-block/.gitignore @@ -0,0 +1,3 @@ +node_modules +assets/js +assets/css diff --git a/modules/ppcp-paylater-block/block.json b/modules/ppcp-paylater-block/block.json new file mode 100644 index 000000000..ff8a5476e --- /dev/null +++ b/modules/ppcp-paylater-block/block.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "woocommerce-paypal-payments/paylater-messages", + "title": "PayPal Pay Later messaging", + "category": "woocommerce", + "description": "PayPal Pay Later messaging will be displayed for eligible customers. Customers automatically see the most relevant Pay Later offering.", + "example": {}, + "attributes": { + "id": { + "type": "string" + }, + "layout": { + "type": "string", + "default": "flex" + }, + "logo": { + "type": "string", + "default": "inline" + }, + "position": { + "type": "string", + "default": "left" + }, + "color": { + "type": "string", + "default": "black" + }, + "flexColor": { + "type": "string", + "default": "white" + }, + "flexRatio": { + "type": "string", + "default": "8x1" + }, + "placement": { + "type": "string", + "default": "auto" + } + }, + "supports": { + "html": false + }, + "textdomain": "woocommerce-paypal-payments", + "editorScript": "ppcp-paylater-block", + "editorStyle": "file:./assets/css/edit.css" +} diff --git a/modules/ppcp-subscription/composer.json b/modules/ppcp-paylater-block/composer.json similarity index 61% rename from modules/ppcp-subscription/composer.json rename to modules/ppcp-paylater-block/composer.json index b8f68646c..58b7a5545 100644 --- a/modules/ppcp-subscription/composer.json +++ b/modules/ppcp-paylater-block/composer.json @@ -1,7 +1,7 @@ { - "name": "woocommerce/ppcp-subscription", + "name": "woocommerce/ppcp-paylater-block", "type": "dhii-mod", - "description": "Subscription module for PPCP", + "description": "Pay Later Block module for PPCP", "license": "GPL-2.0", "require": { "php": "^7.2 | ^8.0", @@ -9,7 +9,7 @@ }, "autoload": { "psr-4": { - "WooCommerce\\PayPalCommerce\\Subscription\\": "src" + "WooCommerce\\PayPalCommerce\\PayLaterBlock\\": "src" } }, "minimum-stability": "dev", diff --git a/modules/ppcp-paylater-block/extensions.php b/modules/ppcp-paylater-block/extensions.php new file mode 100644 index 000000000..81939c6f5 --- /dev/null +++ b/modules/ppcp-paylater-block/extensions.php @@ -0,0 +1,12 @@ + 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-paylater-block/resources/css/edit.scss b/modules/ppcp-paylater-block/resources/css/edit.scss new file mode 100644 index 000000000..ebbbb0546 --- /dev/null +++ b/modules/ppcp-paylater-block/resources/css/edit.scss @@ -0,0 +1,19 @@ +.ppcp-overlay-parent { + display: grid; + grid-template-columns: 1fr; +} + +.ppcp-overlay-child { + grid-row-start: 1; + grid-column-start: 1; +} + +.ppcp-unclicable-overlay { + z-index: 10; +} + +.ppcp-paylater-unavailable { + p.block-editor-warning__message { + margin-bottom: 10px; + } +} diff --git a/modules/ppcp-paylater-block/resources/js/components/PayPalMessages.js b/modules/ppcp-paylater-block/resources/js/components/PayPalMessages.js new file mode 100644 index 000000000..d2115f100 --- /dev/null +++ b/modules/ppcp-paylater-block/resources/js/components/PayPalMessages.js @@ -0,0 +1,29 @@ +import { useRef, useEffect } from '@wordpress/element'; + +export default function PayPalMessages({ + amount, + style, + onRender, +}) { + const containerRef = useRef(null); + + useEffect(() => { + const messages = paypal.Messages({ + amount, + style, + onRender, + }); + + messages.render(containerRef.current) + .catch(err => { + // Ignore when component destroyed. + if (!containerRef.current || containerRef.current.children.length === 0) { + return; + } + + console.error(err); + }); + }, [amount, style, onRender]); + + return
+} diff --git a/modules/ppcp-paylater-block/resources/js/edit.js b/modules/ppcp-paylater-block/resources/js/edit.js new file mode 100644 index 000000000..44b4f895d --- /dev/null +++ b/modules/ppcp-paylater-block/resources/js/edit.js @@ -0,0 +1,222 @@ +import { __ } from '@wordpress/i18n'; +import { useState, useEffect } from '@wordpress/element'; +import { InspectorControls, useBlockProps } from '@wordpress/block-editor'; +import { PanelBody, SelectControl, Spinner } from '@wordpress/components'; +import { useScriptParams } from "./hooks/script-params"; +import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading' +import PayPalMessages from "./components/PayPalMessages"; + +export default function Edit( { attributes, clientId, setAttributes } ) { + const { layout, logo, position, color, size, flexColor, flexRatio, placement, id } = attributes; + const isFlex = layout === 'flex'; + + const [paypalScriptState, setPaypalScriptState] = useState(null); + + const [rendered, setRendered] = useState(false); + + let amount = undefined; + const postContent = String(wp.data.select('core/editor')?.getEditedPostContent()); + if (postContent.includes('woocommerce/checkout') || postContent.includes('woocommerce/cart')) { + amount = 50.0; + } + + const previewStyle = { + layout, + logo: { + position, + type: logo, + }, + color: flexColor, + ratio: flexRatio, + text: { + color, + size + }, + }; + + let classes = ['ppcp-paylater-block-preview', 'ppcp-overlay-parent']; + if (PcpPayLaterBlock.vaultingEnabled || !PcpPayLaterBlock.placementEnabled) { + classes = ['ppcp-paylater-block-preview', 'ppcp-paylater-unavailable', 'block-editor-warning']; + } + const props = useBlockProps({className: classes}); + + const loadingElement =
; + + useEffect(() => { + if (!id) { + setAttributes({id: 'ppcp-' + clientId}); + } + }, []); + + if (PcpPayLaterBlock.vaultingEnabled) { + return
+
+

{__('PayPal Pay Later Messaging', 'woocommerce-paypal-payments')}

+

{__('Pay Later Messaging cannot be used while PayPal Vaulting is active. Disable PayPal Vaulting in the PayPal Payment settings to reactivate this block', 'woocommerce-paypal-payments')}

+
+ + + {__('PayPal Payments Settings', 'woocommerce-paypal-payments')} + + + + + +
+
+
+ } + + if (!PcpPayLaterBlock.placementEnabled) { + return
+
+

{__('PayPal Pay Later Messaging', 'woocommerce-paypal-payments')}

+

{__('Pay Later Messaging cannot be used while the “WooCommerce Block” messaging placement is disabled. Enable the placement in the PayPal Payments Pay Later settings to reactivate this block.', 'woocommerce-paypal-payments')}

+
+ + + {__('PayPal Payments Settings', 'woocommerce-paypal-payments')} + + + + + +
+
+
+ } + + let scriptParams = useScriptParams(PcpPayLaterBlock.ajax.cart_script_params); + if (scriptParams === null) { + return loadingElement; + } + if (scriptParams === false) { + scriptParams = { + url_params: { + clientId: 'test', + } + } + } + scriptParams.url_params.components = 'messages,buttons,funding-eligibility'; + + if (!paypalScriptState) { + loadPaypalScript(scriptParams, () => { + setPaypalScriptState('loaded') + }, () => { + setPaypalScriptState('failed') + }); + } + if (paypalScriptState !== 'loaded') { + return loadingElement; + } + + return ( + <> + + + setAttributes( { layout: value } ) } + /> + { !isFlex && ( setAttributes({logo: value})} + />)} + { !isFlex && logo === 'primary' && ( setAttributes({position: value})} + />)} + { !isFlex && ( setAttributes({color: value})} + />)} + { !isFlex && ( setAttributes({size: value})} + />)} + { isFlex && ( setAttributes({flexColor: value})} + />)} + { isFlex && ( setAttributes({flexRatio: value})} + />)} + setAttributes( { placement: value } ) } + /> + + +
+
+ setRendered(true)} + /> +
+
{/* make the message not clickable */} + {!rendered && ()} +
+
+ + ); +} diff --git a/modules/ppcp-paylater-block/resources/js/hooks/script-params.js b/modules/ppcp-paylater-block/resources/js/hooks/script-params.js new file mode 100644 index 000000000..c5b9de66f --- /dev/null +++ b/modules/ppcp-paylater-block/resources/js/hooks/script-params.js @@ -0,0 +1,24 @@ +import { useState, useEffect } from '@wordpress/element'; + +export const useScriptParams = (requestConfig) => { + const [data, setData] = useState(null); + + useEffect(() => { + (async () => { + try { + const response = await fetch(requestConfig.endpoint); + const json = await response.json(); + if (json.success && json?.data?.url_params) { + setData(json.data); + } else { + setData(false); + } + } catch (e) { + console.error(e); + setData(false); + } + })(); + }, [requestConfig]); + + return data; +}; diff --git a/modules/ppcp-paylater-block/resources/js/paylater-block.js b/modules/ppcp-paylater-block/resources/js/paylater-block.js new file mode 100644 index 000000000..873147c9f --- /dev/null +++ b/modules/ppcp-paylater-block/resources/js/paylater-block.js @@ -0,0 +1,36 @@ +import { registerBlockType } from '@wordpress/blocks'; + +import Edit from './edit'; +import save from './save'; + +const paypalIcon = ( + + + + + + + +) + +const blockId = 'woocommerce-paypal-payments/paylater-messages'; + +registerBlockType( blockId, { + icon: paypalIcon, + edit: Edit, + save, +} ); + +document.addEventListener( 'DOMContentLoaded', () => { + const { registerCheckoutFilters } = window.wc.blocksCheckout; + + // allow to add this block inside WC cart/checkout blocks + registerCheckoutFilters( blockId, { + additionalCartCheckoutInnerBlockTypes: ( + defaultValue + ) => { + defaultValue.push( blockId ); + return defaultValue; + }, + } ); +} ); diff --git a/modules/ppcp-paylater-block/resources/js/save.js b/modules/ppcp-paylater-block/resources/js/save.js new file mode 100644 index 000000000..6a845e7da --- /dev/null +++ b/modules/ppcp-paylater-block/resources/js/save.js @@ -0,0 +1,26 @@ +import { useBlockProps } from '@wordpress/block-editor'; + +export default function save( { attributes } ) { + const { layout, logo, position, color, size, flexColor, flexRatio, placement, id } = attributes; + const paypalAttributes = layout === 'flex' ? { + 'data-pp-style-layout': 'flex', + 'data-pp-style-color': flexColor, + 'data-pp-style-ratio': flexRatio, + } : { + 'data-pp-style-layout': 'text', + 'data-pp-style-logo-type': logo, + 'data-pp-style-logo-position': position, + 'data-pp-style-text-color': color, + 'data-pp-style-text-size': size, + }; + if (placement && placement !== 'auto') { + paypalAttributes['data-pp-placement'] = placement; + } + const props = { + className: 'ppcp-paylater-message-block', + id, + ...paypalAttributes, + }; + + return
; +} diff --git a/modules/ppcp-paylater-block/services.php b/modules/ppcp-paylater-block/services.php new file mode 100644 index 000000000..24b1f0443 --- /dev/null +++ b/modules/ppcp-paylater-block/services.php @@ -0,0 +1,26 @@ + static function ( ContainerInterface $container ): string { + /** + * Cannot return false for this path. + * + * @psalm-suppress PossiblyFalseArgument + */ + return plugins_url( + '/modules/ppcp-paylater-block/', + dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php' + ); + }, +); diff --git a/modules/ppcp-paylater-block/src/PayLaterBlockModule.php b/modules/ppcp-paylater-block/src/PayLaterBlockModule.php new file mode 100644 index 000000000..223ccd972 --- /dev/null +++ b/modules/ppcp-paylater-block/src/PayLaterBlockModule.php @@ -0,0 +1,115 @@ +is_pay_later_messaging_enabled_for_location( 'custom_placement' ); + } + + /** + * {@inheritDoc} + */ + public function setup(): ServiceProviderInterface { + return new ServiceProvider( + require __DIR__ . '/../services.php', + require __DIR__ . '/../extensions.php' + ); + } + + /** + * {@inheritDoc} + */ + public function run( ContainerInterface $c ): void { + $messages_apply = $c->get( 'button.helper.messages-apply' ); + assert( $messages_apply instanceof MessagesApply ); + + if ( ! $messages_apply->for_country() ) { + return; + } + + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + + add_action( + 'init', + function () use ( $c, $settings ): void { + $script_handle = 'ppcp-paylater-block'; + wp_register_script( + $script_handle, + $c->get( 'paylater-block.url' ) . '/assets/js/paylater-block.js', + array(), + $c->get( 'ppcp.asset-version' ), + true + ); + wp_localize_script( + $script_handle, + 'PcpPayLaterBlock', + array( + 'ajax' => array( + 'cart_script_params' => array( + 'endpoint' => \WC_AJAX::get_endpoint( CartScriptParamsEndpoint::ENDPOINT ), + ), + ), + 'settingsUrl' => admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' ), + 'vaultingEnabled' => $settings->has( 'vault_enabled' ) && $settings->get( 'vault_enabled' ), + 'placementEnabled' => self::is_block_enabled( $c->get( 'wcgateway.settings.status' ) ), + 'payLaterSettingsUrl' => admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=ppcp-pay-later' ), + ) + ); + + /** + * Cannot return false for this path. + * + * @psalm-suppress PossiblyFalseArgument + */ + register_block_type( dirname( realpath( __FILE__ ), 2 ) ); + }, + 20 + ); + } + + /** + * Returns the key for the module. + * + * @return string|void + */ + public function getKey() { + } +} diff --git a/modules/ppcp-paylater-block/webpack.config.js b/modules/ppcp-paylater-block/webpack.config.js new file mode 100644 index 000000000..78519f0a9 --- /dev/null +++ b/modules/ppcp-paylater-block/webpack.config.js @@ -0,0 +1,39 @@ +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: { + 'paylater-block': path.resolve('./resources/js/paylater-block.js'), + 'edit': path.resolve('./resources/css/edit.scss'), + }, + 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-paylater-block/yarn.lock b/modules/ppcp-paylater-block/yarn.lock new file mode 100644 index 000000000..209adc4a4 --- /dev/null +++ b/modules/ppcp-paylater-block/yarn.lock @@ -0,0 +1,2201 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.5.tgz#86f172690b093373a933223b4745deeb6049e733" + integrity sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g== + +"@babel/core@^7.19": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.5.tgz#45e2114dc6cd4ab167f81daf7820e8fa1250d113" + integrity sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-module-transforms" "^7.20.2" + "@babel/helpers" "^7.20.5" + "@babel/parser" "^7.20.5" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.1" + semver "^6.3.0" + +"@babel/generator@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.5.tgz#cb25abee3178adf58d6814b68517c62bdbfdda95" + integrity sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA== + dependencies: + "@babel/types" "^7.20.5" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" + integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.18.6" + "@babel/types" "^7.18.9" + +"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" + integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== + dependencies: + "@babel/compat-data" "^7.20.0" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.5.tgz#327154eedfb12e977baa4ecc72e5806720a85a06" + integrity sha512-3RCdA/EmEaikrhayahwToF0fpweU/8o2p8vhc1c/1kftHOdTKuC65kik/TLc+qfbS8JKw4qqJbne4ovICDhmww== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-split-export-declaration" "^7.18.6" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz#5ea79b59962a09ec2acf20a963a01ab4d076ccca" + integrity sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + regexpu-core "^5.2.1" + +"@babel/helper-define-polyfill-provider@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" + integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== + dependencies: + "@babel/helper-compilation-targets" "^7.17.7" + "@babel/helper-plugin-utils" "^7.16.7" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== + +"@babel/helper-explode-assignable-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" + integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-member-expression-to-functions@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" + integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== + dependencies: + "@babel/types" "^7.18.9" + +"@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" + integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.2" + +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== + dependencies: + "@babel/types" "^7.18.6" + +"@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.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== + +"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" + integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-wrap-function" "^7.18.9" + "@babel/types" "^7.18.9" + +"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" + integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/traverse" "^7.19.1" + "@babel/types" "^7.19.0" + +"@babel/helper-simple-access@^7.19.4", "@babel/helper-simple-access@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" + integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== + dependencies: + "@babel/types" "^7.20.2" + +"@babel/helper-skip-transparent-expression-wrappers@^7.18.9": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" + integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== + dependencies: + "@babel/types" "^7.20.0" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helper-wrap-function@^7.18.9": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3" + integrity sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q== + dependencies: + "@babel/helper-function-name" "^7.19.0" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + +"@babel/helpers@^7.20.5": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.6.tgz#e64778046b70e04779dfbdf924e7ebb45992c763" + integrity sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.18.10", "@babel/parser@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.5.tgz#7f3c7335fe417665d929f34ae5dceae4c04015e8" + integrity sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": + version "7.18.6" + 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.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" + integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" + integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/plugin-proposal-optional-chaining" "^7.18.9" + +"@babel/plugin-proposal-async-generator-functions@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.1.tgz#352f02baa5d69f4e7529bdac39aaa02d41146af9" + integrity sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-remap-async-to-generator" "^7.18.9" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-class-static-block@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" + integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-proposal-dynamic-import@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" + integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-proposal-export-namespace-from@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" + integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" + integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" + integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" + integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" + integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.2.tgz#a556f59d555f06961df1e572bb5eca864c84022d" + integrity sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ== + dependencies: + "@babel/compat-data" "^7.20.1" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.20.1" + +"@babel/plugin-proposal-optional-catch-binding@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" + integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-private-methods@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" + integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-private-property-in-object@^7.18.6": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz#309c7668f2263f1c711aa399b5a9a6291eef6135" + integrity sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-create-class-features-plugin" "^7.20.5" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" + integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@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.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" + integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + +"@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.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@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-transform-arrow-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" + integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-async-to-generator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" + integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== + dependencies: + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" + +"@babel/plugin-transform-block-scoped-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-block-scoping@^7.20.2": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.5.tgz#401215f9dc13dc5262940e2e527c9536b3d7f237" + integrity sha512-WvpEIW9Cbj9ApF3yJCjIEEf1EiNJLtXagOrL5LNWEZOo3jv8pmPoYTSNJQvqej8OavVlgOoOPw6/htGZro6IkA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-classes@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.2.tgz#c0033cf1916ccf78202d04be4281d161f6709bb2" + integrity sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-split-export-declaration" "^7.18.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" + integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-destructuring@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.2.tgz#c23741cfa44ddd35f5e53896e88c75331b8b2792" + integrity sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" + integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-duplicate-keys@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" + integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-exponentiation-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" + integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-for-of@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" + integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-function-name@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" + integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== + dependencies: + "@babel/helper-compilation-targets" "^7.18.9" + "@babel/helper-function-name" "^7.18.9" + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-literals@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" + integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-member-expression-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-modules-amd@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.19.6.tgz#aca391801ae55d19c4d8d2ebfeaa33df5f2a2cbd" + integrity sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg== + dependencies: + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + +"@babel/plugin-transform-modules-commonjs@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz#25b32feef24df8038fc1ec56038917eacb0b730c" + integrity sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ== + dependencies: + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-simple-access" "^7.19.4" + +"@babel/plugin-transform-modules-systemjs@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.6.tgz#59e2a84064b5736a4471b1aa7b13d4431d327e0d" + integrity sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ== + dependencies: + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-validator-identifier" "^7.19.1" + +"@babel/plugin-transform-modules-umd@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" + integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz#626298dd62ea51d452c3be58b285d23195ba69a8" + integrity sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.20.5" + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-new-target@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" + integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-object-super@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + +"@babel/plugin-transform-parameters@^7.20.1": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.5.tgz#f8f9186c681d10c3de7620c916156d893c8a019e" + integrity sha512-h7plkOmcndIUWXZFLgpbrh2+fXAi47zcUX7IrOQuZdLD0I0KvjJ6cvo3BEcAOsDOcZhVKGJqv07mkSqK0y2isQ== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-property-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-display-name@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" + integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-jsx-development@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" + integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.18.6" + +"@babel/plugin-transform-react-jsx@^7.18.6": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" + integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-jsx" "^7.18.6" + "@babel/types" "^7.19.0" + +"@babel/plugin-transform-react-pure-annotations@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" + integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-regenerator@^7.18.6": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz#57cda588c7ffb7f4f8483cc83bdcea02a907f04d" + integrity sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + regenerator-transform "^0.15.1" + +"@babel/plugin-transform-reserved-words@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" + integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-shorthand-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-spread@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + +"@babel/plugin-transform-sticky-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" + integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-template-literals@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" + integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-typeof-symbol@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" + integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-unicode-escapes@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" + integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-unicode-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" + integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/preset-env@^7.19": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506" + integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== + dependencies: + "@babel/compat-data" "^7.20.1" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" + "@babel/plugin-proposal-async-generator-functions" "^7.20.1" + "@babel/plugin-proposal-class-properties" "^7.18.6" + "@babel/plugin-proposal-class-static-block" "^7.18.6" + "@babel/plugin-proposal-dynamic-import" "^7.18.6" + "@babel/plugin-proposal-export-namespace-from" "^7.18.9" + "@babel/plugin-proposal-json-strings" "^7.18.6" + "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" + "@babel/plugin-proposal-numeric-separator" "^7.18.6" + "@babel/plugin-proposal-object-rest-spread" "^7.20.2" + "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.9" + "@babel/plugin-proposal-private-methods" "^7.18.6" + "@babel/plugin-proposal-private-property-in-object" "^7.18.6" + "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" + "@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.20.0" + "@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-transform-arrow-functions" "^7.18.6" + "@babel/plugin-transform-async-to-generator" "^7.18.6" + "@babel/plugin-transform-block-scoped-functions" "^7.18.6" + "@babel/plugin-transform-block-scoping" "^7.20.2" + "@babel/plugin-transform-classes" "^7.20.2" + "@babel/plugin-transform-computed-properties" "^7.18.9" + "@babel/plugin-transform-destructuring" "^7.20.2" + "@babel/plugin-transform-dotall-regex" "^7.18.6" + "@babel/plugin-transform-duplicate-keys" "^7.18.9" + "@babel/plugin-transform-exponentiation-operator" "^7.18.6" + "@babel/plugin-transform-for-of" "^7.18.8" + "@babel/plugin-transform-function-name" "^7.18.9" + "@babel/plugin-transform-literals" "^7.18.9" + "@babel/plugin-transform-member-expression-literals" "^7.18.6" + "@babel/plugin-transform-modules-amd" "^7.19.6" + "@babel/plugin-transform-modules-commonjs" "^7.19.6" + "@babel/plugin-transform-modules-systemjs" "^7.19.6" + "@babel/plugin-transform-modules-umd" "^7.18.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1" + "@babel/plugin-transform-new-target" "^7.18.6" + "@babel/plugin-transform-object-super" "^7.18.6" + "@babel/plugin-transform-parameters" "^7.20.1" + "@babel/plugin-transform-property-literals" "^7.18.6" + "@babel/plugin-transform-regenerator" "^7.18.6" + "@babel/plugin-transform-reserved-words" "^7.18.6" + "@babel/plugin-transform-shorthand-properties" "^7.18.6" + "@babel/plugin-transform-spread" "^7.19.0" + "@babel/plugin-transform-sticky-regex" "^7.18.6" + "@babel/plugin-transform-template-literals" "^7.18.9" + "@babel/plugin-transform-typeof-symbol" "^7.18.9" + "@babel/plugin-transform-unicode-escapes" "^7.18.10" + "@babel/plugin-transform-unicode-regex" "^7.18.6" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.20.2" + babel-plugin-polyfill-corejs2 "^0.3.3" + babel-plugin-polyfill-corejs3 "^0.6.0" + babel-plugin-polyfill-regenerator "^0.4.1" + core-js-compat "^3.25.1" + semver "^6.3.0" + +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" + integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-react-display-name" "^7.18.6" + "@babel/plugin-transform-react-jsx" "^7.18.6" + "@babel/plugin-transform-react-jsx-development" "^7.18.6" + "@babel/plugin-transform-react-pure-annotations" "^7.18.6" + +"@babel/runtime@^7.8.4": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3" + integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA== + dependencies: + regenerator-runtime "^0.13.11" + +"@babel/template@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.10" + "@babel/types" "^7.18.10" + +"@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1", "@babel/traverse@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.5.tgz#78eb244bea8270fdda1ef9af22a5d5e5b7e57133" + integrity sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.5" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.20.5" + "@babel/types" "^7.20.5" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.4.4": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.5.tgz#e206ae370b5393d94dfd1d04cd687cace53efa84" + integrity sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + 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.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.4.10" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.10.tgz#19731b9685c19ed1552da7052b6f668ed7eb64bb" + integrity sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/node@*": + version "18.11.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.11.tgz#1d455ac0211549a8409d3cdb371cd55cc971e8dc" + integrity sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g== + +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.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-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + +acorn@^8.5.0, acorn@^8.7.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== + +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.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" + integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== + dependencies: + "@babel/compat-data" "^7.17.7" + "@babel/helper-define-polyfill-provider" "^0.3.3" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" + integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.3" + core-js-compat "^3.25.1" + +babel-plugin-polyfill-regenerator@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" + integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.3" + +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.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^4.21.4: + version "4.21.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== + dependencies: + caniuse-lite "^1.0.30001400" + electron-to-chromium "^1.4.251" + node-releases "^2.0.6" + update-browserslist-db "^1.0.9" + +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.30001400: + version "1.0.30001436" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001436.tgz#22d7cbdbbbb60cdc4ca1030ccd6dea9f5de4848b" + integrity sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg== + +chalk@^2.0.0: + 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.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + 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.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +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.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + +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@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +core-js-compat@^3.25.1: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.26.1.tgz#0e710b09ebf689d719545ac36e49041850f943df" + integrity sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A== + dependencies: + browserslist "^4.21.4" + +core-js@^3.25.0: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e" + integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA== + +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: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +electron-to-chromium@^1.4.251: + version "1.4.284" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== + +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.10.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" + integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +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.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + 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" + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +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.4, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +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== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +immutable@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef" + integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ== + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + 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.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +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.1: + 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.5" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== + +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== + +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.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== + +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: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +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.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +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.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" + integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== + 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.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +regenerator-transform@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" + integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== + dependencies: + "@babel/runtime" "^7.8.4" + +regexpu-core@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" + integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsgen "^0.7.1" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsgen@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" + integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== + +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.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.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.56.1" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.56.1.tgz#94d3910cd468fd075fa87f5bb17437a0b617d8a7" + integrity sha512-VpEyKpyBPCxE7qGDtOcdJ6fFbcpOM+Emu7uZLxVrkX8KVU/Dp5UF7WLvzqRuUhB6mqqQt1xffLoG+AndxTZrCQ== + 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.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + 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.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +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.1.3: + version "5.3.6" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" + integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== + dependencies: + "@jridgewell/trace-mapping" "^0.3.14" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + terser "^5.14.1" + +terser@^5.14.1: + version "5.16.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.1.tgz#5af3bc3d0f24241c7fb2024199d5c461a1075880" + integrity sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + 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" + +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.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +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.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + 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.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + 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.76.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c" + integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.7.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + 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.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.4.0" + 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.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== diff --git a/modules/ppcp-paylater-configurator/.babelrc b/modules/ppcp-paylater-configurator/.babelrc new file mode 100644 index 000000000..822778e6c --- /dev/null +++ b/modules/ppcp-paylater-configurator/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "useBuiltIns": "usage", + "corejs": "3.25.0" + } + ], + [ + "@babel/preset-react" + ] + ] +} diff --git a/modules/ppcp-paylater-configurator/.gitignore b/modules/ppcp-paylater-configurator/.gitignore new file mode 100644 index 000000000..0bd2b9f58 --- /dev/null +++ b/modules/ppcp-paylater-configurator/.gitignore @@ -0,0 +1,3 @@ +node_modules +assets/js +assets/css diff --git a/modules/ppcp-paylater-configurator/composer.json b/modules/ppcp-paylater-configurator/composer.json new file mode 100644 index 000000000..755aa0dce --- /dev/null +++ b/modules/ppcp-paylater-configurator/composer.json @@ -0,0 +1,17 @@ +{ + "name": "woocommerce/ppcp-paylater-configurator", + "type": "dhii-mod", + "description": "Pay Later Messaging configurator module for PPCP", + "license": "GPL-2.0", + "require": { + "php": "^7.2 | ^8.0", + "dhii/module-interface": "^0.3.0-alpha1" + }, + "autoload": { + "psr-4": { + "WooCommerce\\PayPalCommerce\\PayLaterConfigurator\\": "src" + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/modules/ppcp-paylater-configurator/extensions.php b/modules/ppcp-paylater-configurator/extensions.php new file mode 100644 index 000000000..9092912e0 --- /dev/null +++ b/modules/ppcp-paylater-configurator/extensions.php @@ -0,0 +1,83 @@ + function ( ContainerInterface $container, array $fields ): array { + $old_fields = array( + 'pay_later_messaging_locations', + 'pay_later_enable_styling_per_messaging_location', + 'pay_later_general_message_layout', + 'pay_later_general_message_logo', + 'pay_later_general_message_position', + 'pay_later_general_message_color', + 'pay_later_general_message_flex_color', + 'pay_later_general_message_flex_ratio', + 'pay_later_general_message_preview', + 'pay_later_product_messaging_heading', + 'pay_later_product_message_layout', + 'pay_later_product_message_logo', + 'pay_later_product_message_position', + 'pay_later_product_message_color', + 'pay_later_product_message_flex_color', + 'pay_later_product_message_flex_ratio', + 'pay_later_product_message_preview', + 'pay_later_cart_messaging_heading', + 'pay_later_cart_message_layout', + 'pay_later_cart_message_logo', + 'pay_later_cart_message_position', + 'pay_later_cart_message_color', + 'pay_later_cart_message_flex_color', + 'pay_later_cart_message_flex_ratio', + 'pay_later_cart_message_preview', + 'pay_later_checkout_messaging_heading', + 'pay_later_checkout_message_layout', + 'pay_later_checkout_message_logo', + 'pay_later_checkout_message_position', + 'pay_later_checkout_message_color', + 'pay_later_checkout_message_flex_color', + 'pay_later_checkout_message_flex_ratio', + 'pay_later_checkout_message_preview', + 'pay_later_shop_messaging_heading', + 'pay_later_shop_message_layout', + 'pay_later_shop_message_logo', + 'pay_later_shop_message_position', + 'pay_later_shop_message_color', + 'pay_later_shop_message_flex_color', + 'pay_later_shop_message_flex_ratio', + 'pay_later_shop_message_preview', + 'pay_later_home_messaging_heading', + 'pay_later_home_message_layout', + 'pay_later_home_message_logo', + 'pay_later_home_message_position', + 'pay_later_home_message_color', + 'pay_later_home_message_flex_color', + 'pay_later_home_message_flex_ratio', + 'pay_later_home_message_preview', + ); + + $settings = $container->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + $vault_enabled = $settings->has( 'vault_enabled' ) && $settings->get( 'vault_enabled' ); + + if ( ! $vault_enabled ) { + $old_fields[] = 'pay_later_messaging_enabled'; + } + + foreach ( $old_fields as $old_field ) { + unset( $fields[ $old_field ] ); + } + + return $fields; + }, +); diff --git a/modules/ppcp-paylater-configurator/module.php b/modules/ppcp-paylater-configurator/module.php new file mode 100644 index 000000000..d4234abcf --- /dev/null +++ b/modules/ppcp-paylater-configurator/module.php @@ -0,0 +1,16 @@ + 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-paylater-configurator/resources/css/paylater-configurator.scss b/modules/ppcp-paylater-configurator/resources/css/paylater-configurator.scss new file mode 100644 index 000000000..6b61e8a2c --- /dev/null +++ b/modules/ppcp-paylater-configurator/resources/css/paylater-configurator.scss @@ -0,0 +1,55 @@ +#messaging-configurator { + & > div { + justify-content: left; + margin: 0; + + & > div { + padding: 0; + } + } + .ppcp-paylater-configurator-publishButton { + display:none; + } + .ppcp-paylater-configurator-header { + font-size: 1.3em; + color: #1d2327; + margin: 1em 0; + font-weight: 600; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + line-height: 1.3; + } + #configurator-eligibleContainer div:has(.ppcp-paylater-configurator-header#configurator-headerText) { + display: none; + } + .ppcp-paylater-configurator-subheader { + font-size: 14px; + line-height: 1.5; + color: #3c434a; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; + + a { + font-size: 14px; + } + } + + .css-dpyjrq-text_body, .css-dpyjrq-text_body a { + font-size: 14px; + } + + button.css-104jwuk { + background: none; + } + + .css-1yo2lxy-text_body_strong, span.css-16jt5za-text_body, span.css-1yo2lxy-text_body_strong, span { + font-size: 14px; + } + + hr { + margin-right: 16px; + border-top-color: #B1B7BD; + } +} + +#field-pay_later_messaging_heading h3{ + margin-bottom: 0px; +} diff --git a/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js b/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js new file mode 100644 index 000000000..9549ef2af --- /dev/null +++ b/modules/ppcp-paylater-configurator/resources/js/paylater-configurator.js @@ -0,0 +1,62 @@ +document.addEventListener( 'DOMContentLoaded', () => { + const form = document.querySelector('#mainform'); + const table = form.querySelector('.form-table'); + const headingRow = table.querySelector('#field-pay_later_messaging_heading'); + const saveChangesButton = form.querySelector('.woocommerce-save-button'); + const publishButtonClassName = PcpPayLaterConfigurator.publishButtonClassName; + + const tempContainer = document.createElement('div'); + tempContainer.innerHTML = `
`; + + // Get the new row element from the container + const newRow = tempContainer.firstChild; + + // Insert the new row after the headingRow + headingRow.parentNode.insertBefore(newRow, headingRow.nextSibling); + + + let isSaving = false; // Flag variable to track whether saving is in progress + + saveChangesButton.addEventListener('click', () => { + // Check if saving is not already in progress + if (!isSaving) { + isSaving = true; // Set flag to indicate saving is in progress + + // Trigger the click event on the publish button + form.querySelector('.' + publishButtonClassName).click(); + + // Trigger click event on saveChangesButton after a short delay + setTimeout(() => { + saveChangesButton.click(); // Trigger click event on saveChangesButton + isSaving = false; // Reset flag when saving is complete + }, 1000); // Adjust the delay as needed + } + }); + + merchantConfigurators.Messaging({ + config: PcpPayLaterConfigurator.config, + merchantClientId: PcpPayLaterConfigurator.merchantClientId, + partnerClientId: PcpPayLaterConfigurator.partnerClientId, + partnerName: 'WooCommerce', + bnCode: 'Woo_PPCP', + placements: ['cart', 'checkout', 'product', 'shop', 'home', 'custom_placement'], + styleOverrides: { + button: publishButtonClassName, + header: PcpPayLaterConfigurator.headerClassName, + subheader: PcpPayLaterConfigurator.subheaderClassName + }, + onSave: data => { + fetch(PcpPayLaterConfigurator.ajax.save_config.endpoint, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + credentials: 'same-origin', + body: JSON.stringify({ + nonce: PcpPayLaterConfigurator.ajax.save_config.nonce, + config: data, + }), + }); + } + }) +} ); diff --git a/modules/ppcp-paylater-configurator/services.php b/modules/ppcp-paylater-configurator/services.php new file mode 100644 index 000000000..7b668aba7 --- /dev/null +++ b/modules/ppcp-paylater-configurator/services.php @@ -0,0 +1,38 @@ + static function ( ContainerInterface $container ): string { + /** + * Cannot return false for this path. + * + * @psalm-suppress PossiblyFalseArgument + */ + return plugins_url( + '/modules/ppcp-paylater-configurator/', + dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php' + ); + }, + 'paylater-configurator.factory.config' => static function ( ContainerInterface $container ): ConfigFactory { + return new ConfigFactory(); + }, + 'paylater-configurator.endpoint.save-config' => static function ( ContainerInterface $container ): SaveConfig { + return new SaveConfig( + $container->get( 'wcgateway.settings' ), + $container->get( 'button.request-data' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, +); diff --git a/modules/ppcp-paylater-configurator/src/Endpoint/SaveConfig.php b/modules/ppcp-paylater-configurator/src/Endpoint/SaveConfig.php new file mode 100644 index 000000000..df4e4affa --- /dev/null +++ b/modules/ppcp-paylater-configurator/src/Endpoint/SaveConfig.php @@ -0,0 +1,150 @@ +settings = $settings; + $this->request_data = $request_data; + $this->logger = $logger; + } + + /** + * Returns the nonce. + */ + public static function nonce(): string { + return self::ENDPOINT; + } + + /** + * Handles the request. + */ + public function handle_request(): bool { + if ( ! current_user_can( 'manage_woocommerce' ) ) { + wp_send_json_error( 'Not admin.', 403 ); + return false; + } + + try { + $data = $this->request_data->read_request( $this->nonce() ); + + $this->save_config( $data['config']['config'] ); + + wp_send_json_success(); + return true; + } catch ( Throwable $error ) { + $this->logger->error( "SaveConfig execution failed. {$error->getMessage()} {$error->getFile()}:{$error->getLine()}" ); + + wp_send_json_error(); + return false; + } + } + + /** + * Saves the config into the old settings. + * + * @param array $config The configurator config. + */ + private function save_config( array $config ): void { + $this->settings->set( 'pay_later_enable_styling_per_messaging_location', true ); + $this->settings->set( 'pay_later_messaging_enabled', true ); + + $enabled_locations = array(); + foreach ( $config as $placement => $data ) { + $this->save_config_for_location( $data, $placement ); + + if ( $placement === 'custom_placement' ) { + $data = $data[0] ?? array(); + } + + if ( $data['status'] === 'enabled' ) { + $enabled_locations[] = $placement; + } + } + + $this->settings->set( 'pay_later_messaging_locations', $enabled_locations ); + + $this->settings->persist(); + } + + /** + * Saves the config for a location into the old settings. + * + * @param array $config The configurator config for a location. + * @param string $location The location name in the old settings. + */ + private function save_config_for_location( array $config, string $location ): void { + $this->set_value_if_present( $config, 'layout', "pay_later_{$location}_message_layout" ); + + $this->set_value_if_present( $config, 'color', "pay_later_{$location}_message_flex_color" ); + $this->set_value_if_present( $config, 'ratio', "pay_later_{$location}_message_flex_ratio" ); + + $this->set_value_if_present( $config, 'logo-position', "pay_later_{$location}_message_position" ); + $this->set_value_if_present( $config, 'logo-type', "pay_later_{$location}_message_logo" ); + $this->set_value_if_present( $config, 'logo-color', "pay_later_{$location}_message_color" ); + $this->set_value_if_present( $config, 'text-size', "pay_later_{$location}_message_text_size" ); + $this->set_value_if_present( $config, 'text-color', "pay_later_{$location}_message_color" ); + } + + /** + * Sets the value in the settings if it is available in the config. + * + * @param array $config The configurator config. + * @param string $key The key in the config. + * @param string $settings_key The key in the settings. + */ + private function set_value_if_present( array $config, string $key, string $settings_key ): void { + if ( isset( $config[ $key ] ) ) { + $this->settings->set( $settings_key, $config[ $key ] ); + } + } +} diff --git a/modules/ppcp-paylater-configurator/src/Factory/ConfigFactory.php b/modules/ppcp-paylater-configurator/src/Factory/ConfigFactory.php new file mode 100644 index 000000000..c73bbd0ab --- /dev/null +++ b/modules/ppcp-paylater-configurator/src/Factory/ConfigFactory.php @@ -0,0 +1,145 @@ + $this->for_location( $settings, 'cart' ), + 'checkout' => $this->for_location( $settings, 'checkout' ), + 'product' => $this->for_location( $settings, 'product' ), + 'shop' => $this->for_location( $settings, 'shop' ), + 'home' => $this->for_location( $settings, 'home' ), + 'custom_placement' => array( $this->for_location( $settings, 'woocommerceBlock' ) ), + ); + } + + /** + * Returns the configurator config for a location. + * + * @param Settings $settings The settings. + * @param string $location The location name in the old settings. + */ + private function for_location( Settings $settings, string $location ): array { + $selected_locations = $settings->has( 'pay_later_messaging_locations' ) ? $settings->get( 'pay_later_messaging_locations' ) : array(); + + switch ( $location ) { + case 'shop': + case 'home': + $config = $this->for_shop_or_home( $settings, $location, $selected_locations ); + break; + case 'woocommerceBlock': + $config = $this->for_woocommerce_block( $selected_locations ); + break; + default: + $config = $this->for_default_location( $settings, $location, $selected_locations ); + break; + } + + return $config; + } + + /** + * Returns the configurator config for shop, home locations. + * + * @param Settings $settings The settings. + * @param string $location The location. + * @param string[] $selected_locations The list of selected locations. + * @return array{ + * layout: string, + * color: string, + * ratio: string, + * status: "disabled"|"enabled", + * placement: string + * } The configurator config map. + */ + private function for_shop_or_home( Settings $settings, string $location, array $selected_locations ): array { + return array( + 'layout' => $this->get_or_default( $settings, "pay_later_{$location}_message_layout", 'flex' ), + 'color' => $this->get_or_default( $settings, "pay_later_{$location}_message_flex_color", 'black' ), + 'ratio' => $this->get_or_default( $settings, "pay_later_{$location}_message_flex_ratio", '8x1' ), + 'status' => in_array( $location, $selected_locations, true ) ? 'enabled' : 'disabled', + 'placement' => $location, + ); + } + + /** + * Returns the configurator config for woocommerceBlock location. + * + * @param array $selected_locations The list of selected locations. + * @return array{ + * status: "disabled"|"enabled", + * message_reference: string + * } The configurator config map. + */ + private function for_woocommerce_block( array $selected_locations ): array { + return array( + 'status' => in_array( 'custom_placement', $selected_locations, true ) ? 'enabled' : 'disabled', + 'message_reference' => 'woocommerceBlock', + ); + } + + /** + * Returns the configurator config for default locations. + * + * @param Settings $settings The settings. + * @param string $location The location. + * @param string[] $selected_locations The list of selected locations. + * @return array{ + * layout: string, + * logo-position: string, + * logo-type: string, + * text-color: string, + * text-size: string, + * status: "disabled"|"enabled", + * placement: string + * } The configurator config map. + */ + private function for_default_location( Settings $settings, string $location, array $selected_locations ): array { + return array( + 'layout' => $this->get_or_default( $settings, "pay_later_{$location}_message_layout", 'text' ), + 'logo-position' => $this->get_or_default( $settings, "pay_later_{$location}_message_position", 'left' ), + 'logo-type' => $this->get_or_default( $settings, "pay_later_{$location}_message_logo", 'inline' ), + 'text-color' => $this->get_or_default( $settings, "pay_later_{$location}_message_color", 'black' ), + 'text-size' => $this->get_or_default( $settings, "pay_later_{$location}_message_text_size", '12' ), + 'status' => in_array( $location, $selected_locations, true ) ? 'enabled' : 'disabled', + 'placement' => $location, + ); + } + + /** + * Returns the settings value or default, if does not exist or not allowed value. + * + * @param Settings $settings The settings. + * @param string $key The key. + * @param mixed $default The default value. + * @param array|null $allowed_values The list of allowed values, or null if all values are allowed. + * @return string + */ + private function get_or_default( Settings $settings, string $key, $default, ?array $allowed_values = null ): string { + if ( $settings->has( $key ) ) { + $value = $settings->get( $key ); + if ( ! $allowed_values || in_array( $value, $allowed_values, true ) ) { + return $value; + } + } + return $default; + } +} diff --git a/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php b/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php new file mode 100644 index 000000000..fd5d4c6d5 --- /dev/null +++ b/modules/ppcp-paylater-configurator/src/PayLaterConfiguratorModule.php @@ -0,0 +1,135 @@ +get( 'button.helper.messages-apply' ); + assert( $messages_apply instanceof MessagesApply ); + + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + + $vault_enabled = $settings->has( 'vault_enabled' ) && $settings->get( 'vault_enabled' ); + + if ( $vault_enabled || ! $messages_apply->for_country() ) { + return; + } + + add_action( + 'wc_ajax_' . SaveConfig::ENDPOINT, + static function () use ( $c ) { + $endpoint = $c->get( 'paylater-configurator.endpoint.save-config' ); + assert( $endpoint instanceof SaveConfig ); + $endpoint->handle_request(); + } + ); + + $current_page_id = $c->get( 'wcgateway.current-ppcp-settings-page-id' ); + + if ( $current_page_id !== Settings::PAY_LATER_TAB_ID ) { + return; + } + + add_action( + 'init', + static function () use ( $c, $settings ) { + wp_enqueue_script( + 'ppcp-paylater-configurator-lib', + 'https://www.paypalobjects.com/merchant-library/merchant-configurator.js', + array(), + $c->get( 'ppcp.asset-version' ), + true + ); + + wp_enqueue_script( + 'ppcp-paylater-configurator', + $c->get( 'paylater-configurator.url' ) . '/assets/js/paylater-configurator.js', + array(), + $c->get( 'ppcp.asset-version' ), + true + ); + + wp_enqueue_style( + 'ppcp-paylater-configurator-style', + $c->get( 'paylater-configurator.url' ) . '/assets/css/paylater-configurator.css', + array(), + $c->get( 'ppcp.asset-version' ) + ); + + $config_factory = $c->get( 'paylater-configurator.factory.config' ); + assert( $config_factory instanceof ConfigFactory ); + + wp_localize_script( + 'ppcp-paylater-configurator', + 'PcpPayLaterConfigurator', + array( + 'ajax' => array( + 'save_config' => array( + 'endpoint' => \WC_AJAX::get_endpoint( SaveConfig::ENDPOINT ), + 'nonce' => wp_create_nonce( SaveConfig::nonce() ), + ), + ), + 'config' => $config_factory->from_settings( $settings ), + 'merchantClientId' => $settings->get( 'client_id' ), + 'partnerClientId' => $c->get( 'api.partner_merchant_id' ), + 'publishButtonClassName' => 'ppcp-paylater-configurator-publishButton', + 'headerClassName' => 'ppcp-paylater-configurator-header', + 'subheaderClassName' => 'ppcp-paylater-configurator-subheader', + ) + ); + } + ); + } + + /** + * Returns the key for the module. + * + * @return string|void + */ + public function getKey() { + } +} diff --git a/modules/ppcp-paylater-configurator/webpack.config.js b/modules/ppcp-paylater-configurator/webpack.config.js new file mode 100644 index 000000000..d131bfe2e --- /dev/null +++ b/modules/ppcp-paylater-configurator/webpack.config.js @@ -0,0 +1,39 @@ +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: { + 'paylater-configurator': path.resolve('./resources/js/paylater-configurator.js'), + 'paylater-configurator-style': path.resolve('./resources/css/paylater-configurator.scss'), + }, + 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-paylater-configurator/yarn.lock b/modules/ppcp-paylater-configurator/yarn.lock new file mode 100644 index 000000000..209adc4a4 --- /dev/null +++ b/modules/ppcp-paylater-configurator/yarn.lock @@ -0,0 +1,2201 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.5.tgz#86f172690b093373a933223b4745deeb6049e733" + integrity sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g== + +"@babel/core@^7.19": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.5.tgz#45e2114dc6cd4ab167f81daf7820e8fa1250d113" + integrity sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-module-transforms" "^7.20.2" + "@babel/helpers" "^7.20.5" + "@babel/parser" "^7.20.5" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.1" + semver "^6.3.0" + +"@babel/generator@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.5.tgz#cb25abee3178adf58d6814b68517c62bdbfdda95" + integrity sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA== + dependencies: + "@babel/types" "^7.20.5" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" + integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.18.6" + "@babel/types" "^7.18.9" + +"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" + integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== + dependencies: + "@babel/compat-data" "^7.20.0" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.5.tgz#327154eedfb12e977baa4ecc72e5806720a85a06" + integrity sha512-3RCdA/EmEaikrhayahwToF0fpweU/8o2p8vhc1c/1kftHOdTKuC65kik/TLc+qfbS8JKw4qqJbne4ovICDhmww== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-split-export-declaration" "^7.18.6" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz#5ea79b59962a09ec2acf20a963a01ab4d076ccca" + integrity sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + regexpu-core "^5.2.1" + +"@babel/helper-define-polyfill-provider@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" + integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== + dependencies: + "@babel/helper-compilation-targets" "^7.17.7" + "@babel/helper-plugin-utils" "^7.16.7" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== + +"@babel/helper-explode-assignable-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" + integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-member-expression-to-functions@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" + integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== + dependencies: + "@babel/types" "^7.18.9" + +"@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" + integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.2" + +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== + dependencies: + "@babel/types" "^7.18.6" + +"@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.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== + +"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" + integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-wrap-function" "^7.18.9" + "@babel/types" "^7.18.9" + +"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" + integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/traverse" "^7.19.1" + "@babel/types" "^7.19.0" + +"@babel/helper-simple-access@^7.19.4", "@babel/helper-simple-access@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" + integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== + dependencies: + "@babel/types" "^7.20.2" + +"@babel/helper-skip-transparent-expression-wrappers@^7.18.9": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" + integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== + dependencies: + "@babel/types" "^7.20.0" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helper-wrap-function@^7.18.9": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3" + integrity sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q== + dependencies: + "@babel/helper-function-name" "^7.19.0" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + +"@babel/helpers@^7.20.5": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.6.tgz#e64778046b70e04779dfbdf924e7ebb45992c763" + integrity sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.18.10", "@babel/parser@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.5.tgz#7f3c7335fe417665d929f34ae5dceae4c04015e8" + integrity sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": + version "7.18.6" + 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.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" + integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" + integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/plugin-proposal-optional-chaining" "^7.18.9" + +"@babel/plugin-proposal-async-generator-functions@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.1.tgz#352f02baa5d69f4e7529bdac39aaa02d41146af9" + integrity sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-remap-async-to-generator" "^7.18.9" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-class-static-block@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" + integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-proposal-dynamic-import@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" + integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-proposal-export-namespace-from@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" + integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" + integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" + integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" + integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" + integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.2.tgz#a556f59d555f06961df1e572bb5eca864c84022d" + integrity sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ== + dependencies: + "@babel/compat-data" "^7.20.1" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.20.1" + +"@babel/plugin-proposal-optional-catch-binding@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" + integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-private-methods@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" + integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-private-property-in-object@^7.18.6": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz#309c7668f2263f1c711aa399b5a9a6291eef6135" + integrity sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-create-class-features-plugin" "^7.20.5" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" + integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@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.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" + integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + +"@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.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@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-transform-arrow-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" + integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-async-to-generator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" + integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== + dependencies: + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" + +"@babel/plugin-transform-block-scoped-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-block-scoping@^7.20.2": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.5.tgz#401215f9dc13dc5262940e2e527c9536b3d7f237" + integrity sha512-WvpEIW9Cbj9ApF3yJCjIEEf1EiNJLtXagOrL5LNWEZOo3jv8pmPoYTSNJQvqej8OavVlgOoOPw6/htGZro6IkA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-classes@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.2.tgz#c0033cf1916ccf78202d04be4281d161f6709bb2" + integrity sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-split-export-declaration" "^7.18.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" + integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-destructuring@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.2.tgz#c23741cfa44ddd35f5e53896e88c75331b8b2792" + integrity sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" + integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-duplicate-keys@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" + integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-exponentiation-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" + integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-for-of@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" + integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-function-name@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" + integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== + dependencies: + "@babel/helper-compilation-targets" "^7.18.9" + "@babel/helper-function-name" "^7.18.9" + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-literals@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" + integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-member-expression-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-modules-amd@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.19.6.tgz#aca391801ae55d19c4d8d2ebfeaa33df5f2a2cbd" + integrity sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg== + dependencies: + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + +"@babel/plugin-transform-modules-commonjs@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz#25b32feef24df8038fc1ec56038917eacb0b730c" + integrity sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ== + dependencies: + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-simple-access" "^7.19.4" + +"@babel/plugin-transform-modules-systemjs@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.6.tgz#59e2a84064b5736a4471b1aa7b13d4431d327e0d" + integrity sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ== + dependencies: + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-validator-identifier" "^7.19.1" + +"@babel/plugin-transform-modules-umd@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" + integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz#626298dd62ea51d452c3be58b285d23195ba69a8" + integrity sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.20.5" + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-new-target@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" + integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-object-super@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + +"@babel/plugin-transform-parameters@^7.20.1": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.5.tgz#f8f9186c681d10c3de7620c916156d893c8a019e" + integrity sha512-h7plkOmcndIUWXZFLgpbrh2+fXAi47zcUX7IrOQuZdLD0I0KvjJ6cvo3BEcAOsDOcZhVKGJqv07mkSqK0y2isQ== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-property-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-display-name@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" + integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-jsx-development@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" + integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.18.6" + +"@babel/plugin-transform-react-jsx@^7.18.6": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" + integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-jsx" "^7.18.6" + "@babel/types" "^7.19.0" + +"@babel/plugin-transform-react-pure-annotations@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" + integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-regenerator@^7.18.6": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz#57cda588c7ffb7f4f8483cc83bdcea02a907f04d" + integrity sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + regenerator-transform "^0.15.1" + +"@babel/plugin-transform-reserved-words@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" + integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-shorthand-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-spread@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + +"@babel/plugin-transform-sticky-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" + integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-template-literals@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" + integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-typeof-symbol@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" + integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-unicode-escapes@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" + integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-unicode-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" + integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/preset-env@^7.19": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506" + integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== + dependencies: + "@babel/compat-data" "^7.20.1" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" + "@babel/plugin-proposal-async-generator-functions" "^7.20.1" + "@babel/plugin-proposal-class-properties" "^7.18.6" + "@babel/plugin-proposal-class-static-block" "^7.18.6" + "@babel/plugin-proposal-dynamic-import" "^7.18.6" + "@babel/plugin-proposal-export-namespace-from" "^7.18.9" + "@babel/plugin-proposal-json-strings" "^7.18.6" + "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" + "@babel/plugin-proposal-numeric-separator" "^7.18.6" + "@babel/plugin-proposal-object-rest-spread" "^7.20.2" + "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.9" + "@babel/plugin-proposal-private-methods" "^7.18.6" + "@babel/plugin-proposal-private-property-in-object" "^7.18.6" + "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" + "@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.20.0" + "@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-transform-arrow-functions" "^7.18.6" + "@babel/plugin-transform-async-to-generator" "^7.18.6" + "@babel/plugin-transform-block-scoped-functions" "^7.18.6" + "@babel/plugin-transform-block-scoping" "^7.20.2" + "@babel/plugin-transform-classes" "^7.20.2" + "@babel/plugin-transform-computed-properties" "^7.18.9" + "@babel/plugin-transform-destructuring" "^7.20.2" + "@babel/plugin-transform-dotall-regex" "^7.18.6" + "@babel/plugin-transform-duplicate-keys" "^7.18.9" + "@babel/plugin-transform-exponentiation-operator" "^7.18.6" + "@babel/plugin-transform-for-of" "^7.18.8" + "@babel/plugin-transform-function-name" "^7.18.9" + "@babel/plugin-transform-literals" "^7.18.9" + "@babel/plugin-transform-member-expression-literals" "^7.18.6" + "@babel/plugin-transform-modules-amd" "^7.19.6" + "@babel/plugin-transform-modules-commonjs" "^7.19.6" + "@babel/plugin-transform-modules-systemjs" "^7.19.6" + "@babel/plugin-transform-modules-umd" "^7.18.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1" + "@babel/plugin-transform-new-target" "^7.18.6" + "@babel/plugin-transform-object-super" "^7.18.6" + "@babel/plugin-transform-parameters" "^7.20.1" + "@babel/plugin-transform-property-literals" "^7.18.6" + "@babel/plugin-transform-regenerator" "^7.18.6" + "@babel/plugin-transform-reserved-words" "^7.18.6" + "@babel/plugin-transform-shorthand-properties" "^7.18.6" + "@babel/plugin-transform-spread" "^7.19.0" + "@babel/plugin-transform-sticky-regex" "^7.18.6" + "@babel/plugin-transform-template-literals" "^7.18.9" + "@babel/plugin-transform-typeof-symbol" "^7.18.9" + "@babel/plugin-transform-unicode-escapes" "^7.18.10" + "@babel/plugin-transform-unicode-regex" "^7.18.6" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.20.2" + babel-plugin-polyfill-corejs2 "^0.3.3" + babel-plugin-polyfill-corejs3 "^0.6.0" + babel-plugin-polyfill-regenerator "^0.4.1" + core-js-compat "^3.25.1" + semver "^6.3.0" + +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" + integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-react-display-name" "^7.18.6" + "@babel/plugin-transform-react-jsx" "^7.18.6" + "@babel/plugin-transform-react-jsx-development" "^7.18.6" + "@babel/plugin-transform-react-pure-annotations" "^7.18.6" + +"@babel/runtime@^7.8.4": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3" + integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA== + dependencies: + regenerator-runtime "^0.13.11" + +"@babel/template@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.10" + "@babel/types" "^7.18.10" + +"@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1", "@babel/traverse@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.5.tgz#78eb244bea8270fdda1ef9af22a5d5e5b7e57133" + integrity sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.5" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.20.5" + "@babel/types" "^7.20.5" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.4.4": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.5.tgz#e206ae370b5393d94dfd1d04cd687cace53efa84" + integrity sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + 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.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.4.10" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.10.tgz#19731b9685c19ed1552da7052b6f668ed7eb64bb" + integrity sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/node@*": + version "18.11.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.11.tgz#1d455ac0211549a8409d3cdb371cd55cc971e8dc" + integrity sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g== + +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.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-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + +acorn@^8.5.0, acorn@^8.7.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== + +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.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" + integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== + dependencies: + "@babel/compat-data" "^7.17.7" + "@babel/helper-define-polyfill-provider" "^0.3.3" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" + integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.3" + core-js-compat "^3.25.1" + +babel-plugin-polyfill-regenerator@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" + integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.3" + +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.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^4.21.4: + version "4.21.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== + dependencies: + caniuse-lite "^1.0.30001400" + electron-to-chromium "^1.4.251" + node-releases "^2.0.6" + update-browserslist-db "^1.0.9" + +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.30001400: + version "1.0.30001436" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001436.tgz#22d7cbdbbbb60cdc4ca1030ccd6dea9f5de4848b" + integrity sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg== + +chalk@^2.0.0: + 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.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + 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.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +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.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + +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@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +core-js-compat@^3.25.1: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.26.1.tgz#0e710b09ebf689d719545ac36e49041850f943df" + integrity sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A== + dependencies: + browserslist "^4.21.4" + +core-js@^3.25.0: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e" + integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA== + +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: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +electron-to-chromium@^1.4.251: + version "1.4.284" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== + +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.10.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" + integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +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.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + 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" + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +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.4, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +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== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +immutable@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef" + integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ== + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + 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.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +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.1: + 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.5" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== + +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== + +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.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== + +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: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +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.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +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.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" + integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== + 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.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +regenerator-transform@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" + integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== + dependencies: + "@babel/runtime" "^7.8.4" + +regexpu-core@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" + integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsgen "^0.7.1" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsgen@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" + integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== + +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.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.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.56.1" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.56.1.tgz#94d3910cd468fd075fa87f5bb17437a0b617d8a7" + integrity sha512-VpEyKpyBPCxE7qGDtOcdJ6fFbcpOM+Emu7uZLxVrkX8KVU/Dp5UF7WLvzqRuUhB6mqqQt1xffLoG+AndxTZrCQ== + 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.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + 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.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +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.1.3: + version "5.3.6" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" + integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== + dependencies: + "@jridgewell/trace-mapping" "^0.3.14" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + terser "^5.14.1" + +terser@^5.14.1: + version "5.16.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.1.tgz#5af3bc3d0f24241c7fb2024199d5c461a1075880" + integrity sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + 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" + +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.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +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.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + 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.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + 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.76.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c" + integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.7.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + 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.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.4.0" + 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.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== diff --git a/modules/ppcp-subscription/.babelrc b/modules/ppcp-paypal-subscriptions/.babelrc similarity index 100% rename from modules/ppcp-subscription/.babelrc rename to modules/ppcp-paypal-subscriptions/.babelrc diff --git a/modules/ppcp-paypal-subscriptions/.gitignore b/modules/ppcp-paypal-subscriptions/.gitignore new file mode 100644 index 000000000..0bd2b9f58 --- /dev/null +++ b/modules/ppcp-paypal-subscriptions/.gitignore @@ -0,0 +1,3 @@ +node_modules +assets/js +assets/css diff --git a/modules/ppcp-paypal-subscriptions/composer.json b/modules/ppcp-paypal-subscriptions/composer.json new file mode 100644 index 000000000..161c4b9ce --- /dev/null +++ b/modules/ppcp-paypal-subscriptions/composer.json @@ -0,0 +1,17 @@ +{ + "name": "woocommerce/ppcp-paypal-subscriptions", + "type": "dhii-mod", + "description": "Module for PayPal Subscriptions API integration", + "license": "GPL-2.0", + "require": { + "php": "^7.2 | ^8.0", + "dhii/module-interface": "^0.3.0-alpha1" + }, + "autoload": { + "psr-4": { + "WooCommerce\\PayPalCommerce\\PayPalSubscriptions\\": "src" + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/modules/ppcp-paypal-subscriptions/extensions.php b/modules/ppcp-paypal-subscriptions/extensions.php new file mode 100644 index 000000000..fc91cd245 --- /dev/null +++ b/modules/ppcp-paypal-subscriptions/extensions.php @@ -0,0 +1,14 @@ + static function ( ContainerInterface $container ): DeactivatePlanEndpoint { + return new DeactivatePlanEndpoint( + $container->get( 'button.request-data' ), + $container->get( 'api.endpoint.billing-plans' ) + ); + }, + 'paypal-subscriptions.api-handler' => static function( ContainerInterface $container ): SubscriptionsApiHandler { + return new SubscriptionsApiHandler( + $container->get( 'api.endpoint.catalog-products' ), + $container->get( 'api.factory.product' ), + $container->get( 'api.endpoint.billing-plans' ), + $container->get( 'api.factory.billing-cycle' ), + $container->get( 'api.factory.payment-preferences' ), + $container->get( 'api.shop.currency' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, + 'paypal-subscriptions.module.url' => static function ( ContainerInterface $container ): string { + /** + * The path cannot be false. + * + * @psalm-suppress PossiblyFalseArgument + */ + return plugins_url( + '/modules/ppcp-paypal-subscriptions/', + dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php' + ); + }, +); diff --git a/modules/ppcp-subscription/src/DeactivatePlanEndpoint.php b/modules/ppcp-paypal-subscriptions/src/DeactivatePlanEndpoint.php similarity index 94% rename from modules/ppcp-subscription/src/DeactivatePlanEndpoint.php rename to modules/ppcp-paypal-subscriptions/src/DeactivatePlanEndpoint.php index fe10c0638..4bbdc4e28 100644 --- a/modules/ppcp-subscription/src/DeactivatePlanEndpoint.php +++ b/modules/ppcp-paypal-subscriptions/src/DeactivatePlanEndpoint.php @@ -2,12 +2,12 @@ /** * The deactivate Subscription Plan Endpoint. * - * @package WooCommerce\PayPalCommerce\OrderTracking\Endpoint + * @package WooCommerce\PayPalCommerce\WcSubscriptions */ declare( strict_types=1 ); -namespace WooCommerce\PayPalCommerce\Subscription; +namespace WooCommerce\PayPalCommerce\PayPalSubscriptions; use Exception; use WC_Product; diff --git a/modules/ppcp-subscription/src/SubscriptionModule.php b/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php similarity index 69% rename from modules/ppcp-subscription/src/SubscriptionModule.php rename to modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php index f99a4fd8d..d0aefecaa 100644 --- a/modules/ppcp-subscription/src/SubscriptionModule.php +++ b/modules/ppcp-paypal-subscriptions/src/PayPalSubscriptionsModule.php @@ -1,50 +1,40 @@ renew( $order, $c ); - }, - 10, - 2 - ); - - add_action( - 'woocommerce_scheduled_subscription_payment_' . CreditCardGateway::ID, - function ( $amount, $order ) use ( $c ) { - $this->renew( $order, $c ); - }, - 10, - 2 - ); - - add_action( - 'woocommerce_subscription_payment_complete', - function ( $subscription ) use ( $c ) { - if ( ! in_array( $subscription->get_payment_method(), array( PayPalGateway::ID, CreditCardGateway::ID, CardButtonGateway::ID ), true ) ) { - return; - } - - $paypal_subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; - if ( $paypal_subscription_id ) { - return; - } - - $payment_token_repository = $c->get( 'vaulting.repository.payment-token' ); - $logger = $c->get( 'woocommerce.logger.woocommerce' ); - - $this->add_payment_token_id( $subscription, $payment_token_repository, $logger ); - - if ( count( $subscription->get_related_orders() ) === 1 ) { - $parent_order = $subscription->get_parent(); - if ( is_a( $parent_order, WC_Order::class ) ) { - $order_repository = $c->get( 'api.repository.order' ); - $order = $order_repository->for_wc_order( $parent_order ); - $transaction_id = $this->get_paypal_order_transaction_id( $order ); - if ( $transaction_id ) { - $subscription->update_meta_data( 'ppcp_previous_transaction_reference', $transaction_id ); - $subscription->save(); - } - } - } - } - ); - - add_filter( - 'woocommerce_gateway_description', - function ( $description, $id ) use ( $c ) { - $payment_token_repository = $c->get( 'vaulting.repository.payment-token' ); - $settings = $c->get( 'wcgateway.settings' ); - $subscription_helper = $c->get( 'subscription.helper' ); - - return $this->display_saved_paypal_payments( $settings, (string) $id, $payment_token_repository, (string) $description, $subscription_helper ); - }, - 10, - 2 - ); - - add_filter( - 'woocommerce_credit_card_form_fields', - function ( $default_fields, $id ) use ( $c ) { - $payment_token_repository = $c->get( 'vaulting.repository.payment-token' ); - $settings = $c->get( 'wcgateway.settings' ); - $subscription_helper = $c->get( 'subscription.helper' ); - - return $this->display_saved_credit_cards( $settings, $id, $payment_token_repository, $default_fields, $subscription_helper ); - }, - 20, - 2 - ); - - add_filter( - 'ppcp_create_order_request_body_data', - function( array $data ) use ( $c ) { - // phpcs:ignore WordPress.Security.NonceVerification.Missing - $wc_order_action = wc_clean( wp_unslash( $_POST['wc_order_action'] ?? '' ) ); - - // phpcs:ignore WordPress.Security.NonceVerification.Missing - $subscription_id = wc_clean( wp_unslash( $_POST['post_ID'] ?? '' ) ); - if ( ! $subscription_id ) { - return $data; - } - $subscription = wc_get_order( $subscription_id ); - if ( ! is_a( $subscription, WC_Subscription::class ) ) { - return $data; - } - - if ( - $wc_order_action === 'wcs_process_renewal' && $subscription->get_payment_method() === CreditCardGateway::ID - && isset( $data['payment_source']['token'] ) && $data['payment_source']['token']['type'] === 'PAYMENT_METHOD_TOKEN' - && isset( $data['payment_source']['token']['source']->card ) - ) { - $data['payment_source'] = array( - 'card' => array( - 'vault_id' => $data['payment_source']['token']['id'], - 'stored_credential' => array( - 'payment_initiator' => 'MERCHANT', - 'payment_type' => 'RECURRING', - 'usage' => 'SUBSEQUENT', - ), - ), - ); - - $previous_transaction_reference = $subscription->get_meta( 'ppcp_previous_transaction_reference' ); - if ( $previous_transaction_reference ) { - $data['payment_source']['card']['stored_credential']['previous_transaction_reference'] = $previous_transaction_reference; - } - } - - return $data; - } - ); - - $this->subscriptions_api_integration( $c ); - - add_action( - 'admin_enqueue_scripts', - /** - * Param types removed to avoid third-party issues. - * - * @psalm-suppress MissingClosureParamType - */ - function( $hook ) use ( $c ) { - if ( ! is_string( $hook ) ) { - return; - } - $settings = $c->get( 'wcgateway.settings' ); - $subscription_mode = $settings->has( 'subscriptions_mode' ) ? $settings->get( 'subscriptions_mode' ) : ''; - if ( $hook !== 'post.php' || $subscription_mode !== 'subscriptions_api' ) { - return; - } - - //phpcs:disable WordPress.Security.NonceVerification.Recommended - $post_id = wc_clean( wp_unslash( $_GET['post'] ?? '' ) ); - $product = wc_get_product( $post_id ); - if ( ! ( is_a( $product, WC_Product::class ) ) ) { - return; - } - - $subscriptions_helper = $c->get( 'subscription.helper' ); - assert( $subscriptions_helper instanceof SubscriptionHelper ); - - if ( - ! $subscriptions_helper->plugin_is_active() - || ! ( - is_a( $product, WC_Product_Subscription::class ) - || is_a( $product, WC_Product_Variable_Subscription::class ) - || is_a( $product, WC_Product_Subscription_Variation::class ) - ) - || ! WC_Subscriptions_Product::is_subscription( $product ) - ) { - return; - } - - $module_url = $c->get( 'subscription.module.url' ); - wp_enqueue_script( - 'ppcp-paypal-subscription', - untrailingslashit( $module_url ) . '/assets/js/paypal-subscription.js', - array( 'jquery' ), - $c->get( 'ppcp.asset-version' ), - true - ); - - $products = array( $this->set_product_config( $product ) ); - if ( $product->get_type() === 'variable-subscription' ) { - $products = array(); - - /** - * Suppress pslam. - * - * @psalm-suppress TypeDoesNotContainType - * - * WC_Product_Variable_Subscription extends WC_Product_Variable. - */ - assert( $product instanceof WC_Product_Variable ); - $available_variations = $product->get_available_variations(); - foreach ( $available_variations as $variation ) { - /** - * The method is defined in WooCommerce. - * - * @psalm-suppress UndefinedMethod - */ - $variation = wc_get_product_object( 'variation', $variation['variation_id'] ); - $products[] = $this->set_product_config( $variation ); - } - } - - wp_localize_script( - 'ppcp-paypal-subscription', - 'PayPalCommerceGatewayPayPalSubscriptionProducts', - $products - ); - } - ); - - $endpoint = $c->get( 'subscription.deactivate-plan-endpoint' ); - assert( $endpoint instanceof DeactivatePlanEndpoint ); - add_action( - 'wc_ajax_' . DeactivatePlanEndpoint::ENDPOINT, - array( $endpoint, 'handle_request' ) - ); - - add_action( - 'add_meta_boxes', - /** - * Param types removed to avoid third-party issues. - * - * @psalm-suppress MissingClosureParamType - */ - function( string $post_type, $post_or_order_object ) use ( $c ) { - if ( ! function_exists( 'wcs_get_subscription' ) ) { - return; - } - - $order = ( $post_or_order_object instanceof WP_Post ) - ? wc_get_order( $post_or_order_object->ID ) - : $post_or_order_object; - - if ( ! is_a( $order, WC_Order::class ) ) { - return; - } - - $subscription = wcs_get_subscription( $order->get_id() ); - if ( ! is_a( $subscription, WC_Subscription::class ) ) { - return; - } - - $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; - if ( ! $subscription_id ) { - return; - } - - $screen_id = wc_get_page_screen_id( 'shop_subscription' ); - remove_meta_box( 'woocommerce-subscription-schedule', $screen_id, 'side' ); - - $environment = $c->get( 'onboarding.environment' ); - add_meta_box( - 'ppcp_paypal_subscription', - __( 'PayPal Subscription', 'woocommerce-paypal-payments' ), - function() use ( $subscription_id, $environment ) { - $host = $environment->current_environment_is( Environment::SANDBOX ) ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com'; - $url = trailingslashit( $host ) . 'billing/subscriptions/' . $subscription_id; - echo '

' . esc_html__( 'This subscription is linked to a PayPal Subscription, Cancel it to unlink.', 'woocommerce-paypal-payments' ) . '

'; - echo '

' . esc_html__( 'Subscription:', 'woocommerce-paypal-payments' ) . ' ' . esc_attr( $subscription_id ) . '

'; - }, - $post_type, - 'side' - ); - - }, - 30, - 2 - ); - - add_action( - 'action_scheduler_before_execute', - /** - * Param types removed to avoid third-party issues. - * - * @psalm-suppress MissingClosureParamType - */ - function( $action_id ) { - /** - * Class exist in WooCommerce. - * - * @psalm-suppress UndefinedClass - */ - $store = ActionScheduler_Store::instance(); - $action = $store->fetch_action( $action_id ); - - $subscription_id = $action->get_args()['subscription_id'] ?? null; - if ( $subscription_id ) { - $subscription = wcs_get_subscription( $subscription_id ); - if ( is_a( $subscription, WC_Subscription::class ) ) { - $paypal_subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; - if ( $paypal_subscription_id ) { - as_unschedule_action( $action->get_hook(), $action->get_args() ); - } - } - } - } - ); - } - - /** - * Returns the key for the module. - * - * @return string|void - */ - public function getKey() { - } - - /** - * Handles a Subscription product renewal. - * - * @param \WC_Order $order WooCommerce order. - * @param ContainerInterface|null $container The container. - * @return void - */ - protected function renew( $order, $container ) { - if ( ! ( $order instanceof \WC_Order ) ) { - return; - } - - $handler = $container->get( 'subscription.renewal-handler' ); - $handler->renew( $order ); - } - - /** - * Adds Payment token ID to subscription. - * - * @param \WC_Subscription $subscription The subscription. - * @param PaymentTokenRepository $payment_token_repository The payment repository. - * @param LoggerInterface $logger The logger. - */ - protected function add_payment_token_id( - \WC_Subscription $subscription, - PaymentTokenRepository $payment_token_repository, - LoggerInterface $logger - ) { - try { - $tokens = $payment_token_repository->all_for_user_id( $subscription->get_customer_id() ); - if ( $tokens ) { - $latest_token_id = end( $tokens )->id() ? end( $tokens )->id() : ''; - $subscription->update_meta_data( 'payment_token_id', $latest_token_id ); - $subscription->save(); - } - } catch ( RuntimeException $error ) { - $message = sprintf( - // translators: %1$s is the payment token Id, %2$s is the error message. - __( - 'Could not add token Id to subscription %1$s: %2$s', - 'woocommerce-paypal-payments' - ), - $subscription->get_id(), - $error->getMessage() - ); - - $logger->log( 'warning', $message ); - } - } - - /** - * Displays saved PayPal payments. - * - * @param Settings $settings The settings. - * @param string $id The payment gateway Id. - * @param PaymentTokenRepository $payment_token_repository The payment token repository. - * @param string $description The payment gateway description. - * @param SubscriptionHelper $subscription_helper The subscription helper. - * @return string - */ - protected function display_saved_paypal_payments( - Settings $settings, - string $id, - PaymentTokenRepository $payment_token_repository, - string $description, - SubscriptionHelper $subscription_helper - ): string { - if ( $settings->has( 'vault_enabled' ) - && $settings->get( 'vault_enabled' ) - && PayPalGateway::ID === $id - && $subscription_helper->is_subscription_change_payment() - ) { - $tokens = $payment_token_repository->all_for_user_id( get_current_user_id() ); - if ( ! $tokens || ! $payment_token_repository->tokens_contains_paypal( $tokens ) ) { - return esc_html__( - 'No PayPal payments saved, in order to use a saved payment you first need to create it through a purchase.', - 'woocommerce-paypal-payments' - ); - } - - $output = sprintf( - '

'; - - return $output; - } - - return $description; - } - - /** - * Displays saved credit cards. - * - * @param Settings $settings The settings. - * @param string $id The payment gateway Id. - * @param PaymentTokenRepository $payment_token_repository The payment token repository. - * @param array $default_fields Default payment gateway fields. - * @param SubscriptionHelper $subscription_helper The subscription helper. - * @return array|mixed|string - * @throws NotFoundException When setting was not found. - */ - protected function display_saved_credit_cards( - Settings $settings, - string $id, - PaymentTokenRepository $payment_token_repository, - array $default_fields, - SubscriptionHelper $subscription_helper - ) { - - if ( $settings->has( 'vault_enabled_dcc' ) - && $settings->get( 'vault_enabled_dcc' ) - && $subscription_helper->is_subscription_change_payment() - && CreditCardGateway::ID === $id - ) { - $tokens = $payment_token_repository->all_for_user_id( get_current_user_id() ); - if ( ! $tokens || ! $payment_token_repository->tokens_contains_card( $tokens ) ) { - $default_fields = array(); - $default_fields['saved-credit-card'] = esc_html__( - 'No Credit Card saved, in order to use a saved Credit Card you first need to create it through a purchase.', - 'woocommerce-paypal-payments' - ); - return $default_fields; - } - - $output = sprintf( - '

'; - - $default_fields = array(); - $default_fields['saved-credit-card'] = $output; - return $default_fields; - } - - return $default_fields; - } - - /** - * Adds PayPal subscriptions API integration. - * - * @param ContainerInterface $c The container. - * @return void - * @throws Exception When something went wrong. - */ - protected function subscriptions_api_integration( ContainerInterface $c ): void { add_action( 'save_post', /** @@ -554,7 +80,7 @@ class SubscriptionModule implements ModuleInterface { return; } - $subscriptions_api_handler = $c->get( 'subscription.api-handler' ); + $subscriptions_api_handler = $c->get( 'paypal-subscriptions.api-handler' ); assert( $subscriptions_api_handler instanceof SubscriptionsApiHandler ); $this->update_subscription_product_meta( $product, $subscriptions_api_handler ); }, @@ -571,7 +97,7 @@ class SubscriptionModule implements ModuleInterface { function( $variation_id ) use ( $c ) { $wcsnonce_save_variations = wc_clean( wp_unslash( $_POST['_wcsnonce_save_variations'] ?? '' ) ); - $subscriptions_helper = $c->get( 'subscription.helper' ); + $subscriptions_helper = $c->get( 'wc-subscriptions.helper' ); assert( $subscriptions_helper instanceof SubscriptionHelper ); if ( @@ -588,7 +114,7 @@ class SubscriptionModule implements ModuleInterface { return; } - $subscriptions_api_handler = $c->get( 'subscription.api-handler' ); + $subscriptions_api_handler = $c->get( 'paypal-subscriptions.api-handler' ); assert( $subscriptions_api_handler instanceof SubscriptionsApiHandler ); $this->update_subscription_product_meta( $product, $subscriptions_api_handler ); }, @@ -670,7 +196,7 @@ class SubscriptionModule implements ModuleInterface { * * @psalm-suppress MissingClosureParamType */ - function( $actions, $subscription ): array { + function( $actions, $subscription = null ): array { if ( ! is_array( $actions ) || ! is_a( $subscription, WC_Subscription::class ) ) { return $actions; } @@ -947,6 +473,236 @@ class SubscriptionModule implements ModuleInterface { 10, 3 ); + + add_action( + 'admin_enqueue_scripts', + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ + function( $hook ) use ( $c ) { + if ( ! is_string( $hook ) ) { + return; + } + $settings = $c->get( 'wcgateway.settings' ); + $subscription_mode = $settings->has( 'subscriptions_mode' ) ? $settings->get( 'subscriptions_mode' ) : ''; + if ( $hook !== 'post.php' || $subscription_mode !== 'subscriptions_api' ) { + return; + } + + //phpcs:disable WordPress.Security.NonceVerification.Recommended + $post_id = wc_clean( wp_unslash( $_GET['post'] ?? '' ) ); + $product = wc_get_product( $post_id ); + if ( ! ( is_a( $product, WC_Product::class ) ) ) { + return; + } + + $subscriptions_helper = $c->get( 'wc-subscriptions.helper' ); + assert( $subscriptions_helper instanceof SubscriptionHelper ); + + if ( + ! $subscriptions_helper->plugin_is_active() + || ! ( + is_a( $product, WC_Product_Subscription::class ) + || is_a( $product, WC_Product_Variable_Subscription::class ) + || is_a( $product, WC_Product_Subscription_Variation::class ) + ) + || ! WC_Subscriptions_Product::is_subscription( $product ) + ) { + return; + } + + $module_url = $c->get( 'paypal-subscriptions.module.url' ); + wp_enqueue_script( + 'ppcp-paypal-subscription', + untrailingslashit( $module_url ) . '/assets/js/paypal-subscription.js', + array( 'jquery' ), + $c->get( 'ppcp.asset-version' ), + true + ); + + $products = array( $this->set_product_config( $product ) ); + if ( $product->get_type() === 'variable-subscription' ) { + $products = array(); + + /** + * Suppress pslam. + * + * @psalm-suppress TypeDoesNotContainType + * + * WC_Product_Variable_Subscription extends WC_Product_Variable. + */ + assert( $product instanceof WC_Product_Variable ); + $available_variations = $product->get_available_variations(); + foreach ( $available_variations as $variation ) { + /** + * The method is defined in WooCommerce. + * + * @psalm-suppress UndefinedMethod + */ + $variation = wc_get_product_object( 'variation', $variation['variation_id'] ); + $products[] = $this->set_product_config( $variation ); + } + } + + wp_localize_script( + 'ppcp-paypal-subscription', + 'PayPalCommerceGatewayPayPalSubscriptionProducts', + $products + ); + } + ); + + $endpoint = $c->get( 'paypal-subscriptions.deactivate-plan-endpoint' ); + assert( $endpoint instanceof DeactivatePlanEndpoint ); + add_action( + 'wc_ajax_' . DeactivatePlanEndpoint::ENDPOINT, + array( $endpoint, 'handle_request' ) + ); + + add_action( + 'add_meta_boxes', + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ + function( string $post_type, $post_or_order_object ) use ( $c ) { + if ( ! function_exists( 'wcs_get_subscription' ) ) { + return; + } + + $order = ( $post_or_order_object instanceof WP_Post ) + ? wc_get_order( $post_or_order_object->ID ) + : $post_or_order_object; + + if ( ! is_a( $order, WC_Order::class ) ) { + return; + } + + $subscription = wcs_get_subscription( $order->get_id() ); + if ( ! is_a( $subscription, WC_Subscription::class ) ) { + return; + } + + $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; + if ( ! $subscription_id ) { + return; + } + + $screen_id = wc_get_page_screen_id( 'shop_subscription' ); + remove_meta_box( 'woocommerce-subscription-schedule', $screen_id, 'side' ); + + $host = $c->get( 'api.paypal-website-url' ); + + add_meta_box( + 'ppcp_paypal_subscription', + __( 'PayPal Subscription', 'woocommerce-paypal-payments' ), + function() use ( $subscription_id, $host ) { + $url = trailingslashit( $host ) . 'billing/subscriptions/' . $subscription_id; + echo '

' . esc_html__( 'This subscription is linked to a PayPal Subscription, Cancel it to unlink.', 'woocommerce-paypal-payments' ) . '

'; + echo '

' . esc_html__( 'Subscription:', 'woocommerce-paypal-payments' ) . ' ' . esc_attr( $subscription_id ) . '

'; + }, + $post_type, + 'side' + ); + + }, + 30, + 2 + ); + + add_action( + 'action_scheduler_before_execute', + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ + function( $action_id ) { + /** + * Class exist in WooCommerce. + * + * @psalm-suppress UndefinedClass + */ + $store = ActionScheduler_Store::instance(); + $action = $store->fetch_action( $action_id ); + + $subscription_id = $action->get_args()['subscription_id'] ?? null; + if ( $subscription_id ) { + $subscription = wcs_get_subscription( $subscription_id ); + if ( is_a( $subscription, WC_Subscription::class ) ) { + $paypal_subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; + if ( $paypal_subscription_id ) { + as_unschedule_action( $action->get_hook(), $action->get_args() ); + } + } + } + } + ); + } + + /** + * Updates subscription product meta. + * + * @param WC_Product $product The product. + * @param SubscriptionsApiHandler $subscriptions_api_handler The subscription api handler. + * @return void + */ + private function update_subscription_product_meta( WC_Product $product, SubscriptionsApiHandler $subscriptions_api_handler ): void { + // phpcs:ignore WordPress.Security.NonceVerification + $enable_subscription_product = wc_clean( wp_unslash( $_POST['_ppcp_enable_subscription_product'] ?? '' ) ); + $product->update_meta_data( '_ppcp_enable_subscription_product', $enable_subscription_product ); + $product->save(); + + if ( ( $product->get_type() === 'subscription' || $product->get_type() === 'subscription_variation' ) && $enable_subscription_product === 'yes' ) { + if ( $product->meta_exists( 'ppcp_subscription_product' ) && $product->meta_exists( 'ppcp_subscription_plan' ) ) { + $subscriptions_api_handler->update_product( $product ); + $subscriptions_api_handler->update_plan( $product ); + return; + } + + if ( ! $product->meta_exists( 'ppcp_subscription_product' ) ) { + $subscriptions_api_handler->create_product( $product ); + } + + if ( $product->meta_exists( 'ppcp_subscription_product' ) && ! $product->meta_exists( 'ppcp_subscription_plan' ) ) { + // phpcs:ignore WordPress.Security.NonceVerification + $subscription_plan_name = wc_clean( wp_unslash( $_POST['_ppcp_subscription_plan_name'] ?? '' ) ); + if ( ! is_string( $subscription_plan_name ) ) { + return; + } + + $product->update_meta_data( '_ppcp_subscription_plan_name', $subscription_plan_name ); + $product->save(); + + $subscriptions_api_handler->create_plan( $subscription_plan_name, $product ); + } + } + } + + /** + * Returns subscription product configuration. + * + * @param WC_Product $product The product. + * @return array + */ + private function set_product_config( WC_Product $product ): array { + $plan = $product->get_meta( 'ppcp_subscription_plan' ) ?? array(); + $plan_id = $plan['id'] ?? ''; + + return array( + 'product_connected' => $product->get_meta( '_ppcp_enable_subscription_product' ) ?? '', + 'plan_id' => $plan_id, + 'product_id' => $product->get_id(), + 'ajax' => array( + 'deactivate_plan' => array( + 'endpoint' => \WC_AJAX::get_endpoint( DeactivatePlanEndpoint::ENDPOINT ), + 'nonce' => wp_create_nonce( DeactivatePlanEndpoint::ENDPOINT ), + ), + ), + ); } /** @@ -1019,66 +775,4 @@ class SubscriptionModule implements ModuleInterface { ); } } - - /** - * Updates subscription product meta. - * - * @param WC_Product $product The product. - * @param SubscriptionsApiHandler $subscriptions_api_handler The subscription api handler. - * @return void - */ - private function update_subscription_product_meta( WC_Product $product, SubscriptionsApiHandler $subscriptions_api_handler ): void { - // phpcs:ignore WordPress.Security.NonceVerification - $enable_subscription_product = wc_clean( wp_unslash( $_POST['_ppcp_enable_subscription_product'] ?? '' ) ); - $product->update_meta_data( '_ppcp_enable_subscription_product', $enable_subscription_product ); - $product->save(); - - if ( ( $product->get_type() === 'subscription' || $product->get_type() === 'subscription_variation' ) && $enable_subscription_product === 'yes' ) { - if ( $product->meta_exists( 'ppcp_subscription_product' ) && $product->meta_exists( 'ppcp_subscription_plan' ) ) { - $subscriptions_api_handler->update_product( $product ); - $subscriptions_api_handler->update_plan( $product ); - return; - } - - if ( ! $product->meta_exists( 'ppcp_subscription_product' ) ) { - $subscriptions_api_handler->create_product( $product ); - } - - if ( $product->meta_exists( 'ppcp_subscription_product' ) && ! $product->meta_exists( 'ppcp_subscription_plan' ) ) { - // phpcs:ignore WordPress.Security.NonceVerification - $subscription_plan_name = wc_clean( wp_unslash( $_POST['_ppcp_subscription_plan_name'] ?? '' ) ); - if ( ! is_string( $subscription_plan_name ) ) { - return; - } - - $product->update_meta_data( '_ppcp_subscription_plan_name', $subscription_plan_name ); - $product->save(); - - $subscriptions_api_handler->create_plan( $subscription_plan_name, $product ); - } - } - } - - /** - * Returns subscription product configuration. - * - * @param WC_Product $product The product. - * @return array - */ - private function set_product_config( WC_Product $product ): array { - $plan = $product->get_meta( 'ppcp_subscription_plan' ) ?? array(); - $plan_id = $plan['id'] ?? ''; - - return array( - 'product_connected' => $product->get_meta( '_ppcp_enable_subscription_product' ) ?? '', - 'plan_id' => $plan_id, - 'product_id' => $product->get_id(), - 'ajax' => array( - 'deactivate_plan' => array( - 'endpoint' => \WC_AJAX::get_endpoint( DeactivatePlanEndpoint::ENDPOINT ), - 'nonce' => wp_create_nonce( DeactivatePlanEndpoint::ENDPOINT ), - ), - ), - ); - } } diff --git a/modules/ppcp-subscription/src/SubscriptionsApiHandler.php b/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php similarity index 94% rename from modules/ppcp-subscription/src/SubscriptionsApiHandler.php rename to modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php index 2d8bb1d7b..2109f13d2 100644 --- a/modules/ppcp-subscription/src/SubscriptionsApiHandler.php +++ b/modules/ppcp-paypal-subscriptions/src/SubscriptionsApiHandler.php @@ -2,12 +2,12 @@ /** * The subscription module. * - * @package WooCommerce\PayPalCommerce\Subscription + * @package WooCommerce\PayPalCommerce\WcSubscriptions */ declare(strict_types=1); -namespace WooCommerce\PayPalCommerce\Subscription; +namespace WooCommerce\PayPalCommerce\PayPalSubscriptions; use Psr\Log\LoggerInterface; use WC_Product; @@ -114,7 +114,7 @@ class SubscriptionsApiHandler { */ public function create_product( WC_Product $product ) { try { - $subscription_product = $this->products_endpoint->create( $product->get_title(), $this->prepare_description( $product->get_description() ) ); + $subscription_product = $this->products_endpoint->create( $this->prepare_item_string( $product->get_title() ), $this->prepare_item_string( $product->get_description() ) ); $product->update_meta_data( 'ppcp_subscription_product', $subscription_product->to_array() ); $product->save(); } catch ( RuntimeException $exception ) { @@ -169,7 +169,7 @@ class SubscriptionsApiHandler { $catalog_product_name = $catalog_product->name() ?: ''; $catalog_product_description = $catalog_product->description() ?: ''; - $wc_product_description = $this->prepare_description( $product->get_description() ) ?: $product->get_title(); + $wc_product_description = $this->prepare_item_string( $product->get_description() ) ?: $this->prepare_item_string( $product->get_title() ); if ( $catalog_product_name !== $product->get_title() || $catalog_product_description !== $wc_product_description ) { $data = array(); diff --git a/modules/ppcp-subscription/webpack.config.js b/modules/ppcp-paypal-subscriptions/webpack.config.js similarity index 100% rename from modules/ppcp-subscription/webpack.config.js rename to modules/ppcp-paypal-subscriptions/webpack.config.js diff --git a/modules/ppcp-subscription/yarn.lock b/modules/ppcp-paypal-subscriptions/yarn.lock similarity index 100% rename from modules/ppcp-subscription/yarn.lock rename to modules/ppcp-paypal-subscriptions/yarn.lock diff --git a/modules/ppcp-save-payment-methods/.babelrc b/modules/ppcp-save-payment-methods/.babelrc new file mode 100644 index 000000000..822778e6c --- /dev/null +++ b/modules/ppcp-save-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-save-payment-methods/.gitignore b/modules/ppcp-save-payment-methods/.gitignore new file mode 100644 index 000000000..0bd2b9f58 --- /dev/null +++ b/modules/ppcp-save-payment-methods/.gitignore @@ -0,0 +1,3 @@ +node_modules +assets/js +assets/css diff --git a/modules/ppcp-save-payment-methods/composer.json b/modules/ppcp-save-payment-methods/composer.json new file mode 100644 index 000000000..50ff8c251 --- /dev/null +++ b/modules/ppcp-save-payment-methods/composer.json @@ -0,0 +1,17 @@ +{ + "name": "woocommerce/ppcp-save-payment-methods", + "type": "dhii-mod", + "description": "Save payment methods module for PPCP", + "license": "GPL-2.0", + "require": { + "php": "^7.2 | ^8.0", + "dhii/module-interface": "^0.3.0-alpha1" + }, + "autoload": { + "psr-4": { + "WooCommerce\\PayPalCommerce\\SavePaymentMethods\\": "src" + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/modules/ppcp-save-payment-methods/extensions.php b/modules/ppcp-save-payment-methods/extensions.php new file mode 100644 index 000000000..1758f8960 --- /dev/null +++ b/modules/ppcp-save-payment-methods/extensions.php @@ -0,0 +1,14 @@ + 0.5%", + "Safari >= 8", + "Chrome >= 41", + "Firefox >= 43", + "Edge >= 14" + ], + "dependencies": { + "core-js": "^3.25.0", + "@paypal/paypal-js": "^6.0.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-save-payment-methods/resources/js/add-payment-method.js b/modules/ppcp-save-payment-methods/resources/js/add-payment-method.js new file mode 100644 index 000000000..6178bd92c --- /dev/null +++ b/modules/ppcp-save-payment-methods/resources/js/add-payment-method.js @@ -0,0 +1,228 @@ +import { + getCurrentPaymentMethod, + ORDER_BUTTON_SELECTOR, + PaymentMethods +} from "../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState"; +import {loadScript} from "@paypal/paypal-js"; +import { + setVisible, + setVisibleByClass +} from "../../../ppcp-button/resources/js/modules/Helper/Hiding"; +import ErrorHandler from "../../../ppcp-button/resources/js/modules/ErrorHandler"; +import {cardFieldStyles} from "../../../ppcp-button/resources/js/modules/Helper/CardFieldsHelper"; + +const errorHandler = new ErrorHandler( + ppcp_add_payment_method.labels.error.generic, + document.querySelector('.woocommerce-notices-wrapper') +); + +const init = () => { + setVisibleByClass(ORDER_BUTTON_SELECTOR, getCurrentPaymentMethod() !== PaymentMethods.PAYPAL, 'ppcp-hidden'); + setVisible(`#ppc-button-${PaymentMethods.PAYPAL}-save-payment-method`, getCurrentPaymentMethod() === PaymentMethods.PAYPAL); +} + +document.addEventListener( + 'DOMContentLoaded', + () => { + jQuery(document.body).on('click init_add_payment_method', '.payment_methods input.input-radio', function () { + init() + }); + + if(ppcp_add_payment_method.is_subscription_change_payment_page) { + const saveToAccount = document.querySelector('#wc-ppcp-credit-card-gateway-new-payment-method'); + if(saveToAccount) { + saveToAccount.checked = true; + saveToAccount.disabled = true; + } + } + + setTimeout(() => { + loadScript({ + clientId: ppcp_add_payment_method.client_id, + merchantId: ppcp_add_payment_method.merchant_id, + dataUserIdToken: ppcp_add_payment_method.id_token, + components: 'buttons,card-fields', + }) + .then((paypal) => { + errorHandler.clear(); + + const paypalButtonContainer = document.querySelector(`#ppc-button-${PaymentMethods.PAYPAL}-save-payment-method`); + if(paypalButtonContainer) { + paypal.Buttons( + { + createVaultSetupToken: async () => { + const response = await fetch(ppcp_add_payment_method.ajax.create_setup_token.endpoint, { + method: "POST", + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + nonce: ppcp_add_payment_method.ajax.create_setup_token.nonce, + }) + }) + + const result = await response.json() + if (result.data.id) { + return result.data.id + } + + errorHandler.message(ppcp_add_payment_method.error_message); + }, + onApprove: async ({vaultSetupToken}) => { + const response = await fetch(ppcp_add_payment_method.ajax.create_payment_token.endpoint, { + method: "POST", + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + nonce: ppcp_add_payment_method.ajax.create_payment_token.nonce, + vault_setup_token: vaultSetupToken, + }) + }) + + const result = await response.json(); + if(result.success === true) { + window.location.href = ppcp_add_payment_method.payment_methods_page; + return; + } + + errorHandler.message(ppcp_add_payment_method.error_message); + }, + onError: (error) => { + console.error(error) + errorHandler.message(ppcp_add_payment_method.error_message); + } + }, + ).render(`#ppc-button-${PaymentMethods.PAYPAL}-save-payment-method`); + } + + const cardField = paypal.CardFields({ + createVaultSetupToken: async () => { + const response = await fetch(ppcp_add_payment_method.ajax.create_setup_token.endpoint, { + method: "POST", + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + nonce: ppcp_add_payment_method.ajax.create_setup_token.nonce, + payment_method: PaymentMethods.CARDS, + verification_method: ppcp_add_payment_method.verification_method + }) + }) + + const result = await response.json() + if (result.data.id) { + return result.data.id + } + + errorHandler.message(ppcp_add_payment_method.error_message); + }, + onApprove: async ({vaultSetupToken}) => { + const response = await fetch(ppcp_add_payment_method.ajax.create_payment_token.endpoint, { + method: "POST", + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + nonce: ppcp_add_payment_method.ajax.create_payment_token.nonce, + vault_setup_token: vaultSetupToken, + payment_method: PaymentMethods.CARDS + }) + }) + + const result = await response.json(); + if(result.success === true) { + if(ppcp_add_payment_method.is_subscription_change_payment_page) { + const subscriptionId = ppcp_add_payment_method.subscription_id_to_change_payment; + if(subscriptionId && result.data) { + const req = await fetch(ppcp_add_payment_method.ajax.subscription_change_payment_method.endpoint, { + method: "POST", + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + nonce: ppcp_add_payment_method.ajax.subscription_change_payment_method.nonce, + subscription_id: subscriptionId, + payment_method: getCurrentPaymentMethod(), + wc_payment_token_id: result.data + }) + }); + + const res = await req.json(); + if (res.success === true) { + window.location.href = `${ppcp_add_payment_method.view_subscriptions_page}/${subscriptionId}`; + return; + } + } + + return; + } + + window.location.href = ppcp_add_payment_method.payment_methods_page; + return; + } + + errorHandler.message(ppcp_add_payment_method.error_message); + }, + onError: (error) => { + console.error(error) + errorHandler.message(ppcp_add_payment_method.error_message); + } + }); + + if (cardField.isEligible()) { + const nameField = document.getElementById('ppcp-credit-card-gateway-card-name'); + if (nameField) { + let styles = cardFieldStyles(nameField); + cardField.NameField({style: {'input': styles}}).render(nameField.parentNode); + nameField.hidden = true; + } + + const numberField = document.getElementById('ppcp-credit-card-gateway-card-number'); + if (numberField) { + let styles = cardFieldStyles(numberField); + cardField.NumberField({style: {'input': styles}}).render(numberField.parentNode); + numberField.hidden = true; + } + + const expiryField = document.getElementById('ppcp-credit-card-gateway-card-expiry'); + if (expiryField) { + let styles = cardFieldStyles(expiryField); + cardField.ExpiryField({style: {'input': styles}}).render(expiryField.parentNode); + expiryField.hidden = true; + } + + const cvvField = document.getElementById('ppcp-credit-card-gateway-card-cvc'); + if (cvvField) { + let styles = cardFieldStyles(cvvField); + cardField.CVVField({style: {'input': styles}}).render(cvvField.parentNode); + cvvField.hidden = true; + } + } + + document.querySelector('#place_order')?.addEventListener("click", (event) => { + const cardPaymentToken = document.querySelector('input[name="wc-ppcp-credit-card-gateway-payment-token"]:checked')?.value; + if ( + getCurrentPaymentMethod() !== 'ppcp-credit-card-gateway' + || cardPaymentToken && cardPaymentToken !== 'new' + ) { + return; + } + + event.preventDefault(); + + cardField.submit() + .catch((error) => { + console.error(error) + }); + }); + }) + }, 1000) + } +); + diff --git a/modules/ppcp-save-payment-methods/services.php b/modules/ppcp-save-payment-methods/services.php new file mode 100644 index 000000000..a0b43f021 --- /dev/null +++ b/modules/ppcp-save-payment-methods/services.php @@ -0,0 +1,821 @@ + static function ( ContainerInterface $container ): bool { + $save_payment_methods_applies = $container->get( 'save-payment-methods.helpers.save-payment-methods-applies' ); + assert( $save_payment_methods_applies instanceof SavePaymentMethodsApplies ); + + return $save_payment_methods_applies->for_country_currency(); + }, + 'save-payment-methods.helpers.save-payment-methods-applies' => static function ( ContainerInterface $container ) : SavePaymentMethodsApplies { + return new SavePaymentMethodsApplies( + $container->get( 'save-payment-methods.supported-country-currency-matrix' ), + $container->get( 'api.shop.currency' ), + $container->get( 'api.shop.country' ) + ); + }, + 'save-payment-methods.supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array { + return apply_filters( + 'woocommerce_paypal_payments_save_payment_methods_supported_country_currency_matrix', + array( + 'AU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'AT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'BE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'BG' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CA' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CY' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'CZ' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'DK' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'EE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'FI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'FR' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'DE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'GR' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'HU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'IE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'IT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LV' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'LU' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'MT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'NO' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'NL' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'PL' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'PT' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'RO' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SK' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SI' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'ES' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'SE' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'GB' => array( + 'AUD', + 'BRL', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'ILS', + 'JPY', + 'MXN', + 'NOK', + 'NZD', + 'PHP', + 'PLN', + 'SEK', + 'SGD', + 'THB', + 'TWD', + 'USD', + ), + 'US' => array( + 'AUD', + 'CAD', + 'EUR', + 'GBP', + 'JPY', + 'USD', + ), + ) + ); + }, + 'save-payment-methods.module.url' => static function ( ContainerInterface $container ): string { + /** + * The path cannot be false. + * + * @psalm-suppress PossiblyFalseArgument + */ + return plugins_url( + '/modules/ppcp-save-payment-methods/', + dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php' + ); + }, + 'save-payment-methods.endpoint.create-setup-token' => static function ( ContainerInterface $container ): CreateSetupToken { + return new CreateSetupToken( + $container->get( 'button.request-data' ), + $container->get( 'api.endpoint.payment-method-tokens' ) + ); + }, + 'save-payment-methods.endpoint.create-payment-token' => static function ( ContainerInterface $container ): CreatePaymentToken { + return new CreatePaymentToken( + $container->get( 'button.request-data' ), + $container->get( 'api.endpoint.payment-method-tokens' ), + $container->get( 'vaulting.wc-payment-tokens' ) + ); + }, + 'save-payment-methods.endpoint.create-payment-token-for-guest' => static function ( ContainerInterface $container ): CreatePaymentTokenForGuest { + return new CreatePaymentTokenForGuest( + $container->get( 'button.request-data' ), + $container->get( 'api.endpoint.payment-method-tokens' ) + ); + }, +); diff --git a/modules/ppcp-save-payment-methods/src/Endpoint/CreatePaymentToken.php b/modules/ppcp-save-payment-methods/src/Endpoint/CreatePaymentToken.php new file mode 100644 index 000000000..4fea1f188 --- /dev/null +++ b/modules/ppcp-save-payment-methods/src/Endpoint/CreatePaymentToken.php @@ -0,0 +1,128 @@ +request_data = $request_data; + $this->payment_method_tokens_endpoint = $payment_method_tokens_endpoint; + $this->wc_payment_tokens = $wc_payment_tokens; + } + + /** + * Returns the nonce. + * + * @return string + */ + public static function nonce(): string { + return self::ENDPOINT; + } + + /** + * Handles the request. + * + * @return bool + * @throws Exception On Error. + */ + public function handle_request(): bool { + try { + $data = $this->request_data->read_request( $this->nonce() ); + $wc_token_id = 0; + + /** + * Suppress ArgumentTypeCoercion + * + * @psalm-suppress ArgumentTypeCoercion + */ + $payment_source = new PaymentSource( + 'token', + (object) array( + 'id' => $data['vault_setup_token'], + 'type' => 'SETUP_TOKEN', + ) + ); + + $result = $this->payment_method_tokens_endpoint->create_payment_token( $payment_source ); + + if ( is_user_logged_in() && isset( $result->customer->id ) ) { + $current_user_id = get_current_user_id(); + update_user_meta( $current_user_id, '_ppcp_target_customer_id', $result->customer->id ); + + if ( isset( $result->payment_source->paypal ) ) { + $email = ''; + if ( isset( $result->payment_source->paypal->email_address ) ) { + $email = $result->payment_source->paypal->email_address; + } + + $wc_token_id = $this->wc_payment_tokens->create_payment_token_paypal( + $current_user_id, + $result->id, + $email + ); + } + + if ( isset( $result->payment_source->card ) ) { + $wc_token_id = $this->wc_payment_tokens->create_payment_token_card( $current_user_id, $result ); + } + } + + wp_send_json_success( $wc_token_id ); + return true; + } catch ( Exception $exception ) { + wp_send_json_error(); + return false; + } + } +} diff --git a/modules/ppcp-save-payment-methods/src/Endpoint/CreatePaymentTokenForGuest.php b/modules/ppcp-save-payment-methods/src/Endpoint/CreatePaymentTokenForGuest.php new file mode 100644 index 000000000..e458c96be --- /dev/null +++ b/modules/ppcp-save-payment-methods/src/Endpoint/CreatePaymentTokenForGuest.php @@ -0,0 +1,90 @@ +request_data = $request_data; + $this->payment_method_tokens_endpoint = $payment_method_tokens_endpoint; + } + + /** + * Returns the nonce. + * + * @return string + */ + public static function nonce(): string { + return self::ENDPOINT; + } + + /** + * Handles the request. + * + * @return bool + * @throws Exception On Error. + */ + public function handle_request(): bool { + $data = $this->request_data->read_request( $this->nonce() ); + + /** + * Suppress ArgumentTypeCoercion + * + * @psalm-suppress ArgumentTypeCoercion + */ + $payment_source = new PaymentSource( + 'token', + (object) array( + 'id' => $data['vault_setup_token'], + 'type' => 'SETUP_TOKEN', + ) + ); + + $result = $this->payment_method_tokens_endpoint->create_payment_token( $payment_source ); + WC()->session->set( 'ppcp_guest_payment_for_free_trial', $result ); + + wp_send_json_success(); + return true; + } +} diff --git a/modules/ppcp-save-payment-methods/src/Endpoint/CreateSetupToken.php b/modules/ppcp-save-payment-methods/src/Endpoint/CreateSetupToken.php new file mode 100644 index 000000000..7eb3a5ace --- /dev/null +++ b/modules/ppcp-save-payment-methods/src/Endpoint/CreateSetupToken.php @@ -0,0 +1,115 @@ +request_data = $request_data; + $this->payment_method_tokens_endpoint = $payment_method_tokens_endpoint; + } + + /** + * Returns the nonce. + * + * @return string + */ + public static function nonce(): string { + return self::ENDPOINT; + } + + /** + * Handles the request. + * + * @return bool + * @throws Exception On Error. + */ + public function handle_request(): bool { + try { + $data = $this->request_data->read_request( $this->nonce() ); + + $payment_source = new PaymentSource( + 'paypal', + (object) array( + 'usage_type' => 'MERCHANT', + 'experience_context' => (object) array( + 'return_url' => esc_url( wc_get_account_endpoint_url( 'payment-methods' ) ), + 'cancel_url' => esc_url( wc_get_account_endpoint_url( 'add-payment-method' ) ), + ), + ) + ); + + $payment_method = $data['payment_method'] ?? ''; + if ( $payment_method === CreditCardGateway::ID ) { + $properties = (object) array(); + + $verification_method = $data['verification_method'] ?? ''; + if ( $verification_method === 'SCA_WHEN_REQUIRED' || $verification_method === 'SCA_ALWAYS' ) { + $properties = (object) array( + 'verification_method' => $verification_method, + 'usage_type' => 'MERCHANT', + 'experience_context' => (object) array( + 'return_url' => esc_url( wc_get_account_endpoint_url( 'payment-methods' ) ), + 'cancel_url' => esc_url( wc_get_account_endpoint_url( 'add-payment-method' ) ), + ), + ); + } + + $payment_source = new PaymentSource( + 'card', + $properties + ); + } + + $result = $this->payment_method_tokens_endpoint->setup_tokens( $payment_source ); + + wp_send_json_success( $result ); + return true; + } catch ( Exception $exception ) { + wp_send_json_error(); + return false; + } + } +} diff --git a/modules/ppcp-save-payment-methods/src/Helper/SavePaymentMethodsApplies.php b/modules/ppcp-save-payment-methods/src/Helper/SavePaymentMethodsApplies.php new file mode 100644 index 000000000..bef3e6989 --- /dev/null +++ b/modules/ppcp-save-payment-methods/src/Helper/SavePaymentMethodsApplies.php @@ -0,0 +1,66 @@ +allowed_country_currency_matrix = $allowed_country_currency_matrix; + $this->currency = $currency; + $this->country = $country; + } + + /** + * Returns whether Save Payment Methods can be used in the current country and the current currency used. + * + * @return bool + */ + public function for_country_currency(): bool { + if ( ! in_array( $this->country, array_keys( $this->allowed_country_currency_matrix ), true ) ) { + return false; + } + return in_array( $this->currency, $this->allowed_country_currency_matrix[ $this->country ], true ); + } +} diff --git a/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php b/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php new file mode 100644 index 000000000..b667fb10b --- /dev/null +++ b/modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php @@ -0,0 +1,469 @@ +get( 'save-payment-methods.eligible' ) ) { + return; + } + + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + + $billing_agreements_endpoint = $c->get( 'api.endpoint.billing-agreements' ); + assert( $billing_agreements_endpoint instanceof BillingAgreementsEndpoint ); + + add_action( + 'woocommerce_paypal_payments_gateway_migrate_on_update', + function() use ( $settings, $billing_agreements_endpoint ) { + $reference_transaction_enabled = $billing_agreements_endpoint->reference_transaction_enabled(); + if ( $reference_transaction_enabled !== true ) { + $settings->set( 'vault_enabled', false ); + $settings->persist(); + } + } + ); + + if ( + ( ! $settings->has( 'vault_enabled' ) || ! $settings->get( 'vault_enabled' ) ) + && ( ! $settings->has( 'vault_enabled_dcc' ) || ! $settings->get( 'vault_enabled_dcc' ) ) + ) { + return; + } + + add_filter( + 'woocommerce_paypal_payments_localized_script_data', + function( array $localized_script_data ) use ( $c ) { + $api = $c->get( 'api.user-id-token' ); + assert( $api instanceof UserIdToken ); + + $logger = $c->get( 'woocommerce.logger.woocommerce' ); + assert( $logger instanceof LoggerInterface ); + + return $this->add_id_token_to_script_data( $api, $logger, $localized_script_data ); + } + ); + + // Adds attributes needed to save payment method. + add_filter( + 'ppcp_create_order_request_body_data', + function( array $data, string $payment_method, array $request_data ) use ( $settings ): array { + if ( $payment_method === CreditCardGateway::ID ) { + if ( ! $settings->has( 'vault_enabled_dcc' ) || ! $settings->get( 'vault_enabled_dcc' ) ) { + return $data; + } + + $save_payment_method = $request_data['save_payment_method'] ?? false; + if ( $save_payment_method ) { + $data['payment_source'] = array( + 'card' => array( + 'attributes' => array( + 'vault' => array( + 'store_in_vault' => 'ON_SUCCESS', + ), + ), + ), + ); + + $target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true ); + if ( ! $target_customer_id ) { + $target_customer_id = get_user_meta( get_current_user_id(), 'ppcp_customer_id', true ); + } + + if ( $target_customer_id ) { + $data['payment_source']['card']['attributes']['customer'] = array( + 'id' => $target_customer_id, + ); + } + } + } + + if ( $payment_method === PayPalGateway::ID ) { + if ( ! $settings->has( 'vault_enabled' ) || ! $settings->get( 'vault_enabled' ) ) { + return $data; + } + + $funding_source = $request_data['funding_source'] ?? null; + + if ( $funding_source && $funding_source === 'venmo' ) { + $data['payment_source'] = array( + 'venmo' => array( + 'attributes' => array( + 'vault' => array( + 'store_in_vault' => 'ON_SUCCESS', + 'usage_type' => 'MERCHANT', + 'permit_multiple_payment_tokens' => apply_filters( 'woocommerce_paypal_payments_permit_multiple_payment_tokens', false ), + ), + ), + ), + ); + } elseif ( $funding_source && $funding_source === 'apple_pay' ) { + $data['payment_source'] = array( + 'apple_pay' => array( + 'stored_credential' => array( + 'payment_initiator' => 'CUSTOMER', + 'payment_type' => 'RECURRING', + ), + 'attributes' => array( + 'vault' => array( + 'store_in_vault' => 'ON_SUCCESS', + ), + ), + ), + ); + } else { + $data['payment_source'] = array( + 'paypal' => array( + 'attributes' => array( + 'vault' => array( + 'store_in_vault' => 'ON_SUCCESS', + 'usage_type' => 'MERCHANT', + 'permit_multiple_payment_tokens' => apply_filters( 'woocommerce_paypal_payments_permit_multiple_payment_tokens', false ), + ), + ), + ), + ); + } + } + + return $data; + }, + 10, + 3 + ); + + add_action( + 'woocommerce_paypal_payments_after_order_processor', + function( WC_Order $wc_order, Order $order ) use ( $c ) { + $payment_source = $order->payment_source(); + assert( $payment_source instanceof PaymentSource ); + + $payment_vault_attributes = $payment_source->properties()->attributes->vault ?? null; + if ( $payment_vault_attributes ) { + $customer_id = $payment_vault_attributes->customer->id ?? ''; + $token_id = $payment_vault_attributes->id ?? ''; + if ( ! $customer_id || ! $token_id ) { + return; + } + + update_user_meta( $wc_order->get_customer_id(), '_ppcp_target_customer_id', $customer_id ); + + $wc_payment_tokens = $c->get( 'vaulting.wc-payment-tokens' ); + assert( $wc_payment_tokens instanceof WooCommercePaymentTokens ); + + if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) { + $token = new \WC_Payment_Token_CC(); + $token->set_token( $token_id ); + $token->set_user_id( $wc_order->get_customer_id() ); + $token->set_gateway_id( CreditCardGateway::ID ); + + $token->set_last4( $payment_source->properties()->last_digits ?? '' ); + $expiry = explode( '-', $payment_source->properties()->expiry ?? '' ); + $token->set_expiry_year( $expiry[0] ?? '' ); + $token->set_expiry_month( $expiry[1] ?? '' ); + $token->set_card_type( $payment_source->properties()->brand ?? '' ); + + $token->save(); + } + + if ( $wc_order->get_payment_method() === PayPalGateway::ID ) { + switch ( $payment_source->name() ) { + case 'venmo': + $wc_payment_tokens->create_payment_token_venmo( + $wc_order->get_customer_id(), + $token_id, + $payment_source->properties()->email_address ?? '' + ); + break; + case 'apple_pay': + $wc_payment_tokens->create_payment_token_applepay( + $wc_order->get_customer_id(), + $token_id + ); + break; + case 'paypal': + default: + $wc_payment_tokens->create_payment_token_paypal( + $wc_order->get_customer_id(), + $token_id, + $payment_source->properties()->email_address ?? '' + ); + break; + } + } + } + }, + 10, + 2 + ); + + add_filter( 'woocommerce_paypal_payments_disable_add_payment_method', '__return_false' ); + add_filter( 'woocommerce_paypal_payments_should_render_card_custom_fields', '__return_false' ); + + add_action( + 'wp_enqueue_scripts', + function() use ( $c ) { + if ( ! is_user_logged_in() || ! ( $this->is_add_payment_method_page() || $this->is_subscription_change_payment_method_page() ) ) { + return; + } + + $module_url = $c->get( 'save-payment-methods.module.url' ); + wp_enqueue_script( + 'ppcp-add-payment-method', + untrailingslashit( $module_url ) . '/assets/js/add-payment-method.js', + array( 'jquery' ), + $c->get( 'ppcp.asset-version' ), + true + ); + + $api = $c->get( 'api.user-id-token' ); + assert( $api instanceof UserIdToken ); + + try { + $target_customer_id = ''; + if ( is_user_logged_in() ) { + $target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true ); + if ( ! $target_customer_id ) { + $target_customer_id = get_user_meta( get_current_user_id(), 'ppcp_customer_id', true ); + } + } + + $id_token = $api->id_token( $target_customer_id ); + + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + + $verification_method = + $settings->has( '3d_secure_contingency' ) + ? apply_filters( 'woocommerce_paypal_payments_three_d_secure_contingency', $settings->get( '3d_secure_contingency' ) ) + : ''; + + $change_payment_method = wc_clean( wp_unslash( $_GET['change_payment_method'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification + + wp_localize_script( + 'ppcp-add-payment-method', + 'ppcp_add_payment_method', + array( + 'client_id' => $c->get( 'button.client_id' ), + 'merchant_id' => $c->get( 'api.merchant_id' ), + 'id_token' => $id_token, + 'payment_methods_page' => wc_get_account_endpoint_url( 'payment-methods' ), + 'view_subscriptions_page' => wc_get_account_endpoint_url( 'view-subscription' ), + 'is_subscription_change_payment_page' => $this->is_subscription_change_payment_method_page(), + 'subscription_id_to_change_payment' => $this->is_subscription_change_payment_method_page() ? (int) $change_payment_method : 0, + 'error_message' => __( 'Could not save payment method.', 'woocommerce-paypal-payments' ), + 'verification_method' => $verification_method, + 'ajax' => array( + 'create_setup_token' => array( + 'endpoint' => \WC_AJAX::get_endpoint( CreateSetupToken::ENDPOINT ), + 'nonce' => wp_create_nonce( CreateSetupToken::nonce() ), + ), + 'create_payment_token' => array( + 'endpoint' => \WC_AJAX::get_endpoint( CreatePaymentToken::ENDPOINT ), + 'nonce' => wp_create_nonce( CreatePaymentToken::nonce() ), + ), + 'subscription_change_payment_method' => array( + 'endpoint' => \WC_AJAX::get_endpoint( SubscriptionChangePaymentMethod::ENDPOINT ), + 'nonce' => wp_create_nonce( SubscriptionChangePaymentMethod::nonce() ), + ), + ), + 'labels' => array( + 'error' => array( + 'generic' => __( + 'Something went wrong. Please try again or choose another payment source.', + 'woocommerce-paypal-payments' + ), + ), + ), + ) + ); + } catch ( RuntimeException $exception ) { + $logger = $c->get( 'woocommerce.logger.woocommerce' ); + assert( $logger instanceof LoggerInterface ); + + $error = $exception->getMessage(); + if ( is_a( $exception, PayPalApiException::class ) ) { + $error = $exception->get_details( $error ); + } + + $logger->error( $error ); + } + } + ); + + add_action( + 'woocommerce_add_payment_method_form_bottom', + function () { + if ( ! is_user_logged_in() || ! is_add_payment_method_page() ) { + return; + } + + echo '
'; + } + ); + + add_action( + 'wc_ajax_' . CreateSetupToken::ENDPOINT, + static function () use ( $c ) { + $endpoint = $c->get( 'save-payment-methods.endpoint.create-setup-token' ); + assert( $endpoint instanceof CreateSetupToken ); + + $endpoint->handle_request(); + } + ); + + add_action( + 'wc_ajax_' . CreatePaymentToken::ENDPOINT, + static function () use ( $c ) { + $endpoint = $c->get( 'save-payment-methods.endpoint.create-payment-token' ); + assert( $endpoint instanceof CreatePaymentToken ); + + $endpoint->handle_request(); + } + ); + + add_action( + 'wc_ajax_' . CreatePaymentTokenForGuest::ENDPOINT, + static function () use ( $c ) { + $endpoint = $c->get( 'save-payment-methods.endpoint.create-payment-token-for-guest' ); + assert( $endpoint instanceof CreatePaymentTokenForGuest ); + + $endpoint->handle_request(); + } + ); + + add_action( + 'woocommerce_paypal_payments_before_delete_payment_token', + function( string $token_id ) use ( $c ) { + try { + $endpoint = $c->get( 'api.endpoint.payment-tokens' ); + assert( $endpoint instanceof PaymentTokensEndpoint ); + + $endpoint->delete( $token_id ); + } catch ( RuntimeException $exception ) { + $logger = $c->get( 'woocommerce.logger.woocommerce' ); + assert( $logger instanceof LoggerInterface ); + + $error = $exception->getMessage(); + if ( is_a( $exception, PayPalApiException::class ) ) { + $error = $exception->get_details( $error ); + } + + $logger->error( $error ); + } + } + ); + + add_filter( + 'woocommerce_paypal_payments_credit_card_gateway_vault_supports', + function( array $supports ) use ( $c ): array { + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof ContainerInterface ); + + if ( $settings->has( 'vault_enabled_dcc' ) && $settings->get( 'vault_enabled_dcc' ) ) { + $supports[] = 'tokenization'; + } + + return $supports; + } + ); + + add_filter( + 'woocommerce_paypal_payments_save_payment_methods_eligible', + function() { + return true; + } + ); + } + + /** + * Adds id token to localized script data. + * + * @param UserIdToken $api User id token api. + * @param LoggerInterface $logger The logger. + * @param array $localized_script_data The localized script data. + * @return array + */ + private function add_id_token_to_script_data( + UserIdToken $api, + LoggerInterface $logger, + array $localized_script_data + ): array { + try { + $target_customer_id = ''; + if ( is_user_logged_in() ) { + $target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true ); + if ( ! $target_customer_id ) { + $target_customer_id = get_user_meta( get_current_user_id(), 'ppcp_customer_id', true ); + } + } + + $id_token = $api->id_token( $target_customer_id ); + $localized_script_data['save_payment_methods'] = array( + 'id_token' => $id_token, + ); + + $localized_script_data['data_client_id']['set_attribute'] = false; + + } catch ( RuntimeException $exception ) { + $error = $exception->getMessage(); + if ( is_a( $exception, PayPalApiException::class ) ) { + $error = $exception->get_details( $error ); + } + + $logger->error( $error ); + } + + return $localized_script_data; + } +} diff --git a/modules/ppcp-save-payment-methods/webpack.config.js b/modules/ppcp-save-payment-methods/webpack.config.js new file mode 100644 index 000000000..16f380538 --- /dev/null +++ b/modules/ppcp-save-payment-methods/webpack.config.js @@ -0,0 +1,38 @@ +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: { + 'add-payment-method': path.resolve('./resources/js/add-payment-method.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-save-payment-methods/yarn.lock b/modules/ppcp-save-payment-methods/yarn.lock new file mode 100644 index 000000000..2171c2b89 --- /dev/null +++ b/modules/ppcp-save-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.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9", "@babel/compat-data@^7.23.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.2.tgz#6a12ced93455827037bfb5ed8492820d60fc32cc" + integrity sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ== + +"@babel/core@^7.19": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.2.tgz#ed10df0d580fff67c5f3ee70fd22e2e4c90a9f94" + integrity sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-module-transforms" "^7.23.0" + "@babel/helpers" "^7.23.2" + "@babel/parser" "^7.23.0" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.2" + "@babel/types" "^7.23.0" + 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.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" + integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== + dependencies: + "@babel/types" "^7.23.0" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" + integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.5", "@babel/helper-compilation-targets@^7.22.6": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" + integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-validator-option" "^7.22.15" + browserslist "^4.21.9" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.22.11", "@babel/helper-create-class-features-plugin@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz#97a61b385e57fe458496fad19f8e63b63c867de4" + integrity sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" + integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + regexpu-core "^5.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz#a71c10f7146d809f4a256c373f462d9bba8cf6ba" + integrity sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug== + 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-environment-visitor@^7.22.20", "@babel/helper-environment-visitor@^7.22.5": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-member-expression-to-functions@^7.22.15": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" + integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== + dependencies: + "@babel/types" "^7.23.0" + +"@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-transforms@^7.22.5", "@babel/helper-module-transforms@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz#3ec246457f6c842c0aee62a01f60739906f7047e" + integrity sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== + dependencies: + "@babel/types" "^7.22.5" + +"@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.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-remap-async-to-generator@^7.22.20", "@babel/helper-remap-async-to-generator@^7.22.5": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" + integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-wrap-function" "^7.22.20" + +"@babel/helper-replace-supers@^7.22.5", "@babel/helper-replace-supers@^7.22.9": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" + integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" + integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== + +"@babel/helper-wrap-function@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" + integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw== + dependencies: + "@babel/helper-function-name" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/types" "^7.22.19" + +"@babel/helpers@^7.23.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.2.tgz#2832549a6e37d484286e15ba36a5330483cac767" + integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ== + dependencies: + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.2" + "@babel/types" "^7.23.0" + +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.22.15", "@babel/parser@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.15": + version "7.22.15" + 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.22.15.tgz#02dc8a03f613ed5fdc29fb2f728397c78146c962" + integrity sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz#2aeb91d337d4e1a1e7ce85b76a37f5301781200f" + integrity sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-optional-chaining" "^7.22.15" + +"@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.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz#07d252e2aa0bc6125567f742cd58619cb14dce98" + integrity sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-attributes@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz#ab840248d834410b829f569f5262b9e517555ecb" + integrity sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@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.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918" + integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@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.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz#e5ba566d0c58a5b2ba2a8b795450641950b71958" + integrity sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-async-generator-functions@^7.23.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz#054afe290d64c6f576f371ccc321772c8ea87ebb" + integrity sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-transform-async-to-generator@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz#c7a85f44e46f8952f6d27fe57c2ed3cc084c3775" + integrity sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ== + dependencies: + "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.5" + +"@babel/plugin-transform-block-scoped-functions@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz#27978075bfaeb9fa586d3cb63a3d30c1de580024" + integrity sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-block-scoping@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz#8744d02c6c264d82e1a4bc5d2d501fd8aff6f022" + integrity sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-class-properties@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz#97a56e31ad8c9dc06a0b3710ce7803d5a48cca77" + integrity sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-class-static-block@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz#dc8cc6e498f55692ac6b4b89e56d87cec766c974" + integrity sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.11" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-transform-classes@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz#aaf4753aee262a232bbc95451b4bdf9599c65a0b" + integrity sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-split-export-declaration" "^7.22.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz#cd1e994bf9f316bd1c2dafcd02063ec261bb3869" + integrity sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/template" "^7.22.5" + +"@babel/plugin-transform-destructuring@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz#6447aa686be48b32eaf65a73e0e2c0bd010a266c" + integrity sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-dotall-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz#dbb4f0e45766eb544e193fb00e65a1dd3b2a4165" + integrity sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-duplicate-keys@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz#b6e6428d9416f5f0bba19c70d1e6e7e0b88ab285" + integrity sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-dynamic-import@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz#2c7722d2a5c01839eaf31518c6ff96d408e447aa" + integrity sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz#402432ad544a1f9a480da865fda26be653e48f6a" + integrity sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-export-namespace-from@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz#b3c84c8f19880b6c7440108f8929caf6056db26c" + integrity sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-transform-for-of@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz#f64b4ccc3a4f131a996388fae7680b472b306b29" + integrity sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-function-name@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz#935189af68b01898e0d6d99658db6b164205c143" + integrity sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg== + dependencies: + "@babel/helper-compilation-targets" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-json-strings@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz#689a34e1eed1928a40954e37f74509f48af67835" + integrity sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-transform-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz#e9341f4b5a167952576e23db8d435849b1dd7920" + integrity sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-logical-assignment-operators@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz#24c522a61688bde045b7d9bc3c2597a4d948fc9c" + integrity sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz#4fcc9050eded981a468347dd374539ed3e058def" + integrity sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-modules-amd@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz#05b2bc43373faa6d30ca89214731f76f966f3b88" + integrity sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw== + dependencies: + "@babel/helper-module-transforms" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-modules-commonjs@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz#b3dba4757133b2762c00f4f94590cf6d52602481" + integrity sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ== + dependencies: + "@babel/helper-module-transforms" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + +"@babel/plugin-transform-modules-systemjs@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz#77591e126f3ff4132a40595a6cccd00a6b60d160" + integrity sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg== + dependencies: + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-module-transforms" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/plugin-transform-modules-umd@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz#4694ae40a87b1745e3775b6a7fe96400315d4f98" + integrity sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ== + dependencies: + "@babel/helper-module-transforms" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" + integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-new-target@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz#1b248acea54ce44ea06dfd37247ba089fcf9758d" + integrity sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz#debef6c8ba795f5ac67cd861a81b744c5d38d9fc" + integrity sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz#498d77dc45a6c6db74bb829c02a01c1d719cbfbd" + integrity sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz#21a95db166be59b91cde48775310c0df6e1da56f" + integrity sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.22.15" + +"@babel/plugin-transform-object-super@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz#794a8d2fcb5d0835af722173c1a9d704f44e218c" + integrity sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.5" + +"@babel/plugin-transform-optional-catch-binding@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz#461cc4f578a127bb055527b3e77404cad38c08e0" + integrity sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.22.15", "@babel/plugin-transform-optional-chaining@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz#73ff5fc1cf98f542f09f29c0631647d8ad0be158" + integrity sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz#719ca82a01d177af358df64a514d64c2e3edb114" + integrity sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-private-methods@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz#21c8af791f76674420a147ae62e9935d790f8722" + integrity sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-private-property-in-object@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz#ad45c4fc440e9cb84c718ed0906d96cf40f9a4e1" + integrity sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.11" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz#b5ddabd73a4f7f26cd0e20f5db48290b88732766" + integrity sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-react-display-name@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz#3c4326f9fce31c7968d6cb9debcaf32d9e279a2b" + integrity sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-react-jsx-development@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz#e716b6edbef972a92165cd69d92f1255f7e73e87" + integrity sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.22.5" + +"@babel/plugin-transform-react-jsx@^7.22.15", "@babel/plugin-transform-react-jsx@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz#7e6266d88705d7c49f11c98db8b9464531289cd6" + integrity sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-jsx" "^7.22.5" + "@babel/types" "^7.22.15" + +"@babel/plugin-transform-react-pure-annotations@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz#1f58363eef6626d6fa517b95ac66fe94685e32c0" + integrity sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-regenerator@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz#8ceef3bd7375c4db7652878b0241b2be5d0c3cca" + integrity sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-reserved-words@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz#832cd35b81c287c4bcd09ce03e22199641f964fb" + integrity sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-shorthand-properties@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz#6e277654be82b5559fc4b9f58088507c24f0c624" + integrity sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-spread@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz#6487fd29f229c95e284ba6c98d65eafb893fea6b" + integrity sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + +"@babel/plugin-transform-sticky-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz#295aba1595bfc8197abd02eae5fc288c0deb26aa" + integrity sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-template-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz#8f38cf291e5f7a8e60e9f733193f0bcc10909bff" + integrity sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-typeof-symbol@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz#5e2ba478da4b603af8673ff7c54f75a97b716b34" + integrity sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-escapes@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz#c723f380f40a2b2f57a62df24c9005834c8616d9" + integrity sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-property-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz#098898f74d5c1e86660dc112057b2d11227f1c81" + integrity sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz#ce7e7bb3ef208c4ff67e02a22816656256d7a183" + integrity sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-sets-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz#77788060e511b708ffc7d42fdfbc5b37c3004e91" + integrity sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/preset-env@^7.19": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.23.2.tgz#1f22be0ff0e121113260337dbc3e58fafce8d059" + integrity sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ== + dependencies: + "@babel/compat-data" "^7.23.2" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.22.15" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.22.15" + "@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.22.5" + "@babel/plugin-syntax-import-attributes" "^7.22.5" + "@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.22.5" + "@babel/plugin-transform-async-generator-functions" "^7.23.2" + "@babel/plugin-transform-async-to-generator" "^7.22.5" + "@babel/plugin-transform-block-scoped-functions" "^7.22.5" + "@babel/plugin-transform-block-scoping" "^7.23.0" + "@babel/plugin-transform-class-properties" "^7.22.5" + "@babel/plugin-transform-class-static-block" "^7.22.11" + "@babel/plugin-transform-classes" "^7.22.15" + "@babel/plugin-transform-computed-properties" "^7.22.5" + "@babel/plugin-transform-destructuring" "^7.23.0" + "@babel/plugin-transform-dotall-regex" "^7.22.5" + "@babel/plugin-transform-duplicate-keys" "^7.22.5" + "@babel/plugin-transform-dynamic-import" "^7.22.11" + "@babel/plugin-transform-exponentiation-operator" "^7.22.5" + "@babel/plugin-transform-export-namespace-from" "^7.22.11" + "@babel/plugin-transform-for-of" "^7.22.15" + "@babel/plugin-transform-function-name" "^7.22.5" + "@babel/plugin-transform-json-strings" "^7.22.11" + "@babel/plugin-transform-literals" "^7.22.5" + "@babel/plugin-transform-logical-assignment-operators" "^7.22.11" + "@babel/plugin-transform-member-expression-literals" "^7.22.5" + "@babel/plugin-transform-modules-amd" "^7.23.0" + "@babel/plugin-transform-modules-commonjs" "^7.23.0" + "@babel/plugin-transform-modules-systemjs" "^7.23.0" + "@babel/plugin-transform-modules-umd" "^7.22.5" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" + "@babel/plugin-transform-new-target" "^7.22.5" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.22.11" + "@babel/plugin-transform-numeric-separator" "^7.22.11" + "@babel/plugin-transform-object-rest-spread" "^7.22.15" + "@babel/plugin-transform-object-super" "^7.22.5" + "@babel/plugin-transform-optional-catch-binding" "^7.22.11" + "@babel/plugin-transform-optional-chaining" "^7.23.0" + "@babel/plugin-transform-parameters" "^7.22.15" + "@babel/plugin-transform-private-methods" "^7.22.5" + "@babel/plugin-transform-private-property-in-object" "^7.22.11" + "@babel/plugin-transform-property-literals" "^7.22.5" + "@babel/plugin-transform-regenerator" "^7.22.10" + "@babel/plugin-transform-reserved-words" "^7.22.5" + "@babel/plugin-transform-shorthand-properties" "^7.22.5" + "@babel/plugin-transform-spread" "^7.22.5" + "@babel/plugin-transform-sticky-regex" "^7.22.5" + "@babel/plugin-transform-template-literals" "^7.22.5" + "@babel/plugin-transform-typeof-symbol" "^7.22.5" + "@babel/plugin-transform-unicode-escapes" "^7.22.10" + "@babel/plugin-transform-unicode-property-regex" "^7.22.5" + "@babel/plugin-transform-unicode-regex" "^7.22.5" + "@babel/plugin-transform-unicode-sets-regex" "^7.22.5" + "@babel/preset-modules" "0.1.6-no-external-plugins" + "@babel/types" "^7.23.0" + babel-plugin-polyfill-corejs2 "^0.4.6" + babel-plugin-polyfill-corejs3 "^0.8.5" + babel-plugin-polyfill-regenerator "^0.5.3" + core-js-compat "^3.31.0" + 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.22.15" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.22.15.tgz#9a776892b648e13cc8ca2edf5ed1264eea6b6afc" + integrity sha512-Csy1IJ2uEh/PecCBXXoZGAZBeCATTuePzCSB7dLYWS0vOEj6CNpjxIhW4duWwZodBNueH7QO14WbGn8YyeuN9w== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-transform-react-display-name" "^7.22.5" + "@babel/plugin-transform-react-jsx" "^7.22.15" + "@babel/plugin-transform-react-jsx-development" "^7.22.5" + "@babel/plugin-transform-react-pure-annotations" "^7.22.5" + +"@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.23.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885" + integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.22.15", "@babel/template@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@^7.23.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.4.4": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" + integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + 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.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.3": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" + integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.19" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" + integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@paypal/paypal-js@^6.0.0": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@paypal/paypal-js/-/paypal-js-6.0.1.tgz#5d68d5863a5176383fee9424bc944231668fcffd" + integrity sha512-bvYetmkg2GEC6onsUJQx1E9hdAJWff2bS3IPeiZ9Sh9U7h26/fIgMKm240cq/908sbSoDjHys75XXd8at9OpQA== + dependencies: + promise-polyfill "^8.3.0" + +"@types/eslint-scope@^3.7.3": + version "3.7.5" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.5.tgz#e28b09dbb1d9d35fdfa8a884225f00440dfc5a3e" + integrity sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.44.4" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.44.4.tgz#28eaff82e1ca0a96554ec5bb0188f10ae1a74c2f" + integrity sha512-lOzjyfY/D9QR4hY9oblZ76B90MYTB3RrQ4z2vBIJKj9ROCRqdkYl2gSUx1x1a4IWPjKJZLL4Aw1Zfay7eMnmnA== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.2.tgz#ff02bc3dc8317cd668dfec247b750ba1f1d62453" + integrity sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA== + +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": + version "7.0.13" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85" + integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ== + +"@types/node@*": + version "20.8.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.6.tgz#0dbd4ebcc82ad0128df05d0e6f57e05359ee47fa" + integrity sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ== + dependencies: + undici-types "~5.25.1" + +"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" + integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== + 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.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" + integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== + +"@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.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" + integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + +"@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.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" + integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-opt" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" + "@webassemblyjs/wast-printer" "1.11.6" + +"@webassemblyjs/wasm-gen@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" + integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== + dependencies: + "@webassemblyjs/ast" "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/wasm-opt@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" + integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" + +"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" + integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@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.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" + integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@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-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.7.1, acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + +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.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz#b2df0251d8e99f229a8e60fc4efa9a68b41c8313" + integrity sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.4.3" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.5.tgz#a75fa1b0c3fc5bd6837f9ec465c0f48031b8cab1" + integrity sha512-Q6CdATeAvbScWPNLB8lzSO7fgUVBkQt6zLgNlfyeCr/EQaEQR+bWiBYYPYAFyE528BMjRhL+1QBMOI4jc/c5TA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.4.3" + core-js-compat "^3.32.2" + +babel-plugin-polyfill-regenerator@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz#d4c49e4b44614607c13fb769bcd85c72bb26a4a5" + integrity sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.4.3" + +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.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.14.5, browserslist@^4.21.9, browserslist@^4.22.1: + version "4.22.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.1.tgz#ba91958d1a59b87dab6fed8dfbcb3da5e2e9c619" + integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ== + dependencies: + caniuse-lite "^1.0.30001541" + electron-to-chromium "^1.4.535" + node-releases "^2.0.13" + update-browserslist-db "^1.0.13" + +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.30001541: + version "1.0.30001549" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz#7d1a3dce7ea78c06ed72c32c2743ea364b3615aa" + integrity sha512-qRp48dPYSCYaP+KurZLhDYdVE+yEyht/3NlmcJgVQ2VMGt6JL36ndQ/7rgspdZsJuxDPFIo/OzBT2+GmIJ53BA== + +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.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + 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.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +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.31.0, core-js-compat@^3.32.2: + version "3.33.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.33.0.tgz#24aa230b228406450b2277b7c8bfebae932df966" + integrity sha512-0w4LcLXsVEuNkIqwjjf9rjCoPhK8uqA4tMRh4Ge26vfLtUutshn+aRJU21I9LCJlh2QQHfisNToLjw1XEJLTWw== + dependencies: + browserslist "^4.22.1" + +core-js@^3.25.0: + version "3.33.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.33.0.tgz#70366dbf737134761edb017990cf5ce6c6369c40" + integrity sha512-HoZr92+ZjFEKar5HS6MC776gYslNOKHt75mEBKWKnPeFDpZ6nH5OeF3S6HFT1mUAUZKrzkez05VboaX8myjSuw== + +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: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +electron-to-chromium@^1.4.535: + version "1.4.556" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.556.tgz#97385917eb6ea3ac6a3378cf87bb39ee1db96e76" + integrity sha512-6RPN0hHfzDU8D56E72YkDvnLw5Cj2NMXZGg3UkgyoHxjVhG99KZpsKgBWMmTy0Ei89xwan+rbRsVB9yzATmYzQ== + +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.15.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" + integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.7.3: + version "7.10.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.10.0.tgz#55146e3909cc5fe63c22da63fb15b05aeac35b13" + integrity sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw== + +es-module-lexer@^1.2.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.1.tgz#c1b0dd5ada807a3b3155315911f364dc4e909db1" + integrity sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +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.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + 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== + +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.4, graceful-fs@^4.2.9: + 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== + +has@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" + integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== + +immutable@^4.0.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f" + integrity sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA== + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + 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.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + +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.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== + +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: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +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" + +promise-polyfill@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.3.0.tgz#9284810268138d103807b11f4e23d5e945a4db63" + integrity sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +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.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + +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.69.3" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.69.3.tgz#f8a0c488697e6419519834a13335e7b65a609c11" + integrity sha512-X99+a2iGdXkdWn1akFPs0ZmelUzyAQfvqYc2P/MPTrJRuIRoTffGzT9W9nFqG00S+c8hXzVmgxhUuHFdrwxkhQ== + 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.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + 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.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +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.7: + version "5.3.9" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" + integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.17" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.16.8" + +terser@^5.16.8: + version "5.22.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.22.0.tgz#4f18103f84c5c9437aafb7a14918273310a8a49d" + integrity sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw== + 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@~5.25.1: + version "5.25.3" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.25.3.tgz#e044115914c85f0bcbb229f346ab739f064998c3" + integrity sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA== + +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.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +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.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + 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.89.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.89.0.tgz#56b8bf9a34356e93a6625770006490bf3a7f32dc" + integrity sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^1.0.0" + "@webassemblyjs/ast" "^1.11.5" + "@webassemblyjs/wasm-edit" "^1.11.5" + "@webassemblyjs/wasm-parser" "^1.11.5" + acorn "^8.7.1" + acorn-import-assertions "^1.9.0" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.15.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.9" + 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.7" + watchpack "^2.4.0" + 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/modules/ppcp-saved-payment-checker/extensions.php b/modules/ppcp-saved-payment-checker/extensions.php index dad4983b4..e712a03fc 100644 --- a/modules/ppcp-saved-payment-checker/extensions.php +++ b/modules/ppcp-saved-payment-checker/extensions.php @@ -10,12 +10,12 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\SavedPaymentChecker; use WooCommerce\PayPalCommerce\Onboarding\State; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; return array( 'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array { - $subscription_helper = $container->get( 'subscription.helper' ); + $subscription_helper = $container->get( 'wc-subscriptions.helper' ); assert( $subscription_helper instanceof SubscriptionHelper ); $insert_after = function( array $array, string $key, array $new ): array { diff --git a/modules/ppcp-saved-payment-checker/src/PaymentTokenChecker.php b/modules/ppcp-saved-payment-checker/src/PaymentTokenChecker.php index 0da73b51b..df5b3651d 100644 --- a/modules/ppcp-saved-payment-checker/src/PaymentTokenChecker.php +++ b/modules/ppcp-saved-payment-checker/src/PaymentTokenChecker.php @@ -16,7 +16,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokenEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken; use WooCommerce\PayPalCommerce\ApiClient\Repository\OrderRepository; -use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; @@ -126,6 +126,10 @@ class PaymentTokenChecker { return; } + if ( ! in_array( $wc_order->get_payment_method(), array( PayPalGateway::ID, CreditCardGateway::ID, CardButtonGateway::ID ), true ) ) { + return; + } + if ( $wc_order->get_status() === 'processing' || 'capture' !== $intent ) { return; } diff --git a/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php b/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php index f04143ebc..6a6ae3c79 100644 --- a/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php +++ b/modules/ppcp-saved-payment-checker/src/SavedPaymentCheckerModule.php @@ -11,7 +11,7 @@ namespace WooCommerce\PayPalCommerce\SavedPaymentChecker; use Psr\Log\LoggerInterface; use WC_Order; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; @@ -43,7 +43,7 @@ class SavedPaymentCheckerModule implements ModuleInterface { add_filter( 'woocommerce_paypal_payments_order_intent', function( string $intent ) use ( $c ) { - $subscription_helper = $c->get( 'subscription.helper' ); + $subscription_helper = $c->get( 'wc-subscriptions.helper' ); assert( $subscription_helper instanceof SubscriptionHelper ); if ( $subscription_helper->cart_contains_subscription() || $subscription_helper->current_product_is_subscription() ) { @@ -60,7 +60,7 @@ class SavedPaymentCheckerModule implements ModuleInterface { add_action( 'woocommerce_paypal_payments_before_handle_payment_success', function( WC_Order $wc_order ) use ( $c ) { - $subscription_helper = $c->get( 'subscription.helper' ); + $subscription_helper = $c->get( 'wc-subscriptions.helper' ); assert( $subscription_helper instanceof SubscriptionHelper ); if ( $subscription_helper->has_subscription( $wc_order->get_id() ) ) { @@ -93,7 +93,7 @@ class SavedPaymentCheckerModule implements ModuleInterface { add_action( 'woocommerce_email_before_order_table', function( WC_Order $order ) use ( $c ) { - $subscription_helper = $c->get( 'subscription.helper' ); + $subscription_helper = $c->get( 'wc-subscriptions.helper' ); assert( $subscription_helper instanceof SubscriptionHelper ); $logger = $c->get( 'woocommerce.logger.woocommerce' ); assert( $logger instanceof LoggerInterface ); @@ -119,7 +119,7 @@ class SavedPaymentCheckerModule implements ModuleInterface { add_action( 'woocommerce_email_after_order_table', function( WC_Order $order ) use ( $c ) { - $subscription_helper = $c->get( 'subscription.helper' ); + $subscription_helper = $c->get( 'wc-subscriptions.helper' ); assert( $subscription_helper instanceof SubscriptionHelper ); $logger = $c->get( 'woocommerce.logger.woocommerce' ); assert( $logger instanceof LoggerInterface ); diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index 4c2d3c8ae..a7e810abe 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -9,7 +9,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\StatusReport; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; @@ -65,7 +65,7 @@ class StatusReportModule implements ModuleInterface { $messages_apply = $c->get( 'button.helper.messages-apply' ); /* @var SubscriptionHelper $subscription_helper The subscription helper class. */ - $subscription_helper = $c->get( 'subscription.helper' ); + $subscription_helper = $c->get( 'wc-subscriptions.helper' ); $last_webhook_storage = $c->get( 'webhook.last-webhook-storage' ); assert( $last_webhook_storage instanceof WebhookEventStorage ); @@ -78,6 +78,8 @@ class StatusReportModule implements ModuleInterface { $had_ppec_plugin = PPECHelper::is_plugin_configured(); + $subscription_mode_options = $c->get( 'wcgateway.settings.fields.subscriptions_mode_options' ); + $items = array( array( 'label' => esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ), @@ -169,7 +171,7 @@ class StatusReportModule implements ModuleInterface { 'description' => esc_html__( 'Whether subscriptions are active and their mode.', 'woocommerce-paypal-payments' ), 'value' => $this->subscriptions_mode_text( $subscription_helper->plugin_is_active(), - $settings->has( 'subscriptions_mode' ) ? (string) $settings->get( 'subscriptions_mode' ) : '', + $settings->has( 'subscriptions_mode' ) ? (string) $subscription_mode_options[ $settings->get( 'subscriptions_mode' ) ] : '', $subscriptions_mode_settings ), ), diff --git a/modules/ppcp-subscription/services.php b/modules/ppcp-subscription/services.php deleted file mode 100644 index 8ddad1fe6..000000000 --- a/modules/ppcp-subscription/services.php +++ /dev/null @@ -1,74 +0,0 @@ - static function ( ContainerInterface $container ): SubscriptionHelper { - return new SubscriptionHelper( $container->get( 'wcgateway.settings' ) ); - }, - 'subscription.renewal-handler' => static function ( ContainerInterface $container ): RenewalHandler { - $logger = $container->get( 'woocommerce.logger.woocommerce' ); - $repository = $container->get( 'vaulting.repository.payment-token' ); - $endpoint = $container->get( 'api.endpoint.order' ); - $purchase_unit_factory = $container->get( 'api.factory.purchase-unit' ); - $payer_factory = $container->get( 'api.factory.payer' ); - $environment = $container->get( 'onboarding.environment' ); - $settings = $container->get( 'wcgateway.settings' ); - $authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' ); - return new RenewalHandler( - $logger, - $repository, - $endpoint, - $purchase_unit_factory, - $container->get( 'api.factory.shipping-preference' ), - $payer_factory, - $environment, - $settings, - $authorized_payments_processor - ); - }, - 'subscription.repository.payment-token' => static function ( ContainerInterface $container ): PaymentTokenRepository { - $factory = $container->get( 'api.factory.payment-token' ); - $endpoint = $container->get( 'api.endpoint.payment-token' ); - return new PaymentTokenRepository( $factory, $endpoint ); - }, - 'subscription.api-handler' => static function( ContainerInterface $container ): SubscriptionsApiHandler { - return new SubscriptionsApiHandler( - $container->get( 'api.endpoint.catalog-products' ), - $container->get( 'api.factory.product' ), - $container->get( 'api.endpoint.billing-plans' ), - $container->get( 'api.factory.billing-cycle' ), - $container->get( 'api.factory.payment-preferences' ), - $container->get( 'api.shop.currency' ), - $container->get( 'woocommerce.logger.woocommerce' ) - ); - }, - 'subscription.module.url' => static function ( ContainerInterface $container ): string { - /** - * The path cannot be false. - * - * @psalm-suppress PossiblyFalseArgument - */ - return plugins_url( - '/modules/ppcp-subscription/', - dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php' - ); - }, - 'subscription.deactivate-plan-endpoint' => static function ( ContainerInterface $container ): DeactivatePlanEndpoint { - return new DeactivatePlanEndpoint( - $container->get( 'button.request-data' ), - $container->get( 'api.endpoint.billing-plans' ) - ); - }, -); diff --git a/modules/ppcp-subscription/src/RenewalHandler.php b/modules/ppcp-subscription/src/RenewalHandler.php deleted file mode 100644 index f4a9a6cbd..000000000 --- a/modules/ppcp-subscription/src/RenewalHandler.php +++ /dev/null @@ -1,320 +0,0 @@ -logger = $logger; - $this->repository = $repository; - $this->order_endpoint = $order_endpoint; - $this->purchase_unit_factory = $purchase_unit_factory; - $this->shipping_preference_factory = $shipping_preference_factory; - $this->payer_factory = $payer_factory; - $this->environment = $environment; - $this->settings = $settings; - $this->authorized_payments_processor = $authorized_payments_processor; - } - - /** - * Renew an order. - * - * @param \WC_Order $wc_order The WooCommerce order. - */ - public function renew( \WC_Order $wc_order ): void { - try { - $subscription = wcs_get_subscription( $wc_order->get_id() ); - if ( is_a( $subscription, WC_Subscription::class ) ) { - $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; - if ( $subscription_id ) { - return; - } - } - - $this->process_order( $wc_order ); - } catch ( \Exception $exception ) { - $error = $exception->getMessage(); - if ( is_a( $exception, PayPalApiException::class ) ) { - $error = $exception->get_details( $error ); - } - - $wc_order->update_status( - 'failed', - $error - ); - - $error_message = sprintf( - 'An error occurred while trying to renew the subscription for order %1$d: %2$s', - $wc_order->get_id(), - $error - ); - $this->logger->error( $error_message ); - - return; - } - } - - /** - * Process a WooCommerce order. - * - * @param \WC_Order $wc_order The WooCommerce order. - * - * @throws \Exception If customer cannot be read/found. - */ - private function process_order( \WC_Order $wc_order ): void { - - $user_id = (int) $wc_order->get_customer_id(); - $customer = new \WC_Customer( $user_id ); - $token = $this->get_token_for_customer( $customer, $wc_order ); - if ( ! $token ) { - return; - } - - $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); - $payer = $this->payer_factory->from_customer( $customer ); - $shipping_preference = $this->shipping_preference_factory->from_state( - $purchase_unit, - 'renewal' - ); - - $order = $this->order_endpoint->create( - array( $purchase_unit ), - $shipping_preference, - $payer, - $token - ); - - $this->add_paypal_meta( $wc_order, $order, $this->environment ); - - if ( $order->intent() === 'AUTHORIZE' ) { - $order = $this->order_endpoint->authorize( $order ); - $wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'false' ); - } - - $transaction_id = $this->get_paypal_order_transaction_id( $order ); - if ( $transaction_id ) { - $this->update_transaction_id( $transaction_id, $wc_order ); - - $subscriptions = wcs_get_subscriptions_for_order( $wc_order->get_id(), array( 'order_type' => 'any' ) ); - foreach ( $subscriptions as $id => $subscription ) { - $subscription->update_meta_data( 'ppcp_previous_transaction_reference', $transaction_id ); - $subscription->save(); - } - } - - $this->handle_new_order_status( $order, $wc_order ); - - if ( $this->capture_authorized_downloads( $order ) ) { - $this->authorized_payments_processor->capture_authorized_payment( $wc_order ); - } - - $this->logger->info( - sprintf( - 'Renewal for order %d is completed.', - $wc_order->get_id() - ) - ); - } - - /** - * Returns a payment token for a customer. - * - * @param \WC_Customer $customer The customer. - * @param \WC_Order $wc_order The current WooCommerce order we want to process. - * - * @return PaymentToken|null|false - */ - private function get_token_for_customer( \WC_Customer $customer, \WC_Order $wc_order ) { - /** - * Returns a payment token for a customer, or null. - */ - $token = apply_filters( 'woocommerce_paypal_payments_subscriptions_get_token_for_customer', null, $customer, $wc_order ); - if ( null !== $token ) { - return $token; - } - - $tokens = $this->repository->all_for_user_id( (int) $customer->get_id() ); - if ( ! $tokens ) { - - $error_message = sprintf( - 'Payment failed. No payment tokens found for customer %d.', - $customer->get_id() - ); - - $wc_order->update_status( - 'failed', - $error_message - ); - - $this->logger->error( $error_message ); - } - - $subscription = function_exists( 'wcs_get_subscription' ) ? wcs_get_subscription( $wc_order->get_meta( '_subscription_renewal' ) ) : null; - if ( $subscription ) { - $token_id = $subscription->get_meta( 'payment_token_id' ); - if ( $token_id ) { - foreach ( $tokens as $token ) { - if ( $token_id === $token->id() ) { - return $token; - } - } - } - } - - return current( $tokens ); - } - - /** - * Returns if an order should be captured immediately. - * - * @param Order $order The PayPal order. - * - * @return bool - * @throws NotFoundException When a setting was not found. - */ - protected function capture_authorized_downloads( Order $order ): bool { - if ( - ! $this->settings->has( 'capture_for_virtual_only' ) - || ! $this->settings->get( 'capture_for_virtual_only' ) - ) { - return false; - } - - if ( $order->intent() === 'CAPTURE' ) { - return false; - } - - /** - * We fetch the order again as the authorize endpoint (from which the Order derives) - * drops the item's category, making it impossible to check, if purchase units contain - * physical goods. - */ - $order = $this->order_endpoint->order( $order->id() ); - - foreach ( $order->purchase_units() as $unit ) { - if ( $unit->contains_physical_goods() ) { - return false; - } - } - return true; - } -} diff --git a/modules/ppcp-vaulting/services.php b/modules/ppcp-vaulting/services.php index 101e0bb4c..45355225d 100644 --- a/modules/ppcp-vaulting/services.php +++ b/modules/ppcp-vaulting/services.php @@ -31,7 +31,7 @@ return array( }, 'vaulting.credit-card-handler' => function( ContainerInterface $container ): VaultedCreditCardHandler { return new VaultedCreditCardHandler( - $container->get( 'subscription.helper' ), + $container->get( 'wc-subscriptions.helper' ), $container->get( 'vaulting.repository.payment-token' ), $container->get( 'api.factory.purchase-unit' ), $container->get( 'api.factory.payer' ), @@ -56,4 +56,15 @@ return array( $container->get( 'woocommerce.logger.woocommerce' ) ); }, + 'vaulting.wc-payment-tokens' => static function( ContainerInterface $container ): WooCommercePaymentTokens { + return new WooCommercePaymentTokens( + $container->get( 'vaulting.payment-token-helper' ), + $container->get( 'vaulting.payment-token-factory' ), + $container->get( 'api.endpoint.payment-tokens' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, + 'vaulting.vault-v3-enabled' => static function( ContainerInterface $container ): bool { + return $container->has( 'save-payment-methods.eligible' ) && $container->get( 'save-payment-methods.eligible' ); + }, ); diff --git a/modules/ppcp-vaulting/src/CustomerApprovalListener.php b/modules/ppcp-vaulting/src/CustomerApprovalListener.php index 1b922511b..2241d038d 100644 --- a/modules/ppcp-vaulting/src/CustomerApprovalListener.php +++ b/modules/ppcp-vaulting/src/CustomerApprovalListener.php @@ -13,7 +13,7 @@ use Exception; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokenEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Exception\AlreadyVaultedException; -use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; /** * Class CustomerApprovalListener diff --git a/modules/ppcp-vaulting/src/PaymentTokenApplePay.php b/modules/ppcp-vaulting/src/PaymentTokenApplePay.php new file mode 100644 index 000000000..a53aa254a --- /dev/null +++ b/modules/ppcp-vaulting/src/PaymentTokenApplePay.php @@ -0,0 +1,31 @@ +get_token() === $token_id ) { - return true; + if ( null !== $class_name ) { + if ( $wc_token instanceof $class_name ) { + return true; + } + } else { + return true; + } } } return false; } + + /** + * Checks if given token exist as WC Payment Token. + * + * @param array $wc_tokens WC Payment Tokens. + * @param string $class_name Class name of the token. + * @return null|WC_Payment_Token + */ + public function first_token_of_type( array $wc_tokens, string $class_name ) { + foreach ( $wc_tokens as $wc_token ) { + if ( $wc_token instanceof $class_name ) { + return $wc_token; + } + } + + return null; + } } diff --git a/modules/ppcp-vaulting/src/PaymentTokenVenmo.php b/modules/ppcp-vaulting/src/PaymentTokenVenmo.php new file mode 100644 index 000000000..d53a4b4fb --- /dev/null +++ b/modules/ppcp-vaulting/src/PaymentTokenVenmo.php @@ -0,0 +1,51 @@ + '', + ); + + /** + * Get PayPal account email. + * + * @return string PayPal account email. + */ + public function get_email() { + return $this->get_meta( 'email' ); + } + + /** + * Set PayPal account email. + * + * @param string $email PayPal account email. + */ + public function set_email( $email ) { + $this->add_meta_data( 'email', $email, true ); + } +} diff --git a/modules/ppcp-vaulting/src/PaymentTokensMigration.php b/modules/ppcp-vaulting/src/PaymentTokensMigration.php index a7d3511cc..1ef41df4a 100644 --- a/modules/ppcp-vaulting/src/PaymentTokensMigration.php +++ b/modules/ppcp-vaulting/src/PaymentTokensMigration.php @@ -107,7 +107,7 @@ class PaymentTokensMigration { } } elseif ( $token->source()->paypal ) { $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $id, PayPalGateway::ID ); - if ( $this->payment_token_helper->token_exist( $wc_tokens, $token->id() ) ) { + if ( $this->payment_token_helper->token_exist( $wc_tokens, $token->id(), PaymentTokenPayPal::class ) ) { $this->logger->info( 'Token already exist for user ' . (string) $id ); continue; } diff --git a/modules/ppcp-vaulting/src/VaultedCreditCardHandler.php b/modules/ppcp-vaulting/src/VaultedCreditCardHandler.php index 04b1c8d5d..3261e4b8e 100644 --- a/modules/ppcp-vaulting/src/VaultedCreditCardHandler.php +++ b/modules/ppcp-vaulting/src/VaultedCreditCardHandler.php @@ -19,8 +19,8 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory; use WooCommerce\PayPalCommerce\Onboarding\Environment; -use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderMetaTrait; use WooCommerce\PayPalCommerce\WcGateway\Processor\PaymentsStatusHandlingTrait; @@ -143,19 +143,6 @@ class VaultedCreditCardHandler { string $saved_credit_card, WC_Order $wc_order ): WC_Order { - if ( - // phpcs:ignore WordPress.Security.NonceVerification.Missing - isset( $_POST['woocommerce_change_payment'] ) - && $this->subscription_helper->has_subscription( $wc_order->get_id() ) - && $this->subscription_helper->is_subscription_change_payment() - && $saved_credit_card - ) { - $wc_order->update_meta_data( 'payment_token_id', $saved_credit_card ); - $wc_order->save(); - - return $wc_order; - } - $tokens = $this->payment_token_repository->all_for_user_id( $wc_order->get_customer_id() ); $selected_token = null; foreach ( $tokens as $token ) { diff --git a/modules/ppcp-vaulting/src/VaultingModule.php b/modules/ppcp-vaulting/src/VaultingModule.php index 4da9a32bb..5216b82c3 100644 --- a/modules/ppcp-vaulting/src/VaultingModule.php +++ b/modules/ppcp-vaulting/src/VaultingModule.php @@ -51,10 +51,14 @@ class VaultingModule implements ModuleInterface { $listener->listen(); - $subscription_helper = $container->get( 'subscription.helper' ); + $subscription_helper = $container->get( 'wc-subscriptions.helper' ); add_action( 'woocommerce_created_customer', - function( int $customer_id ) use ( $subscription_helper ) { + function( int $customer_id ) use ( $subscription_helper, $container ) { + if ( $container->has( 'save-payment-methods.eligible' ) && $container->get( 'save-payment-methods.eligible' ) ) { + return; + } + $session = WC()->session; if ( ! $session ) { return; @@ -77,11 +81,50 @@ class VaultingModule implements ModuleInterface { if ( $type === 'WC_Payment_Token_PayPal' ) { return PaymentTokenPayPal::class; } + if ( $type === 'WC_Payment_Token_Venmo' ) { + return PaymentTokenVenmo::class; + } + if ( $type === 'WC_Payment_Token_ApplePay' ) { + return PaymentTokenApplePay::class; + } return $type; } ); + add_filter( + 'woocommerce_get_customer_payment_tokens', + /** + * Filter available payment tokens depending on context. + * + * @psalm-suppress MissingClosureParamType + * @psalm-suppress MissingClosureReturnType + */ + function( $tokens, $customer_id, $gateway_id ) { + if ( ! is_array( $tokens ) ) { + return $tokens; + } + + $is_post = isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] === 'POST'; + + // Exclude ApplePay tokens from payment pages. + if ( + ( is_checkout() || is_cart() || is_product() ) + && ! $is_post // Don't check on POST so we have all payment methods on form submissions. + ) { + foreach ( $tokens as $index => $token ) { + if ( $token instanceof PaymentTokenApplePay ) { + unset( $tokens[ $index ] ); + } + } + } + + return $tokens; + }, + 10, + 3 + ); + add_filter( 'woocommerce_payment_methods_list_item', /** @@ -94,10 +137,18 @@ class VaultingModule implements ModuleInterface { return $item; } - if ( strtolower( $payment_token->get_type() ) === 'paypal' ) { - assert( $payment_token instanceof PaymentTokenPayPal ); - $item['method']['brand'] = $payment_token->get_email(); + if ( $payment_token instanceof PaymentTokenPayPal ) { + $item['method']['brand'] = 'PayPal / ' . $payment_token->get_email(); + return $item; + } + if ( $payment_token instanceof PaymentTokenVenmo ) { + $item['method']['brand'] = 'Venmo / ' . $payment_token->get_email(); + return $item; + } + + if ( $payment_token instanceof PaymentTokenApplePay ) { + $item['method']['brand'] = 'ApplePay #' . ( (string) $payment_token->get_id() ); return $item; } @@ -137,6 +188,8 @@ class VaultingModule implements ModuleInterface { } try { + do_action( 'woocommerce_paypal_payments_before_delete_payment_token', $token->get_token() ); + $payment_token_endpoint = $container->get( 'api.endpoint.payment-token' ); $payment_token_endpoint->delete_token_by_id( $token->get_token() ); } catch ( RuntimeException $exception ) { @@ -189,9 +242,22 @@ class VaultingModule implements ModuleInterface { add_filter( 'woocommerce_available_payment_gateways', - function( array $methods ): array { + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ + function( $methods ) { global $wp; - if ( isset( $wp->query_vars['add-payment-method'] ) ) { + + if ( ! is_array( $methods ) ) { + return $methods; + } + + if ( + isset( $wp->query_vars['add-payment-method'] ) + && apply_filters( 'woocommerce_paypal_payments_disable_add_payment_method', true ) + ) { unset( $methods[ PayPalGateway::ID ] ); } diff --git a/modules/ppcp-vaulting/src/WooCommercePaymentTokens.php b/modules/ppcp-vaulting/src/WooCommercePaymentTokens.php new file mode 100644 index 000000000..9136f7d85 --- /dev/null +++ b/modules/ppcp-vaulting/src/WooCommercePaymentTokens.php @@ -0,0 +1,326 @@ +payment_token_helper = $payment_token_helper; + $this->payment_token_factory = $payment_token_factory; + $this->payment_tokens_endpoint = $payment_tokens_endpoint; + $this->logger = $logger; + } + + /** + * Creates a WC Payment Token for PayPal payment. + * + * @param int $customer_id The WC customer ID. + * @param string $token The PayPal payment token. + * @param string $email The PayPal customer email. + * + * @return int + */ + public function create_payment_token_paypal( + int $customer_id, + string $token, + string $email + ): int { + + if ( $customer_id === 0 ) { + return 0; + } + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID ); + if ( $this->payment_token_helper->token_exist( $wc_tokens, $token, PaymentTokenPayPal::class ) ) { + return 0; + } + + // Try to update existing token of type before creating a new one. + $payment_token_paypal = $this->payment_token_helper->first_token_of_type( $wc_tokens, PaymentTokenPayPal::class ); + + if ( ! $payment_token_paypal ) { + $payment_token_paypal = $this->payment_token_factory->create( 'paypal' ); + } + + assert( $payment_token_paypal instanceof PaymentTokenPayPal ); + + $payment_token_paypal->set_token( $token ); + $payment_token_paypal->set_user_id( $customer_id ); + $payment_token_paypal->set_gateway_id( PayPalGateway::ID ); + + if ( $email && is_email( $email ) ) { + $payment_token_paypal->set_email( $email ); + } + + try { + $payment_token_paypal->save(); + } catch ( Exception $exception ) { + $this->logger->error( + "Could not create WC payment token PayPal for customer {$customer_id}. " . $exception->getMessage() + ); + } + + return $payment_token_paypal->get_id(); + } + + /** + * Creates a WC Payment Token for Venmo payment. + * + * @param int $customer_id The WC customer ID. + * @param string $token The Venmo payment token. + * @param string $email The Venmo customer email. + * + * @return int + */ + public function create_payment_token_venmo( + int $customer_id, + string $token, + string $email + ): int { + + if ( $customer_id === 0 ) { + return 0; + } + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID ); + if ( $this->payment_token_helper->token_exist( $wc_tokens, $token, PaymentTokenVenmo::class ) ) { + return 0; + } + + // Try to update existing token of type before creating a new one. + $payment_token_venmo = $this->payment_token_helper->first_token_of_type( $wc_tokens, PaymentTokenVenmo::class ); + + if ( ! $payment_token_venmo ) { + $payment_token_venmo = $this->payment_token_factory->create( 'venmo' ); + } + + assert( $payment_token_venmo instanceof PaymentTokenVenmo ); + + $payment_token_venmo->set_token( $token ); + $payment_token_venmo->set_user_id( $customer_id ); + $payment_token_venmo->set_gateway_id( PayPalGateway::ID ); + + if ( $email && is_email( $email ) ) { + $payment_token_venmo->set_email( $email ); + } + + try { + $payment_token_venmo->save(); + } catch ( Exception $exception ) { + $this->logger->error( + "Could not create WC payment token Venmo for customer {$customer_id}. " . $exception->getMessage() + ); + } + + return $payment_token_venmo->get_id(); + } + + /** + * Creates a WC Payment Token for ApplePay payment. + * + * @param int $customer_id The WC customer ID. + * @param string $token The ApplePay payment token. + * + * @return int + */ + public function create_payment_token_applepay( + int $customer_id, + string $token + ): int { + + if ( $customer_id === 0 ) { + return 0; + } + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID ); + if ( $this->payment_token_helper->token_exist( $wc_tokens, $token, PaymentTokenApplePay::class ) ) { + return 0; + } + + // Try to update existing token of type before creating a new one. + $payment_token_applepay = $this->payment_token_helper->first_token_of_type( $wc_tokens, PaymentTokenApplePay::class ); + + if ( ! $payment_token_applepay ) { + $payment_token_applepay = $this->payment_token_factory->create( 'apple_pay' ); + } + + assert( $payment_token_applepay instanceof PaymentTokenApplePay ); + + $payment_token_applepay->set_token( $token ); + $payment_token_applepay->set_user_id( $customer_id ); + $payment_token_applepay->set_gateway_id( PayPalGateway::ID ); + + try { + $payment_token_applepay->save(); + } catch ( Exception $exception ) { + $this->logger->error( + "Could not create WC payment token ApplePay for customer {$customer_id}. " . $exception->getMessage() + ); + } + + return $payment_token_applepay->get_id(); + } + + /** + * Creates a WC Payment Token for Credit Card payment. + * + * @param int $customer_id The WC customer ID. + * @param stdClass $payment_token The Credit Card payment token. + * + * @return int + */ + public function create_payment_token_card( int $customer_id, stdClass $payment_token ): int { + if ( $customer_id === 0 ) { + return 0; + } + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, CreditCardGateway::ID ); + if ( $this->payment_token_helper->token_exist( $wc_tokens, $payment_token->id ) ) { + return 0; + } + + $token = new WC_Payment_Token_CC(); + $token->set_token( $payment_token->id ); + $token->set_user_id( $customer_id ); + $token->set_gateway_id( CreditCardGateway::ID ); + + $token->set_last4( $payment_token->payment_source->card->last_digits ?? '' ); + $expiry = explode( '-', $payment_token->payment_source->card->expiry ?? '' ); + $token->set_expiry_year( $expiry[0] ?? '' ); + $token->set_expiry_month( $expiry[1] ?? '' ); + + $brand = $payment_token->payment_source->card->brand ?? __( 'N/A', 'woocommerce-paypal-payments' ); + if ( $brand ) { + $token->set_card_type( $brand ); + } + + try { + $token->save(); + } catch ( Exception $exception ) { + $this->logger->error( + "Could not create WC payment token card for customer {$customer_id}. " . $exception->getMessage() + ); + } + + $token->save(); + return $token->get_id(); + } + + /** + * Returns PayPal payment tokens for the given WP user id. + * + * @param int $user_id WP user id. + * @return array + */ + public function customer_tokens( int $user_id ): array { + $customer_id = get_user_meta( $user_id, '_ppcp_target_customer_id', true ); + if ( ! $customer_id ) { + $customer_id = get_user_meta( $user_id, 'ppcp_customer_id', true ); + } + + try { + $customer_tokens = $this->payment_tokens_endpoint->payment_tokens_for_customer( $customer_id ); + } catch ( RuntimeException $exception ) { + $customer_tokens = array(); + } + + return $customer_tokens; + } + + /** + * Creates WC payment tokens for the given WP user id using PayPal payment tokens as source. + * + * @param array $customer_tokens PayPal customer payment tokens. + * @param int $user_id WP user id. + * @return void + */ + public function create_wc_tokens( array $customer_tokens, int $user_id ): void { + foreach ( $customer_tokens as $customer_token ) { + if ( $customer_token['payment_source']->name() === 'paypal' ) { + $this->create_payment_token_paypal( + $user_id, + $customer_token['id'], + $customer_token['payment_source']->properties()->email_address ?? '' + ); + } + + if ( $customer_token['payment_source']->name() === 'card' ) { + /** + * Suppress ArgumentTypeCoercion + * + * @psalm-suppress ArgumentTypeCoercion + */ + $this->create_payment_token_card( + $user_id, + (object) array( + 'id' => $customer_token['id'], + 'payment_source' => (object) array( + $customer_token['payment_source']->name() => $customer_token['payment_source']->properties(), + ), + ) + ); + } + } + } +} diff --git a/modules/ppcp-wc-gateway/extensions.php b/modules/ppcp-wc-gateway/extensions.php index 45a488d86..aca11f1b1 100644 --- a/modules/ppcp-wc-gateway/extensions.php +++ b/modules/ppcp-wc-gateway/extensions.php @@ -60,7 +60,6 @@ return array( $source ); }, - 'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array { $files = array( 'paypal-smart-button-fields.php', diff --git a/modules/ppcp-wc-gateway/resources/css/common.scss b/modules/ppcp-wc-gateway/resources/css/common.scss index 259ecc672..6ab2f4a56 100644 --- a/modules/ppcp-wc-gateway/resources/css/common.scss +++ b/modules/ppcp-wc-gateway/resources/css/common.scss @@ -1,3 +1,4 @@ +@use "../../../ppcp-button/resources/css/mixins/apm-button" as apm-button; .ppcp-field-hidden { display: none !important; @@ -15,3 +16,26 @@ padding-left: 20px; } } + +// Prevents spacing after button group. +.ppcp-button-preview-inner { + line-height: 0; +} + +.ppcp-button-apm { + @include apm-button.button; +} + +.ppcp-status-text { + padding-top: 4px; + + .error { + color: red; + font-weight: bold; + } + + .success { + color: green; + font-weight: bold; + } +} diff --git a/modules/ppcp-wc-gateway/resources/js/common.js b/modules/ppcp-wc-gateway/resources/js/common.js index ba763605b..9b412ff70 100644 --- a/modules/ppcp-wc-gateway/resources/js/common.js +++ b/modules/ppcp-wc-gateway/resources/js/common.js @@ -15,9 +15,6 @@ document.addEventListener( jQuery( '*[data-ppcp-display]' ).each( (index, el) => { const rules = jQuery(el).data('ppcpDisplay'); - - // console.log('rules', rules); - for (const rule of rules) { displayManager.addRule(rule); } diff --git a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js index 0a18d0ab1..ed50902e6 100644 --- a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js +++ b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js @@ -353,5 +353,59 @@ document.addEventListener( }, 'card')); }); } + + // Logic to handle the "Check available features" button. + (($, props, anchor) => { + const $btn = $(props.button); + + const printStatus = (message, showSpinner) => { + const html = message + (showSpinner ? '' : ''); + $btn.siblings('.ppcp-status-text').html(html); + }; + + // If the reload comes from a successful refresh. + if (typeof URLSearchParams === 'function' && (new URLSearchParams(window.location.search)).get('feature-refreshed')) { + printStatus('✔️ ' + props.messages.success + ''); + $('html, body').animate({ + scrollTop: $(anchor).offset().top + }, 500); + } + + $btn.click(async () => { + $btn.prop('disabled', true); + printStatus(props.messages.waiting, true); + + const response = await fetch( + props.endpoint, + { + method: 'POST', + credentials: 'same-origin', + headers: { + 'content-type': 'application/json' + }, + body: JSON.stringify( + { + nonce: props.nonce, + } + ) + } + ); + + const responseData = await response.json(); + + if (!responseData.success) { + printStatus(responseData.data.message); + $btn.prop('disabled', false); + } else { + window.location.href += (window.location.href.indexOf('?') > -1 ? '&' : '?') + "feature-refreshed=1#"; + } + }); + + })( + jQuery, + PayPalCommerceGatewaySettings.ajax.refresh_feature_status, + '#field-credentials_feature_onboarding_heading' + ); + } ); diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 913eaee9f..6bf3d5ecf 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PayUponInvoiceOrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; @@ -21,7 +22,10 @@ use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer; use WooCommerce\PayPalCommerce\Onboarding\State; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcGateway\Admin\RenderReauthorizeAction; +use WooCommerce\PayPalCommerce\WcGateway\Endpoint\CaptureCardPayment; +use WooCommerce\PayPalCommerce\WcGateway\Endpoint\RefreshFeatureStatusEndpoint; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer; use WooCommerce\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn; @@ -76,7 +80,7 @@ return array( $refund_processor = $container->get( 'wcgateway.processor.refunds' ); $state = $container->get( 'onboarding.state' ); $transaction_url_provider = $container->get( 'wcgateway.transaction-url-provider' ); - $subscription_helper = $container->get( 'subscription.helper' ); + $subscription_helper = $container->get( 'wc-subscriptions.helper' ); $page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' ); $payment_token_repository = $container->get( 'vaulting.repository.payment-token' ); $environment = $container->get( 'onboarding.environment' ); @@ -99,7 +103,10 @@ return array( $api_shop_country, $container->get( 'api.endpoint.order' ), $container->get( 'api.factory.paypal-checkout-url' ), - $container->get( 'wcgateway.place-order-button-text' ) + $container->get( 'wcgateway.place-order-button-text' ), + $container->get( 'api.endpoint.payment-tokens' ), + $container->get( 'vaulting.vault-v3-enabled' ), + $container->get( 'vaulting.wc-payment-tokens' ) ); }, 'wcgateway.credit-card-gateway' => static function ( ContainerInterface $container ): CreditCardGateway { @@ -111,7 +118,7 @@ return array( $refund_processor = $container->get( 'wcgateway.processor.refunds' ); $state = $container->get( 'onboarding.state' ); $transaction_url_provider = $container->get( 'wcgateway.transaction-url-provider' ); - $subscription_helper = $container->get( 'subscription.helper' ); + $subscription_helper = $container->get( 'wc-subscriptions.helper' ); $payments_endpoint = $container->get( 'api.endpoint.payments' ); $logger = $container->get( 'woocommerce.logger.woocommerce' ); $vaulted_credit_card_handler = $container->get( 'vaulting.credit-card-handler' ); @@ -125,9 +132,15 @@ return array( $state, $transaction_url_provider, $subscription_helper, - $logger, $payments_endpoint, - $vaulted_credit_card_handler + $vaulted_credit_card_handler, + $container->get( 'onboarding.environment' ), + $container->get( 'api.endpoint.order' ), + $container->get( 'wcgateway.endpoint.capture-card-payment' ), + $container->get( 'api.prefix' ), + $container->get( 'api.endpoint.payment-tokens' ), + $container->get( 'vaulting.wc-payment-tokens' ), + $logger ); }, 'wcgateway.card-button-gateway' => static function ( ContainerInterface $container ): CardButtonGateway { @@ -139,7 +152,7 @@ return array( $container->get( 'wcgateway.processor.refunds' ), $container->get( 'onboarding.state' ), $container->get( 'wcgateway.transaction-url-provider' ), - $container->get( 'subscription.helper' ), + $container->get( 'wc-subscriptions.helper' ), $container->get( 'wcgateway.settings.allow_card_button_gateway.default' ), $container->get( 'onboarding.environment' ), $container->get( 'vaulting.repository.payment-token' ), @@ -152,7 +165,7 @@ return array( $session_handler = $container->get( 'session.handler' ); $settings = $container->get( 'wcgateway.settings' ); $settings_status = $container->get( 'wcgateway.settings.status' ); - $subscription_helper = $container->get( 'subscription.helper' ); + $subscription_helper = $container->get( 'wc-subscriptions.helper' ); return new DisableGateways( $session_handler, $settings, $settings_status, $subscription_helper ); }, @@ -331,6 +344,7 @@ return array( $container->get( 'http.redirector' ), $container->get( 'api.partner_merchant_id-production' ), $container->get( 'api.partner_merchant_id-sandbox' ), + $container->get( 'api.endpoint.billing-agreements' ), $logger ); }, @@ -344,7 +358,7 @@ return array( $settings = $container->get( 'wcgateway.settings' ); $environment = $container->get( 'onboarding.environment' ); $logger = $container->get( 'woocommerce.logger.woocommerce' ); - $subscription_helper = $container->get( 'subscription.helper' ); + $subscription_helper = $container->get( 'wc-subscriptions.helper' ); $order_helper = $container->get( 'api.order-helper' ); return new OrderProcessor( $session_handler, @@ -366,8 +380,9 @@ return array( $order_endpoint = $container->get( 'api.endpoint.order' ); $payments_endpoint = $container->get( 'api.endpoint.payments' ); $refund_fees_updater = $container->get( 'wcgateway.helper.refund-fees-updater' ); + $prefix = $container->get( 'api.prefix' ); $logger = $container->get( 'woocommerce.logger.woocommerce' ); - return new RefundProcessor( $order_endpoint, $payments_endpoint, $refund_fees_updater, $logger ); + return new RefundProcessor( $order_endpoint, $payments_endpoint, $refund_fees_updater, $prefix, $logger ); }, 'wcgateway.processor.authorized-payments' => static function ( ContainerInterface $container ): AuthorizedPaymentsProcessor { $order_endpoint = $container->get( 'api.endpoint.order' ); @@ -375,20 +390,26 @@ return array( $logger = $container->get( 'woocommerce.logger.woocommerce' ); $notice = $container->get( 'wcgateway.notice.authorize-order-action' ); $settings = $container->get( 'wcgateway.settings' ); - $subscription_helper = $container->get( 'subscription.helper' ); + $subscription_helper = $container->get( 'wc-subscriptions.helper' ); + $amount_factory = $container->get( 'api.factory.amount' ); return new AuthorizedPaymentsProcessor( $order_endpoint, $payments_endpoint, $logger, $notice, $settings, - $subscription_helper + $subscription_helper, + $amount_factory ); }, 'wcgateway.admin.render-authorize-action' => static function ( ContainerInterface $container ): RenderAuthorizeAction { $column = $container->get( 'wcgateway.admin.orders-payment-status-column' ); return new RenderAuthorizeAction( $column ); }, + 'wcgateway.admin.render-reauthorize-action' => static function ( ContainerInterface $container ): RenderReauthorizeAction { + $column = $container->get( 'wcgateway.admin.orders-payment-status-column' ); + return new RenderReauthorizeAction( $column ); + }, 'wcgateway.admin.order-payment-status' => static function ( ContainerInterface $container ): PaymentStatusOrderDetail { $column = $container->get( 'wcgateway.admin.orders-payment-status-column' ); return new PaymentStatusOrderDetail( $column ); @@ -400,7 +421,6 @@ return array( 'wcgateway.admin.fees-renderer' => static function ( ContainerInterface $container ): FeesRenderer { return new FeesRenderer(); }, - 'wcgateway.settings.should-render-settings' => static function ( ContainerInterface $container ): bool { $sections = array( @@ -415,8 +435,22 @@ return array( return array_key_exists( $current_page_id, $sections ); }, - + 'wcgateway.settings.fields.subscriptions_mode_options' => static function ( ContainerInterface $container ): array { + return array( + 'vaulting_api' => __( 'PayPal Vaulting', 'woocommerce-paypal-payments' ), + 'subscriptions_api' => __( 'PayPal Subscriptions', 'woocommerce-paypal-payments' ), + 'disable_paypal_subscriptions' => __( 'Disable PayPal for subscriptions', 'woocommerce-paypal-payments' ), + ); + }, 'wcgateway.settings.fields.subscriptions_mode' => static function ( ContainerInterface $container ): array { + $subscription_mode_options = $container->get( 'wcgateway.settings.fields.subscriptions_mode_options' ); + + $billing_agreements_endpoint = $container->get( 'api.endpoint.billing-agreements' ); + $reference_transaction_enabled = $billing_agreements_endpoint->reference_transaction_enabled(); + if ( $reference_transaction_enabled !== true ) { + unset( $subscription_mode_options['vaulting_api'] ); + } + return array( 'title' => __( 'Subscriptions Mode', 'woocommerce-paypal-payments' ), 'type' => 'select', @@ -424,12 +458,8 @@ return array( 'input_class' => array( 'wc-enhanced-select' ), 'desc_tip' => true, 'description' => __( 'Utilize PayPal Vaulting for flexible subscription processing with saved payment methods, create “PayPal Subscriptions” to bill customers at regular intervals, or disable PayPal for subscription-type products.', 'woocommerce-paypal-payments' ), - 'default' => 'vaulting_api', - 'options' => array( - 'vaulting_api' => __( 'PayPal Vaulting', 'woocommerce-paypal-payments' ), - 'subscriptions_api' => __( 'PayPal Subscriptions', 'woocommerce-paypal-payments' ), - 'disable_paypal_subscriptions' => __( 'Disable PayPal for subscriptions', 'woocommerce-paypal-payments' ), - ), + 'default' => array_key_first( $subscription_mode_options ), + 'options' => $subscription_mode_options, 'screens' => array( State::STATE_ONBOARDED, ), @@ -455,7 +485,7 @@ return array( $onboarding_options_renderer = $container->get( 'onboarding.render-options' ); assert( $onboarding_options_renderer instanceof OnboardingOptionsRenderer ); - $subscription_helper = $container->get( 'subscription.helper' ); + $subscription_helper = $container->get( 'wc-subscriptions.helper' ); assert( $subscription_helper instanceof SubscriptionHelper ); $fields = array( @@ -898,11 +928,6 @@ return array( unset( $fields['subscriptions_mode'] ); } - $billing_agreements_endpoint = $container->get( 'api.endpoint.billing-agreements' ); - if ( ! $billing_agreements_endpoint->reference_transaction_enabled() ) { - unset( $fields['vault_enabled'] ); - } - /** * Depending on your store location, some credit cards can't be used. * Here, we filter them out. @@ -931,20 +956,19 @@ return array( 'wcgateway.all-funding-sources' => static function( ContainerInterface $container ): array { return array( - 'card' => _x( 'Credit or debit cards', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'sepa' => _x( 'SEPA-Lastschrift', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'bancontact' => _x( 'Bancontact', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'blik' => _x( 'BLIK', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'eps' => _x( 'eps', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'giropay' => _x( 'giropay', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'ideal' => _x( 'iDEAL', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'mercadopago' => _x( 'Mercado Pago', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'mybank' => _x( 'MyBank', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'p24' => _x( 'Przelewy24', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'sofort' => _x( 'Sofort', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'venmo' => _x( 'Venmo', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'trustly' => _x( 'Trustly', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'paylater' => _x( 'Pay Later', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'card' => _x( 'Credit or debit cards', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'sepa' => _x( 'SEPA-Lastschrift', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'bancontact' => _x( 'Bancontact', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'blik' => _x( 'BLIK', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'eps' => _x( 'eps', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'giropay' => _x( 'giropay', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'ideal' => _x( 'iDEAL', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'mybank' => _x( 'MyBank', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'p24' => _x( 'Przelewy24', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'venmo' => _x( 'Venmo', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'trustly' => _x( 'Trustly', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'paylater' => _x( 'PayPal Pay Later', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'paypal' => _x( 'PayPal', 'Name of payment method', 'woocommerce-paypal-payments' ), ); }, @@ -967,6 +991,7 @@ return array( array_flip( array( 'paylater', + 'paypal', ) ) ); @@ -1003,6 +1028,13 @@ return array( $container->get( 'woocommerce.logger.woocommerce' ) ); }, + 'wcgateway.endpoint.refresh-feature-status' => static function ( ContainerInterface $container ) : RefreshFeatureStatusEndpoint { + return new RefreshFeatureStatusEndpoint( + $container->get( 'wcgateway.settings' ), + new Cache( 'ppcp-timeout' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, 'wcgateway.transaction-url-sandbox' => static function ( ContainerInterface $container ): string { return 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s'; @@ -1180,7 +1212,16 @@ return array( */ return apply_filters( 'woocommerce_paypal_payments_place_order_button_text', - __( 'Pay with PayPal', 'woocommerce-paypal-payments' ) + __( 'Proceed to PayPal', 'woocommerce-paypal-payments' ) + ); + }, + 'wcgateway.place-order-button-description' => function ( ContainerInterface $container ) : string { + /** + * The text for additional description, when the "Place order" button mode is enabled. + */ + return apply_filters( + 'woocommerce_paypal_payments_place_order_button_description', + __( 'Clicking "Proceed to PayPal" will redirect you to PayPal to complete your purchase.', 'woocommerce-paypal-payments' ) ); }, @@ -1298,6 +1339,12 @@ return array( 'wcgateway.enable-pui-url-live' => static function ( ContainerInterface $container ): string { return 'https://www.paypal.com/bizsignup/entry?country.x=DE&product=payment_methods&capabilities=PAY_UPON_INVOICE'; }, + 'wcgateway.enable-reference-transactions-url-sandbox' => static function ( ContainerInterface $container ): string { + return 'https://www.sandbox.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING'; + }, + 'wcgateway.enable-reference-transactions-url-live' => static function ( ContainerInterface $container ): string { + return 'https://www.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING'; + }, 'wcgateway.settings.connection.dcc-status-text' => static function ( ContainerInterface $container ): string { $state = $container->get( 'onboarding.state' ); if ( $state->current_state() < State::STATE_ONBOARDED ) { @@ -1336,6 +1383,39 @@ return array( esc_html( $dcc_button_text ) ); }, + 'wcgateway.settings.connection.reference-transactions-status-text' => static function ( ContainerInterface $container ): string { + $environment = $container->get( 'onboarding.environment' ); + assert( $environment instanceof Environment ); + + $billing_agreements_endpoint = $container->get( 'api.endpoint.billing-agreements' ); + assert( $billing_agreements_endpoint instanceof BillingAgreementsEndpoint ); + + $enabled = $billing_agreements_endpoint->reference_transaction_enabled(); + + $enabled_status_text = esc_html__( 'Status: Available', 'woocommerce-paypal-payments' ); + $disabled_status_text = esc_html__( 'Status: Not yet enabled', 'woocommerce-paypal-payments' ); + + $button_text = $enabled + ? esc_html__( 'Settings', 'woocommerce-paypal-payments' ) + : esc_html__( 'Enable Advanced PayPal Wallet', 'woocommerce-paypal-payments' ); + + $enable_url = $environment->current_environment_is( Environment::PRODUCTION ) + ? $container->get( 'wcgateway.enable-reference-transactions-url-live' ) + : $container->get( 'wcgateway.enable-reference-transactions-url-sandbox' ); + + $button_url = $enabled + ? admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway#field-paypal_saved_payments' ) + : $enable_url; + + return sprintf( + '

%1$s %2$s

%5$s

', + $enabled ? $enabled_status_text : $disabled_status_text, + $enabled ? '' : '', + $enabled ? '_self' : '_blank', + esc_url( $button_url ), + esc_html( $button_text ) + ); + }, 'wcgateway.settings.connection.pui-status-text' => static function ( ContainerInterface $container ): string { $state = $container->get( 'onboarding.state' ); if ( $state->current_state() < State::STATE_ONBOARDED ) { @@ -1383,8 +1463,8 @@ return array( 'wcgateway.button.locations' => static function( ContainerInterface $container ): array { return array( 'product' => 'Single Product', - 'cart' => 'Cart', - 'checkout' => 'Checkout', + 'cart' => 'Classic Cart', + 'checkout' => 'Classic Checkout', 'mini-cart' => 'Mini Cart', ); }, @@ -1513,4 +1593,17 @@ return array( ) ); }, + 'wcgateway.endpoint.capture-card-payment' => static function( ContainerInterface $container ): CaptureCardPayment { + return new CaptureCardPayment( + $container->get( 'api.host' ), + $container->get( 'api.bearer' ), + $container->get( 'api.factory.order' ), + $container->get( 'api.factory.purchase-unit' ), + $container->get( 'api.endpoint.order' ), + $container->get( 'session.handler' ), + $container->get( 'wc-subscriptions.helpers.real-time-account-updater' ), + $container->get( 'wcgateway.settings' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, ); diff --git a/modules/ppcp-wc-gateway/src/Admin/RenderAuthorizeAction.php b/modules/ppcp-wc-gateway/src/Admin/RenderAuthorizeAction.php index 1d38e64a6..4185f6125 100644 --- a/modules/ppcp-wc-gateway/src/Admin/RenderAuthorizeAction.php +++ b/modules/ppcp-wc-gateway/src/Admin/RenderAuthorizeAction.php @@ -9,9 +9,6 @@ declare( strict_types=1 ); namespace WooCommerce\PayPalCommerce\WcGateway\Admin; -use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; -use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; - /** * Class RenderAuthorizeAction */ diff --git a/modules/ppcp-wc-gateway/src/Admin/RenderReauthorizeAction.php b/modules/ppcp-wc-gateway/src/Admin/RenderReauthorizeAction.php new file mode 100644 index 000000000..71dbed0ff --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Admin/RenderReauthorizeAction.php @@ -0,0 +1,67 @@ +column = $column; + } + + /** + * Renders the action into the $order_actions array based on the WooCommerce order. + * + * @param array $order_actions The actions to render into. + * @param \WC_Order $wc_order The order for which to render the action. + * + * @return array + */ + public function render( array $order_actions, \WC_Order $wc_order ) : array { + + if ( ! $this->should_render_for_order( $wc_order ) ) { + return $order_actions; + } + + $order_actions['ppcp_reauthorize_order'] = esc_html__( + 'Reauthorize PayPal payment', + 'woocommerce-paypal-payments' + ); + return $order_actions; + } + + /** + * Whether the action should be rendered for a certain WooCommerce order. + * + * @param \WC_Order $order The Woocommerce order. + * + * @return bool + */ + private function should_render_for_order( \WC_Order $order ) : bool { + $status = $order->get_status(); + $not_allowed_statuses = array( 'refunded', 'cancelled', 'failed' ); + return $this->column->should_render_for_order( $order ) && + ! $this->column->is_captured( $order ) && + ! in_array( $status, $not_allowed_statuses, true ); + } +} diff --git a/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php b/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php index db2bdd68a..0abe5d0c8 100644 --- a/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php +++ b/modules/ppcp-wc-gateway/src/Assets/SettingsPageAssets.php @@ -9,8 +9,10 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway\Assets; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint; use WooCommerce\PayPalCommerce\Onboarding\Environment; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcGateway\Endpoint\RefreshFeatureStatusEndpoint; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; @@ -103,21 +105,29 @@ class SettingsPageAssets { */ private $is_acdc_enabled; + /** + * Billing Agreements endpoint. + * + * @var BillingAgreementsEndpoint + */ + private $billing_agreements_endpoint; + /** * Assets constructor. * - * @param string $module_url The url of this module. - * @param string $version The assets version. - * @param SubscriptionHelper $subscription_helper The subscription helper. - * @param string $client_id The PayPal SDK client ID. - * @param string $currency 3-letter currency code of the shop. - * @param string $country 2-letter country code of the shop. - * @param Environment $environment The environment object. - * @param bool $is_pay_later_button_enabled Whether Pay Later button is enabled either for checkout, cart or product page. - * @param array $disabled_sources The list of disabled funding sources. - * @param array $all_funding_sources The list of all existing funding sources. - * @param bool $is_settings_page Whether it's a settings page of this plugin. - * @param bool $is_acdc_enabled Whether the ACDC gateway is enabled. + * @param string $module_url The url of this module. + * @param string $version The assets version. + * @param SubscriptionHelper $subscription_helper The subscription helper. + * @param string $client_id The PayPal SDK client ID. + * @param string $currency 3-letter currency code of the shop. + * @param string $country 2-letter country code of the shop. + * @param Environment $environment The environment object. + * @param bool $is_pay_later_button_enabled Whether Pay Later button is enabled either for checkout, cart or product page. + * @param array $disabled_sources The list of disabled funding sources. + * @param array $all_funding_sources The list of all existing funding sources. + * @param bool $is_settings_page Whether it's a settings page of this plugin. + * @param bool $is_acdc_enabled Whether the ACDC gateway is enabled. + * @param BillingAgreementsEndpoint $billing_agreements_endpoint Billing Agreements endpoint. */ public function __construct( string $module_url, @@ -131,7 +141,8 @@ class SettingsPageAssets { array $disabled_sources, array $all_funding_sources, bool $is_settings_page, - bool $is_acdc_enabled + bool $is_acdc_enabled, + BillingAgreementsEndpoint $billing_agreements_endpoint ) { $this->module_url = $module_url; $this->version = $version; @@ -145,6 +156,7 @@ class SettingsPageAssets { $this->all_funding_sources = $all_funding_sources; $this->is_settings_page = $is_settings_page; $this->is_acdc_enabled = $is_acdc_enabled; + $this->billing_agreements_endpoint = $billing_agreements_endpoint; } /** @@ -237,6 +249,24 @@ class SettingsPageAssets { 'disabled_sources' => $this->disabled_sources, 'all_funding_sources' => $this->all_funding_sources, 'components' => array( 'buttons', 'funding-eligibility', 'messages' ), + 'ajax' => array( + 'refresh_feature_status' => array( + 'endpoint' => \WC_AJAX::get_endpoint( RefreshFeatureStatusEndpoint::ENDPOINT ), + 'nonce' => wp_create_nonce( RefreshFeatureStatusEndpoint::nonce() ), + 'button' => '.ppcp-refresh-feature-status', + 'messages' => array( + 'waiting' => __( 'Checking features...', 'woocommerce-paypal-payments' ), + 'success' => __( 'Feature status refreshed.', 'woocommerce-paypal-payments' ), + ), + ), + ), + 'reference_transaction_enabled' => $this->billing_agreements_endpoint->reference_transaction_enabled(), + 'vaulting_must_enable_advanced_wallet_message' => sprintf( + // translators: %1$s and %2$s are the opening and closing of HTML tag. + esc_html__( 'Your PayPal account must be enabled for the %1$sAdvanced PayPal Wallet%2$s to use PayPal Vaulting.', 'woocommerce-paypal-payments' ), + '', + '' + ), ) ) ); diff --git a/modules/ppcp-wc-gateway/src/Checkout/DisableGateways.php b/modules/ppcp-wc-gateway/src/Checkout/DisableGateways.php index 6afa24f31..de07ecfef 100644 --- a/modules/ppcp-wc-gateway/src/Checkout/DisableGateways.php +++ b/modules/ppcp-wc-gateway/src/Checkout/DisableGateways.php @@ -11,7 +11,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Checkout; use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait; use WooCommerce\PayPalCommerce\Session\SessionHandler; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; diff --git a/modules/ppcp-wc-gateway/src/Endpoint/CaptureCardPayment.php b/modules/ppcp-wc-gateway/src/Endpoint/CaptureCardPayment.php new file mode 100644 index 000000000..bfb8b4bc4 --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Endpoint/CaptureCardPayment.php @@ -0,0 +1,186 @@ +host = $host; + $this->bearer = $bearer; + $this->order_factory = $order_factory; + $this->purchase_unit_factory = $purchase_unit_factory; + $this->order_endpoint = $order_endpoint; + $this->session_handler = $session_handler; + $this->real_time_account_updater_helper = $real_time_account_updater_helper; + $this->settings = $settings; + $this->logger = $logger; + } + + /** + * Creates PayPal order from the given card vault id. + * + * @param string $vault_id Vault id. + * @param string $custom_id Custom id. + * @param string $invoice_id Invoice id. + * @return stdClass + * @throws RuntimeException When request fails. + */ + public function create_order( string $vault_id, string $custom_id, string $invoice_id ): stdClass { + $intent = $this->settings->has( 'intent' ) && strtoupper( (string) $this->settings->get( 'intent' ) ) === 'AUTHORIZE' ? 'AUTHORIZE' : 'CAPTURE'; + $items = array( $this->purchase_unit_factory->from_wc_cart() ); + + $data = array( + 'intent' => $intent, + 'purchase_units' => array_map( + static function ( PurchaseUnit $item ): array { + return $item->to_array( true, false ); + }, + $items + ), + 'payment_source' => array( + 'card' => array( + 'vault_id' => $vault_id, + 'stored_credential' => array( + 'payment_initiator' => 'CUSTOMER', + 'payment_type' => 'UNSCHEDULED', + 'usage' => 'SUBSEQUENT', + ), + ), + ), + 'custom_id' => $custom_id, + 'invoice_id' => $invoice_id, + ); + + $bearer = $this->bearer->bearer(); + $url = trailingslashit( $this->host ) . 'v2/checkout/orders'; + $args = array( + 'method' => 'POST', + 'headers' => array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + 'PayPal-Request-Id' => uniqid( 'ppcp-', true ), + ), + 'body' => wp_json_encode( $data ), + ); + + $response = $this->request( $url, $args ); + if ( $response instanceof WP_Error ) { + throw new RuntimeException( $response->get_error_message() ); + } + + return json_decode( $response['body'] ); + } +} + diff --git a/modules/ppcp-wc-gateway/src/Endpoint/RefreshFeatureStatusEndpoint.php b/modules/ppcp-wc-gateway/src/Endpoint/RefreshFeatureStatusEndpoint.php new file mode 100644 index 000000000..5831fcb51 --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Endpoint/RefreshFeatureStatusEndpoint.php @@ -0,0 +1,115 @@ +settings = $settings; + $this->cache = $cache; + $this->logger = $logger; + } + + /** + * Returns the nonce. + * + * @return string + */ + public static function nonce(): string { + return self::ENDPOINT; + } + + /** + * Handles the incoming request. + */ + public function handle_request(): void { + $now = time(); + $last_request_time = $this->cache->get( self::CACHE_KEY ) ?: 0; + $seconds_missing = $last_request_time + self::TIMEOUT - $now; + + if ( ! $this->verify_nonce() ) { + wp_send_json_error( + array( + 'message' => __( 'Expired request.', 'woocommerce-paypal-payments' ), + ) + ); + } + + if ( $seconds_missing > 0 ) { + wp_send_json_error( + array( + 'message' => sprintf( + // translators: %1$s is the number of seconds remaining. + __( 'Wait %1$s seconds before trying again.', 'woocommerce-paypal-payments' ), + $seconds_missing + ), + ) + ); + } + + $this->cache->set( self::CACHE_KEY, $now, self::TIMEOUT ); + do_action( 'woocommerce_paypal_payments_clear_apm_product_status', $this->settings ); + wp_send_json_success(); + } + + /** + * Verifies the nonce. + * + * @return bool + */ + private function verify_nonce(): bool { + $json = json_decode( file_get_contents( 'php://input' ) ?: '', true ); + return wp_verify_nonce( $json['nonce'] ?? '', self::nonce() ) !== false; + } +} diff --git a/modules/ppcp-wc-gateway/src/FundingSource/FundingSourceRenderer.php b/modules/ppcp-wc-gateway/src/FundingSource/FundingSourceRenderer.php index a465db721..cdfcb3b47 100644 --- a/modules/ppcp-wc-gateway/src/FundingSource/FundingSourceRenderer.php +++ b/modules/ppcp-wc-gateway/src/FundingSource/FundingSourceRenderer.php @@ -34,7 +34,7 @@ class FundingSourceRenderer { * * @var string[] */ - protected $own_funding_sources = array( 'venmo', 'paylater' ); + protected $own_funding_sources = array( 'venmo', 'paylater', 'paypal' ); /** * FundingSourceRenderer constructor. @@ -56,12 +56,14 @@ class FundingSourceRenderer { * @param string $id The ID of the funding source, such as 'venmo'. */ public function render_name( string $id ): string { + $id = $this->sanitize_id( $id ); + if ( array_key_exists( $id, $this->funding_sources ) ) { if ( in_array( $id, $this->own_funding_sources, true ) ) { return $this->funding_sources[ $id ]; } return sprintf( - /* translators: %s - Sofort, BLIK, iDeal, Mercado Pago, etc. */ + /* translators: %s - BLIK, iDeal, Mercado Pago, etc. */ __( '%s (via PayPal)', 'woocommerce-paypal-payments' ), $this->funding_sources[ $id ] ); @@ -78,9 +80,11 @@ class FundingSourceRenderer { * @param string $id The ID of the funding source, such as 'venmo'. */ public function render_description( string $id ): string { + $id = $this->sanitize_id( $id ); + if ( array_key_exists( $id, $this->funding_sources ) ) { return sprintf( - /* translators: %s - Sofort, BLIK, iDeal, Mercado Pago, etc. */ + /* translators: %s - BLIK, iDeal, Mercado Pago, etc. */ __( 'Pay via %s.', 'woocommerce-paypal-payments' ), $this->funding_sources[ $id ] ); @@ -90,4 +94,14 @@ class FundingSourceRenderer { $this->settings->get( 'description' ) : __( 'Pay via PayPal.', 'woocommerce-paypal-payments' ); } + + /** + * Sanitizes the id to a standard format. + * + * @param string $id The funding source id. + * @return string + */ + private function sanitize_id( string $id ): string { + return str_replace( '_', '', strtolower( $id ) ); + } } diff --git a/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php b/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php index 2f2f17680..58bc4abfe 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/CardButtonGateway.php @@ -17,8 +17,8 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; -use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException; use WooCommerce\PayPalCommerce\WcGateway\Exception\PayPalOrderMissingException; diff --git a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php index 78012b2d7..6e21e70df 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php @@ -11,28 +11,37 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Gateway; use Exception; use Psr\Log\LoggerInterface; -use WC_Customer; use WC_Order; +use WC_Payment_Tokens; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; use WooCommerce\PayPalCommerce\Vaulting\VaultedCreditCardHandler; -use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException; -use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor; -use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; -use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer; +use WooCommerce\PayPalCommerce\Vaulting\WooCommercePaymentTokens; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\WcGateway\Endpoint\CaptureCardPayment; +use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException; +use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; +use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor; +use WooCommerce\PayPalCommerce\WcGateway\Processor\PaymentsStatusHandlingTrait; +use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; +use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait; +use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer; +use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; /** * Class CreditCardGateway */ class CreditCardGateway extends \WC_Payment_Gateway_CC { - use ProcessPaymentTrait, GatewaySettingsRendererTrait; + use ProcessPaymentTrait, GatewaySettingsRendererTrait, TransactionIdHandlingTrait, PaymentsStatusHandlingTrait, FreeTrialHandlerTrait; const ID = 'ppcp-credit-card-gateway'; @@ -113,13 +122,6 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { */ protected $subscription_helper; - /** - * The logger. - * - * @var LoggerInterface - */ - protected $logger; - /** * The payments endpoint * @@ -127,6 +129,55 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { */ protected $payments_endpoint; + /** + * The environment. + * + * @var Environment + */ + private $environment; + + /** + * The order endpoint. + * + * @var OrderEndpoint + */ + private $order_endpoint; + + /** + * Capture card payment. + * + * @var CaptureCardPayment + */ + private $capture_card_payment; + + /** + * The prefix. + * + * @var string + */ + private $prefix; + + /** + * Payment tokens endpoint. + * + * @var PaymentTokensEndpoint + */ + private $payment_tokens_endpoint; + + /** + * WooCommerce payment tokens factory. + * + * @var WooCommercePaymentTokens + */ + private $wc_payment_tokens; + + /** + * The logger. + * + * @var LoggerInterface + */ + protected $logger; + /** * CreditCardGateway constructor. * @@ -139,9 +190,15 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { * @param State $state The state. * @param TransactionUrlProvider $transaction_url_provider Service able to provide view transaction url base. * @param SubscriptionHelper $subscription_helper The subscription helper. - * @param LoggerInterface $logger The logger. * @param PaymentsEndpoint $payments_endpoint The payments endpoint. * @param VaultedCreditCardHandler $vaulted_credit_card_handler The vaulted credit card handler. + * @param Environment $environment The environment. + * @param OrderEndpoint $order_endpoint The order endpoint. + * @param CaptureCardPayment $capture_card_payment Capture card payment. + * @param string $prefix The prefix. + * @param PaymentTokensEndpoint $payment_tokens_endpoint Payment tokens endpoint. + * @param WooCommercePaymentTokens $wc_payment_tokens WooCommerce payment tokens factory. + * @param LoggerInterface $logger The logger. */ public function __construct( SettingsRenderer $settings_renderer, @@ -153,9 +210,15 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { State $state, TransactionUrlProvider $transaction_url_provider, SubscriptionHelper $subscription_helper, - LoggerInterface $logger, PaymentsEndpoint $payments_endpoint, - VaultedCreditCardHandler $vaulted_credit_card_handler + VaultedCreditCardHandler $vaulted_credit_card_handler, + Environment $environment, + OrderEndpoint $order_endpoint, + CaptureCardPayment $capture_card_payment, + string $prefix, + PaymentTokensEndpoint $payment_tokens_endpoint, + WooCommercePaymentTokens $wc_payment_tokens, + LoggerInterface $logger ) { $this->id = self::ID; $this->settings_renderer = $settings_renderer; @@ -167,9 +230,15 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { $this->state = $state; $this->transaction_url_provider = $transaction_url_provider; $this->subscription_helper = $subscription_helper; - $this->logger = $logger; $this->payments_endpoint = $payments_endpoint; $this->vaulted_credit_card_handler = $vaulted_credit_card_handler; + $this->environment = $environment; + $this->order_endpoint = $order_endpoint; + $this->capture_card_payment = $capture_card_payment; + $this->prefix = $prefix; + $this->payment_tokens_endpoint = $payment_tokens_endpoint; + $this->wc_payment_tokens = $wc_payment_tokens; + $this->logger = $logger; if ( $state->current_state() === State::STATE_ONBOARDED ) { $this->supports = array( 'refunds' ); @@ -181,18 +250,25 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { ); if ( $this->config->has( 'vault_enabled_dcc' ) && $this->config->get( 'vault_enabled_dcc' ) ) { - array_push( + $supports = apply_filters( + 'woocommerce_paypal_payments_credit_card_gateway_vault_supports', + array( + 'subscriptions', + 'subscription_cancellation', + 'subscription_suspension', + 'subscription_reactivation', + 'subscription_amount_changes', + 'subscription_date_changes', + 'subscription_payment_method_change', + 'subscription_payment_method_change_customer', + 'subscription_payment_method_change_admin', + 'multiple_subscriptions', + ) + ); + + $this->supports = array_merge( $this->supports, - 'subscriptions', - 'subscription_cancellation', - 'subscription_suspension', - 'subscription_reactivation', - 'subscription_amount_changes', - 'subscription_date_changes', - 'subscription_payment_method_change', - 'subscription_payment_method_change_customer', - 'subscription_payment_method_change_admin', - 'multiple_subscriptions' + $supports ); } } @@ -238,8 +314,10 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { */ public function form() { add_action( 'gettext', array( $this, 'replace_credit_card_cvv_label' ), 10, 3 ); + add_action( 'gettext', array( $this, 'replace_credit_card_cvv_placeholder' ), 10, 3 ); parent::form(); remove_action( 'gettext', 'replace_credit_card_cvv_label' ); + remove_action( 'gettext', 'replace_credit_card_cvv_placeholder' ); } /** @@ -259,6 +337,23 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { return __( 'CVV', 'woocommerce-paypal-payments' ); } + /** + * Replace WooCommerce credit card CVV field placeholder. + * + * @param string $translation Translated text. + * @param string $text Original text to translate. + * @param string $domain Text domain. + * + * @return string Translated field. + */ + public function replace_credit_card_cvv_placeholder( string $translation, string $text, string $domain ): string { + if ( 'woocommerce' !== $domain || 'CVC' !== $text || ! apply_filters( 'woocommerce_paypal_payments_card_fields_translate_card_cvv', true ) ) { + return $translation; + } + + return __( 'CVV', 'woocommerce-paypal-payments' ); + } + /** * Returns the icons of the gateway. * @@ -358,12 +453,76 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { ); } + // phpcs:ignore WordPress.Security.NonceVerification.Missing + $card_payment_token_id = wc_clean( wp_unslash( $_POST['wc-ppcp-credit-card-gateway-payment-token'] ?? '' ) ); + + if ( $this->is_free_trial_order( $wc_order ) && $card_payment_token_id ) { + $customer_tokens = $this->wc_payment_tokens->customer_tokens( get_current_user_id() ); + foreach ( $customer_tokens as $token ) { + if ( $token['payment_source']->name() === 'card' ) { + $wc_order->payment_complete(); + return $this->handle_payment_success( $wc_order ); + } + } + } + + if ( $card_payment_token_id ) { + $customer_tokens = $this->wc_payment_tokens->customer_tokens( get_current_user_id() ); + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), self::ID ); + + if ( $customer_tokens && empty( $wc_tokens ) ) { + $this->wc_payment_tokens->create_wc_tokens( $customer_tokens, get_current_user_id() ); + } + + $customer_token_ids = array(); + foreach ( $customer_tokens as $customer_token ) { + $customer_token_ids[] = $customer_token['id']; + } + + $tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id() ); + foreach ( $tokens as $token ) { + if ( $token->get_id() === (int) $card_payment_token_id ) { + if ( ! in_array( $token->get_token(), $customer_token_ids, true ) ) { + $token->delete(); + continue; + } + + $custom_id = $wc_order->get_order_number(); + $invoice_id = $this->prefix . $wc_order->get_order_number(); + $create_order = $this->capture_card_payment->create_order( $token->get_token(), $custom_id, $invoice_id ); + + $order = $this->order_endpoint->order( $create_order->id ); + $wc_order->update_meta_data( PayPalGateway::INTENT_META_KEY, $order->intent() ); + + if ( $order->intent() === 'AUTHORIZE' ) { + $order = $this->order_endpoint->authorize( $order ); + + $wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'false' ); + + if ( $this->subscription_helper->has_subscription( $wc_order->get_id() ) ) { + $wc_order->update_meta_data( '_ppcp_captured_vault_webhook', 'false' ); + } + } + + $transaction_id = $this->get_paypal_order_transaction_id( $order ); + if ( $transaction_id ) { + $this->update_transaction_id( $transaction_id, $wc_order ); + } + + $this->handle_new_order_status( $order, $wc_order ); + + return $this->handle_payment_success( $wc_order ); + } + } + } + /** - * If customer has chosen a saved credit card payment. + * If customer has chosen a saved credit card payment from checkout page. */ // phpcs:ignore WordPress.Security.NonceVerification.Missing $saved_credit_card = wc_clean( wp_unslash( $_POST['saved_credit_card'] ?? '' ) ); - if ( $saved_credit_card ) { + if ( $saved_credit_card && is_checkout() ) { try { $wc_order = $this->vaulted_credit_card_handler->handle_payment( $saved_credit_card, @@ -377,6 +536,40 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC { } } + /** + * If customer is changing subscription payment. + */ + if ( + // phpcs:disable WordPress.Security.NonceVerification.Missing + isset( $_POST['woocommerce_change_payment'] ) + && $this->subscription_helper->has_subscription( $wc_order->get_id() ) + && $this->subscription_helper->is_subscription_change_payment() + ) { + $saved_credit_card = wc_clean( wp_unslash( $_POST['wc-ppcp-credit-card-gateway-payment-token'] ?? '' ) ); + if ( ! $saved_credit_card ) { + $saved_credit_card = wc_clean( wp_unslash( $_POST['saved_credit_card'] ?? '' ) ); + // phpcs:enable WordPress.Security.NonceVerification.Missing + } + + if ( $saved_credit_card ) { + $payment_token = WC_Payment_Tokens::get( $saved_credit_card ); + if ( $payment_token ) { + $wc_order->add_payment_token( $payment_token ); + $wc_order->save(); + + return $this->handle_payment_success( $wc_order ); + } + } + + wc_add_notice( __( 'Could not change payment.', 'woocommerce-paypal-payments' ), 'error' ); + + return array( + 'result' => 'failure', + 'redirect' => wc_get_checkout_url(), + 'errorMessage' => __( 'Could not change payment.', 'woocommerce-paypal-payments' ), + ); + } + /** * If the WC_Order is paid through the approved webhook. */ diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php b/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php index 297198ba9..6c6568b8d 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php @@ -12,16 +12,18 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Gateway; use Exception; use Psr\Log\LoggerInterface; use WC_Order; +use WC_Payment_Tokens; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; -use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; -use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\Vaulting\WooCommercePaymentTokens; +use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException; use WooCommerce\PayPalCommerce\WcGateway\Exception\PayPalOrderMissingException; @@ -48,9 +50,17 @@ class PayPalGateway extends \WC_Payment_Gateway { const ORDER_ID_META_KEY = '_ppcp_paypal_order_id'; const ORDER_PAYMENT_MODE_META_KEY = '_ppcp_paypal_payment_mode'; const ORDER_PAYMENT_SOURCE_META_KEY = '_ppcp_paypal_payment_source'; + const ORDER_PAYER_EMAIL_META_KEY = '_ppcp_paypal_payer_email'; const FEES_META_KEY = '_ppcp_paypal_fees'; const REFUND_FEES_META_KEY = '_ppcp_paypal_refund_fees'; const REFUNDS_META_KEY = '_ppcp_refunds'; + const THREE_D_AUTH_RESULT_META_KEY = '_ppcp_paypal_3DS_auth_result'; + const FRAUD_RESULT_META_KEY = '_ppcp_paypal_fraud_result'; + + /** + * List of payment sources wich we are expected to store the payer email in the WC Order metadata. + */ + const PAYMENT_SOURCES_WITH_PAYER_EMAIL = array( 'paypal', 'paylater', 'venmo' ); /** * The Settings Renderer. @@ -171,26 +181,50 @@ class PayPalGateway extends \WC_Payment_Gateway { */ private $paypal_checkout_url_factory; + /** + * Payment tokens endpoint. + * + * @var PaymentTokensEndpoint + */ + private $payment_tokens_endpoint; + + /** + * Whether Vault v3 module is enabled. + * + * @var bool + */ + private $vault_v3_enabled; + + /** + * WooCommerce payment tokens. + * + * @var WooCommercePaymentTokens + */ + private $wc_payment_tokens; + /** * PayPalGateway constructor. * - * @param SettingsRenderer $settings_renderer The Settings Renderer. - * @param FundingSourceRenderer $funding_source_renderer The funding source renderer. - * @param OrderProcessor $order_processor The Order Processor. - * @param ContainerInterface $config The settings. - * @param SessionHandler $session_handler The Session Handler. - * @param RefundProcessor $refund_processor The Refund Processor. - * @param State $state The state. - * @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order. - * @param SubscriptionHelper $subscription_helper The subscription helper. - * @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page. - * @param Environment $environment The environment. - * @param PaymentTokenRepository $payment_token_repository The payment token repository. - * @param LoggerInterface $logger The logger. - * @param string $api_shop_country The api shop country. - * @param OrderEndpoint $order_endpoint The order endpoint. - * @param callable(string):string $paypal_checkout_url_factory The function return the PayPal checkout URL for the given order ID. - * @param string $place_order_button_text The text for the standard "Place order" button. + * @param SettingsRenderer $settings_renderer The Settings Renderer. + * @param FundingSourceRenderer $funding_source_renderer The funding source renderer. + * @param OrderProcessor $order_processor The Order Processor. + * @param ContainerInterface $config The settings. + * @param SessionHandler $session_handler The Session Handler. + * @param RefundProcessor $refund_processor The Refund Processor. + * @param State $state The state. + * @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order. + * @param SubscriptionHelper $subscription_helper The subscription helper. + * @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page. + * @param Environment $environment The environment. + * @param PaymentTokenRepository $payment_token_repository The payment token repository. + * @param LoggerInterface $logger The logger. + * @param string $api_shop_country The api shop country. + * @param OrderEndpoint $order_endpoint The order endpoint. + * @param callable(string):string $paypal_checkout_url_factory The function return the PayPal checkout URL for the given order ID. + * @param string $place_order_button_text The text for the standard "Place order" button. + * @param PaymentTokensEndpoint $payment_tokens_endpoint Payment tokens endpoint. + * @param bool $vault_v3_enabled Whether Vault v3 module is enabled. + * @param WooCommercePaymentTokens $wc_payment_tokens WooCommerce payment tokens. */ public function __construct( SettingsRenderer $settings_renderer, @@ -209,7 +243,10 @@ class PayPalGateway extends \WC_Payment_Gateway { string $api_shop_country, OrderEndpoint $order_endpoint, callable $paypal_checkout_url_factory, - string $place_order_button_text + string $place_order_button_text, + PaymentTokensEndpoint $payment_tokens_endpoint, + bool $vault_v3_enabled, + WooCommercePaymentTokens $wc_payment_tokens ) { $this->id = self::ID; $this->settings_renderer = $settings_renderer; @@ -229,6 +266,10 @@ class PayPalGateway extends \WC_Payment_Gateway { $this->api_shop_country = $api_shop_country; $this->paypal_checkout_url_factory = $paypal_checkout_url_factory; $this->order_button_text = $place_order_button_text; + $this->order_endpoint = $order_endpoint; + $this->payment_tokens_endpoint = $payment_tokens_endpoint; + $this->vault_v3_enabled = $vault_v3_enabled; + $this->wc_payment_tokens = $wc_payment_tokens; if ( $this->onboarded ) { $this->supports = array( 'refunds', 'tokenization' ); @@ -257,6 +298,8 @@ class PayPalGateway extends \WC_Payment_Gateway { 'subscription_payment_method_change_admin', 'multiple_subscriptions' ); + } elseif ( $this->config->has( 'subscriptions_mode' ) && $this->config->get( 'subscriptions_mode' ) === 'subscriptions_api' ) { + $this->supports[] = 'gateway_scheduled_payments'; } elseif ( $this->config->has( 'vault_enabled_dcc' ) && $this->config->get( 'vault_enabled_dcc' ) ) { $this->supports[] = 'tokenization'; } @@ -291,8 +334,6 @@ class PayPalGateway extends \WC_Payment_Gateway { 'process_admin_options', ) ); - - $this->order_endpoint = $order_endpoint; } /** @@ -394,13 +435,7 @@ class PayPalGateway extends \WC_Payment_Gateway { } if ( $this->is_pay_later_tab() ) { - return sprintf( - // translators: %1$s is HTML tag and %2$s, %3$s are the opening and closing of HTML tag. - __( 'Let customers pay over time while you get paid up front — at no additional cost.%1$sPayPal’s pay later options are boosting merchant conversion rates and increasing cart sizes by 39%%. %2$s(PayPal Q2 Earnings-2021.)%3$s', 'woocommerce-paypal-payments' ), - '', - '', - '' - ); + return ''; } if ( is_admin() ) { @@ -498,7 +533,49 @@ class PayPalGateway extends \WC_Payment_Gateway { $wc_order->save(); } - if ( 'card' !== $funding_source && $this->is_free_trial_order( $wc_order ) ) { + if ( + 'card' !== $funding_source + && $this->is_free_trial_order( $wc_order ) + && ! $this->subscription_helper->paypal_subscription_id() + ) { + $ppcp_guest_payment_for_free_trial = WC()->session->get( 'ppcp_guest_payment_for_free_trial' ) ?? null; + if ( $this->vault_v3_enabled && $ppcp_guest_payment_for_free_trial ) { + $customer_id = $ppcp_guest_payment_for_free_trial->customer->id ?? ''; + if ( $customer_id ) { + update_user_meta( $wc_order->get_customer_id(), '_ppcp_target_customer_id', $customer_id ); + } + + if ( isset( $ppcp_guest_payment_for_free_trial->payment_source->paypal ) ) { + $email = ''; + if ( isset( $ppcp_guest_payment_for_free_trial->payment_source->paypal->email_address ) ) { + $email = $ppcp_guest_payment_for_free_trial->payment_source->paypal->email_address; + } + + $this->wc_payment_tokens->create_payment_token_paypal( + $wc_order->get_customer_id(), + $ppcp_guest_payment_for_free_trial->id, + $email + ); + } + + WC()->session->set( 'ppcp_guest_payment_for_free_trial', null ); + + $wc_order->payment_complete(); + return $this->handle_payment_success( $wc_order ); + } + + $customer_id = get_user_meta( $wc_order->get_customer_id(), '_ppcp_target_customer_id', true ); + if ( $customer_id ) { + $customer_tokens = $this->payment_tokens_endpoint->payment_tokens_for_customer( $customer_id ); + foreach ( $customer_tokens as $token ) { + $payment_source_name = $token['payment_source']->name() ?? ''; + if ( $payment_source_name === 'paypal' || $payment_source_name === 'venmo' ) { + $wc_order->payment_complete(); + return $this->handle_payment_success( $wc_order ); + } + } + } + $user_id = (int) $wc_order->get_customer_id(); $tokens = $this->payment_token_repository->all_for_user_id( $user_id ); if ( ! array_filter( @@ -511,7 +588,6 @@ class PayPalGateway extends \WC_Payment_Gateway { } $wc_order->payment_complete(); - return $this->handle_payment_success( $wc_order ); } @@ -522,10 +598,21 @@ class PayPalGateway extends \WC_Payment_Gateway { // phpcs:ignore WordPress.Security.NonceVerification.Missing $saved_paypal_payment = wc_clean( wp_unslash( $_POST['saved_paypal_payment'] ?? '' ) ); if ( $saved_paypal_payment ) { - $wc_order->update_meta_data( 'payment_token_id', $saved_paypal_payment ); - $wc_order->save(); + $payment_token = WC_Payment_Tokens::get( $saved_paypal_payment ); + if ( $payment_token ) { + $wc_order->add_payment_token( $payment_token ); + $wc_order->save(); - return $this->handle_payment_success( $wc_order ); + return $this->handle_payment_success( $wc_order ); + } + + wc_add_notice( __( 'Could not change payment.', 'woocommerce-paypal-payments' ), 'error' ); + + return array( + 'result' => 'failure', + 'redirect' => wc_get_checkout_url(), + 'errorMessage' => __( 'Could not change payment.', 'woocommerce-paypal-payments' ), + ); } } diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php index 20ab81fb6..d4ca29121 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php @@ -198,25 +198,41 @@ class PayUponInvoiceGateway extends WC_Payment_Gateway { 'description' => __( "Specify brand name, logo and customer service instructions to be presented on Ratepay's payment instructions.", 'woocommerce-paypal-payments' ), ), 'brand_name' => array( - 'title' => __( 'Brand name', 'woocommerce-paypal-payments' ), - 'type' => 'text', - 'default' => get_bloginfo( 'name' ) ?? '', - 'desc_tip' => true, - 'description' => __( 'Merchant name displayed in Ratepay\'s payment instructions.', 'woocommerce-paypal-payments' ), + 'title' => __( 'Brand name', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => get_bloginfo( 'name' ) ?? '', + 'desc_tip' => true, + 'description' => __( 'Merchant name displayed in Ratepay\'s payment instructions. Should not exceed 127 characters.', 'woocommerce-paypal-payments' ), + 'maxlength' => 127, + 'custom_attributes' => array( + 'pattern' => '.{1,127}', + 'autocomplete' => 'off', + 'required' => '', + ), ), 'logo_url' => array( - 'title' => __( 'Logo URL', 'woocommerce-paypal-payments' ), - 'type' => 'url', - 'default' => '', - 'desc_tip' => true, - 'description' => __( 'Logo to be presented on Ratepay\'s payment instructions.', 'woocommerce-paypal-payments' ), + 'title' => __( 'Logo URL', 'woocommerce-paypal-payments' ), + 'type' => 'url', + 'default' => '', + 'desc_tip' => true, + 'description' => __( 'Logo to be presented on Ratepay\'s payment instructions.', 'woocommerce-paypal-payments' ), + 'custom_attributes' => array( + 'pattern' => '.+', + 'autocomplete' => 'off', + 'required' => '', + ), ), 'customer_service_instructions' => array( - 'title' => __( 'Customer service instructions', 'woocommerce-paypal-payments' ), - 'type' => 'text', - 'default' => '', - 'desc_tip' => true, - 'description' => __( 'Customer service instructions to be presented on Ratepay\'s payment instructions.', 'woocommerce-paypal-payments' ), + 'title' => __( 'Customer service instructions', 'woocommerce-paypal-payments' ), + 'type' => 'text', + 'default' => '', + 'desc_tip' => true, + 'description' => __( 'Customer service instructions to be presented on Ratepay\'s payment instructions.', 'woocommerce-paypal-payments' ), + 'custom_attributes' => array( + 'pattern' => '.+', + 'autocomplete' => 'off', + 'required' => '', + ), ), ); } diff --git a/modules/ppcp-wc-gateway/src/Helper/CheckoutHelper.php b/modules/ppcp-wc-gateway/src/Helper/CheckoutHelper.php index bd21df4c2..1347e6797 100644 --- a/modules/ppcp-wc-gateway/src/Helper/CheckoutHelper.php +++ b/modules/ppcp-wc-gateway/src/Helper/CheckoutHelper.php @@ -91,24 +91,14 @@ class CheckoutHelper { /** * Ensures product is neither downloadable nor virtual. * - * @param WC_Product $product WC product. + * @param WC_Product $product WC product (can be a variation). * @return bool */ - public function is_physical_product( WC_Product $product ):bool { + public function is_physical_product( WC_Product $product ): bool { if ( $product->is_downloadable() || $product->is_virtual() ) { return false; } - if ( is_a( $product, WC_Product_Variable::class ) ) { - foreach ( $product->get_available_variations( 'object' ) as $variation ) { - if ( is_a( $variation, WC_Product_Variation::class ) ) { - if ( true === $variation->is_downloadable() || true === $variation->is_virtual() ) { - return false; - } - } - } - } - return true; } } diff --git a/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php b/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php index 772a76e3a..3ca5b9998 100644 --- a/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php +++ b/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php @@ -186,4 +186,30 @@ class DCCProductStatus { return $this->has_request_failure; } + /** + * Clears the persisted result to force a recheck. + * + * @param Settings|null $settings The settings object. + * We accept a Settings object to don't override other sequential settings that are being updated elsewhere. + * @return void + */ + public function clear( Settings $settings = null ): void { + if ( null === $settings ) { + $settings = $this->settings; + } + + // Unset check stored in memory. + $this->current_status_cache = null; + + // Unset settings flag. + $settings_key = 'products_dcc_enabled'; + if ( $settings->has( $settings_key ) ) { + $settings->set( $settings_key, false ); + $settings->persist(); + } + + // Delete cached value. + $this->cache->delete( self::DCC_STATUS_CACHE_KEY ); + } + } diff --git a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceHelper.php b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceHelper.php index 8ba589789..823caf611 100644 --- a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceHelper.php +++ b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceHelper.php @@ -98,7 +98,11 @@ class PayUponInvoiceHelper { if ( $cart && ! is_checkout_pay_page() ) { $items = $cart->get_cart_contents(); foreach ( $items as $item ) { - $product = wc_get_product( $item['product_id'] ); + $product_id = $item['product_id']; + if ( isset( $item['variation_id'] ) && $item['variation_id'] ) { + $product_id = $item['variation_id']; + } + $product = wc_get_product( $product_id ); if ( $product && ! $this->checkout_helper->is_physical_product( $product ) ) { return false; } diff --git a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php index f1a3221eb..dfbcb0380 100644 --- a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php +++ b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php @@ -173,4 +173,30 @@ class PayUponInvoiceProductStatus { return $this->has_request_failure; } + /** + * Clears the persisted result to force a recheck. + * + * @param Settings|null $settings The settings object. + * We accept a Settings object to don't override other sequential settings that are being updated elsewhere. + * @return void + */ + public function clear( Settings $settings = null ): void { + if ( null === $settings ) { + $settings = $this->settings; + } + + // Unset check stored in memory. + $this->current_status_cache = null; + + // Unset settings flag. + $settings_key = 'products_pui_enabled'; + if ( $settings->has( $settings_key ) ) { + $settings->set( $settings_key, false ); + $settings->persist(); + } + + // Delete cached value. + $this->cache->delete( self::PUI_STATUS_CACHE_KEY ); + } + } diff --git a/modules/ppcp-wc-gateway/src/Helper/SettingsStatus.php b/modules/ppcp-wc-gateway/src/Helper/SettingsStatus.php index d1f848d19..502d7f1dc 100644 --- a/modules/ppcp-wc-gateway/src/Helper/SettingsStatus.php +++ b/modules/ppcp-wc-gateway/src/Helper/SettingsStatus.php @@ -33,15 +33,19 @@ class SettingsStatus { } /** - * Check whether Pay Later message is enabled either for checkout, cart or product page. - * - * @return bool true if is enabled, otherwise false. + * Checks whether Pay Later messaging is enabled. */ public function is_pay_later_messaging_enabled(): bool { - $messaging_enabled = $this->settings->has( 'pay_later_messaging_enabled' ) && $this->settings->get( 'pay_later_messaging_enabled' ); + return $this->settings->has( 'pay_later_messaging_enabled' ) && $this->settings->get( 'pay_later_messaging_enabled' ); + } + + /** + * Check whether any Pay Later messaging location is enabled. + */ + public function has_pay_later_messaging_locations(): bool { $selected_locations = $this->settings->has( 'pay_later_messaging_locations' ) ? $this->settings->get( 'pay_later_messaging_locations' ) : array(); - return $messaging_enabled && ! empty( $selected_locations ); + return ! empty( $selected_locations ); } /** @@ -51,7 +55,9 @@ class SettingsStatus { * @return bool true if is enabled, otherwise false. */ public function is_pay_later_messaging_enabled_for_location( string $location ): bool { - return $this->is_pay_later_messaging_enabled() && $this->is_enabled_for_location( 'pay_later_messaging_locations', $location ); + return $this->is_pay_later_messaging_enabled() && + $this->has_pay_later_messaging_locations() && + $this->is_enabled_for_location( 'pay_later_messaging_locations', $location ); } /** @@ -85,6 +91,9 @@ class SettingsStatus { * @return bool true if is enabled, otherwise false. */ public function is_smart_button_enabled_for_location( string $location ): bool { + if ( $location === 'block-editor' ) { + $location = 'checkout-block'; + } return $this->is_enabled_for_location( 'smart_button_locations', $location ); } diff --git a/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php b/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php index 638758017..e8d88adec 100644 --- a/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php +++ b/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php @@ -57,7 +57,7 @@ class ConnectAdminNotice { $message = sprintf( /* translators: %1$s the gateway name. */ __( - 'PayPal Payments is almost ready. To get started, connect your account.', + 'PayPal Payments is almost ready. To get started, connect your account with the Activate PayPal button on the Account Setup page.', 'woocommerce-paypal-payments' ), admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=' . Settings::CONNECTION_TAB_ID ) diff --git a/modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php b/modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php index db86034d6..34bc13060 100644 --- a/modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php +++ b/modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php @@ -10,6 +10,8 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway\Processor; use Exception; +use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; +use WooCommerce\PayPalCommerce\ApiClient\Factory\AmountFactory; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use WC_Order; @@ -22,7 +24,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\CaptureStatus; use WooCommerce\PayPalCommerce\ApiClient\Entity\Money; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice; @@ -91,6 +93,20 @@ class AuthorizedPaymentsProcessor { */ private $subscription_helper; + /** + * The amount factory. + * + * @var AmountFactory + */ + private $amount_factory; + + /** + * The reauthorization failure reason. + * + * @var string + */ + private $reauthorization_failure_reason = ''; + /** * AuthorizedPaymentsProcessor constructor. * @@ -100,6 +116,7 @@ class AuthorizedPaymentsProcessor { * @param AuthorizeOrderActionNotice $notice The notice. * @param ContainerInterface $config The settings. * @param SubscriptionHelper $subscription_helper The subscription helper. + * @param AmountFactory $amount_factory The amount factory. */ public function __construct( OrderEndpoint $order_endpoint, @@ -107,7 +124,8 @@ class AuthorizedPaymentsProcessor { LoggerInterface $logger, AuthorizeOrderActionNotice $notice, ContainerInterface $config, - SubscriptionHelper $subscription_helper + SubscriptionHelper $subscription_helper, + AmountFactory $amount_factory ) { $this->order_endpoint = $order_endpoint; @@ -116,6 +134,7 @@ class AuthorizedPaymentsProcessor { $this->notice = $notice; $this->config = $config; $this->subscription_helper = $subscription_helper; + $this->amount_factory = $amount_factory; } /** @@ -249,6 +268,67 @@ class AuthorizedPaymentsProcessor { } } + /** + * Reauthorizes an authorized payment for an WooCommerce order. + * + * @param WC_Order $wc_order The WooCommerce order. + * + * @return string The status or reauthorization id. + */ + public function reauthorize_payment( WC_Order $wc_order ): string { + $this->reauthorization_failure_reason = ''; + + try { + $order = $this->paypal_order_from_wc_order( $wc_order ); + } catch ( Exception $exception ) { + $this->logger->error( 'Could not get PayPal order from WC order: ' . $exception->getMessage() ); + if ( $exception->getCode() === 404 ) { + return self::NOT_FOUND; + } + return self::INACCESSIBLE; + } + + $amount = $this->amount_factory->from_wc_order( $wc_order ); + + $authorizations = $this->all_authorizations( $order ); + $uncaptured_authorizations = $this->authorizations_to_capture( ...$authorizations ); + + if ( ! $uncaptured_authorizations ) { + if ( $this->captured_authorizations( ...$authorizations ) ) { + $this->logger->info( 'Authorizations already captured.' ); + return self::ALREADY_CAPTURED; + } + + $this->logger->info( 'Bad authorization.' ); + return self::BAD_AUTHORIZATION; + } + + $authorization = end( $uncaptured_authorizations ); + + try { + $this->payments_endpoint->reauthorize( $authorization->id(), new Money( $amount->value(), $amount->currency_code() ) ); + } catch ( PayPalApiException $exception ) { + $this->reauthorization_failure_reason = $exception->details()[0]->description ?? null; + $this->logger->error( 'Reauthorization failed: ' . $exception->name() . ' | ' . $this->reauthorization_failure_reason ); + return self::FAILED; + + } catch ( Exception $exception ) { + $this->logger->error( 'Failed to capture authorization: ' . $exception->getMessage() ); + return self::FAILED; + } + + return self::SUCCESSFUL; + } + + /** + * The reason for a failed reauthorization. + * + * @return string + */ + public function reauthorization_failure_reason(): string { + return $this->reauthorization_failure_reason; + } + /** * Voids authorizations for the given PayPal order. * @@ -392,4 +472,5 @@ class AuthorizedPaymentsProcessor { } ); } + } diff --git a/modules/ppcp-wc-gateway/src/Processor/CreditCardOrderInfoHandlingTrait.php b/modules/ppcp-wc-gateway/src/Processor/CreditCardOrderInfoHandlingTrait.php new file mode 100644 index 000000000..51a3a741c --- /dev/null +++ b/modules/ppcp-wc-gateway/src/Processor/CreditCardOrderInfoHandlingTrait.php @@ -0,0 +1,158 @@ +payment_source(); + if ( ! $payment_source || $payment_source->name() !== 'card' ) { + return; + } + + $authentication_result = $payment_source->properties()->authentication_result ?? null; + + if ( $authentication_result ) { + $card_authentication_result_factory = new CardAuthenticationResultFactory(); + $result = $card_authentication_result_factory->from_paypal_response( $authentication_result ); + + $three_d_response_order_note_title = __( '3DS Authentication Result', 'woocommerce-paypal-payments' ); + /* translators: %1$s is 3DS order note title, %2$s is 3DS order note result markup */ + $three_d_response_order_note_format = __( '%1$s %2$s', 'woocommerce-paypal-payments' ); + $three_d_response_order_note_result_format = '
    +
  • %1$s
  • +
  • %2$s
  • +
  • %3$s
  • +
'; + $three_d_response_order_note_result = sprintf( + $three_d_response_order_note_result_format, + /* translators: %s is liability shift */ + sprintf( __( 'Liability Shift: %s', 'woocommerce-paypal-payments' ), esc_html( $result->liability_shift() ) ), + /* translators: %s is enrollment status */ + sprintf( __( 'Enrollment Status: %s', 'woocommerce-paypal-payments' ), esc_html( $result->enrollment_status() ) ), + /* translators: %s is authentication status */ + sprintf( __( 'Authentication Status: %s', 'woocommerce-paypal-payments' ), esc_html( $result->authentication_result() ) ) + ); + $three_d_response_order_note = sprintf( + $three_d_response_order_note_format, + esc_html( $three_d_response_order_note_title ), + wp_kses_post( $three_d_response_order_note_result ) + ); + + $wc_order->add_order_note( $three_d_response_order_note ); + + $wc_order->update_meta_data( PayPalGateway::THREE_D_AUTH_RESULT_META_KEY, $result->to_array() ); + $wc_order->save_meta_data(); + + /** + * Fired when the 3DS information is added to WC order. + */ + do_action( 'woocommerce_paypal_payments_three_d_secure_added', $wc_order, $order ); + } + } + + /** + * Handles the fraud processor response details. + * + * Adds the order note with the fraud processor response details. + * Adds the order meta with the fraud processor response details. + * + * @param FraudProcessorResponse $fraud The fraud processor response (AVS, CVV ...). + * @param Order $order The PayPal order. + * @param WC_Order $wc_order The WC order. + */ + protected function handle_fraud( FraudProcessorResponse $fraud, Order $order, WC_Order $wc_order ): void { + $payment_source = $order->payment_source(); + if ( ! $payment_source || $payment_source->name() !== 'card' ) { + return; + } + + $fraud_responses = $fraud->to_array(); + $card_brand = $payment_source->properties()->brand ?? __( 'N/A', 'woocommerce-paypal-payments' ); + $card_last_digits = $payment_source->properties()->last_digits ?? __( 'N/A', 'woocommerce-paypal-payments' ); + + $avs_response_order_note_title = __( 'Address Verification Result', 'woocommerce-paypal-payments' ); + /* translators: %1$s is AVS order note title, %2$s is AVS order note result markup */ + $avs_response_order_note_format = __( '%1$s %2$s', 'woocommerce-paypal-payments' ); + $avs_response_order_note_result_format = '
    +
  • %1$s
  • +
      +
    • %2$s
    • +
    • %3$s
    • +
    +
  • %4$s
  • +
  • %5$s
  • +
'; + $avs_response_order_note_result = sprintf( + $avs_response_order_note_result_format, + /* translators: %s is fraud AVS code */ + sprintf( __( 'AVS: %s', 'woocommerce-paypal-payments' ), esc_html( $fraud_responses['avs_code'] ) ), + /* translators: %s is fraud AVS address match */ + sprintf( __( 'Address Match: %s', 'woocommerce-paypal-payments' ), esc_html( $fraud_responses['address_match'] ) ), + /* translators: %s is fraud AVS postal match */ + sprintf( __( 'Postal Match: %s', 'woocommerce-paypal-payments' ), esc_html( $fraud_responses['postal_match'] ) ), + /* translators: %s is card brand */ + sprintf( __( 'Card Brand: %s', 'woocommerce-paypal-payments' ), esc_html( $card_brand ) ), + /* translators: %s card last digits */ + sprintf( __( 'Card Last Digits: %s', 'woocommerce-paypal-payments' ), esc_html( $card_last_digits ) ) + ); + $avs_response_order_note = sprintf( + $avs_response_order_note_format, + esc_html( $avs_response_order_note_title ), + wp_kses_post( $avs_response_order_note_result ) + ); + $wc_order->add_order_note( $avs_response_order_note ); + + $cvv_response_order_note_format = '
  • %1$s
'; + $cvv_response_order_note = sprintf( + $cvv_response_order_note_format, + /* translators: %s is fraud CVV match */ + sprintf( __( 'CVV2 Match: %s', 'woocommerce-paypal-payments' ), esc_html( $fraud_responses['cvv_match'] ) ) + ); + $wc_order->add_order_note( $cvv_response_order_note ); + + $meta_details = array_merge( + $fraud_responses, + array( + 'card_brand' => $card_brand, + 'card_last_digits' => $card_last_digits, + ) + ); + $wc_order->update_meta_data( PayPalGateway::FRAUD_RESULT_META_KEY, $meta_details ); + $wc_order->save_meta_data(); + + /** + * Fired when the fraud result information is added to WC order. + */ + do_action( 'woocommerce_paypal_payments_fraud_result_added', $wc_order, $order ); + } +} diff --git a/modules/ppcp-wc-gateway/src/Processor/OrderMetaTrait.php b/modules/ppcp-wc-gateway/src/Processor/OrderMetaTrait.php index 47348eca3..62a80456a 100644 --- a/modules/ppcp-wc-gateway/src/Processor/OrderMetaTrait.php +++ b/modules/ppcp-wc-gateway/src/Processor/OrderMetaTrait.php @@ -45,6 +45,18 @@ trait OrderMetaTrait { $wc_order->update_meta_data( PayPalGateway::ORDER_PAYMENT_SOURCE_META_KEY, $payment_source ); } + $payer = $order->payer(); + if ( + $payer + && $payment_source + && in_array( $payment_source, PayPalGateway::PAYMENT_SOURCES_WITH_PAYER_EMAIL, true ) + ) { + $payer_email = $payer->email_address(); + if ( $payer_email ) { + $wc_order->update_meta_data( PayPalGateway::ORDER_PAYER_EMAIL_META_KEY, $payer_email ); + } + } + $wc_order->save(); do_action( 'woocommerce_paypal_payments_woocommerce_order_created', $wc_order, $order ); @@ -59,12 +71,7 @@ trait OrderMetaTrait { private function get_payment_source( Order $order ): ?string { $source = $order->payment_source(); if ( $source ) { - if ( $source->card() ) { - return 'card'; - } - if ( $source->wallet() ) { - return 'wallet'; - } + return $source->name(); } return null; diff --git a/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php b/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php index 2497f8f91..26defd836 100644 --- a/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php +++ b/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php @@ -16,6 +16,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; +use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Factory\OrderFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; @@ -25,7 +26,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderHelper; use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Session\SessionHandler; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; use WooCommerce\PayPalCommerce\WcGateway\Exception\PayPalOrderMissingException; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; @@ -265,6 +266,8 @@ class OrderProcessor { if ( $this->capture_authorized_downloads( $order ) ) { $this->authorized_payments_processor->capture_authorized_payment( $wc_order ); } + + do_action( 'woocommerce_paypal_payments_after_order_processor', $wc_order, $order ); } /** @@ -349,12 +352,16 @@ class OrderProcessor { * @return bool */ private function order_is_ready_for_process( Order $order ): bool { - if ( $order->status()->is( OrderStatus::APPROVED ) || $order->status()->is( OrderStatus::CREATED ) ) { return true; } - if ( ! $order->payment_source() || ! $order->payment_source()->card() ) { + $payment_source = $order->payment_source(); + if ( ! $payment_source ) { + return false; + } + + if ( $payment_source->name() !== 'card' ) { return false; } diff --git a/modules/ppcp-wc-gateway/src/Processor/PaymentsStatusHandlingTrait.php b/modules/ppcp-wc-gateway/src/Processor/PaymentsStatusHandlingTrait.php index e1f4f9654..e6186badf 100644 --- a/modules/ppcp-wc-gateway/src/Processor/PaymentsStatusHandlingTrait.php +++ b/modules/ppcp-wc-gateway/src/Processor/PaymentsStatusHandlingTrait.php @@ -112,6 +112,10 @@ trait PaymentsStatusHandlingTrait { 'on-hold', __( 'Awaiting payment.', 'woocommerce-paypal-payments' ) ); + /** + * Fired when PayPal order is authorized. + */ + do_action( 'woocommerce_paypal_payments_order_authorized', $wc_order, $authorization ); break; case AuthorizationStatus::DENIED: $wc_order->update_status( diff --git a/modules/ppcp-wc-gateway/src/Processor/RefundProcessor.php b/modules/ppcp-wc-gateway/src/Processor/RefundProcessor.php index a8f6dfa31..ed653a5bc 100644 --- a/modules/ppcp-wc-gateway/src/Processor/RefundProcessor.php +++ b/modules/ppcp-wc-gateway/src/Processor/RefundProcessor.php @@ -22,6 +22,8 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments; use WooCommerce\PayPalCommerce\ApiClient\Entity\RefundCapture; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Helper\RefundFeesUpdater; @@ -56,6 +58,13 @@ class RefundProcessor { */ private $logger; + /** + * The prefix. + * + * @var string + */ + private $prefix; + /** * The refund fees updater. * @@ -69,13 +78,21 @@ class RefundProcessor { * @param OrderEndpoint $order_endpoint The order endpoint. * @param PaymentsEndpoint $payments_endpoint The payments endpoint. * @param RefundFeesUpdater $refund_fees_updater The refund fees updater. + * @param string $prefix The prefix. * @param LoggerInterface $logger The logger. */ - public function __construct( OrderEndpoint $order_endpoint, PaymentsEndpoint $payments_endpoint, RefundFeesUpdater $refund_fees_updater, LoggerInterface $logger ) { + public function __construct( + OrderEndpoint $order_endpoint, + PaymentsEndpoint $payments_endpoint, + RefundFeesUpdater $refund_fees_updater, + string $prefix, + LoggerInterface $logger + ) { $this->order_endpoint = $order_endpoint; $this->payments_endpoint = $payments_endpoint; $this->refund_fees_updater = $refund_fees_updater; + $this->prefix = $prefix; $this->logger = $logger; } @@ -92,6 +109,10 @@ class RefundProcessor { */ public function process( WC_Order $wc_order, float $amount = null, string $reason = '' ) : bool { try { + if ( ! in_array( $wc_order->get_payment_method(), array( PayPalGateway::ID, CreditCardGateway::ID, CardButtonGateway::ID ), true ) ) { + return true; + } + $order_id = $wc_order->get_meta( PayPalGateway::ORDER_ID_META_KEY ); if ( ! $order_id ) { throw new RuntimeException( 'PayPal order ID not found in meta.' ); @@ -164,7 +185,7 @@ class RefundProcessor { $capture = $captures[0]; $refund = new RefundCapture( $capture, - $capture->invoice_id(), + $capture->invoice_id() ?: $this->prefix . $wc_order->get_order_number(), $reason, new Amount( new Money( $amount, $wc_order->get_currency() ) diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/connection-tab-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/connection-tab-fields.php index 4a7e3ac6a..33c3f13d6 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/connection-tab-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/connection-tab-fields.php @@ -65,7 +65,7 @@ return function ( ContainerInterface $container, array $fields ): array { American Express Discover iDEAL - Sofort + BLIK
Apple Pay @@ -390,6 +390,16 @@ return function ( ContainerInterface $container, array $fields ): array { '' ), ), + 'refresh_feature_status' => array( + 'title' => __( 'Refresh feature availability status', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-text', + 'text' => '
', + 'screens' => array( + State::STATE_ONBOARDED, + ), + 'requirements' => array(), + 'gateway' => Settings::CONNECTION_TAB_ID, + ), 'ppcp_dcc_status' => array( 'title' => __( 'Advanced Credit and Debit Card Payments', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-text', @@ -400,6 +410,16 @@ return function ( ContainerInterface $container, array $fields ): array { 'requirements' => array( 'dcc' ), 'gateway' => Settings::CONNECTION_TAB_ID, ), + 'ppcp_reference_transactions_status' => array( + 'title' => __( 'Advanced PayPal Wallet', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-text', + 'text' => $container->get( 'wcgateway.settings.connection.reference-transactions-status-text' ), + 'screens' => array( + State::STATE_ONBOARDED, + ), + 'requirements' => array( 'dcc' ), + 'gateway' => Settings::CONNECTION_TAB_ID, + ), 'ppcp_pui_status' => array( 'title' => __( 'Pay upon Invoice', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-text', @@ -416,7 +436,7 @@ return function ( ContainerInterface $container, array $fields ): array { 'desc_tip' => true, 'label' => $container->get( 'wcgateway.settings.fraudnet-label' ), 'description' => __( 'FraudNet is a JavaScript library developed by PayPal and embedded into a merchant’s web page to collect browser-based data to help reduce fraud.', 'woocommerce-paypal-payments' ), - 'default' => false, + 'default' => true, 'screens' => array( State::STATE_ONBOARDED, ), @@ -502,8 +522,8 @@ return function ( ContainerInterface $container, array $fields ): array { 'woocommerce-paypal-payments' ), 'options' => array( - PurchaseUnitSanitizer::MODE_DITCH => __( 'Do not send line items to PayPal', 'woocommerce-paypal-payments' ), PurchaseUnitSanitizer::MODE_EXTRA_LINE => __( 'Add another line item', 'woocommerce-paypal-payments' ), + PurchaseUnitSanitizer::MODE_DITCH => __( 'Do not send line items to PayPal', 'woocommerce-paypal-payments' ), ), 'screens' => array( State::STATE_START, diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/pay-later-tab-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/pay-later-tab-fields.php index 4fc6635f7..8b2fc55e2 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/pay-later-tab-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/pay-later-tab-fields.php @@ -44,51 +44,6 @@ return function ( ContainerInterface $container, array $fields ): array { }; $pay_later_fields = array( - 'pay_later_button_heading' => array( - 'heading' => __( 'Pay Later Button', 'woocommerce-paypal-payments' ), - 'type' => 'ppcp-heading', - 'screens' => array( State::STATE_ONBOARDED ), - 'requirements' => array( 'messages' ), - 'gateway' => Settings::PAY_LATER_TAB_ID, - 'description' => sprintf( - // translators: %1$s and %2$s are the opening and closing of HTML tag. - __( 'When enabled, a %1$sPay Later button%2$s is displayed for eligible customers.%3$sPayPal buttons must be enabled to display the Pay Later button.', 'woocommerce-paypal-payments' ), - '', - '', - '' - ), - ), - 'pay_later_button_enabled' => array( - 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), - 'type' => 'checkbox', - 'label' => esc_html( $pay_later_messaging_enabled_label ), - 'default' => true, - 'screens' => array( State::STATE_ONBOARDED ), - 'requirements' => array( 'messages' ), - 'gateway' => Settings::PAY_LATER_TAB_ID, - 'input_class' => $vault_enabled ? array( 'ppcp-disabled-checkbox' ) : array(), - ), - 'pay_later_button_locations' => array( - 'title' => __( 'Pay Later Button Locations', 'woocommerce-paypal-payments' ), - 'type' => 'ppcp-multiselect', - 'class' => array(), - 'input_class' => array( 'wc-enhanced-select' ), - 'default' => $container->get( 'wcgateway.settings.pay-later.default-button-locations' ), - 'desc_tip' => false, - 'description' => __( 'Select where the Pay Later button should be displayed.', 'woocommerce-paypal-payments' ), - 'options' => $container->get( 'wcgateway.settings.pay-later.button-locations' ), - 'screens' => array( State::STATE_ONBOARDED ), - 'requirements' => array( 'messages' ), - 'gateway' => Settings::PAY_LATER_TAB_ID, - ), - 'pay_later_button_preview' => array( - 'type' => 'ppcp-text', - 'text' => $render_preview_element( 'ppcpPayLaterButtonPreview', 'button', $button_message ), - 'screens' => array( State::STATE_ONBOARDED ), - 'requirements' => array( 'messages' ), - 'gateway' => Settings::PAY_LATER_TAB_ID, - ), - // Messaging. 'pay_later_messaging_heading' => array( 'heading' => __( 'Pay Later Messaging', 'woocommerce-paypal-payments' ), @@ -96,13 +51,6 @@ return function ( ContainerInterface $container, array $fields ): array { 'screens' => array( State::STATE_ONBOARDED ), 'requirements' => array( 'messages' ), 'gateway' => Settings::PAY_LATER_TAB_ID, - 'description' => sprintf( - // translators: %1$s and %2$s are the opening and closing of HTML tag. - __( 'When enabled, %1$sPayPal Pay Later messaging%2$s is displayed for eligible customers.%3$sCustomers automatically see the most relevant Pay Later offering.', 'woocommerce-paypal-payments' ), - '', - '', - '' - ), ), 'pay_later_messaging_enabled' => array( 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), @@ -378,7 +326,7 @@ return function ( ContainerInterface $container, array $fields ): array { // Cart. 'pay_later_cart_messaging_heading' => array( - 'heading' => __( 'Pay Later Messaging on Cart', 'woocommerce-paypal-payments' ), + 'heading' => __( 'Pay Later Messaging on Classic Cart', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( State::STATE_ONBOARDED ), 'requirements' => array(), @@ -502,7 +450,7 @@ return function ( ContainerInterface $container, array $fields ): array { // Checkout. 'pay_later_checkout_messaging_heading' => array( - 'heading' => __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ), + 'heading' => __( 'Pay Later Messaging on Classic Checkout', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( State::STATE_ONBOARDED ), 'requirements' => array(), @@ -871,6 +819,50 @@ return function ( ContainerInterface $container, array $fields ): array { 'requirements' => array( 'messages' ), 'gateway' => Settings::PAY_LATER_TAB_ID, ), + 'pay_later_button_heading' => array( + 'heading' => __( 'Pay Later Button', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-heading', + 'screens' => array( State::STATE_ONBOARDED ), + 'requirements' => array( 'messages' ), + 'gateway' => Settings::PAY_LATER_TAB_ID, + 'description' => sprintf( + // translators: %1$s and %2$s are the opening and closing of HTML tag. + __( 'When enabled, a %1$sPay Later button%2$s is displayed for eligible customers.%3$sPayPal buttons must be enabled to display the Pay Later button.', 'woocommerce-paypal-payments' ), + '', + '', + '' + ), + ), + 'pay_later_button_enabled' => array( + 'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => esc_html( $pay_later_messaging_enabled_label ), + 'default' => true, + 'screens' => array( State::STATE_ONBOARDED ), + 'requirements' => array( 'messages' ), + 'gateway' => Settings::PAY_LATER_TAB_ID, + 'input_class' => $vault_enabled ? array( 'ppcp-disabled-checkbox' ) : array(), + ), + 'pay_later_button_locations' => array( + 'title' => __( 'Pay Later Button Locations', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-multiselect', + 'class' => array(), + 'input_class' => array( 'wc-enhanced-select' ), + 'default' => $container->get( 'wcgateway.settings.pay-later.default-button-locations' ), + 'desc_tip' => false, + 'description' => __( 'Select where the Pay Later button should be displayed.', 'woocommerce-paypal-payments' ), + 'options' => $container->get( 'wcgateway.settings.pay-later.button-locations' ), + 'screens' => array( State::STATE_ONBOARDED ), + 'requirements' => array( 'messages' ), + 'gateway' => Settings::PAY_LATER_TAB_ID, + ), + 'pay_later_button_preview' => array( + 'type' => 'ppcp-text', + 'text' => $render_preview_element( 'ppcpPayLaterButtonPreview', 'button', $button_message ), + 'screens' => array( State::STATE_ONBOARDED ), + 'requirements' => array( 'messages' ), + 'gateway' => Settings::PAY_LATER_TAB_ID, + ), ); return array_merge( $fields, $pay_later_fields ); diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php index aad87730f..83363c08a 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php @@ -91,7 +91,7 @@ return function ( ContainerInterface $container, array $fields ): array { 'title' => __( 'Customize Smart Buttons Per Location', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Customize smart button style per location', 'woocommerce-paypal-payments' ), - 'default' => true, + 'default' => false, 'screens' => array( State::STATE_START, State::STATE_ONBOARDED ), 'requirements' => array(), 'gateway' => 'paypal', @@ -222,11 +222,11 @@ return function ( ContainerInterface $container, array $fields ): array { // Checkout page. 'button_checkout_heading' => array( - 'heading' => __( 'Checkout Buttons', 'woocommerce-paypal-payments' ), + 'heading' => __( 'Classic Checkout Buttons', 'woocommerce-paypal-payments' ), 'description' => sprintf( // translators: %1$s and %2$s are the opening and closing of HTML tag. __( - 'Customize the appearance of the PayPal smart buttons on the %1$sCheckout page%2$s. + 'Customize the appearance of the PayPal smart buttons on the %1$sClassic Checkout page%2$s. %3$sCheckout Buttons must be enabled to display the PayPal gateway on the Checkout page. ', 'woocommerce-paypal-payments' @@ -508,11 +508,11 @@ return function ( ContainerInterface $container, array $fields ): array { // Cart settings. 'button_cart_heading' => array( - 'heading' => __( 'Cart Buttons', 'woocommerce-paypal-payments' ), + 'heading' => __( 'Classic Cart Buttons', 'woocommerce-paypal-payments' ), 'description' => sprintf( // translators: %1$s and %2$s are the opening and closing of HTML tag. __( - 'Customize the appearance of the PayPal smart buttons on the %1$sCart page%2$s.', + 'Customize the appearance of the PayPal smart buttons on the %1$sClassic Cart page%2$s.', 'woocommerce-paypal-payments' ), '', @@ -805,11 +805,11 @@ return function ( ContainerInterface $container, array $fields ): array { // Block express checkout settings. 'button_checkout-block-express_heading' => array( - 'heading' => __( 'Block Express Checkout Buttons', 'woocommerce-paypal-payments' ), + 'heading' => __( 'Express Checkout Buttons', 'woocommerce-paypal-payments' ), 'description' => sprintf( // translators: %1$s and %2$s are the opening and closing of HTML tag. __( - 'Customize the appearance of the PayPal smart buttons on the %1$sBlock Express Checkout%2$s.', + 'Customize the appearance of the PayPal smart buttons on the %1$sExpress Checkout%2$s.', 'woocommerce-paypal-payments' ), '', @@ -923,11 +923,11 @@ return function ( ContainerInterface $container, array $fields ): array { // Block cart settings. 'button_cart-block_heading' => array( - 'heading' => __( 'Block Cart Buttons', 'woocommerce-paypal-payments' ), + 'heading' => __( 'Cart Buttons', 'woocommerce-paypal-payments' ), 'description' => sprintf( // translators: %1$s and %2$s are the opening and closing of HTML tag. __( - 'Customize the appearance of the PayPal smart buttons on the %1$sBlock Cart%2$s.', + 'Customize the appearance of the PayPal smart buttons on the %1$sCart%2$s.', 'woocommerce-paypal-payments' ), '', diff --git a/modules/ppcp-wc-gateway/src/Settings/Settings.php b/modules/ppcp-wc-gateway/src/Settings/Settings.php index 9ba1529c2..ebd6f1081 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Settings.php +++ b/modules/ppcp-wc-gateway/src/Settings/Settings.php @@ -142,7 +142,7 @@ class Settings implements ContainerInterface { 'woocommerce-paypal-payments' ), 'smart_button_locations' => $this->default_button_locations, - 'smart_button_enable_styling_per_location' => true, + 'smart_button_enable_styling_per_location' => false, 'pay_later_messaging_enabled' => true, 'pay_later_button_enabled' => true, 'pay_later_button_locations' => $this->default_pay_later_button_locations, diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php index 7c690c942..b7d0c39bd 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php +++ b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php @@ -14,6 +14,7 @@ use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message; use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\Http\RedirectorInterface; @@ -152,6 +153,13 @@ class SettingsListener { */ private $partner_merchant_id_sandbox; + /** + * Billing Agreements endpoint. + * + * @var BillingAgreementsEndpoint + */ + private $billing_agreements_endpoint; + /** * The logger. * @@ -162,21 +170,22 @@ class SettingsListener { /** * SettingsListener constructor. * - * @param Settings $settings The settings. - * @param array $setting_fields The setting fields. - * @param WebhookRegistrar $webhook_registrar The Webhook Registrar. - * @param Cache $cache The Cache. - * @param State $state The state. - * @param Bearer $bearer The bearer. - * @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page. - * @param Cache $signup_link_cache The signup link cache. - * @param array $signup_link_ids Signup link ids. - * @param Cache $pui_status_cache The PUI status cache. - * @param Cache $dcc_status_cache The DCC status cache. - * @param RedirectorInterface $redirector The HTTP redirector. - * @param string $partner_merchant_id_production Partner merchant ID production. - * @param string $partner_merchant_id_sandbox Partner merchant ID sandbox. - * @param ?LoggerInterface $logger The logger. + * @param Settings $settings The settings. + * @param array $setting_fields The setting fields. + * @param WebhookRegistrar $webhook_registrar The Webhook Registrar. + * @param Cache $cache The Cache. + * @param State $state The state. + * @param Bearer $bearer The bearer. + * @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page. + * @param Cache $signup_link_cache The signup link cache. + * @param array $signup_link_ids Signup link ids. + * @param Cache $pui_status_cache The PUI status cache. + * @param Cache $dcc_status_cache The DCC status cache. + * @param RedirectorInterface $redirector The HTTP redirector. + * @param string $partner_merchant_id_production Partner merchant ID production. + * @param string $partner_merchant_id_sandbox Partner merchant ID sandbox. + * @param BillingAgreementsEndpoint $billing_agreements_endpoint Billing Agreements endpoint. + * @param ?LoggerInterface $logger The logger. */ public function __construct( Settings $settings, @@ -193,6 +202,7 @@ class SettingsListener { RedirectorInterface $redirector, string $partner_merchant_id_production, string $partner_merchant_id_sandbox, + BillingAgreementsEndpoint $billing_agreements_endpoint, LoggerInterface $logger = null ) { @@ -210,6 +220,7 @@ class SettingsListener { $this->redirector = $redirector; $this->partner_merchant_id_production = $partner_merchant_id_production; $this->partner_merchant_id_sandbox = $partner_merchant_id_sandbox; + $this->billing_agreements_endpoint = $billing_agreements_endpoint; $this->logger = $logger ?: new NullLogger(); } @@ -335,9 +346,10 @@ class SettingsListener { /** * Prevent enabling both Pay Later messaging and PayPal vaulting * + * @return void * @throws RuntimeException When API request fails. */ - public function listen_for_vaulting_enabled() { + public function listen_for_vaulting_enabled(): void { if ( ! $this->is_valid_site_request() || State::STATE_ONBOARDED !== $this->state->current_state() ) { return; } @@ -367,7 +379,15 @@ class SettingsListener { $vault_enabled = wc_clean( wp_unslash( $_POST['ppcp']['vault_enabled'] ?? '' ) ); $subscription_mode = wc_clean( wp_unslash( $_POST['ppcp']['subscriptions_mode'] ?? '' ) ); - if ( $subscription_mode === 'vaulting_api' && $vault_enabled !== '1' ) { + $reference_transaction_enabled = $this->billing_agreements_endpoint->reference_transaction_enabled(); + + if ( $reference_transaction_enabled !== true ) { + $this->settings->set( 'vault_enabled', false ); + $this->settings->set( 'subscriptions_mode', 'subscriptions_api' ); + $this->settings->persist(); + } + + if ( $subscription_mode === 'vaulting_api' && $vault_enabled !== '1' && $reference_transaction_enabled === true ) { $this->settings->set( 'vault_enabled', true ); $this->settings->persist(); } diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php b/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php index 95046579b..aa33dd28c 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php +++ b/modules/ppcp-wc-gateway/src/Settings/SettingsRenderer.php @@ -533,19 +533,5 @@ $data_rows_html state->current_state() ) { - return false; - } - - return $this->is_paypal_checkout_screen() - && ( $this->paypal_vaulting_is_enabled() || $this->settings_status->is_pay_later_messaging_enabled() ); - } } diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index 66587d6af..8e765a8e9 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -11,9 +11,12 @@ namespace WooCommerce\PayPalCommerce\WcGateway; use Psr\Log\LoggerInterface; use Throwable; +use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message; +use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcGateway\Endpoint\RefreshFeatureStatusEndpoint; +use WooCommerce\PayPalCommerce\WcGateway\Processor\CreditCardOrderInfoHandlingTrait; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; use WC_Order; @@ -55,6 +58,8 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; */ class WCGatewayModule implements ModuleInterface { + use CreditCardOrderInfoHandlingTrait; + /** * {@inheritDoc} */ @@ -91,7 +96,7 @@ class WCGatewayModule implements ModuleInterface { add_action( 'woocommerce_paypal_payments_order_captured', - function ( WC_Order $wc_order, Capture $capture ) { + function ( WC_Order $wc_order, Capture $capture ) use ( $c ) { $breakdown = $capture->seller_receivable_breakdown(); if ( $breakdown ) { $wc_order->update_meta_data( PayPalGateway::FEES_META_KEY, $breakdown->to_array() ); @@ -103,43 +108,34 @@ class WCGatewayModule implements ModuleInterface { $wc_order->save_meta_data(); } + $order = $c->get( 'session.handler' )->order(); + if ( ! $order ) { + return; + } + $fraud = $capture->fraud_processor_response(); if ( $fraud ) { - $fraud_responses = $fraud->to_array(); - $avs_response_order_note_title = __( 'Address Verification Result', 'woocommerce-paypal-payments' ); - /* translators: %1$s is AVS order note title, %2$s is AVS order note result markup */ - $avs_response_order_note_format = __( '%1$s %2$s', 'woocommerce-paypal-payments' ); - $avs_response_order_note_result_format = '
    -
  • %1$s
  • -
      -
    • %2$s
    • -
    • %3$s
    • -
    -
'; - $avs_response_order_note_result = sprintf( - $avs_response_order_note_result_format, - /* translators: %s is fraud AVS code */ - sprintf( __( 'AVS: %s', 'woocommerce-paypal-payments' ), esc_html( $fraud_responses['avs_code'] ) ), - /* translators: %s is fraud AVS address match */ - sprintf( __( 'Address Match: %s', 'woocommerce-paypal-payments' ), esc_html( $fraud_responses['address_match'] ) ), - /* translators: %s is fraud AVS postal match */ - sprintf( __( 'Postal Match: %s', 'woocommerce-paypal-payments' ), esc_html( $fraud_responses['postal_match'] ) ) - ); - $avs_response_order_note = sprintf( - $avs_response_order_note_format, - esc_html( $avs_response_order_note_title ), - wp_kses_post( $avs_response_order_note_result ) - ); - $wc_order->add_order_note( $avs_response_order_note ); - - $cvv_response_order_note_format = '
  • %1$s
'; - $cvv_response_order_note = sprintf( - $cvv_response_order_note_format, - /* translators: %s is fraud CVV match */ - sprintf( __( 'CVV2 Match: %s', 'woocommerce-paypal-payments' ), esc_html( $fraud_responses['cvv_match'] ) ) - ); - $wc_order->add_order_note( $cvv_response_order_note ); + $this->handle_fraud( $fraud, $order, $wc_order ); } + $this->handle_three_d_secure( $order, $wc_order ); + }, + 10, + 2 + ); + + add_action( + 'woocommerce_paypal_payments_order_authorized', + function ( WC_Order $wc_order, Authorization $authorization ) use ( $c ) { + $order = $c->get( 'session.handler' )->order(); + if ( ! $order ) { + return; + } + + $fraud = $authorization->fraud_processor_response(); + if ( $fraud ) { + $this->handle_fraud( $fraud, $order, $wc_order ); + } + $this->handle_three_d_secure( $order, $wc_order ); }, 10, 2 @@ -177,7 +173,7 @@ class WCGatewayModule implements ModuleInterface { $assets = new SettingsPageAssets( $c->get( 'wcgateway.url' ), $c->get( 'ppcp.asset-version' ), - $c->get( 'subscription.helper' ), + $c->get( 'wc-subscriptions.helper' ), $c->get( 'button.client_id_for_admin' ), $c->get( 'api.shop.currency' ), $c->get( 'api.shop.country' ), @@ -186,7 +182,8 @@ class WCGatewayModule implements ModuleInterface { $settings->has( 'disable_funding' ) ? $settings->get( 'disable_funding' ) : array(), $c->get( 'wcgateway.settings.funding-sources' ), $c->get( 'wcgateway.is-ppcp-settings-page' ), - $settings->has( 'dcc_enabled' ) && $settings->get( 'dcc_enabled' ) + $settings->has( 'dcc_enabled' ) && $settings->get( 'dcc_enabled' ), + $c->get( 'api.endpoint.billing-agreements' ) ); $assets->register_assets(); } @@ -255,6 +252,16 @@ class WCGatewayModule implements ModuleInterface { } ); + add_action( + 'wc_ajax_' . RefreshFeatureStatusEndpoint::ENDPOINT, + static function () use ( $c ) { + $endpoint = $c->get( 'wcgateway.endpoint.refresh-feature-status' ); + assert( $endpoint instanceof RefreshFeatureStatusEndpoint ); + + $endpoint->handle_request(); + } + ); + add_action( 'woocommerce_paypal_payments_gateway_migrate', static function () use ( $c ) { @@ -419,6 +426,75 @@ class WCGatewayModule implements ModuleInterface { $c->get( 'wcgateway.cli.settings.command' ) ); } + + // Clears product status when appropriate. + add_action( + 'woocommerce_paypal_payments_clear_apm_product_status', + function( Settings $settings = null ) use ( $c ): void { + + // Clear DCC Product status. + $dcc_product_status = $c->get( 'wcgateway.helper.dcc-product-status' ); + if ( $dcc_product_status instanceof DCCProductStatus ) { + $dcc_product_status->clear( $settings ); + } + + // Clear Pay Upon Invoice status. + $pui_product_status = $c->get( 'wcgateway.pay-upon-invoice-product-status' ); + if ( $pui_product_status instanceof PayUponInvoiceProductStatus ) { + $pui_product_status->clear( $settings ); + } + + // Clear Reference Transaction status. + delete_transient( 'ppcp_reference_transaction_enabled' ); + } + ); + + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ + add_filter( + 'woocommerce_admin_billing_fields', + function ( $fields ) { + global $theorder; + + if ( ! apply_filters( 'woocommerce_paypal_payments_order_details_show_paypal_email', true ) ) { + return $fields; + } + + if ( ! is_array( $fields ) ) { + return $fields; + } + + if ( ! $theorder instanceof WC_Order ) { + return $fields; + } + + $email = $theorder->get_meta( PayPalGateway::ORDER_PAYER_EMAIL_META_KEY ) ?: ''; + + if ( ! $email ) { + return $fields; + } + + // Is payment source is paypal exclude all non paypal funding sources. + $payment_source = $theorder->get_meta( PayPalGateway::ORDER_PAYMENT_SOURCE_META_KEY ) ?: ''; + $is_paypal_funding_source = ( strpos( $theorder->get_payment_method_title(), '(via PayPal)' ) === false ); + + if ( $payment_source === 'paypal' && ! $is_paypal_funding_source ) { + return $fields; + } + + $fields['paypal_email'] = array( + 'label' => __( 'PayPal email address', 'woocommerce-paypal-payments' ), + 'value' => $email, + 'wrapper_class' => 'form-field-wide', + 'custom_attributes' => array( 'disabled' => 'disabled' ), + ); + + return $fields; + } + ); } /** @@ -586,13 +662,18 @@ class WCGatewayModule implements ModuleInterface { return $order_actions; } - $render = $container->get( 'wcgateway.admin.render-authorize-action' ); + $render_reauthorize = $container->get( 'wcgateway.admin.render-reauthorize-action' ); + $render_authorize = $container->get( 'wcgateway.admin.render-authorize-action' ); + /** * Renders the authorize action in the select field. * * @var RenderAuthorizeAction $render */ - return $render->render( $order_actions, $theorder ); + return $render_reauthorize->render( + $render_authorize->render( $order_actions, $theorder ), + $theorder + ); } ); @@ -609,6 +690,36 @@ class WCGatewayModule implements ModuleInterface { $authorized_payments_processor->capture_authorized_payment( $wc_order ); } ); + + add_action( + 'woocommerce_order_action_ppcp_reauthorize_order', + static function ( WC_Order $wc_order ) use ( $container ) { + $admin_notices = $container->get( 'admin-notices.repository' ); + assert( $admin_notices instanceof Repository ); + + /** + * The authorized payments processor. + * + * @var AuthorizedPaymentsProcessor $authorized_payments_processor + */ + $authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' ); + + if ( $authorized_payments_processor->reauthorize_payment( $wc_order ) !== AuthorizedPaymentsProcessor::SUCCESSFUL ) { + $message = sprintf( + '%1$s %2$s', + esc_html__( 'Reauthorization with PayPal failed: ', 'woocommerce-paypal-payments' ), + $authorized_payments_processor->reauthorization_failure_reason() ?: '' + ); + $admin_notices->persist( new Message( $message, 'error' ) ); + } else { + $admin_notices->persist( new Message( 'Payment reauthorized.', 'info' ) ); + + $wc_order->add_order_note( + __( 'Payment reauthorized.', 'woocommerce-paypal-payments' ) + ); + } + } + ); } /** diff --git a/modules/ppcp-subscription/.gitignore b/modules/ppcp-wc-subscriptions/.gitignore similarity index 100% rename from modules/ppcp-subscription/.gitignore rename to modules/ppcp-wc-subscriptions/.gitignore diff --git a/modules/ppcp-wc-subscriptions/composer.json b/modules/ppcp-wc-subscriptions/composer.json new file mode 100644 index 000000000..3cf50034b --- /dev/null +++ b/modules/ppcp-wc-subscriptions/composer.json @@ -0,0 +1,17 @@ +{ + "name": "woocommerce/ppcp-wc-subscriptions", + "type": "dhii-mod", + "description": "Module for WC Subscriptions plugin integration", + "license": "GPL-2.0", + "require": { + "php": "^7.2 | ^8.0", + "dhii/module-interface": "^0.3.0-alpha1" + }, + "autoload": { + "psr-4": { + "WooCommerce\\PayPalCommerce\\WcSubscriptions\\": "src" + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/modules/ppcp-subscription/extensions.php b/modules/ppcp-wc-subscriptions/extensions.php similarity index 58% rename from modules/ppcp-subscription/extensions.php rename to modules/ppcp-wc-subscriptions/extensions.php index 37b6d423a..d9df212e7 100644 --- a/modules/ppcp-subscription/extensions.php +++ b/modules/ppcp-wc-subscriptions/extensions.php @@ -2,7 +2,7 @@ /** * The extensions. * - * @package WooCommerce\PayPalCommerce\Subscription + * @package WooCommerce\PayPalCommerce\WcSubscriptions */ declare(strict_types=1); diff --git a/modules/ppcp-subscription/module.php b/modules/ppcp-wc-subscriptions/module.php similarity index 55% rename from modules/ppcp-subscription/module.php rename to modules/ppcp-wc-subscriptions/module.php index 1db299a49..a298bac91 100644 --- a/modules/ppcp-subscription/module.php +++ b/modules/ppcp-wc-subscriptions/module.php @@ -2,15 +2,15 @@ /** * The module. * - * @package WooCommerce\PayPalCommerce\Subscription + * @package WooCommerce\PayPalCommerce\WcSubscriptions */ declare(strict_types=1); -namespace WooCommerce\PayPalCommerce\Subscription; +namespace WooCommerce\PayPalCommerce\WcSubscriptions; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; return static function (): ModuleInterface { - return new SubscriptionModule(); + return new WcSubscriptionsModule(); }; diff --git a/modules/ppcp-wc-subscriptions/services.php b/modules/ppcp-wc-subscriptions/services.php new file mode 100644 index 000000000..dc23fca9f --- /dev/null +++ b/modules/ppcp-wc-subscriptions/services.php @@ -0,0 +1,62 @@ + static function ( ContainerInterface $container ): SubscriptionHelper { + return new SubscriptionHelper(); + }, + 'wc-subscriptions.helpers.real-time-account-updater' => static function ( ContainerInterface $container ) : RealTimeAccountUpdaterHelper { + return new RealTimeAccountUpdaterHelper(); + }, + 'wc-subscriptions.renewal-handler' => static function ( ContainerInterface $container ): RenewalHandler { + $logger = $container->get( 'woocommerce.logger.woocommerce' ); + $repository = $container->get( 'vaulting.repository.payment-token' ); + $endpoint = $container->get( 'api.endpoint.order' ); + $purchase_unit_factory = $container->get( 'api.factory.purchase-unit' ); + $payer_factory = $container->get( 'api.factory.payer' ); + $environment = $container->get( 'onboarding.environment' ); + $settings = $container->get( 'wcgateway.settings' ); + $authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' ); + $funding_source_renderer = $container->get( 'wcgateway.funding-source.renderer' ); + return new RenewalHandler( + $logger, + $repository, + $endpoint, + $purchase_unit_factory, + $container->get( 'api.factory.shipping-preference' ), + $payer_factory, + $environment, + $settings, + $authorized_payments_processor, + $funding_source_renderer, + $container->get( 'wc-subscriptions.helpers.real-time-account-updater' ), + $container->get( 'wc-subscriptions.helper' ), + $container->get( 'api.endpoint.payment-tokens' ), + $container->get( 'vaulting.wc-payment-tokens' ) + ); + }, + 'wc-subscriptions.repository.payment-token' => static function ( ContainerInterface $container ): PaymentTokenRepository { + $factory = $container->get( 'api.factory.payment-token' ); + $endpoint = $container->get( 'api.endpoint.payment-token' ); + return new PaymentTokenRepository( $factory, $endpoint ); + }, + 'wc-subscriptions.endpoint.subscription-change-payment-method' => static function( ContainerInterface $container ): SubscriptionChangePaymentMethod { + return new SubscriptionChangePaymentMethod( + $container->get( 'button.request-data' ) + ); + }, +); diff --git a/modules/ppcp-wc-subscriptions/src/Endpoint/SubscriptionChangePaymentMethod.php b/modules/ppcp-wc-subscriptions/src/Endpoint/SubscriptionChangePaymentMethod.php new file mode 100644 index 000000000..7f3df3601 --- /dev/null +++ b/modules/ppcp-wc-subscriptions/src/Endpoint/SubscriptionChangePaymentMethod.php @@ -0,0 +1,81 @@ +request_data = $request_data; + } + + /** + * Returns the nonce. + * + * @return string + */ + public static function nonce(): string { + return self::ENDPOINT; + } + + /** + * Handles the request. + * + * @return bool + * @throws Exception On Error. + */ + public function handle_request(): bool { + try { + $data = $this->request_data->read_request( $this->nonce() ); + + $subscription = wcs_get_subscription( $data['subscription_id'] ); + if ( $subscription instanceof WC_Order ) { + $subscription->set_payment_method( $data['payment_method'] ); + + $wc_payment_token = WC_Payment_Tokens::get( $data['wc_payment_token_id'] ); + if ( $wc_payment_token ) { + $subscription->add_payment_token( $wc_payment_token ); + $subscription->save(); + } + + wp_send_json_success(); + return true; + } + + wp_send_json_error(); + return false; + } catch ( Exception $exception ) { + wp_send_json_error(); + return false; + } + } +} diff --git a/modules/ppcp-subscription/src/FreeTrialHandlerTrait.php b/modules/ppcp-wc-subscriptions/src/FreeTrialHandlerTrait.php similarity index 88% rename from modules/ppcp-subscription/src/FreeTrialHandlerTrait.php rename to modules/ppcp-wc-subscriptions/src/FreeTrialHandlerTrait.php index d528ff554..f97cbc636 100644 --- a/modules/ppcp-subscription/src/FreeTrialHandlerTrait.php +++ b/modules/ppcp-wc-subscriptions/src/FreeTrialHandlerTrait.php @@ -2,12 +2,12 @@ /** * Helper trait for the subscriptions handling. * - * @package WooCommerce\PayPalCommerce\Subscription + * @package WooCommerce\PayPalCommerce\WcSubscriptions */ declare(strict_types=1); -namespace WooCommerce\PayPalCommerce\Subscription; +namespace WooCommerce\PayPalCommerce\WcSubscriptions; use WC_Order; use WC_Subscriptions_Product; @@ -36,7 +36,11 @@ trait FreeTrialHandlerTrait { foreach ( $cart->get_cart() as $item ) { $product = $item['data'] ?? null; - if ( $product && WC_Subscriptions_Product::is_subscription( $product ) ) { + if ( + $product + && WC_Subscriptions_Product::is_subscription( $product ) + && ! $product->get_meta( 'ppcp_subscription_plan' ) + ) { return true; } } diff --git a/modules/ppcp-wc-subscriptions/src/Helper/RealTimeAccountUpdaterHelper.php b/modules/ppcp-wc-subscriptions/src/Helper/RealTimeAccountUpdaterHelper.php new file mode 100644 index 000000000..5cf45b02d --- /dev/null +++ b/modules/ppcp-wc-subscriptions/src/Helper/RealTimeAccountUpdaterHelper.php @@ -0,0 +1,51 @@ +get_type() !== 'CC' + || ! in_array( $token->get_card_type(), array( 'VISA', 'MASTERCARD' ), true ) + ) { + return; + } + + $wc_expiry = $token->get_expiry_month() . '-' . $token->get_expiry_year(); + if ( $expiry !== $wc_expiry ) { + $expiry_split = explode( '-', $expiry ); + $token->set_expiry_year( $expiry_split[0] ); + $token->set_expiry_month( $expiry_split[1] ); + $token->save(); + } + + $wc_last_digits = $token->get_last4(); + if ( $last_digits !== $wc_last_digits ) { + $token->set_last4( $last_digits ); + $token->save(); + } + } +} diff --git a/modules/ppcp-subscription/src/Helper/SubscriptionHelper.php b/modules/ppcp-wc-subscriptions/src/Helper/SubscriptionHelper.php similarity index 74% rename from modules/ppcp-subscription/src/Helper/SubscriptionHelper.php rename to modules/ppcp-wc-subscriptions/src/Helper/SubscriptionHelper.php index b71156f86..969727d63 100644 --- a/modules/ppcp-subscription/src/Helper/SubscriptionHelper.php +++ b/modules/ppcp-wc-subscriptions/src/Helper/SubscriptionHelper.php @@ -4,18 +4,19 @@ * whether the cart contains a subscription, the current product is * a subscription or the subscription plugin is activated in the first place. * - * @package WooCommerce\PayPalCommerce\Subscription\Helper + * @package WooCommerce\PayPalCommerce\WcSubscriptions\Helper */ declare(strict_types=1); -namespace WooCommerce\PayPalCommerce\Subscription\Helper; +namespace WooCommerce\PayPalCommerce\WcSubscriptions\Helper; +use WC_Order; use WC_Product; use WC_Product_Subscription_Variation; +use WC_Subscription; use WC_Subscriptions; use WC_Subscriptions_Product; -use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; /** @@ -23,22 +24,6 @@ use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; */ class SubscriptionHelper { - /** - * The settings. - * - * @var Settings - */ - private $settings; - - /** - * SubscriptionHelper constructor. - * - * @param Settings $settings The settings. - */ - public function __construct( Settings $settings ) { - $this->settings = $settings; - } - /** * Whether the current product is a subscription. * @@ -211,6 +196,21 @@ class SubscriptionHelper { if ( $product->get_type() === 'subscription' && $product->meta_exists( 'ppcp_subscription_plan' ) ) { return $product->get_meta( 'ppcp_subscription_plan' )['id']; } + + if ( $product->get_type() === 'variable-subscription' ) { + /** + * The method is defined in WC_Product_Variable class. + * + * @psalm-suppress UndefinedMethod + */ + $product_variations = $product->get_available_variations(); + foreach ( $product_variations as $variation ) { + $variation_product = wc_get_product( $variation['variation_id'] ) ?? ''; + if ( $variation_product && $variation_product->meta_exists( 'ppcp_subscription_plan' ) ) { + return $variation_product->get_meta( 'ppcp_subscription_plan' )['id']; + } + } + } } return ''; @@ -284,4 +284,60 @@ class SubscriptionHelper { 'cart' => $this->cart_contains_subscription(), ); } + + /** + * Returns previous order transaction from the given subscription. + * + * @param WC_Subscription $subscription WooCommerce Subscription. + * @return string + */ + public function previous_transaction( WC_Subscription $subscription ): string { + $orders = $subscription->get_related_orders( 'ids', array( 'parent', 'renewal' ) ); + if ( ! $orders ) { + return ''; + } + + // Sort orders by key descending. + krsort( $orders ); + + // Removes first order (the current processing order). + unset( $orders[ array_key_first( $orders ) ] ); + + foreach ( $orders as $order_id ) { + $order = wc_get_order( $order_id ); + if ( is_a( $order, WC_Order::class ) && in_array( $order->get_status(), array( 'processing', 'completed' ), true ) ) { + $transaction_id = $order->get_transaction_id(); + if ( $transaction_id ) { + return $transaction_id; + } + } + } + + return ''; + } + + /** + * Returns the variation subscription plan id from the cart. + * + * @return string + */ + public function paypal_subscription_variation_from_cart(): string { + $cart = WC()->cart ?? null; + if ( ! $cart || $cart->is_empty() ) { + return ''; + } + + $items = $cart->get_cart_contents(); + foreach ( $items as $item ) { + $variation_id = $item['variation_id'] ?? 0; + if ( $variation_id ) { + $variation_product = wc_get_product( $variation_id ) ?? ''; + if ( $variation_product && $variation_product->meta_exists( 'ppcp_subscription_plan' ) ) { + return $variation_product->get_meta( 'ppcp_subscription_plan' )['id']; + } + } + } + + return ''; + } } diff --git a/modules/ppcp-wc-subscriptions/src/RenewalHandler.php b/modules/ppcp-wc-subscriptions/src/RenewalHandler.php new file mode 100644 index 000000000..695bce551 --- /dev/null +++ b/modules/ppcp-wc-subscriptions/src/RenewalHandler.php @@ -0,0 +1,591 @@ +logger = $logger; + $this->repository = $repository; + $this->order_endpoint = $order_endpoint; + $this->purchase_unit_factory = $purchase_unit_factory; + $this->shipping_preference_factory = $shipping_preference_factory; + $this->payer_factory = $payer_factory; + $this->environment = $environment; + $this->settings = $settings; + $this->authorized_payments_processor = $authorized_payments_processor; + $this->funding_source_renderer = $funding_source_renderer; + $this->real_time_account_updater_helper = $real_time_account_updater_helper; + $this->subscription_helper = $subscription_helper; + $this->payment_tokens_endpoint = $payment_tokens_endpoint; + $this->wc_payment_tokens = $wc_payment_tokens; + } + + /** + * Renew an order. + * + * @param \WC_Order $wc_order The WooCommerce order. + */ + public function renew( \WC_Order $wc_order ): void { + try { + $subscription = wcs_get_subscription( $wc_order->get_id() ); + if ( is_a( $subscription, WC_Subscription::class ) ) { + $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; + if ( $subscription_id ) { + return; + } + } + + $this->process_order( $wc_order ); + } catch ( \Exception $exception ) { + $error = $exception->getMessage(); + if ( is_a( $exception, PayPalApiException::class ) ) { + $error = $exception->get_details( $error ); + } + + $wc_order->update_status( + 'failed', + $error + ); + + $error_message = sprintf( + 'An error occurred while trying to renew the subscription for order %1$d: %2$s', + $wc_order->get_id(), + $error + ); + $this->logger->error( $error_message ); + + return; + } + } + + /** + * Process a WooCommerce order. + * + * @param \WC_Order $wc_order The WooCommerce order. + * + * @throws \Exception If customer cannot be read/found. + */ + private function process_order( \WC_Order $wc_order ): void { + $user_id = (int) $wc_order->get_customer_id(); + $customer = new \WC_Customer( $user_id ); + + $purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order ); + $payer = $this->payer_factory->from_customer( $customer ); + $shipping_preference = $this->shipping_preference_factory->from_state( + $purchase_unit, + 'renewal' + ); + + // Vault v3. + $payment_source = null; + if ( $wc_order->get_payment_method() === PayPalGateway::ID ) { + $customer_tokens = $this->wc_payment_tokens->customer_tokens( $user_id ); + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id, PayPalGateway::ID ); + + if ( $customer_tokens && empty( $wc_tokens ) ) { + $this->wc_payment_tokens->create_wc_tokens( $customer_tokens, $user_id ); + } + + $customer_token_ids = array(); + foreach ( $customer_tokens as $customer_token ) { + $customer_token_ids[] = $customer_token['id']; + } + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id, PayPalGateway::ID ); + foreach ( $wc_tokens as $token ) { + if ( ! in_array( $token->get_token(), $customer_token_ids, true ) ) { + $token->delete(); + continue; + } + + $name = 'paypal'; + $properties = array( + 'vault_id' => $token->get_token(), + ); + + if ( $token instanceof PaymentTokenPayPal ) { + $name = 'paypal'; + } + + if ( $token instanceof PaymentTokenVenmo ) { + $name = 'venmo'; + } + + if ( $token instanceof PaymentTokenApplePay ) { + $name = 'apple_pay'; + $properties['stored_credential'] = array( + 'payment_initiator' => 'MERCHANT', + 'payment_type' => 'RECURRING', + 'usage' => 'SUBSEQUENT', + ); + } + + $payment_source = new PaymentSource( + $name, + (object) $properties + ); + + break; + } + } + + if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) { + $customer_tokens = $this->wc_payment_tokens->customer_tokens( $user_id ); + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id, CreditCardGateway::ID ); + + if ( $customer_tokens && empty( $wc_tokens ) ) { + $this->wc_payment_tokens->create_wc_tokens( $customer_tokens, $user_id ); + } + + $customer_token_ids = array(); + foreach ( $customer_tokens as $customer_token ) { + $customer_token_ids[] = $customer_token['id']; + } + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id, CreditCardGateway::ID ); + foreach ( $wc_tokens as $token ) { + if ( ! in_array( $token->get_token(), $customer_token_ids, true ) ) { + $token->delete(); + } + } + + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id, CreditCardGateway::ID ); + $last_token = end( $wc_tokens ); + if ( $last_token ) { + $payment_source = $this->card_payment_source( $last_token->get_token(), $wc_order ); + } + } + + if ( $payment_source ) { + $order = $this->order_endpoint->create( + array( $purchase_unit ), + $shipping_preference, + $payer, + null, + '', + ApplicationContext::USER_ACTION_CONTINUE, + '', + array(), + $payment_source + ); + + $this->handle_paypal_order( $wc_order, $order ); + + if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) { + $card_payment_source = $order->payment_source(); + if ( $card_payment_source ) { + $wc_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id, CreditCardGateway::ID ); + $last_token = end( $wc_tokens ); + $expiry = $card_payment_source->properties()->expiry ?? ''; + $last_digits = $card_payment_source->properties()->last_digits ?? ''; + + if ( $last_token && $expiry && $last_digits ) { + $this->real_time_account_updater_helper->update_wc_card_token( $expiry, $last_digits, $last_token ); + } + } + } + + $this->logger->info( + sprintf( + 'Renewal for order %d is completed.', + $wc_order->get_id() + ) + ); + + return; + } + + // Vault v2. + $token = $this->get_token_for_customer( $customer, $wc_order ); + if ( $token ) { + if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) { + $payment_source = $this->card_payment_source( $token->id(), $wc_order ); + + $order = $this->order_endpoint->create( + array( $purchase_unit ), + $shipping_preference, + $payer, + null, + '', + ApplicationContext::USER_ACTION_CONTINUE, + '', + array(), + $payment_source + ); + + $this->handle_paypal_order( $wc_order, $order ); + + $this->logger->info( + sprintf( + 'Renewal for order %d is completed.', + $wc_order->get_id() + ) + ); + + return; + } + + if ( $wc_order->get_payment_method() === PayPalGateway::ID ) { + $order = $this->order_endpoint->create( + array( $purchase_unit ), + $shipping_preference, + $payer, + $token + ); + + $this->handle_paypal_order( $wc_order, $order ); + + $this->logger->info( + sprintf( + 'Renewal for order %d is completed.', + $wc_order->get_id() + ) + ); + } + } + } + + /** + * Returns a payment token for a customer. + * + * @param \WC_Customer $customer The customer. + * @param \WC_Order $wc_order The current WooCommerce order we want to process. + * + * @return PaymentToken|null|false + */ + private function get_token_for_customer( \WC_Customer $customer, \WC_Order $wc_order ) { + /** + * Returns a payment token for a customer, or null. + */ + $token = apply_filters( 'woocommerce_paypal_payments_subscriptions_get_token_for_customer', null, $customer, $wc_order ); + if ( null !== $token ) { + return $token; + } + + $tokens = $this->repository->all_for_user_id( (int) $customer->get_id() ); + if ( ! $tokens ) { + return false; + } + + $subscription = function_exists( 'wcs_get_subscription' ) ? wcs_get_subscription( $wc_order->get_meta( '_subscription_renewal' ) ) : null; + if ( $subscription ) { + $token_id = $subscription->get_meta( 'payment_token_id' ); + if ( $token_id ) { + foreach ( $tokens as $token ) { + if ( $token_id === $token->id() ) { + return $token; + } + } + } + } + + return current( $tokens ); + } + + /** + * Returns if an order should be captured immediately. + * + * @param Order $order The PayPal order. + * + * @return bool + * @throws NotFoundException When a setting was not found. + */ + protected function capture_authorized_downloads( Order $order ): bool { + if ( + ! $this->settings->has( 'capture_for_virtual_only' ) + || ! $this->settings->get( 'capture_for_virtual_only' ) + ) { + return false; + } + + if ( $order->intent() === 'CAPTURE' ) { + return false; + } + + /** + * We fetch the order again as the authorize endpoint (from which the Order derives) + * drops the item's category, making it impossible to check, if purchase units contain + * physical goods. + */ + $order = $this->order_endpoint->order( $order->id() ); + + foreach ( $order->purchase_units() as $unit ) { + if ( $unit->contains_physical_goods() ) { + return false; + } + } + return true; + } + + /** + * Handles PayPal order creation and updates WC order accordingly. + * + * @param \WC_Order $wc_order WC order. + * @param Order $order PayPal order. + * @return void + * @throws NotFoundException When something goes wrong while handling the order. + */ + private function handle_paypal_order( \WC_Order $wc_order, Order $order ): void { + $this->add_paypal_meta( $wc_order, $order, $this->environment ); + + if ( $order->intent() === 'AUTHORIZE' ) { + $order = $this->order_endpoint->authorize( $order ); + $wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'false' ); + } + + $transaction_id = $this->get_paypal_order_transaction_id( $order ); + if ( $transaction_id ) { + $this->update_transaction_id( $transaction_id, $wc_order ); + + $payment_source = $order->payment_source(); + if ( $payment_source instanceof PaymentSource ) { + $this->update_payment_source( $payment_source, $wc_order ); + } + } + + $this->handle_new_order_status( $order, $wc_order ); + + if ( $this->capture_authorized_downloads( $order ) ) { + $this->authorized_payments_processor->capture_authorized_payment( $wc_order ); + } + } + + /** + * Returns a Card payment source. + * + * @param string $token Vault token id. + * @param WC_Order $wc_order WC order. + * @return PaymentSource + * @throws NotFoundException If setting is not found. + */ + private function card_payment_source( string $token, WC_Order $wc_order ): PaymentSource { + $properties = array( + 'vault_id' => $token, + ); + + $subscriptions = wcs_get_subscriptions_for_renewal_order( $wc_order ); + $subscription = end( $subscriptions ); + if ( $subscription ) { + $transaction = $this->subscription_helper->previous_transaction( $subscription ); + if ( $transaction ) { + $properties['stored_credential'] = array( + 'payment_initiator' => 'MERCHANT', + 'payment_type' => 'RECURRING', + 'usage' => 'SUBSEQUENT', + 'previous_transaction_reference' => $transaction, + ); + } + } + + return new PaymentSource( + 'card', + (object) $properties + ); + } + + /** + * Updates the payment source name to the one really used for the payment. + * + * @param PaymentSource $payment_source The Payment Source. + * @param \WC_Order $wc_order WC order. + * @return void + */ + private function update_payment_source( PaymentSource $payment_source, \WC_Order $wc_order ): void { + if ( ! $payment_source->name() ) { + return; + } + try { + $wc_order->set_payment_method_title( $this->funding_source_renderer->render_name( $payment_source->name() ) ); + $wc_order->save(); + } catch ( \Exception $e ) { + $this->logger->error( + sprintf( + 'Failed to update payment source to "%1$s" on order %2$d', + $payment_source->name(), + $wc_order->get_id() + ) + ); + } + } +} diff --git a/modules/ppcp-subscription/src/SubscriptionsHandlerTrait.php b/modules/ppcp-wc-subscriptions/src/SubscriptionsHandlerTrait.php similarity index 78% rename from modules/ppcp-subscription/src/SubscriptionsHandlerTrait.php rename to modules/ppcp-wc-subscriptions/src/SubscriptionsHandlerTrait.php index ae9b35bfb..47140396a 100644 --- a/modules/ppcp-subscription/src/SubscriptionsHandlerTrait.php +++ b/modules/ppcp-wc-subscriptions/src/SubscriptionsHandlerTrait.php @@ -2,12 +2,12 @@ /** * Helper trait for the free trial subscriptions handling. * - * @package WooCommerce\PayPalCommerce\Subscription + * @package WooCommerce\PayPalCommerce\WcSubscriptions */ declare(strict_types=1); -namespace WooCommerce\PayPalCommerce\Subscription; +namespace WooCommerce\PayPalCommerce\WcSubscriptions; use WC_Subscriptions; diff --git a/modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php b/modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php new file mode 100644 index 000000000..9d19dc0ac --- /dev/null +++ b/modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php @@ -0,0 +1,375 @@ +renew( $order, $c ); + }, + 10, + 2 + ); + + add_action( + 'woocommerce_scheduled_subscription_payment_' . CreditCardGateway::ID, + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ + function ( $amount, $order ) use ( $c ) { + $this->renew( $order, $c ); + }, + 10, + 2 + ); + + add_action( + 'woocommerce_subscription_payment_complete', + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ + function ( $subscription ) use ( $c ) { + if ( ! in_array( $subscription->get_payment_method(), array( PayPalGateway::ID, CreditCardGateway::ID, CardButtonGateway::ID ), true ) ) { + return; + } + + $paypal_subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; + if ( $paypal_subscription_id ) { + return; + } + + $payment_token_repository = $c->get( 'vaulting.repository.payment-token' ); + $logger = $c->get( 'woocommerce.logger.woocommerce' ); + + if ( ! $c->has( 'save-payment-methods.eligible' ) || ! $c->get( 'save-payment-methods.eligible' ) ) { + $this->add_payment_token_id( $subscription, $payment_token_repository, $logger ); + } + + if ( count( $subscription->get_related_orders() ) === 1 ) { + $parent_order = $subscription->get_parent(); + if ( is_a( $parent_order, WC_Order::class ) ) { + // Update the initial payment method title if not the same as the first order. + $payment_method_title = $parent_order->get_payment_method_title(); + if ( + $payment_method_title + && $subscription instanceof \WC_Subscription + && $subscription->get_payment_method_title() !== $payment_method_title + ) { + $subscription->set_payment_method_title( $payment_method_title ); + $subscription->save(); + } + } + } + } + ); + + add_filter( + 'woocommerce_gateway_description', + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ + function ( $description, $id ) use ( $c ) { + $payment_token_repository = $c->get( 'vaulting.repository.payment-token' ); + $settings = $c->get( 'wcgateway.settings' ); + $subscription_helper = $c->get( 'wc-subscriptions.helper' ); + + return $this->display_saved_paypal_payments( $settings, (string) $id, $payment_token_repository, (string) $description, $subscription_helper ); + }, + 10, + 2 + ); + + add_filter( + 'woocommerce_credit_card_form_fields', + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ + function ( $default_fields, $id ) use ( $c ) { + if ( $c->has( 'save-payment-methods.eligible' ) && $c->get( 'save-payment-methods.eligible' ) ) { + return $default_fields; + } + + $payment_token_repository = $c->get( 'vaulting.repository.payment-token' ); + $settings = $c->get( 'wcgateway.settings' ); + $subscription_helper = $c->get( 'wc-subscriptions.helper' ); + + return $this->display_saved_credit_cards( $settings, $id, $payment_token_repository, $default_fields, $subscription_helper ); + }, + 20, + 2 + ); + + 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; + } + + //phpcs:disable WordPress.Security.NonceVerification.Recommended + if ( ! ( isset( $_GET['change_payment_method'] ) && is_wc_endpoint_url( 'order-pay' ) ) ) { + return $methods; + } + + $paypal_tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), PayPalGateway::ID ); + if ( ! $paypal_tokens ) { + unset( $methods[ PayPalGateway::ID ] ); + } + + if ( $c->has( 'save-payment-methods.eligible' ) && $c->get( 'save-payment-methods.eligible' ) ) { + return $methods; + } + + $card_tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), CreditCardGateway::ID ); + if ( ! $card_tokens ) { + unset( $methods[ CreditCardGateway::ID ] ); + } + + return $methods; + } + ); + + add_filter( + 'woocommerce_subscription_payment_method_to_display', + /** + * Corrects the payment method name for subscriptions. + * + * @param string $payment_method_to_display The payment method string. + * @param \WC_Subscription $subscription The subscription instance. + * @param string $context The context, ex: view. + * @return string + * + * @psalm-suppress MissingClosureParamType + */ + function ( $payment_method_to_display, $subscription, $context ) { + $payment_gateway = wc_get_payment_gateway_by_order( $subscription ); + + if ( $payment_gateway instanceof \WC_Payment_Gateway && $payment_gateway->id === PayPalGateway::ID ) { + return $subscription->get_payment_method_title( $context ); + } + + return $payment_method_to_display; + }, + 10, + 3 + ); + + add_action( + 'wc_ajax_' . SubscriptionChangePaymentMethod::ENDPOINT, + static function () use ( $c ) { + $endpoint = $c->get( 'wc-subscriptions.endpoint.subscription-change-payment-method' ); + assert( $endpoint instanceof SubscriptionChangePaymentMethod ); + + $endpoint->handle_request(); + } + ); + } + + /** + * Returns the key for the module. + * + * @return string|void + */ + public function getKey() { + } + + /** + * Handles a Subscription product renewal. + * + * @param WC_Order $order WooCommerce order. + * @param ContainerInterface $container The container. + * @return void + */ + protected function renew( WC_Order $order, ContainerInterface $container ) { + $handler = $container->get( 'wc-subscriptions.renewal-handler' ); + assert( $handler instanceof RenewalHandler ); + + $handler->renew( $order ); + } + + /** + * Adds Payment token ID to subscription. + * + * @param \WC_Subscription $subscription The subscription. + * @param PaymentTokenRepository $payment_token_repository The payment repository. + * @param LoggerInterface $logger The logger. + */ + protected function add_payment_token_id( + \WC_Subscription $subscription, + PaymentTokenRepository $payment_token_repository, + LoggerInterface $logger + ): void { + try { + $tokens = $payment_token_repository->all_for_user_id( $subscription->get_customer_id() ); + if ( $tokens ) { + $latest_token_id = end( $tokens )->id() ? end( $tokens )->id() : ''; + $subscription->update_meta_data( 'payment_token_id', $latest_token_id ); + $subscription->save(); + } + } catch ( RuntimeException $error ) { + $message = sprintf( + // translators: %1$s is the payment token Id, %2$s is the error message. + __( + 'Could not add token Id to subscription %1$s: %2$s', + 'woocommerce-paypal-payments' + ), + $subscription->get_id(), + $error->getMessage() + ); + + $logger->log( 'warning', $message ); + } + } + + /** + * Displays saved PayPal payments. + * + * @param Settings $settings The settings. + * @param string $id The payment gateway Id. + * @param PaymentTokenRepository $payment_token_repository The payment token repository. + * @param string $description The payment gateway description. + * @param SubscriptionHelper $subscription_helper The subscription helper. + * @return string + */ + protected function display_saved_paypal_payments( + Settings $settings, + string $id, + PaymentTokenRepository $payment_token_repository, + string $description, + SubscriptionHelper $subscription_helper + ): string { + if ( $settings->has( 'vault_enabled' ) + && $settings->get( 'vault_enabled' ) + && PayPalGateway::ID === $id + && $subscription_helper->is_subscription_change_payment() + ) { + $tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), PayPalGateway::ID ); + + $output = '
    '; + foreach ( $tokens as $token ) { + $output .= '
  • '; + $output .= sprintf( '', $token->get_id() ); + $output .= sprintf( '', $token->get_type(), $token->get_meta( 'email' ) ?? '' ); + $output .= '
  • '; + } + $output .= '
'; + + return $output; + } + + return $description; + } + + /** + * Displays saved credit cards. + * + * @param Settings $settings The settings. + * @param string $id The payment gateway Id. + * @param PaymentTokenRepository $payment_token_repository The payment token repository. + * @param array $default_fields Default payment gateway fields. + * @param SubscriptionHelper $subscription_helper The subscription helper. + * @return array|mixed|string + * @throws NotFoundException When setting was not found. + */ + protected function display_saved_credit_cards( + Settings $settings, + string $id, + PaymentTokenRepository $payment_token_repository, + array $default_fields, + SubscriptionHelper $subscription_helper + ) { + if ( $settings->has( 'vault_enabled_dcc' ) + && $settings->get( 'vault_enabled_dcc' ) + && $subscription_helper->is_subscription_change_payment() + && CreditCardGateway::ID === $id + ) { + $tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), CreditCardGateway::ID ); + $output = sprintf( + '

'; + + $default_fields = array(); + $default_fields['saved-credit-card'] = $output; + return $default_fields; + } + + return $default_fields; + } +} diff --git a/modules/ppcp-webhooks/src/Handler/BillingPlanPricingChangeActivated.php b/modules/ppcp-webhooks/src/Handler/BillingPlanPricingChangeActivated.php index 7a1461caf..8716f8714 100644 --- a/modules/ppcp-webhooks/src/Handler/BillingPlanPricingChangeActivated.php +++ b/modules/ppcp-webhooks/src/Handler/BillingPlanPricingChangeActivated.php @@ -71,7 +71,6 @@ class BillingPlanPricingChangeActivated implements RequestHandler { $plan_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) ); if ( $plan_id && ! empty( $request['resource']['billing_cycles'] ) ) { - $this->logger->info( 'Starting stuff...' ); $args = array( // phpcs:ignore WordPress.DB.SlowDBQuery 'meta_key' => 'ppcp_subscription_plan', diff --git a/modules/ppcp-webhooks/src/Handler/VaultPaymentTokenCreated.php b/modules/ppcp-webhooks/src/Handler/VaultPaymentTokenCreated.php index 893305c75..e1f202ef5 100644 --- a/modules/ppcp-webhooks/src/Handler/VaultPaymentTokenCreated.php +++ b/modules/ppcp-webhooks/src/Handler/VaultPaymentTokenCreated.php @@ -115,6 +115,11 @@ class VaultPaymentTokenCreated implements RequestHandler { * @return WP_REST_Response */ public function handle_request( WP_REST_Request $request ): WP_REST_Response { + $resource_version = $request['resource_version'] ?? ''; + if ( $resource_version && $resource_version !== '2.0' ) { + return $this->success_response(); + } + $customer_id = null !== $request['resource'] && isset( $request['resource']['customer_id'] ) ? $request['resource']['customer_id'] : ''; diff --git a/modules/ppcp-webhooks/src/IncomingWebhookEndpoint.php b/modules/ppcp-webhooks/src/IncomingWebhookEndpoint.php index 6b61d9c1a..cf2d03989 100644 --- a/modules/ppcp-webhooks/src/IncomingWebhookEndpoint.php +++ b/modules/ppcp-webhooks/src/IncomingWebhookEndpoint.php @@ -248,9 +248,14 @@ class IncomingWebhookEndpoint { } } + $event_type = $request['event_type'] ?: ''; + if ( in_array( $event_type, array( 'BILLING_AGREEMENTS.AGREEMENT.CREATED' ), true ) ) { + return $this->success_response(); + } + $message = sprintf( 'Could not find handler for request type %s', - $request['event_type'] ?: '' + $event_type ); return $this->failure_response( $message ); } diff --git a/package.json b/package.json index 7bf456908..a0e2d325a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "woocommerce-paypal-payments", - "version": "2.4.2", + "version": "2.6.1", "description": "WooCommerce PayPal Payments", "repository": "https://github.com/woocommerce/woocommerce-paypal-payments", "license": "GPL-2.0", @@ -9,35 +9,44 @@ "postinstall": "run-s install:modules:* && run-s build:modules", "install:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn install", "install:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn install", + "install:modules:ppcp-paylater-block": "cd modules/ppcp-paylater-block && yarn install", + "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-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", - "install:modules:ppcp-subscription": "cd modules/ppcp-subscription && yarn install", + "install:modules:ppcp-paypal-subscriptions": "cd modules/ppcp-paypal-subscriptions && yarn install", + "install:modules:ppcp-save-payment-methods": "cd modules/ppcp-save-payment-methods && yarn install", "install:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn install", "install:modules:ppcp-compat": "cd modules/ppcp-compat && yarn install", "install:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn install", "build:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run build", "build:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn run build", + "build:modules:ppcp-paylater-block": "cd modules/ppcp-paylater-block && yarn run build", + "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-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", - "build:modules:ppcp-subscription": "cd modules/ppcp-subscription && yarn run build", + "build:modules:ppcp-save-payment-methods": "cd modules/ppcp-save-payment-methods && yarn run build", + "build:modules:ppcp-paypal-subscriptions": "cd modules/ppcp-paypal-subscriptions && yarn run build", "build:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn run build", "build:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run build", "build:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run build", "build:modules": "run-p build:modules:*", "watch:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run watch", "watch:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn run watch", + "watch:modules:ppcp-paylater-block": "cd modules/ppcp-paylater-block && yarn run watch", + "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-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", - "watch:modules:ppcp-subscription": "cd modules/ppcp-subscription && yarn run watch", + "watch:modules:ppcp-paypal-subscriptions": "cd modules/ppcp-paypal-subscriptions && yarn run watch", + "watch:modules:ppcp-save-payment-methods": "cd modules/ppcp-save-payment-methods && yarn run watch", "watch:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn run watch", "watch:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run watch", "watch:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run watch", diff --git a/readme.txt b/readme.txt index 47f7f5dd7..bbf1fecfc 100644 --- a/readme.txt +++ b/readme.txt @@ -2,9 +2,9 @@ Contributors: woocommerce, automattic, inpsyde Tags: woocommerce, paypal, payments, ecommerce, checkout, cart, pay later, apple pay, subscriptions, debit card, credit card, google pay Requires at least: 5.3 -Tested up to: 6.4 +Tested up to: 6.5 Requires PHP: 7.2 -Stable tag: 2.4.2 +Stable tag: 2.6.1 License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -52,16 +52,16 @@ With the [Vaulting](https://www.paypal.com/us/brc/article/securely-store-payment It’s easy for shoppers, simple for you, and great for your business – with no monthly or setup fees. = Activate PayPal = -Are you new to PayPal? [Learn how to add it to your store.](https://woocommerce.com/document/woocommerce-paypal-payments/) +Are you new to PayPal? [Learn how to add it to your store.](https://woocommerce.com/document/woocommerce-paypal-payments/) Need to update your existing PayPal integration? [Learn how to upgrade your integration.](https://woocommerce.com/document/woocommerce-paypal-payments/paypal-payments-upgrade-guide/) [Watch the video on how to activate PayPal for your WooCommerce store](https://woocommerce.com/document/woocommerce-paypal-payments/#complete-setup-video) = More reasons it pays to PayPal = - **Instant access to funds**: Access card payments, send money or make a payment from your bank account. You’re credited immediately while the payment is processing. Funds settle instantly into your PayPal business account. - + - **Fraud Detection**: Save time and money by letting PayPal help you handle the risk of fraudulent transactions with our fraud, chargeback, and Seller Protection capabilities (on eligible transactions†). Our AI technology works hard to monitor all of your transactions — so you can focus on what matters most. †Available on eligible purchases. Limits apply. - + - **Global compliance**: PayPal payment solutions help you meet your global compliance standards, such as PCI and PSD2, bringing international markets within reach for your business. Our platform has built-in compliance with two-factor authentication provided by cards (3D Secure). We include automatic updates as security protocols change. --- @@ -80,17 +80,17 @@ Need to update your existing PayPal integration? [Learn how to upgrade your inte = Where can I find the WooCommerce PayPal Payments documentation and setup guide? = -For help setting up and configuring WooCommerce PayPal Payments, please refer to the documentation. [Learn how to add PayPal to your store.](https://woocommerce.com/document/woocommerce-paypal-payments/) +For help setting up and configuring WooCommerce PayPal Payments, please refer to the documentation. [Learn how to add PayPal to your store.](https://woocommerce.com/document/woocommerce-paypal-payments/) Need to update your existing PayPal integration? [Learn how to upgrade your integration.](https://woocommerce.com/document/woocommerce-paypal-payments/paypal-payments-upgrade-guide/) = Where can I get help for WooCommerce PayPal Payments? = -For questions regarding the plugin setup, we recommend reviewing our [documentation](https://woocommerce.com/document/woocommerce-paypal-payments/) and the [troubleshooting guide](https://woocommerce.com/document/woocommerce-paypal-payments/#troubleshooting) if you encounter any issues. -If the question or problem persists after reviewing the documentation, kindly create a new thread in the [support forums](https://wordpress.org/support/plugin/woocommerce-paypal-payments/#new-topic-0) or open a support ticket via [our helpdesk](https://woocommerce.com/document/woocommerce-paypal-payments/#get-help). +For questions regarding the plugin setup, we recommend reviewing our [documentation](https://woocommerce.com/document/woocommerce-paypal-payments/) and the [troubleshooting guide](https://woocommerce.com/document/woocommerce-paypal-payments/#troubleshooting) if you encounter any issues. +If the question or problem persists after reviewing the documentation, kindly create a new thread in the [support forums](https://wordpress.org/support/plugin/woocommerce-paypal-payments/#new-topic-0) or open a support ticket via [our helpdesk](https://woocommerce.com/document/woocommerce-paypal-payments/#get-help). = WooCommerce PayPal Payments suddenly no longer works – what do I do? = -Start by diagnosing the issue using our helpful [troubleshooting guide](https://woocommerce.com/document/woocommerce-paypal-payments/#troubleshooting). +Start by diagnosing the issue using our helpful [troubleshooting guide](https://woocommerce.com/document/woocommerce-paypal-payments/#troubleshooting). If you notice an error or any other issue after updating a plugin or the theme, there could be a potential compatibility issue between it and WooCommerce PayPal Payments. In such cases, we recommend running a [conflict test](https://github.com/woocommerce/woocommerce-paypal-payments/wiki/Advanced-Troubleshooting) using [Health Check](https://github.com/woocommerce/woocommerce-paypal-payments/wiki/Advanced-Troubleshooting#test-on-staging) (which allows you to disable themes and plugins without affecting your visitors) or troubleshooting the issue using a [staging site](https://github.com/woocommerce/woocommerce-paypal-payments/wiki/Advanced-Troubleshooting#test-on-staging). @@ -123,7 +123,7 @@ View the [Testing features previews FAQ](https://github.com/woocommerce/woocomme = WooCommerce PayPal Payments is awesome! Can I contribute? = Yes, you can! Contributions are always appreciated. Join in on our [GitHub repository](https://github.com/woocommerce/woocommerce-paypal-payments/issues) to stay up-to-date with the latest developments. -If you like the plugin, please also consider leaving a review [here](https://wordpress.org/support/plugin/woocommerce-paypal-payments/reviews/#new-post) or [here](https://woocommerce.com/de-de/products/woocommerce-paypal-payments/#reviews) to share your valuable feedback with other users as it is much appreciated. +If you like the plugin, please also consider leaving a review [here](https://wordpress.org/support/plugin/woocommerce-paypal-payments/reviews/#new-post) or [here](https://woocommerce.com/de-de/products/woocommerce-paypal-payments/#reviews) to share your valuable feedback with other users as it is much appreciated. = My question is not listed here. Where can I find more answers? = @@ -179,7 +179,108 @@ If you encounter issues with the PayPal buttons not appearing after an update, p == Changelog == -= 2.4.2 - xxx-xx-xx = += 2.6.1 - 2024-04-09 = +* Fix - Payment tokens fixes and adjustments #2106 +* Fix - Pay upon Invoice: Add input validation to Experience Context fields #2092 +* Fix - Disable markup in get_plugin_data() returns to fix an issue with wptexturize() #2094 +* Fix - Problem changing the shipping option in block pages #2142 +* Fix - Saved payment token deleted after payment with another saved payment token #2146 +* Enhancement - Pay later messaging configurator improvements #2107 +* Enhancement - Replace the middleware URL from connect.woocommerce.com to api.woocommerce.com/integrations #2130 +* Enhancement - Remove all Sofort references as it has been deprecated #2124 +* Enhancement - Improve funding source names #2118 +* Enhancement - More fraud prevention capabilities by storing additional data in the order #2125 +* Enhancement - Update ACDC currency eligibility for AMEX #2129 +* Enhancement - Sync shipping options with Venmo when skipping final confirmation on Checkout #2108 +* Enhancement - Card Fields: Add a filter for the CVC field and update the placeholder to match the label #2089 +* Enhancement - Product Title: Sanitize before sending to PayPal #2090 +* Enhancement - Add filter for disabling permit_multiple_payment_tokens vault attribute #2136 +* Enhancement - Filter to hide PayPal email address not working on order detail #2137 + += 2.6.0 - 2024-03-20 = +* Fix - invoice_id not included in API call when creating payment with saved card #2086 +* Fix - Typo in SCA indicators for ACDC Vault transactions #2083 +* Fix - Payments with saved card tokens use Capture intent when Authorize is configured #2069 +* Fix - WooPayments multi-currency causing currency mismatch error on Block Cart & Checkout pages #2054 +* Fix - "Must pass createSubscription with intent=subscription" error with PayPal Subscriptions mode #2058 +* Fix - "Proceed to PayPal" button displayed for Free trial PayPal Subscription products when payment token is saved #2041 +* Fix - ACDC payments with new credit card may fail when debugging is enabled (JSON malformed by warning) #2051 +* Enhancement - Add Pay Later Messaging block #1897 +* Enhancement - Submit the form instead of refreshing the page to show the save notice #2081 +* Enhancement - Integrate pay later messaging block with the messaging configurator #2080 +* Enhancement - Reauthorize authorized payments #2062 +* Enhancement - Do not handle VAULT.PAYMENT-TOKEN.CREATED webhook for Vault v3 #2079 +* Enhancement - Improve the messaging configurator styles #2053 +* Enhancement - Ensure PayPal Vaulting is not selected as Subscriptions Mode when Reference Transactions are disabled #2057 +* Enhancement - Pay later messaging configurator & messaging block adjustments #2096 + += 2.5.4 - 2024-02-27 = +* Fix - Cannot enable Apple Pay when API credentials were manually created #2015 +* Fix - Cart simulation type error #1943 +* Enhancement - Apple Pay recurring payments #1986 +* Enhancement - Real Time Account Updater (RTAU) integration #2027 +* Enhancement - Prepare the SKU for sending to PayPal #2033 +* Enhancement - Store the Card Brand in Address Verification Result instead of 3DS authentication result #2026 +* Enhancement - Update country eligibility for AdvancedCard Processing, Apple Pay, Google Pay #2019 +* Enhancement - Disable PayPal Vaulting setting instead of hiding it when Reference Transactions not available #2029 +* Enhancement - Store three d secure enrollment status and authentication status responses in wc order #1980 +* Enhancement - Add more checks to prevent "PayPal order ID not found" errors #2038 +* Enhancement - Disable messaging configurator when vault is enabled #2042 +* Feature preview - Pay Later Messaging configurator #1924 + += 2.5.3 - 2024-02-06 = +* Fix - Free trial subscription products using PayPal Vaulting when PayPal Subscriptions configured as Subscriptions Mode #1979 +* Fix - Pay by link - Germany - PayPal buttons are not visible on Pay for order page #2014 +* Enhancement - Extend Apple Pay, Google Pay, Vault v3 (& RTAU) country availability #1992 +* Enhancement - Enable card fields for ACDC and Vault v3 supported countries/currencies #2007 +* Enhancement - Update ACDC supported currencies list #1991 +* Enhancement - Check if the $wpdb->wc_orders exists before query #1996 +* Enhancement - Remove MercadoPago from disable funding sources #2003 +* Enhancement - Improve onboarding notice text #2002 + += 2.5.2 - 2024-02-01 = +* Fix - NOT_ENABLED_TO_VAULT_PAYMENT_SOURCE error for merchants without reference transactions #1984 +* Fix - Fatal error in WooCommerce PayPal Payments plugin after 2.5.0 update #1985 +* Fix - Can not refund order purchased with Vault v3 Card payment #1997 +* Fix - PayPal Vaulting Subscriptions mode setting visible when merchant not enabled for Reference Transactions #1999 +* Fix - card-fields parameter included in button script despite Advanced Card Processing disabled #2005 +* Enhancement - Add setup URL for reference transactions #1964 +* Enhancement - Improve PUI performance for variable products #1950 + += 2.5.1 - 2024-01-24 = +* Temporary revert Vaulting integration changes introduced in 2.5.0 + += 2.5.0 - 2024-01-22 = +* Fix - WC Subscriptions change subscription payment #1953 +* Fix - GooglePay and ApplePay buttons disappear from the minicart when adding a product to the cart on the shop page #1915 +* Enhancement - Enable Vault v3 and Card Fields by default for US merchants #1967 +* Enhancement - Vault v3 WC Subscriptions integration #1920 +* Enhancement - Implement early WC validation for Hosted Card Fields #1925 +* Enhancement - Rename button locations #1946 +* Enhancement - Improve Apple Pay validation notice text #1938 +* Enhancement - Improve feature availability check UX #1941 +* Enhancement - Make all hosted card fields strings translatable #1926 +* Enhancement - PHP 8.2 deprecations #1939 +* Enhancement - Subscription support on Block Cart & Block Express Checkout #1956 +* Enhancement - Venmo Vaulting integration #1958 +* Enhancement - Add package tracking support for UK #1970 + += 2.4.3 - 2024-01-04 = +* Fix - PayPal Subscription initiated without a WooCommerce order #1907 +* Fix - Block Checkout reloads when submitting order with empty fields #1904 +* Fix - "Send checkout billing and shipping data to Apple Pay" displayed when Apple Pay is disabled #1883 +* Fix - "Order does not contain intent" error for ACDC renewals when triggering 3D Secure #1888 +* Fix - PayPal Subscriptions button greyed out (inactive) on Checkout page for variable subscription products #1914 +* Enhancement - Add button to reload feature eligibility status from Connection tab #1902 +* Enhancement - Apple Pay validation message improvements #1901 +* Enhancement - Improve support for Classic Cart & Classic Checkout blocks #1894 +* Enhancement - Ensure uniform button appearance for PayPal, Google Pay, and Apple Pay buttons #1900 +* Enhancement - remove string translations for package tracking carriers from repository #1885 +* Enhancement - Incorrect margins when PayPal buttons are rendered as separate gateways. #1908 +* Enhancement - Improved button spacing when Apple Pay is enabled but current buyer is not eligible #1922 +* Feature preview - Save payment methods (Vault v3) integration #1779 + += 2.4.2 - 2023-12-04 = * Fix - Action callback arguments count in ShipStation tracking integration #1841 * Fix - Google Pay scripts loading on unrelated admin pages #1834 * Fix - Do not ignore disabled APMs list in blocks #1865 @@ -291,7 +392,7 @@ If you encounter issues with the PayPal buttons not appearing after an update, p * Feature preview - Google Pay integration #1654 = 2.2.2 - 2023-08-29 = -* Fix - High rate of auth voids on vaulted subscriptions for guest users #1529 +* Fix - High rate of auth voids on vaulted subscriptions for guest users #1529 * Enhancement - HPOS compatibility issues #1594 * Feature preview - PayPal Subscriptions API fixes and improvements #1600 #1607 diff --git a/src/FilePathPluginFactory.php b/src/FilePathPluginFactory.php index 69d118fbb..15f4f761d 100644 --- a/src/FilePathPluginFactory.php +++ b/src/FilePathPluginFactory.php @@ -65,7 +65,7 @@ class FilePathPluginFactory implements FilePathPluginFactoryInterface { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } - $plugin_data = get_plugin_data( $filePath ); + $plugin_data = get_plugin_data( $filePath, false ); if ( empty( $plugin_data ) ) { throw new UnexpectedValueException( sprintf( diff --git a/tests/PHPUnit/ApiClient/Endpoint/OrderEndpointTest.php b/tests/PHPUnit/ApiClient/Endpoint/OrderEndpointTest.php index 5041bf16a..557551f8f 100644 --- a/tests/PHPUnit/ApiClient/Endpoint/OrderEndpointTest.php +++ b/tests/PHPUnit/ApiClient/Endpoint/OrderEndpointTest.php @@ -26,7 +26,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\ErrorResponse; use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository; use Mockery; use Psr\Log\LoggerInterface; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\TestCase; use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNet; use function Brain\Monkey\Functions\expect; @@ -1149,6 +1149,7 @@ class OrderEndpointTest extends TestCase $logger = Mockery::mock(LoggerInterface::class); $logger->shouldReceive('log'); $logger->shouldReceive('debug'); + $logger->shouldReceive('warning'); $applicationContext = Mockery::mock(ApplicationContext::class); $applicationContext ->expects('to_array') diff --git a/tests/PHPUnit/ApiClient/Endpoint/OrderTest.php b/tests/PHPUnit/ApiClient/Endpoint/OrderTest.php index e2c120751..6c8abb05f 100644 --- a/tests/PHPUnit/ApiClient/Endpoint/OrderTest.php +++ b/tests/PHPUnit/ApiClient/Endpoint/OrderTest.php @@ -34,9 +34,6 @@ class OrderTest extends TestCase ->expects('to_array') ->andReturn(['applicationContext']); $paymentSource = Mockery::mock(PaymentSource::class); - $paymentSource - ->expects('to_array') - ->andReturn(['paymentSource']); $testee = new Order( $id, @@ -68,8 +65,7 @@ class OrderTest extends TestCase 'create_time' => $createTime->format($this->dateFormat), 'update_time' => $updateTime->format($this->dateFormat), 'payer' => ['payer'], - 'application_context' => ['applicationContext'], - 'payment_source' => ['paymentSource'] + 'application_context' => ['applicationContext'] ]; $this->assertEquals($expected, $testee->to_array()); } diff --git a/tests/PHPUnit/ApiClient/Entity/AuthorizationTest.php b/tests/PHPUnit/ApiClient/Entity/AuthorizationTest.php index 8843ce002..c5895a2f4 100644 --- a/tests/PHPUnit/ApiClient/Entity/AuthorizationTest.php +++ b/tests/PHPUnit/ApiClient/Entity/AuthorizationTest.php @@ -11,7 +11,7 @@ class AuthorizationTest extends TestCase public function testIdAndStatus() { $authorizationStatus = \Mockery::mock(AuthorizationStatus::class); - $testee = new Authorization('foo', $authorizationStatus); + $testee = new Authorization('foo', $authorizationStatus, null); $this->assertEquals('foo', $testee->id()); $this->assertEquals($authorizationStatus, $testee->status()); @@ -22,7 +22,7 @@ class AuthorizationTest extends TestCase $authorizationStatus = \Mockery::mock(AuthorizationStatus::class); $authorizationStatus->expects('name')->andReturn('CAPTURED'); - $testee = new Authorization('foo', $authorizationStatus); + $testee = new Authorization('foo', $authorizationStatus, null); $expected = [ 'id' => 'foo', diff --git a/tests/PHPUnit/ApiClient/Factory/AuthorizationFactoryTest.php b/tests/PHPUnit/ApiClient/Factory/AuthorizationFactoryTest.php index 12a76a016..71df98376 100644 --- a/tests/PHPUnit/ApiClient/Factory/AuthorizationFactoryTest.php +++ b/tests/PHPUnit/ApiClient/Factory/AuthorizationFactoryTest.php @@ -17,8 +17,9 @@ class AuthorizationFactoryTest extends TestCase 'id' => 'foo', 'status' => 'CAPTURED', ]; + $fraudProcessorResponseFactory = \Mockery::mock(FraudProcessorResponseFactory::class); - $testee = new AuthorizationFactory(); + $testee = new AuthorizationFactory($fraudProcessorResponseFactory); $result = $testee->from_paypal_response($response); $this->assertInstanceOf(Authorization::class, $result); @@ -36,7 +37,9 @@ class AuthorizationFactoryTest extends TestCase 'status' => 'CAPTURED', ]; - $testee = new AuthorizationFactory(); + $fraudProcessorResponseFactory = \Mockery::mock(FraudProcessorResponseFactory::class); + + $testee = new AuthorizationFactory($fraudProcessorResponseFactory); $testee->from_paypal_response($response); } @@ -47,7 +50,9 @@ class AuthorizationFactoryTest extends TestCase 'id' => 'foo', ]; - $testee = new AuthorizationFactory(); + $fraudProcessorResponseFactory = \Mockery::mock(FraudProcessorResponseFactory::class); + + $testee = new AuthorizationFactory($fraudProcessorResponseFactory); $testee->from_paypal_response($response); } } diff --git a/tests/PHPUnit/ApiClient/Factory/ItemFactoryTest.php b/tests/PHPUnit/ApiClient/Factory/ItemFactoryTest.php index f8eedb3bb..65d41e881 100644 --- a/tests/PHPUnit/ApiClient/Factory/ItemFactoryTest.php +++ b/tests/PHPUnit/ApiClient/Factory/ItemFactoryTest.php @@ -312,11 +312,12 @@ class ItemFactoryTest extends TestCase $result = $testee->from_wc_order($order); $item = current($result); + /** * @var Item $item */ - $this->assertEquals(mb_substr($name, 0, 127), $item->name()); - $this->assertEquals(substr($description, 0, 127), $item->description()); + $this->assertEquals(substr( strip_shortcodes( wp_strip_all_tags( $name ) ), 0, 127 ), $item->name()); + $this->assertEquals(substr( strip_shortcodes( wp_strip_all_tags( $description ) ), 0, 127 ), $item->description()); } public function testFromPayPalResponse() diff --git a/tests/PHPUnit/Button/Helper/ThreeDSecureTest.php b/tests/PHPUnit/Button/Helper/ThreeDSecureTest.php index 406e9fd64..bfe6f4e85 100644 --- a/tests/PHPUnit/Button/Helper/ThreeDSecureTest.php +++ b/tests/PHPUnit/Button/Helper/ThreeDSecureTest.php @@ -3,15 +3,12 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Button\Helper; - use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource; -use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSourceCard; +use WooCommerce\PayPalCommerce\ApiClient\Factory\CardAuthenticationResultFactory; use WooCommerce\PayPalCommerce\TestCase; -use Mockery\Mock; -use function Brain\Monkey\Functions\when; class ThreeDSecureTest extends TestCase { @@ -23,21 +20,35 @@ class ThreeDSecureTest extends TestCase */ public function testDefault(int $expected, string $liabilityShift, string $authenticationResult, string $enrollment) { - $result = \Mockery::mock(CardAuthenticationResult::class); - $result->shouldReceive('liability_shift')->andReturn($liabilityShift); - $result->shouldReceive('authentication_result')->andReturn($authenticationResult); - $result->shouldReceive('enrollment_status')->andReturn($enrollment); - $result->shouldReceive('to_array')->andReturn(['foo' => 'bar',]); - $card = \Mockery::mock(PaymentSourceCard::class); - $card->shouldReceive('authentication_result')->andReturn($result); - $source = \Mockery::mock(PaymentSource::class); - $source->shouldReceive('card')->andReturn($card); - $order = \Mockery::mock(Order::class); - $order->shouldReceive('payment_source')->andReturn($source); - $logger = \Mockery::mock(LoggerInterface::class); - $logger->shouldReceive('info'); + $authResult = \Mockery::mock(CardAuthenticationResult::class); + $authResult->shouldReceive('liability_shift')->andReturn($liabilityShift); + $authResult->shouldReceive('authentication_result')->andReturn($authenticationResult); + $authResult->shouldReceive('enrollment_status')->andReturn($enrollment); + $authResult->shouldReceive('to_array')->andReturn(['foo' => 'bar',]); - $testee = new ThreeDSecure($logger); + $authenticationResultFactory = \Mockery::mock(CardAuthenticationResultFactory::class); + $authenticationResultFactory->shouldReceive('from_paypal_response') + ->andReturn($authResult); + + $source = \Mockery::mock(PaymentSource::class); + $authentication_result = (object)[ + 'brand' => 'visa', + 'authentication_result' => (object)array( + 'liability_shift' => $liabilityShift, + 'authentication_result' => $authenticationResult, + 'enrollment_status' => $enrollment + ), + ]; + + $source->shouldReceive('properties')->andReturn($authentication_result); + + $order = \Mockery::mock(Order::class); + $order->shouldReceive('payment_source')->andReturn($source); + + $logger = \Mockery::mock(LoggerInterface::class); + $logger->shouldReceive('info'); + + $testee = new ThreeDSecure($authenticationResultFactory, $logger); $result = $testee->proceed_with_order($order); $this->assertEquals($expected, $result); } diff --git a/tests/PHPUnit/Subscription/RenewalHandlerTest.php b/tests/PHPUnit/Subscription/RenewalHandlerTest.php deleted file mode 100644 index 84ecb0447..000000000 --- a/tests/PHPUnit/Subscription/RenewalHandlerTest.php +++ /dev/null @@ -1,168 +0,0 @@ -logger = Mockery::mock(LoggerInterface::class); - $this->repository = Mockery::mock(PaymentTokenRepository::class); - $this->orderEndpoint = Mockery::mock(OrderEndpoint::class); - $this->purchaseUnitFactory = Mockery::mock(PurchaseUnitFactory::class); - $this->shippingPreferenceFactory = Mockery::mock(ShippingPreferenceFactory::class); - $this->payerFactory = Mockery::mock(PayerFactory::class); - $this->environment = new Environment(new Dictionary([])); - $authorizedPaymentProcessor = Mockery::mock(AuthorizedPaymentsProcessor::class); - $settings = Mockery::mock(Settings::class); - $settings - ->shouldReceive('has') - ->andReturnFalse(); - - $this->logger->shouldReceive('error')->andReturnUsing(function ($msg) { - throw new Exception($msg); - }); - $this->logger->shouldReceive('info'); - - $this->sut = new RenewalHandler( - $this->logger, - $this->repository, - $this->orderEndpoint, - $this->purchaseUnitFactory, - $this->shippingPreferenceFactory, - $this->payerFactory, - $this->environment, - $settings, - $authorizedPaymentProcessor - ); - } - - /** - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testRenewProcessOrder() - { - $transactionId = 'ABC123'; - $wcOrder = Mockery::mock(\WC_Order::class); - $customer = Mockery::mock('overload:WC_Customer'); - $token = Mockery::mock(PaymentToken::class); - $payer = Mockery::mock(Payer::class); - $order = Mockery::mock(Order::class); - - $capture = Mockery::mock(Capture::class); - $capture->expects('id') - ->andReturn($transactionId); - $capture->expects('status') - ->andReturn(new CaptureStatus(CaptureStatus::COMPLETED)); - - $payments = Mockery::mock(Payments::class); - $payments->shouldReceive('captures') - ->andReturn([$capture]); - - $purchaseUnit = Mockery::mock(PurchaseUnit::class); - $purchaseUnit->shouldReceive('payments') - ->andReturn($payments); - - $order - ->shouldReceive('id') - ->andReturn('101'); - $order->shouldReceive('intent') - ->andReturn('CAPTURE'); - $order->shouldReceive('status->is') - ->andReturn(true); - $order - ->shouldReceive('purchase_units') - ->andReturn([$purchaseUnit]); - $order - ->shouldReceive('payment_source') - ->andReturn(null); - - $wcOrder - ->shouldReceive('get_meta') - ->andReturn(''); - $wcOrder - ->shouldReceive('get_id') - ->andReturn(1); - $wcOrder - ->shouldReceive('get_customer_id') - ->andReturn(2); - $wcOrder - ->expects('update_meta_data') - ->with(PayPalGateway::ORDER_ID_META_KEY, '101'); - $wcOrder - ->expects('update_meta_data') - ->with(PayPalGateway::INTENT_META_KEY, 'CAPTURE'); - $wcOrder - ->expects('update_meta_data') - ->with(PayPalGateway::ORDER_PAYMENT_MODE_META_KEY, 'live'); - $wcOrder - ->expects('payment_complete'); - $wcOrder - ->expects('set_transaction_id'); - - $this->repository->shouldReceive('all_for_user_id') - ->andReturn([$token]); - - $customer->shouldReceive('get_id') - ->andReturn(1); - - $this->purchaseUnitFactory->shouldReceive('from_wc_order') - ->andReturn($purchaseUnit); - $this->payerFactory->shouldReceive('from_customer') - ->andReturn($payer); - - $this->shippingPreferenceFactory->shouldReceive('from_state') - ->with($purchaseUnit, 'renewal') - ->andReturn('no_shipping'); - - $this->orderEndpoint->shouldReceive('create') - ->with([$purchaseUnit], 'no_shipping', $payer, $token) - ->andReturn($order); - - when('wcs_get_subscriptions_for_order')->justReturn(array()); - - $wcOrder->shouldReceive('update_status'); - $wcOrder->shouldReceive('save'); - - $this->sut->renew($wcOrder); - } -} diff --git a/tests/PHPUnit/Vaulting/VaultedCreditCardHandlerTest.php b/tests/PHPUnit/Vaulting/VaultedCreditCardHandlerTest.php index 8a7f9de51..c7d176c8e 100644 --- a/tests/PHPUnit/Vaulting/VaultedCreditCardHandlerTest.php +++ b/tests/PHPUnit/Vaulting/VaultedCreditCardHandlerTest.php @@ -20,7 +20,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory; use WooCommerce\PayPalCommerce\Onboarding\Environment; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\TestCase; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; use WooCommerce\PayPalCommerce\Vaulting\VaultedCreditCardHandler; @@ -68,24 +68,6 @@ class VaultedCreditCardHandlerTest extends TestCase ); } - public function testHandlePaymentChangingPayment() - { - $_POST['woocommerce_change_payment'] = 1; - $wcOrder = Mockery::mock(\WC_Order::class); - $wcOrder->shouldReceive('get_id')->andReturn(1); - $wcOrder->shouldReceive('update_meta_data') - ->with('payment_token_id', 'abc123') - ->andReturn(1); - $wcOrder->shouldReceive('save')->andReturn(1); - $this->subscriptionHelper->shouldReceive('has_subscription')->andReturn(true); - $this->subscriptionHelper->shouldReceive('is_subscription_change_payment')->andReturn(true); - - $customer = Mockery::mock(WC_Customer::class); - - $result = $this->testee->handle_payment('abc123', $wcOrder, $customer); - $this->assertInstanceOf(\WC_Order::class, $result); - } - public function testHandlePayment() { $_POST['woocommerce_change_payment'] = null; @@ -110,6 +92,8 @@ class VaultedCreditCardHandlerTest extends TestCase $customer = Mockery::mock(WC_Customer::class); $payer = Mockery::mock(Payer::class); + $payer->shouldReceive('email_address'); + $this->payerFactory->shouldReceive('from_wc_order') ->andReturn($payer); $this->shippingPreferenceFactory->shouldReceive('from_state') @@ -118,10 +102,12 @@ class VaultedCreditCardHandlerTest extends TestCase $order = Mockery::mock(Order::class); $order->shouldReceive('id')->andReturn('1'); $order->shouldReceive('intent')->andReturn('CAPTURE'); + $order->shouldReceive('payer')->andReturn($payer); + $paymentSource = Mockery::mock(PaymentSource::class); - $paymentSourceCard = Mockery::mock(PaymentSourceCard::class); - $paymentSource->shouldReceive('card')->andReturn($paymentSourceCard); + $paymentSource->shouldReceive('name')->andReturn('card'); $order->shouldReceive('payment_source')->andReturn($paymentSource); + $orderStatus = Mockery::mock(OrderStatus::class); $orderStatus->shouldReceive('is')->andReturn(true); $order->shouldReceive('status')->andReturn($orderStatus); diff --git a/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php b/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php index f5066db40..5569c4158 100644 --- a/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php +++ b/tests/PHPUnit/WcGateway/Assets/SettingsPagesAssetsTest.php @@ -3,8 +3,9 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Assets; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint; use WooCommerce\PayPalCommerce\Onboarding\Environment; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\TestCase; use function Brain\Monkey\Functions\when; use Mockery; @@ -16,6 +17,8 @@ class SettingsPagesAssetsTest extends TestCase $moduleUrl = 'http://example.com/wp-content/plugins/woocommerce-paypal-payments/modules/ppcp-wc-gateway'; $modulePath = '/var/www/html/wp-content/plugins/woocommerce-paypal-payments/modules/ppcp-wc-gateway'; $subscriptionsHelper = Mockery::mock(SubscriptionHelper::class); + $billingAgreementEndpoint = Mockery::mock(BillingAgreementsEndpoint::class); + $testee = new SettingsPageAssets( $moduleUrl, @@ -29,7 +32,8 @@ class SettingsPagesAssetsTest extends TestCase array(), array(), true, - false + false, + $billingAgreementEndpoint ); when('is_admin') diff --git a/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php b/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php index 5e2a8bbc7..60b86a643 100644 --- a/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php +++ b/tests/PHPUnit/WcGateway/Gateway/CreditCardGatewayTest.php @@ -4,18 +4,23 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway\Gateway; use Mockery; -use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use WC_Order; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; +use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\TestCase; use WooCommerce\PayPalCommerce\Vaulting\VaultedCreditCardHandler; +use WooCommerce\PayPalCommerce\Vaulting\WooCommercePaymentTokens; +use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; +use WooCommerce\PayPalCommerce\WcGateway\Endpoint\CaptureCardPayment; use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor; use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use function Brain\Monkey\Functions\when; class CreditCardGatewayTest extends TestCase @@ -29,9 +34,15 @@ class CreditCardGatewayTest extends TestCase private $state; private $transactionUrlProvider; private $subscriptionHelper; + private $captureCardPayment; + private $prefix; + private $paymentTokensEndpoint; + private $wcPaymentTokens; private $logger; private $paymentsEndpoint; private $vaultedCreditCardHandler; + private $environment; + private $orderEndpoint; private $testee; public function setUp(): void @@ -47,9 +58,15 @@ class CreditCardGatewayTest extends TestCase $this->state = Mockery::mock(State::class); $this->transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class); $this->subscriptionHelper = Mockery::mock(SubscriptionHelper::class); + $this->captureCardPayment = Mockery::mock(CaptureCardPayment::class); + $this->prefix = 'some-prefix'; + $this->paymentTokensEndpoint = Mockery::mock(PaymentTokensEndpoint::class); + $this->wcPaymentTokens = Mockery::mock(WooCommercePaymentTokens::class); $this->logger = Mockery::mock(LoggerInterface::class); $this->paymentsEndpoint = Mockery::mock(PaymentsEndpoint::class); $this->vaultedCreditCardHandler = Mockery::mock(VaultedCreditCardHandler::class); + $this->environment = Mockery::mock(Environment::class); + $this->orderEndpoint = Mockery::mock(OrderEndpoint::class); $this->state->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED); $this->config->shouldReceive('has')->andReturn(true); @@ -67,9 +84,15 @@ class CreditCardGatewayTest extends TestCase $this->state, $this->transactionUrlProvider, $this->subscriptionHelper, - $this->logger, $this->paymentsEndpoint, - $this->vaultedCreditCardHandler + $this->vaultedCreditCardHandler, + $this->environment, + $this->orderEndpoint, + $this->captureCardPayment, + $this->prefix, + $this->paymentTokensEndpoint, + $this->wcPaymentTokens, + $this->logger ); } @@ -83,6 +106,7 @@ class CreditCardGatewayTest extends TestCase when('WC')->justReturn($woocommerce); $woocommerce->session = $session; $session->shouldReceive('set')->andReturn([]); + $session->shouldReceive('get')->andReturn(''); $this->orderProcessor->shouldReceive('process') ->with($wc_order) @@ -106,6 +130,9 @@ class CreditCardGatewayTest extends TestCase when('WC')->justReturn($woocommerce); $woocommerce->session = $session; $session->shouldReceive('set')->andReturn([]); + $session->shouldReceive('get')->andReturn(''); + + when('is_checkout')->justReturn(true); $savedCreditCard = 'abc123'; $_POST['saved_credit_card'] = $savedCreditCard; diff --git a/tests/PHPUnit/WcGateway/Gateway/OXXO/OXXOGatewayTest.php b/tests/PHPUnit/WcGateway/Gateway/OXXO/OXXOGatewayTest.php index abff51a10..0f70f801c 100644 --- a/tests/PHPUnit/WcGateway/Gateway/OXXO/OXXOGatewayTest.php +++ b/tests/PHPUnit/WcGateway/Gateway/OXXO/OXXOGatewayTest.php @@ -89,6 +89,7 @@ private $testee; $order->shouldReceive('id')->andReturn('1'); $order->shouldReceive('intent'); $order->shouldReceive('payment_source'); + $order->shouldReceive('payer'); $this->orderEndpoint ->shouldReceive('create') diff --git a/tests/PHPUnit/WcGateway/Gateway/WcGatewayTest.php b/tests/PHPUnit/WcGateway/Gateway/WcGatewayTest.php index 962dbbdd4..041141492 100644 --- a/tests/PHPUnit/WcGateway/Gateway/WcGatewayTest.php +++ b/tests/PHPUnit/WcGateway/Gateway/WcGatewayTest.php @@ -6,12 +6,14 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Gateway; use Exception; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\Session\SessionHandler; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\Vaulting\WooCommercePaymentTokens; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\TestCase; use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository; use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer; @@ -44,6 +46,9 @@ class WcGatewayTest extends TestCase private $logger; private $apiShopCountry; private $orderEndpoint; + private $paymentTokensEndpoint; + private $vaultV3Enabled; + private $wcPaymentTokens; public function setUp(): void { parent::setUp(); @@ -88,6 +93,10 @@ class WcGatewayTest extends TestCase $this->logger->shouldReceive('info'); $this->logger->shouldReceive('error'); + + $this->paymentTokensEndpoint = Mockery::mock(PaymentTokensEndpoint::class); + $this->vaultV3Enabled = true; + $this->wcPaymentTokens = Mockery::mock(WooCommercePaymentTokens::class); } private function createGateway() @@ -111,7 +120,10 @@ class WcGatewayTest extends TestCase function ($id) { return 'checkoutnow=' . $id; }, - 'Pay via PayPal' + 'Pay via PayPal', + $this->paymentTokensEndpoint, + $this->vaultV3Enabled, + $this->wcPaymentTokens ); } diff --git a/tests/PHPUnit/WcGateway/Processor/AuthorizedPaymentsProcessorTest.php b/tests/PHPUnit/WcGateway/Processor/AuthorizedPaymentsProcessorTest.php index 0d5fd386a..9f9aa8c3c 100644 --- a/tests/PHPUnit/WcGateway/Processor/AuthorizedPaymentsProcessorTest.php +++ b/tests/PHPUnit/WcGateway/Processor/AuthorizedPaymentsProcessorTest.php @@ -5,6 +5,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Processor; use Mockery\MockInterface; +use WooCommerce\PayPalCommerce\ApiClient\Factory\AmountFactory; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use Psr\Log\NullLogger; use WC_Order; @@ -19,7 +20,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments; use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\TestCase; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use Mockery; @@ -69,6 +70,7 @@ class AuthorizedPaymentsProcessorTest extends TestCase $this->config = Mockery::mock(ContainerInterface::class); $this->subscription_helper = Mockery::mock(SubscriptionHelper::class); + $this->amount_factory = Mockery::mock(AmountFactory::class); $this->testee = new AuthorizedPaymentsProcessor( $this->orderEndpoint, @@ -76,7 +78,8 @@ class AuthorizedPaymentsProcessorTest extends TestCase new NullLogger(), $this->notice, $this->config, - $this->subscription_helper + $this->subscription_helper, + $this->amount_factory ); } @@ -251,7 +254,7 @@ class AuthorizedPaymentsProcessorTest extends TestCase } private function createAuthorization(string $id, string $status): Authorization { - return new Authorization($id, new AuthorizationStatus($status)); + return new Authorization($id, new AuthorizationStatus($status), null); } private function createCapture(string $id, string $status): Capture { diff --git a/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php b/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php index d6754fdee..95f1b7b48 100644 --- a/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php +++ b/tests/PHPUnit/WcGateway/Processor/OrderProcessorTest.php @@ -3,7 +3,6 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\WcGateway\Processor; - use Exception; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; @@ -24,7 +23,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderHelper; use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Session\SessionHandler; -use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; use WooCommerce\PayPalCommerce\TestCase; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; @@ -94,6 +93,7 @@ class OrderProcessorTest extends TestCase $currentOrder ->shouldReceive('payment_source') ->andReturn(null); + $currentOrder->shouldReceive('payer'); $wcOrder ->shouldReceive('get_meta') @@ -231,6 +231,7 @@ class OrderProcessorTest extends TestCase $currentOrder ->shouldReceive('payment_source') ->andReturn(null); + $currentOrder->shouldReceive('payer'); $wcOrder ->shouldReceive('get_meta') @@ -358,6 +359,7 @@ class OrderProcessorTest extends TestCase $currentOrder ->shouldReceive('purchase_units') ->andReturn([$purchaseUnit]); + $currentOrder->shouldReceive('payer'); $wcOrder ->shouldReceive('get_meta') diff --git a/tests/PHPUnit/WcGateway/Repository/ApplicationContextRepositoryTest.php b/tests/PHPUnit/WcGateway/Repository/ApplicationContextRepositoryTest.php index 1bd5b59f3..48af8f3a4 100644 --- a/tests/PHPUnit/WcGateway/Repository/ApplicationContextRepositoryTest.php +++ b/tests/PHPUnit/WcGateway/Repository/ApplicationContextRepositoryTest.php @@ -36,7 +36,7 @@ class ApplicationContextRepositoryTest extends TestCase ->andReturn($value); } - expect('network_home_url') + expect('home_url') ->andReturn('https://example.com/'); expect('wc_get_checkout_url') ->andReturn('https://example.com/checkout/'); diff --git a/tests/PHPUnit/WcGateway/Settings/LocationsTest.php b/tests/PHPUnit/WcGateway/Settings/LocationsTest.php index 45cb63ffa..23bd375be 100644 --- a/tests/PHPUnit/WcGateway/Settings/LocationsTest.php +++ b/tests/PHPUnit/WcGateway/Settings/LocationsTest.php @@ -40,16 +40,16 @@ class LocationsTest extends ModularTestCase ['product', 'cart', 'checkout', 'mini-cart'], [ 'product' => 'Single Product', - 'cart' => 'Cart', - 'checkout' => 'Checkout', + 'cart' => 'Classic Cart', + 'checkout' => 'Classic Checkout', 'mini-cart' => 'Mini Cart', ], ]; yield [ ['cart', 'checkout'], [ - 'cart' => 'Cart', - 'checkout' => 'Checkout', + 'cart' => 'Classic Cart', + 'checkout' => 'Classic Checkout', ], ]; yield [ diff --git a/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php b/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php index c66665bbc..7b23ca67d 100644 --- a/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php +++ b/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php @@ -2,8 +2,10 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Settings; +use Psr\Log\LoggerInterface; use Requests_Utility_CaseInsensitiveDictionary; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\Helper\RedirectorStub; use WooCommerce\PayPalCommerce\Helper\StubRedirectionException; @@ -12,7 +14,6 @@ use WooCommerce\PayPalCommerce\Onboarding\State; use Mockery; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\Webhooks\WebhookRegistrar; -use function Brain\Monkey\Functions\expect; use function Brain\Monkey\Functions\when; class SettingsListenerTest extends ModularTestCase @@ -40,6 +41,8 @@ class SettingsListenerTest extends ModularTestCase $signup_link_ids = array(); $pui_status_cache = Mockery::mock(Cache::class); $dcc_status_cache = Mockery::mock(Cache::class); + $billing_agreement_endpoint = Mockery::mock(BillingAgreementsEndpoint::class); + $logger = Mockery::mock(LoggerInterface::class); $testee = new SettingsListener( $settings, @@ -55,7 +58,9 @@ class SettingsListenerTest extends ModularTestCase $dcc_status_cache, new RedirectorStub(), '', - '' + '', + $billing_agreement_endpoint, + $logger ); $_GET['section'] = PayPalGateway::ID; diff --git a/tests/PHPUnit/WcSubscriptions/Helper/SubscriptionHelperTest.php b/tests/PHPUnit/WcSubscriptions/Helper/SubscriptionHelperTest.php new file mode 100644 index 000000000..bbde3ebe0 --- /dev/null +++ b/tests/PHPUnit/WcSubscriptions/Helper/SubscriptionHelperTest.php @@ -0,0 +1,37 @@ +shouldReceive('get_related_orders') + ->andReturn( + [ + 1 => 1, + 3 => 3, + 2 => 2, + ] + ); + + $wc_order = Mockery::mock(WC_Order::class); + $wc_order->shouldReceive('get_status')->andReturn('processing'); + $wc_order->shouldReceive('get_transaction_id')->andReturn('ABC123'); + + when('wc_get_order')->justReturn($wc_order); + + $this->assertSame( + 'ABC123', + (new SubscriptionHelper())->previous_transaction($subscription) + ); + } +} diff --git a/tests/Playwright/.env.example b/tests/Playwright/.env.example index 3de8add8c..e23512085 100644 --- a/tests/Playwright/.env.example +++ b/tests/Playwright/.env.example @@ -13,7 +13,7 @@ PRODUCT_ID=123 SUBSCRIPTION_URL="/product/sub" -APM_ID="sofort" +APM_ID="paypal" WP_MERCHANT_USER="admin" WP_MERCHANT_PASSWORD="admin" diff --git a/tests/Playwright/tests/save-payment-methods.spec.js b/tests/Playwright/tests/save-payment-methods.spec.js new file mode 100644 index 000000000..f6fb46315 --- /dev/null +++ b/tests/Playwright/tests/save-payment-methods.spec.js @@ -0,0 +1,89 @@ +const {test, expect} = require('@playwright/test'); +const {loginAsCustomer} = require("./utils/user"); +const {openPaypalPopup, loginIntoPaypal, completePaypalPayment} = require("./utils/paypal-popup"); +const {fillCheckoutForm, expectOrderReceivedPage} = require("./utils/checkout"); + +const { + PRODUCT_URL, +} = process.env; + +async function expectContinuation(page) { + await expect(page.locator('#payment_method_ppcp-gateway')).toBeChecked(); + + await expect(page.locator('.component-frame')).toHaveCount(0); +} + +async function completeContinuation(page) { + await expectContinuation(page); + + await Promise.all([ + page.waitForNavigation(), + page.locator('#place_order').click(), + ]); +} + +test('Save during purchase', async ({page}) => { + await loginAsCustomer(page) + + await page.goto(PRODUCT_URL); + const popup = await openPaypalPopup(page); + + await loginIntoPaypal(popup); + await completePaypalPayment(popup); + await fillCheckoutForm(page); + + await completeContinuation(page); + + await expectOrderReceivedPage(page); +}); + +test('PayPal add payment method', async ({page}) => { + await loginAsCustomer(page); + await page.goto('/my-account/add-payment-method'); + + const popup = await openPaypalPopup(page); + await loginIntoPaypal(popup); + popup.locator('#consentButton').click(); + + await page.waitForURL('/my-account/payment-methods'); +}); + +test('ACDC add payment method', async ({page}) => { + await loginAsCustomer(page); + await page.goto('/my-account/add-payment-method'); + + await page.click("text=Debit & Credit Cards"); + + const creditCardNumber = await page.frameLocator('[title="paypal_card_number_field"]').locator('.card-field-number'); + await creditCardNumber.fill('4005519200000004'); + + const expirationDate = await page.frameLocator('[title="paypal_card_expiry_field"]').locator('.card-field-expiry'); + await expirationDate.fill('01/25'); + + const cvv = await page.frameLocator('[title="paypal_card_cvv_field"]').locator('.card-field-cvv'); + await cvv.fill('123'); + + await page.waitForURL('/my-account/payment-methods'); +}); + +test('PayPal logged-in user free trial subscription without payment token', async ({page}) => { + await loginAsCustomer(page); + + await page.goto('/shop'); + await page.click("text=Sign up now"); + await page.goto('/classic-checkout'); + + const popup = await openPaypalPopup(page); + await loginIntoPaypal(popup); + popup.locator('#consentButton').click(); + + await page.click("text=Proceed to PayPal"); + + const title = await page.locator('.entry-title'); + await expect(title).toHaveText('Order received'); +}) + + + + + diff --git a/tests/e2e/PHPUnit/RealTimeAccountUpdaterTest.php b/tests/e2e/PHPUnit/RealTimeAccountUpdaterTest.php new file mode 100644 index 000000000..5f582d881 --- /dev/null +++ b/tests/e2e/PHPUnit/RealTimeAccountUpdaterTest.php @@ -0,0 +1,64 @@ +delete(); + } + + parent::tearDown(); + } + + public function testUpdateCard() + { + $token = $this->createToken(); + + (new RealTimeAccountUpdaterHelper())->update_wc_card_token('2042-02', '0004', $token); + + $this->assertTrue($token->get_expiry_year() === '2042'); + $this->assertTrue($token->get_expiry_month() === '02'); + $this->assertTrue($token->get_last4() === '0004'); + } + + public function testUpdateOnlyAllowedCards() + { + $token = $this->createToken('AMEX'); + + (new RealTimeAccountUpdaterHelper())->update_wc_card_token('2042-02', '0004', $token); + + $this->assertTrue($token->get_expiry_year() === '2025'); + $this->assertTrue($token->get_expiry_month() === '01'); + $this->assertTrue($token->get_last4() === '1234'); + } + + /** + * @return WC_Payment_Token_CC + */ + private function createToken($brand = 'VISA'): \WC_Payment_Token_CC + { + $token = new WC_Payment_Token_CC(); + $token->set_token('abc123'); + $token->set_user_id(1); + $token->set_gateway_id(CreditCardGateway::ID); + + $token->set_last4('1234'); + $token->set_expiry_month('01'); + $token->set_expiry_year('2025'); + $token->set_card_type($brand); + + $token->save(); + + return $token; + } +} diff --git a/woocommerce-paypal-payments.php b/woocommerce-paypal-payments.php index 026f010e6..b55b1f00d 100644 --- a/woocommerce-paypal-payments.php +++ b/woocommerce-paypal-payments.php @@ -3,13 +3,14 @@ * Plugin Name: WooCommerce PayPal Payments * Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/ * Description: PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage. - * Version: 2.4.2 + * Version: 2.6.1 * Author: WooCommerce * Author URI: https://woocommerce.com/ * License: GPL-2.0 * Requires PHP: 7.2 + * Requires Plugins: woocommerce * WC requires at least: 3.9 - * WC tested up to: 8.3 + * WC tested up to: 8.7 * Text Domain: woocommerce-paypal-payments * * @package WooCommerce\PayPalCommerce @@ -25,14 +26,14 @@ define( 'PAYPAL_API_URL', 'https://api-m.paypal.com' ); define( 'PAYPAL_URL', 'https://www.paypal.com' ); define( 'PAYPAL_SANDBOX_API_URL', 'https://api-m.sandbox.paypal.com' ); define( 'PAYPAL_SANDBOX_URL', 'https://www.sandbox.paypal.com' ); -define( 'PAYPAL_INTEGRATION_DATE', '2023-11-28' ); +define( 'PAYPAL_INTEGRATION_DATE', '2024-04-03' ); ! defined( 'CONNECT_WOO_CLIENT_ID' ) && define( 'CONNECT_WOO_CLIENT_ID', 'AcCAsWta_JTL__OfpjspNyH7c1GGHH332fLwonA5CwX4Y10mhybRZmHLA0GdRbwKwjQIhpDQy0pluX_P' ); ! defined( 'CONNECT_WOO_SANDBOX_CLIENT_ID' ) && define( 'CONNECT_WOO_SANDBOX_CLIENT_ID', 'AYmOHbt1VHg-OZ_oihPdzKEVbU3qg0qXonBcAztuzniQRaKE0w1Hr762cSFwd4n8wxOl-TCWohEa0XM_' ); ! defined( 'CONNECT_WOO_MERCHANT_ID' ) && define( 'CONNECT_WOO_MERCHANT_ID', 'K8SKZ36LQBWXJ' ); ! defined( 'CONNECT_WOO_SANDBOX_MERCHANT_ID' ) && define( 'CONNECT_WOO_SANDBOX_MERCHANT_ID', 'MPMFHQTVMBZ6G' ); -! defined( 'CONNECT_WOO_URL' ) && define( 'CONNECT_WOO_URL', 'https://connect.woocommerce.com/ppc' ); -! defined( 'CONNECT_WOO_SANDBOX_URL' ) && define( 'CONNECT_WOO_SANDBOX_URL', 'https://connect.woocommerce.com/ppcsandbox' ); +! defined( 'CONNECT_WOO_URL' ) && define( 'CONNECT_WOO_URL', 'https://api.woocommerce.com/integrations/ppc' ); +! defined( 'CONNECT_WOO_SANDBOX_URL' ) && define( 'CONNECT_WOO_SANDBOX_URL', 'https://api.woocommerce.com/integrations/ppcsandbox' ); ( function () { $autoload_filepath = __DIR__ . '/vendor/autoload.php'; @@ -97,7 +98,7 @@ define( 'PAYPAL_INTEGRATION_DATE', '2023-11-28' ); */ require_once ABSPATH . 'wp-admin/includes/plugin.php'; } - $plugin_data = get_plugin_data( __DIR__ . '/woocommerce-paypal-payments.php' ); + $plugin_data = get_plugin_data( __DIR__ . '/woocommerce-paypal-payments.php', false ); $plugin_version = $plugin_data['Version'] ?? null; $installed_plugin_version = get_option( 'woocommerce-ppcp-version' ); if ( $installed_plugin_version !== $plugin_version ) {