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

feat: tokenized cart PRB PDP session handler #9021

Merged
merged 49 commits into from
Jul 30, 2024

Conversation

frosso
Copy link
Contributor

@frosso frosso commented Jun 26, 2024

Fixes #8841

Changes proposed in this Pull Request

Adding capability to pay for subscriptions & associating orders placed by the current logged-in customer.

Screen.Recording.2024-07-18.at.2.34.03.PM.mov

When an order is placed with the PRB on a product page, the customer's main cart should remain unaltered.
So, if the customer placed an order for one product (but had other items in their cart), they should be able to check out only the single product.

After discussing with the Blocks team, the solution we concluded with was to implement a custom SessionHandler.

Testing instructions

  • Disable ECE with the following snippet:
add_filter( 'pre_option__wcpay_feature_stripe_ece', function () {
    return '0'; 
}, 100 );
  • Enable the "Enable Cart-Token implementation for PRBs" flag in your dev tools (you'll need to update them)
  • Ensure you have Google Pay/Apple Pay enabled in the merchant's settings
  • Ensure you have WC Subscriptions installed
  • As a logged-in customer, add some random products to the cart (we'll need this to later validate that the main customer cart isn't affected)
  • Go to a subscription's product page
  • Click on the GooglePay/ApplePay button to purchase the subscription
  • A few things can happen:
    • If you already placed a subscription order on this site and you're logged in, the order should be placed (and the backend will associate the order to your account)
    • If you already placed a subscription order on this site and you're not logged in, the order will fail with an error message in the back of the page (the behavior is a bit janky - but it's the same behavior as the non-tokenized cart implementation)
Screenshot 2024-07-18 at 2 40 30 PM - If you haven't placed a subscription order on this site, the new subscription will be created and the backend will associate the order to your account (if you have one)
  • Run npm run changelog to add a changelog file, choose patch to leave it empty if the change is not significant. You can add multiple changelog files in one PR by running this command a few times.
  • Covered with tests (or have a good reason not to test in description ☝️)
  • Tested on mobile (or does not apply)

Post merge

@botwoo
Copy link
Collaborator

botwoo commented Jun 26, 2024

Test the build

Option 1. Jetpack Beta

  • Install and activate Jetpack Beta.
  • Use this build by searching for PR number 9021 or branch name feat/tokenized-cart-pdp-session-handler in your-test.site/wp-admin/admin.php?page=jetpack-beta&plugin=woocommerce-payments

Option 2. Jurassic Ninja - available for logged-in A12s

🚀 Launch a JN site with this branch 🚀

ℹ️ Install this Tampermonkey script to get more options.


Build info:

  • Latest commit: a02086a
  • Build time: 2024-07-29 15:01:30 UTC

Note: the build is updated when a new commit is pushed to this PR.

Copy link
Contributor

github-actions bot commented Jun 26, 2024

Size Change: -37 B (0%)

Total Size: 1.33 MB

