Skip to content

Monetization

SectorWars 2102 is free-to-play with optional subscriptions. The base game (sign-up, single-region play, all core gameplay) is free forever. Real money buys cross-region travel, region ownership, and (future) cosmetic / convenience perks — never a competitive ceiling.

Source files: - services/gameserver/src/services/paypal_service.py — PayPal API integration, plan IDs, webhook handling. - services/gameserver/src/models/user.pysubscription_tier, subscription_status, paypal_subscription_id columns on User. - services/gameserver/src/models/region.pysubscription_tier, paypal_subscription_id on Region (for Region Owner billing). - services/gameserver/src/services/regional_auth_service.pyRegionalRole.GALACTIC_CITIZEN, role permissions.


1. Subscription tiers

Three tiers are defined in paypal_service.py:SubscriptionTier. The first two are live; the third is reserved for future expansion.

1.1 Free

Price: $0.

Identity: Default for every new account. User.subscription_tier = NULL.

Includes: - Full character creation and play within a single home region. - All core gameplay: trading, combat, planet ownership, colonization, faction missions, team membership, ranking progression. - ARIA companion at base consciousness tier. - Access to leaderboards and cross-team chat within the home region.

Excludes: - Cross-region travel (cannot leave home region except to visit Central Nexus as a visitor membership). - Region ownership. - (Future) cosmetic ship skins and ARIA voice packs.

1.2 Galactic Citizen — $5 / month

Identity: User.subscription_tier = "galactic_citizen". PayPal plan ID configured via PAYPAL_GALACTIC_CITIZEN_PLAN_ID env var (services/gameserver/src/core/config.py:73).

When a Galactic Citizenship subscription activates, Player.is_galactic_citizen is set to true (paypal_service.py:_activate_galactic_citizenship, line 412).

Unlocks: - Cross-region travel via Central Nexus warp gates (the Player.can_travel_between_regions property gates this — models/player.py:147). - Auto-elevation to RegionalRole.GALACTIC_CITIZEN in any visited region, granting GALACTIC_CITIZEN_BENEFITS permission (regional_auth_service.py:179). - A small monthly in-game credit stipend (target: 5,000 cr/month — see FEATURES/economy/lifecycle.md). - Faster ARIA relationship score growth and elevated initial consciousness tier. - Cosmetic citizenship badge on player profile.

1.3 Region Owner — $25 / month

Identity: Region.subscription_tier = "regional_owner", Region.paypal_subscription_id set, Region.owner_id linked to the User. PayPal plan ID via PAYPAL_REGIONAL_OWNER_PLAN_ID.

Activation: paypal_service.py:_activate_regional_ownership (line 426). On subscription approval, the system either creates a new Region row or transfers ownership of an existing one.

Unlocks: - Ability to create and own a player-owned region (100–1,000 sectors, per valid_region_type_sector_count constraint in models/region.py:138). - Configure governance_type (autocracy / democracy / council). - Set tax_rate (5% to 25%, constraint in models/region.py:134). - Set starting_credits for new players spawning in the region. - Customize language_pack, aesthetic_theme, traditions (cultural identity). - Receive a share of regional tax revenue (📐 Design-only — payout share %). - Issue regional bounties from treasury. - Includes Galactic Citizen benefits for the owning user.

1.4 Nexus Premium — $50 / month (future)

Identity: User.subscription_tier = "nexus_premium". Plan ID PAYPAL_NEXUS_PREMIUM_PLAN_ID.

Reserved tier (paypal_service.py:30 annotates "future expansion"). Intended for power users who want Galactic Citizen + a permanent presence in the Central Nexus + enhanced ARIA features. Specifics to be defined.


2. PayPal billing flow

End-to-end topology of a subscription purchase. Source: paypal_service.py:create_galactic_citizen_subscription (line 166) and create_regional_ownership_subscription (line 206).

2.1 Subscription create

Player-client                 gameserver                      PayPal
     │                             │                             │
     │ POST /api/v1/subscriptions/ │                             │
     │   galactic-citizen          │                             │
     │ ─────────────────────────►  │                             │
     │                             │ POST /v1/billing/           │
     │                             │   subscriptions             │
     │                             │ ──────────────────────────► │
     │                             │ ◄────── subscription.id +   │
     │                             │         approval_url        │
     │ ◄─── { approval_url } ─────  │                             │
     │                             │                             │
     │ user redirected to PayPal approval page                   │
     │ ─────────────────────────────────────────────────────────►│
     │ user completes PayPal flow                                │
     │ ◄──── return_url with subscription_id ─────────────────── │

2.2 Webhook activation

PayPal calls back to the gameserver webhook endpoint when the subscription state changes. Source: paypal_service.py:handle_subscription_webhook (line 294).

PayPal                          gameserver                   database
   │                                │                            │
   │ POST /webhooks/paypal          │                            │
   │   { event_type:                │                            │
   │     BILLING.SUBSCRIPTION       │                            │
   │     .ACTIVATED }               │                            │
   │ ─────────────────────────────► │                            │
   │                                │ verify signature           │
   │                                │ (validate_webhook_signature)│
   │                                │ ─────────────────────────► │
   │                                │ parse custom_id            │
   │                                │ → "galactic_citizen_<uid>" │
   │                                │ or "regional_owner_<uid>_<region>"
   │                                │                            │
   │                                │ User.paypal_subscription_id│
   │                                │ User.subscription_tier     │
   │                                │ Player.is_galactic_citizen │
   │                                │   = true                   │
   │                                │ ─────────────────────────► │
   │ ◄── 200 OK ────────────────────│                            │

