diff --git a/.changeset/kind-zebras-kick.md b/.changeset/kind-zebras-kick.md new file mode 100644 index 000000000..2aa53691a --- /dev/null +++ b/.changeset/kind-zebras-kick.md @@ -0,0 +1,5 @@ +--- +"shopify-buy": patch +--- + +Update checkout.webUrl to use the same domain for checkout as shopify-buy v2 diff --git a/DEPLOYING.md b/DEPLOYING.md index 7d190f796..4d00082d3 100644 --- a/DEPLOYING.md +++ b/DEPLOYING.md @@ -1,12 +1,36 @@ # Deploying JS Buy SDK -1. Merge your branch into main -2. Run `npm version [patch|minor|major]` which will do the following: - * write new version to package.json - * create a commit with a commit message matching the version number - * create a new tag matching the version number -3. Push the new commit and tags to main with `git push && git push --tags` -4. Deploy built scripts to s3 via [shipit](https://shipit.shopify.io/shopify/js-buy-sdk/production) +### 1. Make your desired changes + + +### 2. Then run + +``` +npx changeset add +``` + +### 3. Commit your changes (manually) using git. + +**Do NOT bump the version manually in `package.json`.** + +### 4. Push your changes +``` +git push +``` + +### 5. Create a PR and merge it into `main` + +This will automatically: +- Bump the version in `package.json` +- Create the tag in GitHub for the new version +- Publish the new version to npm + +### 6. Deploy via [Shipit](https://shipit.shopify.io/shopify/js-buy-sdk/production) + +Merging the PR will automatically publish the new version to npm, but the Shipit deploy is necessary to publish the new version to Shopify's CDN. + +Press "Deploy" next to your changes once CI has passed, read and tick off the checkbox once you have read and verified the instructions, and create the deploy. Monitor it and verify it succeeds. + # Updating Documentation diff --git a/README.md b/README.md index 3ba7077bf..3344ee761 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ npm install shopify-buy@3 **With Yarn:** ```bash -yarn install shopify-buy@3 +yarn add shopify-buy@3 ``` **CDN:** diff --git a/src/cart-payload-mapper.js b/src/cart-payload-mapper.js index a98df31fa..f7806c8c1 100644 --- a/src/cart-payload-mapper.js +++ b/src/cart-payload-mapper.js @@ -76,6 +76,22 @@ export function mapCartPayload(cart) { subtotalPrice = calculateSubtotalPrice(totalPrice, totalDutyAmount, totalTaxAmount); } + let webUrl = cart.checkoutUrl; + + if (webUrl) { + try { + const url = new URL(webUrl); + + if (!url.searchParams.has('_fd') || url.searchParams.get('_fd') !== '0') { + url.searchParams.set('_fd', '0'); + webUrl = url.toString(); + } + } catch (error) { + // If URL parsing fails, return the original URL unchanged + // rather than risk breaking the checkout flow + } + } + const checkoutPayload = Object.assign({ appliedGiftCards, buyerIdentity, @@ -98,7 +114,7 @@ export function mapCartPayload(cart) { totalTax: totalTaxAmount || getDefaultMoneyObject(currencyCode, totalAmount), totalTaxV2: totalTaxAmount || getDefaultMoneyObject(currencyCode, totalAmount), updatedAt: cart.updatedAt, - webUrl: cart.checkoutUrl + webUrl }, UNSUPPORTED_FIELDS); normalizeCartMoneyFieldDecimalPlaces(checkoutPayload); diff --git a/test/cart-payload-mapper-test.js b/test/cart-payload-mapper-test.js index 3690f1252..757e471b0 100644 --- a/test/cart-payload-mapper-test.js +++ b/test/cart-payload-mapper-test.js @@ -471,13 +471,63 @@ suite('cart-payload-mapper-test', () => { }); suite('webUrl', () => { - test('it returns checkout URL', () => { + test('it returns checkout URL, with _fd=0 appended if not present', () => { const cart = { checkoutUrl: 'https://shop.com/checkout' }; const result = mapCartPayload(cart); + assert.strictEqual(result.webUrl, `${cart.checkoutUrl}?_fd=0`); + }); + + test('it gracefully handles invalid URLs by returning them unchanged', () => { + const cart = { + checkoutUrl: 'invalid' + }; + + const result = mapCartPayload(cart); + + assert.strictEqual(result.webUrl, cart.checkoutUrl); + }); + + test('it does not duplicate the query param _fd=0 if it is already present', () => { + const cart = { + checkoutUrl: 'https://shop.com/checkout?_fd=0' + }; + + const result = mapCartPayload(cart); + + assert.strictEqual(result.webUrl, cart.checkoutUrl); + }); + + test('it updates the value of _fd to 0 if it is present but with a different value', () => { + const cart = { + checkoutUrl: 'https://shop.com/checkout?_fd=1' + }; + + const result = mapCartPayload(cart); + + assert.strictEqual(result.webUrl, 'https://shop.com/checkout?_fd=0'); + }); + + test('it adds _fd=0 while preserving other query params', () => { + const cart = { + checkoutUrl: 'https://shop.com/checkout?foo=bar&baz=qux' + }; + + const result = mapCartPayload(cart); + + assert.strictEqual(result.webUrl, 'https://shop.com/checkout?foo=bar&baz=qux&_fd=0'); + }); + + test('it returns the original URL unchanged if it contains a _fd=0 query param along with other query params', () => { + const cart = { + checkoutUrl: 'https://shop.com/checkout?foo=bar&_fd=0&baz=qux' + }; + + const result = mapCartPayload(cart); + assert.strictEqual(result.webUrl, cart.checkoutUrl); }); }); diff --git a/test/client-checkout-integration-test.js b/test/client-checkout-integration-test.js index db98585a1..ce91bf64a 100644 --- a/test/client-checkout-integration-test.js +++ b/test/client-checkout-integration-test.js @@ -217,6 +217,16 @@ suite('client-checkout-integration-test', () => { }); }); }); + + test('it appends _fd=0 to the checkout URL if it is not present', () => { + return client.checkout.create({}).then((checkout) => { + return client.checkout.fetch(checkout.id).then((updatedCheckout) => { + const checkoutUrl = new URL(updatedCheckout.webUrl); + + assert.strictEqual(checkoutUrl.searchParams.get('_fd'), '0'); + }); + }); + }); }); suite('payload fields verification', () => {