Filename Size Change
release/woocommerce-payments/dist/tokenized-payment-request.js 14.3 kB -37 B (0%)
ℹ️ View Unchanged
Filename Size
release/woocommerce-payments/assets/css/admin.css 1.08 kB
release/woocommerce-payments/assets/css/admin.rtl.css 1.08 kB
release/woocommerce-payments/assets/css/success.css 173 B
release/woocommerce-payments/assets/css/success.rtl.css 173 B
release/woocommerce-payments/dist/blocks-checkout-rtl.css 2.21 kB
release/woocommerce-payments/dist/blocks-checkout.css 2.21 kB
release/woocommerce-payments/dist/blocks-checkout.js 61.1 kB
release/woocommerce-payments/dist/bnpl-announcement-rtl.css 528 B
release/woocommerce-payments/dist/bnpl-announcement.css 529 B
release/woocommerce-payments/dist/bnpl-announcement.js 20.8 kB
release/woocommerce-payments/dist/cart-block.js 16.1 kB
release/woocommerce-payments/dist/cart.js 5.72 kB
release/woocommerce-payments/dist/checkout-rtl.css 600 B
release/woocommerce-payments/dist/checkout.css 600 B
release/woocommerce-payments/dist/checkout.js 31.7 kB
release/woocommerce-payments/dist/express-checkout-rtl.css 235 B
release/woocommerce-payments/dist/express-checkout.css 235 B
release/woocommerce-payments/dist/express-checkout.js 13.9 kB
release/woocommerce-payments/dist/index-rtl.css 39.1 kB
release/woocommerce-payments/dist/index.css 39 kB
release/woocommerce-payments/dist/index.js 296 kB
release/woocommerce-payments/dist/multi-currency-analytics.js 1.08 kB
release/woocommerce-payments/dist/multi-currency-rtl.css 3.41 kB
release/woocommerce-payments/dist/multi-currency-switcher-block.js 60.5 kB
release/woocommerce-payments/dist/multi-currency.css 3.41 kB
release/woocommerce-payments/dist/multi-currency.js 55.5 kB
release/woocommerce-payments/dist/order-rtl.css 730 B
release/woocommerce-payments/dist/order.css 730 B
release/woocommerce-payments/dist/order.js 42.7 kB
release/woocommerce-payments/dist/payment-gateways-rtl.css 1.35 kB
release/woocommerce-payments/dist/payment-gateways.css 1.35 kB
release/woocommerce-payments/dist/payment-gateways.js 39.2 kB
release/woocommerce-payments/dist/payment-request-rtl.css 235 B
release/woocommerce-payments/dist/payment-request.css 235 B
release/woocommerce-payments/dist/payment-request.js 13.5 kB
release/woocommerce-payments/dist/plugins-page-rtl.css 386 B
release/woocommerce-payments/dist/plugins-page.css 386 B
release/woocommerce-payments/dist/plugins-page.js 20.1 kB
release/woocommerce-payments/dist/product-details-rtl.css 397 B
release/woocommerce-payments/dist/product-details.css 398 B
release/woocommerce-payments/dist/product-details.js 11.3 kB
release/woocommerce-payments/dist/settings-rtl.css 11.2 kB
release/woocommerce-payments/dist/settings.css 11.1 kB
release/woocommerce-payments/dist/settings.js 223 kB
release/woocommerce-payments/dist/subscription-edit-page.js 703 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal-rtl.css 524 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.css 524 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.js 20.2 kB
release/woocommerce-payments/dist/subscription-product-onboarding-toast.js 730 B
release/woocommerce-payments/dist/subscriptions-empty-state-rtl.css 120 B
release/woocommerce-payments/dist/subscriptions-empty-state.css 120 B
release/woocommerce-payments/dist/subscriptions-empty-state.js 19.3 kB
release/woocommerce-payments/dist/tokenized-payment-request-rtl.css 235 B
release/woocommerce-payments/dist/tokenized-payment-request.css 235 B
release/woocommerce-payments/dist/tos-rtl.css 235 B
release/woocommerce-payments/dist/tos.css 235 B
release/woocommerce-payments/dist/tos.js 21.8 kB
release/woocommerce-payments/dist/woopay-direct-checkout.js 6.14 kB
release/woocommerce-payments/dist/woopay-express-button-rtl.css 235 B
release/woocommerce-payments/dist/woopay-express-button.css 235 B
release/woocommerce-payments/dist/woopay-express-button.js 23.9 kB
release/woocommerce-payments/dist/woopay-rtl.css 4.5 kB
release/woocommerce-payments/dist/woopay.css 4.48 kB
release/woocommerce-payments/dist/woopay.js 71.1 kB
release/woocommerce-payments/includes/subscriptions/assets/css/plugin-page.css 625 B
release/woocommerce-payments/includes/subscriptions/assets/js/plugin-page.js 814 B
release/woocommerce-payments/vendor/automattic/jetpack-assets/build/i18n-loader.js 2.46 kB
release/woocommerce-payments/vendor/automattic/jetpack-assets/src/js/i18n-loader.js 1.02 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.css 198 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.js 20 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.rtl.css 198 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.css 625 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.js 20 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.rtl.css 626 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-users.js 392 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-ajax.js 521 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-callables.js 584 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-admin-create-user.css 215 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-admin-create-user.js 521 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-login.css 721 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-login.js 412 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-users.js 520 B
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/babel.config.js 159 B
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/build/index.css 2.36 kB
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/build/index.js 13.6 kB
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/build/index.rtl.css 2.36 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/about.css 1.04 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-empty-state.css 294 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-order-statuses.css 408 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin.css 3.59 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/checkout.css 301 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/modal.css 746 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/view-subscription.css 574 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/wcs-upgrade.css 414 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin-pointers.js 543 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin.js 9.4 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.js 6.78 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.min.js 3.84 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-coupon.js 545 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-subscription.js 2.52 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.js 22.2 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.min.js 11.7 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/payment-method-restrictions.js 1.29 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/wcs-meta-boxes-order.js 507 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/payment-methods.js 358 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/single-product.js 428 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/view-subscription.js 1.38 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/wcs-cart.js 782 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/modal.js 1.09 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/wcs-upgrade.js 1.26 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.css 391 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.js 3.04 kB

compressed-size-action

@frosso frosso marked this pull request as ready for review July 18, 2024 15:15
@frosso frosso self-assigned this Jul 18, 2024
@frosso frosso requested review from a team and brettshumaker and removed request for a team July 18, 2024 15:16
Copy link
Contributor Author

@frosso frosso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the notification galore - I forgot to publish these comments as inline explanation of the changes

