-
Notifications
You must be signed in to change notification settings - Fork 0
Store
The supporter store at /store is how players support the site's hosting costs and pick up a few quality-of-life perks in return: a custom profile tag, raid queue priority, and (for super donators) pre-queueing. Payments run through PayPal orders with a server-to-server webhook as a safety net. This page covers what is sold, how purchases flow, the custom tag pipeline, and what an operator needs to configure.
The seeded catalog (from schema.sql; admins can toggle items and add more):
| Item | Slug | Price | Billing | Benefit |
|---|---|---|---|---|
| Supporter Pack | supporter |
$2.99 | Bimonthly (60 days) |
supporter: submit a staff-reviewed custom tag for your profile, recolor it, and show a Supporter badge |
| Priority Pass | priority_pass |
$7.99 | Monthly (30 days) |
queue_priority: jump to the front of the raid join queue |
A third benefit type, super_donator, exists in the code for higher-tier items: it inherits queue priority and additionally unlocks pre-queueing (waiting on a raid boss before any lobby is open) plus a donator badge. See Raid Finder for what the raid perks do in practice.
Item types are one_time, monthly, or bimonthly. Monthly purchases expire 30 days after completion and bimonthly after 60; one_time purchases never expire (and cannot be bought again while still active). There is no auto-renewal: each term is a separate checkout. Users can cancel an active monthly or bimonthly purchase from the store page, which ends it immediately.
Two side effects of any active purchase:
- a +5 read-time bonus to effective trust while it lasts (see Trust and Awards),
- the perks above, evaluated live against the purchase's expiry on every check.
- The user posts
/store/checkoutwith an item slug. The server creates a PayPal order (intent: CAPTURE, USD) with return and cancel URLs pointing back at the site, records apendingpurchase row keyed by the PayPal order id, and redirects the user to PayPal's approval page. -
Return path: PayPal sends the user back to
/store/return?token=<orderID>. The server captures the order and marks the purchasecompleted, stamping the expiry from the item type. -
Cancel path:
/store/cancelmarks the pending purchasecancelled. -
Webhook path: PayPal also posts
CHECKOUT.ORDER.APPROVEDto/api/store/webhook. If the user approved payment but never made it back to the return URL, the webhook captures and completes the purchase instead. The endpoint verifies the transmission signature against the configured webhook id via PayPal's verification API, always answers 200 so PayPal does not retry, and ignores anything that fails verification or is not pending. It is the one CSRF-exempt route in the app (see Architecture).
Supporters can request a custom colored tag, shown next to their name everywhere tags appear:
- Submit a name (up to 32 characters) and color from the store or settings page. Submitting requires an active Supporter Pack.
- The request enters staff review with states
pending,approved,rejected, orrevision:- Approved: the tag is created and assigned. Staff approval double-checks the pack is still active.
- Rejected (with a reason): a 7-day cooldown starts before a fresh request can be submitted.
- Revision requested (with notes): the user may resubmit immediately, no cooldown.
- You can only have one pending or approved request at a time. If an approved tag is later rejected, it is removed from the profile.
- Color changes to an approved tag are self-service but rate limited to 5 changes per 30 minutes.
The review queue lives in the admin panel; see the Admin Guide.
The store is off until both of these are true:
- The
store_enabledsite setting is on (toggled from the admin Settings tab, Admin+). - PayPal credentials are configured. Without them the page can still be shown, but checkout is unavailable (
PayPalReadyis false and order creation fails safely back to the store with an error flash).
Create a REST app in the PayPal developer dashboard and set these environment variables (see Configuration for the full env reference):
| Variable | Meaning |
|---|---|
PAYPAL_CLIENT_ID |
REST app client id |
PAYPAL_CLIENT_SECRET |
REST app secret |
PAYPAL_MODE |
live for production; anything else (or unset) uses the sandbox (api-m.sandbox.paypal.com vs api-m.paypal.com) |
PAYPAL_WEBHOOK_ID |
The id PayPal assigns when you register the webhook |
Register a webhook in the PayPal app pointing at https://your.site/api/store/webhook, subscribed to CHECKOUT.ORDER.APPROVED, and put the resulting webhook id in PAYPAL_WEBHOOK_ID. Without it, webhook signature verification fails closed and only the browser return path completes purchases.
OAuth tokens are fetched with the client credentials grant and cached in-process until shortly before expiry.
Items live in the store_items table (name, slug, description, price in cents, type, benefit, active, sort order). The admin Donations tab lists them and toggles active; adding items or changing prices is done in the database. Purchases keep a full status history (pending, completed, refunded, cancelled) joined to the user and item.
Repository | Live site | hailsDotGO is a fan-made project, not affiliated with, endorsed by, or connected to Niantic or The Pokémon Company. Game data comes from community sources credited on the Data Sources page.
Start Here
Features
- Raids and Counters
- DPS Calculator
- IV Calculator
- PvP IV Ranker
- Events
- Shiny Tracking
- Trainer Directory
- Raid Finder
- Social Features
- Trust and Awards
- Bug Reports
- Player Reports
- Store
- Accounts and Roles
- Admin Guide
Self-Hosting
Development
Translations