Skip to content

fix(rest/python): deliver the order object as the webhook body#140

Merged
damaz91 merged 3 commits into
Universal-Commerce-Protocol:mainfrom
vishkaty:fix/webhook-order-body
Jul 23, 2026
Merged

fix(rest/python): deliver the order object as the webhook body#140
damaz91 merged 3 commits into
Universal-Commerce-Protocol:mainfrom
vishkaty:fix/webhook-order-body

Conversation

@vishkaty

Copy link
Copy Markdown
Contributor

Fixes #135.

What

The order webhook (orderEvent in source/services/shopping/rest.openapi.json)
defines its request body as {"$ref": "order"} — the delivered body must be an
order object. The Python server instead posted a custom envelope
{event_type, checkout_id, order}, and posted it even when there was no order
(body null).

This posts the order object as the JSON body, carries the event type in an
X-Event-Type header (the reporter's own suggestion), and skips delivery when
there is no order — so the body is always a valid order.

Tests

Adds two tests to integration_test.py that capture the delivered webhook
request (httpx.AsyncClient stubbed by a capturing fake, driven through a real
create+complete):

  • test_webhook_delivers_the_bare_order_as_body — exactly one POST; body passes
    Order.model_validate() with all required top-level fields
    (ucp, id, checkout_id, permalink_url, line_items, fulfillment, currency, totals);
    no event_type/nested-order envelope keys; event type in X-Event-Type.
  • test_webhook_is_skipped_when_there_is_no_order — no delivery when order absent.

Both fail on the old envelope and pass on the fix.

Verification

  • Full suite green on latest: 9 passed (7 existing + 2 new), zero regression.
  • ruff check + ruff format --check clean; pre-commit run all hooks pass.

Note: the Node.js sample has the same envelope in rest/nodejs/src/api/checkout.ts;
this PR scopes only the Python server per the issue — happy to send a parallel
Node.js fix if useful.

The order webhook (orderEvent) is defined in rest.openapi.json with a request
body of $ref: order — the delivered body must be an order object. The server
instead posted a custom envelope {event_type, checkout_id, order}, and posted it
even when there was no order (body = null).

Post the order object as the JSON body, carry the event type in an X-Event-Type
header (per the reporter's suggestion), and skip delivery when there is no order.

Adds two tests that capture the delivered request: the body validates as an
Order with all required top-level fields and no envelope keys, the event type is
in X-Event-Type, and no delivery occurs without an order. Fixes Universal-Commerce-Protocol#135.
@damaz91 damaz91 added status:needs-triage Signal that the PR is ready for human triage status:under-review and removed status:needs-triage Signal that the PR is ready for human triage labels Jul 22, 2026
@damaz91

damaz91 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Approved. I'll make sure conformance test suite is also update to support this change before merging.

@damaz91

damaz91 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

I included the changes in Universal-Commerce-Protocol/conformance#63 - we can merge both at the same time once approved

Resolves conflicts in rest/python/server/integration_test.py.

TAG=agy
CONV=f0d818cd-0531-40ee-880f-865ddf2b2a5f
@damaz91
damaz91 requested a review from carolinerg1 July 23, 2026 11:39
Comment thread rest/python/server/integration_test.py Outdated
Address review comment suggesting using respx to simplify mocking of httpx.
Removed custom _CapturingAsyncClient and updated _notify_and_capture to use respx.mock.

TAG=agy
CONV=94ff3e71-a493-4097-9827-22e9aeda899c
@damaz91
damaz91 merged commit f59d963 into Universal-Commerce-Protocol:main Jul 23, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Python server's webhook payload doesn't match the canonical orderEvent shape

4 participants