mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-07 19:54:15 +08:00
Merge branch 'trunk' into PCP-2520-cart-simulation-type-error
This commit is contained in:
commit
d738755216
99 changed files with 7923 additions and 878 deletions
|
@ -1,5 +1,42 @@
|
|||
*** Changelog ***
|
||||
|
||||
= 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
|
||||
|
|
16
modules.php
16
modules.php
|
@ -5,6 +5,7 @@
|
|||
* @package WooCommerce\PayPalCommerce
|
||||
*/
|
||||
|
||||
use WooCommerce\PayPalCommerce\PayLaterBlock\PayLaterBlockModule;
|
||||
use WooCommerce\PayPalCommerce\PluginModule;
|
||||
|
||||
return function ( string $root_dir ): iterable {
|
||||
|
@ -29,8 +30,9 @@ return function ( string $root_dir ): iterable {
|
|||
( 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'
|
||||
) ) {
|
||||
|
@ -38,7 +40,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'
|
||||
) ) {
|
||||
|
@ -46,7 +47,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'
|
||||
) ) {
|
||||
|
@ -54,20 +54,22 @@ 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(
|
||||
//phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
'woocommerce.feature-flags.woocommerce_paypal_payments.save_payment_methods_enabled',
|
||||
getenv( 'PCP_SAVE_PAYMENT_METHODS' ) === '1'
|
||||
getenv( 'PCP_SAVE_PAYMENT_METHODS' ) !== '0'
|
||||
) ) {
|
||||
$modules[] = ( require "$modules_dir/ppcp-save-payment-methods/module.php" )();
|
||||
}
|
||||
|
||||
if ( PayLaterBlockModule::is_enabled() ) {
|
||||
$modules[] = ( require "$modules_dir/ppcp-paylater-block/module.php" )();
|
||||
}
|
||||
|
||||
return $modules;
|
||||
};
|
||||
|
|
|
@ -604,6 +604,7 @@ return array(
|
|||
array(
|
||||
'AU' => array(
|
||||
'AUD',
|
||||
'BRL',
|
||||
'CAD',
|
||||
'CHF',
|
||||
'CZK',
|
||||
|
@ -612,47 +613,94 @@ return array(
|
|||
'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',
|
||||
|
@ -661,26 +709,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',
|
||||
|
@ -689,20 +757,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',
|
||||
|
@ -711,16 +829,457 @@ 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',
|
||||
),
|
||||
'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',
|
||||
|
@ -729,68 +1288,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',
|
||||
|
@ -799,52 +1309,6 @@ 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',
|
||||
|
@ -852,64 +1316,6 @@ return array(
|
|||
'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',
|
||||
'CAD',
|
||||
'CHF',
|
||||
'CZK',
|
||||
'DKK',
|
||||
'EUR',
|
||||
'GBP',
|
||||
'HKD',
|
||||
'HUF',
|
||||
'JPY',
|
||||
'NOK',
|
||||
'NZD',
|
||||
'PLN',
|
||||
'SEK',
|
||||
'SGD',
|
||||
'USD',
|
||||
),
|
||||
)
|
||||
);
|
||||
},
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -71,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' ),
|
||||
|
|
|
@ -70,10 +70,6 @@ class ApplepayButton {
|
|||
|
||||
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;
|
||||
|
@ -214,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';
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ class PayNowHandler extends BaseHandler {
|
|||
|
||||
validateContext() {
|
||||
if ( this.ppcpConfig?.locations_with_subscription_product?.payorder ) {
|
||||
return false;
|
||||
return this.isVaultV3Mode();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ class SingleProductHandler extends BaseHandler {
|
|||
|
||||
validateContext() {
|
||||
if ( this.ppcpConfig?.locations_with_subscription_product?.product ) {
|
||||
return false;
|
||||
return this.isVaultV3Mode();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -50,6 +52,13 @@ const ApplePayComponent = () => {
|
|||
|
||||
const features = ['products'];
|
||||
|
||||
if (
|
||||
cartHasSubscriptionProducts(ppcpConfig)
|
||||
&& (new CheckoutHandler(buttonConfig, ppcpConfig)).isVaultV3Mode()
|
||||
) {
|
||||
features.push('subscriptions');
|
||||
}
|
||||
|
||||
registerExpressPaymentMethod({
|
||||
name: buttonData.id,
|
||||
label: <div dangerouslySetInnerHTML={{__html: buttonData.title}}/>,
|
||||
|
|
|
@ -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',
|
||||
() => {
|
||||
|
|
|
@ -171,8 +171,9 @@ return array(
|
|||
return apply_filters(
|
||||
'woocommerce_paypal_payments_applepay_supported_country_currency_matrix',
|
||||
array(
|
||||
'CA' => array(
|
||||
'AU' => array(
|
||||
'AUD',
|
||||
'BRL',
|
||||
'CAD',
|
||||
'CHF',
|
||||
'CZK',
|
||||
|
@ -181,16 +182,22 @@ return array(
|
|||
'GBP',
|
||||
'HKD',
|
||||
'HUF',
|
||||
'ILS',
|
||||
'JPY',
|
||||
'MXN',
|
||||
'NOK',
|
||||
'NZD',
|
||||
'PHP',
|
||||
'PLN',
|
||||
'SEK',
|
||||
'SGD',
|
||||
'THB',
|
||||
'TWD',
|
||||
'USD',
|
||||
),
|
||||
'GB' => array(
|
||||
'BE' => array(
|
||||
'AUD',
|
||||
'BRL',
|
||||
'CAD',
|
||||
'CHF',
|
||||
'CZK',
|
||||
|
@ -199,16 +206,286 @@ return array(
|
|||
'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',
|
||||
),
|
||||
'IT' => array(
|
||||
'AUD',
|
||||
'BRL',
|
||||
'CAD',
|
||||
'CHF',
|
||||
'CZK',
|
||||
|
@ -217,12 +494,329 @@ 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',
|
||||
),
|
||||
'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(
|
||||
|
|
|
@ -273,7 +273,7 @@ class AvailabilityNotice {
|
|||
$message = sprintf(
|
||||
// translators: %1$s and %2$s are the opening and closing of HTML <a> tag for the well-known file, %3$s and %4$s are the opening and closing of HTML <a> 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'
|
||||
),
|
||||
'<a href="/.well-known/apple-developer-merchantid-domain-association" target="_blank">',
|
||||
|
|
|
@ -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.
|
||||
<p class="description">If this setting is not enabled, <a href="https://woocommerce.com/document/woocommerce-paypal-payments/#blocks-faq" target="_blank">payment confirmation on the checkout will be skipped</a>.
|
||||
Skipping the final confirmation on the checkout page may impact the buyer experience during the PayPal payment process.</p>',
|
||||
'woocommerce-paypal-payments'
|
||||
|
|
|
@ -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;
|
|
@ -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,
|
||||
|
@ -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}
|
||||
|
@ -130,6 +146,17 @@ export const paypalOrderToWcAddresses = (order) => {
|
|||
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.
|
||||
|
|
16
modules/ppcp-blocks/resources/js/Helper/Subscription.js
Normal file
16
modules/ppcp-blocks/resources/js/Helper/Subscription.js
Normal file
|
@ -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;
|
||||
}
|
9
modules/ppcp-blocks/resources/js/Helper/debounce.js
Normal file
9
modules/ppcp-blocks/resources/js/Helper/debounce.js
Normal file
|
@ -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);
|
||||
};
|
||||
};
|
|
@ -1,6 +1,15 @@
|
|||
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 {
|
||||
cartHasSubscriptionProducts,
|
||||
isPayPalSubscription
|
||||
} from "./Helper/Subscription";
|
||||
import {
|
||||
loadPaypalScriptPromise
|
||||
} from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading'
|
||||
|
@ -8,13 +17,15 @@ import {
|
|||
normalizeStyleForFundingSource
|
||||
} from '../../../ppcp-button/resources/js/modules/Helper/Style'
|
||||
import buttonModuleWatcher from "../../../ppcp-button/resources/js/modules/ButtonModuleWatcher";
|
||||
|
||||
import BlockCheckoutMessagesBootstrap from "./Bootstrap/BlockCheckoutMessagesBootstrap";
|
||||
const config = wc.wcSettings.getSetting('ppcp-gateway_data');
|
||||
|
||||
window.ppcpFundingSource = config.fundingSource;
|
||||
|
||||
let registeredContext = false;
|
||||
|
||||
let paypalScriptPromise = null;
|
||||
|
||||
const PayPalComponent = ({
|
||||
onClick,
|
||||
onClose,
|
||||
|
@ -33,6 +44,16 @@ const PayPalComponent = ({
|
|||
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;
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -66,6 +87,7 @@ const PayPalComponent = ({
|
|||
bn_code: '',
|
||||
context: config.scriptData.context,
|
||||
payment_method: 'ppcp-gateway',
|
||||
funding_source: window.ppcpFundingSource ?? 'paypal',
|
||||
createaccount: false
|
||||
}),
|
||||
});
|
||||
|
@ -93,6 +115,78 @@ const PayPalComponent = ({
|
|||
}
|
||||
};
|
||||
|
||||
const createSubscription = async (data, actions) => {
|
||||
return actions.subscription.create({
|
||||
'plan_id': config.scriptData.subscription_plan_id
|
||||
});
|
||||
};
|
||||
|
||||
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,
|
||||
|
@ -193,6 +287,7 @@ const PayPalComponent = ({
|
|||
};
|
||||
|
||||
let handleShippingChange = null;
|
||||
let handleSubscriptionShippingChange = null;
|
||||
if (shippingData.needsShipping && !config.finalReviewEnabled) {
|
||||
handleShippingChange = async (data, actions) => {
|
||||
try {
|
||||
|
@ -229,6 +324,28 @@ const PayPalComponent = ({
|
|||
actions.reject();
|
||||
}
|
||||
};
|
||||
|
||||
handleSubscriptionShippingChange = async (data, actions) => {
|
||||
try {
|
||||
const shippingOptionId = data.selected_shipping_option?.id;
|
||||
if (shippingOptionId) {
|
||||
await shippingData.setSelectedRates(shippingOptionId);
|
||||
}
|
||||
|
||||
const address = paypalAddressToWc(data.shipping_address);
|
||||
|
||||
await wp.data.dispatch('wc/store/cart').updateCustomerData({
|
||||
shipping_address: address,
|
||||
});
|
||||
|
||||
await shippingData.setShippingAddress(address);
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
actions.reject();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -309,7 +426,26 @@ 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 (
|
||||
<PayPalButton
|
||||
fundingSource={fundingSource}
|
||||
style={style}
|
||||
onClick={handleClick}
|
||||
onCancel={onClose}
|
||||
onError={onClose}
|
||||
createSubscription={createSubscription}
|
||||
onApprove={handleApproveSubscription}
|
||||
onShippingChange={handleSubscriptionShippingChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<PayPalButton
|
||||
|
@ -326,8 +462,40 @@ const PayPalComponent = ({
|
|||
}
|
||||
|
||||
const features = ['products'];
|
||||
let block_enabled = true;
|
||||
|
||||
if ((config.addPlaceOrderMethod || config.usePlaceOrder) && !config.scriptData.continuation) {
|
||||
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 (block_enabled) {
|
||||
if ((config.addPlaceOrderMethod || config.usePlaceOrder) && !config.scriptData.continuation) {
|
||||
let descriptionElement = <div dangerouslySetInnerHTML={{__html: config.description}}></div>;
|
||||
if (config.placeOrderButtonDescription) {
|
||||
descriptionElement = <div>
|
||||
|
@ -343,28 +511,30 @@ if ((config.addPlaceOrderMethod || config.usePlaceOrder) && !config.scriptData.c
|
|||
edit: descriptionElement,
|
||||
placeOrderButtonLabel: config.placeOrderButtonText,
|
||||
ariaLabel: config.title,
|
||||
canMakePayment: () => config.enabled,
|
||||
canMakePayment: () => {
|
||||
return config.enabled;
|
||||
},
|
||||
supports: {
|
||||
features: features,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (config.scriptData.continuation) {
|
||||
if (config.scriptData.continuation) {
|
||||
registerPaymentMethod({
|
||||
name: config.id,
|
||||
label: <div dangerouslySetInnerHTML={{__html: config.title}}/>,
|
||||
content: <PayPalComponent isEditing={false}/>,
|
||||
edit: <PayPalComponent isEditing={true}/>,
|
||||
ariaLabel: config.title,
|
||||
canMakePayment: () => true,
|
||||
canMakePayment: () => {
|
||||
return true;
|
||||
},
|
||||
supports: {
|
||||
features: [...features, 'ppcp_continuation'],
|
||||
},
|
||||
});
|
||||
} else if (!config.usePlaceOrder) {
|
||||
const paypalScriptPromise = loadPaypalScriptPromise(config.scriptData);
|
||||
|
||||
} else if (!config.usePlaceOrder) {
|
||||
for (const fundingSource of ['paypal', ...config.enabledFundingSources]) {
|
||||
registerExpressPaymentMethod({
|
||||
name: `${config.id}-${fundingSource}`,
|
||||
|
@ -374,6 +544,13 @@ if (config.scriptData.continuation) {
|
|||
edit: <PayPalComponent isEditing={true} fundingSource={fundingSource}/>,
|
||||
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();
|
||||
|
@ -383,4 +560,5 @@ if (config.scriptData.continuation) {
|
|||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -224,6 +224,8 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
|||
}
|
||||
}
|
||||
|
||||
$funding_sources = array();
|
||||
if ( ! $this->is_editing() ) {
|
||||
$disabled_funding_sources = explode( ',', $script_data['url_params']['disable-funding'] ?? '' ) ?: array();
|
||||
$funding_sources = array_values(
|
||||
array_diff(
|
||||
|
@ -231,12 +233,13 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
|||
$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'] ),
|
||||
'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,
|
||||
|
@ -253,4 +256,15 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
|||
'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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,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,
|
||||
|
@ -73,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.
|
||||
|
@ -117,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) {
|
||||
|
@ -131,7 +137,7 @@ const bootstrap = () => {
|
|||
}
|
||||
|
||||
const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart;
|
||||
if (isFreeTrial && data.fundingSource !== 'card') {
|
||||
if (isFreeTrial && data.fundingSource !== 'card' && ! PayPalCommerceGateway.subscription_plan_id) {
|
||||
freeTrialHandler.handle();
|
||||
return actions.reject();
|
||||
}
|
||||
|
@ -149,6 +155,12 @@ const bootstrap = () => {
|
|||
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);
|
||||
|
||||
|
@ -229,6 +241,7 @@ document.addEventListener(
|
|||
if (!typeof (PayPalCommerceGateway)) {
|
||||
console.error('PayPal button could not be configured.');
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
||||
if (!this.shouldRender()) {
|
||||
this.renderers.forEach(renderer => {
|
||||
const shouldShow = this.shouldShow(renderer);
|
||||
setVisible(renderer.config.wrapper, shouldShow);
|
||||
if (!shouldShow) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.renderer.renderWithAmount(this.lastAmount);
|
||||
if (!renderer.shouldRender()) {
|
||||
return;
|
||||
}
|
||||
|
||||
renderer.renderWithAmount(this.lastAmount);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,6 @@ export class ApmButtons {
|
|||
this.containers.push(parent);
|
||||
}
|
||||
});
|
||||
console.log('this.containers', this.containers);
|
||||
}
|
||||
|
||||
refresh() {
|
||||
|
|
|
@ -56,10 +56,12 @@ export const loadPaypalScript = (config, onLoaded, onError = null) => {
|
|||
|
||||
// Build the PayPal script options.
|
||||
let scriptOptions = keysToCamelCase(config.url_params);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ 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;
|
||||
|
@ -11,6 +11,7 @@ class CardFieldsRenderer {
|
|||
this.formValid = false;
|
||||
this.emptyFields = new Set(['number', 'cvv', 'expirationDate']);
|
||||
this.currentHostedFieldsInstance = null;
|
||||
this.onCardFieldsBeforeSubmit = onCardFieldsBeforeSubmit;
|
||||
}
|
||||
|
||||
render(wrapper, contextConfig) {
|
||||
|
@ -55,28 +56,52 @@ class CardFieldsRenderer {
|
|||
const nameField = document.getElementById('ppcp-credit-card-gateway-card-name');
|
||||
if (nameField) {
|
||||
let styles = cardFieldStyles(nameField);
|
||||
cardField.NameField({style: {'input': styles}}).render(nameField.parentNode);
|
||||
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 = cardFieldStyles(numberField);
|
||||
cardField.NumberField({style: {'input': styles}}).render(numberField.parentNode);
|
||||
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 = cardFieldStyles(expiryField);
|
||||
cardField.ExpiryField({style: {'input': styles}}).render(expiryField.parentNode);
|
||||
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 = cardFieldStyles(cvvField);
|
||||
cardField.CVVField({style: {'input': styles}}).render(cvvField.parentNode);
|
||||
let fieldOptions = {
|
||||
style: { 'input': styles }
|
||||
}
|
||||
if (cvvField.getAttribute('placeholder')) {
|
||||
fieldOptions.placeholder = cvvField.getAttribute('placeholder');
|
||||
}
|
||||
cardField.CVVField(fieldOptions).render(cvvField.parentNode);
|
||||
cvvField.remove();
|
||||
}
|
||||
|
||||
|
@ -87,6 +112,14 @@ 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();
|
||||
|
@ -110,6 +143,11 @@ class CardFieldsRenderer {
|
|||
return;
|
||||
}
|
||||
|
||||
if (typeof this.onCardFieldsBeforeSubmit === 'function' && !this.onCardFieldsBeforeSubmit()) {
|
||||
this.spinner.unblock();
|
||||
return;
|
||||
}
|
||||
|
||||
cardField.submit()
|
||||
.catch((error) => {
|
||||
this.spinner.unblock();
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -32,6 +32,7 @@ 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\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
@ -393,7 +394,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;
|
||||
}
|
||||
|
||||
|
@ -605,7 +606,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -618,6 +619,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;
|
||||
}
|
||||
|
@ -626,6 +631,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_enabled();
|
||||
|
||||
switch ( $location ) {
|
||||
case 'checkout':
|
||||
case 'cart':
|
||||
|
@ -634,8 +641,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -843,9 +855,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' );
|
||||
}
|
||||
|
||||
|
@ -863,6 +876,9 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
return array(
|
||||
'wrapper' => '#ppcp-messages',
|
||||
'is_hidden' => ! $this->is_pay_later_filter_enabled_for_location( $this->context() ),
|
||||
'block' => array(
|
||||
'enabled' => PayLaterBlockModule::is_enabled(),
|
||||
),
|
||||
'amount' => $amount,
|
||||
'placement' => $placement,
|
||||
'style' => array(
|
||||
|
@ -878,7 +894,6 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
'ratio' => $ratio,
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1041,6 +1056,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
'endpoint' => \WC_AJAX::get_endpoint( CartScriptParamsEndpoint::ENDPOINT ),
|
||||
),
|
||||
),
|
||||
'cart_contains_subscription' => $this->subscription_helper->cart_contains_subscription(),
|
||||
'subscription_plan_id' => $this->subscription_helper->paypal_subscription_id(),
|
||||
'variable_paypal_subscription_variations' => $this->subscription_helper->variable_paypal_subscription_variations(),
|
||||
'subscription_product_allowed' => $this->subscription_helper->checkout_subscription_product_allowed(),
|
||||
|
@ -1154,6 +1170,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() ) {
|
||||
|
@ -1237,6 +1256,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
|
||||
|
@ -1447,8 +1476,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 ] ?? '' );
|
||||
}
|
||||
|
@ -1463,7 +1492,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' );
|
||||
}
|
||||
|
@ -1584,14 +1613,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(
|
||||
|
@ -1615,14 +1644,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(
|
||||
|
|
|
@ -79,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' );
|
||||
|
||||
|
|
|
@ -294,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 );
|
||||
}
|
||||
|
|
|
@ -131,6 +131,10 @@ trait ContextTrait {
|
|||
return 'add-payment-method';
|
||||
}
|
||||
|
||||
if ( $this->is_block_editor() ) {
|
||||
return 'block-editor';
|
||||
}
|
||||
|
||||
return 'mini-cart';
|
||||
}
|
||||
|
||||
|
@ -207,4 +211,28 @@ trait ContextTrait {
|
|||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,654 @@ 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',
|
||||
),
|
||||
'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',
|
||||
),
|
||||
'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',
|
||||
),
|
||||
'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',
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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' ),
|
||||
|
|
|
@ -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',
|
||||
() => {
|
||||
|
|
|
@ -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(
|
||||
'BE' => array(
|
||||
'AUD',
|
||||
'BRL',
|
||||
'CAD',
|
||||
'CHF',
|
||||
'CZK',
|
||||
|
@ -118,16 +125,286 @@ return array(
|
|||
'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',
|
||||
),
|
||||
'IT' => array(
|
||||
'AUD',
|
||||
'BRL',
|
||||
'CAD',
|
||||
'CHF',
|
||||
'CZK',
|
||||
|
@ -136,12 +413,329 @@ 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',
|
||||
),
|
||||
'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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
14
modules/ppcp-paylater-block/.babelrc
Normal file
14
modules/ppcp-paylater-block/.babelrc
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"useBuiltIns": "usage",
|
||||
"corejs": "3.25.0"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@babel/preset-react"
|
||||
]
|
||||
]
|
||||
}
|
3
modules/ppcp-paylater-block/.gitignore
vendored
Normal file
3
modules/ppcp-paylater-block/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
node_modules
|
||||
assets/js
|
||||
assets/css
|
48
modules/ppcp-paylater-block/block.json
Normal file
48
modules/ppcp-paylater-block/block.json
Normal file
|
@ -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"
|
||||
}
|
17
modules/ppcp-paylater-block/composer.json
Normal file
17
modules/ppcp-paylater-block/composer.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "woocommerce/ppcp-paylater-block",
|
||||
"type": "dhii-mod",
|
||||
"description": "Pay Later Block 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\\PayLaterBlock\\": "src"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
12
modules/ppcp-paylater-block/extensions.php
Normal file
12
modules/ppcp-paylater-block/extensions.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* The Pay Later block module extensions.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterBlock
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterBlock;
|
||||
|
||||
return array();
|
16
modules/ppcp-paylater-block/module.php
Normal file
16
modules/ppcp-paylater-block/module.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* The Pay Later block module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterBlock
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterBlock;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
|
||||
return static function (): ModuleInterface {
|
||||
return new PayLaterBlockModule();
|
||||
};
|
33
modules/ppcp-paylater-block/package.json
Normal file
33
modules/ppcp-paylater-block/package.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "ppcp-paylater-block",
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"browserslist": [
|
||||
"> 0.5%",
|
||||
"Safari >= 8",
|
||||
"Chrome >= 41",
|
||||
"Firefox >= 43",
|
||||
"Edge >= 14"
|
||||
],
|
||||
"dependencies": {
|
||||
"core-js": "^3.25.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19",
|
||||
"@babel/preset-env": "^7.19",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@woocommerce/dependency-extraction-webpack-plugin": "^2.2.0",
|
||||
"babel-loader": "^8.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"file-loader": "^6.2.0",
|
||||
"sass": "^1.42.1",
|
||||
"sass-loader": "^12.1.0",
|
||||
"webpack": "^5.76",
|
||||
"webpack-cli": "^4.10"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "cross-env BABEL_ENV=default NODE_ENV=production webpack",
|
||||
"watch": "cross-env BABEL_ENV=default NODE_ENV=production webpack --watch",
|
||||
"dev": "cross-env BABEL_ENV=default webpack --watch"
|
||||
}
|
||||
}
|
19
modules/ppcp-paylater-block/resources/css/edit.scss
Normal file
19
modules/ppcp-paylater-block/resources/css/edit.scss
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 <div ref={containerRef}/>
|
||||
}
|
196
modules/ppcp-paylater-block/resources/js/edit.js
Normal file
196
modules/ppcp-paylater-block/resources/js/edit.js
Normal file
|
@ -0,0 +1,196 @@
|
|||
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, 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,
|
||||
},
|
||||
};
|
||||
|
||||
let classes = ['ppcp-paylater-block-preview', 'ppcp-overlay-parent'];
|
||||
if (PcpPayLaterBlock.vaultingEnabled) {
|
||||
classes = ['ppcp-paylater-block-preview', 'ppcp-paylater-unavailable', 'block-editor-warning'];
|
||||
}
|
||||
const props = useBlockProps({className: classes});
|
||||
|
||||
const loadingElement = <div {...props}><Spinner/></div>;
|
||||
|
||||
useEffect(() => {
|
||||
if (!id) {
|
||||
setAttributes({id: 'ppcp-' + clientId});
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (PcpPayLaterBlock.vaultingEnabled) {
|
||||
return <div {...props}>
|
||||
<div className={'block-editor-warning__contents'}>
|
||||
<h3>{__('PayPal Pay Later Messaging', 'woocommerce-paypal-payments')}</h3>
|
||||
<p className={'block-editor-warning__message'}>{__('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')}</p>
|
||||
<div className={'class="block-editor-warning__actions"'}>
|
||||
<span className={'block-editor-warning__action'}>
|
||||
<a href={PcpPayLaterBlock.settingsUrl} className={'components-button is-primary'}>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</a>
|
||||
</span>
|
||||
<span className={'block-editor-warning__action'}>
|
||||
<button onClick={() => wp.data.dispatch( 'core/block-editor' ).removeBlock(clientId)} type={'button'} className={'components-button is-secondary'}>
|
||||
{__('Remove Block', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
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 (
|
||||
<>
|
||||
<InspectorControls>
|
||||
<PanelBody title={ __( 'Settings', 'woocommerce-paypal-payments' ) }>
|
||||
<SelectControl
|
||||
label={ __( 'Layout', 'woocommerce-paypal-payments' ) }
|
||||
options={ [
|
||||
{ label: __( 'Text', 'woocommerce-paypal-payments' ), value: 'text' },
|
||||
{ label: __( 'Banner', 'woocommerce-paypal-payments' ), value: 'flex' },
|
||||
] }
|
||||
value={ layout }
|
||||
onChange={ ( value ) => setAttributes( { layout: value } ) }
|
||||
/>
|
||||
{ !isFlex && (<SelectControl
|
||||
label={__('Logo', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __('Primary', 'woocommerce-paypal-payments'), value: 'primary' },
|
||||
{ label: __('Alternative', 'woocommerce-paypal-payments'), value: 'alternative' },
|
||||
{ label: __('Inline', 'woocommerce-paypal-payments'), value: 'inline' },
|
||||
{ label: __('None', 'woocommerce-paypal-payments'), value: 'none' },
|
||||
]}
|
||||
value={logo}
|
||||
onChange={(value) => setAttributes({logo: value})}
|
||||
/>)}
|
||||
{ !isFlex && logo === 'primary' && (<SelectControl
|
||||
label={__('Logo Position', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __( 'Left', 'woocommerce-paypal-payments' ), value: 'left' },
|
||||
{ label: __( 'Right', 'woocommerce-paypal-payments' ), value: 'right' },
|
||||
{ label: __( 'Top', 'woocommerce-paypal-payments' ), value: 'top' },
|
||||
]}
|
||||
value={position}
|
||||
onChange={(value) => setAttributes({position: value})}
|
||||
/>)}
|
||||
{ !isFlex && (<SelectControl
|
||||
label={__('Text Color', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __( 'Black', 'woocommerce-paypal-payments' ), value: 'black' },
|
||||
{ label: __( 'White', 'woocommerce-paypal-payments' ), value: 'white' },
|
||||
{ label: __( 'Monochrome', 'woocommerce-paypal-payments' ), value: 'monochrome' },
|
||||
{ label: __( 'Grayscale', 'woocommerce-paypal-payments' ), value: 'grayscale' },
|
||||
]}
|
||||
value={color}
|
||||
onChange={(value) => setAttributes({color: value})}
|
||||
/>)}
|
||||
{ isFlex && (<SelectControl
|
||||
label={__('Color', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __( 'Blue', 'woocommerce-paypal-payments' ), value: 'blue' },
|
||||
{ label: __( 'Black', 'woocommerce-paypal-payments' ), value: 'black' },
|
||||
{ label: __( 'White', 'woocommerce-paypal-payments' ), value: 'white' },
|
||||
{ label: __( 'White no border', 'woocommerce-paypal-payments' ), value: 'white-no-border' },
|
||||
{ label: __( 'Gray', 'woocommerce-paypal-payments' ), value: 'gray' },
|
||||
{ label: __( 'Monochrome', 'woocommerce-paypal-payments' ), value: 'monochrome' },
|
||||
{ label: __( 'Grayscale', 'woocommerce-paypal-payments' ), value: 'grayscale' },
|
||||
]}
|
||||
value={flexColor}
|
||||
onChange={(value) => setAttributes({flexColor: value})}
|
||||
/>)}
|
||||
{ isFlex && (<SelectControl
|
||||
label={__('Ratio', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __( '1x1', 'woocommerce-paypal-payments' ), value: '1x1' },
|
||||
{ label: __( '1x4', 'woocommerce-paypal-payments' ), value: '1x4' },
|
||||
{ label: __( '8x1', 'woocommerce-paypal-payments' ), value: '8x1' },
|
||||
{ label: __( '20x1', 'woocommerce-paypal-payments' ), value: '20x1' },
|
||||
]}
|
||||
value={flexRatio}
|
||||
onChange={(value) => setAttributes({flexRatio: value})}
|
||||
/>)}
|
||||
<SelectControl
|
||||
label={ __( 'Placement page', 'woocommerce-paypal-payments' ) }
|
||||
help={ __( 'Used for the analytics dashboard in the merchant account.', 'woocommerce-paypal-payments' ) }
|
||||
options={ [
|
||||
{ label: __( 'Detect automatically', 'woocommerce-paypal-payments' ), value: 'auto' },
|
||||
{ label: __( 'Cart', 'woocommerce-paypal-payments' ), value: 'cart' },
|
||||
{ label: __( 'Payment', 'woocommerce-paypal-payments' ), value: 'payment' },
|
||||
{ label: __( 'Product', 'woocommerce-paypal-payments' ), value: 'product' },
|
||||
{ label: __( 'Product list', 'woocommerce-paypal-payments' ), value: 'product-list' },
|
||||
{ label: __( 'Home', 'woocommerce-paypal-payments' ), value: 'home' },
|
||||
{ label: __( 'Category', 'woocommerce-paypal-payments' ), value: 'category' },
|
||||
] }
|
||||
value={ placement }
|
||||
onChange={ ( value ) => setAttributes( { placement: value } ) }
|
||||
/>
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
<div {...props}>
|
||||
<div className={'ppcp-overlay-child'}>
|
||||
<PayPalMessages
|
||||
style={previewStyle}
|
||||
amount={amount}
|
||||
onRender={() => setRendered(true)}
|
||||
/>
|
||||
</div>
|
||||
<div className={'ppcp-overlay-child ppcp-unclicable-overlay'}> {/* make the message not clickable */}
|
||||
{!rendered && (<Spinner/>)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -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;
|
||||
};
|
36
modules/ppcp-paylater-block/resources/js/paylater-block.js
Normal file
36
modules/ppcp-paylater-block/resources/js/paylater-block.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { registerBlockType } from '@wordpress/blocks';
|
||||
|
||||
import Edit from './edit';
|
||||
import save from './save';
|
||||
|
||||
const paypalIcon = (
|
||||
<svg width="584.798" height="720" viewBox="0 0 154.728 190.5">
|
||||
<g transform="translate(898.192 276.071)">
|
||||
<path clipPath="none" d="M-837.663-237.968a5.49 5.49 0 0 0-5.423 4.633l-9.013 57.15-8.281 52.514-.005.044.01-.044 8.281-52.514c.421-2.669 2.719-4.633 5.42-4.633h26.404c26.573 0 49.127-19.387 53.246-45.658.314-1.996.482-3.973.52-5.924v-.003h-.003c-6.753-3.543-14.683-5.565-23.372-5.565z" fill="#001c64"/>
|
||||
<path clipPath="none" d="M-766.506-232.402c-.037 1.951-.207 3.93-.52 5.926-4.119 26.271-26.673 45.658-53.246 45.658h-26.404c-2.701 0-4.999 1.964-5.42 4.633l-8.281 52.514-5.197 32.947a4.46 4.46 0 0 0 4.405 5.153h28.66a5.49 5.49 0 0 0 5.423-4.633l7.55-47.881c.423-2.669 2.722-4.636 5.423-4.636h16.876c26.573 0 49.124-19.386 53.243-45.655 2.924-18.649-6.46-35.614-22.511-44.026z" fill="#0070e0"/>
|
||||
<path clipPath="none" d="M-870.225-276.071a5.49 5.49 0 0 0-5.423 4.636l-22.489 142.608a4.46 4.46 0 0 0 4.405 5.156h33.351l8.281-52.514 9.013-57.15a5.49 5.49 0 0 1 5.423-4.633h47.782c8.691 0 16.621 2.025 23.375 5.563.46-23.917-19.275-43.666-46.412-43.666z" fill="#003087"/>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
|
||||
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;
|
||||
},
|
||||
} );
|
||||
} );
|
25
modules/ppcp-paylater-block/resources/js/save.js
Normal file
25
modules/ppcp-paylater-block/resources/js/save.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { useBlockProps } from '@wordpress/block-editor';
|
||||
|
||||
export default function save( { attributes } ) {
|
||||
const { layout, logo, position, color, 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,
|
||||
};
|
||||
if (placement && placement !== 'auto') {
|
||||
paypalAttributes['data-pp-placement'] = placement;
|
||||
}
|
||||
const props = {
|
||||
className: 'ppcp-paylater-message-block',
|
||||
id,
|
||||
...paypalAttributes,
|
||||
};
|
||||
|
||||
return <div { ...useBlockProps.save(props) }></div>;
|
||||
}
|
26
modules/ppcp-paylater-block/services.php
Normal file
26
modules/ppcp-paylater-block/services.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* The Pay Later block module services.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterBlock
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterBlock;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array(
|
||||
'paylater-block.url' => 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'
|
||||
);
|
||||
},
|
||||
);
|
102
modules/ppcp-paylater-block/src/PayLaterBlockModule.php
Normal file
102
modules/ppcp-paylater-block/src/PayLaterBlockModule.php
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/**
|
||||
* The Pay Later block module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterBlock
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterBlock;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\CartScriptParamsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
/**
|
||||
* Class PayLaterBlockModule
|
||||
*/
|
||||
class PayLaterBlockModule implements ModuleInterface {
|
||||
/**
|
||||
* Returns whether the block should be loaded.
|
||||
*/
|
||||
public static function is_enabled(): bool {
|
||||
return apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
'woocommerce.feature-flags.woocommerce_paypal_payments.paylater_block_enabled',
|
||||
getenv( 'PCP_PAYLATER_BLOCK' ) === '1'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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' ),
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
}
|
||||
}
|
39
modules/ppcp-paylater-block/webpack.config.js
Normal file
39
modules/ppcp-paylater-block/webpack.config.js
Normal file
|
@ -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'}
|
||||
]
|
||||
}]
|
||||
}
|
||||
};
|
2201
modules/ppcp-paylater-block/yarn.lock
Normal file
2201
modules/ppcp-paylater-block/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
|
@ -28,6 +28,14 @@ document.addEventListener(
|
|||
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,
|
||||
|
@ -38,6 +46,8 @@ document.addEventListener(
|
|||
.then((paypal) => {
|
||||
errorHandler.clear();
|
||||
|
||||
const paypalButtonContainer = document.querySelector(`#ppc-button-${PaymentMethods.PAYPAL}-save-payment-method`);
|
||||
if(paypalButtonContainer) {
|
||||
paypal.Buttons(
|
||||
{
|
||||
createVaultSetupToken: async () => {
|
||||
|
@ -86,6 +96,7 @@ document.addEventListener(
|
|||
}
|
||||
},
|
||||
).render(`#ppc-button-${PaymentMethods.PAYPAL}-save-payment-method`);
|
||||
}
|
||||
|
||||
const cardField = paypal.CardFields({
|
||||
createVaultSetupToken: async () => {
|
||||
|
@ -125,6 +136,33 @@ document.addEventListener(
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -167,7 +205,15 @@ document.addEventListener(
|
|||
}
|
||||
}
|
||||
|
||||
document.querySelector('#place_order').addEventListener("click", (event) => {
|
||||
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()
|
||||
|
|
|
@ -33,6 +33,654 @@ return 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',
|
||||
),
|
||||
'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',
|
||||
),
|
||||
'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',
|
||||
),
|
||||
'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',
|
||||
|
|
|
@ -81,6 +81,7 @@ class CreatePaymentToken implements EndpointInterface {
|
|||
public function handle_request(): bool {
|
||||
try {
|
||||
$data = $this->request_data->read_request( $this->nonce() );
|
||||
$wc_token_id = 0;
|
||||
|
||||
/**
|
||||
* Suppress ArgumentTypeCoercion
|
||||
|
@ -98,7 +99,8 @@ class CreatePaymentToken implements EndpointInterface {
|
|||
$result = $this->payment_method_tokens_endpoint->payment_tokens( $payment_source );
|
||||
|
||||
if ( is_user_logged_in() && isset( $result->customer->id ) ) {
|
||||
update_user_meta( get_current_user_id(), '_ppcp_target_customer_id', $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 = '';
|
||||
|
@ -106,34 +108,19 @@ class CreatePaymentToken implements EndpointInterface {
|
|||
$email = $result->payment_source->paypal->email_address;
|
||||
}
|
||||
|
||||
$this->wc_payment_tokens->create_payment_token_paypal(
|
||||
get_current_user_id(),
|
||||
$wc_token_id = $this->wc_payment_tokens->create_payment_token_paypal(
|
||||
$current_user_id,
|
||||
$result->id,
|
||||
$email
|
||||
);
|
||||
}
|
||||
|
||||
if ( isset( $result->payment_source->card ) ) {
|
||||
$token = new \WC_Payment_Token_CC();
|
||||
$token->set_token( $result->id );
|
||||
$token->set_user_id( get_current_user_id() );
|
||||
$token->set_gateway_id( CreditCardGateway::ID );
|
||||
|
||||
$token->set_last4( $result->payment_source->card->last_digits ?? '' );
|
||||
$expiry = explode( '-', $result->payment_source->card->expiry ?? '' );
|
||||
$token->set_expiry_year( $expiry[0] ?? '' );
|
||||
$token->set_expiry_month( $expiry[1] ?? '' );
|
||||
|
||||
$brand = $result->payment_source->card->brand ?? __( 'N/A', 'woocommerce-paypal-payments' );
|
||||
if ( $brand ) {
|
||||
$token->set_card_type( $brand );
|
||||
}
|
||||
|
||||
$token->save();
|
||||
$wc_token_id = $this->wc_payment_tokens->create_payment_token_card( $current_user_id, $result );
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_success( $result );
|
||||
wp_send_json_success( $wc_token_id );
|
||||
return true;
|
||||
} catch ( Exception $exception ) {
|
||||
wp_send_json_error();
|
||||
|
|
|
@ -11,8 +11,8 @@ namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
|
|||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
|
@ -29,6 +29,7 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Endpoint\SubscriptionChangePaymentMethod;
|
||||
|
||||
/**
|
||||
* Class SavePaymentMethodsModule
|
||||
|
@ -55,6 +56,30 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
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 ) {
|
||||
|
@ -78,29 +103,12 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
// Adds attributes needed to save payment method.
|
||||
add_filter(
|
||||
'ppcp_create_order_request_body_data',
|
||||
function( array $data, string $payment_method, array $request_data ): array {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$wc_order_action = wc_clean( wp_unslash( $_POST['wc_order_action'] ?? '' ) );
|
||||
if ( $wc_order_action === 'wcs_process_renewal' ) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$subscription_id = wc_clean( wp_unslash( $_POST['post_ID'] ?? '' ) );
|
||||
$subscription = wcs_get_subscription( (int) $subscription_id );
|
||||
if ( $subscription ) {
|
||||
$customer_id = $subscription->get_customer_id();
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID );
|
||||
foreach ( $wc_tokens as $token ) {
|
||||
$data['payment_source'] = array(
|
||||
'paypal' => array(
|
||||
'vault_id' => $token->get_token(),
|
||||
),
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $payment_method === CreditCardGateway::ID ) {
|
||||
$save_payment_method = $request_data['save_payment_method'] ?? false;
|
||||
if ( $save_payment_method ) {
|
||||
$data['payment_source'] = array(
|
||||
|
@ -114,6 +122,10 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
);
|
||||
|
||||
$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,
|
||||
|
@ -123,17 +135,52 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
}
|
||||
|
||||
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' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} 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' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
},
|
||||
|
@ -176,11 +223,29 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -189,13 +254,12 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
);
|
||||
|
||||
add_filter( 'woocommerce_paypal_payments_disable_add_payment_method', '__return_false' );
|
||||
add_filter( 'woocommerce_paypal_payments_subscription_renewal_return_before_create_order_without_token', '__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() ) {
|
||||
if ( ! is_user_logged_in() || ! ( $this->is_add_payment_method_page() || $this->is_subscription_change_payment_method_page() ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -215,6 +279,9 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
$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 );
|
||||
|
@ -223,6 +290,8 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
assert( $settings instanceof Settings );
|
||||
$verification_method = $settings->has( '3d_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',
|
||||
|
@ -231,6 +300,9 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
'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(
|
||||
|
@ -242,6 +314,10 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
'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() ),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
@ -335,6 +411,13 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_paypal_payments_save_payment_methods_eligible',
|
||||
function() {
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -354,6 +437,9 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
$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 );
|
||||
|
|
|
@ -11,10 +11,15 @@ namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
|
|||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use stdClass;
|
||||
use WC_Payment_Token_CC;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenApplePay;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenFactory;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenPayPal;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenVenmo;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
/**
|
||||
|
@ -67,20 +72,26 @@ class WooCommercePaymentTokens {
|
|||
* @param string $token The PayPal payment token.
|
||||
* @param string $email The PayPal customer email.
|
||||
*
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function create_payment_token_paypal(
|
||||
int $customer_id,
|
||||
string $token,
|
||||
string $email
|
||||
): void {
|
||||
): int {
|
||||
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID );
|
||||
if ( $this->payment_token_helper->token_exist( $wc_tokens, $token ) ) {
|
||||
return;
|
||||
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 );
|
||||
|
@ -98,5 +109,138 @@ class WooCommercePaymentTokens {
|
|||
"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 {
|
||||
|
||||
$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 {
|
||||
|
||||
$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 {
|
||||
$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( get_current_user_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();
|
||||
}
|
||||
}
|
||||
|
|
31
modules/ppcp-vaulting/src/PaymentTokenApplePay.php
Normal file
31
modules/ppcp-vaulting/src/PaymentTokenApplePay.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/**
|
||||
* WooCommerce Payment token for ApplePay.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Vaulting
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||
|
||||
use WC_Payment_Token;
|
||||
|
||||
/**
|
||||
* Class PaymentTokenApplePay
|
||||
*/
|
||||
class PaymentTokenApplePay extends WC_Payment_Token {
|
||||
/**
|
||||
* Token Type String.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'ApplePay';
|
||||
|
||||
/**
|
||||
* Extra data.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $extra_data = array();
|
||||
}
|
|
@ -19,12 +19,16 @@ class PaymentTokenFactory {
|
|||
*
|
||||
* @param string $type The type of WC payment token.
|
||||
*
|
||||
* @return void|PaymentTokenPayPal
|
||||
* @return void|PaymentTokenPayPal|PaymentTokenVenmo|PaymentTokenApplePay
|
||||
*/
|
||||
public function create( string $type ) {
|
||||
switch ( $type ) {
|
||||
case 'paypal':
|
||||
return new PaymentTokenPayPal();
|
||||
case 'venmo':
|
||||
return new PaymentTokenVenmo();
|
||||
case 'apple_pay':
|
||||
return new PaymentTokenApplePay();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,15 +21,39 @@ class PaymentTokenHelper {
|
|||
*
|
||||
* @param WC_Payment_Token[] $wc_tokens WC Payment Tokens.
|
||||
* @param string $token_id Payment Token ID.
|
||||
* @param ?string $class_name Class name of the token.
|
||||
* @return bool
|
||||
*/
|
||||
public function token_exist( array $wc_tokens, string $token_id ): bool {
|
||||
public function token_exist( array $wc_tokens, string $token_id, string $class_name = null ): bool {
|
||||
foreach ( $wc_tokens as $wc_token ) {
|
||||
if ( $wc_token->get_token() === $token_id ) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
51
modules/ppcp-vaulting/src/PaymentTokenVenmo.php
Normal file
51
modules/ppcp-vaulting/src/PaymentTokenVenmo.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/**
|
||||
* WooCommerce Payment token for Venmo.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Vaulting
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Vaulting;
|
||||
|
||||
use WC_Payment_Token;
|
||||
|
||||
/**
|
||||
* Class PaymentTokenVenmo
|
||||
*/
|
||||
class PaymentTokenVenmo extends WC_Payment_Token {
|
||||
/**
|
||||
* Token Type String.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'Venmo';
|
||||
|
||||
/**
|
||||
* Extra data.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $extra_data = array(
|
||||
'email' => '',
|
||||
);
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -54,7 +54,11 @@ class VaultingModule implements ModuleInterface {
|
|||
$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;
|
||||
}
|
||||
|
||||
|
@ -191,8 +242,18 @@ 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 ( ! is_array( $methods ) ) {
|
||||
return $methods;
|
||||
}
|
||||
|
||||
if (
|
||||
isset( $wp->query_vars['add-payment-method'] )
|
||||
&& apply_filters( 'woocommerce_paypal_payments_disable_add_payment_method', true )
|
||||
|
|
|
@ -25,3 +25,17 @@
|
|||
.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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -355,11 +355,25 @@ document.addEventListener(
|
|||
}
|
||||
|
||||
// Logic to handle the "Check available features" button.
|
||||
((props) => {
|
||||
const $btn = jQuery(props.button);
|
||||
(($, props, anchor) => {
|
||||
const $btn = $(props.button);
|
||||
|
||||
const printStatus = (message, showSpinner) => {
|
||||
const html = message + (showSpinner ? '<span class="spinner is-active" style="float: none;"></span>' : '');
|
||||
$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('<span class="success">✔️ ' + props.messages.success + '</span>');
|
||||
$('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,
|
||||
|
@ -380,14 +394,18 @@ document.addEventListener(
|
|||
const responseData = await response.json();
|
||||
|
||||
if (!responseData.success) {
|
||||
alert(responseData.data.message);
|
||||
printStatus(responseData.data.message);
|
||||
$btn.prop('disabled', false);
|
||||
} else {
|
||||
window.location.reload();
|
||||
window.location.href += (window.location.href.indexOf('?') > -1 ? '&' : '?') + "feature-refreshed=1#";
|
||||
}
|
||||
});
|
||||
|
||||
})(PayPalCommerceGatewaySettings.ajax.refresh_feature_status);
|
||||
})(
|
||||
jQuery,
|
||||
PayPalCommerceGatewaySettings.ajax.refresh_feature_status,
|
||||
'#field-credentials_feature_onboarding_heading'
|
||||
);
|
||||
|
||||
}
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
|
@ -332,6 +333,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
|
||||
);
|
||||
},
|
||||
|
@ -367,8 +369,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' );
|
||||
|
@ -418,6 +421,18 @@ return array(
|
|||
},
|
||||
|
||||
'wcgateway.settings.fields.subscriptions_mode' => static function ( ContainerInterface $container ): array {
|
||||
$subscription_mode_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' ),
|
||||
);
|
||||
|
||||
$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',
|
||||
|
@ -426,11 +441,7 @@ return array(
|
|||
'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' ),
|
||||
),
|
||||
'options' => $subscription_mode_options,
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
|
@ -939,7 +950,6 @@ return array(
|
|||
'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' ),
|
||||
|
@ -1315,6 +1325,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 ) {
|
||||
|
@ -1353,6 +1369,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(
|
||||
'<p>%1$s %2$s</p><p><a target="%3$s" href="%4$s" class="button">%5$s</a></p>',
|
||||
$enabled ? $enabled_status_text : $disabled_status_text,
|
||||
$enabled ? '<span class="dashicons dashicons-yes"></span>' : '<span class="dashicons dashicons-no"></span>',
|
||||
$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 ) {
|
||||
|
@ -1400,8 +1449,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',
|
||||
);
|
||||
},
|
||||
|
|
|
@ -244,6 +244,10 @@ class SettingsPageAssets {
|
|||
'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' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -56,6 +56,8 @@ 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 ];
|
||||
|
@ -78,6 +80,8 @@ 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. */
|
||||
|
@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
|||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
|
@ -368,6 +369,9 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
$saved_payment_card = WC()->session->get( 'ppcp_saved_payment_card' );
|
||||
if ( $saved_payment_card ) {
|
||||
if ( $saved_payment_card['payment_source'] === 'card' && $saved_payment_card['status'] === 'COMPLETED' ) {
|
||||
$wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $saved_payment_card['order_id'] );
|
||||
$wc_order->save_meta_data();
|
||||
|
||||
$this->update_transaction_id( $saved_payment_card['order_id'], $wc_order );
|
||||
$wc_order->payment_complete();
|
||||
WC()->session->set( 'ppcp_saved_payment_card', null );
|
||||
|
@ -377,11 +381,11 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
|
@ -395,6 +399,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.
|
||||
*/
|
||||
|
|
|
@ -12,11 +12,11 @@ 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\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;
|
||||
|
@ -498,7 +498,7 @@ 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() ) {
|
||||
$user_id = (int) $wc_order->get_customer_id();
|
||||
$tokens = $this->payment_token_repository->all_for_user_id( $user_id );
|
||||
if ( ! array_filter(
|
||||
|
@ -522,11 +522,22 @@ 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 );
|
||||
$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 );
|
||||
}
|
||||
|
||||
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' ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ class ConnectAdminNotice {
|
|||
$message = sprintf(
|
||||
/* translators: %1$s the gateway name. */
|
||||
__(
|
||||
'PayPal Payments is almost ready. To get started, <a href="%1$s">connect your account</a>.',
|
||||
'PayPal Payments is almost ready. To get started, connect your account with the <b>Activate PayPal</b> button <a href="%1$s">on the Account Setup page</a>.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=' . Settings::CONNECTION_TAB_ID )
|
||||
|
|
|
@ -56,6 +56,13 @@ class RefundProcessor {
|
|||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* The prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* The refund fees updater.
|
||||
*
|
||||
|
@ -69,13 +76,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;
|
||||
}
|
||||
|
||||
|
@ -164,7 +179,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() )
|
||||
|
|
|
@ -393,7 +393,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'refresh_feature_status' => array(
|
||||
'title' => __( 'Refresh feature availability status', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-text',
|
||||
'text' => '<button type="button" class="button ppcp-refresh-feature-status">' . esc_html__( 'Check available features', 'woocommerce-paypal-payments' ) . '</button>',
|
||||
'text' => '<button type="button" class="button ppcp-refresh-feature-status">' . esc_html__( 'Check available features', 'woocommerce-paypal-payments' ) . '</button><div class="ppcp-status-text"></div>',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
|
@ -410,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',
|
||||
|
|
|
@ -378,7 +378,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 +502,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(),
|
||||
|
|
|
@ -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 <a> 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 <a> 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'
|
||||
),
|
||||
'<a href="https://woocommerce.com/document/woocommerce-paypal-payments/#button-on-cart" target="_blank">',
|
||||
|
@ -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 <a> 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'
|
||||
),
|
||||
'<a href="https://woocommerce.com/document/woocommerce-paypal-payments/#button-on-block-express-checkout" target="_blank">',
|
||||
|
@ -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 <a> 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'
|
||||
),
|
||||
'<a href="https://woocommerce.com/document/woocommerce-paypal-payments/#button-on-cart-block" target="_blank">',
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
@ -176,6 +184,7 @@ class SettingsListener {
|
|||
* @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(
|
||||
|
@ -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,9 @@ 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 ( $subscription_mode === 'vaulting_api' && $vault_enabled !== '1' && $reference_transaction_enabled === true ) {
|
||||
$this->settings->set( 'vault_enabled', true );
|
||||
$this->settings->persist();
|
||||
}
|
||||
|
|
|
@ -533,19 +533,5 @@ $data_rows_html
|
|||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if vaulting admin message can be displayed.
|
||||
*
|
||||
* @return bool Whether the message can be displayed or not.
|
||||
*/
|
||||
private function can_display_vaulting_admin_message(): bool {
|
||||
if ( State::STATE_ONBOARDED !== $this->state->current_state() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->is_paypal_checkout_screen()
|
||||
&& ( $this->paypal_vaulting_is_enabled() || $this->settings_status->is_pay_later_messaging_enabled() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -430,6 +430,28 @@ 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' );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,10 +9,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use WooCommerce\PayPalCommerce\PayPalSubscriptions\DeactivatePlanEndpoint;
|
||||
use WooCommerce\PayPalCommerce\PayPalSubscriptions\SubscriptionsApiHandler;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Endpoint\SubscriptionChangePaymentMethod;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
||||
return array(
|
||||
|
@ -28,6 +27,7 @@ return array(
|
|||
$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,
|
||||
|
@ -37,7 +37,8 @@ return array(
|
|||
$payer_factory,
|
||||
$environment,
|
||||
$settings,
|
||||
$authorized_payments_processor
|
||||
$authorized_payments_processor,
|
||||
$funding_source_renderer
|
||||
);
|
||||
},
|
||||
'wc-subscriptions.repository.payment-token' => static function ( ContainerInterface $container ): PaymentTokenRepository {
|
||||
|
@ -45,4 +46,9 @@ return array(
|
|||
$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' )
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
/**
|
||||
* The Create Payment Token endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions\Endpoint;
|
||||
|
||||
use Exception;
|
||||
use WC_Order;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
|
||||
/**
|
||||
* Class SubscriptionChangePaymentMethod
|
||||
*/
|
||||
class SubscriptionChangePaymentMethod implements EndpointInterface {
|
||||
|
||||
const ENDPOINT = 'ppc-subscription-change-payment-method';
|
||||
|
||||
/**
|
||||
* The request data.
|
||||
*
|
||||
* @var RequestData
|
||||
*/
|
||||
private $request_data;
|
||||
|
||||
/**
|
||||
* SubscriptionChangePaymentMethod constructor.
|
||||
*
|
||||
* @param RequestData $request_data $request_data The request data.
|
||||
*/
|
||||
public function __construct( RequestData $request_data ) {
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use WC_Order;
|
||||
use WC_Subscription;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
|
@ -20,10 +22,15 @@ 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\Vaulting\PaymentTokenApplePay;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenPayPal;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenVenmo;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderMetaTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\PaymentsStatusHandlingTrait;
|
||||
|
@ -102,6 +109,13 @@ class RenewalHandler {
|
|||
*/
|
||||
protected $authorized_payments_processor;
|
||||
|
||||
/**
|
||||
* The funding source renderer.
|
||||
*
|
||||
* @var FundingSourceRenderer
|
||||
*/
|
||||
protected $funding_source_renderer;
|
||||
|
||||
/**
|
||||
* RenewalHandler constructor.
|
||||
*
|
||||
|
@ -114,6 +128,7 @@ class RenewalHandler {
|
|||
* @param Environment $environment The environment.
|
||||
* @param Settings $settings The Settings.
|
||||
* @param AuthorizedPaymentsProcessor $authorized_payments_processor The Authorized Payments Processor.
|
||||
* @param FundingSourceRenderer $funding_source_renderer The funding source renderer.
|
||||
*/
|
||||
public function __construct(
|
||||
LoggerInterface $logger,
|
||||
|
@ -124,7 +139,8 @@ class RenewalHandler {
|
|||
PayerFactory $payer_factory,
|
||||
Environment $environment,
|
||||
Settings $settings,
|
||||
AuthorizedPaymentsProcessor $authorized_payments_processor
|
||||
AuthorizedPaymentsProcessor $authorized_payments_processor,
|
||||
FundingSourceRenderer $funding_source_renderer
|
||||
) {
|
||||
|
||||
$this->logger = $logger;
|
||||
|
@ -136,6 +152,7 @@ class RenewalHandler {
|
|||
$this->environment = $environment;
|
||||
$this->settings = $settings;
|
||||
$this->authorized_payments_processor = $authorized_payments_processor;
|
||||
$this->funding_source_renderer = $funding_source_renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -194,32 +211,80 @@ class RenewalHandler {
|
|||
'renewal'
|
||||
);
|
||||
|
||||
$token = $this->get_token_for_customer( $customer, $wc_order );
|
||||
if ( $token ) {
|
||||
if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) {
|
||||
$stored_credentials = array(
|
||||
// Vault v3.
|
||||
$payment_source = null;
|
||||
if ( $wc_order->get_payment_method() === PayPalGateway::ID ) {
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $wc_order->get_customer_id(), PayPalGateway::ID );
|
||||
foreach ( $wc_tokens as $token ) {
|
||||
$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
|
||||
);
|
||||
|
||||
$subscriptions = wcs_get_subscriptions_for_renewal_order( $wc_order );
|
||||
foreach ( $subscriptions as $post_id => $subscription ) {
|
||||
$previous_transaction_reference = $subscription->get_meta( 'ppcp_previous_transaction_reference' );
|
||||
if ( $previous_transaction_reference ) {
|
||||
$stored_credentials['previous_transaction_reference'] = $previous_transaction_reference;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$payment_source = new PaymentSource(
|
||||
'card',
|
||||
(object) array(
|
||||
'vault_id' => $token->id(),
|
||||
'stored_credential' => $stored_credentials,
|
||||
if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) {
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $wc_order->get_customer_id(), CreditCardGateway::ID );
|
||||
foreach ( $wc_tokens as $token ) {
|
||||
$payment_source = $this->card_payment_source( $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 );
|
||||
|
||||
$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,
|
||||
|
@ -244,6 +309,7 @@ class RenewalHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
if ( $wc_order->get_payment_method() === PayPalGateway::ID ) {
|
||||
$order = $this->order_endpoint->create(
|
||||
array( $purchase_unit ),
|
||||
$shipping_preference,
|
||||
|
@ -259,28 +325,8 @@ class RenewalHandler {
|
|||
$wc_order->get_id()
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( apply_filters( 'woocommerce_paypal_payments_subscription_renewal_return_before_create_order_without_token', true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$order = $this->order_endpoint->create(
|
||||
array( $purchase_unit ),
|
||||
$shipping_preference,
|
||||
$payer
|
||||
);
|
||||
|
||||
$this->handle_paypal_order( $wc_order, $order );
|
||||
|
||||
$this->logger->info(
|
||||
sprintf(
|
||||
'Renewal for order %d is completed.',
|
||||
$wc_order->get_id()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -302,18 +348,7 @@ class RenewalHandler {
|
|||
|
||||
$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 );
|
||||
return false;
|
||||
}
|
||||
|
||||
$subscription = function_exists( 'wcs_get_subscription' ) ? wcs_get_subscription( $wc_order->get_meta( '_subscription_renewal' ) ) : null;
|
||||
|
@ -386,6 +421,11 @@ class RenewalHandler {
|
|||
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 );
|
||||
}
|
||||
|
||||
$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 );
|
||||
|
@ -399,4 +439,69 @@ class RenewalHandler {
|
|||
$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,
|
||||
);
|
||||
|
||||
if (
|
||||
$this->settings->has( '3d_secure_contingency' )
|
||||
&& ( $this->settings->get( '3d_secure_contingency' ) === 'SCA_ALWAYS' || $this->settings->get( '3d_secure_contingency' ) === 'SCA_WHEN_REQUIRED' )
|
||||
) {
|
||||
$stored_credentials = array(
|
||||
'payment_initiator' => 'MERCHANT',
|
||||
'payment_type' => 'RECURRING',
|
||||
'usage' => 'SUBSEQUENT',
|
||||
);
|
||||
|
||||
$subscriptions = wcs_get_subscriptions_for_renewal_order( $wc_order );
|
||||
foreach ( $subscriptions as $post_id => $subscription ) {
|
||||
$previous_transaction_reference = $subscription->get_meta( 'ppcp_previous_transaction_reference' );
|
||||
if ( $previous_transaction_reference ) {
|
||||
$stored_credentials['previous_transaction_reference'] = $previous_transaction_reference;
|
||||
$properties['stored_credentials'] = $stored_credentials;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
|||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Subscription;
|
||||
use WC_Payment_Token_CC;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
|
@ -19,10 +20,12 @@ use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
|||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Endpoint\SubscriptionChangePaymentMethod;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
||||
/**
|
||||
|
@ -82,6 +85,10 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
* @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;
|
||||
|
@ -90,7 +97,9 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
$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();
|
||||
|
@ -102,6 +111,17 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
$subscription->update_meta_data( 'ppcp_previous_transaction_reference', $transaction_id );
|
||||
$subscription->save();
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,6 +153,10 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
* @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' );
|
||||
|
@ -142,6 +166,76 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
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();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,28 +316,16 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
&& 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'
|
||||
);
|
||||
}
|
||||
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), PayPalGateway::ID );
|
||||
|
||||
$output = sprintf(
|
||||
'<p class="form-row form-row-wide"><label>%1$s</label><select id="saved-paypal-payment" name="saved_paypal_payment">',
|
||||
esc_html__( 'Select a saved PayPal payment', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
$output = '<ul class="wc-saved-payment-methods">';
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( isset( $token->source()->paypal ) ) {
|
||||
$output .= sprintf(
|
||||
'<option value="%1$s">%2$s</option>',
|
||||
$token->id(),
|
||||
$token->source()->paypal->payer->email_address
|
||||
);
|
||||
$output .= '<li>';
|
||||
$output .= sprintf( '<input name="saved_paypal_payment" type="radio" value="%s" style="width:auto;" checked="checked">', $token->get_id() );
|
||||
$output .= sprintf( '<label for="saved_paypal_payment">%s / %s</label>', $token->get_type(), $token->get_meta( 'email' ) ?? '' );
|
||||
$output .= '</li>';
|
||||
}
|
||||
}
|
||||
$output .= '</select></p>';
|
||||
$output .= '</ul>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
@ -269,33 +351,23 @@ class WcSubscriptionsModule implements ModuleInterface {
|
|||
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;
|
||||
}
|
||||
|
||||
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), CreditCardGateway::ID );
|
||||
$output = sprintf(
|
||||
'<p class="form-row form-row-wide"><label>%1$s</label><select id="saved-credit-card" name="saved_credit_card">',
|
||||
esc_html__( 'Select a saved Credit Card payment', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( isset( $token->source()->card ) ) {
|
||||
if ( $token instanceof WC_Payment_Token_CC ) {
|
||||
$output .= sprintf(
|
||||
'<option value="%1$s">%2$s ...%3$s</option>',
|
||||
$token->id(),
|
||||
$token->source()->card->brand,
|
||||
$token->source()->card->last_digits
|
||||
$token->get_id(),
|
||||
$token->get_card_type(),
|
||||
$token->get_last4()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "woocommerce-paypal-payments",
|
||||
"version": "2.4.3",
|
||||
"version": "2.5.3",
|
||||
"description": "WooCommerce PayPal Payments",
|
||||
"repository": "https://github.com/woocommerce/woocommerce-paypal-payments",
|
||||
"license": "GPL-2.0",
|
||||
|
@ -9,6 +9,7 @@
|
|||
"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-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",
|
||||
|
@ -21,6 +22,7 @@
|
|||
"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-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",
|
||||
|
@ -34,6 +36,7 @@
|
|||
"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-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",
|
||||
|
|
39
readme.txt
39
readme.txt
|
@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, checkout, cart, pay later, apple
|
|||
Requires at least: 5.3
|
||||
Tested up to: 6.4
|
||||
Requires PHP: 7.2
|
||||
Stable tag: 2.4.3
|
||||
Stable tag: 2.5.3
|
||||
License: GPLv2
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
|
@ -179,6 +179,43 @@ If you encounter issues with the PayPal buttons not appearing after an update, p
|
|||
|
||||
== Changelog ==
|
||||
|
||||
= 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -109,6 +109,8 @@ class CreditCardGatewayTest extends TestCase
|
|||
$session->shouldReceive('set')->andReturn([]);
|
||||
$session->shouldReceive('get')->andReturn('');
|
||||
|
||||
when('is_checkout')->justReturn(true);
|
||||
|
||||
$savedCreditCard = 'abc123';
|
||||
$_POST['saved_credit_card'] = $savedCreditCard;
|
||||
|
||||
|
|
|
@ -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 [
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,171 +0,0 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\Dictionary;
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\CaptureStatus;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
|
||||
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\TestCase;
|
||||
use Mockery;
|
||||
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use function Brain\Monkey\Functions\when;
|
||||
|
||||
class RenewalHandlerTest extends TestCase
|
||||
{
|
||||
use MockeryPHPUnitIntegration;
|
||||
|
||||
private $logger;
|
||||
private $repository;
|
||||
private $orderEndpoint;
|
||||
private $purchaseUnitFactory;
|
||||
private $shippingPreferenceFactory;
|
||||
private $payerFactory;
|
||||
private $environment;
|
||||
private $sut;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->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_payment_method')
|
||||
->andReturn('');
|
||||
$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);
|
||||
}
|
||||
}
|
|
@ -3,13 +3,13 @@
|
|||
* 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.3
|
||||
* Version: 2.5.3
|
||||
* Author: WooCommerce
|
||||
* Author URI: https://woocommerce.com/
|
||||
* License: GPL-2.0
|
||||
* Requires PHP: 7.2
|
||||
* WC requires at least: 3.9
|
||||
* WC tested up to: 8.4
|
||||
* WC tested up to: 8.5
|
||||
* Text Domain: woocommerce-paypal-payments
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce
|
||||
|
@ -25,7 +25,7 @@ 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-12-18' );
|
||||
define( 'PAYPAL_INTEGRATION_DATE', '2024-02-01' );
|
||||
|
||||
! 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_' );
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue