expo-iap 2.2.0-rc.2 → 2.2.0-rc.3

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.
Files changed (43) hide show
  1. package/build/ExpoIap.types.js +0 -1
  2. package/build/ExpoIap.types.ts +125 -0
  3. package/build/ExpoIapModule.js +0 -1
  4. package/build/ExpoIapModule.ts +5 -0
  5. package/build/index.js +0 -1
  6. package/build/index.ts +354 -0
  7. package/build/modules/android.js +0 -1
  8. package/build/modules/android.ts +99 -0
  9. package/build/modules/ios.js +0 -1
  10. package/build/modules/ios.ts +84 -0
  11. package/build/types/ExpoIapAndroid.types.js +0 -1
  12. package/build/types/ExpoIapAndroid.types.ts +127 -0
  13. package/build/types/ExpoIapIos.types.js +0 -1
  14. package/build/types/ExpoIapIos.types.ts +136 -0
  15. package/build/useIap.js +0 -1
  16. package/build/useIap.ts +185 -0
  17. package/package.json +6 -5
  18. package/src/types/ExpoIapIos.types.ts +0 -1
  19. package/tsconfig.json +6 -1
  20. package/build/ExpoIap.types.d.ts +0 -80
  21. package/build/ExpoIap.types.d.ts.map +0 -1
  22. package/build/ExpoIap.types.js.map +0 -1
  23. package/build/ExpoIapModule.d.ts +0 -3
  24. package/build/ExpoIapModule.d.ts.map +0 -1
  25. package/build/ExpoIapModule.js.map +0 -1
  26. package/build/index.d.ts +0 -37
  27. package/build/index.d.ts.map +0 -1
  28. package/build/index.js.map +0 -1
  29. package/build/modules/android.d.ts +0 -48
  30. package/build/modules/android.d.ts.map +0 -1
  31. package/build/modules/android.js.map +0 -1
  32. package/build/modules/ios.d.ts +0 -49
  33. package/build/modules/ios.d.ts.map +0 -1
  34. package/build/modules/ios.js.map +0 -1
  35. package/build/types/ExpoIapAndroid.types.d.ts +0 -113
  36. package/build/types/ExpoIapAndroid.types.d.ts.map +0 -1
  37. package/build/types/ExpoIapAndroid.types.js.map +0 -1
  38. package/build/types/ExpoIapIos.types.d.ts +0 -119
  39. package/build/types/ExpoIapIos.types.d.ts.map +0 -1
  40. package/build/types/ExpoIapIos.types.js.map +0 -1
  41. package/build/useIap.d.ts +0 -23
  42. package/build/useIap.d.ts.map +0 -1
  43. package/build/useIap.js.map +0 -1
@@ -45,4 +45,3 @@ export class PurchaseError {
45
45
  this.productId = productId;
46
46
  }
47
47
  }
48
- //# sourceMappingURL=ExpoIap.types.js.map
@@ -0,0 +1,125 @@
1
+ import {
2
+ ProductAndroid,
3
+ ProductPurchaseAndroid,
4
+ RequestPurchaseAndroidProps,
5
+ RequestSubscriptionAndroidProps,
6
+ SubscriptionProductAndroid,
7
+ } from './types/ExpoIapAndroid.types';
8
+ import {
9
+ ProductIos,
10
+ ProductPurchaseIos,
11
+ RequestPurchaseIosProps,
12
+ RequestSubscriptionIosProps,
13
+ SubscriptionProductIos,
14
+ } from './types/ExpoIapIos.types';
15
+
16
+ export type ChangeEventPayload = {
17
+ value: string;
18
+ };
19
+
20
+ /**
21
+ * Base product type with common properties shared between iOS and Android
22
+ */
23
+ export type ProductBase = {
24
+ id: string;
25
+ title: string;
26
+ description: string;
27
+ type: ProductType;
28
+ displayName?: string;
29
+ displayPrice?: string;
30
+ price?: number;
31
+ currency?: string;
32
+ };
33
+
34
+ // Define literal platform types for better type discrimination
35
+ export type IosPlatform = {platform: 'ios'};
36
+ export type AndroidPlatform = {platform: 'android'};
37
+
38
+ export enum ProductType {
39
+ InAppPurchase = 'inapp',
40
+ Subscription = 'subs',
41
+ }
42
+
43
+ // Common base purchase type
44
+ export type PurchaseBase = {
45
+ id: string;
46
+ transactionId?: string;
47
+ transactionDate: number;
48
+ transactionReceipt: string;
49
+ purchaseToken?: string;
50
+ };
51
+
52
+ // Union type for platform-specific product types with proper discriminators
53
+ export type Product =
54
+ | (ProductAndroid & AndroidPlatform)
55
+ | (ProductIos & IosPlatform);
56
+
57
+ // Union type for platform-specific purchase types with proper discriminators
58
+ export type ProductPurchase =
59
+ | (ProductPurchaseAndroid & AndroidPlatform)
60
+ | (ProductPurchaseIos & IosPlatform);
61
+
62
+ // Union type for platform-specific subscription purchase types with proper discriminators
63
+ export type SubscriptionPurchase =
64
+ | (ProductPurchaseAndroid & AndroidPlatform & { autoRenewingAndroid: boolean })
65
+ | (ProductPurchaseIos & IosPlatform);
66
+
67
+ export type Purchase = ProductPurchase | SubscriptionPurchase;
68
+
69
+ export type RequestPurchaseProps =
70
+ | RequestPurchaseIosProps
71
+ | RequestPurchaseAndroidProps;
72
+
73
+ export type SubscriptionProduct =
74
+ | (SubscriptionProductAndroid & AndroidPlatform)
75
+ | (SubscriptionProductIos & IosPlatform);
76
+
77
+ export type RequestSubscriptionProps =
78
+ | RequestSubscriptionAndroidProps
79
+ | RequestSubscriptionIosProps;
80
+
81
+ export type PurchaseResult = {
82
+ responseCode?: number;
83
+ debugMessage?: string;
84
+ code?: string;
85
+ message?: string;
86
+ purchaseToken?: string;
87
+ };
88
+
89
+ export enum ErrorCode {
90
+ E_UNKNOWN = 'E_UNKNOWN',
91
+ E_USER_CANCELLED = 'E_USER_CANCELLED',
92
+ E_USER_ERROR = 'E_USER_ERROR',
93
+ E_ITEM_UNAVAILABLE = 'E_ITEM_UNAVAILABLE',
94
+ E_REMOTE_ERROR = 'E_REMOTE_ERROR',
95
+ E_NETWORK_ERROR = 'E_NETWORK_ERROR',
96
+ E_SERVICE_ERROR = 'E_SERVICE_ERROR',
97
+ E_RECEIPT_FAILED = 'E_RECEIPT_FAILED',
98
+ E_RECEIPT_FINISHED_FAILED = 'E_RECEIPT_FINISHED_FAILED',
99
+ E_NOT_PREPARED = 'E_NOT_PREPARED',
100
+ E_NOT_ENDED = 'E_NOT_ENDED',
101
+ E_ALREADY_OWNED = 'E_ALREADY_OWNED',
102
+ E_DEVELOPER_ERROR = 'E_DEVELOPER_ERROR',
103
+ E_BILLING_RESPONSE_JSON_PARSE_ERROR = 'E_BILLING_RESPONSE_JSON_PARSE_ERROR',
104
+ E_DEFERRED_PAYMENT = 'E_DEFERRED_PAYMENT',
105
+ E_INTERRUPTED = 'E_INTERRUPTED',
106
+ E_IAP_NOT_AVAILABLE = 'E_IAP_NOT_AVAILABLE',
107
+ }
108
+
109
+ export class PurchaseError implements Error {
110
+ constructor(
111
+ public name: string,
112
+ public message: string,
113
+ public responseCode?: number,
114
+ public debugMessage?: string,
115
+ public code?: ErrorCode,
116
+ public productId?: string,
117
+ ) {
118
+ this.name = '[expo-iap]: PurchaseError';
119
+ this.message = message;
120
+ this.responseCode = responseCode;
121
+ this.debugMessage = debugMessage;
122
+ this.code = code;
123
+ this.productId = productId;
124
+ }
125
+ }
@@ -2,4 +2,3 @@ import { requireNativeModule } from 'expo-modules-core';
2
2
  // It loads the native module object from the JSI or falls back to
3
3
  // the bridge module (from NativeModulesProxy) if the remote debugger is on.
4
4
  export default requireNativeModule('ExpoIap');
