mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-04 08:47:23 +08:00
Merge pull request #2688 from woocommerce/PCP-3374-google-pay-button-not-displayed-in-the-word-press-editor-v2
Google Pay: Fix button preview in the editor (3374)
This commit is contained in:
commit
469d42f6bb
8 changed files with 287 additions and 90 deletions
|
@ -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
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
const GooglepayManagerBlockEditor = ( {
|
||||
namespace,
|
||||
buttonConfig,
|
||||
ppcpConfig,
|
||||
} ) => (
|
||||
<GooglepayButton
|
||||
namespace={ namespace }
|
||||
buttonConfig={ buttonConfig }
|
||||
ppcpConfig={ ppcpConfig }
|
||||
/>
|
||||
);
|
||||
|
||||
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,56 +20,55 @@ 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
|
||||
loadCustomScript( { url: buttonConfig.sdk_url } ).then( () => {
|
||||
setGooglePayLoaded( true );
|
||||
} );
|
||||
|
||||
ppcpConfig.url_params.components += ',googlepay';
|
||||
|
||||
// Load PayPal
|
||||
loadPayPalScript( namespace, ppcpConfig )
|
||||
.then( () => {
|
||||
setPaypalLoaded( true );
|
||||
} )
|
||||
.catch( ( error ) => {
|
||||
console.error( 'Failed to load PayPal script: ', error );
|
||||
if ( ! isEditing ) {
|
||||
loadCustomScript( { url: buttonConfig.sdk_url } ).then( () => {
|
||||
setGooglePayLoaded( true );
|
||||
} );
|
||||
}, [] );
|
||||
|
||||
ppcpConfig.url_params.components += ',googlepay';
|
||||
|
||||
loadPayPalScript( namespace, ppcpConfig )
|
||||
.then( () => {
|
||||
setPaypalLoaded( true );
|
||||
} )
|
||||
.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();
|
||||
}
|
||||
}, [ manager, bootstrapped ] );
|
||||
if ( isEditing ) {
|
||||
return (
|
||||
<GooglepayManagerBlockEditor
|
||||
namespace={ namespace }
|
||||
buttonConfig={ buttonConfig }
|
||||
ppcpConfig={ ppcpConfig }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
id={ buttonConfig.button.wrapper.replace( '#', '' ) }
|
||||
className="ppcp-button-apm ppcp-button-googlepay"
|
||||
></div>
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue