Skip to main content

Premium Subscription System

This document describes the Aleteia Premium subscription system, which integrates Stripe for payment processing, Firebase Authentication for user management, and Firestore for premium status persistence. The system enables seamless premium subscription lifecycle management with automated user provisioning and email notifications.

Architecture Overview

The premium system operates as a standalone module within the Rails application, processing Stripe webhook events to manage Firebase users and their premium status.

Key Features

FeatureDescription
Automated User ProvisioningCreates Firebase Auth users automatically when subscriptions are created
Premium Status ManagementTracks premium status and plan tier in Firestore
Newsletter Auto-SubscriptionAutomatically subscribes new users to daily and vatican newsletter segments
Multi-Language SupportAll communications respect subscriber's locale preference
Password Reset LinksGenerates secure password reset links with custom parameters for frontend detection
Email NotificationsSends welcome and goodbye emails via SendGrid templates
Idempotent ProcessingAll webhook handlers are safely re-runnable

System Components

Services

ServicePurposeLocation
Premium::StripeServiceHandles Stripe subscription eventsapp/services/premium/stripe_service.rb
Premium::UsersServiceManages Firebase users and Firestore dataapp/services/premium/users_service.rb
Premium::SendgridServiceSends templated emailsapp/services/premium/sendgrid_service.rb

Background Jobs

JobQueuePurpose
StripeWebhookJobdefaultRoutes all Stripe events to appropriate handlers
Premium::StripeEventJobdefaultProcesses premium-specific subscription events
Premium::SendEmailJobemailSends welcome/goodbye emails asynchronously

Data Structures

The system uses Ruby Data classes for immutable value objects:

# Plan information from Stripe product metadata
Plan = Data.define(:id, :name, :tier, :platform, :locale)

# Result of user creation/lookup
UserResult = Data.define(:uid, :email, :display_name, :new_user, :password_generation_link)

Event Routing

The system uses a unified webhook entry point that intelligently routes events based on product metadata:

Supported Events

EventHandlerAction
customer.subscription.createdPremium::StripeServiceCreates/updates user, enables premium
customer.subscription.deletedPremium::StripeServiceDisables premium status

User Lifecycle

New Premium Subscriber

Premium Cancellation

Firestore Data Model

Premium user data is stored in the users collection:

Example Document

{
"email": "[email protected]",
"display_name": "John Doe",
"first_name": "John",
"last_name": "Doe",
"premium": true,
"plan": "essential",
"plan_name": "Premium Essential",
"plan_monthly_fee": 6.90,
"premium_started_at": "2024-01-15T10:30:00Z",
"premium_ended_at": null,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}

Stripe Product Configuration

Premium products in Stripe must include specific metadata for proper routing:

Metadata KeyRequiredDescriptionExample
platformYesMust be "premium" for premium routingpremium
tierYesPlan tier identifieressential
nameNoDisplay name for emailsPremium Essential
localeNoDefault locale for communicationsit

Example Product Metadata

{
"platform": "premium",
"tier": "essential",
"name": "Premium Essential",
"locale": "it"
}

Integration Points

The premium system integrates with several external services:

ServiceIntegration TypePurpose
StripeWebhooksPayment processing, subscription lifecycle
Firebase AuthAdmin SDKUser creation, email verification
FirestoreClient SDKPremium status persistence
SendGridREST APITransactional email delivery

Security Considerations

  1. Webhook Verification: All Stripe webhooks are verified using the signing secret
  2. Service Account: Firebase operations use scoped service account credentials
  3. Password Reset: Links generated with 30-second timeout and specific continue URL
  4. Logging: Structured logs avoid accidentally logging sensitive data
  5. Idempotency: All handlers are safely re-runnable without side effects