Capacitor plugin for handling subscriptions on Android and iOS using Google Play Billing v7 and StoreKit 2
npm install scgs-capacitor-subscribeA Capacitor plugin for handling in-app subscriptions on iOS and Android.
- iOS: Built with StoreKit 2 for modern subscription handling
- Android: Uses Google Play Billing Library v7
- TypeScript: Full type definitions for type-safe development
- Web: Placeholder implementation for development/testing
- Capacitor 7.0.0 or higher
- Node.js 20.0.0 or higher
- For iOS development: Xcode 16.0 or higher
- For Android development: Android Studio
``bash`
npm install scgs-capacitor-subscribe
npx cap sync
1. Configure your app's in-app purchases in App Store Connect
2. Add In-App Purchase capability to your app in Xcode
3. Ensure your app's minimum iOS version is 15.0 or higher
4. Requires Xcode 16.0 or higher
1. Configure your app's in-app purchases in Google Play Console
2. Add the billing permission (automatically included by the plugin)
3. Ensure your app's minimum SDK version is 23 (Android 6.0) or higher
`typescript
import { Subscribe } from 'scgs-capacitor-subscribe';
// Initialize the plugin
await Subscribe.initialize({
enablePendingPurchases: true,
enableLogging: true
});
// Get available products
const { products, invalidProductIds } = await Subscribe.getProducts({
productIds: ['monthly_subscription', 'yearly_subscription']
});
// Purchase a product
try {
const { purchase } = await Subscribe.purchaseProduct({
productId: 'monthly_subscription'
});
console.log('Purchase successful:', purchase);
} catch (error) {
console.error('Purchase failed:', error);
}
// Restore purchases
const { purchases } = await Subscribe.restorePurchases({
userId: 'user123' // optional
});
// Get active purchases
const { purchases: activePurchases } = await Subscribe.getActivePurchases({
userId: 'user123' // optional
});
// Check eligibility for introductory price
const { eligible, introductoryPriceEligible } = await Subscribe.checkEligibility({
productId: 'monthly_subscription'
});
// Present code redemption sheet (iOS only)
await Subscribe.presentCodeRedemptionSheet();
`
Initialize the plugin. Should be called once when your app starts.
Options:
- enablePendingPurchases (boolean): Enable pending purchases (default: true)enableLogging
- (boolean): Enable debug logging (default: false)
Fetch product details from the store.
Options:
- productIds (string[]): Array of product IDs to fetch
Returns:
- products (Product[]): Array of available productsinvalidProductIds
- (string[]): Array of product IDs that weren't found
Initiate a purchase.
Options:
- productId (string): Product ID to purchasequantity
- (number): Quantity to purchase (optional, default: 1)userId
- (string): User ID (In Android it is set to obfuscatedAccountId) (In iOS it is set to appAccountToken)obfuscatedProfileId
- (string): Obfuscated profile ID (Android only, optional)offerToken
- (string): Offer token for the purchase (Android only, optional)
Returns:
- purchase (Purchase): The completed purchase details
Restore previously made purchases.
Options:
- userId (string): User ID for filtering purchases (optional)
Returns:
- purchases (Purchase[]): Array of restored purchases
Get currently active (non-expired) purchases.
Options:
- userId (string): User ID for filtering purchases (optional)
Returns:
- purchases (Purchase[]): Array of active purchases
Acknowledge a purchase (Android only, automatically handled on iOS).
Options:
- purchaseToken (string): The purchase token to acknowledgedeveloperPayload
- (string): Developer payload (optional)
Consume a purchase (Android only).
Options:
- purchaseToken (string): The purchase token to consume
Check if user is eligible for introductory price or discounts.
Options:
- productId (string): Product ID to check
Returns:
- eligible (boolean): Whether user is eligible to purchaseintroductoryPriceEligible
- (boolean): Whether user is eligible for intro pricediscountEligible
- (boolean): Whether user is eligible for discounts
Present the code redemption sheet (iOS only).
typescript
interface Product {
productId: string;
title: string;
description: string;
price: string;
priceAmount: number;
priceCurrencyCode: string;
priceLocale: string;
subscriptionPeriod?: SubscriptionPeriod;
introductoryPrice?: IntroductoryPrice;
discounts?: Discount[];
}
`$3
`typescript
interface Purchase {
productId: string;
purchaseToken: string;
transactionId: string;
purchaseTime: number;
purchaseState: PurchaseState;
autoRenewing?: boolean;
acknowledged: boolean;
orderId?: string;
packageName?: string;
developerPayload?: string;
userId?: string;
price?: string; // Formatted display price (e.g., "$9.99")
priceAmount?: number; // Numeric price amount (e.g., 9.99)
priceCurrencyCode?: string; // Currency code (e.g., "USD")
}
`$3
`typescript
interface SubscriptionPeriod {
value: number;
unit: PeriodUnit; // 'DAY' | 'WEEK' | 'MONTH' | 'YEAR'
}
`$3
`typescript
enum PurchaseState {
UNSPECIFIED = 0,
PURCHASED = 1,
PENDING = 2
}
``The plugin will reject promises with descriptive error messages when operations fail. Common errors include:
- Product not found
- Purchase cancelled by user
- Network errors
- Store not available
- Invalid product configuration
MIT