5
- //# sourceMappingURL=ExpoIapModule.js.map
@@ -0,0 +1,5 @@
1
+ import {requireNativeModule} from 'expo-modules-core';
2
+
3
+ // It loads the native module object from the JSI or falls back to
4
+ // the bridge module (from NativeModulesProxy) if the remote debugger is on.
5
+ export default requireNativeModule('ExpoIap');
package/build/index.js CHANGED
@@ -186,4 +186,3 @@ export const finishTransaction = ({ purchase, isConsumable, developerPayloadAndr
186
186
  }) || (() => Promise.reject(new Error('Unsupported Platform'))))();
187
187
  };
188
188
  export * from './useIap';
189
- //# sourceMappingURL=index.js.map
package/build/index.ts ADDED
@@ -0,0 +1,354 @@
1
+ // Import the native module. On web, it will be resolved to ExpoIap.web.ts
2
+ // and on native platforms to ExpoIap.ts
3
+ import {NativeModulesProxy, EventEmitter} from 'expo-modules-core';
4
+ import {Platform} from 'react-native';
5
+ import {
6
+ Product,
7
+ ProductPurchase,
8
+ ProductType,
9
+ Purchase,
10
+ PurchaseError,
11
+ PurchaseResult,
12
+ RequestSubscriptionProps,
13
+ SubscriptionProduct,
14
+ SubscriptionPurchase,
15
+ } from './ExpoIap.types';
16
+ import ExpoIapModule from './ExpoIapModule';
17
+ import {
18
+ RequestPurchaseAndroidProps,
19
+ RequestSubscriptionAndroidProps,
20
+ } from './types/ExpoIapAndroid.types';
21
+ import {
22
+ PaymentDiscount,
23
+ RequestPurchaseIosProps,
24
+ RequestSubscriptionIosProps,
25
+ } from './types/ExpoIapIos.types';
26
+ import {isProductIos, isSubscriptionProductIos} from './modules/ios';
27
+ import {
28
+ isProductAndroid,
29
+ isSubscriptionProductAndroid,
30
+ } from './modules/android';
31
+
32
+ export * from './modules/android';
33
+ export * from './modules/ios';
34
+
35
+ // Get the native constant value.
36
+ export const PI = ExpoIapModule.PI;
37
+
38
+ export enum IapEvent {
39
+ PurchaseUpdated = 'purchase-updated',
40
+ PurchaseError = 'purchase-error',
41
+ TransactionIapUpdated = 'iap-transaction-updated',
42
+ }
43
+
44
+ export async function setValueAsync(value: string) {
45
+ return await ExpoIapModule.setValueAsync(value);
46
+ }
47
+
48
+ export const emitter = new EventEmitter(
49
+ ExpoIapModule ?? NativeModulesProxy.ExpoIap,
50
+ );
51
+
52
+ export const purchaseUpdatedListener = (
53
+ listener: (event: Purchase) => void,
54
+ ) => {
55
+ const emitterSubscription = emitter.addListener(
56
+ IapEvent.PurchaseUpdated,
57
+ listener,
58
+ );
59
+ return emitterSubscription;
60
+ };
61
+
62
+ export const purchaseErrorListener = (
63
+ listener: (error: PurchaseError) => void,
64
+ ) => {
65
+ return emitter.addListener<PurchaseError>(IapEvent.PurchaseError, listener);
66
+ };
67
+
68
+ export function initConnection() {
69
+ return ExpoIapModule.initConnection();
70
+ }
71
+
72
+ export const getProducts = async (skus: string[]): Promise<Product[]> => {
73
+ console.log('getProducts', skus);
74
+ if (!skus?.length) {
75
+ return Promise.reject(new Error('"skus" is required'));
76
+ }
77
+
78
+ return Platform.select({
79
+ ios: async () => {
80
+ const items = await ExpoIapModule.getItems(skus);
81
+ console.log('items', items);
82
+ return items.filter((item: unknown) => isProductIos<Product>(item));
83
+ },
84
+ android: async () => {
85
+ const products = await ExpoIapModule.getItemsByType(
86
+ ProductType.InAppPurchase,
87
+ skus,
88
+ );
89
+ return products.filter((product: unknown) =>
90
+ isProductAndroid<Product>(product),
91
+ );
92
+ },
93
+ default: () => Promise.reject(new Error('Unsupported Platform')),
94
+ })();
95
+ };
96
+
97
+ export const getSubscriptions = async (
98
+ skus: string[],
99
+ ): Promise<SubscriptionProduct[]> => {
100
+ if (!skus?.length) {
101
+ return Promise.reject(new Error('"skus" is required'));
102
+ }
103
+
104
+ return Platform.select({
105
+ ios: async () => {
106
+ const rawItems = await ExpoIapModule.getItems(skus);
107
+
108
+ return rawItems.filter((item: unknown) => {
109
+ if (!isSubscriptionProductIos(item)) return false;
110
+ return (
111
+ typeof item === 'object' &&
112
+ item !== null &&
113
+ 'id' in item &&
114
+ typeof item.id === 'string' &&
115
+ skus.includes(item.id)
116
+ );
117
+ }) as SubscriptionProduct[];
118
+ },
119
+ android: async () => {
120
+ const rawItems = await ExpoIapModule.getItemsByType('subs', skus);
121
+
122
+ return rawItems.filter((item: unknown) => {
123
+ if (!isSubscriptionProductAndroid(item)) return false;
124
+ return (
125
+ typeof item === 'object' &&
126
+ item !== null &&
127
+ 'id' in item &&
128
+ typeof item.id === 'string' &&
129
+ skus.includes(item.id)
130
+ );
131
+ }) as SubscriptionProduct[];
132
+ },
133
+ default: () => Promise.reject(new Error('Unsupported Platform')),
134
+ })();
135
+ };
136
+
137
+ export async function endConnection(): Promise<boolean> {
138
+ return ExpoIapModule.endConnection();
139
+ }
140
+
141
+ export const getPurchaseHistory = ({
142
+ alsoPublishToEventListener = false,
143
+ onlyIncludeActiveItems = false,
144
+ }: {
145
+ alsoPublishToEventListener?: boolean;
146
+ onlyIncludeActiveItems?: boolean;
147
+ } = {}): Promise<ProductPurchase[]> =>
148
+ (
149
+ Platform.select({
150
+ ios: async () => {
151
+ return ExpoIapModule.getAvailableItems(
152
+ alsoPublishToEventListener,
153
+ onlyIncludeActiveItems,
154
+ );
155
+ },
156
+ android: async () => {
157
+ const products = await ExpoIapModule.getPurchaseHistoryByType(
158
+ ProductType.InAppPurchase,
159
+ );
160
+
161
+ const subscriptions = await ExpoIapModule.getPurchaseHistoryByType(
162
+ ProductType.Subscription,
163
+ );
164
+
165
+ return products.concat(subscriptions);
166
+ },
167
+ }) || (() => Promise.resolve([]))
168
+ )();
169
+
170
+ export const getAvailablePurchases = ({
171
+ alsoPublishToEventListener = false,
172
+ onlyIncludeActiveItems = true,
173
+ }: {
174
+ alsoPublishToEventListener?: boolean;
175
+ onlyIncludeActiveItems?: boolean;
176
+ } = {}): Promise<ProductPurchase[]> =>
177
+ (
178
+ Platform.select({
179
+ ios: () =>
180
+ ExpoIapModule.getAvailableItems(
181
+ alsoPublishToEventListener,
182
+ onlyIncludeActiveItems,
183
+ ),
184
+ android: async () => {
185
+ const products = await ExpoIapModule.getAvailableItemsByType(
186
+ ProductType.InAppPurchase,
187
+ );
188
+
189
+ const subscriptions = await ExpoIapModule.getAvailableItemsByType(
190
+ ProductType.Subscription,
191
+ );
192
+
193
+ return products.concat(subscriptions);
194
+ },
195
+ }) || (() => Promise.resolve([]))
196
+ )();
197
+
198
+ const offerToRecordIos = (
199
+ offer: PaymentDiscount | undefined,
200
+ ): Record<keyof PaymentDiscount, string> | undefined => {
201
+ if (!offer) {
202
+ return undefined;
203
+ }
204
+ return {
205
+ identifier: offer.identifier,
206
+ keyIdentifier: offer.keyIdentifier,
207
+ nonce: offer.nonce,
208
+ signature: offer.signature,
209
+ timestamp: offer.timestamp.toString(),
210
+ };
211
+ };
212
+
213
+ export const requestPurchase = (
214
+ request: RequestPurchaseIosProps | RequestPurchaseAndroidProps,
215
+ ): Promise<ProductPurchase | ProductPurchase[] | void> =>
216
+ (
217
+ Platform.select({
218
+ ios: async () => {
219
+ if (!('sku' in request)) {
220
+ throw new Error('sku is required for iOS purchase');
221
+ }
222
+
223
+ const {sku, appAccountToken, quantity, withOffer} = request;
224
+
225
+ const offer = offerToRecordIos(withOffer);
226
+
227
+ const purchase = await ExpoIapModule.buyProduct(
228
+ sku,
229
+ appAccountToken,
230
+ quantity ?? -1,
231
+ offer,
232
+ );
233
+
234
+ return Promise.resolve(purchase);
235
+ },
236
+ android: async () => {
237
+ if (!('skus' in request) || !request.skus.length) {
238
+ throw new Error('skus is required for Android purchase');
239
+ }
240
+
241
+ const {
242
+ skus,
243
+ obfuscatedAccountIdAndroid,
244
+ obfuscatedProfileIdAndroid,
245
+ isOfferPersonalized,
246
+ } = request;
247
+
248
+ return ExpoIapModule.buyItemByType({
249
+ type: ProductType.InAppPurchase,
250
+ skuArr: skus,
251
+ purchaseToken: undefined,
252
+ replacementMode: -1,
253
+ obfuscatedAccountId: obfuscatedAccountIdAndroid,
254
+ obfuscatedProfileId: obfuscatedProfileIdAndroid,
255
+ offerTokenArr: [],
256
+ isOfferPersonalized: isOfferPersonalized ?? false,
257
+ });
258
+ },
259
+ }) || Promise.resolve
260
+ )();
261
+
262
+ export const requestSubscription = (
263
+ request: RequestSubscriptionProps,
264
+ ): Promise<SubscriptionPurchase | SubscriptionPurchase[] | null | void> =>
265
+ (
266
+ Platform.select({
267
+ ios: async () => {
268
+ if (!('sku' in request)) {
269
+ throw new Error('sku is required for iOS subscriptions');
270
+ }
271
+
272
+ const {sku, appAccountToken, quantity, withOffer} =
273
+ request as RequestSubscriptionIosProps;
274
+
275
+ const offer = offerToRecordIos(withOffer);
276
+
277
+ const purchase = await ExpoIapModule.buyProduct(
278
+ sku,
279
+ appAccountToken,
280
+ quantity ?? -1,
281
+ offer,
282
+ );
283
+
284
+ return Promise.resolve(purchase as SubscriptionPurchase);
285
+ },
286
+ android: async () => {
287
+ const {
288
+ skus,
289
+ isOfferPersonalized,
290
+ obfuscatedAccountIdAndroid,
291
+ obfuscatedProfileIdAndroid,
292
+ subscriptionOffers,
293
+ replacementModeAndroid,
294
+ purchaseTokenAndroid,
295
+ } = request as RequestSubscriptionAndroidProps;
296
+
297
+ return ExpoIapModule.buyItemByType({
298
+ type: ProductType.Subscription,
299
+ skuArr: skus.map((so) => so),
300
+ purchaseToken: purchaseTokenAndroid,
301
+ replacementMode: replacementModeAndroid,
302
+ obfuscatedAccountId: obfuscatedAccountIdAndroid,
303
+ obfuscatedProfileId: obfuscatedProfileIdAndroid,
304
+ offerTokenArr: subscriptionOffers.map((so) => so.offerToken),
305
+ isOfferPersonalized: isOfferPersonalized ?? false,
306
+ });
307
+ },
308
+ }) || (() => Promise.resolve(null))
309
+ )();
310
+
311
+ export const finishTransaction = ({
312
+ purchase,
313
+ isConsumable,
314
+ developerPayloadAndroid,
315
+ }: {
316
+ purchase: Purchase;
317
+ isConsumable?: boolean;
318
+ developerPayloadAndroid?: string;
319
+ }): Promise<PurchaseResult | boolean> => {
320
+ return (
321
+ Platform.select({
322
+ ios: async () => {
323
+ const transactionId = purchase.transactionId;
324
+
325
+ if (!transactionId) {
326
+ return Promise.reject(
327
+ new Error('transactionId required to finish iOS transaction'),
328
+ );
329
+ }
330
+ await ExpoIapModule.finishTransaction(transactionId);
331
+ return Promise.resolve(true);
332
+ },
333
+ android: async () => {
334
+ if (purchase?.purchaseToken) {
335
+ if (!isConsumable) {
336
+ return Promise.reject(
337
+ new Error('purchase is not suitable to be purchased'),
338
+ );
339
+ }
340
+
341
+ return ExpoIapModule.consumeProduct(
342
+ purchase.purchaseToken,
343
+ developerPayloadAndroid,
344
+ );
345
+ }
346
+ return Promise.reject(
347
+ new Error('purchase is not suitable to be purchased'),
348
+ );
349
+ },
350
+ }) || (() => Promise.reject(new Error('Unsupported Platform')))
351
+ )();
352
+ };
353
+
354
+ export * from './useIap';
@@ -55,4 +55,3 @@ export const validateReceiptAndroid = async ({ packageName, productId, productTo
55
55
  export const acknowledgePurchaseAndroid = ({ token, developerPayload, }) => {
56
56
  return ExpoIapModule.acknowledgePurchase(token, developerPayload);
57
57
  };
58
- //# sourceMappingURL=android.js.map
@@ -0,0 +1,99 @@
1
+ import {Linking} from 'react-native';
2
+ import {PurchaseResult} from '../ExpoIap.types';
3
+ import {ReceiptAndroid} from '../types/ExpoIapAndroid.types';
4
+ import ExpoIapModule from '../ExpoIapModule';
5
+
6
+ // Type guards
7
+ export function isProductAndroid<T extends {platform?: string}>(
8
+ item: unknown,
9
+ ): item is T & {platform: 'android'} {
10
+ return (
11
+ item != null &&
12
+ typeof item === 'object' &&
13
+ 'platform' in item &&
14
+ item.platform === 'android'
15
+ );
16
+ }
17
+
18
+ export function isSubscriptionProductAndroid<T extends {platform?: string}>(
19
+ item: unknown,
20
+ ): item is T & {platform: 'android'} {
21
+ return isProductAndroid(item);
22
+ }
23
+
24
+ /**
25
+ * Deep link to subscriptions screen on Android.
26
+ * @param {string} sku The product's SKU (on Android)
27
+ * @returns {Promise<void>}
28
+ */
29
+ export const deepLinkToSubscriptionsAndroid = async ({
30
+ sku,
31
+ }: {
32
+ sku: string;
33
+ }): Promise<void> => {
34
+ return Linking.openURL(
35
+ `https://play.google.com/store/account/subscriptions?package=${await ExpoIapModule.getPackageName()}&sku=${sku}`,
36
+ );
37
+ };
38
+
39
+ /**
40
+ * Validate receipt for Android. NOTE: This method is here for debugging purposes only. Including
41
+ * your access token in the binary you ship to users is potentially dangerous.
42
+ * Use server side validation instead for your production builds
43
+ * @param {string} packageName package name of your app.
44
+ * @param {string} productId product id for your in app product.
45
+ * @param {string} productToken token for your purchase.
46
+ * @param {string} accessToken accessToken from googleApis.
47
+ * @param {boolean} isSub whether this is subscription or inapp. `true` for subscription.
48
+ * @returns {Promise<object>}
49
+ */
50
+ export const validateReceiptAndroid = async ({
51
+ packageName,
52
+ productId,
53
+ productToken,
54
+ accessToken,
55
+ isSub,
56
+ }: {
57
+ packageName: string;
58
+ productId: string;
59
+ productToken: string;
60
+ accessToken: string;
61
+ isSub?: boolean;
62
+ }): Promise<ReceiptAndroid> => {
63
+ const type = isSub ? 'subscriptions' : 'products';
64
+
65
+ const url =
66
+ 'https://androidpublisher.googleapis.com/androidpublisher/v3/applications' +
67
+ `/${packageName}/purchases/${type}/${productId}` +
68
+ `/tokens/${productToken}?access_token=${accessToken}`;
69
+
70
+ const response = await fetch(url, {
71
+ method: 'GET',
72
+ headers: {
73
+ 'Content-Type': 'application/json',
74
+ },
75
+ });
76
+
77
+ if (!response.ok) {
78
+ throw Object.assign(new Error(response.statusText), {
79
+ statusCode: response.status,
80
+ });
81
+ }
82
+
83
+ return response.json();
84
+ };
85
+
86
+ /**
87
+ * Acknowledge a product (on Android.) No-op on iOS.
88
+ * @param {string} token The product's token (on Android)
89
+ * @returns {Promise<PurchaseResult | void>}
90
+ */
91
+ export const acknowledgePurchaseAndroid = ({
92
+ token,
93
+ developerPayload,
94
+ }: {
95
+ token: string;
96
+ developerPayload?: string;
97
+ }): Promise<PurchaseResult | boolean | void> => {
98
+ return ExpoIapModule.acknowledgePurchase(token, developerPayload);
99
+ };
@@ -45,4 +45,3 @@ export const beginRefundRequest = (sku) => ExpoIapModule.beginRefundRequest(sku)
45
45
  *
46
46
  */
47
47
  export const showManageSubscriptions = () => ExpoIapModule.showManageSubscriptions();
48
- //# sourceMappingURL=ios.js.map
@@ -0,0 +1,84 @@
1
+ import {Platform} from 'react-native';
2
+ import {emitter, IapEvent} from '..';
3
+ import {ProductPurchase, PurchaseError} from '../ExpoIap.types';
4
+ import type {ProductStatusIos} from '../types/ExpoIapIos.types';
5
+ import ExpoIapModule from '../ExpoIapModule';
6
+
7
+ export type TransactionEvent = {
8
+ transaction?: ProductPurchase;
9
+ error?: PurchaseError;
10
+ };
11
+
12
+ // Listeners
13
+ export const transactionUpdatedIos = (
14
+ listener: (event: TransactionEvent) => void,
15
+ ) => {
16
+ if (Platform.OS !== 'ios') {
17
+ throw new Error('This method is only available on iOS');
18
+ }
19
+
20
+ return emitter.addListener(IapEvent.TransactionIapUpdated, listener);
21
+ };
22
+
23
+ // Type guards
24
+ export function isProductIos<T extends {platform?: string}>(
25
+ item: unknown,
26
+ ): item is T & {platform: 'ios'} {
27
+ return (
28
+ item != null &&
29
+ typeof item === 'object' &&
30
+ 'platform' in item &&
31
+ item.platform === 'ios'
32
+ );
33
+ }
34
+
35
+ export function isSubscriptionProductIos<T extends {platform?: string}>(
36
+ item: unknown,
37
+ ): item is T & {platform: 'ios'} {
38
+ return isProductIos(item);
39
+ }
40
+
41
+ // Functions
42
+ /**
43
+ * Sync state with Appstore (iOS only)
44
+ * https://developer.apple.com/documentation/storekit/appstore/3791906-sync
45
+ */
46
+ export const sync = (): Promise<null> => ExpoIapModule.sync();
47
+
48
+ /**
49
+ *
50
+ */
51
+ export const isEligibleForIntroOffer = (groupID: string): Promise<boolean> =>
52
+ ExpoIapModule.isEligibleForIntroOffer(groupID);
53
+
54
+ /**
55
+ *
56
+ */
57
+
58
+ export const subscriptionStatus = (sku: string): Promise<ProductStatusIos[]> =>
59
+ ExpoIapModule.subscriptionStatus(sku);
60
+
61
+ /**
62
+ *
63
+ */
64
+ export const currentEntitlement = (sku: string): Promise<ProductPurchase> =>
65
+ ExpoIapModule.currentEntitlement(sku);
66
+
67
+ /**
68
+ *
69
+ */
70
+ export const latestTransaction = (sku: string): Promise<ProductPurchase> =>
71
+ ExpoIapModule.latestTransaction(sku);
72
+
73
+ /**
74
+ *
75
+ */
76
+ type RefundRequestStatus = 'success' | 'userCancelled';
77
+ export const beginRefundRequest = (sku: string): Promise<RefundRequestStatus> =>
78
+ ExpoIapModule.beginRefundRequest(sku);
79
+
80
+ /**
81
+ *
82
+ */
83
+ export const showManageSubscriptions = (): Promise<null> =>
84
+ ExpoIapModule.showManageSubscriptions();
@@ -26,4 +26,3 @@ export var PurchaseStateAndroid;
26
26
  PurchaseStateAndroid[PurchaseStateAndroid["PURCHASED"] = 1] = "PURCHASED";
27
27
  PurchaseStateAndroid[PurchaseStateAndroid["PENDING"] = 2] = "PENDING";
28
28
  })(PurchaseStateAndroid || (PurchaseStateAndroid = {}));
29
- //# sourceMappingURL=ExpoIapAndroid.types.js.map