Merge remote-tracking branch 'origin/trunk' into modularity-module-migration

# Conflicts:
#	modules/ppcp-admin-notices/src/AdminNotices.php
#	modules/ppcp-save-payment-methods/src/SavePaymentMethodsModule.php
#	modules/ppcp-wc-gateway/src/WCGatewayModule.php
#	modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php
#	tests/PHPUnit/WcSubscriptions/RenewalHandlerTest.php
This commit is contained in:
Pedro Silva 2024-03-27 18:42:21 +00:00
commit 392d27f08b
No known key found for this signature in database
GPG key ID: E2EE20C0669D24B3
163 changed files with 13687 additions and 1746 deletions

View file

@ -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' ),

View file

@ -34,6 +34,9 @@ class ApplepayButton {
// Stores initialization data sent to the button.
this.initialPaymentRequest = null;
// Default eligibility status.
this.isEligible = true;
this.log = function() {
if ( this.buttonConfig.is_debug ) {
console.log('[ApplePayButton]', ...arguments);
@ -63,14 +66,10 @@ class ApplepayButton {
this.initEventHandlers();
this.isInitialized = true;
this.applePayConfig = config;
const isEligible = (this.applePayConfig.isEligible && window.ApplePaySession) || this.buttonConfig.is_admin;
this.isEligible = (this.applePayConfig.isEligible && window.ApplePaySession) || this.buttonConfig.is_admin;
if (isEligible) {
if (this.isEligible) {
this.fetchTransactionInfo().then(() => {
const isSubscriptionProduct = this.ppcpConfig?.data_client_id?.has_subscriptions === true;
if (isSubscriptionProduct) {
return;
}
this.addButton();
const id_minicart = "#apple-" + this.buttonConfig.button.mini_cart_wrapper;
const id = "#apple-" + this.buttonConfig.button.wrapper;
@ -137,6 +136,10 @@ class ApplepayButton {
const wrapper_id = '#' + wrapper;
const syncButtonVisibility = () => {
if (!this.isEligible) {
return;
}
const $ppcpButtonWrapper = jQuery(ppcpButtonWrapper);
setVisible(wrapper_id, $ppcpButtonWrapper.is(':visible'));
setEnabled(wrapper_id, !$ppcpButtonWrapper.hasClass('ppcp-disabled'));
@ -207,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';

View file

@ -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;
}

View file

@ -7,7 +7,7 @@ class PayNowHandler extends BaseHandler {
validateContext() {
if ( this.ppcpConfig?.locations_with_subscription_product?.payorder ) {
return false;
return this.isVaultV3Mode();
}
return true;
}

View file

@ -9,7 +9,7 @@ class SingleProductHandler extends BaseHandler {
validateContext() {
if ( this.ppcpConfig?.locations_with_subscription_product?.product ) {
return false;
return this.isVaultV3Mode();
}
return true;
}

View file

@ -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}}/>,

View file

@ -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',
() => {

View file

@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\Applepay\Assets\BlocksPaymentMethod;
use WooCommerce\PayPalCommerce\Applepay\Assets\PropertiesDictionary;
use WooCommerce\PayPalCommerce\Applepay\Helper\ApmApplies;
use WooCommerce\PayPalCommerce\Applepay\Helper\AvailabilityNotice;
use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator;
use WooCommerce\PayPalCommerce\Onboarding\Environment;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
@ -72,14 +73,16 @@ return array(
return $settings->has( 'applepay_validated' ) ? $settings->get( 'applepay_validated' ) === true : false;
},
'applepay.apple-product-status' => static function( ContainerInterface $container ): AppleProductStatus {
return new AppleProductStatus(
$container->get( 'wcgateway.settings' ),
$container->get( 'api.endpoint.partners' ),
$container->get( 'onboarding.state' ),
$container->get( 'api.helper.failure-registry' )
);
},
'applepay.apple-product-status' => SingletonDecorator::make(
static function( ContainerInterface $container ): AppleProductStatus {
return new AppleProductStatus(
$container->get( 'wcgateway.settings' ),
$container->get( 'api.endpoint.partners' ),
$container->get( 'onboarding.state' ),
$container->get( 'api.helper.failure-registry' )
);
}
),
'applepay.available' => static function ( ContainerInterface $container ): bool {
if ( apply_filters( 'woocommerce_paypal_payments_applepay_validate_product_status', true ) ) {
$status = $container->get( 'applepay.apple-product-status' );
@ -171,8 +174,9 @@ return array(
return apply_filters(
'woocommerce_paypal_payments_applepay_supported_country_currency_matrix',
array(
'CA' => array(
'AU' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
@ -181,16 +185,22 @@ return array(
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'GB' => array(
'AT' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
@ -199,16 +209,334 @@ return array(
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'BE' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'BG' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'CA' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'CY' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'CZ' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'DK' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'EE' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'FI' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'FR' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'DE' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'GR' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'HU' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'IE' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'IT' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
@ -217,12 +545,377 @@ return array(
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'LV' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'LI' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'LT' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'LU' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'MT' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'NO' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'NL' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'PL' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'PT' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'RO' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'SK' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'SI' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'ES' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'SE' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'GB' => array(
'AUD',
'BRL',
'CAD',
'CHF',
'CZK',
'DKK',
'EUR',
'GBP',
'HKD',
'HUF',
'ILS',
'JPY',
'MXN',
'NOK',
'NZD',
'PHP',
'PLN',
'SEK',
'SGD',
'THB',
'TWD',
'USD',
),
'US' => array(

View file

@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\Applepay\Assets;
use Throwable;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusCapability;
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
@ -100,6 +101,11 @@ class AppleProductStatus {
return false;
}
$status_override = apply_filters( 'woocommerce_paypal_payments_apple_pay_product_status', null );
if ( null !== $status_override ) {
return $status_override;
}
// If status was already checked on this request return the same result.
if ( null !== $this->current_status ) {
return $this->current_status;
@ -128,21 +134,32 @@ class AppleProductStatus {
}
// Check the seller status for the intended capability.
$has_capability = false;
foreach ( $seller_status->products() as $product ) {
if ( $product->name() !== 'PAYMENT_METHODS' ) {
continue;
}
if ( in_array( self::CAPABILITY_NAME, $product->capabilities(), true ) ) {
// Capability found, persist status and return true.
$this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED );
$this->settings->persist();
$this->current_status = true;
return $this->current_status;
$has_capability = true;
}
}
foreach ( $seller_status->capabilities() as $capability ) {
if ( $capability->name() === self::CAPABILITY_NAME && $capability->status() === SellerStatusCapability::STATUS_ACTIVE ) {
$has_capability = true;
}
}
if ( $has_capability ) {
// Capability found, persist status and return true.
$this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED );
$this->settings->persist();
$this->current_status = true;
return $this->current_status;
}
// Capability not found, persist status and return false.
$this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED );
$this->settings->persist();

View file

@ -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">',