Presenting a payment form without a complete order summary — line items, shipping cost, tax amount, and final total — violates the reasonable expectation of informed consent before a financial transaction. ISO 25010:2011 functional correctness requires that the system accurately communicate what the user is authorizing. CWE-20 applies when placeholder values ("TBD", "$0.00") appear in tax or shipping fields: the user authorizes an amount they cannot verify, which leads to chargebacks, disputes, and loss of trust. Regulatory guidance in many jurisdictions (EU Consumer Rights Directive, FTC rules) also requires clear pre-payment disclosure of total charges.
Critical because a user who pays without seeing a complete summary can claim they did not authorize the actual charge, triggering chargebacks and regulatory exposure.
Add a review step at src/components/OrderReview.tsx and render it before the payment form — not after. The component must display all four fields computed from live cart data:
// src/components/OrderReview.tsx
function OrderReview({ cart, shipping, tax, total }: OrderReviewProps) {
const subtotal = cart.reduce((sum, i) => sum + i.lineTotal, 0)
return (
<section>
{cart.map(item => (
<div key={item.id}>{item.name} x{item.quantity} — ${(item.lineTotal/100).toFixed(2)}</div>
))}
<p>Shipping: ${(shipping/100).toFixed(2)}</p>
<p>Tax: ${(tax/100).toFixed(2)}</p>
<p><strong>Total: ${(total/100).toFixed(2)}</strong></p>
</section>
)
}
Never render "TBD" or $0.00 for shipping or tax when real values are computable; fetch shipping and tax estimates as soon as an address is entered.
ID: ecommerce-cart-ux.checkout-flow.pre-payment-review
Severity: critical
What to look for: Count all 4 required summary fields: (1) line items with name, quantity, and price, (2) shipping cost or method, (3) tax amount, (4) final total including all charges. Find the pre-payment review component or page and enumerate which of the 4 fields are displayed. Quote the component name and file path. Verify this summary appears before (not after) the payment submission action.
Pass criteria: A summary is shown before the payment step containing at least 4 of 4 required fields: line items, shipping cost, tax amount, and final total. All amounts must be computed from actual cart data, not hardcoded placeholder values. Report: "Pre-payment summary at [component/path] displays X of 4 required fields."
Fail criteria: No summary is shown before payment, or fewer than 4 of 4 required fields are displayed (e.g., missing tax or shipping cost).
Do NOT pass when: A summary exists but shows "TBD" or "$0.00" placeholders for tax or shipping — placeholder values are not a real summary.
Skip (N/A) when: The project has no checkout flow or payment processing.
Detail on fail: Example: "Payment form at src/app/checkout/payment/page.tsx is presented immediately after address entry. No order summary component exists. 0 of 4 required summary fields shown before payment."
Cross-reference: For cart total accuracy, see the cart-totals check in Cart Management. For confirmation page content after payment, see the confirmation-page check in Order Summary & Confirmation.
Remediation: Add a review step component at src/components/OrderReview.tsx and render it before the payment form:
// src/components/OrderReview.tsx
function OrderReview({ cart, shipping, tax, total }) {
return (
<div className="review">
<h2>Review Your Order</h2>
<section>
<h3>Items</h3>
{cart.map(item => (
<div key={item.id}>
<p>{item.name} x {item.quantity}</p>
<p>${(item.lineTotal / 100).toFixed(2)}</p>
</div>
))}
</section>
<section>
<p>Subtotal: ${(cart.reduce((sum, i) => sum + i.lineTotal, 0) / 100).toFixed(2)}</p>
<p>Shipping: ${(shipping / 100).toFixed(2)}</p>
<p>Tax: ${(tax / 100).toFixed(2)}</p>
<p className="total">Total: ${(total / 100).toFixed(2)}</p>
</section>
</div>
)
}