react-native-iap 15.5.4 → 15.6.1
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/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +163 -15
- package/android/src/main/java/com/margelo/nitro/iap/PendingEventBuffer.kt +86 -0
- package/android/src/main/java/com/margelo/nitro/iap/RnIapLog.kt +13 -0
- package/ios/HybridRnIap.swift +31 -4
- package/ios/RnIapHelper.swift +3 -2
- package/ios/RnIapLog.swift +14 -0
- package/lib/module/hooks/useIAP.js +8 -2
- package/lib/module/hooks/useIAP.js.map +1 -1
- package/lib/module/index.js +105 -30
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.kepler.js +72 -5
- package/lib/module/index.kepler.js.map +1 -1
- package/lib/module/kit-api.js +78 -3
- package/lib/module/kit-api.js.map +1 -1
- package/lib/module/types.js +29 -25
- package/lib/module/types.js.map +1 -1
- package/lib/module/utils/deprecation.js +15 -0
- package/lib/module/utils/deprecation.js.map +1 -0
- package/lib/module/utils/platform-request.js +28 -0
- package/lib/module/utils/platform-request.js.map +1 -0
- package/lib/module/utils/type-bridge.js +9 -4
- package/lib/module/utils/type-bridge.js.map +1 -1
- package/lib/module/vega-adapter.js +34 -22
- package/lib/module/vega-adapter.js.map +1 -1
- package/lib/typescript/src/hooks/useIAP.d.ts +16 -2
- package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +56 -12
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.kepler.d.ts +50 -4
- package/lib/typescript/src/index.kepler.d.ts.map +1 -1
- package/lib/typescript/src/kit-api.d.ts +18 -8
- package/lib/typescript/src/kit-api.d.ts.map +1 -1
- package/lib/typescript/src/specs/RnIap.nitro.d.ts +32 -6
- package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +119 -175
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/utils/deprecation.d.ts +3 -0
- package/lib/typescript/src/utils/deprecation.d.ts.map +1 -0
- package/lib/typescript/src/utils/platform-request.d.ts +12 -0
- package/lib/typescript/src/utils/platform-request.d.ts.map +1 -0
- package/lib/typescript/src/utils/type-bridge.d.ts.map +1 -1
- package/lib/typescript/src/vega-adapter.d.ts +1 -0
- package/lib/typescript/src/vega-adapter.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +16 -0
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +1 -0
- package/nitrogen/generated/android/c++/JNitroPurchase.hpp +5 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +4 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroPurchase.kt +7 -2
- package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +8 -0
- package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +19 -0
- package/nitrogen/generated/ios/swift/NitroPurchase.swift +39 -2
- package/nitrogen/generated/shared/c++/HybridRnIapSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +1 -0
- package/nitrogen/generated/shared/c++/NitroPurchase.hpp +5 -1
- package/openiap-versions.json +3 -3
- package/package.json +1 -1
- package/src/hooks/useIAP.ts +22 -2
- package/src/index.kepler.ts +86 -8
- package/src/index.ts +139 -47
- package/src/kit-api.ts +136 -13
- package/src/specs/RnIap.nitro.ts +33 -6
- package/src/types.ts +130 -203
- package/src/utils/deprecation.ts +16 -0
- package/src/utils/platform-request.ts +37 -0
- package/src/utils/type-bridge.ts +20 -4
- package/src/vega-adapter.ts +50 -24
- package/lib/module/hooks/useWebhookEvents.js +0 -113
- package/lib/module/hooks/useWebhookEvents.js.map +0 -1
- package/lib/module/webhook-client.js +0 -164
- package/lib/module/webhook-client.js.map +0 -1
- package/lib/typescript/src/hooks/useWebhookEvents.d.ts +0 -55
- package/lib/typescript/src/hooks/useWebhookEvents.d.ts.map +0 -1
- package/lib/typescript/src/webhook-client.d.ts +0 -82
- package/lib/typescript/src/webhook-client.d.ts.map +0 -1
- package/src/hooks/useWebhookEvents.ts +0 -180
- package/src/webhook-client.ts +0 -312
package/src/hooks/useIAP.ts
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
launchExternalLinkAndroid,
|
|
31
31
|
showBillingProgramInformationDialogAndroid,
|
|
32
32
|
showInAppMessagesAndroid,
|
|
33
|
+
openRedeemOfferCodeAndroid,
|
|
33
34
|
userChoiceBillingListenerAndroid,
|
|
34
35
|
developerProvidedBillingListenerAndroid,
|
|
35
36
|
subscriptionBillingIssueListener,
|
|
@@ -194,7 +195,8 @@ type UseIap = {
|
|
|
194
195
|
*/
|
|
195
196
|
requestPurchase: (params: RequestPurchaseProps) => Promise<void>;
|
|
196
197
|
/**
|
|
197
|
-
* @deprecated Use `verifyPurchase` instead. This function will be removed in
|
|
198
|
+
* @deprecated Use `verifyPurchase` instead. This function will be removed in
|
|
199
|
+
* react-native-iap 16.0.0.
|
|
198
200
|
*
|
|
199
201
|
* @see {@link https://openiap.dev/docs/apis/validate-receipt}
|
|
200
202
|
*/
|
|
@@ -233,6 +235,9 @@ type UseIap = {
|
|
|
233
235
|
* Buy the currently promoted product.
|
|
234
236
|
*
|
|
235
237
|
* @see {@link https://openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios}
|
|
238
|
+
* @deprecated Use the `onPromotedProductIOS` hook callback followed by
|
|
239
|
+
* `requestPurchase` instead. Scheduled for removal in react-native-iap
|
|
240
|
+
* 16.0.0.
|
|
236
241
|
*/
|
|
237
242
|
requestPurchaseOnPromotedProductIOS: () => Promise<boolean>;
|
|
238
243
|
/**
|
|
@@ -260,18 +265,25 @@ type UseIap = {
|
|
|
260
265
|
* Check whether alternative billing is available for the user.
|
|
261
266
|
*
|
|
262
267
|
* @see {@link https://openiap.dev/docs/apis/android/check-alternative-billing-availability-android}
|
|
268
|
+
* @deprecated Use `isBillingProgramAvailableAndroid('external-offer')`
|
|
269
|
+
* instead. Scheduled for removal in react-native-iap 16.0.0.
|
|
263
270
|
*/
|
|
264
271
|
checkAlternativeBillingAvailabilityAndroid?: () => Promise<boolean>;
|
|
265
272
|
/**
|
|
266
273
|
* Display Google's alternative billing information dialog.
|
|
267
274
|
*
|
|
268
275
|
* @see {@link https://openiap.dev/docs/apis/android/show-alternative-billing-dialog-android}
|
|
276
|
+
* @deprecated Use `launchExternalLinkAndroid` instead. Scheduled for removal in
|
|
277
|
+
* react-native-iap 16.0.0.
|
|
269
278
|
*/
|
|
270
279
|
showAlternativeBillingDialogAndroid?: () => Promise<boolean>;
|
|
271
280
|
/**
|
|
272
281
|
* Create a reporting token for an alternative billing flow.
|
|
273
282
|
*
|
|
274
283
|
* @see {@link https://openiap.dev/docs/apis/android/create-alternative-billing-token-android}
|
|
284
|
+
* @deprecated Use
|
|
285
|
+
* `createBillingProgramReportingDetailsAndroid('external-offer')` instead.
|
|
286
|
+
* Scheduled for removal in react-native-iap 16.0.0.
|
|
275
287
|
*/
|
|
276
288
|
createAlternativeBillingTokenAndroid?: (
|
|
277
289
|
sku?: string,
|
|
@@ -288,6 +300,8 @@ type UseIap = {
|
|
|
288
300
|
showBillingProgramInformationDialogAndroid?: MutationField<'showBillingProgramInformationDialogAndroid'>;
|
|
289
301
|
/** Show Play billing in-app messages. */
|
|
290
302
|
showInAppMessagesAndroid?: MutationField<'showInAppMessagesAndroid'>;
|
|
303
|
+
/** Open the Play Store offer code redemption page; purchases arrive via the standard purchase listeners. */
|
|
304
|
+
openRedeemOfferCodeAndroid?: MutationField<'openRedeemOfferCodeAndroid'>;
|
|
291
305
|
};
|
|
292
306
|
|
|
293
307
|
export interface UseIapOptions {
|
|
@@ -321,7 +335,8 @@ export interface UseIapOptions {
|
|
|
321
335
|
*/
|
|
322
336
|
onSubscriptionBillingIssue?: (purchase: Purchase) => void;
|
|
323
337
|
/**
|
|
324
|
-
* @deprecated Use enableBillingProgramAndroid instead.
|
|
338
|
+
* @deprecated Use enableBillingProgramAndroid instead. This option will be
|
|
339
|
+
* removed in react-native-iap 16.0.0.
|
|
325
340
|
* - 'user-choice' → 'user-choice-billing'
|
|
326
341
|
* - 'alternative-only' → 'external-offer'
|
|
327
342
|
*/
|
|
@@ -743,11 +758,15 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
743
758
|
}
|
|
744
759
|
|
|
745
760
|
if (!result) {
|
|
761
|
+
cleanupListeners();
|
|
746
762
|
setConnected(false);
|
|
747
763
|
RnIapConsole.warn('[useIAP] initConnection returned false');
|
|
748
764
|
return;
|
|
749
765
|
}
|
|
750
766
|
|
|
767
|
+
// Android retains events emitted during connection setup in bounded
|
|
768
|
+
// native queues; registration flushes that backlog after Nitro is ready.
|
|
769
|
+
// Other platforms preserve the existing post-init listener ordering.
|
|
751
770
|
registerListeners();
|
|
752
771
|
setConnected(true);
|
|
753
772
|
} catch (error) {
|
|
@@ -833,6 +852,7 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
833
852
|
launchExternalLinkAndroid,
|
|
834
853
|
showBillingProgramInformationDialogAndroid,
|
|
835
854
|
showInAppMessagesAndroid,
|
|
855
|
+
openRedeemOfferCodeAndroid,
|
|
836
856
|
}
|
|
837
857
|
: {}),
|
|
838
858
|
};
|
package/src/index.kepler.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
MutationField,
|
|
4
4
|
Product,
|
|
5
5
|
ProductQueryType,
|
|
6
|
+
ProductRequest,
|
|
6
7
|
ProductSubscription,
|
|
7
8
|
Purchase,
|
|
8
9
|
PurchaseError,
|
|
@@ -25,16 +26,19 @@ import {
|
|
|
25
26
|
validateNitroProduct,
|
|
26
27
|
validateNitroPurchase,
|
|
27
28
|
} from './utils/type-bridge';
|
|
29
|
+
import {warnLegacyOnce} from './utils/deprecation';
|
|
30
|
+
import {selectCanonicalPlatformRequest} from './utils/platform-request';
|
|
28
31
|
|
|
29
32
|
export * from './types';
|
|
30
33
|
export * from './utils/error';
|
|
31
34
|
export * from './vega';
|
|
32
35
|
export {useIAP, type UseIapOptions} from './hooks/useIAP';
|
|
33
|
-
export {connectWebhookStream, parseWebhookEventData} from './webhook-client';
|
|
34
36
|
export {kitApi, KitApiError} from './kit-api';
|
|
35
37
|
export type {
|
|
36
38
|
EntitlementsResponse,
|
|
37
39
|
KitApiOptions,
|
|
40
|
+
KitClientPayloadCache,
|
|
41
|
+
KitClientPayloadOptions,
|
|
38
42
|
KitClientPayloadResponse,
|
|
39
43
|
KitProduct,
|
|
40
44
|
KitProductClientPayload,
|
|
@@ -46,8 +50,17 @@ export type {
|
|
|
46
50
|
StatusResponse,
|
|
47
51
|
} from './kit-api';
|
|
48
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Product type accepted by the Amazon Vega entry point.
|
|
55
|
+
*
|
|
56
|
+
* Compatibility note: the `'inapp'` member is deprecated. Use `'in-app'`
|
|
57
|
+
* instead; the alias will be removed in react-native-iap 16.0.0.
|
|
58
|
+
*/
|
|
49
59
|
export type ProductTypeInput = 'inapp' | 'in-app' | 'subs';
|
|
50
60
|
|
|
61
|
+
const LEGACY_INAPP_WARNING =
|
|
62
|
+
"[react-native-iap] `type: 'inapp'` is deprecated and will be removed in react-native-iap 16.0.0. Use 'in-app' instead.";
|
|
63
|
+
|
|
51
64
|
export interface EventSubscription {
|
|
52
65
|
remove(): void;
|
|
53
66
|
}
|
|
@@ -80,7 +93,10 @@ const normalizeProductQueryType = (
|
|
|
80
93
|
): ProductTypeInput | 'all' => {
|
|
81
94
|
if (type === 'subs') return 'subs';
|
|
82
95
|
if (type === 'all') return 'all';
|
|
83
|
-
|
|
96
|
+
if (type === 'inapp') {
|
|
97
|
+
warnLegacyOnce('product-type.inapp', LEGACY_INAPP_WARNING);
|
|
98
|
+
}
|
|
99
|
+
return 'in-app';
|
|
84
100
|
};
|
|
85
101
|
|
|
86
102
|
const mapProducts = (
|
|
@@ -113,13 +129,16 @@ export const endConnection: MutationField<'endConnection'> = async () => {
|
|
|
113
129
|
return getModule().endConnection();
|
|
114
130
|
};
|
|
115
131
|
|
|
116
|
-
export const fetchProducts
|
|
132
|
+
export const fetchProducts = async (
|
|
133
|
+
request: Omit<ProductRequest, 'type'> & {
|
|
134
|
+
type?: ProductQueryType | ProductTypeInput | null;
|
|
135
|
+
},
|
|
136
|
+
): ReturnType<QueryField<'fetchProducts'>> => {
|
|
117
137
|
const {skus, type} = request;
|
|
118
138
|
const normalizedType = normalizeProductQueryType(type);
|
|
119
139
|
const nitroProducts = await getModule().fetchProducts(skus, normalizedType);
|
|
120
140
|
return mapProducts(nitroProducts, normalizedType) as
|
|
121
|
-
|
|
|
122
|
-
| ProductSubscription[];
|
|
141
|
+
Product[] | ProductSubscription[];
|
|
123
142
|
};
|
|
124
143
|
|
|
125
144
|
export const requestPurchase: MutationField<'requestPurchase'> = async (
|
|
@@ -129,8 +148,19 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
|
|
|
129
148
|
| RequestPurchasePropsByPlatforms
|
|
130
149
|
| RequestSubscriptionPropsByPlatforms
|
|
131
150
|
| undefined;
|
|
132
|
-
const
|
|
133
|
-
|
|
151
|
+
const selection = perPlatformRequest
|
|
152
|
+
? selectCanonicalPlatformRequest<
|
|
153
|
+
| RequestPurchasePropsByPlatforms['google']
|
|
154
|
+
| RequestSubscriptionPropsByPlatforms['google']
|
|
155
|
+
>(perPlatformRequest, 'google', 'android')
|
|
156
|
+
: {usesLegacyKey: false, value: undefined};
|
|
157
|
+
if (selection.usesLegacyKey && selection.value != null) {
|
|
158
|
+
warnLegacyOnce(
|
|
159
|
+
'request-purchase.android',
|
|
160
|
+
'[react-native-iap] `request.android` is deprecated and will be removed in react-native-iap 16.0.0. Use `request.google` instead.',
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
const androidRequest = selection.value;
|
|
134
164
|
|
|
135
165
|
if (!androidRequest?.skus?.length) {
|
|
136
166
|
throw new Error(
|
|
@@ -140,7 +170,6 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
|
|
|
140
170
|
|
|
141
171
|
const nitroRequest: NitroPurchaseRequest = {
|
|
142
172
|
google: androidRequest,
|
|
143
|
-
android: androidRequest,
|
|
144
173
|
};
|
|
145
174
|
const result = await getModule().requestPurchase(nitroRequest);
|
|
146
175
|
if (!Array.isArray(result)) return null;
|
|
@@ -247,11 +276,20 @@ export const verifyPurchaseWithProvider: MutationField<
|
|
|
247
276
|
>;
|
|
248
277
|
};
|
|
249
278
|
|
|
279
|
+
/**
|
|
280
|
+
* @deprecated Use `verifyPurchase` instead. This compatibility operation will
|
|
281
|
+
* be removed in react-native-iap 16.0.0.
|
|
282
|
+
*/
|
|
250
283
|
export const validateReceipt: MutationField<'validateReceipt'> = async () => {
|
|
251
284
|
return unsupported('validateReceipt');
|
|
252
285
|
};
|
|
253
286
|
|
|
254
287
|
export const verifyPurchase: MutationField<'verifyPurchase'> = validateReceipt;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @deprecated Use `verifyPurchase` instead. This iOS compatibility operation
|
|
291
|
+
* will be removed in react-native-iap 16.0.0.
|
|
292
|
+
*/
|
|
255
293
|
export const validateReceiptIOS: QueryField<'validateReceiptIOS'> = async () =>
|
|
256
294
|
unsupported('validateReceiptIOS');
|
|
257
295
|
export const syncIOS: MutationField<'syncIOS'> = async () =>
|
|
@@ -262,7 +300,18 @@ export const getAppTransactionIOS: QueryField<
|
|
|
262
300
|
export const getPromotedProductIOS: QueryField<
|
|
263
301
|
'getPromotedProductIOS'
|
|
264
302
|
> = async () => null;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* @deprecated Use `getPromotedProductIOS` instead. This compatibility alias
|
|
306
|
+
* will be removed in react-native-iap 16.0.0.
|
|
307
|
+
*/
|
|
265
308
|
export const requestPromotedProductIOS = getPromotedProductIOS;
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* @deprecated Use `promotedProductListenerIOS` followed by `requestPurchase`
|
|
312
|
+
* instead. This compatibility operation will be removed in react-native-iap
|
|
313
|
+
* 16.0.0.
|
|
314
|
+
*/
|
|
266
315
|
export const requestPurchaseOnPromotedProductIOS = async (): Promise<void> =>
|
|
267
316
|
unsupported('requestPurchaseOnPromotedProductIOS');
|
|
268
317
|
export const showManageSubscriptionsIOS: MutationField<
|
|
@@ -291,15 +340,44 @@ export const consumePurchaseAndroid: MutationField<
|
|
|
291
340
|
> = async (purchaseToken) => {
|
|
292
341
|
return getVegaModule().consumePurchaseAndroid(purchaseToken);
|
|
293
342
|
};
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* @deprecated Use `acknowledgePurchaseAndroid` instead. This alias will be
|
|
346
|
+
* removed in react-native-iap 16.0.0.
|
|
347
|
+
*/
|
|
294
348
|
export const acknowledgePurchase = acknowledgePurchaseAndroid;
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* @deprecated Use `consumePurchaseAndroid` instead. This alias will be removed
|
|
352
|
+
* in react-native-iap 16.0.0.
|
|
353
|
+
*/
|
|
295
354
|
export const consumePurchase = consumePurchaseAndroid;
|
|
296
355
|
|
|
356
|
+
export const openRedeemOfferCodeAndroid: MutationField<
|
|
357
|
+
'openRedeemOfferCodeAndroid'
|
|
358
|
+
> = async () => false;
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* @deprecated Use `isBillingProgramAvailableAndroid('external-offer')`
|
|
362
|
+
* instead. Scheduled for removal in react-native-iap 16.0.0.
|
|
363
|
+
*/
|
|
297
364
|
export const checkAlternativeBillingAvailabilityAndroid: MutationField<
|
|
298
365
|
'checkAlternativeBillingAvailabilityAndroid'
|
|
299
366
|
> = async () => unsupported('checkAlternativeBillingAvailabilityAndroid');
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* @deprecated Use `launchExternalLinkAndroid` instead. Scheduled for removal
|
|
370
|
+
* in react-native-iap 16.0.0.
|
|
371
|
+
*/
|
|
300
372
|
export const showAlternativeBillingDialogAndroid: MutationField<
|
|
301
373
|
'showAlternativeBillingDialogAndroid'
|
|
302
374
|
> = async () => unsupported('showAlternativeBillingDialogAndroid');
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* @deprecated Use `createBillingProgramReportingDetailsAndroid` with the
|
|
378
|
+
* external-offer program instead. Scheduled for removal in react-native-iap
|
|
379
|
+
* 16.0.0.
|
|
380
|
+
*/
|
|
303
381
|
export const createAlternativeBillingTokenAndroid: MutationField<
|
|
304
382
|
'createAlternativeBillingTokenAndroid'
|
|
305
383
|
> = async () => unsupported('createAlternativeBillingTokenAndroid');
|
package/src/index.ts
CHANGED
|
@@ -57,6 +57,8 @@ import {
|
|
|
57
57
|
DUPLICATE_PURCHASE_CODE,
|
|
58
58
|
} from './utils/errorMapping';
|
|
59
59
|
import {RnIapConsole} from './utils/debug';
|
|
60
|
+
import {warnLegacyOnce} from './utils/deprecation';
|
|
61
|
+
import {selectCanonicalPlatformRequest} from './utils/platform-request';
|
|
60
62
|
import {getSuccessFromPurchaseVariant} from './utils/purchase';
|
|
61
63
|
import {parseAppTransactionPayload} from './utils';
|
|
62
64
|
import {getVegaIapModule, isVegaOS} from './vega';
|
|
@@ -91,10 +93,16 @@ export * from './types';
|
|
|
91
93
|
export * from './utils/error';
|
|
92
94
|
export * from './vega';
|
|
93
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Product type accepted by public query and purchase helpers.
|
|
98
|
+
*
|
|
99
|
+
* Compatibility note: the `'inapp'` member is deprecated. Use `'in-app'`
|
|
100
|
+
* instead; the alias will be removed in react-native-iap 16.0.0.
|
|
101
|
+
*/
|
|
94
102
|
export type ProductTypeInput = 'inapp' | 'in-app' | 'subs';
|
|
95
103
|
|
|
96
104
|
const LEGACY_INAPP_WARNING =
|
|
97
|
-
"[react-native-iap] `type: 'inapp'` is deprecated and will be removed in
|
|
105
|
+
"[react-native-iap] `type: 'inapp'` is deprecated and will be removed in react-native-iap 16.0.0. Use 'in-app' instead.";
|
|
98
106
|
|
|
99
107
|
type NitroPurchaseRequest = Parameters<RnIap['requestPurchase']>[0];
|
|
100
108
|
type NitroAvailablePurchasesOptions = NonNullable<
|
|
@@ -148,23 +156,11 @@ export interface EventSubscription {
|
|
|
148
156
|
|
|
149
157
|
// Export hooks
|
|
150
158
|
export {useIAP} from './hooks/useIAP';
|
|
151
|
-
export {useWebhookEvents} from './hooks/useWebhookEvents';
|
|
152
|
-
export type {
|
|
153
|
-
UseWebhookEventsOptions,
|
|
154
|
-
UseWebhookEventsResult,
|
|
155
|
-
} from './hooks/useWebhookEvents';
|
|
156
|
-
export {connectWebhookStream, parseWebhookEventData} from './webhook-client';
|
|
157
|
-
export type {
|
|
158
|
-
WebhookEventPayload,
|
|
159
|
-
WebhookEventStream,
|
|
160
|
-
WebhookEventType as WebhookEventTypeName,
|
|
161
|
-
WebhookListener,
|
|
162
|
-
WebhookListenerError,
|
|
163
|
-
WebhookListenerOptions,
|
|
164
|
-
} from './webhook-client';
|
|
165
159
|
export {kitApi, KitApiError} from './kit-api';
|
|
166
160
|
export type {
|
|
167
161
|
KitApiOptions,
|
|
162
|
+
KitClientPayloadCache,
|
|
163
|
+
KitClientPayloadOptions,
|
|
168
164
|
KitClientPayloadResponse,
|
|
169
165
|
KitProduct,
|
|
170
166
|
KitProductClientPayload,
|
|
@@ -512,6 +508,14 @@ export const purchaseErrorListener = (
|
|
|
512
508
|
return {
|
|
513
509
|
remove: () => {
|
|
514
510
|
purchaseErrorJsListeners.delete(listener);
|
|
511
|
+
if (purchaseErrorJsListeners.size === 0 && purchaseErrorNativeAttached) {
|
|
512
|
+
try {
|
|
513
|
+
IAP.instance.removePurchaseErrorListener(purchaseErrorNativeHandler);
|
|
514
|
+
purchaseErrorNativeAttached = false;
|
|
515
|
+
} catch (e) {
|
|
516
|
+
RnIapConsole.warn('[purchaseErrorListener] native remove failed:', e);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
515
519
|
},
|
|
516
520
|
};
|
|
517
521
|
};
|
|
@@ -871,8 +875,7 @@ export const fetchProducts: QueryField<'fetchProducts'> = async (request) => {
|
|
|
871
875
|
|
|
872
876
|
if (normalizedType === 'all') {
|
|
873
877
|
const converted = (await fetchAndConvert('all')) as (
|
|
874
|
-
|
|
|
875
|
-
| ProductSubscription
|
|
878
|
+
Product | ProductSubscription
|
|
876
879
|
)[];
|
|
877
880
|
|
|
878
881
|
RnIapConsole.debug(
|
|
@@ -1104,6 +1107,10 @@ export const getPromotedProductIOS: QueryField<
|
|
|
1104
1107
|
}
|
|
1105
1108
|
};
|
|
1106
1109
|
|
|
1110
|
+
/**
|
|
1111
|
+
* @deprecated Use `getPromotedProductIOS` instead. This compatibility alias
|
|
1112
|
+
* will be removed in react-native-iap 16.0.0.
|
|
1113
|
+
*/
|
|
1107
1114
|
export const requestPromotedProductIOS = getPromotedProductIOS;
|
|
1108
1115
|
|
|
1109
1116
|
/**
|
|
@@ -1118,6 +1125,8 @@ export const requestPromotedProductIOS = getPromotedProductIOS;
|
|
|
1118
1125
|
* ```
|
|
1119
1126
|
*
|
|
1120
1127
|
* @see {@link https://openiap.dev/docs/apis/ios/get-storefront-ios}
|
|
1128
|
+
* @deprecated Use `getStorefront` instead. Scheduled for removal in
|
|
1129
|
+
* react-native-iap 16.0.0.
|
|
1121
1130
|
*/
|
|
1122
1131
|
export const getStorefrontIOS: QueryField<'getStorefrontIOS'> = async () => {
|
|
1123
1132
|
if (Platform.OS !== 'ios') {
|
|
@@ -1521,13 +1530,21 @@ export const getReceiptDataIOS: QueryField<'getReceiptDataIOS'> = async () => {
|
|
|
1521
1530
|
}
|
|
1522
1531
|
};
|
|
1523
1532
|
|
|
1533
|
+
/**
|
|
1534
|
+
* Legacy alias for `getReceiptDataIOS`.
|
|
1535
|
+
*
|
|
1536
|
+
* @deprecated Use `getReceiptDataIOS` for the cumulative App Store receipt or
|
|
1537
|
+
* `getTransactionJwsIOS(productId)` for one transaction. This alias will be
|
|
1538
|
+
* removed in react-native-iap 16.0.0.
|
|
1539
|
+
*/
|
|
1524
1540
|
export const getReceiptIOS = async (): Promise<string> => {
|
|
1525
1541
|
if (Platform.OS !== 'ios') {
|
|
1526
1542
|
throw new Error('getReceiptIOS is only available on iOS');
|
|
1527
1543
|
}
|
|
1528
1544
|
|
|
1529
1545
|
RnIapConsole.warn(
|
|
1530
|
-
'[getReceiptIOS]
|
|
1546
|
+
'[getReceiptIOS] is deprecated and will be removed in react-native-iap 16.0.0. ' +
|
|
1547
|
+
'Use getReceiptDataIOS() for the cumulative receipt. iOS receipts contain ALL transactions, not just the latest one. ' +
|
|
1531
1548
|
'For individual purchase validation, use getTransactionJwsIOS(productId) instead. ' +
|
|
1532
1549
|
'See: https://react-native-iap.hyo.dev/docs/guides/receipt-validation',
|
|
1533
1550
|
);
|
|
@@ -1791,19 +1808,22 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
|
|
|
1791
1808
|
throw new Error('Missing purchase request configuration');
|
|
1792
1809
|
}
|
|
1793
1810
|
|
|
1811
|
+
const iosRequestSource =
|
|
1812
|
+
Platform.OS === 'ios'
|
|
1813
|
+
? selectApplePurchaseRequest(perPlatformRequest)
|
|
1814
|
+
: undefined;
|
|
1815
|
+
const androidRequestSource = isAndroidStoreRuntime()
|
|
1816
|
+
? selectGooglePurchaseRequest(perPlatformRequest)
|
|
1817
|
+
: undefined;
|
|
1818
|
+
|
|
1794
1819
|
if (Platform.OS === 'ios') {
|
|
1795
|
-
|
|
1796
|
-
const iosRequest = perPlatformRequest.apple ?? perPlatformRequest.ios;
|
|
1797
|
-
if (!iosRequest?.sku) {
|
|
1820
|
+
if (!iosRequestSource?.sku) {
|
|
1798
1821
|
throw new Error(
|
|
1799
1822
|
'Invalid request for iOS. The `sku` property is required.',
|
|
1800
1823
|
);
|
|
1801
1824
|
}
|
|
1802
1825
|
} else if (isAndroidStoreRuntime()) {
|
|
1803
|
-
|
|
1804
|
-
const androidRequest =
|
|
1805
|
-
perPlatformRequest.google ?? perPlatformRequest.android;
|
|
1806
|
-
if (!androidRequest?.skus?.length) {
|
|
1826
|
+
if (!androidRequestSource?.skus?.length) {
|
|
1807
1827
|
throw new Error(
|
|
1808
1828
|
'Invalid request for Android. The `skus` property is required and must be a non-empty array.',
|
|
1809
1829
|
);
|
|
@@ -1814,14 +1834,12 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
|
|
|
1814
1834
|
|
|
1815
1835
|
const unifiedRequest: NitroPurchaseRequest = {};
|
|
1816
1836
|
|
|
1817
|
-
// Support both 'apple' (recommended) and 'ios' (deprecated) fields
|
|
1818
|
-
const iosRequestSource = perPlatformRequest.apple ?? perPlatformRequest.ios;
|
|
1819
1837
|
if (Platform.OS === 'ios' && iosRequestSource) {
|
|
1820
1838
|
const iosRequest = isSubs
|
|
1821
1839
|
? (iosRequestSource as RequestSubscriptionIosProps)
|
|
1822
1840
|
: (iosRequestSource as RequestPurchaseIosProps);
|
|
1823
1841
|
|
|
1824
|
-
const iosPayload: NonNullable<NitroPurchaseRequest['
|
|
1842
|
+
const iosPayload: NonNullable<NitroPurchaseRequest['apple']> = {
|
|
1825
1843
|
sku: iosRequest.sku,
|
|
1826
1844
|
};
|
|
1827
1845
|
|
|
@@ -1861,18 +1879,15 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
|
|
|
1861
1879
|
}
|
|
1862
1880
|
}
|
|
1863
1881
|
|
|
1864
|
-
unifiedRequest.
|
|
1882
|
+
unifiedRequest.apple = iosPayload;
|
|
1865
1883
|
}
|
|
1866
1884
|
|
|
1867
|
-
// Support both 'google' (recommended) and 'android' (deprecated) fields
|
|
1868
|
-
const androidRequestSource =
|
|
1869
|
-
perPlatformRequest.google ?? perPlatformRequest.android;
|
|
1870
1885
|
if (isAndroidStoreRuntime() && androidRequestSource) {
|
|
1871
1886
|
const androidRequest = isSubs
|
|
1872
1887
|
? (androidRequestSource as RequestSubscriptionAndroidProps)
|
|
1873
1888
|
: (androidRequestSource as RequestPurchaseAndroidProps);
|
|
1874
1889
|
|
|
1875
|
-
const androidPayload: NonNullable<NitroPurchaseRequest['
|
|
1890
|
+
const androidPayload: NonNullable<NitroPurchaseRequest['google']> = {
|
|
1876
1891
|
skus: androidRequest.skus,
|
|
1877
1892
|
};
|
|
1878
1893
|
|
|
@@ -1926,7 +1941,7 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
|
|
|
1926
1941
|
}));
|
|
1927
1942
|
}
|
|
1928
1943
|
|
|
1929
|
-
unifiedRequest.
|
|
1944
|
+
unifiedRequest.google = androidPayload;
|
|
1930
1945
|
}
|
|
1931
1946
|
|
|
1932
1947
|
return await IAP.instance.requestPurchase(unifiedRequest);
|
|
@@ -2112,13 +2127,40 @@ export const consumePurchaseAndroid: MutationField<
|
|
|
2112
2127
|
}
|
|
2113
2128
|
};
|
|
2114
2129
|
|
|
2130
|
+
/**
|
|
2131
|
+
* Open the Google Play offer/promo code redemption page (Android only).
|
|
2132
|
+
* On Google Play builds, launches the Play Store redeem page so the user can
|
|
2133
|
+
* enter a code. Returns false on store flavors without an equivalent flow.
|
|
2134
|
+
* Does not require the billing client to be initialized. Reconcile purchases
|
|
2135
|
+
* when the app resumes because listener delivery depends on connection state.
|
|
2136
|
+
*
|
|
2137
|
+
* @returns Promise<boolean> - true when the redemption page was launched
|
|
2138
|
+
* @platform Android
|
|
2139
|
+
*
|
|
2140
|
+
* @example
|
|
2141
|
+
* ```typescript
|
|
2142
|
+
* await openRedeemOfferCodeAndroid();
|
|
2143
|
+
* // Reconcile with getAvailablePurchases() when the app resumes.
|
|
2144
|
+
* ```
|
|
2145
|
+
*
|
|
2146
|
+
* @see {@link https://openiap.dev/docs/apis/android/open-redeem-offer-code-android}
|
|
2147
|
+
*/
|
|
2148
|
+
export const openRedeemOfferCodeAndroid: MutationField<
|
|
2149
|
+
'openRedeemOfferCodeAndroid'
|
|
2150
|
+
> = async () => {
|
|
2151
|
+
if (Platform.OS !== 'android') {
|
|
2152
|
+
throw new Error('openRedeemOfferCodeAndroid is only supported on Android');
|
|
2153
|
+
}
|
|
2154
|
+
return IAP.instance.openRedeemOfferCodeAndroid();
|
|
2155
|
+
};
|
|
2156
|
+
|
|
2115
2157
|
// ============================================================================
|
|
2116
2158
|
// iOS-SPECIFIC FUNCTIONS
|
|
2117
2159
|
// ============================================================================
|
|
2118
2160
|
|
|
2119
2161
|
/**
|
|
2120
2162
|
* Validate receipt on both iOS and Android platforms
|
|
2121
|
-
* @deprecated Use `verifyPurchase` instead. This function will be removed in
|
|
2163
|
+
* @deprecated Use `verifyPurchase` instead. This function will be removed in react-native-iap 16.0.0.
|
|
2122
2164
|
* @param options - Platform-specific verification options
|
|
2123
2165
|
* @param options.apple - Apple App Store verification options (iOS)
|
|
2124
2166
|
* @param options.google - Google Play verification options (Android)
|
|
@@ -2280,9 +2322,8 @@ export const verifyPurchase: MutationField<'verifyPurchase'> = validateReceipt;
|
|
|
2280
2322
|
/**
|
|
2281
2323
|
* iOS-only receipt validation alias.
|
|
2282
2324
|
*
|
|
2283
|
-
* @deprecated Use `verifyPurchase`
|
|
2284
|
-
*
|
|
2285
|
-
* OpenIAP Query interface — keep working. Throws on non-iOS platforms.
|
|
2325
|
+
* @deprecated Use `verifyPurchase` instead. This compatibility alias will be
|
|
2326
|
+
* removed in react-native-iap 16.0.0. Throws on non-iOS platforms.
|
|
2286
2327
|
*
|
|
2287
2328
|
* @see {@link https://openiap.dev/docs/apis/ios/validate-receipt-ios}
|
|
2288
2329
|
*/
|
|
@@ -2430,7 +2471,9 @@ export const presentCodeRedemptionSheetIOS: MutationField<
|
|
|
2430
2471
|
|
|
2431
2472
|
/**
|
|
2432
2473
|
* Buy promoted product on iOS
|
|
2433
|
-
* @deprecated In StoreKit 2, promoted products can be purchased directly via
|
|
2474
|
+
* @deprecated In StoreKit 2, promoted products can be purchased directly via
|
|
2475
|
+
* the standard `requestPurchase()` flow. This alias will be removed in
|
|
2476
|
+
* react-native-iap 16.0.0.
|
|
2434
2477
|
* Use `promotedProductListenerIOS` to receive the product ID when a user taps a promoted product,
|
|
2435
2478
|
* then call `requestPurchase()` with the received SKU directly.
|
|
2436
2479
|
*
|
|
@@ -2638,6 +2681,7 @@ export const getActiveSubscriptions: QueryField<
|
|
|
2638
2681
|
willAutoRenew: sub.renewalInfoIOS.willAutoRenew ?? false,
|
|
2639
2682
|
autoRenewPreference:
|
|
2640
2683
|
sub.renewalInfoIOS.autoRenewPreference ?? null,
|
|
2684
|
+
commitmentInfo: sub.renewalInfoIOS.commitmentInfo ?? null,
|
|
2641
2685
|
pendingUpgradeProductId:
|
|
2642
2686
|
sub.renewalInfoIOS.pendingUpgradeProductId ?? null,
|
|
2643
2687
|
renewalDate: sub.renewalInfoIOS.renewalDate ?? null,
|
|
@@ -2647,8 +2691,11 @@ export const getActiveSubscriptions: QueryField<
|
|
|
2647
2691
|
sub.renewalInfoIOS.gracePeriodExpirationDate ?? null,
|
|
2648
2692
|
priceIncreaseStatus:
|
|
2649
2693
|
sub.renewalInfoIOS.priceIncreaseStatus ?? null,
|
|
2694
|
+
renewalBillingPlanType:
|
|
2695
|
+
sub.renewalInfoIOS.renewalBillingPlanType ?? null,
|
|
2650
2696
|
renewalOfferType: sub.renewalInfoIOS.renewalOfferType ?? null,
|
|
2651
2697
|
renewalOfferId: sub.renewalInfoIOS.renewalOfferId ?? null,
|
|
2698
|
+
jsonRepresentation: sub.renewalInfoIOS.jsonRepresentation ?? null,
|
|
2652
2699
|
}
|
|
2653
2700
|
: null,
|
|
2654
2701
|
// Android specific fields
|
|
@@ -2712,12 +2759,14 @@ export {
|
|
|
2712
2759
|
|
|
2713
2760
|
// Deprecated exports for backward compatibility
|
|
2714
2761
|
/**
|
|
2715
|
-
* @deprecated Use acknowledgePurchaseAndroid instead
|
|
2762
|
+
* @deprecated Use acknowledgePurchaseAndroid instead. This alias will be
|
|
2763
|
+
* removed in react-native-iap 16.0.0.
|
|
2716
2764
|
*/
|
|
2717
2765
|
export const acknowledgePurchase = acknowledgePurchaseAndroid;
|
|
2718
2766
|
|
|
2719
2767
|
/**
|
|
2720
|
-
* @deprecated Use consumePurchaseAndroid instead
|
|
2768
|
+
* @deprecated Use consumePurchaseAndroid instead. This alias will be removed
|
|
2769
|
+
* in react-native-iap 16.0.0.
|
|
2721
2770
|
*/
|
|
2722
2771
|
export const consumePurchase = consumePurchaseAndroid;
|
|
2723
2772
|
|
|
@@ -2726,9 +2775,45 @@ export const consumePurchase = consumePurchaseAndroid;
|
|
|
2726
2775
|
// ============================================================================
|
|
2727
2776
|
|
|
2728
2777
|
type NitroDiscountOfferRecord = NonNullable<
|
|
2729
|
-
NonNullable<NitroPurchaseRequest['
|
|
2778
|
+
NonNullable<NitroPurchaseRequest['apple']>['withOffer']
|
|
2730
2779
|
>;
|
|
2731
2780
|
|
|
2781
|
+
const selectApplePurchaseRequest = (
|
|
2782
|
+
request:
|
|
2783
|
+
RequestPurchasePropsByPlatforms | RequestSubscriptionPropsByPlatforms,
|
|
2784
|
+
): RequestPurchaseIosProps | RequestSubscriptionIosProps | null | undefined => {
|
|
2785
|
+
const selection = selectCanonicalPlatformRequest<
|
|
2786
|
+
RequestPurchaseIosProps | RequestSubscriptionIosProps
|
|
2787
|
+
>(request, 'apple', 'ios');
|
|
2788
|
+
if (selection.usesLegacyKey && selection.value != null) {
|
|
2789
|
+
warnLegacyOnce(
|
|
2790
|
+
'request-purchase.ios',
|
|
2791
|
+
'[react-native-iap] `request.ios` is deprecated and will be removed in react-native-iap 16.0.0. Use `request.apple` instead.',
|
|
2792
|
+
);
|
|
2793
|
+
}
|
|
2794
|
+
return selection.value;
|
|
2795
|
+
};
|
|
2796
|
+
|
|
2797
|
+
const selectGooglePurchaseRequest = (
|
|
2798
|
+
request:
|
|
2799
|
+
RequestPurchasePropsByPlatforms | RequestSubscriptionPropsByPlatforms,
|
|
2800
|
+
):
|
|
2801
|
+
| RequestPurchaseAndroidProps
|
|
2802
|
+
| RequestSubscriptionAndroidProps
|
|
2803
|
+
| null
|
|
2804
|
+
| undefined => {
|
|
2805
|
+
const selection = selectCanonicalPlatformRequest<
|
|
2806
|
+
RequestPurchaseAndroidProps | RequestSubscriptionAndroidProps
|
|
2807
|
+
>(request, 'google', 'android');
|
|
2808
|
+
if (selection.usesLegacyKey && selection.value != null) {
|
|
2809
|
+
warnLegacyOnce(
|
|
2810
|
+
'request-purchase.android',
|
|
2811
|
+
'[react-native-iap] `request.android` is deprecated and will be removed in react-native-iap 16.0.0. Use `request.google` instead.',
|
|
2812
|
+
);
|
|
2813
|
+
}
|
|
2814
|
+
return selection.value;
|
|
2815
|
+
};
|
|
2816
|
+
|
|
2732
2817
|
const toDiscountOfferRecordIOS = (
|
|
2733
2818
|
offer: DiscountOfferInputIOS | null | undefined,
|
|
2734
2819
|
): NitroDiscountOfferRecord | undefined => {
|
|
@@ -2746,7 +2831,7 @@ const toDiscountOfferRecordIOS = (
|
|
|
2746
2831
|
|
|
2747
2832
|
const toNitroProductType = (
|
|
2748
2833
|
type?: ProductTypeInput | ProductQueryType | null,
|
|
2749
|
-
): '
|
|
2834
|
+
): 'in-app' | 'subs' | 'all' => {
|
|
2750
2835
|
if (type === 'subs') {
|
|
2751
2836
|
return 'subs';
|
|
2752
2837
|
}
|
|
@@ -2754,10 +2839,10 @@ const toNitroProductType = (
|
|
|
2754
2839
|
return 'all';
|
|
2755
2840
|
}
|
|
2756
2841
|
if (type === 'inapp') {
|
|
2757
|
-
|
|
2758
|
-
return '
|
|
2842
|
+
warnLegacyOnce('product-type.inapp', LEGACY_INAPP_WARNING);
|
|
2843
|
+
return 'in-app';
|
|
2759
2844
|
}
|
|
2760
|
-
return '
|
|
2845
|
+
return 'in-app';
|
|
2761
2846
|
};
|
|
2762
2847
|
|
|
2763
2848
|
const isSubscriptionQuery = (type?: ProductQueryType | null): boolean =>
|
|
@@ -2780,7 +2865,7 @@ const normalizeProductQueryType = (
|
|
|
2780
2865
|
return 'subs';
|
|
2781
2866
|
}
|
|
2782
2867
|
if (normalized === 'inapp') {
|
|
2783
|
-
|
|
2868
|
+
warnLegacyOnce('product-type.inapp', LEGACY_INAPP_WARNING);
|
|
2784
2869
|
return 'in-app';
|
|
2785
2870
|
}
|
|
2786
2871
|
if (normalized === 'in-app') {
|
|
@@ -2815,6 +2900,8 @@ const normalizeProductQueryType = (
|
|
|
2815
2900
|
* ```
|
|
2816
2901
|
*
|
|
2817
2902
|
* @see {@link https://openiap.dev/docs/apis/android/check-alternative-billing-availability-android}
|
|
2903
|
+
* @deprecated Use `isBillingProgramAvailableAndroid('external-offer')`
|
|
2904
|
+
* instead. Scheduled for removal in react-native-iap 16.0.0.
|
|
2818
2905
|
*/
|
|
2819
2906
|
export const checkAlternativeBillingAvailabilityAndroid: MutationField<
|
|
2820
2907
|
'checkAlternativeBillingAvailabilityAndroid'
|
|
@@ -2857,6 +2944,8 @@ export const checkAlternativeBillingAvailabilityAndroid: MutationField<
|
|
|
2857
2944
|
* ```
|
|
2858
2945
|
*
|
|
2859
2946
|
* @see {@link https://openiap.dev/docs/apis/android/show-alternative-billing-dialog-android}
|
|
2947
|
+
* @deprecated Use `launchExternalLinkAndroid` instead. Scheduled for removal in
|
|
2948
|
+
* react-native-iap 16.0.0.
|
|
2860
2949
|
*/
|
|
2861
2950
|
export const showAlternativeBillingDialogAndroid: MutationField<
|
|
2862
2951
|
'showAlternativeBillingDialogAndroid'
|
|
@@ -2896,6 +2985,9 @@ export const showAlternativeBillingDialogAndroid: MutationField<
|
|
|
2896
2985
|
* ```
|
|
2897
2986
|
*
|
|
2898
2987
|
* @see {@link https://openiap.dev/docs/apis/android/create-alternative-billing-token-android}
|
|
2988
|
+
* @deprecated Use
|
|
2989
|
+
* `createBillingProgramReportingDetailsAndroid('external-offer')` instead.
|
|
2990
|
+
* Scheduled for removal in react-native-iap 16.0.0.
|
|
2899
2991
|
*/
|
|
2900
2992
|
export const createAlternativeBillingTokenAndroid: MutationField<
|
|
2901
2993
|
'createAlternativeBillingTokenAndroid'
|