Skip to content

feat(betterzeriya): add Universal Commerce Protocol (UCP) checkout endpoints#21

Open
nakasyou wants to merge 1 commit intomainfrom
codex/implement-google-ucp-for-betterzeriya
Open

feat(betterzeriya): add Universal Commerce Protocol (UCP) checkout endpoints#21
nakasyou wants to merge 1 commit intomainfrom
codex/implement-google-ucp-for-betterzeriya

Conversation

@nakasyou
Copy link
Copy Markdown
Member

@nakasyou nakasyou commented May 8, 2026

Motivation

  • Provide a simple Google UCP (Universal Commerce Protocol) implementation so external partners can discover and initiate checkouts against betterzeriya.
  • Offer an in-memory checkout session flow (create / inspect / complete) to support UCP REST checkout bindings for development and integration.

Description

  • Add an in-memory UCP session store and helpers in apps/betterzeriya/src/lib/server/ucp.ts with createUcpCheckoutSession, getUcpCheckoutSession, and completeUcpCheckoutSession.
  • Expose a discovery endpoint at /.well-known/ucp (apps/betterzeriya/src/routes/.well-known/ucp/+server.ts) that advertises the dev.ucp.shopping.checkout capability and a REST binding with base_url: /api/ucp.
  • Implement POST /api/ucp/checkout-sessions (apps/betterzeriya/src/routes/api/ucp/checkout-sessions/+server.ts) to validate line_items, create a UCP checkout session, and return checkout_url and status_url.
  • Implement GET and POST on /api/ucp/checkout-sessions/:id (apps/betterzeriya/src/routes/api/ucp/checkout-sessions/[id]/+server.ts) to fetch session status and to mark a session completed, returning 404 for unknown IDs.
  • Update dependency lockfile (bun.lock) as part of environment runs.

Testing

  • Ran bun run test, which succeeded: 7 test files, 24 tests passed.
  • Ran bun check:fix, which failed in this environment due to a TypeScript/Vite config runtime mismatch when loading vite.config.ts, causing formatting to be skipped.

Codex Task

Copilot AI review requested due to automatic review settings May 8, 2026 03:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a basic Universal Commerce Protocol (UCP) discovery document and REST checkout-session endpoints to betterzeriya, backed by an in-memory session store for development/integration flows.

Changes:

  • Introduces an in-memory UCP checkout session store with create/get/complete helpers.
  • Adds UCP discovery at /.well-known/ucp advertising a REST binding under /api/ucp.
  • Implements POST /api/ucp/checkout-sessions and GET/POST /api/ucp/checkout-sessions/:id endpoints.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
bun.lock Lockfile update from environment runs.
apps/betterzeriya/src/lib/server/ucp.ts Adds in-memory UCP checkout session storage and helpers.
apps/betterzeriya/src/routes/.well-known/ucp/+server.ts Adds UCP capability discovery endpoint.
apps/betterzeriya/src/routes/api/ucp/checkout-sessions/+server.ts Adds endpoint to create UCP checkout sessions and return URLs.
apps/betterzeriya/src/routes/api/ucp/checkout-sessions/[id]/+server.ts Adds endpoints to fetch and complete a checkout session by ID.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +17 to +22

return json(
{
checkout_session: session,
checkout_url: `${url.origin}/sessions/${session.id}`,
status_url: `${url.origin}/api/ucp/checkout-sessions/${session.id}`,
Comment on lines +4 to +15
export const POST: RequestHandler = async ({ request, url }) => {
const body = await request.json().catch(() => null)
const lineItems = body?.line_items

if (!Array.isArray(lineItems) || lineItems.length === 0) {
return json({ error: 'line_items is required' }, { status: 400 })
}

const session = createUcpCheckoutSession({
line_items: lineItems,
buyer: body?.buyer,
currency: body?.currency,
Comment on lines +30 to +57
const sessions = new Map<string, UcpCheckoutSession>()

export const createUcpCheckoutSession = (input: CreateCheckoutSessionInput) => {
const now = new Date().toISOString()
const session: UcpCheckoutSession = {
id: crypto.randomUUID(),
status: 'requires_action',
currency: input.currency ?? 'JPY',
buyer: input.buyer,
line_items: input.line_items,
created_at: now,
updated_at: now,
}
sessions.set(session.id, session)
return session
}

export const getUcpCheckoutSession = (id: string) => sessions.get(id)

export const completeUcpCheckoutSession = (id: string) => {
const session = sessions.get(id)
if (!session) return undefined
const updated = {
...session,
status: 'completed' as const,
updated_at: new Date().toISOString(),
}
sessions.set(id, updated)
@otnc otnc self-requested a review May 8, 2026 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants