Skip to content

feat(kit): add read-only order lookup - #285

Merged
hyochan merged 2 commits into
mainfrom
feat/kit-order-lookup
Aug 5, 2026
Merged

hyochan merged 2 commits into
mainfrom
feat/kit-order-lookup

Conversation

@hyochan

@hyochan hyochan commented Aug 5, 2026 •

Copy link
Copy Markdown
Member

Closes #284 (feature request from @LukasB-DEV).

Summary

  • Support tooling for customer inquiries: paste an Apple or Google order ID from a customer's receipt and IAPKit returns the full order, plus the current subscription status for subscription orders
  • Uses the store credentials each project already configured for verification — no new setup for most projects
  • Read-only and stateless: lookups are proxied live to the store APIs and nothing is persisted or logged

Changes

Backend (packages/kit/convex/orders/)

  • lookupOrder action gated on dashboard session + organization membership. It never accepts an API key — this is operator tooling, not part of the public /api/v1 surface.
  • Apple: App Store Server API lookUpOrderId, with each signed transaction verified through the same SignedDataVerifier path receipt verification already uses, then an optional getAllSubscriptionStatuses fetch.
  • Google: androidpublisher.orders.get, then an optional purchases.subscriptionsv2.get for subscription line items.
  • Optional subscription fetches never invalidate the order result; a failure surfaces as a technical notice, per the request's spec.
  • Pure mappers and validators live in shared.ts with unit tests.

Dashboard (Orders tab)

Summary, transaction identifiers, payment & subscription status, and collapsible raw payloads, with the status colors from the request. The Google purchase token is masked by default with explicit Show / Copy actions.

Docs

New Order lookup section in the IAPKit backend guide (credentials, Apple production-only + App Apple ID requirement, Play View financial data permission, privacy note) and a capability bullet in the kit README.

Correctness notes

These came out of the review rounds and are the parts most worth a reviewer's eye:

  • Apple subscription status is matched by originalTransactionId across every subscription group. getAllSubscriptionStatuses returns all of the customer's subscriptions, so taking the first entry would report an unrelated subscription's state as this order's — actionable misinformation in a support tool.
  • Status is only fetched for auto-renewable orders. Every Apple transaction carries an originalTransactionId (it equals transactionId for one-time purchases), so gating on that alone fired the request — and rendered a failure notice — for consumable orders.
  • App Apple ID is preflighted. Order lookup always targets production, and SignedDataVerifier refuses to construct for production without it; without the preflight a normal sandbox-first project got Unknown verification error from deep inside JWS verification.
  • Apple order IDs are charset-validated before use: the library concatenates the value straight into the request path with no percent-encoding.
  • Errors are ConvexError so their guidance survives Convex's production redaction of plain Error messages, and the dashboard unwraps ReceiptVerificationError's JSON envelope rather than printing it verbatim.

Test plan

  • bun run lint (tsc + convex typecheck + eslint)
  • bun run test — 913 tests pass (13 new, covering the two selection helpers that carried the subtlest bugs)
  • bun run smoke:server
  • docs tsc + vite build, bun run audit:docs clean
  • Manual verification against a real project's store credentials (maintainer)

Four review-self rounds converged: 13 findings (1 high, 5 medium, 7 low) fixed, final round clean.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a beta Orders section to project dashboards.
    • Added read-only order lookup for Apple App Store and Google Play order IDs.
    • Displays order details, transaction identifiers, subscription status, and raw store responses.
    • Supports masked purchase tokens with reveal and copy controls.
    • Lookup results are not stored.
    • Provides guidance for missing orders, configuration issues, and subscription lookup notices.
  • Documentation

    • Added setup, credential, platform requirement, and order lookup guidance.
    • Updated SEO keywords for order lookup.

Support tooling requested in discussion #284: paste an Apple or Google
order ID from a customer's receipt and get the full order plus, for
subscription orders, the current subscription status.

Backend (convex/orders):
- lookupOrder action, dashboard-session + org-membership only — never
  an API key, since this is operator tooling rather than public API
- Apple: App Store Server API lookUpOrderId, signed transactions
  verified through the same SignedDataVerifier path receipt
  verification uses, then optional getAllSubscriptionStatuses
- Google: androidpublisher orders.get plus optional subscriptionsv2
- Reuses the credentials each project already configured; nothing is
  persisted and no lookup is logged
- Optional subscription fetches never invalidate the order result;
  their failure surfaces as a technical notice

Dashboard: Orders tab with summary, transaction identifiers, payment
and subscription status, and collapsible raw payloads. The Google
purchase token is masked with explicit Show and Copy actions.

Correctness details worth noting:
- The Apple subscription status is matched by originalTransactionId
  across every subscription group. Taking the first entry would report
  an unrelated subscription for customers holding several.
- Apple status is only fetched for auto-renewable orders. Every Apple
  transaction carries an originalTransactionId, so gating on that
  alone fired the request for consumables too.
- Order lookup always runs against production, which SignedDataVerifier
  refuses without the App Apple ID, so that is preflighted with an
  actionable message instead of failing deep inside JWS verification.
- Apple order IDs are charset-validated: the client concatenates the
  value straight into the request path without percent-encoding.
- Errors are ConvexError so their guidance survives Convex's production
  redaction, and the dashboard unwraps ReceiptVerificationError's JSON
  envelope instead of printing it.

