@capgo/native-purchases 7.6.0 → 7.7.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.
package/Package.swift
CHANGED
|
@@ -10,7 +10,7 @@ let package = Package(
|
|
|
10
10
|
targets: ["NativePurchasesPlugin"])
|
|
11
11
|
],
|
|
12
12
|
dependencies: [
|
|
13
|
-
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.4.
|
|
13
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.4.3")
|
|
14
14
|
],
|
|
15
15
|
targets: [
|
|
16
16
|
.target(
|
package/README.md
CHANGED
|
@@ -727,6 +727,8 @@ This approach balances immediate user gratification with proper server-side vali
|
|
|
727
727
|
* [`isBillingSupported()`](#isbillingsupported)
|
|
728
728
|
* [`getPluginVersion()`](#getpluginversion)
|
|
729
729
|
* [`getPurchases(...)`](#getpurchases)
|
|
730
|
+
* [`addListener('transactionUpdated', ...)`](#addlistenertransactionupdated-)
|
|
731
|
+
* [`removeAllListeners()`](#removealllisteners)
|
|
730
732
|
* [Interfaces](#interfaces)
|
|
731
733
|
* [Enums](#enums)
|
|
732
734
|
|
|
@@ -843,6 +845,37 @@ This method queries the platform's purchase history for the current user.
|
|
|
843
845
|
--------------------
|
|
844
846
|
|
|
845
847
|
|
|
848
|
+
### addListener('transactionUpdated', ...)
|
|
849
|
+
|
|
850
|
+
```typescript
|
|
851
|
+
addListener(eventName: "transactionUpdated", listenerFunc: (transaction: Transaction) => void) => Promise<PluginListenerHandle>
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
Listen for StoreKit transaction updates delivered by Apple's <a href="#transaction">Transaction</a>.updates.
|
|
855
|
+
Fires on app launch if there are unfinished transactions, and for any updates afterward.
|
|
856
|
+
iOS only.
|
|
857
|
+
|
|
858
|
+
| Param | Type |
|
|
859
|
+
| ------------------ | ----------------------------------------------------------------------------- |
|
|
860
|
+
| **`eventName`** | <code>'transactionUpdated'</code> |
|
|
861
|
+
| **`listenerFunc`** | <code>(transaction: <a href="#transaction">Transaction</a>) => void</code> |
|
|
862
|
+
|
|
863
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>></code>
|
|
864
|
+
|
|
865
|
+
--------------------
|
|
866
|
+
|
|
867
|
+
|
|
868
|
+
### removeAllListeners()
|
|
869
|
+
|
|
870
|
+
```typescript
|
|
871
|
+
removeAllListeners() => Promise<void>
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
Remove all registered listeners
|
|
875
|
+
|
|
876
|
+
--------------------
|
|
877
|
+
|
|
878
|
+
|
|
846
879
|
### Interfaces
|
|
847
880
|
|
|
848
881
|
|
|
@@ -910,6 +943,13 @@ This method queries the platform's purchase history for the current user.
|
|
|
910
943
|
| **`subscriptionPeriod`** | <code><a href="#subscriptionperiod">SubscriptionPeriod</a></code> | The <a href="#product">Product</a> discount subscription period. |
|
|
911
944
|
|
|
912
945
|
|
|
946
|
+
#### PluginListenerHandle
|
|
947
|
+
|
|
948
|
+
| Prop | Type |
|
|
949
|
+
| ------------ | ----------------------------------------- |
|
|
950
|
+
| **`remove`** | <code>() => Promise<void></code> |
|
|
951
|
+
|
|
952
|
+
|
|
913
953
|
### Enums
|
|
914
954
|
|
|
915
955
|
|
package/dist/docs.json
CHANGED
|
@@ -199,6 +199,40 @@
|
|
|
199
199
|
"PURCHASE_TYPE"
|
|
200
200
|
],
|
|
201
201
|
"slug": "getpurchases"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "addListener",
|
|
205
|
+
"signature": "(eventName: \"transactionUpdated\", listenerFunc: (transaction: Transaction) => void) => Promise<PluginListenerHandle>",
|
|
206
|
+
"parameters": [
|
|
207
|
+
{
|
|
208
|
+
"name": "eventName",
|
|
209
|
+
"docs": "",
|
|
210
|
+
"type": "'transactionUpdated'"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"name": "listenerFunc",
|
|
214
|
+
"docs": "",
|
|
215
|
+
"type": "(transaction: Transaction) => void"
|
|
216
|
+
}
|
|
217
|
+
],
|
|
218
|
+
"returns": "Promise<PluginListenerHandle>",
|
|
219
|
+
"tags": [],
|
|
220
|
+
"docs": "Listen for StoreKit transaction updates delivered by Apple's Transaction.updates.\nFires on app launch if there are unfinished transactions, and for any updates afterward.\niOS only.",
|
|
221
|
+
"complexTypes": [
|
|
222
|
+
"PluginListenerHandle",
|
|
223
|
+
"Transaction"
|
|
224
|
+
],
|
|
225
|
+
"slug": "addlistenertransactionupdated-"
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"name": "removeAllListeners",
|
|
229
|
+
"signature": "() => Promise<void>",
|
|
230
|
+
"parameters": [],
|
|
231
|
+
"returns": "Promise<void>",
|
|
232
|
+
"tags": [],
|
|
233
|
+
"docs": "Remove all registered listeners",
|
|
234
|
+
"complexTypes": [],
|
|
235
|
+
"slug": "removealllisteners"
|
|
202
236
|
}
|
|
203
237
|
],
|
|
204
238
|
"properties": []
|
|
@@ -527,6 +561,22 @@
|
|
|
527
561
|
"type": "SubscriptionPeriod"
|
|
528
562
|
}
|
|
529
563
|
]
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
"name": "PluginListenerHandle",
|
|
567
|
+
"slug": "pluginlistenerhandle",
|
|
568
|
+
"docs": "",
|
|
569
|
+
"tags": [],
|
|
570
|
+
"methods": [],
|
|
571
|
+
"properties": [
|
|
572
|
+
{
|
|
573
|
+
"name": "remove",
|
|
574
|
+
"tags": [],
|
|
575
|
+
"docs": "",
|
|
576
|
+
"complexTypes": [],
|
|
577
|
+
"type": "() => Promise<void>"
|
|
578
|
+
}
|
|
579
|
+
]
|
|
530
580
|
}
|
|
531
581
|
],
|
|
532
582
|
"enums": [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PluginListenerHandle } from "@capacitor/core";
|
|
1
2
|
export declare enum ATTRIBUTION_NETWORK {
|
|
2
3
|
APPLE_SEARCH_ADS = 0,
|
|
3
4
|
ADJUST = 1,
|
|
@@ -369,4 +370,12 @@ export interface NativePurchasesPlugin {
|
|
|
369
370
|
}): Promise<{
|
|
370
371
|
purchases: Transaction[];
|
|
371
372
|
}>;
|
|
373
|
+
/**
|
|
374
|
+
* Listen for StoreKit transaction updates delivered by Apple's Transaction.updates.
|
|
375
|
+
* Fires on app launch if there are unfinished transactions, and for any updates afterward.
|
|
376
|
+
* iOS only.
|
|
377
|
+
*/
|
|
378
|
+
addListener(eventName: "transactionUpdated", listenerFunc: (transaction: Transaction) => void): Promise<PluginListenerHandle>;
|
|
379
|
+
/** Remove all registered listeners */
|
|
380
|
+
removeAllListeners(): Promise<void>;
|
|
372
381
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,mBAOX;AAPD,WAAY,mBAAmB;IAC7B,qFAAoB,CAAA;IACpB,iEAAU,CAAA;IACV,uEAAa,CAAA;IACb,iEAAU,CAAA;IACV,iEAAU,CAAA;IACV,qEAAY,CAAA;AACd,CAAC,EAPW,mBAAmB,KAAnB,mBAAmB,QAO9B;AAED,MAAM,CAAN,IAAY,aAUX;AAVD,WAAY,aAAa;IACvB;;OAEG;IACH,gCAAe,CAAA;IAEf;;OAEG;IACH,8BAAa,CAAA;AACf,CAAC,EAVW,aAAa,KAAb,aAAa,QAUxB;AAED;;;;GAIG;AACH,MAAM,CAAN,IAAY,eAyBX;AAzBD,WAAY,eAAe;IACzB;;OAEG;IACH,uEAAa,CAAA;IAEb;;OAEG;IACH,qFAAoB,CAAA;IAEpB;;OAEG;IACH,iFAAkB,CAAA;IAElB;;OAEG;IACH,mFAAmB,CAAA;IAEnB;;OAEG;IACH,+FAAyB,CAAA;AAC3B,CAAC,EAzBW,eAAe,KAAf,eAAe,QAyB1B;AACD,MAAM,CAAN,IAAY,cA2BX;AA3BD,WAAY,cAAc;IACxB,qIAAiD,CAAA;IAEjD;;;OAGG;IACH,qGAAiC,CAAA;IAEjC;;;;OAIG;IACH,iHAAuC,CAAA;IAEvC;;;OAGG;IACH,iGAA+B,CAAA;IAE/B;;;OAGG;IACH,2DAAY,CAAA;AACd,CAAC,EA3BW,cAAc,KAAd,cAAc,QA2BzB;AAED,MAAM,CAAN,IAAY,YA6CX;AA7CD,WAAY,YAAY;IACtB;;OAEG;IACH,mCAAmB,CAAA;IAEnB;;OAEG;IACH,iCAAiB,CAAA;IAEjB;;OAEG;IACH,qCAAqB,CAAA;IAErB;;OAEG;IACH,iCAAiB,CAAA;IAEjB;;OAEG;IACH,uCAAuB,CAAA;IAEvB;;OAEG;IACH,2CAA2B,CAAA;IAE3B;;OAEG;IACH,uCAAuB,CAAA;IAEvB;;OAEG;IACH,mCAAmB,CAAA;IAEnB;;OAEG;IACH,iCAAiB,CAAA;AACnB,CAAC,EA7CW,YAAY,KAAZ,YAAY,QA6CvB;AAED,MAAM,CAAN,IAAY,wBAaX;AAbD,WAAY,wBAAwB;IAClC;;OAEG;IACH,+HAAoC,CAAA;IACpC;;OAEG;IACH,qIAAmC,CAAA;IACnC;;OAEG;IACH,iIAAiC,CAAA;AACnC,CAAC,EAbW,wBAAwB,KAAxB,wBAAwB,QAanC","sourcesContent":["export enum ATTRIBUTION_NETWORK {\n APPLE_SEARCH_ADS = 0,\n ADJUST = 1,\n APPSFLYER = 2,\n BRANCH = 3,\n TENJIN = 4,\n FACEBOOK = 5,\n}\n\nexport enum PURCHASE_TYPE {\n /**\n * A type of SKU for in-app products.\n */\n INAPP = \"inapp\",\n\n /**\n * A type of SKU for subscriptions.\n */\n SUBS = \"subs\",\n}\n\n/**\n * Enum for billing features.\n * Currently, these are only relevant for Google Play Android users:\n * https://developer.android.com/reference/com/android/billingclient/api/BillingClient.FeatureType\n */\nexport enum BILLING_FEATURE {\n /**\n * Purchase/query for subscriptions.\n */\n SUBSCRIPTIONS,\n\n /**\n * Subscriptions update/replace.\n */\n SUBSCRIPTIONS_UPDATE,\n\n /**\n * Purchase/query for in-app items on VR.\n */\n IN_APP_ITEMS_ON_VR,\n\n /**\n * Purchase/query for subscriptions on VR.\n */\n SUBSCRIPTIONS_ON_VR,\n\n /**\n * Launch a price change confirmation flow.\n */\n PRICE_CHANGE_CONFIRMATION,\n}\nexport enum PRORATION_MODE {\n UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY = 0,\n\n /**\n * Replacement takes effect immediately, and the remaining time will be\n * prorated and credited to the user. This is the current default behavior.\n */\n IMMEDIATE_WITH_TIME_PRORATION = 1,\n\n /**\n * Replacement takes effect immediately, and the billing cycle remains the\n * same. The price for the remaining period will be charged. This option is\n * only available for subscription upgrade.\n */\n IMMEDIATE_AND_CHARGE_PRORATED_PRICE = 2,\n\n /**\n * Replacement takes effect immediately, and the new price will be charged on\n * next recurrence time. The billing cycle stays the same.\n */\n IMMEDIATE_WITHOUT_PRORATION = 3,\n\n /**\n * Replacement takes effect when the old plan expires, and the new price will\n * be charged at the same time.\n */\n DEFERRED = 4,\n}\n\nexport enum PACKAGE_TYPE {\n /**\n * A package that was defined with a custom identifier.\n */\n UNKNOWN = \"UNKNOWN\",\n\n /**\n * A package that was defined with a custom identifier.\n */\n CUSTOM = \"CUSTOM\",\n\n /**\n * A package configured with the predefined lifetime identifier.\n */\n LIFETIME = \"LIFETIME\",\n\n /**\n * A package configured with the predefined annual identifier.\n */\n ANNUAL = \"ANNUAL\",\n\n /**\n * A package configured with the predefined six month identifier.\n */\n SIX_MONTH = \"SIX_MONTH\",\n\n /**\n * A package configured with the predefined three month identifier.\n */\n THREE_MONTH = \"THREE_MONTH\",\n\n /**\n * A package configured with the predefined two month identifier.\n */\n TWO_MONTH = \"TWO_MONTH\",\n\n /**\n * A package configured with the predefined monthly identifier.\n */\n MONTHLY = \"MONTHLY\",\n\n /**\n * A package configured with the predefined weekly identifier.\n */\n WEEKLY = \"WEEKLY\",\n}\n\nexport enum INTRO_ELIGIBILITY_STATUS {\n /**\n * RevenueCat doesn't have enough information to determine eligibility.\n */\n INTRO_ELIGIBILITY_STATUS_UNKNOWN = 0,\n /**\n * The user is not eligible for a free trial or intro pricing for this product.\n */\n INTRO_ELIGIBILITY_STATUS_INELIGIBLE,\n /**\n * The user is eligible for a free trial or intro pricing for this product.\n */\n INTRO_ELIGIBILITY_STATUS_ELIGIBLE,\n}\n\nexport interface Transaction {\n /**\n * RevenueCat Id associated to the transaction.\n */\n readonly transactionId: string;\n /**\n * Receipt data for validation (iOS only - base64 encoded receipt)\n */\n readonly receipt?: string;\n /**\n * Product Id associated with the transaction.\n */\n readonly productIdentifier: string;\n /**\n * Purchase date of the transaction in ISO 8601 format.\n */\n readonly purchaseDate: string;\n /**\n * Original purchase date of the transaction in ISO 8601 format (for subscriptions).\n */\n readonly originalPurchaseDate?: string;\n /**\n * Expiration date of the transaction in ISO 8601 format (for subscriptions).\n */\n readonly expirationDate?: string;\n /**\n * Whether the transaction is still active/valid.\n */\n readonly isActive?: boolean;\n /**\n * Whether the subscription will be cancelled at the end of the billing cycle, or null if not cancelled. Only available on iOS.\n */\n readonly willCancel: boolean | null;\n /**\n * Purchase state of the transaction.\n */\n readonly purchaseState?: string;\n /**\n * Order ID associated with the transaction (Android).\n */\n readonly orderId?: string;\n /**\n * Purchase token associated with the transaction (Android).\n */\n readonly purchaseToken?: string;\n /**\n * Whether the purchase has been acknowledged (Android).\n */\n readonly isAcknowledged?: boolean;\n /**\n * Quantity purchased.\n */\n readonly quantity?: number;\n /**\n * Product type (inapp or subs).\n */\n readonly productType?: string;\n /**\n * Whether the transaction is a trial period.\n */\n readonly isTrialPeriod?: boolean;\n /**\n * Whether the transaction is in intro price period.\n */\n readonly isInIntroPricePeriod?: boolean;\n /**\n * Whether the transaction is in grace period.\n */\n readonly isInGracePeriod?: boolean;\n}\n\nexport interface SubscriptionPeriod {\n /**\n * The Subscription Period number of unit.\n */\n readonly numberOfUnits: number;\n /**\n * The Subscription Period unit.\n */\n readonly unit: number;\n}\nexport interface SKProductDiscount {\n /**\n * The Product discount identifier.\n */\n readonly identifier: string;\n /**\n * The Product discount type.\n */\n readonly type: number;\n /**\n * The Product discount price.\n */\n readonly price: number;\n /**\n * Formatted price of the item, including its currency sign, such as €3.99.\n */\n readonly priceString: string;\n /**\n * The Product discount currency symbol.\n */\n readonly currencySymbol: string;\n /**\n * The Product discount currency code.\n */\n readonly currencyCode: string;\n /**\n * The Product discount paymentMode.\n */\n readonly paymentMode: number;\n /**\n * The Product discount number Of Periods.\n */\n readonly numberOfPeriods: number;\n /**\n * The Product discount subscription period.\n */\n readonly subscriptionPeriod: SubscriptionPeriod;\n}\nexport interface Product {\n /**\n * Product Id.\n */\n readonly identifier: string;\n /**\n * Description of the product.\n */\n readonly description: string;\n /**\n * Title of the product.\n */\n readonly title: string;\n /**\n * Price of the product in the local currency.\n */\n readonly price: number;\n /**\n * Formatted price of the item, including its currency sign, such as €3.99.\n */\n readonly priceString: string;\n /**\n * Currency code for price and original price.\n */\n readonly currencyCode: string;\n /**\n * Currency symbol for price and original price.\n */\n readonly currencySymbol: string;\n /**\n * Boolean indicating if the product is sharable with family\n */\n readonly isFamilyShareable: boolean;\n /**\n * Group identifier for the product.\n */\n readonly subscriptionGroupIdentifier: string;\n /**\n * The Product subcription group identifier.\n */\n readonly subscriptionPeriod: SubscriptionPeriod;\n /**\n * The Product introductory Price.\n */\n readonly introductoryPrice: SKProductDiscount | null;\n /**\n * The Product discounts list.\n */\n readonly discounts: SKProductDiscount[];\n}\n\nexport interface NativePurchasesPlugin {\n /**\n * Restores a user's previous and links their appUserIDs to any user's also using those .\n */\n restorePurchases(): Promise<void>;\n\n /**\n * Started purchase process for the given product.\n *\n * @param options - The product to purchase\n * @param options.productIdentifier - The product identifier of the product you want to purchase.\n * @param options.productType - Only Android, the type of product, can be inapp or subs. Will use inapp by default.\n * @param options.planIdentifier - Only Android, the identifier of the plan you want to purchase, require for for subs.\n * @param options.quantity - Only iOS, the number of items you wish to purchase. Will use 1 by default.\n * @param options.appAccountToken - Only iOS, UUID for the user's account. Used to link purchases to the user account for App Store Server Notifications.\n */\n purchaseProduct(options: {\n productIdentifier: string;\n planIdentifier?: string;\n productType?: PURCHASE_TYPE;\n quantity?: number;\n appAccountToken?: string;\n }): Promise<Transaction>;\n\n /**\n * Gets the product info associated with a list of product identifiers.\n *\n * @param options - The product identifiers you wish to retrieve information for\n * @param options.productIdentifiers - Array of product identifiers\n * @param options.productType - Only Android, the type of product, can be inapp or subs. Will use inapp by default.\n * @returns - The requested product info\n */\n getProducts(options: {\n productIdentifiers: string[];\n productType?: PURCHASE_TYPE;\n }): Promise<{ products: Product[] }>;\n\n /**\n * Gets the product info for a single product identifier.\n *\n * @param options - The product identifier you wish to retrieve information for\n * @param options.productIdentifier - The product identifier\n * @param options.productType - Only Android, the type of product, can be inapp or subs. Will use inapp by default.\n * @returns - The requested product info\n */\n getProduct(options: {\n productIdentifier: string;\n productType?: PURCHASE_TYPE;\n }): Promise<{ product: Product }>;\n\n /**\n * Check if billing is supported for the current device.\n *\n *\n */\n isBillingSupported(): Promise<{ isBillingSupported: boolean }>;\n /**\n * Get the native Capacitor plugin version\n *\n * @returns {Promise<{ id: string }>} an Promise with version for this device\n * @throws An error if the something went wrong\n */\n getPluginVersion(): Promise<{ version: string }>;\n\n /**\n * Gets all the user's purchases (both in-app purchases and subscriptions).\n * This method queries the platform's purchase history for the current user.\n *\n * @param options - Optional parameters for filtering purchases\n * @param options.productType - Only Android, filter by product type (inapp or subs). If not specified, returns both types.\n * @returns {Promise<{ purchases: Transaction[] }>} Promise that resolves with array of user's purchases\n * @throws An error if the purchase query fails\n * @since 7.2.0\n */\n getPurchases(options?: {\n productType?: PURCHASE_TYPE;\n }): Promise<{ purchases: Transaction[] }>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,mBAOX;AAPD,WAAY,mBAAmB;IAC7B,qFAAoB,CAAA;IACpB,iEAAU,CAAA;IACV,uEAAa,CAAA;IACb,iEAAU,CAAA;IACV,iEAAU,CAAA;IACV,qEAAY,CAAA;AACd,CAAC,EAPW,mBAAmB,KAAnB,mBAAmB,QAO9B;AAED,MAAM,CAAN,IAAY,aAUX;AAVD,WAAY,aAAa;IACvB;;OAEG;IACH,gCAAe,CAAA;IAEf;;OAEG;IACH,8BAAa,CAAA;AACf,CAAC,EAVW,aAAa,KAAb,aAAa,QAUxB;AAED;;;;GAIG;AACH,MAAM,CAAN,IAAY,eAyBX;AAzBD,WAAY,eAAe;IACzB;;OAEG;IACH,uEAAa,CAAA;IAEb;;OAEG;IACH,qFAAoB,CAAA;IAEpB;;OAEG;IACH,iFAAkB,CAAA;IAElB;;OAEG;IACH,mFAAmB,CAAA;IAEnB;;OAEG;IACH,+FAAyB,CAAA;AAC3B,CAAC,EAzBW,eAAe,KAAf,eAAe,QAyB1B;AACD,MAAM,CAAN,IAAY,cA2BX;AA3BD,WAAY,cAAc;IACxB,qIAAiD,CAAA;IAEjD;;;OAGG;IACH,qGAAiC,CAAA;IAEjC;;;;OAIG;IACH,iHAAuC,CAAA;IAEvC;;;OAGG;IACH,iGAA+B,CAAA;IAE/B;;;OAGG;IACH,2DAAY,CAAA;AACd,CAAC,EA3BW,cAAc,KAAd,cAAc,QA2BzB;AAED,MAAM,CAAN,IAAY,YA6CX;AA7CD,WAAY,YAAY;IACtB;;OAEG;IACH,mCAAmB,CAAA;IAEnB;;OAEG;IACH,iCAAiB,CAAA;IAEjB;;OAEG;IACH,qCAAqB,CAAA;IAErB;;OAEG;IACH,iCAAiB,CAAA;IAEjB;;OAEG;IACH,uCAAuB,CAAA;IAEvB;;OAEG;IACH,2CAA2B,CAAA;IAE3B;;OAEG;IACH,uCAAuB,CAAA;IAEvB;;OAEG;IACH,mCAAmB,CAAA;IAEnB;;OAEG;IACH,iCAAiB,CAAA;AACnB,CAAC,EA7CW,YAAY,KAAZ,YAAY,QA6CvB;AAED,MAAM,CAAN,IAAY,wBAaX;AAbD,WAAY,wBAAwB;IAClC;;OAEG;IACH,+HAAoC,CAAA;IACpC;;OAEG;IACH,qIAAmC,CAAA;IACnC;;OAEG;IACH,iIAAiC,CAAA;AACnC,CAAC,EAbW,wBAAwB,KAAxB,wBAAwB,QAanC","sourcesContent":["import type { PluginListenerHandle } from \"@capacitor/core\";\n\nexport enum ATTRIBUTION_NETWORK {\n APPLE_SEARCH_ADS = 0,\n ADJUST = 1,\n APPSFLYER = 2,\n BRANCH = 3,\n TENJIN = 4,\n FACEBOOK = 5,\n}\n\nexport enum PURCHASE_TYPE {\n /**\n * A type of SKU for in-app products.\n */\n INAPP = \"inapp\",\n\n /**\n * A type of SKU for subscriptions.\n */\n SUBS = \"subs\",\n}\n\n/**\n * Enum for billing features.\n * Currently, these are only relevant for Google Play Android users:\n * https://developer.android.com/reference/com/android/billingclient/api/BillingClient.FeatureType\n */\nexport enum BILLING_FEATURE {\n /**\n * Purchase/query for subscriptions.\n */\n SUBSCRIPTIONS,\n\n /**\n * Subscriptions update/replace.\n */\n SUBSCRIPTIONS_UPDATE,\n\n /**\n * Purchase/query for in-app items on VR.\n */\n IN_APP_ITEMS_ON_VR,\n\n /**\n * Purchase/query for subscriptions on VR.\n */\n SUBSCRIPTIONS_ON_VR,\n\n /**\n * Launch a price change confirmation flow.\n */\n PRICE_CHANGE_CONFIRMATION,\n}\nexport enum PRORATION_MODE {\n UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY = 0,\n\n /**\n * Replacement takes effect immediately, and the remaining time will be\n * prorated and credited to the user. This is the current default behavior.\n */\n IMMEDIATE_WITH_TIME_PRORATION = 1,\n\n /**\n * Replacement takes effect immediately, and the billing cycle remains the\n * same. The price for the remaining period will be charged. This option is\n * only available for subscription upgrade.\n */\n IMMEDIATE_AND_CHARGE_PRORATED_PRICE = 2,\n\n /**\n * Replacement takes effect immediately, and the new price will be charged on\n * next recurrence time. The billing cycle stays the same.\n */\n IMMEDIATE_WITHOUT_PRORATION = 3,\n\n /**\n * Replacement takes effect when the old plan expires, and the new price will\n * be charged at the same time.\n */\n DEFERRED = 4,\n}\n\nexport enum PACKAGE_TYPE {\n /**\n * A package that was defined with a custom identifier.\n */\n UNKNOWN = \"UNKNOWN\",\n\n /**\n * A package that was defined with a custom identifier.\n */\n CUSTOM = \"CUSTOM\",\n\n /**\n * A package configured with the predefined lifetime identifier.\n */\n LIFETIME = \"LIFETIME\",\n\n /**\n * A package configured with the predefined annual identifier.\n */\n ANNUAL = \"ANNUAL\",\n\n /**\n * A package configured with the predefined six month identifier.\n */\n SIX_MONTH = \"SIX_MONTH\",\n\n /**\n * A package configured with the predefined three month identifier.\n */\n THREE_MONTH = \"THREE_MONTH\",\n\n /**\n * A package configured with the predefined two month identifier.\n */\n TWO_MONTH = \"TWO_MONTH\",\n\n /**\n * A package configured with the predefined monthly identifier.\n */\n MONTHLY = \"MONTHLY\",\n\n /**\n * A package configured with the predefined weekly identifier.\n */\n WEEKLY = \"WEEKLY\",\n}\n\nexport enum INTRO_ELIGIBILITY_STATUS {\n /**\n * RevenueCat doesn't have enough information to determine eligibility.\n */\n INTRO_ELIGIBILITY_STATUS_UNKNOWN = 0,\n /**\n * The user is not eligible for a free trial or intro pricing for this product.\n */\n INTRO_ELIGIBILITY_STATUS_INELIGIBLE,\n /**\n * The user is eligible for a free trial or intro pricing for this product.\n */\n INTRO_ELIGIBILITY_STATUS_ELIGIBLE,\n}\n\nexport interface Transaction {\n /**\n * RevenueCat Id associated to the transaction.\n */\n readonly transactionId: string;\n /**\n * Receipt data for validation (iOS only - base64 encoded receipt)\n */\n readonly receipt?: string;\n /**\n * Product Id associated with the transaction.\n */\n readonly productIdentifier: string;\n /**\n * Purchase date of the transaction in ISO 8601 format.\n */\n readonly purchaseDate: string;\n /**\n * Original purchase date of the transaction in ISO 8601 format (for subscriptions).\n */\n readonly originalPurchaseDate?: string;\n /**\n * Expiration date of the transaction in ISO 8601 format (for subscriptions).\n */\n readonly expirationDate?: string;\n /**\n * Whether the transaction is still active/valid.\n */\n readonly isActive?: boolean;\n /**\n * Whether the subscription will be cancelled at the end of the billing cycle, or null if not cancelled. Only available on iOS.\n */\n readonly willCancel: boolean | null;\n /**\n * Purchase state of the transaction.\n */\n readonly purchaseState?: string;\n /**\n * Order ID associated with the transaction (Android).\n */\n readonly orderId?: string;\n /**\n * Purchase token associated with the transaction (Android).\n */\n readonly purchaseToken?: string;\n /**\n * Whether the purchase has been acknowledged (Android).\n */\n readonly isAcknowledged?: boolean;\n /**\n * Quantity purchased.\n */\n readonly quantity?: number;\n /**\n * Product type (inapp or subs).\n */\n readonly productType?: string;\n /**\n * Whether the transaction is a trial period.\n */\n readonly isTrialPeriod?: boolean;\n /**\n * Whether the transaction is in intro price period.\n */\n readonly isInIntroPricePeriod?: boolean;\n /**\n * Whether the transaction is in grace period.\n */\n readonly isInGracePeriod?: boolean;\n}\n\nexport interface SubscriptionPeriod {\n /**\n * The Subscription Period number of unit.\n */\n readonly numberOfUnits: number;\n /**\n * The Subscription Period unit.\n */\n readonly unit: number;\n}\nexport interface SKProductDiscount {\n /**\n * The Product discount identifier.\n */\n readonly identifier: string;\n /**\n * The Product discount type.\n */\n readonly type: number;\n /**\n * The Product discount price.\n */\n readonly price: number;\n /**\n * Formatted price of the item, including its currency sign, such as €3.99.\n */\n readonly priceString: string;\n /**\n * The Product discount currency symbol.\n */\n readonly currencySymbol: string;\n /**\n * The Product discount currency code.\n */\n readonly currencyCode: string;\n /**\n * The Product discount paymentMode.\n */\n readonly paymentMode: number;\n /**\n * The Product discount number Of Periods.\n */\n readonly numberOfPeriods: number;\n /**\n * The Product discount subscription period.\n */\n readonly subscriptionPeriod: SubscriptionPeriod;\n}\nexport interface Product {\n /**\n * Product Id.\n */\n readonly identifier: string;\n /**\n * Description of the product.\n */\n readonly description: string;\n /**\n * Title of the product.\n */\n readonly title: string;\n /**\n * Price of the product in the local currency.\n */\n readonly price: number;\n /**\n * Formatted price of the item, including its currency sign, such as €3.99.\n */\n readonly priceString: string;\n /**\n * Currency code for price and original price.\n */\n readonly currencyCode: string;\n /**\n * Currency symbol for price and original price.\n */\n readonly currencySymbol: string;\n /**\n * Boolean indicating if the product is sharable with family\n */\n readonly isFamilyShareable: boolean;\n /**\n * Group identifier for the product.\n */\n readonly subscriptionGroupIdentifier: string;\n /**\n * The Product subcription group identifier.\n */\n readonly subscriptionPeriod: SubscriptionPeriod;\n /**\n * The Product introductory Price.\n */\n readonly introductoryPrice: SKProductDiscount | null;\n /**\n * The Product discounts list.\n */\n readonly discounts: SKProductDiscount[];\n}\n\nexport interface NativePurchasesPlugin {\n /**\n * Restores a user's previous and links their appUserIDs to any user's also using those .\n */\n restorePurchases(): Promise<void>;\n\n /**\n * Started purchase process for the given product.\n *\n * @param options - The product to purchase\n * @param options.productIdentifier - The product identifier of the product you want to purchase.\n * @param options.productType - Only Android, the type of product, can be inapp or subs. Will use inapp by default.\n * @param options.planIdentifier - Only Android, the identifier of the plan you want to purchase, require for for subs.\n * @param options.quantity - Only iOS, the number of items you wish to purchase. Will use 1 by default.\n * @param options.appAccountToken - Only iOS, UUID for the user's account. Used to link purchases to the user account for App Store Server Notifications.\n */\n purchaseProduct(options: {\n productIdentifier: string;\n planIdentifier?: string;\n productType?: PURCHASE_TYPE;\n quantity?: number;\n appAccountToken?: string;\n }): Promise<Transaction>;\n\n /**\n * Gets the product info associated with a list of product identifiers.\n *\n * @param options - The product identifiers you wish to retrieve information for\n * @param options.productIdentifiers - Array of product identifiers\n * @param options.productType - Only Android, the type of product, can be inapp or subs. Will use inapp by default.\n * @returns - The requested product info\n */\n getProducts(options: {\n productIdentifiers: string[];\n productType?: PURCHASE_TYPE;\n }): Promise<{ products: Product[] }>;\n\n /**\n * Gets the product info for a single product identifier.\n *\n * @param options - The product identifier you wish to retrieve information for\n * @param options.productIdentifier - The product identifier\n * @param options.productType - Only Android, the type of product, can be inapp or subs. Will use inapp by default.\n * @returns - The requested product info\n */\n getProduct(options: {\n productIdentifier: string;\n productType?: PURCHASE_TYPE;\n }): Promise<{ product: Product }>;\n\n /**\n * Check if billing is supported for the current device.\n *\n *\n */\n isBillingSupported(): Promise<{ isBillingSupported: boolean }>;\n /**\n * Get the native Capacitor plugin version\n *\n * @returns {Promise<{ id: string }>} an Promise with version for this device\n * @throws An error if the something went wrong\n */\n getPluginVersion(): Promise<{ version: string }>;\n\n /**\n * Gets all the user's purchases (both in-app purchases and subscriptions).\n * This method queries the platform's purchase history for the current user.\n *\n * @param options - Optional parameters for filtering purchases\n * @param options.productType - Only Android, filter by product type (inapp or subs). If not specified, returns both types.\n * @returns {Promise<{ purchases: Transaction[] }>} Promise that resolves with array of user's purchases\n * @throws An error if the purchase query fails\n * @since 7.2.0\n */\n getPurchases(options?: {\n productType?: PURCHASE_TYPE;\n }): Promise<{ purchases: Transaction[] }>;\n\n /**\n * Listen for StoreKit transaction updates delivered by Apple's Transaction.updates.\n * Fires on app launch if there are unfinished transactions, and for any updates afterward.\n * iOS only.\n */\n addListener(\n eventName: \"transactionUpdated\",\n listenerFunc: (transaction: Transaction) => void,\n ): Promise<PluginListenerHandle>;\n\n /** Remove all registered listeners */\n removeAllListeners(): Promise<void>;\n}\n"]}
|
|
@@ -21,11 +21,97 @@ public class NativePurchasesPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
private let PLUGIN_VERSION = "0.0.25"
|
|
24
|
+
private var transactionUpdatesTask: Task<Void, Never>?
|
|
24
25
|
|
|
25
26
|
@objc func getPluginVersion(_ call: CAPPluginCall) {
|
|
26
27
|
call.resolve(["version": self.PLUGIN_VERSION])
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
public override func load() {
|
|
31
|
+
super.load()
|
|
32
|
+
// Start listening to StoreKit transaction updates as early as possible
|
|
33
|
+
if #available(iOS 15.0, *) {
|
|
34
|
+
startTransactionUpdatesListener()
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
deinit {
|
|
39
|
+
if #available(iOS 15.0, *) { cancelTransactionUpdatesListener() }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private func cancelTransactionUpdatesListener() {
|
|
43
|
+
self.transactionUpdatesTask?.cancel()
|
|
44
|
+
self.transactionUpdatesTask = nil
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@available(iOS 15.0, *)
|
|
48
|
+
private func startTransactionUpdatesListener() {
|
|
49
|
+
// Ensure only one listener is running
|
|
50
|
+
cancelTransactionUpdatesListener()
|
|
51
|
+
let task = Task.detached { [weak self] in
|
|
52
|
+
// Create a single ISO8601DateFormatter once per Task to avoid repeated allocations
|
|
53
|
+
let dateFormatter = ISO8601DateFormatter()
|
|
54
|
+
|
|
55
|
+
for await result in Transaction.updates {
|
|
56
|
+
guard !Task.isCancelled else { break }
|
|
57
|
+
do {
|
|
58
|
+
guard case .verified(let transaction) = result else {
|
|
59
|
+
// Ignore/unverified transactions; nothing to finish
|
|
60
|
+
continue
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Build payload similar to purchase response
|
|
64
|
+
var payload: [String: Any] = ["transactionId": String(transaction.id)]
|
|
65
|
+
|
|
66
|
+
// Always include willCancel key with NSNull() default
|
|
67
|
+
payload["willCancel"] = NSNull()
|
|
68
|
+
|
|
69
|
+
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
|
|
70
|
+
FileManager.default.fileExists(atPath: appStoreReceiptURL.path),
|
|
71
|
+
let receiptData = try? Data(contentsOf: appStoreReceiptURL) {
|
|
72
|
+
payload["receipt"] = receiptData.base64EncodedString()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
payload["productIdentifier"] = transaction.productID
|
|
76
|
+
payload["purchaseDate"] = dateFormatter.string(from: transaction.purchaseDate)
|
|
77
|
+
payload["productType"] = transaction.productType == .autoRenewable ? "subs" : "inapp"
|
|
78
|
+
|
|
79
|
+
if transaction.productType == .autoRenewable {
|
|
80
|
+
payload["originalPurchaseDate"] = dateFormatter.string(from: transaction.originalPurchaseDate)
|
|
81
|
+
if let expirationDate = transaction.expirationDate {
|
|
82
|
+
payload["expirationDate"] = dateFormatter.string(from: expirationDate)
|
|
83
|
+
payload["isActive"] = expirationDate > Date()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let subscriptionStatus = await transaction.subscriptionStatus
|
|
88
|
+
if let subscriptionStatus = subscriptionStatus {
|
|
89
|
+
if subscriptionStatus.state == .subscribed {
|
|
90
|
+
let renewalInfo = subscriptionStatus.renewalInfo
|
|
91
|
+
switch renewalInfo {
|
|
92
|
+
case .verified(let value):
|
|
93
|
+
payload["willCancel"] = !value.willAutoRenew
|
|
94
|
+
case .unverified(_, _):
|
|
95
|
+
// willCancel remains NSNull() for unverified renewalInfo
|
|
96
|
+
break
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Finish the transaction to avoid blocking future purchases
|
|
102
|
+
await transaction.finish()
|
|
103
|
+
|
|
104
|
+
// Notify JS listeners on main thread, after slight delay
|
|
105
|
+
try? await Task.sleep(nanoseconds: 500_000_000) // 0.5s delay
|
|
106
|
+
await MainActor.run {
|
|
107
|
+
self?.notifyListeners("transactionUpdated", data: payload)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
transactionUpdatesTask = task
|
|
113
|
+
}
|
|
114
|
+
|
|
29
115
|
@objc func isBillingSupported(_ call: CAPPluginCall) {
|
|
30
116
|
if #available(iOS 15, *) {
|
|
31
117
|
call.resolve([
|