Skip to content

Commit

Permalink
Pass Blocks checkout appearance on init WooPay (#9075)
Browse files Browse the repository at this point in the history
  • Loading branch information
hsingyuc authored and lovo-h committed Aug 1, 2024
1 parent 803e736 commit 8ad6e85
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 3 deletions.
4 changes: 4 additions & 0 deletions changelog/add-pass-blocks-checkout-appearance-on-init-woopay
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: add

Pass Blocks checkout appearance on init WooPay
4 changes: 4 additions & 0 deletions client/checkout/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
getExpressCheckoutAjaxURL,
getExpressCheckoutConfig,
} from 'utils/express-checkout';
import { getAppearance } from 'checkout/upe-styles';

/**
* Handles generic connections to the server and Stripe.
Expand Down Expand Up @@ -459,8 +460,11 @@ export default class WCPayAPI {
this.isWooPayRequesting = true;
const wcAjaxUrl = getConfig( 'wcAjaxUrl' );
const nonce = getConfig( 'initWooPayNonce' );
const appearance = getAppearance( 'blocks_checkout' );

return this.request( buildAjaxURL( wcAjaxUrl, 'init_woopay' ), {
_wpnonce: nonce,
appearance: appearance,
email: userEmail,
user_session: woopayUserSession,
order_id: getConfig( 'order_id' ),
Expand Down
29 changes: 29 additions & 0 deletions client/checkout/api/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,33 @@ jest.mock( 'wcpay/utils/checkout', () => ( {
getConfig: jest.fn(),
} ) );

const mockAppearance = {
rules: {
'.Block': {},
'.Input': {},
'.Input--invalid': {},
'.Label': {},
'.Tab': {},
'.Tab--selected': {},
'.Tab:hover': {},
'.TabIcon--selected': {
color: undefined,
},
'.TabIcon:hover': {
color: undefined,
},
'.Text': {},
'.Text--redirect': {},
},
theme: 'stripe',
variables: {
colorBackground: '#ffffff',
colorText: undefined,
fontFamily: undefined,
fontSizeBase: undefined,
},
};

describe( 'WCPayAPI', () => {
test( 'does not initialize woopay if already requesting', async () => {
buildAjaxURL.mockReturnValue( 'https://example.org/' );
Expand All @@ -48,6 +75,7 @@ describe( 'WCPayAPI', () => {
getConfig.mockImplementation( ( key ) => {
const mockProperties = {
initWooPayNonce: 'foo',
appearance: mockAppearance,
order_id: 1,
key: 'testkey',
billing_email: '[email protected]',
Expand All @@ -60,6 +88,7 @@ describe( 'WCPayAPI', () => {

expect( request ).toHaveBeenLastCalledWith( 'https://example.org/', {
_wpnonce: 'foo',
appearance: mockAppearance,
email: '[email protected]',
user_session: 'qwerty123',
order_id: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
appendRedirectionParams,
} from '../utils';
import { getTracksIdentity } from 'tracks';
import { getAppearance } from 'wcpay/checkout/upe-styles';

export const expressCheckoutIframe = async ( api, context, emailSelector ) => {
const woopayEmailInput = await getTargetElement( emailSelector );
Expand Down Expand Up @@ -106,6 +107,7 @@ export const expressCheckoutIframe = async ( api, context, emailSelector ) => {
order_id: getConfig( 'order_id' ),
key: getConfig( 'key' ),
billing_email: getConfig( 'billing_email' ),
appearance: getAppearance( 'blocks_checkout' ),
}
).then( ( response ) => {
if ( response?.data?.session ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,32 @@ describe( 'WoopayExpressCheckoutButton', () => {
const mockRequest = jest.fn().mockResolvedValue( true );
const mockAddToCart = jest.fn().mockResolvedValue( true );
const api = new WCPayAPI( {}, mockRequest );
const mockAppearance = {
rules: {
'.Block': {},
'.Input': {},
'.Input--invalid': {},
'.Label': {},
'.Tab': {},
'.Tab--selected': {},
'.Tab:hover': {},
'.TabIcon--selected': {
color: undefined,
},
'.TabIcon:hover': {
color: undefined,
},
'.Text': {},
'.Text--redirect': {},
},
theme: 'stripe',
variables: {
colorBackground: '#ffffff',
colorText: undefined,
fontFamily: undefined,
fontSizeBase: undefined,
},
};

beforeEach( () => {
expressCheckoutIframe.mockImplementation( () => jest.fn() );
Expand Down Expand Up @@ -145,6 +171,8 @@ describe( 'WoopayExpressCheckoutButton', () => {
return 'testkey';
case 'order_id':
return 1;
case 'appearance':
return mockAppearance;
default:
return 'foo';
}
Expand All @@ -170,6 +198,7 @@ describe( 'WoopayExpressCheckoutButton', () => {
order_id: 1,
key: 'testkey',
billing_email: '[email protected]',
appearance: mockAppearance,
} );
expect( expressCheckoutIframe ).not.toHaveBeenCalled();
} );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
deleteSkipWooPayCookie,
} from 'wcpay/checkout/woopay/utils';
import WooPayFirstPartyAuth from 'wcpay/checkout/woopay/express-button/woopay-first-party-auth';
import { getAppearance } from 'wcpay/checkout/upe-styles';

const BUTTON_WIDTH_THRESHOLD = 140;

Expand Down Expand Up @@ -268,6 +269,7 @@ export const WoopayExpressCheckoutButton = ( {
order_id: getConfig( 'order_id' ),
key: getConfig( 'key' ),
billing_email: getConfig( 'billing_email' ),
appearance: getAppearance( 'blocks_checkout' ),
} )
.then( async ( response ) => {
if ( response?.blog_id && response?.data?.session ) {
Expand Down
38 changes: 35 additions & 3 deletions includes/woopay/class-woopay-session.php
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,10 @@ public static function get_frontend_init_session_request() {
$key = ! empty( $_POST['key'] ) ? sanitize_text_field( wp_unslash( $_POST['key'] ) ) : null;
$billing_email = ! empty( $_POST['billing_email'] ) ? sanitize_text_field( wp_unslash( $_POST['billing_email'] ) ) : null;
// phpcs:enable
// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, Generic.Arrays.DisallowLongArraySyntax.Found
$appearance = ! empty( $_POST['appearance'] ) ? self::array_map_recursive( array( __CLASS__, 'sanitize_string' ), $_POST['appearance'] ) : null;

$session = self::get_init_session_request( $order_id, $key, $billing_email );
$session = self::get_init_session_request( $order_id, $key, $billing_email, null, $appearance );

return WooPay_Utilities::encrypt_and_sign_data( $session );
}
Expand Down Expand Up @@ -416,9 +418,10 @@ private static function get_user_email( $user ) {
* @param string|null $key Pay-for-order key.
* @param string|null $billing_email Pay-for-order billing email.
* @param WP_REST_Request|null $woopay_request The WooPay request object.
* @param array $appearance Merchant appearance.
* @return array The initial session request data without email and user_session.
*/
public static function get_init_session_request( $order_id = null, $key = null, $billing_email = null, $woopay_request = null ) {
public static function get_init_session_request( $order_id = null, $key = null, $billing_email = null, $woopay_request = null, $appearance = null ) {
$user = wp_get_current_user();
$is_pay_for_order = null !== $order_id;
$order = wc_get_order( $order_id );
Expand Down Expand Up @@ -500,6 +503,7 @@ public static function get_init_session_request( $order_id = null, $key = null,
],
],
'tracks_user_identity' => WC_Payments::woopay_tracker()->tracks_get_identity(),
'appearance' => $appearance,
];

