expo-iap 2.8.0 → 2.8.2
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/CHANGELOG.md +57 -1
- package/CLAUDE.md +44 -7
- package/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +52 -35
- package/build/ExpoIap.types.d.ts +26 -23
- package/build/ExpoIap.types.d.ts.map +1 -1
- package/build/ExpoIap.types.js +0 -1
- package/build/ExpoIap.types.js.map +1 -1
- package/build/index.d.ts +6 -6
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -5
- package/build/index.js.map +1 -1
- package/build/modules/ios.d.ts +8 -8
- package/build/modules/ios.d.ts.map +1 -1
- package/build/modules/ios.js +3 -3
- package/build/modules/ios.js.map +1 -1
- package/build/types/ExpoIapAndroid.types.d.ts +50 -15
- package/build/types/ExpoIapAndroid.types.d.ts.map +1 -1
- package/build/types/ExpoIapAndroid.types.js +11 -6
- package/build/types/ExpoIapAndroid.types.js.map +1 -1
- package/build/types/ExpoIapIOS.types.d.ts +43 -22
- package/build/types/ExpoIapIOS.types.d.ts.map +1 -1
- package/build/types/ExpoIapIOS.types.js.map +1 -1
- package/build/useIAP.d.ts +6 -6
- package/build/useIAP.d.ts.map +1 -1
- package/build/useIAP.js.map +1 -1
- package/bun.lock +122 -456
- package/ios/ExpoIapModule.swift +87 -5
- package/package.json +1 -1
- package/src/ExpoIap.types.ts +45 -45
- package/src/index.ts +14 -24
- package/src/modules/ios.ts +13 -20
- package/src/types/ExpoIapAndroid.types.ts +62 -15
- package/src/types/ExpoIapIOS.types.ts +49 -25
- package/src/useIAP.ts +11 -19
package/ios/ExpoIapModule.swift
CHANGED
|
@@ -106,10 +106,26 @@ func serializeTransaction(_ transaction: Transaction, jwsRepresentationIOS: Stri
|
|
|
106
106
|
|
|
107
107
|
if #available(iOS 15.4, *), let jsonData = jsonData {
|
|
108
108
|
if let price = jsonData["price"] as? NSNumber {
|
|
109
|
+
// START: Deprecated - will be removed in v2.9.0
|
|
110
|
+
// Use currencyCodeIOS, currencySymbolIOS, countryCodeIOS instead
|
|
109
111
|
purchaseMap["priceIOS"] = price.doubleValue
|
|
112
|
+
// END: Deprecated - will be removed in v2.9.0
|
|
110
113
|
}
|
|
111
114
|
if let currency = jsonData["currency"] as? String {
|
|
115
|
+
purchaseMap["currencyCodeIOS"] = currency
|
|
116
|
+
|
|
117
|
+
// Try to get currency symbol from locale
|
|
118
|
+
let locale = Locale(identifier: Locale.identifier(fromComponents: [NSLocale.Key.currencyCode.rawValue: currency]))
|
|
119
|
+
purchaseMap["currencySymbolIOS"] = locale.currencySymbol
|
|
120
|
+
|
|
121
|
+
// START: Deprecated - will be removed in v2.9.0
|
|
122
|
+
// Use currencyCodeIOS instead
|
|
112
123
|
purchaseMap["currencyIOS"] = currency
|
|
124
|
+
// END: Deprecated - will be removed in v2.9.0
|
|
125
|
+
}
|
|
126
|
+
// Extract country code from storefront if available
|
|
127
|
+
if let storefront = jsonData["storefront"] as? String {
|
|
128
|
+
purchaseMap["countryCodeIOS"] = storefront
|
|
113
129
|
}
|
|
114
130
|
}
|
|
115
131
|
|
|
@@ -162,20 +178,86 @@ func serializeSubscription(_ s: Product.SubscriptionInfo?) -> [String: Any?]? {
|
|
|
162
178
|
|
|
163
179
|
@available(iOS 15.0, *)
|
|
164
180
|
func serializeProduct(_ p: Product) -> [String: Any?] {
|
|
181
|
+
// Convert Product.ProductType to our expected 'inapp' or 'subs' string
|
|
182
|
+
let productType: String = p.subscription != nil ? "subs" : "inapp"
|
|
183
|
+
|
|
184
|
+
// For subscription products, add discounts and introductory price
|
|
185
|
+
var discounts: [[String: Any?]]? = nil
|
|
186
|
+
var introductoryPrice: String? = nil
|
|
187
|
+
var introductoryPriceAsAmountIOS: String? = nil
|
|
188
|
+
var introductoryPricePaymentModeIOS: String? = nil
|
|
189
|
+
var introductoryPriceNumberOfPeriodsIOS: String? = nil
|
|
190
|
+
var introductoryPriceSubscriptionPeriodIOS: String? = nil
|
|
191
|
+
var subscriptionPeriodNumberIOS: String? = nil
|
|
192
|
+
var subscriptionPeriodUnitIOS: String? = nil
|
|
193
|
+
|
|
194
|
+
if let subscription = p.subscription {
|
|
195
|
+
// Extract discount information from promotional offers
|
|
196
|
+
if !subscription.promotionalOffers.isEmpty {
|
|
197
|
+
discounts = subscription.promotionalOffers.compactMap { offer in
|
|
198
|
+
return [
|
|
199
|
+
"identifier": offer.id ?? "",
|
|
200
|
+
"type": offer.type.rawValue,
|
|
201
|
+
"numberOfPeriods": "\(offer.periodCount)",
|
|
202
|
+
"price": "\(offer.price)",
|
|
203
|
+
"localizedPrice": offer.displayPrice,
|
|
204
|
+
"paymentMode": offer.paymentMode.rawValue,
|
|
205
|
+
"subscriptionPeriod": getPeriodIOS(offer.period.unit)
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Extract introductory price from introductory offer
|
|
211
|
+
if let introOffer = subscription.introductoryOffer {
|
|
212
|
+
introductoryPrice = introOffer.displayPrice
|
|
213
|
+
introductoryPriceAsAmountIOS = "\(introOffer.price)"
|
|
214
|
+
introductoryPricePaymentModeIOS = introOffer.paymentMode.rawValue
|
|
215
|
+
introductoryPriceNumberOfPeriodsIOS = "\(introOffer.periodCount)"
|
|
216
|
+
introductoryPriceSubscriptionPeriodIOS = getPeriodIOS(introOffer.period.unit)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Extract subscription period information
|
|
220
|
+
subscriptionPeriodNumberIOS = "\(subscription.subscriptionPeriod.value)"
|
|
221
|
+
subscriptionPeriodUnitIOS = getPeriodIOS(subscription.subscriptionPeriod.unit)
|
|
222
|
+
}
|
|
223
|
+
|
|
165
224
|
return [
|
|
166
225
|
"debugDescription": serializeDebug(p.debugDescription),
|
|
167
226
|
"description": p.description,
|
|
168
|
-
|
|
227
|
+
// New iOS-suffixed fields
|
|
228
|
+
"displayNameIOS": p.displayName,
|
|
229
|
+
"discountsIOS": discounts,
|
|
230
|
+
"introductoryPriceIOS": introductoryPrice,
|
|
231
|
+
"introductoryPriceAsAmountIOS": introductoryPriceAsAmountIOS,
|
|
232
|
+
"introductoryPricePaymentModeIOS": introductoryPricePaymentModeIOS,
|
|
233
|
+
"introductoryPriceNumberOfPeriodsIOS": introductoryPriceNumberOfPeriodsIOS,
|
|
234
|
+
"introductoryPriceSubscriptionPeriodIOS": introductoryPriceSubscriptionPeriodIOS,
|
|
235
|
+
"subscriptionPeriodNumberIOS": subscriptionPeriodNumberIOS,
|
|
236
|
+
"subscriptionPeriodUnitIOS": subscriptionPeriodUnitIOS,
|
|
169
237
|
"displayPrice": p.displayPrice,
|
|
170
238
|
"id": p.id,
|
|
171
239
|
"title": p.displayName,
|
|
172
|
-
"
|
|
173
|
-
"
|
|
240
|
+
"isFamilyShareableIOS": p.isFamilyShareable,
|
|
241
|
+
"jsonRepresentationIOS": String(data: p.jsonRepresentation, encoding: .utf8),
|
|
174
242
|
"price": p.price,
|
|
175
|
-
"
|
|
176
|
-
"type":
|
|
243
|
+
"subscriptionInfoIOS": serializeSubscription(p.subscription),
|
|
244
|
+
"type": productType,
|
|
177
245
|
"currency": p.priceFormatStyle.currencyCode,
|
|
178
246
|
"platform": "ios",
|
|
247
|
+
// START: Deprecated - will be removed in v2.9.0
|
|
248
|
+
// Use displayNameIOS instead of displayName
|
|
249
|
+
"displayName": p.displayName,
|
|
250
|
+
// Use discountsIOS instead of discounts
|
|
251
|
+
"discounts": discounts,
|
|
252
|
+
// Use introductoryPriceIOS instead of introductoryPrice
|
|
253
|
+
"introductoryPrice": introductoryPrice,
|
|
254
|
+
// Use isFamilyShareableIOS instead of isFamilyShareable
|
|
255
|
+
"isFamilyShareable": p.isFamilyShareable,
|
|
256
|
+
// Use jsonRepresentationIOS instead of jsonRepresentation
|
|
257
|
+
"jsonRepresentation": String(data: p.jsonRepresentation, encoding: .utf8),
|
|
258
|
+
// Use subscriptionInfoIOS instead of subscription
|
|
259
|
+
"subscription": serializeSubscription(p.subscription),
|
|
260
|
+
// END: Deprecated - will be removed in v2.9.0
|
|
179
261
|
]
|
|
180
262
|
}
|
|
181
263
|
|
package/package.json
CHANGED
package/src/ExpoIap.types.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ProductAndroid,
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
PurchaseAndroid,
|
|
4
|
+
ProductSubscriptionAndroid,
|
|
5
5
|
} from './types/ExpoIapAndroid.types';
|
|
6
6
|
import {
|
|
7
7
|
ProductIOS,
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
PurchaseIOS,
|
|
9
|
+
ProductSubscriptionIOS,
|
|
10
10
|
} from './types/ExpoIapIOS.types';
|
|
11
11
|
import {NATIVE_ERROR_CODES} from './ExpoIapModule';
|
|
12
12
|
|
|
@@ -16,7 +16,11 @@ export type ChangeEventPayload = {
|
|
|
16
16
|
|
|
17
17
|
export type ProductType = 'inapp' | 'subs';
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// COMMON TYPES (Base types shared across all platforms)
|
|
21
|
+
// =============================================================================
|
|
22
|
+
|
|
23
|
+
export type ProductCommon = {
|
|
20
24
|
id: string;
|
|
21
25
|
title: string;
|
|
22
26
|
description: string;
|
|
@@ -25,15 +29,23 @@ export type ProductBase = {
|
|
|
25
29
|
displayPrice: string;
|
|
26
30
|
currency: string;
|
|
27
31
|
price?: number;
|
|
32
|
+
debugDescription?: string;
|
|
33
|
+
platform?: string;
|
|
28
34
|
};
|
|
29
35
|
|
|
30
|
-
export type
|
|
36
|
+
export type PurchaseCommon = {
|
|
31
37
|
id: string; // Transaction identifier - used by finishTransaction
|
|
32
38
|
productId: string; // Product identifier - which product was purchased
|
|
39
|
+
ids?: string[]; // Product identifiers for purchases that include multiple products
|
|
33
40
|
transactionId?: string; // @deprecated - use id instead
|
|
34
41
|
transactionDate: number;
|
|
35
42
|
transactionReceipt: string;
|
|
36
43
|
purchaseToken?: string; // Unified purchase token (jwsRepresentation for iOS, purchaseToken for Android)
|
|
44
|
+
platform?: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type ProductSubscriptionCommon = ProductCommon & {
|
|
48
|
+
type: 'subs';
|
|
37
49
|
};
|
|
38
50
|
|
|
39
51
|
// Define literal platform types for better type discrimination
|
|
@@ -46,35 +58,34 @@ export type Product =
|
|
|
46
58
|
| (ProductIOS & IosPlatform);
|
|
47
59
|
|
|
48
60
|
export type SubscriptionProduct =
|
|
49
|
-
| (
|
|
50
|
-
| (
|
|
61
|
+
| (ProductSubscriptionAndroid & AndroidPlatform)
|
|
62
|
+
| (ProductSubscriptionIOS & IosPlatform);
|
|
51
63
|
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
// Re-export platform-specific types
|
|
65
|
+
export type {
|
|
66
|
+
PurchaseAndroid,
|
|
67
|
+
ProductSubscriptionAndroid,
|
|
68
|
+
} from './types/ExpoIapAndroid.types';
|
|
69
|
+
export type {
|
|
70
|
+
PurchaseIOS,
|
|
71
|
+
ProductSubscriptionIOS,
|
|
72
|
+
} from './types/ExpoIapIOS.types';
|
|
55
73
|
|
|
56
|
-
//
|
|
57
|
-
export type
|
|
58
|
-
|
|
74
|
+
// Unified purchase type for both products and subscriptions
|
|
75
|
+
export type Purchase =
|
|
76
|
+
| (PurchaseAndroid & AndroidPlatform)
|
|
77
|
+
| (PurchaseIOS & IosPlatform);
|
|
59
78
|
|
|
79
|
+
// Legacy type aliases - deprecated, use Purchase instead
|
|
60
80
|
/**
|
|
61
|
-
* @deprecated Use
|
|
81
|
+
* @deprecated Use `Purchase` instead. This type alias will be removed in v2.9.0.
|
|
62
82
|
*/
|
|
63
|
-
export type
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
| (ProductPurchaseIOS & IosPlatform);
|
|
69
|
-
|
|
70
|
-
// Union type for platform-specific subscription purchase types (legacy support)
|
|
71
|
-
export type SubscriptionPurchase =
|
|
72
|
-
| (ProductPurchaseAndroid & AndroidPlatform & {autoRenewingAndroid: boolean})
|
|
73
|
-
| (ProductPurchaseIOS & IosPlatform);
|
|
74
|
-
|
|
75
|
-
export type Purchase = ProductPurchase | SubscriptionPurchase;
|
|
83
|
+
export type ProductPurchase = Purchase;
|
|
84
|
+
/**
|
|
85
|
+
* @deprecated Use `Purchase` instead. This type alias will be removed in v2.9.0.
|
|
86
|
+
*/
|
|
87
|
+
export type SubscriptionPurchase = Purchase;
|
|
76
88
|
|
|
77
|
-
// Legacy result type
|
|
78
89
|
export type PurchaseResult = {
|
|
79
90
|
responseCode?: number;
|
|
80
91
|
debugMessage?: string;
|
|
@@ -310,7 +321,7 @@ export interface UnifiedRequestPurchaseProps {
|
|
|
310
321
|
readonly skus?: string[]; // Multiple SKUs (Android native, iOS uses first item)
|
|
311
322
|
|
|
312
323
|
// iOS-specific properties (ignored on Android)
|
|
313
|
-
readonly
|
|
324
|
+
readonly andDangerouslyFinishTransactionAutomatically?: boolean;
|
|
314
325
|
readonly appAccountToken?: string;
|
|
315
326
|
readonly quantity?: number;
|
|
316
327
|
readonly withOffer?: import('./types/ExpoIapIOS.types').PaymentDiscount;
|
|
@@ -328,9 +339,9 @@ export interface UnifiedRequestPurchaseProps {
|
|
|
328
339
|
/**
|
|
329
340
|
* iOS-specific purchase request parameters
|
|
330
341
|
*/
|
|
331
|
-
export interface
|
|
342
|
+
export interface RequestPurchaseIosProps {
|
|
332
343
|
readonly sku: string;
|
|
333
|
-
readonly
|
|
344
|
+
readonly andDangerouslyFinishTransactionAutomatically?: boolean;
|
|
334
345
|
readonly appAccountToken?: string;
|
|
335
346
|
readonly quantity?: number;
|
|
336
347
|
readonly withOffer?: import('./types/ExpoIapIOS.types').PaymentDiscount;
|
|
@@ -364,7 +375,7 @@ export interface RequestSubscriptionAndroidProps
|
|
|
364
375
|
* Allows clear separation of iOS and Android parameters
|
|
365
376
|
*/
|
|
366
377
|
export interface RequestPurchasePropsByPlatforms {
|
|
367
|
-
readonly ios?:
|
|
378
|
+
readonly ios?: RequestPurchaseIosProps;
|
|
368
379
|
readonly android?: RequestPurchaseAndroidProps;
|
|
369
380
|
}
|
|
370
381
|
|
|
@@ -372,7 +383,7 @@ export interface RequestPurchasePropsByPlatforms {
|
|
|
372
383
|
* Modern platform-specific subscription request structure (v2.7.0+)
|
|
373
384
|
*/
|
|
374
385
|
export interface RequestSubscriptionPropsByPlatforms {
|
|
375
|
-
readonly ios?:
|
|
386
|
+
readonly ios?: RequestPurchaseIosProps;
|
|
376
387
|
readonly android?: RequestSubscriptionAndroidProps;
|
|
377
388
|
}
|
|
378
389
|
|
|
@@ -387,14 +398,3 @@ export type RequestPurchaseProps = RequestPurchasePropsByPlatforms;
|
|
|
387
398
|
* This is the recommended API moving forward
|
|
388
399
|
*/
|
|
389
400
|
export type RequestSubscriptionProps = RequestSubscriptionPropsByPlatforms;
|
|
390
|
-
|
|
391
|
-
// ============================================================================
|
|
392
|
-
// Deprecated Aliases for Backward Compatibility
|
|
393
|
-
// ============================================================================
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* @deprecated Use RequestPurchaseIOSProps instead. This alias will be removed in v3.0.0.
|
|
397
|
-
*/
|
|
398
|
-
export type RequestPurchaseIosProps = RequestPurchaseIOSProps;
|
|
399
|
-
|
|
400
|
-
// Note: Type guard functions are exported from index.ts to avoid conflicts
|
package/src/index.ts
CHANGED
|
@@ -18,16 +18,14 @@ import {
|
|
|
18
18
|
// Types
|
|
19
19
|
import {
|
|
20
20
|
Product,
|
|
21
|
-
ProductPurchase,
|
|
22
21
|
Purchase,
|
|
23
22
|
PurchaseError,
|
|
24
23
|
PurchaseResult,
|
|
25
24
|
RequestSubscriptionProps,
|
|
26
25
|
RequestPurchaseProps,
|
|
27
26
|
SubscriptionProduct,
|
|
28
|
-
SubscriptionPurchase,
|
|
29
27
|
} from './ExpoIap.types';
|
|
30
|
-
import {
|
|
28
|
+
import {PurchaseAndroid} from './types/ExpoIapAndroid.types';
|
|
31
29
|
import {PaymentDiscount} from './types/ExpoIapIOS.types';
|
|
32
30
|
|
|
33
31
|
// Export all types
|
|
@@ -281,7 +279,7 @@ export const getPurchaseHistory = ({
|
|
|
281
279
|
}: {
|
|
282
280
|
alsoPublishToEventListener?: boolean;
|
|
283
281
|
onlyIncludeActiveItems?: boolean;
|
|
284
|
-
} = {}): Promise<
|
|
282
|
+
} = {}): Promise<Purchase[]> => {
|
|
285
283
|
console.warn(
|
|
286
284
|
'`getPurchaseHistory` is deprecated. Use `getPurchaseHistories` instead. This function will be removed in version 3.0.0.',
|
|
287
285
|
);
|
|
@@ -297,7 +295,7 @@ export const getPurchaseHistories = ({
|
|
|
297
295
|
}: {
|
|
298
296
|
alsoPublishToEventListener?: boolean;
|
|
299
297
|
onlyIncludeActiveItems?: boolean;
|
|
300
|
-
} = {}): Promise<
|
|
298
|
+
} = {}): Promise<Purchase[]> =>
|
|
301
299
|
(
|
|
302
300
|
Platform.select({
|
|
303
301
|
ios: async () => {
|
|
@@ -323,7 +321,7 @@ export const getAvailablePurchases = ({
|
|
|
323
321
|
}: {
|
|
324
322
|
alsoPublishToEventListener?: boolean;
|
|
325
323
|
onlyIncludeActiveItems?: boolean;
|
|
326
|
-
} = {}): Promise<
|
|
324
|
+
} = {}): Promise<Purchase[]> =>
|
|
327
325
|
(
|
|
328
326
|
Platform.select({
|
|
329
327
|
ios: () =>
|
|
@@ -409,13 +407,7 @@ const normalizeRequestProps = (
|
|
|
409
407
|
*/
|
|
410
408
|
export const requestPurchase = (
|
|
411
409
|
requestObj: PurchaseRequest,
|
|
412
|
-
): Promise<
|
|
413
|
-
| ProductPurchase
|
|
414
|
-
| SubscriptionPurchase
|
|
415
|
-
| ProductPurchase[]
|
|
416
|
-
| SubscriptionPurchase[]
|
|
417
|
-
| void
|
|
418
|
-
> => {
|
|
410
|
+
): Promise<Purchase | Purchase[] | void> => {
|
|
419
411
|
const {request, type = 'inapp'} = requestObj;
|
|
420
412
|
|
|
421
413
|
if (Platform.OS === 'ios') {
|
|
@@ -429,7 +421,7 @@ export const requestPurchase = (
|
|
|
429
421
|
|
|
430
422
|
const {
|
|
431
423
|
sku,
|
|
432
|
-
|
|
424
|
+
andDangerouslyFinishTransactionAutomatically = false,
|
|
433
425
|
appAccountToken,
|
|
434
426
|
quantity,
|
|
435
427
|
withOffer,
|
|
@@ -439,15 +431,13 @@ export const requestPurchase = (
|
|
|
439
431
|
const offer = offerToRecordIOS(withOffer);
|
|
440
432
|
const purchase = await ExpoIapModule.buyProduct(
|
|
441
433
|
sku,
|
|
442
|
-
|
|
434
|
+
andDangerouslyFinishTransactionAutomatically,
|
|
443
435
|
appAccountToken,
|
|
444
436
|
quantity ?? -1,
|
|
445
437
|
offer,
|
|
446
438
|
);
|
|
447
439
|
|
|
448
|
-
return type === 'inapp'
|
|
449
|
-
? (purchase as ProductPurchase)
|
|
450
|
-
: (purchase as SubscriptionPurchase);
|
|
440
|
+
return type === 'inapp' ? (purchase as Purchase) : (purchase as Purchase);
|
|
451
441
|
})();
|
|
452
442
|
}
|
|
453
443
|
|
|
@@ -478,7 +468,7 @@ export const requestPurchase = (
|
|
|
478
468
|
obfuscatedProfileId: obfuscatedProfileIdAndroid,
|
|
479
469
|
offerTokenArr: [],
|
|
480
470
|
isOfferPersonalized: isOfferPersonalized ?? false,
|
|
481
|
-
}) as Promise<
|
|
471
|
+
}) as Promise<Purchase[]>;
|
|
482
472
|
})();
|
|
483
473
|
}
|
|
484
474
|
|
|
@@ -504,7 +494,7 @@ export const requestPurchase = (
|
|
|
504
494
|
obfuscatedProfileId: obfuscatedProfileIdAndroid,
|
|
505
495
|
offerTokenArr: subscriptionOffers.map((so: any) => so.offerToken),
|
|
506
496
|
isOfferPersonalized: isOfferPersonalized ?? false,
|
|
507
|
-
}) as Promise<
|
|
497
|
+
}) as Promise<Purchase[]>;
|
|
508
498
|
})();
|
|
509
499
|
}
|
|
510
500
|
|
|
@@ -543,13 +533,13 @@ export const requestPurchase = (
|
|
|
543
533
|
*/
|
|
544
534
|
export const requestSubscription = async (
|
|
545
535
|
request: RequestSubscriptionProps,
|
|
546
|
-
): Promise<
|
|
536
|
+
): Promise<Purchase | Purchase[] | null | void> => {
|
|
547
537
|
console.warn(
|
|
548
538
|
"`requestSubscription` is deprecated and will be removed in version 3.0.0. Use `requestPurchase({ request, type: 'subs' })` instead.",
|
|
549
539
|
);
|
|
550
540
|
return (await requestPurchase({request, type: 'subs'})) as
|
|
551
|
-
|
|
|
552
|
-
|
|
|
541
|
+
| Purchase
|
|
542
|
+
| Purchase[]
|
|
553
543
|
| null
|
|
554
544
|
| void;
|
|
555
545
|
};
|
|
@@ -574,7 +564,7 @@ export const finishTransaction = ({
|
|
|
574
564
|
return Promise.resolve(true);
|
|
575
565
|
},
|
|
576
566
|
android: async () => {
|
|
577
|
-
const androidPurchase = purchase as
|
|
567
|
+
const androidPurchase = purchase as PurchaseAndroid;
|
|
578
568
|
|
|
579
569
|
if (isConsumable) {
|
|
580
570
|
return ExpoIapModule.consumeProduct(androidPurchase.purchaseToken);
|
package/src/modules/ios.ts
CHANGED
|
@@ -5,12 +5,7 @@ import {purchaseUpdatedListener} from '..';
|
|
|
5
5
|
import ExpoIapModule from '../ExpoIapModule';
|
|
6
6
|
|
|
7
7
|
// Types
|
|
8
|
-
import {
|
|
9
|
-
ProductPurchase,
|
|
10
|
-
PurchaseError,
|
|
11
|
-
Purchase,
|
|
12
|
-
SubscriptionPurchase,
|
|
13
|
-
} from '../ExpoIap.types';
|
|
8
|
+
import {Purchase, PurchaseError} from '../ExpoIap.types';
|
|
14
9
|
import type {
|
|
15
10
|
ProductStatusIOS,
|
|
16
11
|
AppTransactionIOS,
|
|
@@ -18,7 +13,7 @@ import type {
|
|
|
18
13
|
import {Linking} from 'react-native';
|
|
19
14
|
|
|
20
15
|
export type TransactionEvent = {
|
|
21
|
-
transaction?:
|
|
16
|
+
transaction?: Purchase;
|
|
22
17
|
error?: PurchaseError;
|
|
23
18
|
};
|
|
24
19
|
|
|
@@ -39,7 +34,7 @@ export type TransactionEvent = {
|
|
|
39
34
|
export const transactionUpdatedIOS = (
|
|
40
35
|
listener: (event: TransactionEvent) => void,
|
|
41
36
|
) => {
|
|
42
|
-
const
|
|
37
|
+
const isPurchase = (item: unknown): item is Purchase => {
|
|
43
38
|
return (
|
|
44
39
|
item != null &&
|
|
45
40
|
typeof item === 'object' &&
|
|
@@ -51,18 +46,18 @@ export const transactionUpdatedIOS = (
|
|
|
51
46
|
|
|
52
47
|
// Helper function to safely convert Purchase to TransactionEvent
|
|
53
48
|
const mapPurchaseToTransactionEvent = (
|
|
54
|
-
purchase: Purchase
|
|
49
|
+
purchase: Purchase,
|
|
55
50
|
): TransactionEvent => {
|
|
56
51
|
// Validate the purchase object before casting
|
|
57
|
-
if (
|
|
52
|
+
if (isPurchase(purchase)) {
|
|
58
53
|
return {
|
|
59
|
-
transaction: purchase as
|
|
54
|
+
transaction: purchase as Purchase,
|
|
60
55
|
};
|
|
61
56
|
}
|
|
62
57
|
|
|
63
58
|
// Fallback: create a basic TransactionEvent structure
|
|
64
59
|
return {
|
|
65
|
-
transaction: purchase as
|
|
60
|
+
transaction: purchase as Purchase,
|
|
66
61
|
};
|
|
67
62
|
};
|
|
68
63
|
|
|
@@ -138,9 +133,7 @@ export const subscriptionStatusIOS = (
|
|
|
138
133
|
*
|
|
139
134
|
* @platform iOS
|
|
140
135
|
*/
|
|
141
|
-
export const currentEntitlementIOS = (
|
|
142
|
-
sku: string,
|
|
143
|
-
): Promise<ProductPurchase> => {
|
|
136
|
+
export const currentEntitlementIOS = (sku: string): Promise<Purchase> => {
|
|
144
137
|
return ExpoIapModule.currentEntitlement(sku);
|
|
145
138
|
};
|
|
146
139
|
|
|
@@ -153,7 +146,7 @@ export const currentEntitlementIOS = (
|
|
|
153
146
|
*
|
|
154
147
|
* @platform iOS
|
|
155
148
|
*/
|
|
156
|
-
export const latestTransactionIOS = (sku: string): Promise<
|
|
149
|
+
export const latestTransactionIOS = (sku: string): Promise<Purchase> => {
|
|
157
150
|
return ExpoIapModule.latestTransaction(sku);
|
|
158
151
|
};
|
|
159
152
|
|
|
@@ -241,7 +234,7 @@ export const getTransactionJwsIOS = (sku: string): Promise<string> => {
|
|
|
241
234
|
* isValid: boolean;
|
|
242
235
|
* receiptData: string;
|
|
243
236
|
* jwsRepresentation: string;
|
|
244
|
-
* latestTransaction?:
|
|
237
|
+
* latestTransaction?: Purchase;
|
|
245
238
|
* }>}
|
|
246
239
|
*/
|
|
247
240
|
export const validateReceiptIOS = async (
|
|
@@ -250,7 +243,7 @@ export const validateReceiptIOS = async (
|
|
|
250
243
|
isValid: boolean;
|
|
251
244
|
receiptData: string;
|
|
252
245
|
jwsRepresentation: string;
|
|
253
|
-
latestTransaction?:
|
|
246
|
+
latestTransaction?: Purchase;
|
|
254
247
|
}> => {
|
|
255
248
|
const result = await ExpoIapModule.validateReceiptIOS(sku);
|
|
256
249
|
return result;
|
|
@@ -362,7 +355,7 @@ export const subscriptionStatus = (
|
|
|
362
355
|
/**
|
|
363
356
|
* @deprecated Use `currentEntitlementIOS` instead. This function will be removed in version 3.0.0.
|
|
364
357
|
*/
|
|
365
|
-
export const currentEntitlement = (sku: string): Promise<
|
|
358
|
+
export const currentEntitlement = (sku: string): Promise<Purchase> => {
|
|
366
359
|
console.warn(
|
|
367
360
|
'`currentEntitlement` is deprecated. Use `currentEntitlementIOS` instead. This function will be removed in version 3.0.0.',
|
|
368
361
|
);
|
|
@@ -372,7 +365,7 @@ export const currentEntitlement = (sku: string): Promise<ProductPurchase> => {
|
|
|
372
365
|
/**
|
|
373
366
|
* @deprecated Use `latestTransactionIOS` instead. This function will be removed in version 3.0.0.
|
|
374
367
|
*/
|
|
375
|
-
export const latestTransaction = (sku: string): Promise<
|
|
368
|
+
export const latestTransaction = (sku: string): Promise<Purchase> => {
|
|
376
369
|
console.warn(
|
|
377
370
|
'`latestTransaction` is deprecated. Use `latestTransactionIOS` instead. This function will be removed in version 3.0.0.',
|
|
378
371
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {PurchaseCommon, ProductCommon} from '../ExpoIap.types';
|
|
2
2
|
|
|
3
|
-
type
|
|
3
|
+
type ProductAndroidOneTimePurchaseOfferDetail = {
|
|
4
4
|
priceCurrencyCode: string;
|
|
5
5
|
formattedPrice: string;
|
|
6
6
|
priceAmountMicros: string;
|
|
@@ -20,21 +20,34 @@ type PricingPhasesAndroid = {
|
|
|
20
20
|
pricingPhaseList: PricingPhaseAndroid[];
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
type
|
|
23
|
+
type ProductSubscriptionAndroidOfferDetail = {
|
|
24
24
|
basePlanId: string;
|
|
25
|
-
offerId: string;
|
|
25
|
+
offerId: string | null;
|
|
26
26
|
offerToken: string;
|
|
27
27
|
offerTags: string[];
|
|
28
28
|
pricingPhases: PricingPhasesAndroid;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
export type ProductAndroid =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
export type ProductAndroid = ProductCommon & {
|
|
32
|
+
nameAndroid: string;
|
|
33
|
+
oneTimePurchaseOfferDetailsAndroid?: ProductAndroidOneTimePurchaseOfferDetail;
|
|
34
|
+
platform: 'android';
|
|
35
|
+
subscriptionOfferDetailsAndroid?: ProductSubscriptionAndroidOfferDetail[];
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated Use `nameAndroid` instead. This field will be removed in v2.9.0.
|
|
38
|
+
*/
|
|
39
|
+
name?: string;
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated Use `oneTimePurchaseOfferDetailsAndroid` instead. This field will be removed in v2.9.0.
|
|
42
|
+
*/
|
|
43
|
+
oneTimePurchaseOfferDetails?: ProductAndroidOneTimePurchaseOfferDetail;
|
|
44
|
+
/**
|
|
45
|
+
* @deprecated Use `subscriptionOfferDetailsAndroid` instead. This field will be removed in v2.9.0.
|
|
46
|
+
*/
|
|
47
|
+
subscriptionOfferDetails?: ProductSubscriptionAndroidOfferDetail[];
|
|
35
48
|
};
|
|
36
49
|
|
|
37
|
-
type
|
|
50
|
+
type ProductSubscriptionAndroidOfferDetails = {
|
|
38
51
|
basePlanId: string;
|
|
39
52
|
offerId: string | null;
|
|
40
53
|
offerToken: string;
|
|
@@ -42,10 +55,17 @@ type SubscriptionOfferAndroid = {
|
|
|
42
55
|
offerTags: string[];
|
|
43
56
|
};
|
|
44
57
|
|
|
45
|
-
export type
|
|
46
|
-
|
|
58
|
+
export type ProductSubscriptionAndroid = ProductAndroid & {
|
|
59
|
+
subscriptionOfferDetailsAndroid: ProductSubscriptionAndroidOfferDetails[];
|
|
60
|
+
/**
|
|
61
|
+
* @deprecated Use `subscriptionOfferDetailsAndroid` instead. This field will be removed in v2.9.0.
|
|
62
|
+
*/
|
|
63
|
+
subscriptionOfferDetails?: ProductSubscriptionAndroidOfferDetails[];
|
|
47
64
|
};
|
|
48
65
|
|
|
66
|
+
// Legacy naming for backward compatibility
|
|
67
|
+
export type SubscriptionProductAndroid = ProductSubscriptionAndroid;
|
|
68
|
+
|
|
49
69
|
export type RequestPurchaseAndroidProps = {
|
|
50
70
|
skus: string[];
|
|
51
71
|
obfuscatedAccountIdAndroid?: string;
|
|
@@ -110,14 +130,21 @@ export enum FeatureTypeAndroid {
|
|
|
110
130
|
SUBSCRIPTIONS_UPDATE = 'SUBSCRIPTIONS_UPDATE',
|
|
111
131
|
}
|
|
112
132
|
|
|
113
|
-
export enum
|
|
133
|
+
export enum PurchaseAndroidState {
|
|
114
134
|
UNSPECIFIED_STATE = 0,
|
|
115
135
|
PURCHASED = 1,
|
|
116
136
|
PENDING = 2,
|
|
117
137
|
}
|
|
118
138
|
|
|
119
|
-
|
|
120
|
-
|
|
139
|
+
// Legacy naming for backward compatibility
|
|
140
|
+
/**
|
|
141
|
+
* @deprecated Use `PurchaseAndroidState` instead. This enum will be removed in v2.9.0.
|
|
142
|
+
*/
|
|
143
|
+
export const PurchaseStateAndroid = PurchaseAndroidState;
|
|
144
|
+
|
|
145
|
+
// Legacy naming for backward compatibility
|
|
146
|
+
export type ProductPurchaseAndroid = PurchaseCommon & {
|
|
147
|
+
platform: 'android';
|
|
121
148
|
/**
|
|
122
149
|
* @deprecated Use `purchaseToken` instead. This field will be removed in a future version.
|
|
123
150
|
*/
|
|
@@ -125,10 +152,30 @@ export type ProductPurchaseAndroid = PurchaseBase & {
|
|
|
125
152
|
dataAndroid?: string;
|
|
126
153
|
signatureAndroid?: string;
|
|
127
154
|
autoRenewingAndroid?: boolean;
|
|
128
|
-
purchaseStateAndroid?:
|
|
155
|
+
purchaseStateAndroid?: PurchaseAndroidState;
|
|
129
156
|
isAcknowledgedAndroid?: boolean;
|
|
130
157
|
packageNameAndroid?: string;
|
|
131
158
|
developerPayloadAndroid?: string;
|
|
132
159
|
obfuscatedAccountIdAndroid?: string;
|
|
133
160
|
obfuscatedProfileIdAndroid?: string;
|
|
134
161
|
};
|
|
162
|
+
|
|
163
|
+
// Preferred naming
|
|
164
|
+
export type PurchaseAndroid = ProductPurchaseAndroid;
|
|
165
|
+
|
|
166
|
+
// Legacy type aliases for backward compatibility
|
|
167
|
+
/**
|
|
168
|
+
* @deprecated Use `ProductAndroidOneTimePurchaseOfferDetail` instead. This type will be removed in v2.9.0.
|
|
169
|
+
*/
|
|
170
|
+
export type OneTimePurchaseOfferDetails =
|
|
171
|
+
ProductAndroidOneTimePurchaseOfferDetail;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @deprecated Use `ProductSubscriptionAndroidOfferDetail` instead. This type will be removed in v2.9.0.
|
|
175
|
+
*/
|
|
176
|
+
export type SubscriptionOfferDetail = ProductSubscriptionAndroidOfferDetail;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @deprecated Use `ProductSubscriptionAndroidOfferDetails` instead. This type will be removed in v2.9.0.
|
|
180
|
+
*/
|
|
181
|
+
export type SubscriptionOfferAndroid = ProductSubscriptionAndroidOfferDetails;
|