Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checkout: Fetch PayPal configuration directly in calypso #97487

Merged
merged 3 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions client/my-sites/checkout/src/payment-methods/paypal-js.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PayPalProvider } from '@automattic/calypso-paypal';
import { PayPalConfigurationApiResponse, PayPalProvider } from '@automattic/calypso-paypal';
import {
useTogglePaymentMethod,
type PaymentMethod,
Expand All @@ -14,11 +14,20 @@ import {
import debugFactory from 'debug';
import { useTranslate } from 'i18n-calypso';
import { useEffect, useState } from 'react';
import wp from 'calypso/lib/wp';
import useCartKey from 'calypso/my-sites/checkout/use-cart-key';
import { PaymentMethodLogos } from '../components/payment-method-logos';
import { convertErrorToString, logStashEvent } from '../lib/analytics';

const debug = debugFactory( 'calypso:paypal-js' );

async function fetchPayPalConfiguration(): Promise< PayPalConfigurationApiResponse > {
return await wp.req.get( {
path: `/me/paypal-configuration`,
method: 'GET',
} );
}

export function createPayPal(): PaymentMethod {
return {
id: 'paypal-js',
Expand Down Expand Up @@ -66,12 +75,20 @@ function PayPalSubmitButtonWrapper( {
const cartKey = useCartKey();
const { responseCart } = useShoppingCart( cartKey );
return (
<PayPalProvider currency={ responseCart.currency }>
<PayPalProvider
currency={ responseCart.currency }
fetchPayPalConfiguration={ fetchPayPalConfiguration }
handleError={ handlePayPalConfigurationError }
>
<PayPalSubmitButton disabled={ disabled } onClick={ onClick } />
</PayPalProvider>
);
}

function handlePayPalConfigurationError( error: Error ) {
logStashEvent( convertErrorToString( error ), { tags: [ 'paypal-configuration' ] }, 'error' );
}

function PayPalSubmitButton( {
disabled,
onClick,
Expand Down
49 changes: 38 additions & 11 deletions packages/calypso-paypal/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { PayPalScriptProvider, ReactPayPalScriptOptions } from '@paypal/react-paypal-js';
import { useI18n } from '@wordpress/react-i18n';
import { useEffect, useState, createContext, PropsWithChildren, useContext } from 'react';
import { useEffect, useState, createContext, PropsWithChildren, useContext, useRef } from 'react';
import wpcomRequest from 'wpcom-proxy-request';

interface PayPalConfigurationApiResponse {
export interface PayPalConfigurationApiResponse {
client_id: string | undefined;
}

Expand All @@ -15,7 +15,7 @@ export interface UsePayPalConfiguration {
payPalConfiguration: PayPalConfiguration | undefined;
}

async function fetchPayPalConfiguration(): Promise< PayPalConfigurationApiResponse > {
async function defaultFetchPayPalConfiguration(): Promise< PayPalConfigurationApiResponse > {
return await wpcomRequest( {
path: `/me/paypal-configuration`,
method: 'GET',
Expand All @@ -28,7 +28,11 @@ const defaultConfiguration: PayPalConfiguration = {
clientId: undefined,
};

function usePayPalConfigurationInternalOnly(): {
function usePayPalConfigurationInternalOnly( {
fetchPayPalConfiguration,
}: {
fetchPayPalConfiguration?: () => Promise< PayPalConfigurationApiResponse >;
} ): {
payPalConfiguration: PayPalConfiguration | undefined;
error: undefined | Error;
} {
Expand All @@ -39,7 +43,7 @@ function usePayPalConfigurationInternalOnly(): {

useEffect( () => {
let isSubscribed = true;
fetchPayPalConfiguration()
( fetchPayPalConfiguration ?? defaultFetchPayPalConfiguration )()
.then( ( configuration ) => {
if ( ! isSubscribed ) {
return;
Expand All @@ -57,7 +61,7 @@ function usePayPalConfigurationInternalOnly(): {
return () => {
isSubscribed = false;
};
}, [] );
}, [ fetchPayPalConfiguration ] );

return { payPalConfiguration, error: configurationError };
}
Expand All @@ -73,12 +77,35 @@ export function usePayPalConfiguration(): UsePayPalConfiguration {
export function PayPalProvider( {
children,
currency,
}: PropsWithChildren< { currency: string } > ) {
const { payPalConfiguration, error } = usePayPalConfigurationInternalOnly();
handleError,
fetchPayPalConfiguration,
}: PropsWithChildren< {
currency: string;
handleError?: ( error: Error ) => void;
fetchPayPalConfiguration?: () => Promise< PayPalConfigurationApiResponse >;
} > ) {
const { payPalConfiguration, error } = usePayPalConfigurationInternalOnly( {
fetchPayPalConfiguration,
} );
const lastError = useRef< Error | undefined >();

if ( error ) {
throw error;
}
useEffect( () => {
if ( ! error || lastError.current === error ) {
return;
}
lastError.current = error;
const errorWithCause = new Error(
`Error fetching PayPal configuration: ${ error?.message ?? error }`,
{
cause: error,
}
);
// eslint-disable-next-line no-console
console.error( errorWithCause );
if ( handleError ) {
handleError( errorWithCause );
}
}, [ error, handleError ] );

const payPalScriptOptions: ReactPayPalScriptOptions = {
clientId: payPalConfiguration?.clientId ?? 'loading-client-id',
Expand Down
Loading