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 ECE base implementation #9739

Merged
merged 61 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
1d3fc0f
feat: tokenized cart ECE base implementation
frosso Nov 15, 2024
21ad804
restore original files to avoid issues with linting
frosso Nov 15, 2024
d0c40ab
WIP
frosso Nov 18, 2024
4a2748e
porting
frosso Nov 18, 2024
2981cba
WIP
frosso Nov 18, 2024
d1acf78
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 18, 2024
345db05
WIP
frosso Nov 18, 2024
060305e
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 19, 2024
f83de72
missing method
frosso Nov 19, 2024
d60479c
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 19, 2024
6f74fdf
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 19, 2024
30268a5
added notes, added transformers
frosso Nov 19, 2024
450ba16
change path references
frosso Nov 19, 2024
69391e8
states rename
frosso Nov 19, 2024
f710c4c
rename
frosso Nov 19, 2024
482bec6
undo a rename
frosso Nov 19, 2024
de7c358
cart api handler approach
frosso Nov 19, 2024
9496e83
fix conflicts
frosso Nov 19, 2024
a731d7b
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 19, 2024
283cc8c
shipping rate selection working
frosso Nov 19, 2024
aa5fb33
WIP
frosso Nov 19, 2024
596fb37
it was an ez fix
frosso Nov 19, 2024
d70152e
fix type
frosso Nov 19, 2024
7f343df
WIP
frosso Nov 20, 2024
69bd51e
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 20, 2024
f05e634
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 20, 2024
2ba9ec9
tests add
frosso Nov 20, 2024
1509005
tests fix
frosso Nov 20, 2024
d30b7ea
limiting the number of changes
frosso Nov 20, 2024
f252e18
options is always defined
frosso Nov 20, 2024
4cab61e
place order via Store API
frosso Nov 20, 2024
e5a9a96
done with event handlers?
frosso Nov 20, 2024
8ffd6e8
remove unused api argument
frosso Nov 20, 2024
f07d8b6
some cleanup of JS
frosso Nov 20, 2024
4c635f1
restore some things
frosso Nov 20, 2024
ecd0c0a
fix void return type
frosso Nov 20, 2024
4335e88
less changes?
frosso Nov 20, 2024
014442d
less changes
frosso Nov 20, 2024
06cc7cd
less changes
frosso Nov 20, 2024
bc9a57c
less changes
frosso Nov 20, 2024
1731980
less changes
frosso Nov 20, 2024
e8e3bb3
less changes
frosso Nov 20, 2024
b65dabe
lint ignore
frosso Nov 20, 2024
87a2840
changelog
frosso Nov 20, 2024
6bef470
PRB > ECE
frosso Nov 20, 2024
bcf97d6
fix docs ref
frosso Nov 20, 2024
2366c72
rename for ECE
frosso Nov 20, 2024
63e5872
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 20, 2024
20787f0
ignore tokenized prb tests
frosso Nov 20, 2024
bbfa8b8
replacing another call, fixing cart updates on shortcode
frosso Nov 20, 2024
6196ba5
some null coalescing, just in case
frosso Nov 20, 2024
3ab4f95
fix e -> error
frosso Nov 20, 2024
4cb49ca
pay-for-order missing address
frosso Nov 20, 2024
22a8372
less changes
frosso Nov 20, 2024
6190e62
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 20, 2024
3256cda
revert
frosso Nov 20, 2024
4d31e93
revert rename
frosso Nov 20, 2024
567675f
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 21, 2024
84326d6
sorting selected rates at the top
frosso Nov 22, 2024
9a5b7ab
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 22, 2024
a147dcc
Merge branch 'develop' into refactor/tokenized-ece-base-implementation
frosso Nov 22, 2024
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
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ vendor/*
release/*
tests/e2e/docker*
tests/e2e/deps*

# We'll delete the directory and its contents as part of https://github.com/Automattic/woocommerce-payments/issues/9722 .
# ignoring it because we're temporariily cleaning it up.
client/tokenized-payment-request
5 changes: 5 additions & 0 deletions changelog/refactor-tokenized-ece-base-implementation
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: update
Comment: feat: tokenized cart ECE shortcode base implementation.


4 changes: 4 additions & 0 deletions client/express-checkout/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface WCPayExpressCheckoutParams {
currency_code: string;
needs_payer_phone: boolean;
needs_shipping: boolean;
currency_decimals: number;
};

/**
Expand All @@ -54,6 +55,9 @@ export interface WCPayExpressCheckoutParams {
platform_tracker: string;
shipping: string;
update_shipping: string;
tokenized_cart_nonce: string;
tokenized_cart_session_nonce: string;
store_api_nonce: string;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ import apiFetch from '@wordpress/api-fetch';
/**
* Internal dependencies
*/
import PaymentRequestCartApi from '../cart-api';
import ExpressCheckoutCartApi from '../cart-api';

