register-invite-requests-front/README.md
2026-07-25 17:08:19 +03:30

75 lines
3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Winsoo Invite Page
A single-page invite/referral landing page for Winsoo. A visitor lands on the
page via an invite link, enters their mobile number, and the page submits
that number against the invite code embedded in the URL. Built with plain
HTML, CSS, and JavaScript — no build step, no framework, no dependencies.
## Project structure
```
InvitePage/
├── index.html Markup for the page
├── favicon.svg Browser tab icon
├── css/
│ └── style.css Styles + @font-face declarations
├── js/
│ └── script.js OAuth token fetch + invite submission logic
└── assets/
├── images/
│ ├── logo.png Winsoo wordmark
│ └── illustration.png Hero illustration
└── fonts/
└── iransans/ IRANSans font family (all weights/variants)
```
## Running locally
The page must be served over `http://` or `https://`, not opened directly
as a `file://` URL — the invite API's CORS policy is keyed to real origins,
and some browsers handle a `file://` "null" origin inconsistently.
```bash
python3 -m http.server 8765
```
Then open:
```
http://localhost:8765/index.html?inviteCode=<uuid>
```
The `inviteCode` query parameter is required — it's the invite code that
gets sent to the API along with the submitted phone number.
## How it works
1. **On page load**, [`js/script.js`](js/script.js) requests an OAuth2
access token from Gooyal's `client_credentials` token endpoint, using
Basic auth (base64 of `client_id:client_secret`) and scope
`accounts.invite:submit`. The token is cached in memory for reuse.
2. **On submit**, the phone number is normalized to E.164 format:
- Persian (`۰-۹`) and Arabic-Indic (`٠-٩`) digits are converted to Latin
digits.
- Common prefixes (`0`, `98`, `+98`, `0098`) are stripped and replaced
with `+98`.
- The result must match a 10-digit Iranian mobile number (`9XXXXXXXXX`).
- Invalid input highlights the field and shows an inline error instead
of calling the API.
3. The invite code is read from the page's own URL (`?inviteCode=...`) and
POSTed together with the mobile number to the invite request endpoint,
authenticated with the bearer token from step 1.
4. If the invite request fails with `401` (expired/invalid token), the
token is refetched once and the request is retried automatically.
Any other failure surfaces the API's own `status_message` (falling back
to a generic Persian error) in the inline message area below the input.
A successful submission shows a success message.
## Known limitation
`js/script.js` contains the OAuth client ID and client secret in plain
text, which means anyone viewing the page source can read them. This is
acceptable for the current staging environment, but **before shipping to
production**, the `client_credentials` token exchange should move to a
small backend/proxy that holds the secret server-side; the browser should
never see it directly.