mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
🔀 Merge branch 'trunk'
This commit is contained in:
commit
32d870bd6b
39 changed files with 11104 additions and 307 deletions
|
@ -1,5 +1,30 @@
|
|||
*** Changelog ***
|
||||
|
||||
= 2.9.3 - 2024-10-15 =
|
||||
* Fix - Multi-currency support #2667
|
||||
* Fix - "0.00" amount in Google Pay for virtual products #2636
|
||||
* Fix - Unsuccessfully payment from product page with Apple Pay button #2643
|
||||
* Fix - Button Unlinking PayPal Subscriptions plan does not showing for simple subscription #2618
|
||||
* Fix - Declare tokenization for ACDC only when vaulting enabled #2581
|
||||
* Fix - Classic shortcode block type checks #2608
|
||||
* Fix - PUI error in editor #2580
|
||||
* Fix - Add a new namespaced script loader for ApplePay #2682 #2675
|
||||
* Fix - Axo Block: Fix the Fastlane modal info message text overflow issue #2663
|
||||
* Fix - Add Custom Placeholder Handling when rendering the card fields #2651
|
||||
* Fix - Use the PayPal icons instead of WC ones #2639
|
||||
* Fix - Google Pay preview config and style #2661
|
||||
* Fix - Improve context detection #2631
|
||||
* Fix - Check that get_the_ID is valid before using #2573
|
||||
* Fix - Axo Block: Always display the Fastlane watermark in the includeAdditionalInfo mode #2690
|
||||
* Fix - Axo Block: Display card fields for authenticated cardless profiles #2672
|
||||
* Fix - Google Pay: Fix button preview in the editor #2688
|
||||
* Fix - ACDC gateway not visible on the block Checkout for logged-out users #2693
|
||||
* Enhancement - Enhancement - Add Fastlane support for Checkout block
|
||||
* Enhancement - Multiple calls to POST /v1/oauth2/token?grant_type=client_credentials&response_type=id_token #2671
|
||||
* Enhancement - Fastlane update shipping options & taxes when changing address #2665
|
||||
* Enhancement - Axo: Remove Axo from the Checkout block in the editor and add an ACDC card preview #2662
|
||||
* Enhancement - Set email when creating order for express payment #2577
|
||||
|
||||
= 2.9.2 - 2024-10-01 =
|
||||
* Enhancement - Add Fastlane support for Classic Checkout
|
||||
* Fix - Fatal error when Pay Later messaging configurator was disabled with a code snippet
|
||||
|
|
|
@ -90,5 +90,12 @@ return function ( string $root_dir ): iterable {
|
|||
$modules[] = ( require "$modules_dir/ppcp-axo-block/module.php" )();
|
||||
}
|
||||
|
||||
if ( apply_filters(
|
||||
'woocommerce.feature-flags.woocommerce_paypal_payments.settings_enabled',
|
||||
getenv( 'PCP_SETTINGS_ENABLED' ) === '1'
|
||||
) ) {
|
||||
$modules[] = ( require "$modules_dir/ppcp-settings/module.php" )();
|
||||
}
|
||||
|
||||
return $modules;
|
||||
};
|
||||
|
|
|
@ -716,7 +716,6 @@ return array(
|
|||
'FR' => $mastercard_visa_amex,
|
||||
'GB' => $mastercard_visa_amex,
|
||||
'GR' => $mastercard_visa_amex,
|
||||
'HK' => $mastercard_visa_amex,
|
||||
'HU' => $mastercard_visa_amex,
|
||||
'IE' => $mastercard_visa_amex,
|
||||
'IT' => $mastercard_visa_amex,
|
||||
|
@ -746,7 +745,6 @@ return array(
|
|||
'SE' => $mastercard_visa_amex,
|
||||
'SI' => $mastercard_visa_amex,
|
||||
'SK' => $mastercard_visa_amex,
|
||||
'SG' => $mastercard_visa_amex,
|
||||
'JP' => array(
|
||||
'mastercard' => array(),
|
||||
'visa' => array(),
|
||||
|
|
|
@ -191,7 +191,6 @@ return array(
|
|||
'FR', // France
|
||||
'DE', // Germany
|
||||
'GR', // Greece
|
||||
'HK', // Hong Kong
|
||||
'HU', // Hungary
|
||||
'IE', // Ireland
|
||||
'IT', // Italy
|
||||
|
@ -205,7 +204,6 @@ return array(
|
|||
'PL', // Poland
|
||||
'PT', // Portugal
|
||||
'RO', // Romania
|
||||
'SG', // Singapore
|
||||
'SK', // Slovakia
|
||||
'SI', // Slovenia
|
||||
'ES', // Spain
|
||||
|
|
|
@ -174,9 +174,6 @@ $fast-transition-duration: 0.5s;
|
|||
grid-area: watermark;
|
||||
justify-self: end;
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
&:not(.wc-block-axo-is-authenticated) .wc-block-checkout-axo-block-watermark-container {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
|
@ -259,8 +256,8 @@ a.wc-block-axo-change-link {
|
|||
.wp-block-woocommerce-checkout-fields-block:not(.wc-block-axo-is-loaded) {
|
||||
.wc-block-checkout-axo-block-watermark-container {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
margin-left: 10px;
|
||||
justify-content: right;
|
||||
margin-right: 10px;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useEffect, useCallback, useState } from '@wordpress/element';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { log } from '../../../../../ppcp-axo/resources/js/Helper/Debug';
|
||||
import { Card } from '../Card';
|
||||
import { STORE_NAME } from '../../stores/axoStore';
|
||||
|
||||
|
@ -16,27 +17,48 @@ export const Payment = ( { fastlaneSdk, onPaymentLoad } ) => {
|
|||
const [ isCardElementReady, setIsCardElementReady ] = useState( false );
|
||||
|
||||
// Select relevant states from the AXO store
|
||||
const { isGuest, isEmailLookupCompleted } = useSelect(
|
||||
const { isGuest, isEmailLookupCompleted, cardDetails } = useSelect(
|
||||
( select ) => ( {
|
||||
isGuest: select( STORE_NAME ).getIsGuest(),
|
||||
isEmailLookupCompleted:
|
||||
select( STORE_NAME ).getIsEmailLookupCompleted(),
|
||||
cardDetails: select( STORE_NAME ).getCardDetails(),
|
||||
} ),
|
||||
[]
|
||||
);
|
||||
|
||||
/**
|
||||
* Loads and renders the Fastlane card fields component when necessary.
|
||||
* This function is called for:
|
||||
* 1. Guest users who have completed email lookup
|
||||
* 2. Authenticated users who are missing card details
|
||||
*
|
||||
* The component allows users to enter new card details for payment.
|
||||
*/
|
||||
const loadPaymentComponent = useCallback( async () => {
|
||||
if ( isGuest && isEmailLookupCompleted && isCardElementReady ) {
|
||||
const paymentComponent = await fastlaneSdk.FastlaneCardComponent(
|
||||
{}
|
||||
);
|
||||
paymentComponent.render( `#fastlane-card` );
|
||||
if (
|
||||
( isGuest && isEmailLookupCompleted && isCardElementReady ) ||
|
||||
( ! isGuest && ! cardDetails )
|
||||
) {
|
||||
try {
|
||||
const paymentComponent =
|
||||
await fastlaneSdk.FastlaneCardComponent( {} );
|
||||
// Check if the container exists before rendering
|
||||
const cardContainer =
|
||||
document.querySelector( '#fastlane-card' );
|
||||
if ( cardContainer ) {
|
||||
paymentComponent.render( '#fastlane-card' );
|
||||
onPaymentLoad( paymentComponent );
|
||||
}
|
||||
} catch ( error ) {
|
||||
log( `Error loading payment component: ${ error }`, 'error' );
|
||||
}
|
||||
}
|
||||
}, [
|
||||
isGuest,
|
||||
isEmailLookupCompleted,
|
||||
isCardElementReady,
|
||||
cardDetails,
|
||||
fastlaneSdk,
|
||||
onPaymentLoad,
|
||||
] );
|
||||
|
@ -48,19 +70,27 @@ export const Payment = ( { fastlaneSdk, onPaymentLoad } ) => {
|
|||
}
|
||||
}, [ isGuest, isEmailLookupCompleted ] );
|
||||
|
||||
// Load payment component when dependencies change
|
||||
// Load payment component when card element is ready
|
||||
useEffect( () => {
|
||||
if ( isCardElementReady ) {
|
||||
loadPaymentComponent();
|
||||
}, [ loadPaymentComponent ] );
|
||||
|
||||
// Conditional rendering based on user state:
|
||||
// 1. If authenticated: Render the Card component
|
||||
// 2. If guest with completed email lookup: Render the card fields
|
||||
// 3. If guest without completed email lookup: Render a message to enter email
|
||||
if ( isGuest ) {
|
||||
if ( isEmailLookupCompleted ) {
|
||||
return <div id="fastlane-card" key="fastlane-card" />;
|
||||
}
|
||||
}, [ isCardElementReady, loadPaymentComponent ] );
|
||||
|
||||
/**
|
||||
* Determines which component to render based on the current state.
|
||||
*
|
||||
* Rendering logic:
|
||||
* 1. For guests without completed email lookup: Show message to enter email
|
||||
* 2. For guests with completed email lookup: Render Fastlane card fields
|
||||
* 3. For authenticated users without card details: Render Fastlane card fields
|
||||
* 4. For authenticated users with card details: Render Card component
|
||||
*
|
||||
* @return {JSX.Element} The appropriate component based on the current state
|
||||
*/
|
||||
const renderPaymentComponent = () => {
|
||||
// Case 1: Guest user without completed email lookup
|
||||
if ( isGuest && ! isEmailLookupCompleted ) {
|
||||
return (
|
||||
<div id="ppcp-axo-block-radio-content">
|
||||
{ __(
|
||||
|
@ -70,5 +100,18 @@ export const Payment = ( { fastlaneSdk, onPaymentLoad } ) => {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Case 2 & 3: Guest with completed email lookup or authenticated user without card details
|
||||
if (
|
||||
( isGuest && isEmailLookupCompleted ) ||
|
||||
( ! isGuest && ! cardDetails )
|
||||
) {
|
||||
return <div id="fastlane-card" />;
|
||||
}
|
||||
|
||||
// Case 4: Authenticated user with card details
|
||||
return <Card fastlaneSdk={ fastlaneSdk } showWatermark={ ! isGuest } />;
|
||||
};
|
||||
|
||||
return renderPaymentComponent();
|
||||
};
|
||||
|
|
|
@ -16,9 +16,6 @@ import {
|
|||
*/
|
||||
const WatermarkManager = ( { fastlaneSdk } ) => {
|
||||
// Select relevant states from the AXO store
|
||||
const isGuest = useSelect( ( select ) =>
|
||||
select( STORE_NAME ).getIsGuest()
|
||||
);
|
||||
const isAxoActive = useSelect( ( select ) =>
|
||||
select( STORE_NAME ).getIsAxoActive()
|
||||
);
|
||||
|
@ -34,7 +31,6 @@ const WatermarkManager = ( { fastlaneSdk } ) => {
|
|||
isAxoActive,
|
||||
isAxoScriptLoaded,
|
||||
fastlaneSdk,
|
||||
isGuest,
|
||||
} );
|
||||
} else {
|
||||
// Remove watermark when AXO is inactive and not loading
|
||||
|
@ -43,7 +39,7 @@ const WatermarkManager = ( { fastlaneSdk } ) => {
|
|||
|
||||
// Cleanup function to remove watermark on unmount
|
||||
return removeWatermark;
|
||||
}, [ fastlaneSdk, isGuest, isAxoActive, isAxoScriptLoaded ] );
|
||||
}, [ fastlaneSdk, isAxoActive, isAxoScriptLoaded ] );
|
||||
|
||||
// This component doesn't render anything directly
|
||||
return null;
|
||||
|
|
|
@ -112,13 +112,11 @@ export const renderWatermarkContent = ( content ) => {
|
|||
* @param {boolean} params.isAxoActive - Whether AXO is active.
|
||||
* @param {boolean} params.isAxoScriptLoaded - Whether AXO script is loaded.
|
||||
* @param {Object} params.fastlaneSdk - The Fastlane SDK instance.
|
||||
* @param {boolean} params.isGuest - Whether the user is a guest.
|
||||
*/
|
||||
export const updateWatermarkContent = ( {
|
||||
isAxoActive,
|
||||
isAxoScriptLoaded,
|
||||
fastlaneSdk,
|
||||
isGuest,
|
||||
} ) => {
|
||||
if ( ! isAxoActive && ! isAxoScriptLoaded ) {
|
||||
// Show loading spinner
|
||||
|
@ -134,7 +132,7 @@ export const updateWatermarkContent = ( {
|
|||
createElement( Watermark, {
|
||||
fastlaneSdk,
|
||||
name: 'fastlane-watermark-email',
|
||||
includeAdditionalInfo: isGuest,
|
||||
includeAdditionalInfo: true,
|
||||
} )
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -18,7 +18,8 @@ import useCustomerData from './useCustomerData';
|
|||
*/
|
||||
const useAxoCleanup = () => {
|
||||
// Get dispatch functions from the AXO store
|
||||
const { setIsAxoActive, setIsGuest } = useDispatch( STORE_NAME );
|
||||
const { setIsAxoActive, setIsGuest, setIsEmailLookupCompleted } =
|
||||
useDispatch( STORE_NAME );
|
||||
|
||||
// Get functions to update WooCommerce shipping and billing addresses
|
||||
const {
|
||||
|
@ -45,6 +46,7 @@ const useAxoCleanup = () => {
|
|||
// Reset AXO state
|
||||
setIsAxoActive( false );
|
||||
setIsGuest( true );
|
||||
setIsEmailLookupCompleted( false );
|
||||
|
||||
// Remove AXO UI elements
|
||||
removeShippingChangeButton();
|
||||
|
|
|
@ -17,6 +17,7 @@ use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule;
|
|||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
/**
|
||||
* Class BlocksModule
|
||||
|
@ -69,8 +70,11 @@ class BlocksModule implements ServiceModule, ExtendingModule, ExecutableModule {
|
|||
function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void {
|
||||
$payment_method_registry->register( $c->get( 'blocks.method' ) );
|
||||
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
assert( $settings instanceof Settings );
|
||||
|
||||
// Include ACDC in the Block Checkout only in case Axo doesn't exist or is not available or the user is logged in.
|
||||
if ( ! $c->has( 'axoblock.available' ) || ! $c->get( 'axoblock.available' ) || is_user_logged_in() ) {
|
||||
if ( ( $settings->has( 'axo_enabled' ) && ! $settings->get( 'axo_enabled' ) ) || is_user_logged_in() ) {
|
||||
$payment_method_registry->register( $c->get( 'blocks.advanced-card-method' ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ return array(
|
|||
'FR',
|
||||
'DE',
|
||||
'GR',
|
||||
'HK',
|
||||
'HU',
|
||||
'IE',
|
||||
'IT',
|
||||
|
@ -57,7 +56,6 @@ return array(
|
|||
'PT',
|
||||
'RO',
|
||||
'SK',
|
||||
'SG',
|
||||
'SI',
|
||||
'ES',
|
||||
'SE',
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import { useState, useEffect } from '@wordpress/element';
|
||||
import useGooglepayApiToGenerateButton from '../hooks/useGooglepayApiToGenerateButton';
|
||||
import usePayPalScript from '../hooks/usePayPalScript';
|
||||
import useGooglepayScript from '../hooks/useGooglepayScript';
|
||||
import useGooglepayConfig from '../hooks/useGooglepayConfig';
|
||||
|
||||
const GooglepayButton = ( { namespace, buttonConfig, ppcpConfig } ) => {
|
||||
const [ buttonHtml, setButtonHtml ] = useState( '' );
|
||||
const [ buttonElement, setButtonElement ] = useState( null );
|
||||
const [ componentFrame, setComponentFrame ] = useState( null );
|
||||
const isPayPalLoaded = usePayPalScript( namespace, ppcpConfig );
|
||||
|
||||
const isGooglepayLoaded = useGooglepayScript(
|
||||
componentFrame,
|
||||
buttonConfig,
|
||||
isPayPalLoaded
|
||||
);
|
||||
|
||||
const googlepayConfig = useGooglepayConfig( namespace, isGooglepayLoaded );
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! buttonElement ) {
|
||||
return;
|
||||
}
|
||||
|
||||
setComponentFrame( buttonElement.ownerDocument );
|
||||
}, [ buttonElement ] );
|
||||
|
||||
const googlepayButton = useGooglepayApiToGenerateButton(
|
||||
componentFrame,
|
||||
namespace,
|
||||
buttonConfig,
|
||||
ppcpConfig,
|
||||
googlepayConfig
|
||||
);
|
||||
|
||||
useEffect( () => {
|
||||
if ( googlepayButton ) {
|
||||
const hideLoader =
|
||||
'<style>.block-editor-iframe__html .gpay-card-info-animated-progress-bar-container {display:none !important}</style>';
|
||||
setButtonHtml( googlepayButton.outerHTML + hideLoader );
|
||||
}
|
||||
}, [ googlepayButton ] );
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ setButtonElement }
|
||||
dangerouslySetInnerHTML={ { __html: buttonHtml } }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default GooglepayButton;
|
|
@ -0,0 +1,19 @@
|
|||
import { useMemo } from '@wordpress/element';
|
||||
import { combineStyles } from '../../../../../ppcp-button/resources/js/modules/Helper/PaymentButtonHelpers';
|
||||
|
||||
const useButtonStyles = ( buttonConfig, ppcpConfig ) => {
|
||||
return useMemo( () => {
|
||||
const styles = combineStyles(
|
||||
ppcpConfig?.button || {},
|
||||
buttonConfig?.button || {}
|
||||
);
|
||||
|
||||
if ( styles.MiniCart && styles.MiniCart.type === 'buy' ) {
|
||||
styles.MiniCart.type = 'pay';
|
||||
}
|
||||
|
||||
return styles;
|
||||
}, [ buttonConfig, ppcpConfig ] );
|
||||
};
|
||||
|
||||
export default useButtonStyles;
|
|
@ -0,0 +1,57 @@
|
|||
import { useEffect, useState } from '@wordpress/element';
|
||||
import useButtonStyles from './useButtonStyles';
|
||||
|
||||
const useGooglepayApiToGenerateButton = (
|
||||
componentDocument,
|
||||
namespace,
|
||||
buttonConfig,
|
||||
ppcpConfig,
|
||||
googlepayConfig
|
||||
) => {
|
||||
const [ googlepayButton, setGooglepayButton ] = useState( null );
|
||||
const buttonStyles = useButtonStyles( buttonConfig, ppcpConfig );
|
||||
|
||||
useEffect( () => {
|
||||
if (
|
||||
! componentDocument?.defaultView ||
|
||||
! buttonConfig ||
|
||||
! googlepayConfig
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const api = componentDocument.defaultView.google?.payments?.api;
|
||||
if ( ! api ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const paymentsClient = new api.PaymentsClient( {
|
||||
environment: 'TEST',
|
||||
} );
|
||||
|
||||
const googlePayButtonOptions = {
|
||||
allowedPaymentMethods: googlepayConfig.allowedPaymentMethods,
|
||||
buttonColor: buttonConfig.buttonColor || 'black',
|
||||
buttonType: buttonConfig.buttonType || 'pay',
|
||||
buttonLocale: buttonConfig.buttonLocale || 'en',
|
||||
buttonSizeMode: 'fill',
|
||||
};
|
||||
|
||||
const button = paymentsClient.createButton( {
|
||||
...googlePayButtonOptions,
|
||||
onClick: ( event ) => {
|
||||
event.preventDefault();
|
||||
},
|
||||
} );
|
||||
|
||||
setGooglepayButton( button );
|
||||
|
||||
return () => {
|
||||
setGooglepayButton( null );
|
||||
};
|
||||
}, [ namespace, buttonConfig, ppcpConfig, googlepayConfig, buttonStyles ] );
|
||||
|
||||
return googlepayButton;
|
||||
};
|
||||
|
||||
export default useGooglepayApiToGenerateButton;
|
|
@ -0,0 +1,26 @@
|
|||
import { useState, useEffect } from '@wordpress/element';
|
||||
|
||||
const useGooglepayConfig = ( namespace, isGooglepayLoaded ) => {
|
||||
const [ googlePayConfig, setGooglePayConfig ] = useState( null );
|
||||
|
||||
useEffect( () => {
|
||||
const fetchConfig = async () => {
|
||||
if ( ! isGooglepayLoaded ) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const config = await window[ namespace ].Googlepay().config();
|
||||
setGooglePayConfig( config );
|
||||
} catch ( error ) {
|
||||
console.error( 'Failed to fetch Google Pay config:', error );
|
||||
}
|
||||
};
|
||||
|
||||
fetchConfig();
|
||||
}, [ namespace, isGooglepayLoaded ] );
|
||||
|
||||
return googlePayConfig;
|
||||
};
|
||||
|
||||
export default useGooglepayConfig;
|
|
@ -0,0 +1,65 @@
|
|||
import { useState, useEffect } from '@wordpress/element';
|
||||
import { loadCustomScript } from '@paypal/paypal-js';
|
||||
|
||||
const useGooglepayScript = (
|
||||
componentDocument,
|
||||
buttonConfig,
|
||||
isPayPalLoaded
|
||||
) => {
|
||||
const [ isGooglepayLoaded, setIsGooglepayLoaded ] = useState( false );
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! componentDocument ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const injectScriptToFrame = ( scriptSrc ) => {
|
||||
if ( document === componentDocument ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const script = document.querySelector(
|
||||
`script[src^="${ scriptSrc }"]`
|
||||
);
|
||||
|
||||
if ( script ) {
|
||||
const newScript = componentDocument.createElement( 'script' );
|
||||
newScript.src = script.src;
|
||||
newScript.async = script.async;
|
||||
newScript.type = script.type;
|
||||
|
||||
componentDocument.head.appendChild( newScript );
|
||||
} else {
|
||||
console.error( 'Script not found in the document:', scriptSrc );
|
||||
}
|
||||
};
|
||||
|
||||
const loadGooglepayScript = async () => {
|
||||
if ( ! isPayPalLoaded ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! buttonConfig || ! buttonConfig.sdk_url ) {
|
||||
console.error( 'Invalid buttonConfig or missing sdk_url' );
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await loadCustomScript( { url: buttonConfig.sdk_url } ).then(
|
||||
() => {
|
||||
injectScriptToFrame( buttonConfig.sdk_url );
|
||||
}
|
||||
);
|
||||
setIsGooglepayLoaded( true );
|
||||
} catch ( error ) {
|
||||
console.error( 'Failed to load Googlepay script:', error );
|
||||
}
|
||||
};
|
||||
|
||||
loadGooglepayScript();
|
||||
}, [ componentDocument, buttonConfig, isPayPalLoaded ] );
|
||||
|
||||
return isGooglepayLoaded;
|
||||
};
|
||||
|
||||
export default useGooglepayScript;
|
|
@ -0,0 +1,25 @@
|
|||
import { useState, useEffect } from '@wordpress/element';
|
||||
import { loadPayPalScript } from '../../../../../ppcp-button/resources/js/modules/Helper/PayPalScriptLoading';
|
||||
|
||||
const usePayPalScript = ( namespace, ppcpConfig ) => {
|
||||
const [ isPayPalLoaded, setIsPayPalLoaded ] = useState( false );
|
||||
|
||||
ppcpConfig.url_params.components += ',googlepay';
|
||||
|
||||
useEffect( () => {
|
||||
const loadScript = async () => {
|
||||
try {
|
||||
await loadPayPalScript( namespace, ppcpConfig );
|
||||
setIsPayPalLoaded( true );
|
||||
} catch ( error ) {
|
||||
console.error( `Error loading PayPal script: ${ error }` );
|
||||
}
|
||||
};
|
||||
|
||||
loadScript();
|
||||
}, [ namespace, ppcpConfig ] );
|
||||
|
||||
return isPayPalLoaded;
|
||||
};
|
||||
|
||||
export default usePayPalScript;
|
|
@ -1,62 +1,15 @@
|
|||
import GooglepayButton from './GooglepayButton';
|
||||
import ContextHandlerFactory from './Context/ContextHandlerFactory';
|
||||
import GooglepayButton from './Block/components/GooglepayButton';
|
||||
|
||||
class GooglepayManagerBlockEditor {
|
||||
constructor( namespace, buttonConfig, ppcpConfig ) {
|
||||
this.namespace = namespace;
|
||||
this.buttonConfig = buttonConfig;
|
||||
this.ppcpConfig = ppcpConfig;
|
||||
this.googlePayConfig = null;
|
||||
this.transactionInfo = null;
|
||||
this.contextHandler = null;
|
||||
}
|
||||
|
||||
init() {
|
||||
( async () => {
|
||||
await this.config();
|
||||
} )();
|
||||
}
|
||||
|
||||
async config() {
|
||||
try {
|
||||
// Gets GooglePay configuration of the PayPal merchant.
|
||||
this.googlePayConfig = await window[ this.namespace ]
|
||||
.Googlepay()
|
||||
.config();
|
||||
|
||||
// Fetch transaction information.
|
||||
this.transactionInfo = await this.fetchTransactionInfo();
|
||||
|
||||
const button = new GooglepayButton(
|
||||
this.ppcpConfig.context,
|
||||
null,
|
||||
this.buttonConfig,
|
||||
this.ppcpConfig,
|
||||
this.contextHandler
|
||||
const GooglepayManagerBlockEditor = ( {
|
||||
namespace,
|
||||
buttonConfig,
|
||||
ppcpConfig,
|
||||
} ) => (
|
||||
<GooglepayButton
|
||||
namespace={ namespace }
|
||||
buttonConfig={ buttonConfig }
|
||||
ppcpConfig={ ppcpConfig }
|
||||
/>
|
||||
);
|
||||
|
||||
button.init( this.googlePayConfig, this.transactionInfo );
|
||||
} catch ( error ) {
|
||||
console.error( 'Failed to initialize Google Pay:', error );
|
||||
}
|
||||
}
|
||||
|
||||
async fetchTransactionInfo() {
|
||||
try {
|
||||
if ( ! this.contextHandler ) {
|
||||
this.contextHandler = ContextHandlerFactory.create(
|
||||
this.ppcpConfig.context,
|
||||
this.buttonConfig,
|
||||
this.ppcpConfig,
|
||||
null
|
||||
);
|
||||
}
|
||||
return null;
|
||||
} catch ( error ) {
|
||||
console.error( 'Error fetching transaction info:', error );
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default GooglepayManagerBlockEditor;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { useEffect, useState } from '@wordpress/element';
|
||||
import { loadCustomScript } from '@paypal/paypal-js';
|
||||
import {
|
||||
registerExpressPaymentMethod,
|
||||
registerPaymentMethod,
|
||||
|
@ -6,7 +7,6 @@ import {
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { loadPayPalScript } from '../../../ppcp-button/resources/js/modules/Helper/PayPalScriptLoading';
|
||||
import GooglepayManager from './GooglepayManager';
|
||||
import { loadCustomScript } from '@paypal/paypal-js';
|
||||
import GooglepayManagerBlockEditor from './GooglepayManagerBlockEditor';
|
||||
|
||||
const ppcpData = wc.wcSettings.getSetting( 'ppcp-gateway_data' );
|
||||
|
@ -20,21 +20,19 @@ if ( typeof window.PayPalCommerceGateway === 'undefined' ) {
|
|||
window.PayPalCommerceGateway = ppcpConfig;
|
||||
}
|
||||
|
||||
const GooglePayComponent = ( props ) => {
|
||||
const [ bootstrapped, setBootstrapped ] = useState( false );
|
||||
const GooglePayComponent = ( { isEditing } ) => {
|
||||
const [ paypalLoaded, setPaypalLoaded ] = useState( false );
|
||||
const [ googlePayLoaded, setGooglePayLoaded ] = useState( false );
|
||||
const [ manager, setManager ] = useState( null );
|
||||
|
||||
useEffect( () => {
|
||||
// Load GooglePay SDK
|
||||
if ( ! isEditing ) {
|
||||
loadCustomScript( { url: buttonConfig.sdk_url } ).then( () => {
|
||||
setGooglePayLoaded( true );
|
||||
} );
|
||||
|
||||
ppcpConfig.url_params.components += ',googlepay';
|
||||
|
||||
// Load PayPal
|
||||
loadPayPalScript( namespace, ppcpConfig )
|
||||
.then( () => {
|
||||
setPaypalLoaded( true );
|
||||
|
@ -42,34 +40,35 @@ const GooglePayComponent = ( props ) => {
|
|||
.catch( ( error ) => {
|
||||
console.error( 'Failed to load PayPal script: ', error );
|
||||
} );
|
||||
}, [] );
|
||||
}
|
||||
}, [ isEditing, buttonConfig, ppcpConfig ] );
|
||||
|
||||
useEffect( () => {
|
||||
if ( paypalLoaded && googlePayLoaded && ! manager ) {
|
||||
const ManagerClass = props.isEditing
|
||||
? GooglepayManagerBlockEditor
|
||||
: GooglepayManager;
|
||||
const newManager = new ManagerClass(
|
||||
if ( ! isEditing && paypalLoaded && googlePayLoaded && ! manager ) {
|
||||
const newManager = new GooglepayManager(
|
||||
namespace,
|
||||
buttonConfig,
|
||||
ppcpConfig
|
||||
);
|
||||
setManager( newManager );
|
||||
}
|
||||
}, [ paypalLoaded, googlePayLoaded, props.isEditing ] );
|
||||
}, [ paypalLoaded, googlePayLoaded, isEditing, manager ] );
|
||||
|
||||
useEffect( () => {
|
||||
if ( manager && ! bootstrapped ) {
|
||||
setBootstrapped( true );
|
||||
manager.init();
|
||||
if ( isEditing ) {
|
||||
return (
|
||||
<GooglepayManagerBlockEditor
|
||||
namespace={ namespace }
|
||||
buttonConfig={ buttonConfig }
|
||||
ppcpConfig={ ppcpConfig }
|
||||
/>
|
||||
);
|
||||
}
|
||||
}, [ manager, bootstrapped ] );
|
||||
|
||||
return (
|
||||
<div
|
||||
id={ buttonConfig.button.wrapper.replace( '#', '' ) }
|
||||
className="ppcp-button-apm ppcp-button-googlepay"
|
||||
></div>
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -106,7 +106,6 @@ return array(
|
|||
'FR', // France
|
||||
'DE', // Germany
|
||||
'GR', // Greece
|
||||
'HK', // Hong Kong
|
||||
'HU', // Hungary
|
||||
'IE', // Ireland
|
||||
'IT', // Italy
|
||||
|
@ -120,7 +119,6 @@ return array(
|
|||
'PL', // Poland
|
||||
'PT', // Portugal
|
||||
'RO', // Romania
|
||||
'SG', // Singapore
|
||||
'SK', // Slovakia
|
||||
'SI', // Slovenia
|
||||
'ES', // Spain
|
||||
|
|
|
@ -72,7 +72,6 @@ return array(
|
|||
'FR' => $default_currencies,
|
||||
'DE' => $default_currencies,
|
||||
'GR' => $default_currencies,
|
||||
'HK' => $default_currencies,
|
||||
'HU' => $default_currencies,
|
||||
'IE' => $default_currencies,
|
||||
'IT' => $default_currencies,
|
||||
|
@ -87,7 +86,6 @@ return array(
|
|||
'PT' => $default_currencies,
|
||||
'RO' => $default_currencies,
|
||||
'SK' => $default_currencies,
|
||||
'SG' => $default_currencies,
|
||||
'SI' => $default_currencies,
|
||||
'ES' => $default_currencies,
|
||||
'SE' => $default_currencies,
|
||||
|
|
16
modules/ppcp-settings/composer.json
Normal file
16
modules/ppcp-settings/composer.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "woocommerce/ppcp-settings",
|
||||
"type": "inpsyde-module",
|
||||
"description": "Settings module",
|
||||
"license": "GPL-2.0",
|
||||
"require": {
|
||||
"php": "^7.4 | ^8.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WooCommerce\\PayPalCommerce\\Settings\\": "src"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
14
modules/ppcp-settings/module.php
Normal file
14
modules/ppcp-settings/module.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* The Settings module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Settings
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Settings;
|
||||
|
||||
return static function () : SettingsModule {
|
||||
return new SettingsModule();
|
||||
};
|
12
modules/ppcp-settings/package.json
Normal file
12
modules/ppcp-settings/package.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "ppcp-settings",
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"watch": "wp-scripts start --webpack-src-dir=resources/js --output-path=assets",
|
||||
"build": "wp-scripts build --webpack-src-dir=resources/js --output-path=assets"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@wordpress/scripts": "^30.3.0"
|
||||
}
|
||||
}
|
1
modules/ppcp-settings/resources/css/style.scss
Normal file
1
modules/ppcp-settings/resources/css/style.scss
Normal file
|
@ -0,0 +1 @@
|
|||
.red {color:red;}
|
3
modules/ppcp-settings/resources/js/App.js
Normal file
3
modules/ppcp-settings/resources/js/App.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function App() {
|
||||
return <div className="red">App</div>;
|
||||
}
|
7
modules/ppcp-settings/resources/js/index.js
Normal file
7
modules/ppcp-settings/resources/js/index.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { App } from './App';
|
||||
|
||||
createRoot( document.getElementById( 'ppcp-settings-container' ) ).render(
|
||||
<App />
|
||||
);
|
26
modules/ppcp-settings/services.php
Normal file
26
modules/ppcp-settings/services.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* The Settings module services.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Settings
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Settings;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array(
|
||||
'settings.url' => static function ( ContainerInterface $container ) : string {
|
||||
/**
|
||||
* The path cannot be false.
|
||||
*
|
||||
* @psalm-suppress PossiblyFalseArgument
|
||||
*/
|
||||
return plugins_url(
|
||||
'/modules/ppcp-settings/',
|
||||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
);
|
95
modules/ppcp-settings/src/SettingsModule.php
Normal file
95
modules/ppcp-settings/src/SettingsModule.php
Normal file
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
/**
|
||||
* The Settings module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\AxoBlock
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace WooCommerce\PayPalCommerce\Settings;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
/**
|
||||
* Class SettingsModule
|
||||
*/
|
||||
class SettingsModule implements ServiceModule, ExecutableModule {
|
||||
use ModuleClassNameIdTrait;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function services(): array {
|
||||
return require __DIR__ . '/../services.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function run( ContainerInterface $container ): bool {
|
||||
add_action(
|
||||
'admin_enqueue_scripts',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
static function( $hook_suffix ) use ( $container ) {
|
||||
if ( 'woocommerce_page_wc-settings' !== $hook_suffix ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Require resolves.
|
||||
*
|
||||
* @psalm-suppress UnresolvableInclude
|
||||
*/
|
||||
$script_asset_file = require dirname( realpath( __FILE__ ) ?: '', 2 ) . '/assets/index.asset.php';
|
||||
|
||||
$module_url = $container->get( 'settings.url' );
|
||||
|
||||
wp_register_script(
|
||||
'ppcp-admin-settings',
|
||||
$module_url . '/assets/index.js',
|
||||
$script_asset_file['dependencies'],
|
||||
$script_asset_file['version'],
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script( 'ppcp-admin-settings' );
|
||||
|
||||
/**
|
||||
* Require resolves.
|
||||
*
|
||||
* @psalm-suppress UnresolvableInclude
|
||||
*/
|
||||
$style_asset_file = require dirname( realpath( __FILE__ ) ?: '', 2 ) . '/assets/style.asset.php';
|
||||
|
||||
wp_register_style(
|
||||
'ppcp-admin-settings',
|
||||
$module_url . '/assets/style-style.css',
|
||||
$style_asset_file['dependencies'],
|
||||
$style_asset_file['version']
|
||||
);
|
||||
|
||||
wp_enqueue_style( 'ppcp-admin-settings' );
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_gateway_admin_options_wrapper',
|
||||
static function(): void {
|
||||
global $hide_save_button;
|
||||
$hide_save_button = true;
|
||||
|
||||
echo '<div id="ppcp-settings-container"></div>';
|
||||
}
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
12
modules/ppcp-settings/webpack.config.js
Normal file
12
modules/ppcp-settings/webpack.config.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
|
||||
const path = require( 'path' );
|
||||
|
||||
module.exports = {
|
||||
...defaultConfig,
|
||||
...{
|
||||
entry: {
|
||||
index: path.resolve( process.cwd(), 'resources/js', 'index.js' ),
|
||||
style: path.resolve( process.cwd(), 'resources/css', 'style.scss' ),
|
||||
},
|
||||
},
|
||||
};
|
10453
modules/ppcp-settings/yarn.lock
Normal file
10453
modules/ppcp-settings/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
|
@ -118,7 +118,8 @@ return array(
|
|||
$container->get( 'wcgateway.place-order-button-text' ),
|
||||
$container->get( 'api.endpoint.payment-tokens' ),
|
||||
$container->get( 'vaulting.vault-v3-enabled' ),
|
||||
$container->get( 'vaulting.wc-payment-tokens' )
|
||||
$container->get( 'vaulting.wc-payment-tokens' ),
|
||||
$container->get( 'wcgateway.settings.admin-settings-enabled' )
|
||||
);
|
||||
},
|
||||
'wcgateway.credit-card-gateway' => static function ( ContainerInterface $container ): CreditCardGateway {
|
||||
|
@ -1914,4 +1915,8 @@ return array(
|
|||
|
||||
return $simple_redirect_tasks;
|
||||
},
|
||||
|
||||
'wcgateway.settings.admin-settings-enabled' => static function( ContainerInterface $container ): bool {
|
||||
return $container->has( 'settings.url' );
|
||||
},
|
||||
);
|
||||
|
|
|
@ -202,6 +202,13 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
*/
|
||||
private $wc_payment_tokens;
|
||||
|
||||
/**
|
||||
* Whether settings module is enabled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $admin_settings_enabled;
|
||||
|
||||
/**
|
||||
* PayPalGateway constructor.
|
||||
*
|
||||
|
@ -225,6 +232,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
* @param PaymentTokensEndpoint $payment_tokens_endpoint Payment tokens endpoint.
|
||||
* @param bool $vault_v3_enabled Whether Vault v3 module is enabled.
|
||||
* @param WooCommercePaymentTokens $wc_payment_tokens WooCommerce payment tokens.
|
||||
* @param bool $admin_settings_enabled Whether settings module is enabled.
|
||||
*/
|
||||
public function __construct(
|
||||
SettingsRenderer $settings_renderer,
|
||||
|
@ -246,7 +254,8 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
string $place_order_button_text,
|
||||
PaymentTokensEndpoint $payment_tokens_endpoint,
|
||||
bool $vault_v3_enabled,
|
||||
WooCommercePaymentTokens $wc_payment_tokens
|
||||
WooCommercePaymentTokens $wc_payment_tokens,
|
||||
bool $admin_settings_enabled
|
||||
) {
|
||||
$this->id = self::ID;
|
||||
$this->settings_renderer = $settings_renderer;
|
||||
|
@ -270,6 +279,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
$this->payment_tokens_endpoint = $payment_tokens_endpoint;
|
||||
$this->vault_v3_enabled = $vault_v3_enabled;
|
||||
$this->wc_payment_tokens = $wc_payment_tokens;
|
||||
$this->admin_settings_enabled = $admin_settings_enabled;
|
||||
|
||||
$default_support = array(
|
||||
'products',
|
||||
|
@ -745,6 +755,17 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the parent admin_options method.
|
||||
*/
|
||||
public function admin_options() {
|
||||
if ( ! $this->admin_settings_enabled ) {
|
||||
parent::admin_options();
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_paypal_payments_gateway_admin_options_wrapper', $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the settings renderer.
|
||||
*
|
||||
|
|
2
package-lock.json
generated
2
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "woocommerce-paypal-payments",
|
||||
"version": "2.9.2",
|
||||
"version": "2.9.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "woocommerce-paypal-payments",
|
||||
"version": "2.9.2",
|
||||
"version": "2.9.3",
|
||||
"description": "WooCommerce PayPal Payments",
|
||||
"repository": "https://github.com/woocommerce/woocommerce-paypal-payments",
|
||||
"license": "GPL-2.0",
|
||||
|
@ -26,6 +26,7 @@
|
|||
"install:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn install",
|
||||
"install:modules:ppcp-card-fields": "cd modules/ppcp-card-fields && yarn install",
|
||||
"install:modules:ppcp-compat": "cd modules/ppcp-compat && yarn install",
|
||||
"install:modules:ppcp-settings": "cd modules/ppcp-settings && yarn install",
|
||||
"install:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn install",
|
||||
"build:modules:ppcp-admin-notices": "cd modules/ppcp-admin-notices && yarn run build",
|
||||
"build:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run build",
|
||||
|
@ -47,6 +48,7 @@
|
|||
"build:modules:ppcp-card-fields": "cd modules/ppcp-card-fields && yarn run build",
|
||||
"build:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run build",
|
||||
"build:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run build",
|
||||
"build:modules:ppcp-settings": "cd modules/ppcp-settings && yarn run build",
|
||||
"build:modules": "run-p build:modules:*",
|
||||
"watch:modules:ppcp-admin-notices": "cd modules/ppcp-admin-notices && yarn run watch",
|
||||
"watch:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run watch",
|
||||
|
@ -68,6 +70,7 @@
|
|||
"watch:modules:ppcp-card-fields": "cd modules/ppcp-card-fields && yarn run watch",
|
||||
"watch:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run watch",
|
||||
"watch:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run watch",
|
||||
"watch:modules:ppcp-settings": "cd modules/ppcp-settings && yarn run watch",
|
||||
"watch:modules": "run-p watch:modules:*",
|
||||
"ddev:setup": "ddev start && ddev orchestrate",
|
||||
"ddev:start": "ddev start",
|
||||
|
|
27
readme.txt
27
readme.txt
|
@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, credit card
|
|||
Requires at least: 6.3
|
||||
Tested up to: 6.6
|
||||
Requires PHP: 7.4
|
||||
Stable tag: 2.9.2
|
||||
Stable tag: 2.9.3
|
||||
License: GPLv2
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
|
@ -179,6 +179,31 @@ If you encounter issues with the PayPal buttons not appearing after an update, p
|
|||
|
||||
== Changelog ==
|
||||
|
||||
= 2.9.3 - 2024-10-15 =
|
||||
* Fix - Multi-currency support #2667
|
||||
* Fix - "0.00" amount in Google Pay for virtual products #2636
|
||||
* Fix - Unsuccessfully payment from product page with Apple Pay button #2643
|
||||
* Fix - Button Unlinking PayPal Subscriptions plan does not showing for simple subscription #2618
|
||||
* Fix - Declare tokenization for ACDC only when vaulting enabled #2581
|
||||
* Fix - Classic shortcode block type checks #2608
|
||||
* Fix - PUI error in editor #2580
|
||||
* Fix - Add a new namespaced script loader for ApplePay #2682 #2675
|
||||
* Fix - Axo Block: Fix the Fastlane modal info message text overflow issue #2663
|
||||
* Fix - Add Custom Placeholder Handling when rendering the card fields #2651
|
||||
* Fix - Use the PayPal icons instead of WC ones #2639
|
||||
* Fix - Google Pay preview config and style #2661
|
||||
* Fix - Improve context detection #2631
|
||||
* Fix - Check that get_the_ID is valid before using #2573
|
||||
* Fix - Axo Block: Always display the Fastlane watermark in the includeAdditionalInfo mode #2690
|
||||
* Fix - Axo Block: Display card fields for authenticated cardless profiles #2672
|
||||
* Fix - Google Pay: Fix button preview in the editor #2688
|
||||
* Fix - ACDC gateway not visible on the block Checkout for logged-out users #2693
|
||||
* Enhancement - Enhancement - Add Fastlane support for Checkout block
|
||||
* Enhancement - Multiple calls to POST /v1/oauth2/token?grant_type=client_credentials&response_type=id_token #2671
|
||||
* Enhancement - Fastlane update shipping options & taxes when changing address #2665
|
||||
* Enhancement - Axo: Remove Axo from the Checkout block in the editor and add an ACDC card preview #2662
|
||||
* Enhancement - Set email when creating order for express payment #2577
|
||||
|
||||
= 2.9.2 - 2024-10-01 =
|
||||
* Enhancement - Add Fastlane support for Classic Checkout
|
||||
* Fix - Fatal error when Pay Later messaging configurator was disabled with a code snippet
|
||||
|
|
|
@ -1,156 +0,0 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
|
||||
|
||||
use Mockery;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Requests_Utility_CaseInsensitiveDictionary;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Token;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\OrderFactory;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNet;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice\PaymentSource;
|
||||
use function Brain\Monkey\Functions\expect;
|
||||
use function Brain\Monkey\Functions\when;
|
||||
|
||||
class PayUponInvoiceOrderEndpointTest extends TestCase
|
||||
{
|
||||
private $bearer;
|
||||
private $orderFactory;
|
||||
private $fraudnet;
|
||||
private $logger;
|
||||
private $testee;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->bearer = Mockery::mock(Bearer::class);
|
||||
$token = Mockery::mock(Token::class);
|
||||
$token->shouldReceive('token')->andReturn('');
|
||||
$this->bearer->shouldReceive('bearer')->andReturn($token);
|
||||
|
||||
$this->orderFactory = Mockery::mock(OrderFactory::class);
|
||||
$this->fraudnet = Mockery::mock(FraudNet::class);
|
||||
$this->logger = Mockery::mock(LoggerInterface::class);
|
||||
|
||||
$this->testee = new PayUponInvoiceOrderEndpoint(
|
||||
'',
|
||||
$this->bearer,
|
||||
$this->orderFactory,
|
||||
$this->fraudnet,
|
||||
$this->logger
|
||||
);
|
||||
}
|
||||
|
||||
public function testCreateOrder()
|
||||
{
|
||||
$this->markTestSkipped('must be revisited.');
|
||||
list($items, $paymentSource, $headers) = $this->setStubs();
|
||||
|
||||
$response = [
|
||||
'body' => '{"is_correct":true}',
|
||||
'headers' => $headers,
|
||||
];
|
||||
expect('wp_remote_get')->andReturn($response);
|
||||
expect('wp_remote_retrieve_response_code')->with($response)->andReturn(200);
|
||||
|
||||
$this->logger->shouldReceive('debug');
|
||||
|
||||
$wc_order = Mockery::mock(WC_Order::class);
|
||||
|
||||
|
||||
$result = $this->testee->create($items, $paymentSource, $wc_order );
|
||||
$this->assertInstanceOf(Order::class, $result);
|
||||
}
|
||||
|
||||
public function testCreateOrderWpError()
|
||||
{
|
||||
$this->markTestSkipped('must be revisited.');
|
||||
list($items, $paymentSource) = $this->setStubsForError();
|
||||
|
||||
$wpError = Mockery::mock(\WP_Error::class);
|
||||
$wpError->shouldReceive('get_error_messages')->andReturn(['foo']);
|
||||
$wpError->shouldReceive('get_error_message')->andReturn('foo');
|
||||
expect('wp_remote_get')->andReturn($wpError);
|
||||
|
||||
$this->logger->shouldReceive('debug');
|
||||
$wc_order = Mockery::mock(WC_Order::class);
|
||||
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->testee->create($items, $paymentSource, $wc_order);
|
||||
}
|
||||
|
||||
public function testCreateOrderApiError()
|
||||
{
|
||||
$this->markTestSkipped('must be revisited.');
|
||||
list($items, $paymentSource) = $this->setStubsForError();
|
||||
|
||||
$headers = Mockery::mock(Requests_Utility_CaseInsensitiveDictionary::class);
|
||||
$headers->shouldReceive('getAll');
|
||||
$response = [
|
||||
'body' => '{"is_correct":true}',
|
||||
'headers' => $headers,
|
||||
];
|
||||
|
||||
when('get_bloginfo')->justReturn('de-DE');
|
||||
expect('wp_remote_get')->andReturn($response);
|
||||
expect('wp_remote_retrieve_response_code')->with($response)->andReturn(500);
|
||||
|
||||
$this->logger->shouldReceive('debug');
|
||||
|
||||
$wc_order = Mockery::mock(WC_Order::class);
|
||||
$this->expectException(PayPalApiException::class);
|
||||
$this->testee->create($items, $paymentSource, $wc_order);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function setStubs(): array
|
||||
{
|
||||
$order = Mockery::mock(Order::class);
|
||||
$this->orderFactory
|
||||
->expects('from_paypal_response')
|
||||
->andReturnUsing(function (\stdClass $object) use ($order): ?Order {
|
||||
return ($object->is_correct) ? $order : null;
|
||||
});
|
||||
|
||||
$this->fraudnet->shouldReceive('session_id')->andReturn('');
|
||||
|
||||
$purchaseUnit = Mockery::mock(PurchaseUnit::class);
|
||||
$purchaseUnit->shouldReceive('to_array')->andReturn([
|
||||
'items' => [],
|
||||
]);
|
||||
$items = [$purchaseUnit];
|
||||
|
||||
$paymentSource = Mockery::mock(PaymentSource::class);
|
||||
$paymentSource->shouldReceive('to_array')->andReturn([]);
|
||||
|
||||
$headers = Mockery::mock(Requests_Utility_CaseInsensitiveDictionary::class);
|
||||
$headers->shouldReceive('getAll');
|
||||
return array($items, $paymentSource, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function setStubsForError(): array
|
||||
{
|
||||
$this->fraudnet->shouldReceive('session_id')->andReturn('');
|
||||
$purchaseUnit = Mockery::mock(PurchaseUnit::class);
|
||||
$purchaseUnit->shouldReceive('to_array')->andReturn([
|
||||
'items' => [],
|
||||
]);
|
||||
$items = [$purchaseUnit];
|
||||
$paymentSource = Mockery::mock(PaymentSource::class);
|
||||
$paymentSource->shouldReceive('to_array')->andReturn([]);
|
||||
return array($items, $paymentSource);
|
||||
}
|
||||
}
|
|
@ -123,7 +123,8 @@ class WcGatewayTest extends TestCase
|
|||
'Pay via PayPal',
|
||||
$this->paymentTokensEndpoint,
|
||||
$this->vaultV3Enabled,
|
||||
$this->wcPaymentTokens
|
||||
$this->wcPaymentTokens,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* 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.9.2
|
||||
* Version: 2.9.3
|
||||
* Author: WooCommerce
|
||||
* Author URI: https://woocommerce.com/
|
||||
* License: GPL-2.0
|
||||
|
@ -26,7 +26,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', '2024-09-30' );
|
||||
define( 'PAYPAL_INTEGRATION_DATE', '2024-10-11' );
|
||||
define( 'PPCP_PAYPAL_BN_CODE', 'Woo_PPCP' );
|
||||
|
||||
! defined( 'CONNECT_WOO_CLIENT_ID' ) && define( 'CONNECT_WOO_CLIENT_ID', 'AcCAsWta_JTL__OfpjspNyH7c1GGHH332fLwonA5CwX4Y10mhybRZmHLA0GdRbwKwjQIhpDQy0pluX_P' );
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue