Skip to content

Commit

Permalink
Pass pay for order param to init WooPay session (#7253)
Browse files Browse the repository at this point in the history
  • Loading branch information
hsingyuc authored Sep 26, 2023
1 parent 8c1558b commit 237ebf4
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 15 deletions.
4 changes: 4 additions & 0 deletions changelog/fix-init-woopay-error
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fix

Fix init WooPay and empty cart error
3 changes: 3 additions & 0 deletions client/checkout/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,9 @@ export default class WCPayAPI {
_wpnonce: nonce,
email: userEmail,
user_session: woopayUserSession,
order_id: getConfig( 'order_id' ),
key: getConfig( 'key' ),
billing_email: getConfig( 'billing_email' ),
} ).finally( () => {
this.isWooPayRequesting = false;
} );
Expand Down
23 changes: 21 additions & 2 deletions client/checkout/api/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ jest.mock( 'wcpay/utils/checkout', () => ( {
describe( 'WCPayAPI', () => {
test( 'does not initialize woopay if already requesting', async () => {
buildAjaxURL.mockReturnValue( 'https://example.org/' );
getConfig.mockReturnValue( 'foo' );
getConfig.mockImplementation( ( key ) => {
const mockProperties = {
initWooPayNonce: 'foo',
order_id: 1,
key: 'testkey',
billing_email: '[email protected]',
};
return mockProperties[ key ];
} );

const api = new WCPayAPI( {}, request );
api.isWooPayRequesting = true;
Expand All @@ -31,7 +39,15 @@ describe( 'WCPayAPI', () => {

test( 'initializes woopay using config params', async () => {
buildAjaxURL.mockReturnValue( 'https://example.org/' );
getConfig.mockReturnValue( 'foo' );
getConfig.mockImplementation( ( key ) => {
const mockProperties = {
initWooPayNonce: 'foo',
order_id: 1,
key: 'testkey',
billing_email: '[email protected]',
};
return mockProperties[ key ];
} );

const api = new WCPayAPI( {}, request );
await api.initWooPay( '[email protected]', 'qwerty123' );
Expand All @@ -40,6 +56,9 @@ describe( 'WCPayAPI', () => {
_wpnonce: 'foo',
email: '[email protected]',
user_session: 'qwerty123',
order_id: 1,
key: 'testkey',
billing_email: '[email protected]',
} );
expect( api.isWooPayRequesting ).toBe( false );
} );
Expand Down
3 changes: 3 additions & 0 deletions client/checkout/woopay/email-input-iframe.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ export const handleWooPayEmailInput = async (
buildAjaxURL( getConfig( 'wcAjaxUrl' ), 'get_woopay_session' ),
{
_ajax_nonce: getConfig( 'woopaySessionNonce' ),
order_id: getConfig( 'order_id' ),
key: getConfig( 'key' ),
billing_email: getConfig( 'billing_email' ),
}
).then( ( response ) => {
if ( response?.data?.session ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ export const expressCheckoutIframe = async ( api, context, emailSelector ) => {
buildAjaxURL( getConfig( 'wcAjaxUrl' ), 'get_woopay_session' ),
{
_ajax_nonce: getConfig( 'woopaySessionNonce' ),
order_id: getConfig( 'order_id' ),
key: getConfig( 'key' ),
billing_email: getConfig( 'billing_email' ),
}
).then( ( response ) => {
if ( response?.data?.session ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public function __construct( WC_Payment_Gateway_WCPay $gateway, WC_Payments_Paym
}

if ( class_exists( '\Automattic\WooCommerce\Blocks\Package' ) && version_compare( \Automattic\WooCommerce\Blocks\Package::get_version(), '10.8.0', '>=' ) ) {
add_action( 'before_woocommerce_pay_form', [ $this, 'add_pay_for_order_params_to_js_config' ] );
add_action( 'wp_enqueue_scripts', [ $this, 'add_pay_for_order_params_to_js_config' ], 5 );
add_action( 'woocommerce_pay_order_before_payment', [ $this, 'display_express_checkout_buttons' ], 1 );
}
}
Expand Down Expand Up @@ -114,12 +114,13 @@ public function is_woopay_enabled() {

/**
* Add the Pay for order params to the JS config.
*
* @param WC_Order $order The pay-for-order order.
*/
public function add_pay_for_order_params_to_js_config( $order ) {
public function add_pay_for_order_params_to_js_config() {
// phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( isset( $_GET['pay_for_order'] ) && isset( $_GET['key'] ) ) {
global $wp;
$order_id = $wp->query_vars['order-pay'];
$order = wc_get_order( $order_id );
add_filter(
'wcpay_payment_fields_js_config',
function( $js_config ) use ( $order ) {
Expand Down
8 changes: 7 additions & 1 deletion includes/class-wc-payments-upe-checkout.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,13 @@ public function get_payment_fields_js_config() {
);
}
}
return $payment_fields; // nosemgrep: audit.php.wp.security.xss.query-arg -- server generated url is passed in.

/**
* Allows filtering for the payment fields.
*
* @param array $payment_fields The payment fields.
*/
return apply_filters( 'wcpay_payment_fields_js_config', $payment_fields ); // nosemgrep: audit.php.wp.security.xss.query-arg -- server generated url is passed in.
}

/**
Expand Down
39 changes: 31 additions & 8 deletions includes/woopay/class-woopay-session.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ class WooPay_Session {
'@^\/wc\/store(\/v[\d]+)?\/cart\/update-customer$@',
'@^\/wc\/store(\/v[\d]+)?\/cart\/update-item$@',
'@^\/wc\/store(\/v[\d]+)?\/cart\/extensions$@',
'@^\/wc\/store(\/v[\d]+)?\/checkout\/(?P<id>[\d]+)@',
'@^\/wc\/store(\/v[\d]+)?\/checkout$@',
'@^\/wc\/store(\/v[\d]+)?\/order\/(?P<id>[\d]+)@',
];

/**
Expand Down Expand Up @@ -289,7 +291,13 @@ public static function get_frontend_init_session_request() {
return [];
}

$session = self::get_init_session_request();
// phpcs:disable WordPress.Security.NonceVerification.Missing
$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;
// phpcs:enable

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

$store_blog_token = ( WooPay_Utilities::get_woopay_url() === WooPay_Utilities::DEFAULT_WOOPAY_URL ) ? Jetpack_Options::get_option( 'blog_token' ) : 'dev_mode';

Expand Down Expand Up @@ -321,11 +329,16 @@ public static function get_frontend_init_session_request() {
/**
* Returns the initial session request data.
*
* @param int|null $order_id Pay-for-order order ID.
* @param string|null $key Pay-for-order key.
* @param string|null $billing_email Pay-for-order billing email.
* @return array The initial session request data without email and user_session.
*/
private static function get_init_session_request() {
$user = wp_get_current_user();
$customer_id = WC_Payments::get_customer_service()->get_customer_id_by_user_id( $user->ID );
private static function get_init_session_request( $order_id = null, $key = null, $billing_email = null ) {
$user = wp_get_current_user();
$is_pay_for_order = null !== $order_id;
$order = wc_get_order( $order_id );
$customer_id = WC_Payments::get_customer_service()->get_customer_id_by_user_id( $user->ID );
if ( null === $customer_id ) {
// create customer.
$customer_data = WC_Payments_Customer_Service::map_customer_data( null, new WC_Customer( $user->ID ) );
Expand Down Expand Up @@ -358,7 +371,9 @@ private static function get_init_session_request() {
$blocks_data_extractor = new Blocks_Data_Extractor();

// This uses the same logic as the Checkout block in hydrate_from_api to get the cart and checkout data.
$cart_data = rest_preload_api_request( [], '/wc/store/v1/cart' )['/wc/store/v1/cart']['body'];
$cart_data = ! $is_pay_for_order
? rest_preload_api_request( [], '/wc/store/v1/cart' )['/wc/store/v1/cart']['body']
: rest_preload_api_request( [], "/wc/store/v1/order/{$order_id}?key={$key}&billing_email={$billing_email}" )[ "/wc/store/v1/order/{$order_id}?key={$key}&billing_email={$billing_email}" ]['body'];
add_filter( 'woocommerce_store_api_disable_nonce_check', '__return_true' );
$preloaded_checkout_data = rest_preload_api_request( [], '/wc/store/v1/checkout' );
remove_filter( 'woocommerce_store_api_disable_nonce_check', '__return_true' );
Expand Down Expand Up @@ -391,9 +406,14 @@ private static function get_init_session_request() {
'checkout_schema_namespaces' => $blocks_data_extractor->get_checkout_schema_namespaces(),
],
'user_session' => null,
'preloaded_requests' => [
'preloaded_requests' => ! $is_pay_for_order ? [
'cart' => $cart_data,
'checkout' => $checkout_data,
] : [
'cart' => $cart_data,
'checkout' => [
'order_id' => $order_id, // This is a workaround for the checkout order error. https://github.com/woocommerce/woocommerce-blocks/blob/04f36065b34977f02079e6c2c8cb955200a783ff/assets/js/blocks/checkout/block.tsx#L81-L83.
],
],
'tracks_user_identity' => WC_Payments::woopay_tracker()->tracks_get_identity( $user->ID ),
];
Expand All @@ -416,9 +436,12 @@ public static function ajax_init_woopay() {
);
}

$email = ! empty( $_POST['email'] ) ? wc_clean( wp_unslash( $_POST['email'] ) ) : '';
$email = ! empty( $_POST['email'] ) ? wc_clean( wp_unslash( $_POST['email'] ) ) : '';
$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;

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

Expand Down

0 comments on commit 237ebf4

Please sign in to comment.