Skip to content

feat(pricing): hide pricing for US users and load plan prices from the quote store - #1306

Merged
twosugar merged 2 commits into
mainfrom
feat/pricing-hide-for-us
Oct 26, 2026
Merged

twosugar merged 2 commits into
mainfrom
feat/pricing-hide-for-us

Conversation

@twosugar

Copy link
Copy Markdown
Collaborator

Problem

  • US users saw the navbar Pricing, the homepage See pricing button and the paid plans on /pricing (LBUS does not sell these OpenAPI quote packages).
  • The paid plan prices were hard-coded in HK$ and no longer matched the store (HK LV2 OpenAPI monthly 718 on the page vs 498 in the store; OPRA monthly 40 vs 28).

Change

1. Hide pricing for US users (feat(pricing): hide pricing entries…)

New isUSUser() in @longbridge/openapi-utils (packages/utils/src/us-user.ts), decided in order:

  1. Logged in → app_id cookie is a US tenant (longbridge_us / longbridge_us_uat)
  2. Not logged in → region cookie is US (case-insensitive)
  3. No region cookie → x-ip-region header from the portal GET /api/_ping (same endpoint h5hub / longbridge-websites use)

Cached per page; any failure counts as non-US. When true, hides the navbar Pricing link (desktop + mobile), the homepage See pricing button and the Subscribe only to what you need plans. Free tier, comparison table and FAQ stay.

2. Load plan prices from the quote store (feat(pricing): load paid quote plan prices…)

GET /v2/rewards/quote_product_list?account_channel=lb with x-app-id: longbridge (no login needed; CORS allows the docs origins and x-app-id), matched by package_key HK_L2_International_OpenAPI / US_OPRA_LV1_OpenAPI:

  • Currency from each SKU — no hard-coded symbol.
  • Price = real_price; per_month_price shown for quarterly / annual; when price > real_price, discount % and original price are shown.
  • Billing-cycle tabs built from card_duration (1/2/3 = month/quarter/year, 5 = auto-renew, same enum as h5hub opa) — only cycles the API returns. Production currently returns 1/2/3 only, so Auto-renew is not shown; it appears automatically once the store returns it.
  • Loading / failure → —.

Verification (local dev against production portal data)

Local dev cannot call the portal directly (CORS), so it was tested through a throwaway local proxy that forwards to mr.lbkrs.com and adds CORS headers (not committed).

Cycle HK LV2 Advanced OPRA US Options
Monthly HKD 498 /mo HKD 28 /mo
Quarterly HKD 998 /quarter, ≈HKD 333/mo HKD 58 /quarter, ≈HKD 19/mo
Annual HKD 3698 /year −38%, ≈HKD 308/mo, was HKD 5976 HKD 188 /year −44%, ≈HKD 16/mo, was HKD 336
  • /zh-CN/pricing renders 月付 / 季付 / 年付 with the same data.
  • region=US → Pricing link, See pricing and the paid plans are hidden; region=hk → shown; no region → /api/_ping called, x-ip-region: HK read, shown.
  • Logged-in branch tested by stubbing the login bridge and calling isUSUser() (US app_id → true even with region=hk; HK app_id → false even with region=US).
  • In a real browser on open.longbridge.com and open-canary.longbridge.xyz, /api/_ping returns 200 and x-ip-region is readable.
  • oxlint: clean on the changed files.

Not verified: a real US IP end-to-end, and a real logged-in US session on this branch.

Notes

  • Canary portal data has no US_OPRA_LV1_OpenAPI and only annual for HK LV2, so on canary the OPRA card shows — and fewer cycles.
  • The US tenant app_id list now exists in three places (BaseLayout.astro inline bootstrap, packages/tryit, and the new file); the new file notes they must match.
  • Rebased onto docs: scope markets, paper trading and OTC wording to account regions #1305 (pricing FAQ wording) without conflicts.

🤖 Generated with Claude Code

twosugar and others added 2 commits October 26, 2026 15:10
Longbridge US does not sell these OpenAPI quote packages, but the
navbar "Pricing", the homepage "See pricing" button and the
"Subscribe only to what you need" plans on /pricing were shown to
everyone (with HK$ prices).

Adds isUSUser() in @longbridge/openapi-utils, decided in order:
1. logged in: app_id cookie is a US tenant (longbridge_us / _uat)
2. not logged in: region cookie is US (case-insensitive)
3. no region cookie: x-ip-region header from the portal /api/_ping
Result is cached per page; any failure counts as non-US, so the page
keeps its current content.

The three entries hide when isUSUser() resolves true. The free tier,
comparison table and FAQ on /pricing are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The paid plans had hard-coded HK$ prices that no longer matched the
store (e.g. HK LV2 OpenAPI monthly 718 on the page vs 498 in the store).

Prices now come from /v2/rewards/quote_product_list (no login needed,
x-app-id: longbridge, account_channel=lb), matched by package_key
(HK_L2_International_OpenAPI, US_OPRA_LV1_OpenAPI):
- currency comes from each SKU (no hard-coded symbol)
- current price is real_price; per_month_price is shown for quarterly
  and annual; when price > real_price the discount and original price
  are shown
- billing cycle tabs are built from card_duration (1/2/3 = month /
  quarter / year, 5 = auto-renew) and only include cycles the API
  returns; the default is the first available one
- while loading or if the request fails, prices show "—"

Plan names, taglines and feature lists stay as static copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@twosugar
twosugar merged commit 09e74c4 into main Oct 26, 2026
2 checks passed
@twosugar
twosugar deleted the feat/pricing-hide-for-us branch October 26, 2026 07:14
twosugar added a commit that referenced this pull request Oct 26, 2026
Restores the comments that shipped with #1306 (Pricing.tsx, TopNav.tsx,
isUSUser docs in us-user.ts); only the comments added in this PR stay
in English.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
twosugar added a commit that referenced this pull request Oct 26, 2026
…#1307)

## Problem

The site footer (`Footer.tsx`) and the docs page footer
(`DocFooter.astro`) always link **Terms of Service** / **Privacy
Policy** to the SG support pages, including for Longbridge US users.

## Change

For US users — same `isUSUser()` rule as pricing (#1306: logged in → US
`app_id`; else `region` cookie; else `x-ip-region` from `/api/_ping`) —
the two links point to the Longbridge US PDFs:
- Terms of Service:
https://assets.lbkrs.com/uploads/317ef02f-85e7-4afa-9e76-8acd8c0b42fe/Terms-of-Service-final-.pdf
- Privacy Policy:
https://assets.lbkrs.com/uploads/e4890745-e18b-42f2-9817-da63148e0ac4/Privacy-Policy-final-.pdf

Both URLs are defined once as `US_LEGAL_LINKS` in
`@longbridge/openapi-utils`.

- `Footer.tsx` (hydrated island): picks the href from `isUSUser()`.
- `DocFooter.astro` (static): the two links carry
`data-legal="terms|privacy"`; a small client script swaps the href on
`astro:page-load` when the visitor is a US user.

Non-US users keep the current SG links.

## Verification (local dev)

| Case | Site footer (`/`) | Docs footer (`/docs`) |
|---|---|---|
| `region=US` | US Terms / Privacy PDFs | US Terms / Privacy PDFs |
| `region=hk` | `longbridge.com/sg/support/...` (unchanged) | unchanged
|

Both PDF URLs return 200 `application/pdf`. oxlint clean on the changed
files.

The matching change for the dashboard / authorize pages is in
`longbridge/developers-website-private`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant