Back to OSS
Swift Package 認証 / 課金

swift-subscription

RevenueCat 統合のサブスクリプション管理を SwiftUI でシンプルに

Swift
revenuecatsubscriptionin-app-purchase

Subscription

A Swift package for subscription management using RevenueCat.

Swift Platforms SPM License

English | 日本語

📚 Full Documentation

Overview

The Subscription package integrates with RevenueCat to provide a high-level API for implementing in-app purchases and subscriptions.

Features

  • ✅ Check and observe subscription status
  • ✅ Fetch available plans
  • ✅ Purchase and restore plans
  • ✅ User authentication integration
  • ✅ SwiftUI-ready (async/await, AsyncStream)
  • ✅ Actor-based thread-safe design

Requirements

  • iOS 17.0+ / macOS 14.0+
  • Swift 6.0+
  • RevenueCat SDK 5.14.0+

Prerequisites

RevenueCat Project Setup

Complete the following steps in the RevenueCat Dashboard:

  1. Create a project

    • Create a new project and obtain your API key
  2. Configure products

    • Create subscription products in App Store Connect / Google Play Console
    • Import products into the RevenueCat Dashboard
    • Configure entitlements (e.g., "premium")
  3. Create an offering

    • Group plans (monthly, annual, etc.) into an offering
    • Set the default offering

Installation

Swift Package Manager

Add the following to your Package.swift:

dependencies: [
    .package(url: "https://github.com/no-problem-dev/swift-subscription.git", from: "1.0.4")
]

Or add it via File > Add Package Dependencies... in Xcode using https://github.com/no-problem-dev/swift-subscription.

Quick Start

1. Initialize

import Subscription

let config = SubscriptionConfiguration(
    apiKey: "your_revenuecat_api_key",
    entitlementId: "premium"
)
let subscriptionUseCase = SubscriptionUseCaseImpl(configuration: config)

2. Check Subscription Status

// Get cached status immediately
let status = await subscriptionUseCase.getSubscriptionStatus()

// Fetch the latest status from the server
let latestStatus = try await subscriptionUseCase.checkSubscriptionStatus()

if latestStatus.isActive {
    print("Active plan: \(latestStatus.activePackageId ?? "unknown")")
}

3. Fetch and Purchase Plans

// Fetch available plans
let offerings = try await subscriptionUseCase.loadOfferings()

if let packages = offerings?.packages {
    for package in packages {
        print("\(package.title): \(package.price)")
    }

    // Purchase a plan
    if let package = packages.first {
        let status = try await subscriptionUseCase.purchase(packageId: package.id)
    }
}

4. Real-time Observation

// Observe subscription status changes
Task {
    for await status in subscriptionUseCase.observeSubscriptionStatus() {
        if status.isActive {
            // Enable premium features
        }
    }
}

Usage Examples

SwiftUI Integration

import SwiftUI
import Subscription

struct ContentView: View {
    @Environment(\.subscriptionUseCase) private var subscriptionUseCase
    @State private var status: SubscriptionStatus = .inactive

    var body: some View {
        VStack {
            if status.isActive {
                Text("Premium Member")
            } else {
                Button("Subscribe to Premium") {
                    Task { await showPaywall() }
                }
            }
        }
        .task {
            guard let subscriptionUseCase else { return }
            for await newStatus in subscriptionUseCase.observeSubscriptionStatus() {
                status = newStatus
            }
        }
    }

    private func showPaywall() async {
        // Paywall presentation
    }
}

Inject the use case at the App entry point:

@main
struct MyApp: App {
    private let subscriptionUseCase = SubscriptionUseCaseImpl(
        configuration: SubscriptionConfiguration(apiKey: "your_revenuecat_api_key")
    )

    var body: some Scene {
        WindowGroup {
            ContentView()
                .subscriptionUseCase(subscriptionUseCase)
        }
    }
}

User Authentication Integration

// On user login
func userDidLogin(userId: String) async throws {
    try await subscriptionUseCase.syncUser(userId: userId)
}

// On user logout
func userDidLogout() async throws {
    try await subscriptionUseCase.clearUser()
}

Error Handling

do {
    let status = try await subscriptionUseCase.purchase(packageId: packageId)
} catch let error as SubscriptionError {
    switch error {
    case .purchaseCancelled:
        // User cancelled — no error display needed
        break
    case .networkError:
        // Prompt retry on network error
        showRetryAlert()
    default:
        showAlert(message: error.localizedDescription)
    }
}

Dependencies

License

MIT License

Support

For issues or feature requests, please create a GitHub Issue.

同じカテゴリの OSS — 認証 / 課金

swift-authentication

Swift Package

Google / Apple Sign-In を async/await で扱う Firebase 認証統合パッケージ

Swift
· 認証 / 課金
firebaseauthenticationsign-in

© 2026 Kyoichi Taniguchi. All rights reserved.