When the cart page computes tax inline as subtotal * 0.085 while the checkout page calls getTaxAmount(), and the order creation API passes a different address to a third calculation, a customer who sees $8.50 in the cart arrives at checkout and sees $8.75 — a difference that reads as a pricing error and triggers abandonment or disputes. CWE-682 (Incorrect Calculation) applies when multiple call sites produce divergent values for the same input. ISO 25010:2011 functional correctness requires that the same cart contents and address produce the same tax amount at every display point. Inconsistency is especially damaging during the payment step: customers read the discrepancy as evidence the system is untrustworthy.
High because tax amount discrepancies between cart and checkout are immediately visible to customers and create the impression of a bait-and-switch, driving abandonment at the payment step.
Consolidate all tax display call sites onto a single getTaxAmount function in lib/tax.ts:
// lib/tax.ts — single source of truth, called from all pages
export function getTaxAmount(
items: OrderItem[],
address: Address,
customerIsExempt = false
): number {
if (customerIsExempt) return 0
const taxable = items
.filter(i => !i.is_tax_exempt)
.reduce((sum, i) => sum + i.price * i.quantity, 0)
const rate = getTaxRate(address)
return Math.round(taxable * rate)
}
// Usage on cart page:
const tax = getTaxAmount(cart.items, shippingAddress, user?.is_tax_exempt)
// Same call on checkout page:
const tax = getTaxAmount(cart.items, shippingAddress, user?.is_tax_exempt)
// Same call in order creation API route:
const tax = getTaxAmount(items, address, customer.is_tax_exempt)
Delete any inline subtotal * constant tax expressions scattered across component files and replace with this import. Confirm in a unit test that all three call sites return identical values for the same inputs.
ID: ecommerce-shipping-tax.checkout-integration.tax-consistency
Severity: high
What to look for: Count the number of distinct tax calculation call sites across the checkout flow: cart summary, checkout page, order creation API, confirmation page. For each call site, extract and quote the function call or calculation. Classify whether all call sites use the same calculation function or if different logic exists.
Pass criteria: All tax display locations (at least 3: cart, checkout, and confirmation) call the same tax calculation function or API endpoint, ensuring the tax amount is identical for the same cart contents and address across all pages.
Fail criteria: At least 2 call sites use different tax calculation logic, or tax amounts differ between cart and checkout for identical cart contents and address.
Skip (N/A) when: The business does not collect sales tax (no tax calculation logic exists).
Detail on fail: "3 tax calculation call sites found. Cart uses inline calculation (subtotal * 0.085), checkout uses getTaxAmount() function, confirmation re-reads from order record. Cart and checkout produce different values for same cart." or "Tax displayed in cart ($8.50) differs from checkout ($8.75) for identical items."
Remediation: Ensure consistent tax calculation in lib/tax.ts called from all pages:
// Use same function throughout checkout
function getTaxAmount(items: OrderItem[], address: Address, exempt: boolean = false): number {
if (exempt) return 0
const rate = getTaxRate(address)
const taxable = items.filter(i => !i.is_tax_exempt).reduce((sum, i) => sum + i.price * i.quantity, 0)
return Math.round(taxable * rate)
}
// Call same function on cart page, checkout page, and confirmation
const tax = getTaxAmount(cart.items, shippingAddress, customer.is_tax_exempt)