Subscriptions
Paid subscriptions in Now Playing unlock Pro features. Payment processing runs through PayPal, and entitlement (what features a user has access to) is managed by a dedicated subscription service that talks to PayPal and updates the user’s roles.
How It’s Structured
Section titled “How It’s Structured”Browser ──► Next.js web ──► Subscription service ──► PayPal API │ ▼ PostgreSQL │ ▼ RBAC roles- Browser — runs the PayPal JavaScript SDK to show an embedded checkout widget. The user never leaves the Now Playing dashboard.
- Web (Next.js) — thin API routes that authenticate the user, then proxy to the subscription service.
- Subscription service (Python) — handles all the business logic: PayPal API calls, webhook processing, discount codes, scheduled jobs, and role management.
- PostgreSQL — stores subscription state, payment history, and user roles.
- PayPal — source of truth for payments and invoices.
This split keeps the web app simple (auth + proxy) and isolates the stateful parts (talking to PayPal, handling webhooks) in a service that can run on its own schedule.
The Subscription Lifecycle
Section titled “The Subscription Lifecycle”- Subscribe. The user picks a plan in the dashboard. PayPal’s embedded checkout collects payment details. On success, PayPal returns a subscription ID.
- Activate. The subscription service records the subscription in the
database and grants the user the
prorole through the role-based access control system. - Renew. PayPal charges the user automatically each billing period. A webhook notifies the subscription service, which records the payment.
- Cancel. The user can cancel at any time. The subscription remains active through the end of the current billing period, then lapses.
- Lapse. When the billing period ends without renewal, the subscription
service revokes the
prorole.
Role-Based Access Control
Section titled “Role-Based Access Control”Pro features are gated through roles in the RBAC system:
| Role | Meaning |
|---|---|
pro | Active paid subscription |
lifetime | Permanent access (granted manually) |
staff | Now Playing team member with elevated access |
When a feature needs to check entitlement, it asks the RBAC system whether the userId has the required role. The role check is cheap — it is a single database lookup backed by a Redis cache.
Discount Codes
Section titled “Discount Codes”Discount codes can be validated by the subscription service and applied at checkout. Validation happens server-side, so there is no way to fake a code from the browser. Applied discounts are recorded as part of the subscription record.
Invoices
Section titled “Invoices”Invoices are tracked in PayPal, not recreated locally. When a user wants to view their payment history, the subscription service fetches the invoice list from PayPal’s API on demand. This keeps accounting records consistent with what PayPal has on file.
Manual Overrides
Section titled “Manual Overrides”For partners, contest winners, or compensated comp accounts, staff can grant the
pro or lifetime role directly without going through PayPal. These grants
bypass the subscription lifecycle and stay in place until manually revoked.
What Happens on Payment Failure
Section titled “What Happens on Payment Failure”If a scheduled renewal payment fails:
- PayPal retries the payment according to its standard retry schedule.
- The subscription service waits out the grace period before taking action.
- If PayPal ultimately fails the renewal, the subscription is marked
past_dueand thencancelled, and theprorole is revoked.
The user is notified at each step so they have a chance to update their payment method before losing access.
Why PayPal?
Section titled “Why PayPal?”PayPal’s Subscriptions API handles recurring billing, tax collection in applicable regions, and invoicing — removing a large compliance and accounting surface from Now Playing’s own codebase. The embedded checkout experience (via the PayPal JS SDK) keeps the user inside the Now Playing dashboard, so the flow feels native.