Skip to content

[B2BTEAM-3732] Forward priceToken on addToCart (Pricing Fallback V2) - #185

Draft
wender wants to merge 1 commit into
masterfrom
feature/B2BTEAM-3732_forward-price-token-on-add-to-cart
Draft

[B2BTEAM-3732] Forward priceToken on addToCart (Pricing Fallback V2)#185
wender wants to merge 1 commit into
masterfrom
feature/B2BTEAM-3732_forward-price-token-on-add-to-cart

Conversation

@wender

@wender wender commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do? *

Pricing Fallback V2 (B2BTEAM-3732): captures the signed price returned by the search (items[].sellers[].commertialOffer.PriceToken) and forwards it as priceToken in the addToCart payload, so the Checkout can close the cart with that price even while the Pricing is unavailable.

  • react/queries/product.gql and react/queries/productsByCategory.gql now request commertialOffer { PriceToken } under sellers.
  • AutocompleteBlock captures the token of the default seller both on onSelect (single-SKU product) and on selectSku (SKU switch), and sends it on callAddUnitToCart.
  • CategoryBlock keeps a priceTokens map by SKU, filled when the quantity is set, and sends it on callAddToCart.

Two deliberate choices:

  • The token is read from the seller that is actually sent. In CategoryBlock the seller sent to the cart may be the sellerDefault or the first one in the list (pre-existing fallback), so the token is looked up by the already resolved sellerId instead of assuming the default — otherwise we could sign the price of a different seller than the one added to the cart.
  • priceToken is only added to the payload when the search returns one (conditional spread). While the field is not exposed, the payload is exactly the same as today, and the same applies if ItemInput on vtex.checkout-graphql does not accept priceToken yet.

How to test it? *

Requires an account where CommertialOffer.PriceToken is exposed by vtex.search-graphql and the feature flag is enabled (e.g. storeframework).

  1. vtex link the app and open a page with quickorder.autocomplete.
  2. Select a product and inspect the product query response — sellers[].commertialOffer.PriceToken should be present.
  3. Add it to the cart and inspect the addToCart mutation payload — the item should carry priceToken alongside id, quantity and seller.
  4. For a multi-SKU product, switch the SKU tag before adding and confirm the token belongs to the newly selected SKU.
  5. Repeat on a page with quickorder.category, including a product whose seller comes from the fallback (no sellerDefault), and confirm the token matches the seller that was sent.
  6. Regression: on an account without the field exposed, both blocks must keep working with no priceToken in the payload.

Describe alternatives you've considered, if any. *

  • Fetching the token in a separate, error-tolerant query, so a schema mismatch could not break the product lookup. Dropped in favour of the simpler final shape, at the cost of the blocker below.
  • Gating the field behind a public app setting. Dropped to avoid shipping a setting that would have to be removed later.

Related to / Depends on *

Blocked — do not merge yet. CommertialOffer.PriceToken is not exposed on search-resolver/search-graphql yet. Since the field is requested directly in the queries, on any account where it is missing the GraphQL validation rejects the whole document and the product lookup of AutocompleteBlock/CategoryBlock stops working. This can only be merged once the field is exposed.

Out of scope, to be handled in a follow-up: TextAreaBlock and UploadBlock resolve SKUs through this app's own skuFromRefIds resolver (node/resolvers/search/index.ts), which relies on stockkeepingunitidsbyrefids + Checkout simulation — neither returns PriceToken. Covering them needs a Catalog Search API call in node, a new field on ItemsSeller (graphql/types/Refids.graphql), a new outbound-access policy and propagation through ReviewBlock.

Open question for the Checkout team: the token is valid for 30 minutes and cannot be renewed. In CategoryBlock it is captured when the category is opened, so a user browsing for a long time may send an expired token. Worth confirming whether an expired token is ignored (falling back to the Pricing) or returns an error — in the latter case the search would have to be repeated before adding to the cart.

Pricing Fallback V2: fetch the signed price (commertialOffer.PriceToken)
in the search-graphql product queries and forward it as priceToken in the
addToCart payload, so the Checkout can close the cart while the Pricing is
unavailable.

Covers AutocompleteBlock and CategoryBlock. TextAreaBlock and UploadBlock
resolve SKUs through the app's own skuFromRefIds resolver, which has no
access to the token, and are left for a follow-up.

The token is only added to the payload when the search actually returns
one, keeping the payload unchanged while the field is not exposed yet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vtex-io-ci-cd

vtex-io-ci-cd Bot commented Jul 30, 2026

Copy link
Copy Markdown

Hi! I'm VTEX IO CI/CD Bot and I'll be helping you to publish your app! 🤖

Please select which version do you want to release:

  • Patch (backwards-compatible bug fixes)

  • Minor (backwards-compatible functionality)

  • Major (incompatible API changes)

And then you just need to merge your PR when you are ready! There is no need to create a release commit/tag.

  • No thanks, I would rather do it manually 😞

@vtex-io-docs-bot

Copy link
Copy Markdown

Beep boop 🤖

I noticed you didn't make any changes at the docs/ folder

  • There's nothing new to document 🤔
  • I'll do it later 😞

In order to keep track, I'll create an issue if you decide now is not a good time

  • I just updated 🎉🎉

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.

1 participant