capacitor-plugin-cdv-purchase 13.18.0 → 13.20.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/README.md +32 -0
- package/dist/index.js +105 -19
- package/dist/index.js.map +1 -1
- package/ios/Sources/PurchasePlugin/PurchasePlugin.swift +127 -37
- package/package.json +2 -1
- package/src/ts/platforms/iaptic-js/iaptic-js-types.d.ts +451 -0
- package/www/store.d.ts +111 -7
- package/www/store.js +105 -19
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "capacitor-plugin-cdv-purchase",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.20.0",
|
|
4
4
|
"description": "In-App Purchases for Capacitor — iOS (StoreKit 2) and Android (Google Play Billing)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"dist/",
|
|
39
39
|
"types/",
|
|
40
40
|
"www/",
|
|
41
|
+
"src/ts/platforms/iaptic-js/iaptic-js-types.d.ts",
|
|
41
42
|
"android/",
|
|
42
43
|
"!android/build",
|
|
43
44
|
"ios/",
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
declare namespace ModuleIapticJS {
|
|
2
|
+
/**
|
|
3
|
+
* Type of product that can be purchased:
|
|
4
|
+
*
|
|
5
|
+
* - subscription: A recurring subscription product
|
|
6
|
+
* - consumable: A product that can be purchased multiple times
|
|
7
|
+
* - non consumable: A product that can only be purchased once
|
|
8
|
+
* - paid subscription: An auto-renewing subscription
|
|
9
|
+
* - non renewing subscription: A subscription that does not auto-renew
|
|
10
|
+
* - application: The application itself
|
|
11
|
+
* - product: A generic product
|
|
12
|
+
*
|
|
13
|
+
* `'non_consumable'` is deprecated: the server never sends it. It is kept so existing
|
|
14
|
+
* code compiles, and will be removed in the next major version. Use `'non consumable'`.
|
|
15
|
+
*/
|
|
16
|
+
export type ProductType = 'subscription' | 'consumable' | 'non consumable' | 'paid subscription' | 'non renewing subscription' | 'application' | 'product' | 'non_consumable';
|
|
17
|
+
/**
|
|
18
|
+
* Represents a pricing phase for an offer
|
|
19
|
+
* @remarks
|
|
20
|
+
* A pricing phase defines how much and when a customer will be charged.
|
|
21
|
+
* For example, a subscription might have an initial trial phase followed by a recurring payment phase.
|
|
22
|
+
*/
|
|
23
|
+
export interface PricingPhase {
|
|
24
|
+
/** Price in micros (1/1,000,000 of the currency unit). For example, $1.99 = 1990000 micros */
|
|
25
|
+
priceMicros: number;
|
|
26
|
+
/** ISO 4217 currency code (e.g., 'USD', 'EUR', 'JPY') */
|
|
27
|
+
currency: string;
|
|
28
|
+
/**
|
|
29
|
+
* ISO 8601 duration string representing the billing period
|
|
30
|
+
* @example
|
|
31
|
+
* - 'P1M' = 1 month
|
|
32
|
+
* - 'P1Y' = 1 year
|
|
33
|
+
* - 'P7D' = 7 days
|
|
34
|
+
*
|
|
35
|
+
* Absent for one-time purchases.
|
|
36
|
+
*/
|
|
37
|
+
billingPeriod: string;
|
|
38
|
+
/**
|
|
39
|
+
* Defines how the subscription recurs
|
|
40
|
+
* @remarks
|
|
41
|
+
* - INFINITE_RECURRING: Subscription continues until explicitly cancelled
|
|
42
|
+
* - NON_RECURRING: One-time purchase that does not auto-renew
|
|
43
|
+
* - FINITE_RECURRING: Subscription that renews a fixed number of times
|
|
44
|
+
*/
|
|
45
|
+
recurrenceMode: 'INFINITE_RECURRING' | 'NON_RECURRING' | 'FINITE_RECURRING';
|
|
46
|
+
/**
|
|
47
|
+
* Defines when payment is collected
|
|
48
|
+
* @remarks
|
|
49
|
+
* - PayAsYouGo: Payment collected at the start of each billing period
|
|
50
|
+
* - UpFront: Full payment collected at time of purchase
|
|
51
|
+
* - FreeTrial: No payment during this phase
|
|
52
|
+
*
|
|
53
|
+
* `'PayUpFront'` is deprecated: the server never sends it. It is kept so existing
|
|
54
|
+
* code compiles, and will be removed in the next major version. Use `'UpFront'`.
|
|
55
|
+
*/
|
|
56
|
+
paymentMode: 'PayAsYouGo' | 'UpFront' | 'FreeTrial' | 'PayUpFront';
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Represents a purchase offer for a product
|
|
60
|
+
* @remarks
|
|
61
|
+
* An offer defines how a product can be purchased, including pricing and billing details
|
|
62
|
+
*/
|
|
63
|
+
export interface Offer {
|
|
64
|
+
/** Unique identifier for the offer in the format 'platform:id' */
|
|
65
|
+
id: string;
|
|
66
|
+
/** Payment platform identifier (e.g., 'stripe', 'google', 'apple') */
|
|
67
|
+
platform: string;
|
|
68
|
+
/** Type of the offer */
|
|
69
|
+
offerType: 'Subscription' | 'Default' | 'Introductory';
|
|
70
|
+
/** Array of pricing phases that make up this offer's payment schedule */
|
|
71
|
+
pricingPhases: PricingPhase[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Represents a product that can be purchased
|
|
75
|
+
*/
|
|
76
|
+
export interface Product {
|
|
77
|
+
/** Type of the product (subscription, consumable, etc.) */
|
|
78
|
+
type: ProductType;
|
|
79
|
+
/** Unique identifier for the product */
|
|
80
|
+
id: string;
|
|
81
|
+
/** Display name of the product shown to customers */
|
|
82
|
+
title: string;
|
|
83
|
+
/** Optional detailed description of the product */
|
|
84
|
+
description?: string;
|
|
85
|
+
/** Available purchase offers for this product */
|
|
86
|
+
offers: Offer[];
|
|
87
|
+
/**
|
|
88
|
+
* Optional additional data associated with the product
|
|
89
|
+
* @remarks
|
|
90
|
+
* This can be used to store custom data needed by your application
|
|
91
|
+
*/
|
|
92
|
+
metadata?: Record<string, any>;
|
|
93
|
+
/** Optional platform identifier (e.g., 'stripe') */
|
|
94
|
+
platform?: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Represents a purchased product
|
|
98
|
+
*/
|
|
99
|
+
export interface Purchase {
|
|
100
|
+
/** Unique identifier for the purchase */
|
|
101
|
+
purchaseId: string;
|
|
102
|
+
/** Unique identifier for the transaction */
|
|
103
|
+
transactionId: string;
|
|
104
|
+
/** Unique identifier for the product */
|
|
105
|
+
productId: string;
|
|
106
|
+
/** Platform identifier (e.g., 'stripe') */
|
|
107
|
+
platform: 'stripe';
|
|
108
|
+
/** Date of the purchase (ISO 8601). Can be absent, check before use. */
|
|
109
|
+
purchaseDate: string;
|
|
110
|
+
/** Date of the last renewal (ISO 8601). Can be absent, check before use. */
|
|
111
|
+
lastRenewalDate: string;
|
|
112
|
+
/** Date of the expiration (ISO 8601). Absent for one-time purchases. */
|
|
113
|
+
expirationDate: string;
|
|
114
|
+
/**
|
|
115
|
+
* Intent of the renewal: 'Lapse' to let the subscription expire, 'Renew' to keep it
|
|
116
|
+
*
|
|
117
|
+
* `'Cancel'` is deprecated: the server never sends it. It is kept so existing
|
|
118
|
+
* code compiles, and will be removed in the next major version. Use `'Lapse'`.
|
|
119
|
+
*/
|
|
120
|
+
renewalIntent: 'Lapse' | 'Renew' | 'Cancel';
|
|
121
|
+
/** Whether the purchase is a trial period */
|
|
122
|
+
isTrialPeriod: boolean;
|
|
123
|
+
/** Price in micros (1/1,000,000 of the currency unit) */
|
|
124
|
+
amountMicros: number;
|
|
125
|
+
/** Currency code (e.g., 'USD', 'EUR') */
|
|
126
|
+
currency: string;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Represents an order for a product
|
|
130
|
+
*/
|
|
131
|
+
export interface Order {
|
|
132
|
+
/** Unique identifier for the offer */
|
|
133
|
+
offerId: string;
|
|
134
|
+
/** Username in the application */
|
|
135
|
+
applicationUsername: string;
|
|
136
|
+
/** URL to redirect to on success */
|
|
137
|
+
successUrl: string;
|
|
138
|
+
/** URL to redirect to on cancel */
|
|
139
|
+
cancelUrl: string;
|
|
140
|
+
/** Optional access token for the user */
|
|
141
|
+
accessToken?: string;
|
|
142
|
+
}
|
|
143
|
+
/** Plan change request */
|
|
144
|
+
export interface PlanChange {
|
|
145
|
+
/** Unique identifier for the purchase to replace */
|
|
146
|
+
purchaseId: string;
|
|
147
|
+
/** New offer to subscribe to */
|
|
148
|
+
offerId: string;
|
|
149
|
+
/** Optional access token for the user */
|
|
150
|
+
accessToken?: string;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Configuration options for creating an Iaptic adapter
|
|
154
|
+
* @remarks
|
|
155
|
+
* Currently only supports Stripe integration, but may support other platforms in the future
|
|
156
|
+
*/
|
|
157
|
+
export interface Config {
|
|
158
|
+
/**
|
|
159
|
+
* Adapter type (currently only 'stripe' is supported)
|
|
160
|
+
* @remarks
|
|
161
|
+
* This field determines which payment platform will be used
|
|
162
|
+
*/
|
|
163
|
+
type: 'stripe';
|
|
164
|
+
/**
|
|
165
|
+
* Your application name as configured on iaptic.com
|
|
166
|
+
* @remarks
|
|
167
|
+
* This must match exactly what you set up in the Iaptic dashboard
|
|
168
|
+
*/
|
|
169
|
+
appName: string;
|
|
170
|
+
/**
|
|
171
|
+
* Your Iaptic public API key
|
|
172
|
+
* @remarks
|
|
173
|
+
* Can be found in your Iaptic dashboard under API settings
|
|
174
|
+
*/
|
|
175
|
+
apiKey: string;
|
|
176
|
+
/**
|
|
177
|
+
* Stripe publishable key
|
|
178
|
+
*/
|
|
179
|
+
stripePublicKey: string;
|
|
180
|
+
/**
|
|
181
|
+
* Optional custom Iaptic URL for private deployments
|
|
182
|
+
* @remarks
|
|
183
|
+
* Only needed if you're using a self-hosted version of Iaptic
|
|
184
|
+
*/
|
|
185
|
+
customIapticUrl?: string;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Response from Iaptic's /stripe/products API
|
|
191
|
+
* @internal
|
|
192
|
+
*/
|
|
193
|
+
export interface GetProductsResponse {
|
|
194
|
+
/** Whether the request was successful */
|
|
195
|
+
ok: boolean;
|
|
196
|
+
/** Array of available products */
|
|
197
|
+
products: Product[];
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Response from Iaptic's /stripe/checkout API
|
|
201
|
+
* @internal
|
|
202
|
+
*/
|
|
203
|
+
export interface PostCheckoutSessionResponse {
|
|
204
|
+
/** Whether the request was successful */
|
|
205
|
+
ok: boolean;
|
|
206
|
+
/** Stripe Checkout URL where the customer will be redirected */
|
|
207
|
+
url: string;
|
|
208
|
+
/** Access token for the customer */
|
|
209
|
+
accessToken: string;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Response from Iaptic's /stripe/purchases API
|
|
213
|
+
* @internal
|
|
214
|
+
*/
|
|
215
|
+
export interface GetPurchasesResponse {
|
|
216
|
+
/** Whether the request was successful */
|
|
217
|
+
ok: boolean;
|
|
218
|
+
/** Array of customer's purchases */
|
|
219
|
+
purchases: Purchase[];
|
|
220
|
+
/** Optional new access token */
|
|
221
|
+
newAccessToken?: string;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Response from Iaptic's /stripe/change-plan API
|
|
225
|
+
* @internal
|
|
226
|
+
*/
|
|
227
|
+
export interface ChangePlanResponse {
|
|
228
|
+
/** Whether the request was successful */
|
|
229
|
+
ok: boolean;
|
|
230
|
+
/** Updated purchase details */
|
|
231
|
+
purchase: Purchase;
|
|
232
|
+
/** Optional new access token */
|
|
233
|
+
newAccessToken?: string;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Main class for interacting with Iaptic's Stripe integration
|
|
237
|
+
* @remarks
|
|
238
|
+
* This class handles all Stripe-related operations including product listing,
|
|
239
|
+
* checkout sessions, and subscription management.
|
|
240
|
+
*/
|
|
241
|
+
export class IapticStripe {
|
|
242
|
+
/**
|
|
243
|
+
* Creates a new IapticStripe instance
|
|
244
|
+
* @param config - Configuration options for the Stripe integration
|
|
245
|
+
* @throws Error if required configuration is missing
|
|
246
|
+
*/
|
|
247
|
+
constructor(config: Config);
|
|
248
|
+
/**
|
|
249
|
+
* Gets a list of available products and their pricing
|
|
250
|
+
* @returns Promise resolving to an array of products
|
|
251
|
+
* @remarks
|
|
252
|
+
* Results are cached locally. Use refreshProducts() to force a fresh fetch.
|
|
253
|
+
*/
|
|
254
|
+
getProducts(): Promise<Product[]>;
|
|
255
|
+
/**
|
|
256
|
+
* Forces a refresh of the products list from the server
|
|
257
|
+
* @returns Promise resolving to an array of products
|
|
258
|
+
*/
|
|
259
|
+
refreshProducts(): Promise<Product[]>;
|
|
260
|
+
/**
|
|
261
|
+
* Gets the current access token if one exists
|
|
262
|
+
* @returns The current access token or undefined if none exists
|
|
263
|
+
*/
|
|
264
|
+
getAccessToken(): string | undefined;
|
|
265
|
+
/**
|
|
266
|
+
* Creates a new order and redirects to Stripe Checkout
|
|
267
|
+
* @param params - Order parameters including product and URLs
|
|
268
|
+
* @throws Error if the checkout session creation fails
|
|
269
|
+
* @remarks
|
|
270
|
+
* This method will redirect the user to Stripe's checkout page on success
|
|
271
|
+
*/
|
|
272
|
+
order(params: Order): Promise<void>;
|
|
273
|
+
/**
|
|
274
|
+
* Gets the customer's purchase history
|
|
275
|
+
* @param accessToken - Optional access token (uses stored token if not provided)
|
|
276
|
+
* @returns Promise resolving to an array of purchases
|
|
277
|
+
* @remarks
|
|
278
|
+
* This method will automatically schedule refresh operations for active subscriptions
|
|
279
|
+
*/
|
|
280
|
+
getPurchases(accessToken?: string): Promise<Purchase[]>;
|
|
281
|
+
/**
|
|
282
|
+
* Redirects to Stripe Customer Portal for subscription management
|
|
283
|
+
* @param params - Portal parameters including return URL
|
|
284
|
+
* @throws Error if portal session creation fails
|
|
285
|
+
* @remarks
|
|
286
|
+
* This method will redirect the user to Stripe's customer portal on success
|
|
287
|
+
*/
|
|
288
|
+
redirectToCustomerPortal(params: {
|
|
289
|
+
returnUrl?: string;
|
|
290
|
+
accessToken?: string;
|
|
291
|
+
}): Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Changes a subscription plan
|
|
294
|
+
* @param planChange - Plan change parameters
|
|
295
|
+
* @returns Promise resolving to the updated purchase details
|
|
296
|
+
* @remarks
|
|
297
|
+
* This method handles immediate plan changes without requiring customer portal access
|
|
298
|
+
*/
|
|
299
|
+
changePlan(planChange: PlanChange): Promise<Purchase>;
|
|
300
|
+
/**
|
|
301
|
+
* Clears all stored data including access tokens and cached products
|
|
302
|
+
*/
|
|
303
|
+
clearStoredData(): void;
|
|
304
|
+
onAccessTokenChange(callback: (accessToken: string) => void): void;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Represents a scheduled refresh for a subscription
|
|
311
|
+
*/
|
|
312
|
+
export interface ScheduledRefresh {
|
|
313
|
+
/** Unique identifier for the scheduled refresh */
|
|
314
|
+
id: string;
|
|
315
|
+
/** Unique identifier for the subscription */
|
|
316
|
+
subscriptionId: string;
|
|
317
|
+
/** Date and time of the scheduled refresh */
|
|
318
|
+
scheduledAt: number;
|
|
319
|
+
/** Whether the refresh has been completed */
|
|
320
|
+
completed: boolean;
|
|
321
|
+
/** Whether the refresh is currently in progress */
|
|
322
|
+
inProgress: boolean;
|
|
323
|
+
/** Reason for the scheduled refresh */
|
|
324
|
+
reason: string;
|
|
325
|
+
}
|
|
326
|
+
export class RefreshScheduler {
|
|
327
|
+
schedules: ScheduledRefresh[];
|
|
328
|
+
constructor(iapticStripe: IapticStripe);
|
|
329
|
+
scheduleRefresh(subscriptionId: string, date: Date, reason: string): void;
|
|
330
|
+
schedulePurchaseRefreshes(purchase: Purchase): void;
|
|
331
|
+
clearSchedules(): void;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Utility functions for the Iaptic library
|
|
336
|
+
*/
|
|
337
|
+
export class Utils {
|
|
338
|
+
/**
|
|
339
|
+
* Base64 encode a string with fallbacks for different environments
|
|
340
|
+
* @param str - String to encode
|
|
341
|
+
* @returns Base64 encoded string
|
|
342
|
+
* @remarks
|
|
343
|
+
* Handles non-ASCII characters and provides fallbacks for older browsers
|
|
344
|
+
* and Node.js environments
|
|
345
|
+
*/
|
|
346
|
+
static base64Encode(str: string): string;
|
|
347
|
+
/**
|
|
348
|
+
* Get and parse a JSON item from localStorage
|
|
349
|
+
* @param key - Storage key
|
|
350
|
+
* @returns Parsed value or null if not found/invalid
|
|
351
|
+
* @internal
|
|
352
|
+
*/
|
|
353
|
+
static storageGetJson<T>(key: string): T | null;
|
|
354
|
+
/**
|
|
355
|
+
* Get a string item from localStorage
|
|
356
|
+
* @param key - Storage key
|
|
357
|
+
* @returns String value or null if not found
|
|
358
|
+
* @internal
|
|
359
|
+
*/
|
|
360
|
+
static storageGetString(key: string): string | null;
|
|
361
|
+
/**
|
|
362
|
+
* Store a JSON-serializable value in localStorage
|
|
363
|
+
* @param key - Storage key
|
|
364
|
+
* @param value - Value to store
|
|
365
|
+
* @returns true if successful, false if storage failed
|
|
366
|
+
* @internal
|
|
367
|
+
*/
|
|
368
|
+
static storageSetJson(key: string, value: any): boolean;
|
|
369
|
+
/**
|
|
370
|
+
* Store a string value in localStorage
|
|
371
|
+
* @param key - Storage key
|
|
372
|
+
* @param value - String to store
|
|
373
|
+
* @returns true if successful, false if storage failed
|
|
374
|
+
* @internal
|
|
375
|
+
*/
|
|
376
|
+
static storageSetString(key: string, value: string): boolean;
|
|
377
|
+
/**
|
|
378
|
+
* Remove an item from localStorage
|
|
379
|
+
* @param key - Storage key
|
|
380
|
+
* @returns true if successful, false if removal failed
|
|
381
|
+
* @internal
|
|
382
|
+
*/
|
|
383
|
+
static storageRemove(key: string): boolean;
|
|
384
|
+
/**
|
|
385
|
+
* Build a URL with query parameters
|
|
386
|
+
* @param baseUrl - Base URL without query parameters
|
|
387
|
+
* @param params - Object containing query parameters
|
|
388
|
+
* @returns Complete URL with encoded query parameters
|
|
389
|
+
* @remarks
|
|
390
|
+
* Handles URL encoding and removes undefined/null parameters
|
|
391
|
+
* @internal
|
|
392
|
+
*/
|
|
393
|
+
static buildUrl(baseUrl: string, params: Record<string, string>): string;
|
|
394
|
+
/**
|
|
395
|
+
* Format a currency amount from micros with proper localization
|
|
396
|
+
* @param amountMicros - Amount in micros (1/1,000,000 of currency unit)
|
|
397
|
+
* @param currency - ISO 4217 currency code (e.g., 'USD', 'EUR')
|
|
398
|
+
* @returns Formatted currency string
|
|
399
|
+
* @example
|
|
400
|
+
* ```ts
|
|
401
|
+
* Utils.formatCurrency(1990000, 'USD') // Returns "$1.99"
|
|
402
|
+
* Utils.formatCurrency(1000000, 'EUR') // Returns "€1"
|
|
403
|
+
* ```
|
|
404
|
+
*/
|
|
405
|
+
static formatCurrency(amountMicros: number, currency: string): string;
|
|
406
|
+
/**
|
|
407
|
+
* Format an ISO 8601 period string into human-readable English
|
|
408
|
+
* @param period - ISO 8601 duration string
|
|
409
|
+
* @returns Human-readable period string
|
|
410
|
+
* @example
|
|
411
|
+
* ```ts
|
|
412
|
+
* Utils.formatBillingPeriodEN('P1M') // Returns "Monthly"
|
|
413
|
+
* Utils.formatBillingPeriodEN('P3M') // Returns "Every 3 months"
|
|
414
|
+
* Utils.formatBillingPeriodEN('P1Y') // Returns "Yearly"
|
|
415
|
+
* ```
|
|
416
|
+
*/
|
|
417
|
+
static formatBillingPeriodEN(period: string): string;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Creates an Iaptic adapter for the specified payment platform
|
|
422
|
+
* @param config - Configuration options for the adapter
|
|
423
|
+
* @returns An initialized adapter instance
|
|
424
|
+
* @throws Error if the specified adapter type is not supported
|
|
425
|
+
* @example
|
|
426
|
+
* ```ts
|
|
427
|
+
* const iaptic = createAdapter({
|
|
428
|
+
* type: 'stripe',
|
|
429
|
+
* appName: 'my-app',
|
|
430
|
+
* apiKey: '1234567890'
|
|
431
|
+
* });
|
|
432
|
+
* ```
|
|
433
|
+
*/
|
|
434
|
+
export function createAdapter(config: Config): IapticStripe;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Global IapticJS object available in browser environments
|
|
439
|
+
*/
|
|
440
|
+
interface Window {
|
|
441
|
+
IapticJS: {
|
|
442
|
+
/** Current version of the IapticJS library */
|
|
443
|
+
version: string;
|
|
444
|
+
/** Function to create a new Iaptic adapter */
|
|
445
|
+
createAdapter: typeof ModuleIapticJS.createAdapter;
|
|
446
|
+
/** Stripe adapter class */
|
|
447
|
+
IapticStripe: typeof ModuleIapticJS.IapticStripe;
|
|
448
|
+
/** Utility functions */
|
|
449
|
+
Utils: typeof ModuleIapticJS.Utils;
|
|
450
|
+
};
|
|
451
|
+
}
|
package/www/store.d.ts
CHANGED
|
@@ -366,6 +366,18 @@ declare namespace CdvPurchase {
|
|
|
366
366
|
/** List of verified receipts */
|
|
367
367
|
verifiedReceipts: VerifiedReceipt[];
|
|
368
368
|
constructor(controller: ValidatorController, log: Logger);
|
|
369
|
+
/** Maximum number of validation attempts for a receipt when failures are temporary */
|
|
370
|
+
maxAttempts: number;
|
|
371
|
+
/** Number of failed attempts in a row, per receipt */
|
|
372
|
+
private failedAttempts;
|
|
373
|
+
/** Backoff for retrying temporary failures (created on first use, it listens to the "online" event) */
|
|
374
|
+
private retry?;
|
|
375
|
+
/**
|
|
376
|
+
* Schedule a new validation if the failure is temporary and attempts remain.
|
|
377
|
+
*
|
|
378
|
+
* @return true if a retry was scheduled
|
|
379
|
+
*/
|
|
380
|
+
private scheduleRetry;
|
|
369
381
|
numRequests: number;
|
|
370
382
|
numResponses: number;
|
|
371
383
|
incrRequestsCounter(): void;
|
|
@@ -393,6 +405,20 @@ declare namespace CdvPurchase {
|
|
|
393
405
|
private removeExpiredCache;
|
|
394
406
|
private runValidatorRequest;
|
|
395
407
|
}
|
|
408
|
+
/**
|
|
409
|
+
* True if a validation error is temporary (validator or store unreachable,
|
|
410
|
+
* server error, timeout, no network) rather than a definitive answer about
|
|
411
|
+
* the receipt.
|
|
412
|
+
*
|
|
413
|
+
* Error responses from the validator come in two shapes:
|
|
414
|
+
* - HTTP 200 with `{ ok: false, status, code }` in the body (iaptic does this,
|
|
415
|
+
* so a store outage is `status: 502, code: 6778002` in the body);
|
|
416
|
+
* - a failed HTTP request, reported by the plugin as `code: COMMUNICATION`
|
|
417
|
+
* with the transport status: 5xx, 408 (timeout), 417 (unreadable response,
|
|
418
|
+
* e.g. a captive portal page), 0 or negative (no network, as reported by
|
|
419
|
+
* XMLHttpRequest or cordova-plugin-advanced-http).
|
|
420
|
+
*/
|
|
421
|
+
function isTransientError(payload: Validator.Response.ErrorPayload): boolean;
|
|
396
422
|
}
|
|
397
423
|
}
|
|
398
424
|
declare namespace CdvPurchase {
|
|
@@ -905,8 +931,8 @@ declare namespace CdvPurchase {
|
|
|
905
931
|
}
|
|
906
932
|
/**
|
|
907
933
|
* Persist a subset of {@link VerifiedPurchase} to device storage so that
|
|
908
|
-
* `
|
|
909
|
-
* without connectivity.
|
|
934
|
+
* `offline.isOwned()` can answer "is this product owned?" when the device
|
|
935
|
+
* is offline or has just restarted without connectivity.
|
|
910
936
|
*
|
|
911
937
|
* Phase 1 — unsigned cache. No JWT, no crypto, no server changes.
|
|
912
938
|
*
|
|
@@ -1046,7 +1072,7 @@ declare namespace CdvPurchase {
|
|
|
1046
1072
|
/**
|
|
1047
1073
|
* Current release number of the plugin.
|
|
1048
1074
|
*/
|
|
1049
|
-
const PLUGIN_VERSION = "13.
|
|
1075
|
+
const PLUGIN_VERSION = "13.20.0";
|
|
1050
1076
|
/**
|
|
1051
1077
|
* Entry class of the plugin.
|
|
1052
1078
|
*/
|
|
@@ -2181,7 +2207,23 @@ declare namespace CdvPurchase {
|
|
|
2181
2207
|
lastRenewalDate?: Date;
|
|
2182
2208
|
/** Time when the subscription is set to expire following this transaction */
|
|
2183
2209
|
expirationDate?: Date;
|
|
2184
|
-
/**
|
|
2210
|
+
/**
|
|
2211
|
+
* True when the transaction has been acknowledged to the platform.
|
|
2212
|
+
*
|
|
2213
|
+
* - Google Play: the purchase was acknowledged (or consumed).
|
|
2214
|
+
* - Apple App Store (StoreKit 2, Capacitor build only): the transaction was finished. StoreKit 2 re-reports
|
|
2215
|
+
* finished non-consumables and non-renewing subscriptions as `approved` at every
|
|
2216
|
+
* app launch; check this flag in your `approved()` handler to skip delivering them again.
|
|
2217
|
+
*
|
|
2218
|
+
* Undefined when the platform doesn't report it (including StoreKit 1 and the Cordova
|
|
2219
|
+
* `cordova-plugin-purchase-storekit2` plugin).
|
|
2220
|
+
*
|
|
2221
|
+
* @example
|
|
2222
|
+
* store.when().approved(transaction => {
|
|
2223
|
+
* if (transaction.isAcknowledged) return transaction.finish(); // already delivered
|
|
2224
|
+
* deliver(transaction).then(() => transaction.finish());
|
|
2225
|
+
* });
|
|
2226
|
+
*/
|
|
2185
2227
|
isAcknowledged?: boolean;
|
|
2186
2228
|
/** True when the transaction is still pending payment. */
|
|
2187
2229
|
isPending?: boolean;
|
|
@@ -3015,7 +3057,7 @@ declare namespace CdvPurchase {
|
|
|
3015
3057
|
/** Extended callbacks with SK2 fields (same as SK2BridgeCallbacks) */
|
|
3016
3058
|
interface CapacitorBridgeCallbacks extends Bridge.BridgeCallbacks {
|
|
3017
3059
|
purchased: (transactionIdentifier: string, productId: string, originalTransactionIdentifier?: string, transactionDate?: string, discountId?: string, expirationDate?: string, jwsRepresentation?: string, quantity?: number) => void;
|
|
3018
|
-
restored: (transactionIdentifier: string, productId: string, originalTransactionIdentifier?: string, transactionDate?: string, discountId?: string, expirationDate?: string, jwsRepresentation?: string, quantity?: number) => void;
|
|
3060
|
+
restored: (transactionIdentifier: string, productId: string, originalTransactionIdentifier?: string, transactionDate?: string, discountId?: string, expirationDate?: string, jwsRepresentation?: string, quantity?: number, isFinished?: boolean) => void;
|
|
3019
3061
|
}
|
|
3020
3062
|
class CapacitorNativeBridge implements Bridge.BridgeInterface {
|
|
3021
3063
|
appStoreReceipt: ApplicationReceipt | null;
|
|
@@ -3279,8 +3321,14 @@ declare namespace CdvPurchase {
|
|
|
3279
3321
|
deferred: (productId: string) => void;
|
|
3280
3322
|
/** Called when a transaction is in "finished" state */
|
|
3281
3323
|
finished: (transactionIdentifier: string, productId: string) => void;
|
|
3282
|
-
/**
|
|
3283
|
-
|
|
3324
|
+
/**
|
|
3325
|
+
* Called when a transaction is in "restored" state.
|
|
3326
|
+
*
|
|
3327
|
+
* `isFinished` is set by StoreKit 2 bridges when known: true when the app
|
|
3328
|
+
* already finished the transaction (e.g. a finished entitlement re-emitted
|
|
3329
|
+
* at launch), false when it is still unfinished.
|
|
3330
|
+
*/
|
|
3331
|
+
restored: (transactionIdentifier: string, productId: string, originalTransactionIdentifier?: string, transactionDate?: string, discountId?: string, expirationDate?: string, jwsRepresentation?: string, quantity?: number, isFinished?: boolean) => void;
|
|
3284
3332
|
/** Called when the application receipt is refreshed */
|
|
3285
3333
|
receiptsRefreshed: (receipt: ApplicationReceipt) => void;
|
|
3286
3334
|
/** Called when a call to "restore" failed */
|
|
@@ -6635,6 +6683,9 @@ declare namespace CdvPurchase {
|
|
|
6635
6683
|
*
|
|
6636
6684
|
* It might be present when the server had to fallback to a backup validation solution. */
|
|
6637
6685
|
warning?: string;
|
|
6686
|
+
/** Present when the server answered from its last successful validation of this
|
|
6687
|
+
* receipt because the store couldn't be reached, instead of asking the store. */
|
|
6688
|
+
cache?: ValidatorCacheInfo;
|
|
6638
6689
|
/** Date and time the receipt was validated.
|
|
6639
6690
|
*
|
|
6640
6691
|
* It will provide the client with a more reliable clock time
|
|
@@ -6642,6 +6693,15 @@ declare namespace CdvPurchase {
|
|
|
6642
6693
|
date?: ISODate;
|
|
6643
6694
|
};
|
|
6644
6695
|
}
|
|
6696
|
+
/** Marker added by the validator to an answer that wasn't confirmed by the store just now. */
|
|
6697
|
+
interface ValidatorCacheInfo {
|
|
6698
|
+
/** Where the answer comes from. `last-verified`: the last answer the store confirmed for this exact receipt. */
|
|
6699
|
+
source: 'last-verified' | (string & {});
|
|
6700
|
+
/** Why the cache was used. `store_unreachable`: the store (Apple, Google, ...) couldn't be reached. */
|
|
6701
|
+
reason: 'store_unreachable' | (string & {});
|
|
6702
|
+
/** When the store last confirmed this receipt (ISO 8601). */
|
|
6703
|
+
lastConfirmedAt: ISODate;
|
|
6704
|
+
}
|
|
6645
6705
|
type NativeTransaction = ({
|
|
6646
6706
|
type: 'braintree';
|
|
6647
6707
|
data: Braintree.TransactionObject;
|
|
@@ -6714,6 +6774,39 @@ declare namespace CdvPurchase {
|
|
|
6714
6774
|
interface UnverifiedReceipt {
|
|
6715
6775
|
receipt: Receipt;
|
|
6716
6776
|
payload: Validator.Response.ErrorPayload;
|
|
6777
|
+
/**
|
|
6778
|
+
* True when validation failed without a definitive answer about the
|
|
6779
|
+
* receipt: the validator (or the store behind it) couldn't be
|
|
6780
|
+
* reached, timed out, answered with a server error, or responded with
|
|
6781
|
+
* data the plugin couldn't process. The receipt may well be valid.
|
|
6782
|
+
*
|
|
6783
|
+
* Don't revoke access on a transient failure: keep what your app (or
|
|
6784
|
+
* your server) last knew, and validate again later.
|
|
6785
|
+
*
|
|
6786
|
+
* The plugin already retried a few times (with backoff) before firing
|
|
6787
|
+
* a transient failure. This matches the plugin's own retry decision:
|
|
6788
|
+
* since v13.20.0, `BAD_RESPONSE` (the validator's answer was
|
|
6789
|
+
* malformed) and `VERIFICATION_FAILED` (the plugin failed while
|
|
6790
|
+
* processing the validator's answer) are reported as transient (they
|
|
6791
|
+
* used to be `transient: false`).
|
|
6792
|
+
*
|
|
6793
|
+
* False when the validator gave a definitive answer (e.g. invalid
|
|
6794
|
+
* receipt, expired subscription, authentication error).
|
|
6795
|
+
*
|
|
6796
|
+
* Transient:
|
|
6797
|
+
* - HTTP 5xx, from the transport or as `payload.status` in the response body
|
|
6798
|
+
* - `CONNECTION_FAILED` (6778002) from the validator
|
|
6799
|
+
* - request timeout, no network, unreadable response
|
|
6800
|
+
* - `BAD_RESPONSE`: the validator's answer was malformed
|
|
6801
|
+
* - `VERIFICATION_FAILED`: the plugin failed while processing the
|
|
6802
|
+
* validator's answer
|
|
6803
|
+
*
|
|
6804
|
+
* Definitive: everything else (HTTP 400 `INVALID_PAYLOAD`, 401/403, 410,
|
|
6805
|
+
* 419 expired, ...).
|
|
6806
|
+
*
|
|
6807
|
+
* Set by the plugin on every `unverified` event since v13.19.0.
|
|
6808
|
+
*/
|
|
6809
|
+
transient?: boolean;
|
|
6717
6810
|
}
|
|
6718
6811
|
/** Receipt data as validated by the receipt validation server */
|
|
6719
6812
|
class VerifiedReceipt {
|
|
@@ -6746,6 +6839,17 @@ declare namespace CdvPurchase {
|
|
|
6746
6839
|
* When a warning is present, you should threat the content of this receipt accordingly.
|
|
6747
6840
|
*/
|
|
6748
6841
|
warning?: string;
|
|
6842
|
+
/**
|
|
6843
|
+
* Set when the validator answered from its last successful validation of this receipt,
|
|
6844
|
+
* because the store (Apple, Google, ...) couldn't be reached.
|
|
6845
|
+
*
|
|
6846
|
+
* `undefined` means the store confirmed this receipt during the validation.
|
|
6847
|
+
* The content is the last one confirmed by the store, `cache.lastConfirmedAt` tells when.
|
|
6848
|
+
*
|
|
6849
|
+
* Receipts with a `cache` are as valid as the others (no purchase is owned past its `expiryDate`),
|
|
6850
|
+
* but you might prefer to validate again later, or tell your users.
|
|
6851
|
+
*/
|
|
6852
|
+
cache?: Validator.Response.ValidatorCacheInfo;
|
|
6749
6853
|
/**
|
|
6750
6854
|
* Id of the product that have been validated. Used internally.
|
|
6751
6855
|
*/
|