Skip to content

A v3 item in a v1 basket is accepted and silently stored as 0.0000 #16

Description

@sveneberth

Basket and BasketItem decide their schema independently and nothing checks that they agree:

  • Basket.isV3() is totalValueGross is not None — and it also picks the endpoint, /v1/baskets vs /v3/baskets.
  • BasketItem.isV3() is amountPerUnitGross is not None or amountDiscountPerUnitGross is not None.

Measured against the sandbox, all four combinations:

Basket Item Result
v1 v1 stored correctly
v3 v3 stored correctly
v3 v1 refused, API.600.410.051
v1 v3 201, and every item amount stored as 0.0000

The dangerous one in full — sent:

{"basketItemReferenceId": "i", "quantity": 1, "vat": 19, "amountPerUnitGross": 907.8,
 "amountDiscountPerUnitGross": 90.78}

read back:

{"basketItemReferenceId": "i", "quantity": 1, "vat": 19.0, "amountDiscount": 0.0,
 "amountGross": 0.0, "amountVat": 0.0, "amountPerUnit": 0.0, "amountNet": 0.0}

The basket-level total survives (it is a v1 field and was set), so the basket looks right at a glance and every line is worth nothing. A payment method that renders the basket to the customer shows a cart full of zero-priced items against a non-zero invoice.

Reaching this needs no exotic code: Basket(amountTotalGross=…, basketItems=[BasketItem(amountPerUnitGross=…)]). BaseModel.__init__ swallowing unknown kwargs (#17) makes it easier still, since a mistyped v1 field leaves the item looking v3.

Basket's docstring already says "don't mix the schemas within one basket", which is exactly the kind of rule validateBeforeRequest() exists to enforce — and unlike a returnUrl blocklist it encodes nothing that Unzer could relax later, since the two schemas are mutually exclusive by construction.

Suggested: refuse in Basket.serialize() (or validateBeforeRequest) when self.isV3() disagrees with any item's isV3(), naming the item.

Related, from the same measurements: a basket is only readable through the schema it was created with (API.600.410.024 otherwise), and the ids differ visibly — v1 gives s-bsk-72, v3 gives a UUID.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions