@capivv/capacitor-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapivvCapacitor'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url'].gsub(/^git\+/, '').gsub(/\.git$/, '')
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'].gsub(/^git\+/, ''), :tag => s.version.to_s }
13
+ s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '15.0'
15
+ s.dependency 'Capacitor'
16
+ s.swift_version = '5.9'
17
+
18
+ # Required frameworks for StoreKit 2
19
+ s.frameworks = 'StoreKit'
20
+ end
package/README.md ADDED
@@ -0,0 +1,378 @@
1
+ # @capivv/capacitor-sdk
2
+
3
+ Official Capacitor plugin for [Capivv](https://capivv.com) - Revenue as Code for subscription management.
4
+
5
+ This plugin provides in-app purchase and subscription management for Ionic/Capacitor apps, with native support for iOS (StoreKit 2) and Android (Google Play Billing).
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @capivv/capacitor-sdk
11
+ npx cap sync
12
+ ```
13
+
14
+ ## Platform Requirements
15
+
16
+ - **iOS**: iOS 15.0+ (StoreKit 2)
17
+ - **Android**: API 24+ (Google Play Billing Library 6.x)
18
+ - **Web**: Requires Stripe integration (coming soon)
19
+
20
+ ## Configuration
21
+
22
+ ### iOS Setup
23
+
24
+ Add in-app purchase capability in Xcode:
25
+
26
+ 1. Open your app in Xcode
27
+ 2. Select your target → "Signing & Capabilities"
28
+ 3. Click "+ Capability" and add "In-App Purchase"
29
+
30
+ ### Android Setup
31
+
32
+ No additional configuration required. The plugin automatically requests the billing permission.
33
+
34
+ ## Usage
35
+
36
+ ### Initialize the SDK
37
+
38
+ ```typescript
39
+ import { Capivv } from '@capivv/capacitor-sdk';
40
+
41
+ // Configure with your API key
42
+ await Capivv.configure({
43
+ apiKey: 'capivv_pk_your_public_key',
44
+ debug: true, // Enable for development
45
+ });
46
+
47
+ // Identify the current user
48
+ const userInfo = await Capivv.identify({
49
+ userId: 'user_123',
50
+ attributes: {
51
+ email: 'user@example.com',
52
+ name: 'John Doe',
53
+ },
54
+ });
55
+
56
+ console.log('User entitlements:', userInfo.entitlements);
57
+ ```
58
+
59
+ ### Check Entitlements
60
+
61
+ ```typescript
62
+ // Check if user has access to a specific feature
63
+ const result = await Capivv.checkEntitlement({
64
+ entitlementIdentifier: 'premium',
65
+ });
66
+
67
+ if (result.hasAccess) {
68
+ // User has premium access
69
+ showPremiumContent();
70
+ } else {
71
+ // Show paywall
72
+ showPaywall();
73
+ }
74
+
75
+ // Get all active entitlements
76
+ const { entitlements } = await Capivv.getEntitlements();
77
+ ```
78
+
79
+ ### Get Products and Offerings
80
+
81
+ ```typescript
82
+ // Get configured offerings from Capivv dashboard
83
+ const { offerings } = await Capivv.getOfferings();
84
+
85
+ for (const offering of offerings) {
86
+ console.log(`Offering: ${offering.identifier}`);
87
+ for (const product of offering.products) {
88
+ console.log(` ${product.title}: ${product.priceString}`);
89
+ }
90
+ }
91
+
92
+ // Get a specific product
93
+ const { product } = await Capivv.getProduct({
94
+ productIdentifier: 'com.yourapp.premium.monthly',
95
+ });
96
+ ```
97
+
98
+ ### Make a Purchase
99
+
100
+ ```typescript
101
+ import { Capivv, ProductType } from '@capivv/capacitor-sdk';
102
+
103
+ const result = await Capivv.purchase({
104
+ productIdentifier: 'com.yourapp.premium.monthly',
105
+ productType: ProductType.SUBSCRIPTION,
106
+ });
107
+
108
+ if (result.success) {
109
+ console.log('Purchase successful!', result.transaction);
110
+ // Entitlements are automatically updated
111
+ } else {
112
+ console.log('Purchase failed:', result.error);
113
+ }
114
+ ```
115
+
116
+ ### Restore Purchases
117
+
118
+ ```typescript
119
+ // Restore purchases for users who reinstall or switch devices
120
+ const { entitlements } = await Capivv.restorePurchases();
121
+ console.log('Restored entitlements:', entitlements);
122
+ ```
123
+
124
+ ### Listen for Updates
125
+
126
+ ```typescript
127
+ // Listen for entitlement changes
128
+ const listener = await Capivv.addListener('entitlementsUpdated', (event) => {
129
+ console.log('Entitlements updated:', event.entitlements);
130
+ updateUIForEntitlements(event.entitlements);
131
+ });
132
+
133
+ // Listen for purchase completion
134
+ await Capivv.addListener('purchaseCompleted', (event) => {
135
+ console.log('Purchase completed:', event.transaction);
136
+ });
137
+
138
+ // Listen for purchase failures
139
+ await Capivv.addListener('purchaseFailed', (event) => {
140
+ console.error('Purchase failed:', event.error);
141
+ });
142
+
143
+ // Remove listener when done
144
+ listener.remove();
145
+ ```
146
+
147
+ ### Subscription Management
148
+
149
+ ```typescript
150
+ // Open platform-specific subscription management UI
151
+ await Capivv.manageSubscriptions();
152
+ // iOS: Opens App Store subscription settings
153
+ // Android: Opens Google Play subscription management
154
+ ```
155
+
156
+ ### Sync Purchases
157
+
158
+ ```typescript
159
+ // Sync local purchases with server (call on app launch)
160
+ const { entitlements } = await Capivv.syncPurchases();
161
+ ```
162
+
163
+ ## API Reference
164
+
165
+ ### Configuration
166
+
167
+ #### `configure(config: CapivvConfig): Promise<void>`
168
+
169
+ Initialize the SDK with your API key.
170
+
171
+ | Parameter | Type | Required | Description |
172
+ | --------- | ------- | -------- | ---------------------------------------- |
173
+ | apiKey | string | Yes | Your Capivv public API key |
174
+ | apiUrl | string | No | API endpoint (defaults to production) |
175
+ | debug | boolean | No | Enable debug logging |
176
+
177
+ ### User Management
178
+
179
+ #### `identify(options): Promise<UserInfo>`
180
+
181
+ Identify the current user. Creates the user in Capivv if they don't exist.
182
+
183
+ #### `logout(): Promise<void>`
184
+
185
+ Log out the current user and clear cached data.
186
+
187
+ #### `getUserInfo(): Promise<UserInfo>`
188
+
189
+ Get the current user's information including entitlements.
190
+
191
+ ### Products
192
+
193
+ #### `getOfferings(): Promise<{ offerings: Offering[] }>`
194
+
195
+ Get available offerings configured in your Capivv dashboard.
196
+
197
+ #### `getProduct(options): Promise<{ product: Product }>`
198
+
199
+ Get a specific product by identifier.
200
+
201
+ #### `getProducts(options): Promise<{ products: Product[] }>`
202
+
203
+ Get multiple products by identifier.
204
+
205
+ ### Purchases
206
+
207
+ #### `purchase(options): Promise<PurchaseResult>`
208
+
209
+ Purchase a product.
210
+
211
+ #### `restorePurchases(): Promise<{ entitlements: Entitlement[] }>`
212
+
213
+ Restore previous purchases.
214
+
215
+ #### `syncPurchases(): Promise<{ entitlements: Entitlement[] }>`
216
+
217
+ Sync purchases with the server.
218
+
219
+ #### `manageSubscriptions(): Promise<void>`
220
+
221
+ Open the platform-specific subscription management UI.
222
+
223
+ ### Entitlements
224
+
225
+ #### `checkEntitlement(options): Promise<EntitlementCheckResult>`
226
+
227
+ Check if the user has access to a specific entitlement.
228
+
229
+ #### `getEntitlements(): Promise<{ entitlements: Entitlement[] }>`
230
+
231
+ Get all active entitlements for the current user.
232
+
233
+ ### Events
234
+
235
+ | Event | Description |
236
+ | -------------------- | ------------------------------------------ |
237
+ | entitlementsUpdated | Fired when entitlements change |
238
+ | purchaseCompleted | Fired when a purchase completes |
239
+ | purchaseFailed | Fired when a purchase fails |
240
+
241
+ ## Integration with Ionic
242
+
243
+ ### Angular
244
+
245
+ ```typescript
246
+ import { Component, OnInit } from '@angular/core';
247
+ import { Capivv } from '@capivv/capacitor-sdk';
248
+
249
+ @Component({
250
+ selector: 'app-subscription',
251
+ template: `
252
+ <ion-content>
253
+ <ion-list *ngIf="offerings">
254
+ <ion-item *ngFor="let product of offerings[0]?.products" (click)="purchase(product)">
255
+ <ion-label>
256
+ <h2>{{ product.title }}</h2>
257
+ <p>{{ product.priceString }}</p>
258
+ </ion-label>
259
+ </ion-item>
260
+ </ion-list>
261
+ </ion-content>
262
+ `,
263
+ })
264
+ export class SubscriptionPage implements OnInit {
265
+ offerings: Offering[] = [];
266
+
267
+ async ngOnInit() {
268
+ await Capivv.configure({ apiKey: 'your_api_key' });
269
+ await Capivv.identify({ userId: 'user_123' });
270
+
271
+ const { offerings } = await Capivv.getOfferings();
272
+ this.offerings = offerings;
273
+ }
274
+
275
+ async purchase(product: Product) {
276
+ const result = await Capivv.purchase({
277
+ productIdentifier: product.identifier,
278
+ });
279
+
280
+ if (result.success) {
281
+ // Navigate to premium content
282
+ }
283
+ }
284
+ }
285
+ ```
286
+
287
+ ### React
288
+
289
+ ```tsx
290
+ import { useEffect, useState } from 'react';
291
+ import { Capivv, Offering } from '@capivv/capacitor-sdk';
292
+
293
+ function SubscriptionPage() {
294
+ const [offerings, setOfferings] = useState<Offering[]>([]);
295
+
296
+ useEffect(() => {
297
+ async function init() {
298
+ await Capivv.configure({ apiKey: 'your_api_key' });
299
+ await Capivv.identify({ userId: 'user_123' });
300
+
301
+ const { offerings } = await Capivv.getOfferings();
302
+ setOfferings(offerings);
303
+ }
304
+ init();
305
+ }, []);
306
+
307
+ const handlePurchase = async (productId: string) => {
308
+ const result = await Capivv.purchase({ productIdentifier: productId });
309
+ if (result.success) {
310
+ // Navigate to premium content
311
+ }
312
+ };
313
+
314
+ return (
315
+ <IonContent>
316
+ <IonList>
317
+ {offerings[0]?.products.map((product) => (
318
+ <IonItem key={product.identifier} onClick={() => handlePurchase(product.identifier)}>
319
+ <IonLabel>
320
+ <h2>{product.title}</h2>
321
+ <p>{product.priceString}</p>
322
+ </IonLabel>
323
+ </IonItem>
324
+ ))}
325
+ </IonList>
326
+ </IonContent>
327
+ );
328
+ }
329
+ ```
330
+
331
+ ## Testing
332
+
333
+ ### iOS Sandbox Testing
334
+
335
+ 1. Create sandbox testers in App Store Connect
336
+ 2. Sign out of your Apple ID on the device
337
+ 3. Launch your app and attempt a purchase
338
+ 4. Sign in with the sandbox tester account when prompted
339
+
340
+ ### Android Test Purchases
341
+
342
+ 1. Add license testers in Google Play Console
343
+ 2. Upload your app to internal testing track
344
+ 3. Use the license tester accounts to test purchases
345
+
346
+ ## Troubleshooting
347
+
348
+ ### "Not configured" error
349
+
350
+ Make sure to call `configure()` before any other methods:
351
+
352
+ ```typescript
353
+ await Capivv.configure({ apiKey: 'your_api_key' });
354
+ ```
355
+
356
+ ### "Not identified" error
357
+
358
+ Make sure to call `identify()` after configuration:
359
+
360
+ ```typescript
361
+ await Capivv.identify({ userId: 'user_123' });
362
+ ```
363
+
364
+ ### Products not loading
365
+
366
+ - Verify products are configured in App Store Connect / Google Play Console
367
+ - Ensure product IDs match exactly (case-sensitive)
368
+ - For iOS, make sure paid agreements are signed in App Store Connect
369
+ - For Android, ensure the app is uploaded to at least internal testing
370
+
371
+ ## License
372
+
373
+ MIT
374
+
375
+ ## Support
376
+
377
+ - Documentation: https://docs.capivv.com
378
+ - Issues: https://github.com/capivv/capivv/issues
@@ -0,0 +1,74 @@
1
+ ext {
2
+ junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
4
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
5
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
6
+ }
7
+
8
+ buildscript {
9
+ ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.9.22'
10
+ repositories {
11
+ google()
12
+ mavenCentral()
13
+ }
14
+ dependencies {
15
+ classpath 'com.android.tools.build:gradle:8.2.1'
16
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
17
+ }
18
+ }
19
+
20
+ apply plugin: 'com.android.library'
21
+ apply plugin: 'kotlin-android'
22
+
23
+ android {
24
+ namespace "com.capivv.capacitor"
25
+ compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 34
26
+ defaultConfig {
27
+ minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 24
28
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 34
29
+ versionCode 1
30
+ versionName "0.1.0"
31
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
32
+ }
33
+ buildTypes {
34
+ release {
35
+ minifyEnabled false
36
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
37
+ }
38
+ }
39
+ compileOptions {
40
+ sourceCompatibility JavaVersion.VERSION_17
41
+ targetCompatibility JavaVersion.VERSION_17
42
+ }
43
+ kotlinOptions {
44
+ jvmTarget = '17'
45
+ }
46
+ }
47
+
48
+ repositories {
49
+ google()
50
+ mavenCentral()
51
+ }
52
+
53
+ dependencies {
54
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
55
+ implementation project(':capacitor-android')
56
+
57
+ // Google Play Billing
58
+ implementation 'com.android.billingclient:billing-ktx:6.1.0'
59
+
60
+ // Kotlin Coroutines
61
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
62
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3'
63
+
64
+ // JSON
65
+ implementation 'org.json:json:20231013'
66
+
67
+ // OkHttp for API requests
68
+ implementation 'com.squareup.okhttp3:okhttp:4.12.0'
69
+
70
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
71
+ testImplementation "junit:junit:$junitVersion"
72
+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
73
+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
74
+ }
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <!-- Required for Google Play Billing -->
4
+ <uses-permission android:name="com.android.vending.BILLING" />
5
+ </manifest>