// this header will be overwritten by a filter in the backend to overcome nonce overwrites in this middleware:
// https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce-blocks/assets/js/middleware/store-api-nonce.js
'X-WooPayments-Store-Api-Nonce': response.headers.get( 'Nonce' ),
'Cart-Token': response.headers.get( 'Cart-Token' ),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer necessary to save this for anonymous carts.

Comment on lines -141 to -144
credentials:
getPaymentRequestData( 'button_context' ) === 'product'
? 'omit'
: undefined,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of PDPs, the cart will no longer be "anonymous" - we'll always provide cookies to identify the customer.

Comment on lines -169 to -172
credentials:
getPaymentRequestData( 'button_context' ) === 'product'
? 'omit'
: undefined,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of PDPs, the cart will no longer be "anonymous" - we'll always provide cookies to identify the customer.

@@ -192,7 +187,6 @@ export default class PaymentRequestCartApi {
return await this._request( {
method: 'POST',
path: '/wc/store/v1/cart/add-item',
credentials: 'omit',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of PDPs, the cart will no longer be "anonymous" - we'll always provide cookies to identify the customer.

const cartData = await this._request( {
method: 'GET',
path: '/wc/store/v1/cart',
credentials: 'omit',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of PDPs, the cart will no longer be "anonymous" - we'll always provide cookies to identify the customer.

@@ -120,7 +120,6 @@ public function init() {
2
);
add_filter( 'rest_pre_dispatch', [ $this, 'tokenized_cart_store_api_address_normalization' ], 10, 3 );
add_filter( 'rest_pre_dispatch', [ $this, 'tokenized_cart_store_api_nonce_overwrite' ], 10, 3 );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer need to overwrite the nonce value

'platform_tracker' => wp_create_nonce( 'platform_tracks_nonce' ),
'pay_for_order' => wp_create_nonce( 'pay_for_order' ),
'tokenized_cart_nonce' => wp_create_nonce( 'woopayments_tokenized_cart_nonce' ),
'tokenized_cart_session_nonce' => wp_create_nonce( 'tokenized_cart_session_nonce' ),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a new nonce for product pages

Comment on lines -959 to -969
'get_cart_details' => wp_create_nonce( 'wcpay-get-cart-details' ),
'shipping' => wp_create_nonce( 'wcpay-payment-request-shipping' ),
'update_shipping' => wp_create_nonce( 'wcpay-update-shipping-method' ),
'checkout' => wp_create_nonce( 'woocommerce-process_checkout' ),
'add_to_cart' => wp_create_nonce( 'wcpay-add-to-cart' ),
'empty_cart' => wp_create_nonce( 'wcpay-empty-cart' ),
'get_selected_product_data' => wp_create_nonce( 'wcpay-get-selected-product-data' ),
'platform_tracker' => wp_create_nonce( 'platform_tracks_nonce' ),
'pay_for_order' => wp_create_nonce( 'pay_for_order' ),
'tokenized_cart_nonce' => wp_create_nonce( 'woopayments_tokenized_cart_nonce' ),
'tokenized_order_nonce' => wp_create_nonce( 'wc_store_api' ),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I just added the tokenized_cart_session_nonce nonce and renamed the pay_for_order nonce to a more generic store_api_nonce.
The rest of the changes are just indentation.

// On cart, checkout, place order pages we instead use the cart itself.
if ( getPaymentRequestData( 'button_context' ) === 'product' ) {
await this.paymentRequestCartApi.createAnonymousCart();
this.paymentRequestCartApi.useSeparateCart();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed the createAnonymousCart() method to useSeparateCart() - since the cart is no longer "anonymous" (we're sending cookies this time - we weren't before)

Copy link
Contributor

@brettshumaker brettshumaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed that this is all working as expected. Do you know what's going on with these failing tests, though?

1) WC_Payments_Payment_Request_Session_Test::test_restores_cart_data_on_order_received_page
Exception: Invalid token: cookie and session customer mismatch

2) WC_Payments_Payment_Request_Session_Test::test_does_not_restore_cart_data_when_missing_query_parameter
Exception: Invalid token: cookie and session customer mismatch

@frosso
Copy link
Contributor Author

frosso commented Jul 29, 2024

Do you know what's going on with these failing tests, though?

@brettshumaker thank you for pointing it out, I'm not sure why the tests were passing before. In any case, after debugging, I noticed that the incorrect session handler was lingering across test cases. So I added some cleanup steps in 6f1d761 to solve for it.

@frosso frosso requested a review from brettshumaker July 29, 2024 12:01
@frosso frosso added this pull request to the merge queue Jul 30, 2024
Merged via the queue into develop with commit 26d444d Jul 30, 2024
23 checks passed
@frosso frosso deleted the feat/tokenized-cart-pdp-session-handler branch July 30, 2024 08:23
lovo-h pushed a commit that referenced this pull request Aug 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PRBs with Tokenized carts - interesting quirks
3 participants