jest.mock( '@wordpress/api-fetch', () => jest.fn() );

global.wcpayPaymentRequestParams = {};
global.wcpayPaymentRequestParams.nonce = {};
global.wcpayPaymentRequestParams.nonce.store_api_nonce =
global.wcpayExpressCheckoutParams = {};
global.wcpayExpressCheckoutParams.nonce = {};
global.wcpayExpressCheckoutParams.nonce.store_api_nonce =
'global_store_api_nonce';
global.wcpayPaymentRequestParams.nonce.tokenized_cart_nonce =
global.wcpayExpressCheckoutParams.nonce.tokenized_cart_nonce =
'global_tokenized_cart_nonce';
global.wcpayPaymentRequestParams.nonce.tokenized_cart_session_nonce =
global.wcpayExpressCheckoutParams.nonce.tokenized_cart_session_nonce =
'global_tokenized_cart_session_nonce';
global.wcpayPaymentRequestParams.checkout = {};
global.wcpayPaymentRequestParams.checkout.currency_code = 'USD';
global.wcpayExpressCheckoutParams.checkout = {};
global.wcpayExpressCheckoutParams.checkout.currency_code = 'USD';

describe( 'PaymentRequestCartApi', () => {
describe( 'ExpressCheckoutCartApi', () => {
afterEach( () => {
jest.resetAllMocks();
} );

it( 'should allow to create an anonymous cart for a specific class instance, without affecting other instances', async () => {
global.wcpayPaymentRequestParams.button_context = 'product';
global.wcpayExpressCheckoutParams.button_context = 'product';
const headers = new Headers();
headers.append(
'X-WooPayments-Tokenized-Cart-Session',
Expand All @@ -39,8 +39,8 @@ describe( 'PaymentRequestCartApi', () => {
json: () => Promise.resolve( {} ),
} );

const api = new PaymentRequestCartApi();
const anotherApi = new PaymentRequestCartApi();
const api = new ExpressCheckoutCartApi();
const anotherApi = new ExpressCheckoutCartApi();

api.useSeparateCart();
await api.getCart();
Expand Down Expand Up @@ -120,12 +120,12 @@ describe( 'PaymentRequestCartApi', () => {
} );

it( 'should call `/cart/update-customer` with the global headers if the cart is not anonymous', async () => {
global.wcpayPaymentRequestParams.button_context = 'cart';
global.wcpayExpressCheckoutParams.button_context = 'cart';
apiFetch.mockResolvedValue( {
headers: new Headers(),
json: () => Promise.resolve( {} ),
} );
const api = new PaymentRequestCartApi();
const api = new ExpressCheckoutCartApi();

await api.updateCustomer( {
billing_address: { last_name: 'Last' },
Expand All @@ -150,14 +150,14 @@ describe( 'PaymentRequestCartApi', () => {
} );

it( 'should store received header information for subsequent usage', async () => {
global.wcpayPaymentRequestParams.button_context = 'cart';
global.wcpayExpressCheckoutParams.button_context = 'cart';
const headers = new Headers();
headers.append( 'Nonce', 'nonce-value' );
apiFetch.mockResolvedValue( {
headers,
json: () => Promise.resolve( {} ),
} );
const api = new PaymentRequestCartApi();
const api = new ExpressCheckoutCartApi();

await api.getCart();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ import apiFetch from '@wordpress/api-fetch';
/**
* Internal dependencies
*/
import PaymentRequestOrderApi from '../order-api';
import ExpressCheckoutOrderApi from '../order-api';

jest.mock( '@wordpress/api-fetch', () => jest.fn() );

global.wcpayPaymentRequestParams = {};
global.wcpayPaymentRequestParams.nonce = {};
global.wcpayPaymentRequestParams.nonce.store_api_nonce =
global.wcpayExpressCheckoutParams = {};
global.wcpayExpressCheckoutParams.nonce = {};
global.wcpayExpressCheckoutParams.nonce.store_api_nonce =
'global_store_api_nonce';

describe( 'PaymentRequestOrderApi', () => {
describe( 'ExpressCheckoutOrderApi', () => {
afterEach( () => {
jest.resetAllMocks();
} );

it( 'gets order data with the provided arguments', async () => {
const api = new PaymentRequestOrderApi( {
const api = new ExpressCheckoutOrderApi( {
orderId: '1',
key: 'key_123',
billingEmail: 'cheese@toast.com',
Expand All @@ -40,7 +40,7 @@ describe( 'PaymentRequestOrderApi', () => {
} );

it( 'places an order', async () => {
const api = new PaymentRequestOrderApi( {
const api = new ExpressCheckoutOrderApi( {
orderId: '1',
key: 'key_123',
billingEmail: 'cheese@toast.com',
Expand Down Expand Up @@ -74,7 +74,7 @@ describe( 'PaymentRequestOrderApi', () => {
} );

it( 'places an order with the previous API request data', async () => {
const api = new PaymentRequestOrderApi( {
const api = new ExpressCheckoutOrderApi( {
orderId: '1',
key: 'key_123',
billingEmail: 'cheese@toast.com',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ const ExpressCheckoutComponent = ( {
} );
const onClickHandler = ! isPreview ? onButtonClick : () => {};
const onShippingAddressChange = ( event ) =>
shippingAddressChangeHandler( api, event, elements );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The api argument is no longer needed when changing the shipping address or selecting a shipping rate.

shippingAddressChangeHandler( event, elements );

const onShippingRateChange = ( event ) =>
shippingRateChangeHandler( api, event, elements );
shippingRateChangeHandler( event, elements );

const onElementsReady = ( event ) => {
const paymentMethodContainer = document.getElementById(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { addQueryArgs } from '@wordpress/url';
/**
* Internal dependencies
*/
import { getPaymentRequestData } from './frontend-utils';
import { getExpressCheckoutData } from './utils';

export default class PaymentRequestCartApi {
export default class ExpressCheckoutCartApi {
// Used on product pages to interact with an anonymous cart.
// This anonymous cart is separate from the customer's cart, which might contain additional products.
// This functionality is also useful to calculate product/shipping pricing (and shipping needs)
Expand All @@ -30,23 +30,23 @@ export default class PaymentRequestCartApi {
...options,
parse: false,
path: addQueryArgs( options.path, {
// `wcpayPaymentRequestParams` will always be defined if this file is needed.
// If there's an issue with it, ask yourself why this file is queued and `wcpayPaymentRequestParams` isn't present.
currency: getPaymentRequestData(
// `wcpayExpressCheckoutParams` will always be defined if this file is needed.
// If there's an issue with it, ask yourself why this file is queued and `wcpayExpressCheckoutParams` isn't present.
currency: getExpressCheckoutData(
'checkout'
).currency_code.toUpperCase(),
} ),
headers: {
// the Store API nonce, which could later be overwritten in subsequent requests.
Nonce: getPaymentRequestData( 'nonce' ).store_api_nonce,
Nonce: getExpressCheckoutData( 'nonce' ).store_api_nonce,
// needed for validation of address data, etc.
'X-WooPayments-Tokenized-Cart-Nonce':
getPaymentRequestData( 'nonce' ).tokenized_cart_nonce ||
getExpressCheckoutData( 'nonce' ).tokenized_cart_nonce ||
undefined,
// necessary to validate any request made to the backend from the PDP.
'X-WooPayments-Tokenized-Cart-Session-Nonce':
getPaymentRequestData( 'button_context' ) === 'product'
? getPaymentRequestData( 'nonce' )
getExpressCheckoutData( 'button_context' ) === 'product'
? getExpressCheckoutData( 'nonce' )
.tokenized_cart_session_nonce
: undefined,
...this.cartRequestHeaders,
Expand Down Expand Up @@ -170,7 +170,7 @@ export default class PaymentRequestCartApi {
method: 'POST',
path: '/wc/store/v1/cart/add-item',
data: applyFilters(
'wcpay.payment-request.cart-add-item',
'wcpay.express-checkout.cart-add-item',
productData
),
} );
Expand Down
Loading
Loading