payloadcms / payloadcms/payload
[plugin-ecommerce] Cart items with a variant skip stock and price validation in initiatePayment
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 44.8k
- Forks
- 4.2k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 53
Description
Describe the Bug
In initiatePayment, the validation block for variants can never run. The outer condition excludes items that have a variant, but the variant check is nested inside it:
if (item.product && !item.variant) {
// product is fetched and validated here
if (item.variant) {
// variant is fetched and validated here — unreachable,
// the outer branch requires !item.variant
}
}
(initiatePayment.ts lines 201 and 253 at v3.88.0)
As a result, any cart item that carries a variant reaches the payment adapter with no stock check and no price-field check. With inventory tracking enabled, a variant with inventory 2 can be bought in any quantity. In our reproduction the request then failed inside the payment adapter with HTTP 500, so the customer sees a server error instead of the out-of-stock message, and with a live key the payment would proceed.
A related observation in the same area: confirmOrder destructures productsValidation from its arguments but never calls it.
The amount itself comes from the server-side cart subtotal, so we did not find a way for a client to influence the charged price through this path — it appears to be a correctness and availability defect, not a price-manipulation one.
Link to the code that reproduces this issue
https://github.com/payloadcms/payload/blob/v3.88.0/packages/plugin-ecommerce/src/endpoints/initiatePayment.ts#L201-L253 — reproduced on the official ecommerce template with no modifications.
Reproduction Steps
- Start the official ecommerce template with
@payloadcms/plugin-ecommerce3.88.0, inventory tracking on, Stripe test keys. - Create a product with variants; give one variant inventory 2.
- As a customer, add 5 of that variant to the cart and call
initiatePayment. - Expected: HTTP 400 with
OutOfStock. Actual: validation is skipped and the request reaches the payment adapter; with a Stripe test key it returns HTTP 500. - Control case: the same flow on a product without a variant and inventory 2 correctly returns HTTP 400.
Which area(s) are affected?
plugin: ecommerce
Environment Info
Payload 3.88.0
@payloadcms/plugin-ecommerce 3.88.0
Node 22
PostgreSQL 17.10 (also observed on MongoDB)
Official ecommerce template
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/plugin-ecommerce/src/endpoints/initiatePayment.ts around lines 201-253 and reproduce the variant-cart flow described against the official ecommerce template. Confirm that an over-quantity variant returns HTTP 400 with OutOfStock, while the control product path continues to validate correctly; also inspect the nearby confirmOrder productsValidation observation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend, payments
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100