Architecture

This document describes the system architecture and component design of the Wallet Service.

System Overview

┌─────────────────────────────────────────────────────────────────────────┐
│                           Wallet Service                                 │
│                                                                          │
│  ┌──────────────┐   ┌──────────────┐   ┌──────────────────────────────┐ │
│  │   Fastify    │   │  Controllers │   │         Services             │ │
│  │   Server     │ ─▶│              │──▶│                              │ │
│  │              │   │ - Apple      │   │ - DigitalMembershipService   │ │
│  │ - Routing    │   │ - Google     │   │ - ApplePasskitService        │ │
│  │ - Plugins    │   │ - Passes     │   │ - GoogleWalletService        │ │
│  └──────────────┘   └──────────────┘   └──────────────────────────────┘ │
│         │                                          │                     │
│         ▼                                          ▼                     │
│  ┌──────────────┐                         ┌──────────────────┐          │
│  │   Modules    │                         │   External APIs  │          │
│  │              │                         │                  │          │
│  │ - Apple      │                         │ - Salesforce     │          │
│  │ - Google     │                         │ - SMTP           │          │
│  │ - Salesforce │                         │ - APNs           │          │
│  └──────────────┘                         └──────────────────┘          │
└─────────────────────────────────────────────────────────────────────────┘

Core Components

Application Layer (src/app/)

app.ts - Application Core

The main Fastify application instance implementing:

Key Features:

app.environment.ts - Configuration

Centralized environment configuration using envalid for:

Controllers (src/lib/controllers/)

Controllers handle HTTP requests and route them to appropriate services.

passes.controller.ts

General pass management operations:

apple.controller.ts

Apple PassKit WebService implementation:

google.controller.ts

Google Wallet callback handling:

Services (src/lib/services/)

Services contain business logic and orchestrate operations.

DigitalMembershipService

Core membership pass operations:

ApplePasskitService

Apple Wallet-specific operations:

GoogleWalletService

Google Wallet-specific operations:

Modules (src/lib/modules/)

Reusable utility modules for external integrations.

apple.ts

Apple PassKit utilities:

google.ts

Google Wallet utilities:

salesforce.ts

Salesforce integration:


Data Flow

Apple Pass Generation Flow

1. Request → PassesController.send()
2. DigitalMembershipService.retrieveApplePassesBySalesforceId()
3. Salesforce module → Fetch member data
4. Apple module → Generate .pkpass file
5. Email → Send to member

Apple Pass Update Flow (Push Notification)

1. Data changes in Salesforce
2. Trigger → GET /passes/update/:serialNumber
3. DigitalMembershipService.updateApplePassBySerialNumber()
4. APNs → Push notification to registered devices
5. Device → GET /apple/v1/passes/:passTypeIdentifier/:serialNumber
6. Return updated pass

Google Wallet Flow

1. Request → PassesController.send()
2. DigitalMembershipService.retrieveGooglePassesBySalesforceId()
3. Salesforce module → Fetch member data
4. Google module → Generate JWT save link
5. Email → Send save link to member

Dependency Injection

The service uses @fastify-decorators/simple-di for dependency injection:

// Service definition
@Service()
export class DigitalMembershipService {
  @Initializer()
  async init() { /* ... */ }
}

// Controller usage
@Controller('/passes')
class PassesController {
  private readonly _service = getInstanceByToken<DigitalMembershipService>(DigitalMembershipService);
}

Security Architecture

Request Authentication

┌──────────────┐     ┌─────────────────┐     ┌────────────────┐
│  Apple       │     │  Authorization  │     │  Controller    │
│  Device      │────▶│  Middleware     │────▶│  Handler       │
└──────────────┘     │                 │     └────────────────┘
                     │  verifyToken()  │
                     │  - Format check │
                     │  - Token match  │
                     └─────────────────┘

Google Message Verification

┌──────────────┐     ┌─────────────────────┐     ┌────────────────┐
│  Google      │     │  PaymentMethod      │     │  Controller    │
│  Wallet      │────▶│  TokenRecipient     │────▶│  Handler       │
└──────────────┘     │                     │     └────────────────┘
                     │  - Fetch public keys│
                     │  - Verify signature │
                     │  - Unseal message   │
                     └─────────────────────┘

Plugins & Middleware

Plugin Purpose
@fastify/cors Cross-Origin Resource Sharing
@fastify/helmet Security headers
@fastify/rate-limit Request rate limiting
@fastify/circuit-breaker Failure protection
@fastify/compress Response compression
@fastify/swagger API documentation
@fastify/static Static file serving
@fastify/view Template rendering
@mgcrea/fastify-graceful-exit Graceful shutdown
@sentry/node Error tracking

Background Jobs

update-google-passes.ts

Scheduled job for batch updating Google Wallet passes.

Uses @fastify/schedule for cron-based execution.


Error Handling

The application implements centralized error handling:

// 404 Handler
this._instance.setNotFoundHandler(async (request) => {
  throw new Error('404');
});

// Global Error Handler
this._instance.setErrorHandler(async (error, request, reply) => {
  // Log to Sentry
  this._sentry.captureException(error);
  // Return standardized response
  await reply.status(statusCode).send(buildResponseObject(statusCode));
});

Deployment Architecture

Docker Deployment

# docker-compose.yml
services:
  wallet-service:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    volumes:
      - ./certs:/app/src/lib/certs

Production Topology

┌───────────────┐     ┌───────────────┐     ┌───────────────┐
│  Load         │     │  Wallet       │     │  External     │
│  Balancer     │────▶│  Service      │────▶│  Services     │
│               │     │  (Container)  │     │               │
│  - TLS        │     │               │     │  - Salesforce │
│  - Rate Limit │     │  - Port 3000  │     │  - SMTP       │
└───────────────┘     └───────────────┘     │  - APNs       │
                                            │  - Google API │
                                            └───────────────┘