Docs: new Order lookup section in the IAPKit backend guide covering
credentials, the Apple production-only and App Apple ID requirements,
the Play "View financial data" permission, and the privacy note; kit
README lists the capability.

Verified: kit lint, 913 vitest tests, smoke:server, docs build,
audit:docs. Four review-self rounds converged (13 findings fixed,
final round clean); the two selection helpers that carried the
subtlest bugs are pure functions with regression tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@hyochan hyochan added 🎯 feature New feature 📖 documentation Improvements or additions to documentation labels Aug 5, 2026
@coderabbitai

coderabbitai Bot commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9ac8fc6b-4270-4397-b5a8-36bdcb74a96b

📥 Commits

Reviewing files that changed from the base of the PR and between cb0b861 and 0898b6b.

📒 Files selected for processing (2)
  • packages/docs/src/pages/docs/kit-backend.tsx
  • packages/kit/README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/kit/README.md
  • packages/docs/src/pages/docs/kit-backend.tsx

📝 Walkthrough

Walkthrough

Added authenticated Apple and Google order lookup through Convex. Added normalized order and subscription responses, a project Orders dashboard page, navigation, tests, and documentation.

Changes

Order lookup

Layer / File(s) Summary
Lookup contracts and summaries
packages/kit/convex/orders/shared.ts, packages/kit/convex/orders/shared.test.ts, packages/kit/convex/purchases/*
Added shared validators, response types, Apple and Google summarizers, conversion helpers, and coverage for lookup data shapes. Existing purchase helpers are now exported.
Authenticated provider lookups
packages/kit/convex/orders/action.ts
Added the authenticated lookupOrder action with Apple and Google API requests, retries, credential validation, subscription retrieval, not-found responses, and formatted errors.
Dashboard route and lookup page
packages/kit/src/pages/auth/index.tsx, packages/kit/src/pages/auth/organization/project/index.tsx, packages/kit/src/pages/auth/organization/project/orders.tsx
Added the project Orders route and tab. The page submits lookups and renders summaries, identifiers, masked purchase tokens, subscription status, errors, and raw responses.
Feature documentation
packages/docs/src/pages/docs/kit-backend.tsx, packages/kit/README.md
Documented supported stores, credential requirements, live lookup behavior, and non-persistence. Added related SEO keywords.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ProjectOrders
  participant lookupOrder
  participant AppleOrGoogleAPI
  ProjectOrders->>lookupOrder: submit store and order ID
  lookupOrder->>AppleOrGoogleAPI: request order details
  AppleOrGoogleAPI-->>lookupOrder: order data or lookup error
  lookupOrder->>AppleOrGoogleAPI: request optional subscription status
  AppleOrGoogleAPI-->>lookupOrder: subscription data or secondary error
  lookupOrder-->>ProjectOrders: return normalized lookup response
Loading

Possibly related PRs

  • hyodotdev/openiap#210: The lookup action reuses exported Apple and Google purchase credential and transaction-parsing helpers.

Suggested labels: kit

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding read-only order lookup functionality to Kit.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/kit-order-lookup

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/docs/src/pages/docs/kit-backend.tsx`:
- Around line 210-214: Update the order lookup description in
packages/docs/src/pages/docs/kit-backend.tsx at lines 210-214 to say
subscription status is returned “when available.” Also update
packages/kit/README.md at line 50 to replace “subscription state” with “when
available, subscription status,” preserving the documented best-effort behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c6fd957-57ef-4e6f-82b3-05a6648f6211

📥 Commits

Reviewing files that changed from the base of the PR and between 059063c and cb0b861.

⛔ Files ignored due to path filters (1)
  • packages/kit/convex/_generated/api.d.ts is excluded by !**/_generated/**
📒 Files selected for processing (10)
  • packages/docs/src/pages/docs/kit-backend.tsx
  • packages/kit/README.md
  • packages/kit/convex/orders/action.ts
  • packages/kit/convex/orders/shared.test.ts
  • packages/kit/convex/orders/shared.ts
  • packages/kit/convex/purchases/android.ts
  • packages/kit/convex/purchases/ios.ts
  • packages/kit/src/pages/auth/index.tsx
  • packages/kit/src/pages/auth/organization/project/index.tsx
  • packages/kit/src/pages/auth/organization/project/orders.tsx

Comment thread packages/docs/src/pages/docs/kit-backend.tsx Outdated
Per review: the subscription fetch is optional and its failure does not
invalidate the order result, so the docs and README should not read as
if every subscription order always returns a status.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@hyochan
hyochan merged commit 5990d14 into main Aug 5, 2026
13 checks passed
@hyochan
hyochan deleted the feat/kit-order-lookup branch August 5, 2026 09:53
hyochan added a commit that referenced this pull request Aug 13, 2026
The page states it is the canonical changelog and that every shipped PR
lands an entry, but the last one was 2026-07-28 while five production
changes had deployed since. Entries reconstructed from each PR, dated by
its merge to main, which is when deploy-kit.yml ships it: order lookup
(#285), sync/verification/MCP session correctness (#292), the production
Convex target guard (#314), store verification integrity (#313), and the
entitlement defects the conformance suite surfaced (#316).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📖 documentation Improvements or additions to documentation 🎯 feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant