import { NativePurchases } from '@capgo/native-purchases';
// Initialize with your app's API keysawait NativePurchases.configure({ apiKey: 'your_api_key_here', appUserID: 'user123' // Optional custom user ID});
Install the package
npm i @capgo/native-purchases
pnpm add @capgo/native-purchases
yarn add @capgo/native-purchases
bun add @capgo/native-purchases
Sync with native projects
npx cap sync
pnpm cap sync
yarn cap sync
bunx cap sync
Configure the plugin
import { NativePurchases } from '@capgo/native-purchases';
// Initialize with your app's API keysawait NativePurchases.configure({ apiKey: 'your_api_key_here', appUserID: 'user123' // Optional custom user ID});
// Fetch available productsconst { products } = await NativePurchases.getProducts({ productIdentifiers: [ 'premium_monthly', 'premium_yearly' ]});
console.log('Available products:', products);
Configure in App Store Connect:
Add to Info.plist
:
<key>SKAdNetworkItems</key><array> <dict> <key>SKAdNetworkIdentifier</key> <string>your-network-id.skadnetwork</string> </dict></array>
Configure in Google Play Console:
Add to AndroidManifest.xml
:
<uses-permission android:name="com.android.vending.BILLING" />
Making purchases
import { NativePurchases } from '@capgo/native-purchases';
// Purchase a producttry { const { customerInfo } = await NativePurchases.purchaseProduct({ productIdentifier: 'premium_monthly' });
console.log('Purchase successful:', customerInfo);
// Check if user has active entitlements if (customerInfo.entitlements.active['premium']) { console.log('User has premium access!'); }} catch (error) { console.error('Purchase failed:', error);}
// Restore purchasesconst { customerInfo } = await NativePurchases.restorePurchases();console.log('Restored purchases:', customerInfo);
Advanced implementation
import { NativePurchases } from '@capgo/native-purchases';
export class PurchaseService { private products: any[] = []; private customerInfo: any = null;
async initialize(userId?: string) { try { // Configure SDK await NativePurchases.configure({ apiKey: process.env.PURCHASES_API_KEY, appUserID: userId, observerMode: false, // Set true if using with other purchase SDKs userDefaultsSuiteName: 'group.com.yourapp' });
// Set user attributes await NativePurchases.setAttributes({ '$email': 'user@example.com', 'user_level': 'gold', 'app_version': '1.0.0' });
// Get initial customer info await this.syncCustomerInfo();
// Listen for updates this.setupListeners(); } catch (error) { console.error('Failed to initialize purchases:', error); } }
private setupListeners() { // Listen for customer info updates NativePurchases.addListener('customerInfoUpdate', (info) => { this.customerInfo = info.customerInfo; this.checkSubscriptionStatus(); });
// Listen for promotional purchases (iOS) NativePurchases.addListener('shouldPurchasePromoProduct', async (data) => { // Handle App Store promotional purchases const { product } = data; const shouldPurchase = await this.showPromotionalOffer(product);
if (shouldPurchase) { await this.purchaseProduct(product.identifier); } }); }
async loadProducts() { const { products } = await NativePurchases.getProducts({ productIdentifiers: [ 'premium_monthly', 'premium_yearly', 'lifetime_access' ] });
this.products = products; return products; }
async purchaseProduct(productId: string) { try { // Show loading this.showLoading(true);
const { customerInfo } = await NativePurchases.purchaseProduct({ productIdentifier: productId });
this.customerInfo = customerInfo;
// Handle successful purchase if (this.hasActiveSubscription()) { this.unlockPremiumFeatures(); this.showSuccessMessage(); }
return customerInfo; } catch (error: any) { // Handle different error cases if (error.userCancelled) { console.log('User cancelled purchase'); } else if (error.code === 'PRODUCT_ALREADY_PURCHASED') { await this.restorePurchases(); } else { this.showErrorMessage(error.message); } throw error; } finally { this.showLoading(false); } }
async restorePurchases() { const { customerInfo } = await NativePurchases.restorePurchases(); this.customerInfo = customerInfo;
if (this.hasActiveSubscription()) { this.showSuccessMessage('Purchases restored!'); this.unlockPremiumFeatures(); } else { this.showInfoMessage('No purchases to restore'); }
return customerInfo; }
async checkTrialOrIntroductoryPrice(productId: string) { const { eligible } = await NativePurchases.checkTrialOrIntroductoryPriceEligibility({ productIdentifiers: [productId] });
return eligible[productId]; }
hasActiveSubscription(): boolean { return this.customerInfo?.entitlements?.active?.['premium'] !== undefined; }
getSubscriptionExpirationDate(): Date | null { const premium = this.customerInfo?.entitlements?.active?.['premium']; return premium ? new Date(premium.expirationDate) : null; }
async syncCustomerInfo() { const { customerInfo } = await NativePurchases.getCustomerInfo(); this.customerInfo = customerInfo; return customerInfo; }
private unlockPremiumFeatures() { // Enable premium features in your app localStorage.setItem('isPremium', 'true'); // Update UI, enable features, etc. }
private showLoading(show: boolean) { // Show/hide loading indicator }
private showSuccessMessage(message = 'Purchase successful!') { // Show success notification }
private showErrorMessage(message: string) { // Show error notification }
private showInfoMessage(message: string) { // Show info notification }
private async showPromotionalOffer(product: any): Promise<boolean> { // Show UI for promotional offer return true; // or false based on user choice }}
configure(options: ConfigureOptions)
Initialize the SDK with your credentials.
Parameters:
options.apiKey
: string - Your app’s API keyoptions.appUserID
: string (optional) - Custom user identifieroptions.observerMode
: boolean (optional) - Disable automatic transaction finishingoptions.userDefaultsSuiteName
: string (optional) - iOS App Group namegetProducts(options: GetProductsOptions)
Fetch product details from the store.
Returns: Promise<{ products: Product[] }>
purchaseProduct(options: PurchaseOptions)
Initiate a purchase.
Returns: Promise<{ customerInfo: CustomerInfo }>
restorePurchases()
Restore previous purchases.
Returns: Promise<{ customerInfo: CustomerInfo }>
getCustomerInfo()
Get current customer information.
Returns: Promise<{ customerInfo: CustomerInfo }>
customerInfoUpdate
: Fired when customer info changesshouldPurchasePromoProduct
: iOS promotional purchase eventsProducts not loading:
Purchases failing:
Subscription status incorrect:
syncCustomerInfo()
to refresh