2.3 Feature flag flip

After the webhook commits, gated features become available immediately: - Player.can_travel_between_regions returns true (gates inter-region travel API). - Player.is_galactic_citizen = true (gates Galactic-Citizen-only UI elements). - For Region Owner: Region.status = "active", Region.owner_id set — region governance UI unlocks.

No client-side cache flush is required; the player-client checks these flags on each session and on key UI transitions.


3. Webhook event handling

Source: paypal_service.py:handle_subscription_webhook (line 294). Mapping of PayPal event → action:

PayPal event Handler Effect
BILLING.SUBSCRIPTION.ACTIVATED _handle_subscription_activated Set is_galactic_citizen = true or activate region
BILLING.SUBSCRIPTION.CANCELLED _handle_subscription_cancelled Clear is_galactic_citizen; suspend region (Region.status = "suspended")
BILLING.SUBSCRIPTION.SUSPENDED _handle_subscription_suspended Suspend region access
BILLING.SUBSCRIPTION.PAYMENT.FAILED _handle_payment_failed Log warning; failure-counter for eventual suspension
PAYMENT.SALE.COMPLETED _handle_payment_completed Confirm renewal; reactivate suspended region if applicable

Webhook signature validation is mandatory in production (validate_webhook_signature, line 507) — calls PayPal's verification API with the configured PAYPAL_WEBHOOK_ID. The bypass PAYPAL_SKIP_WEBHOOK_VALIDATION env var exists only for local development and emits a warning when used.


4. Refund, suspension, termination

4.1 Suspension

Triggered by: - Repeated payment failures (PayPal sends BILLING.SUBSCRIPTION.SUSPENDED after configured retry attempts). - Operator-initiated suspension via admin UI. - Direct PayPal API call: paypal_service.suspend_subscription(subscription_id, reason) (line 266).

Effect: - Region.status = "suspended" for region subscriptions — the region remains in the database, citizens cannot enter/leave, owner cannot configure. - Player.is_galactic_citizen unset for citizenship subscriptions — cross-region travel blocked, but in-game character data is untouched.

A suspended subscription auto-reactivates when payment resumes (_handle_payment_completed, line 393, sets region.status = "active").

4.2 Cancellation

User-initiated: - Player cancels via PayPal account or via in-game UI (which calls paypal_service.cancel_subscription, line 252).

Effect: - Subscription becomes CANCELLED at PayPal. - Webhook fires BILLING.SUBSCRIPTION.CANCELLED. - _handle_subscription_cancelled (line 340) clears Region.paypal_subscription_id, sets region.status = "suspended", or clears player.is_galactic_citizen.

4.3 Refunds

Refund handling is operator-driven — there is no in-app "request refund" button. An operator reviews the case and: 1. Issues the PayPal refund out-of-band via the PayPal merchant dashboard. 2. Cancels the subscription via paypal_service.cancel_subscription. 3. Logs an audit entry via services/audit_service.py.

Target policy: pro-rata refunds within 7 days of charge for Galactic Citizen; pro-rata only on first month for Region Owner; no refund after the first month of a region subscription (since the universe state has been altered by the player's ownership actions).

4.4 Termination

Permanent termination beyond cancellation: - Region subscriptions: after 30 days of suspended status, the region becomes eligible for Region.status = "terminated". Resident players are migrated to a default region. Region records retained for audit. - Galactic Citizen: cancellation is termination — the user simply returns to free tier.

The RegionStatus.TERMINATED enum (models/region.py:RegionStatus) reserves the state; the migration job is 📐 Design-only.


5. Pricing rationale

Tier Price Marginal cost Target audience Conversion goal
Free $0 Hosting share Everyone Onboard, retain ≥ 10 hours
Galactic Citizen $5 Trivial Hour-50+ players 5–10% of active players
Region Owner $25 Operator cost dominant (region creation, persistence, governance UI) Hour-300+ committed players 0.5–1% of active players
Nexus Premium $50 (future) Power users, content creators <0.1% (luxury tier)

The price ladder is deliberately steep — Region Owner is 5x Galactic Citizen — because region ownership is a creator role, not a consumer role, and pricing it close to Galactic Citizen would devalue regional politics.


6. Identity-state lookup

A user's combined subscription state can be queried via paypal_service.get_user_subscriptions(user_id) (line 459), which returns all active subscriptions across both Galactic Citizen and any owned regions. The function consults both User.paypal_subscription_id and the joined Region.paypal_subscription_id rows.

For internal feature-gating, services should consult: - User.subscription_tier (string column) — fast in-process check. - User.subscription_status — must equal "active" (or PayPal's "ACTIVE"). - Player.is_galactic_citizen — derived flag for cross-region permissions. - Region.owner_id == user.id AND Region.status == "active" — region ownership check.


7. Audit and compliance

All subscription state changes log to services/audit_service.py. Webhooks include: - Inbound webhook payload (full body) with redacted PayPal access tokens. - Resulting database mutations. - Operator who initiated any direct cancellation/suspension.

Retention: 7 years for billing-related audit entries (financial-services standard).


8. Cross-references