Two shipping charges in a mixed basket can come from the configuration rather than duplicate execution. Define the intended basket behaviour before asking a developer to remove the second charge. This resource helps merchants brief shipping work; it does not quote carrier prices or certify a particular store.
Read the actual configuration model
Shopify documents combined rates across shipping profiles and a flat-rate exception within one profile and location group. The documentation, checked on 16 October 2026, also describes migration towards shipping options by market. First identify which model your store actually uses. The fixture below covers legacy profiles and fixed rates only.
Filled basket matrix
Synthetic inputs in AUD: small accessories use profile P1 at $8 standard shipping; fragile fittings use P2 at $14. A separate control uses one profile and one location group with a shared $9 flat rate. These are invented configuration amounts, not market rates.
On narrow screens, scroll sideways to read the full table.
| Test basket | Configuration | Expected shipping | Interpretation |
|---|---|---|---|
| Accessories only | P1 | 8 | Single profile control |
| Fittings only | P2 | 14 | Second profile control |
| Accessory + fitting | P1 + P2 | 8 + 14 = 22 | Combined separate profiles |
| Two shipments, same flat group | One profile, one group | $9 once | Do not apply $9 twice |
| Carrier/app-calculated basket | Outside fixture | Unknown | Obtain a real checkout quote |
Compare native settings with extra logic
If $22 matches the intended separate handling, explain that rule before payment. If the commercial promise is one $9 charge, first check whether the product/profile design can express it natively. Use an app or custom quotation only when an independently required rule cannot be represented and the supplier can demonstrate it. A custom rule must not conceal a charge that the merchant still intends to collect later.
Repeatable checkout test
- Freeze a test address, quantities, currency and stock location for each row.
- Record profile IDs, location group, rate names and whether a rate is flat, weight-based, carrier-calculated or app supplied.
- Compare basket summary and final checkout; preserve the observed rate name and amount.
- Repeat after adding and removing each product. A failed $9 control should be investigated before changing any public promise.
What the supplier must hand over
Require a basket-to-rule map, observed screenshots or redacted response records, expected totals and unresolved exceptions. This makes an apparent double charge reproducible. Different rate names, stock routing, weights and market migration can change the result; the offline sum alone cannot establish the live outcome.
Scope boundary
The matrix excludes tax, duties, discounts, return freight and live carrier rates. It is a configuration test, not legal advice or a price guarantee. Reverse logistics needs a separate receipt/refund/restock handover: continue with the ecommerce returns and 3PL handover scenario when that is the next task.
Replay the teaching example
These files run locally without network access. They model only the stated cases, not a live vendor integration. Filled inputs and expected results · Inspectable teaching functions
Save both files in one folder. With Node 22.13 or newer, run:
node decision-check.mjs mixed-cart-shipping-contract.json