$woopay_adapted_extensions = new WooPay_Adapted_Extensions();
Expand All @@ -526,6 +530,33 @@ public static function get_init_session_request( $order_id = null, $key = null,
return $request;
}

/**
* Recursively map an array.
*
* @param callable $callback The sanitize_text_field function.
* @param array $array The nested array.
*
* @return array A new appearance array.
*/
private static function array_map_recursive( $callback, $array ) {
$func = function ( $item ) use ( &$func, &$callback ) {
return is_array( $item ) ? array_map( $func, $item ) : call_user_func( $callback, $item );
};

return array_map( $func, $array );
}

/**
* Sanitize a string.
*
* @param string $item A string.
*
* @return string The sanitized string.
*/
private static function sanitize_string( $item ) {
return sanitize_text_field( wp_unslash( $item ) );
}

/**
* Used to initialize woopay session.
*
Expand All @@ -544,8 +575,9 @@ public static function ajax_init_woopay() {
$order_id = ! empty( $_POST['order_id'] ) ? absint( wp_unslash( $_POST['order_id'] ) ) : null;
$key = ! empty( $_POST['key'] ) ? sanitize_text_field( wp_unslash( $_POST['key'] ) ) : null;
$billing_email = ! empty( $_POST['billing_email'] ) ? sanitize_text_field( wp_unslash( $_POST['billing_email'] ) ) : null;
$appearance = ! empty( $_POST['appearance'] ) ? self::array_map_recursive( array( __CLASS__, 'sanitize_string' ), $_POST['appearance'] ) : null; // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, Generic.Arrays.DisallowLongArraySyntax.Found

$body = self::get_init_session_request( $order_id, $key, $billing_email );
$body = self::get_init_session_request( $order_id, $key, $billing_email, null, $appearance );
$body['user_session'] = isset( $_REQUEST['user_session'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['user_session'] ) ) : null;

$args = [
Expand Down

0 comments on commit 8ad6e85

Please sign in to comment.