react-native-iap 15.1.0 → 15.2.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 +171 -114
- package/android/src/main/java/com/margelo/nitro/iap/ProductQueryHelpers.kt +42 -0
- package/android/src/test/java/com/margelo/nitro/iap/ProductQueryHelpersTest.kt +140 -0
- package/ios/HybridRnIap.swift +72 -1
- package/lib/module/hooks/useIAP.js +11 -1
- package/lib/module/hooks/useIAP.js.map +1 -1
- package/lib/module/hooks/useWebhookEvents.js +113 -0
- package/lib/module/hooks/useWebhookEvents.js.map +1 -0
- package/lib/module/index.js +405 -131
- package/lib/module/index.js.map +1 -1
- package/lib/module/kit-api.js +161 -0
- package/lib/module/kit-api.js.map +1 -0
- package/lib/module/types.js +16 -0
- package/lib/module/types.js.map +1 -1
- package/lib/module/utils/error.js.map +1 -1
- package/lib/module/utils/errorMapping.js +6 -0
- package/lib/module/utils/errorMapping.js.map +1 -1
- package/lib/module/webhook-client.js +164 -0
- package/lib/module/webhook-client.js.map +1 -0
- package/lib/typescript/plugin/src/withIAP.d.ts +1 -1
- package/lib/typescript/src/hooks/useIAP.d.ts +172 -2
- package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useWebhookEvents.d.ts +55 -0
- package/lib/typescript/src/hooks/useWebhookEvents.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +283 -129
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/kit-api.d.ts +54 -0
- package/lib/typescript/src/kit-api.d.ts.map +1 -0
- package/lib/typescript/src/specs/RnIap.nitro.d.ts +24 -0
- package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +320 -75
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/utils/error.d.ts +3 -0
- package/lib/typescript/src/utils/error.d.ts.map +1 -1
- package/lib/typescript/src/utils/errorMapping.d.ts +6 -0
- package/lib/typescript/src/utils/errorMapping.d.ts.map +1 -1
- package/lib/typescript/src/webhook-client.d.ts +82 -0
- package/lib/typescript/src/webhook-client.d.ts.map +1 -0
- package/nitrogen/generated/android/NitroIap+autolinking.cmake +3 -0
- package/nitrogen/generated/android/c++/JAdvancedCommerceInfoIOS.hpp +118 -0
- package/nitrogen/generated/android/c++/JAdvancedCommerceItemDetailsIOS.hpp +62 -0
- package/nitrogen/generated/android/c++/JAdvancedCommerceItemIOS.hpp +78 -0
- package/nitrogen/generated/android/c++/JAdvancedCommerceRefundIOS.hpp +62 -0
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +52 -0
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +3 -0
- package/nitrogen/generated/android/c++/JPurchase.hpp +11 -0
- package/nitrogen/generated/android/c++/JPurchaseIOS.hpp +16 -1
- package/nitrogen/generated/android/c++/JRequestPurchaseResult.hpp +11 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_AdvancedCommerceInfoIOS.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_AdvancedCommerceInfoIOS.hpp +84 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_AdvancedCommerceItemDetailsIOS.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_AdvancedCommerceItemDetailsIOS.hpp +74 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_Array_AdvancedCommerceRefundIOS_.cpp +35 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_Array_AdvancedCommerceRefundIOS_.hpp +84 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/AdvancedCommerceInfoIOS.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/AdvancedCommerceItemDetailsIOS.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/AdvancedCommerceItemIOS.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/AdvancedCommerceRefundIOS.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseIOS.kt +5 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_NullType_AdvancedCommerceInfoIOS.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_NullType_AdvancedCommerceItemDetailsIOS.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_NullType_Array_AdvancedCommerceRefundIOS_.kt +53 -0
- package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.hpp +166 -0
- package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +12 -0
- package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +32 -0
- package/nitrogen/generated/ios/swift/AdvancedCommerceInfoIOS.swift +294 -0
- package/nitrogen/generated/ios/swift/AdvancedCommerceItemDetailsIOS.swift +61 -0
- package/nitrogen/generated/ios/swift/AdvancedCommerceItemIOS.swift +141 -0
- package/nitrogen/generated/ios/swift/AdvancedCommerceRefundIOS.swift +61 -0
- package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +3 -0
- package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +57 -0
- package/nitrogen/generated/ios/swift/PurchaseIOS.swift +39 -2
- package/nitrogen/generated/ios/swift/Variant_NullType_AdvancedCommerceInfoIOS.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_AdvancedCommerceItemDetailsIOS.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_NullType__AdvancedCommerceRefundIOS_.swift +18 -0
- package/nitrogen/generated/shared/c++/AdvancedCommerceInfoIOS.hpp +117 -0
- package/nitrogen/generated/shared/c++/AdvancedCommerceItemDetailsIOS.hpp +86 -0
- package/nitrogen/generated/shared/c++/AdvancedCommerceItemIOS.hpp +99 -0
- package/nitrogen/generated/shared/c++/AdvancedCommerceRefundIOS.hpp +86 -0
- package/nitrogen/generated/shared/c++/HybridRnIapSpec.cpp +3 -0
- package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +3 -0
- package/nitrogen/generated/shared/c++/PurchaseIOS.hpp +9 -2
- package/openiap-versions.json +3 -3
- package/package.json +1 -1
- package/plugin/build/withIAP.d.ts +1 -1
- package/plugin/src/withIAP.ts +1 -1
- package/src/hooks/useIAP.ts +185 -2
- package/src/hooks/useWebhookEvents.ts +180 -0
- package/src/index.ts +440 -130
- package/src/kit-api.ts +225 -0
- package/src/specs/RnIap.nitro.ts +31 -0
- package/src/types.ts +330 -75
- package/src/utils/error.ts +3 -0
- package/src/utils/errorMapping.ts +12 -0
- package/src/webhook-client.ts +312 -0
package/lib/module/index.js
CHANGED
|
@@ -39,7 +39,9 @@ const toErrorMessage = error => {
|
|
|
39
39
|
|
|
40
40
|
// Export hooks
|
|
41
41
|
export { useIAP } from "./hooks/useIAP.js";
|
|
42
|
-
|
|
42
|
+
export { useWebhookEvents } from "./hooks/useWebhookEvents.js";
|
|
43
|
+
export { connectWebhookStream, parseWebhookEventData } from "./webhook-client.js";
|
|
44
|
+
export { kitApi, KitApiError } from "./kit-api.js";
|
|
43
45
|
// Restore completed transactions (cross-platform)
|
|
44
46
|
// Development utilities removed - use type bridge functions directly if needed
|
|
45
47
|
|
|
@@ -170,12 +172,14 @@ export const resetListenerState = () => {
|
|
|
170
172
|
promotedProductNativeAttached = false;
|
|
171
173
|
userChoiceBillingNativeAttached = false;
|
|
172
174
|
developerProvidedBillingNativeAttached = false;
|
|
175
|
+
subscriptionBillingIssueNativeAttached = false;
|
|
173
176
|
// Clear all JS listeners since native side clears them in endConnection
|
|
174
177
|
purchaseUpdateJsListeners.clear();
|
|
175
178
|
purchaseErrorJsListeners.clear();
|
|
176
179
|
promotedProductJsListeners.clear();
|
|
177
180
|
userChoiceBillingJsListeners.clear();
|
|
178
181
|
developerProvidedBillingJsListeners.clear();
|
|
182
|
+
subscriptionBillingIssueJsListeners.clear();
|
|
179
183
|
};
|
|
180
184
|
export const purchaseUpdatedListener = listener => {
|
|
181
185
|
purchaseUpdateJsListeners.add(listener);
|
|
@@ -388,25 +392,105 @@ export const developerProvidedBillingListenerAndroid = listener => {
|
|
|
388
392
|
};
|
|
389
393
|
};
|
|
390
394
|
|
|
395
|
+
/**
|
|
396
|
+
* Listen for subscription billing-issue events (cross-platform).
|
|
397
|
+
*
|
|
398
|
+
* Fires when an active subscription enters a billing-issue state:
|
|
399
|
+
* - iOS 18+ / Mac Catalyst 18+: via StoreKit 2 `Message.Reason.billingIssue`.
|
|
400
|
+
* - Android (Play Billing 8.1+): when `isSuspendedAndroid === true` is observed.
|
|
401
|
+
* - Horizon / iOS 17 / older platforms: never fires.
|
|
402
|
+
*
|
|
403
|
+
* Recommended UX: on fire, call `deepLinkToSubscriptions()` so the user can
|
|
404
|
+
* update their payment method in the platform subscription center.
|
|
405
|
+
*
|
|
406
|
+
* @param listener - Function to call with the affected Purchase
|
|
407
|
+
* @returns EventSubscription with remove() method to unsubscribe
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* ```typescript
|
|
411
|
+
* const subscription = subscriptionBillingIssueListener((purchase) => {
|
|
412
|
+
* console.warn('Subscription needs attention:', purchase.productId);
|
|
413
|
+
* deepLinkToSubscriptions({skuAndroid: purchase.productId, packageNameAndroid: 'com.example.app'});
|
|
414
|
+
* });
|
|
415
|
+
*
|
|
416
|
+
* subscription.remove();
|
|
417
|
+
* ```
|
|
418
|
+
*/
|
|
419
|
+
|
|
420
|
+
const subscriptionBillingIssueJsListeners = new Set();
|
|
421
|
+
let subscriptionBillingIssueNativeAttached = false;
|
|
422
|
+
const subscriptionBillingIssueNativeHandler = nitroPurchase => {
|
|
423
|
+
if (!validateNitroPurchase(nitroPurchase)) {
|
|
424
|
+
RnIapConsole.warn('[subscriptionBillingIssueListener] dropped malformed native payload');
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
const purchase = convertNitroPurchaseToPurchase(nitroPurchase);
|
|
428
|
+
for (const listener of subscriptionBillingIssueJsListeners) {
|
|
429
|
+
try {
|
|
430
|
+
listener(purchase);
|
|
431
|
+
} catch (e) {
|
|
432
|
+
RnIapConsole.error('[subscriptionBillingIssueListener] callback threw:', e);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
function tryAttachSubscriptionBillingIssueNative() {
|
|
437
|
+
if (subscriptionBillingIssueNativeAttached) return;
|
|
438
|
+
try {
|
|
439
|
+
IAP.instance.addSubscriptionBillingIssueListener(subscriptionBillingIssueNativeHandler);
|
|
440
|
+
subscriptionBillingIssueNativeAttached = true;
|
|
441
|
+
} catch (e) {
|
|
442
|
+
const msg = toErrorMessage(e);
|
|
443
|
+
if (msg.includes('Nitro runtime not installed')) {
|
|
444
|
+
RnIapConsole.warn('[subscriptionBillingIssueListener] Nitro not ready yet; will retry on next registration after initConnection()');
|
|
445
|
+
} else {
|
|
446
|
+
throw e;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
export const subscriptionBillingIssueListener = listener => {
|
|
451
|
+
subscriptionBillingIssueJsListeners.add(listener);
|
|
452
|
+
// Retry attachment every call so a listener registered before initConnection()
|
|
453
|
+
// doesn't stay permanently inert once Nitro is ready.
|
|
454
|
+
try {
|
|
455
|
+
tryAttachSubscriptionBillingIssueNative();
|
|
456
|
+
} catch (error) {
|
|
457
|
+
subscriptionBillingIssueJsListeners.delete(listener);
|
|
458
|
+
throw error;
|
|
459
|
+
}
|
|
460
|
+
return {
|
|
461
|
+
remove: () => {
|
|
462
|
+
subscriptionBillingIssueJsListeners.delete(listener);
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
};
|
|
466
|
+
|
|
391
467
|
// ------------------------------
|
|
392
468
|
// Query API
|
|
393
469
|
// ------------------------------
|
|
394
470
|
|
|
395
471
|
/**
|
|
396
|
-
*
|
|
397
|
-
* @param params - Product request configuration
|
|
398
|
-
* @param params.skus - Array of product SKUs to fetch
|
|
399
|
-
* @param params.type - Optional filter: 'in-app' (default) for products, 'subs' for subscriptions, or 'all' for both.
|
|
400
|
-
* @returns Promise<Product[]> - Array of products from the store
|
|
472
|
+
* Retrieve products or subscriptions from the store by SKU.
|
|
401
473
|
*
|
|
402
|
-
* @
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
474
|
+
* @param request `ProductRequest` — `skus` (string[]) and optional `type`
|
|
475
|
+
* (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
|
|
476
|
+
* @returns Promise resolving to a `FetchProductsResult` union — `Product[]` for `'in-app'`,
|
|
477
|
+
* `ProductSubscription[]` for `'subs'`, a mixed array for `'all'`, or `null`
|
|
478
|
+
* (the schema retains the nullable branch for backwards compatibility).
|
|
479
|
+
* @throws When the store rejects the request (empty `skus`, not connected,
|
|
480
|
+
* network/store error). Unknown SKUs are simply omitted from the result, not thrown.
|
|
406
481
|
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
482
|
+
* @example
|
|
483
|
+
* ```ts
|
|
484
|
+
* const products = await fetchProducts({
|
|
485
|
+
* skus: ['com.app.coins_100', 'com.app.premium'],
|
|
486
|
+
* type: 'in-app',
|
|
487
|
+
* });
|
|
409
488
|
* ```
|
|
489
|
+
*
|
|
490
|
+
* @remarks This is a regular promise-based call. Don't confuse with `request*` APIs
|
|
491
|
+
* (`requestPurchase`), which are event-based.
|
|
492
|
+
*
|
|
493
|
+
* @see {@link https://www.openiap.dev/docs/apis/fetch-products}
|
|
410
494
|
*/
|
|
411
495
|
export const fetchProducts = async request => {
|
|
412
496
|
const {
|
|
@@ -480,22 +564,40 @@ export const fetchProducts = async request => {
|
|
|
480
564
|
return convertedProducts;
|
|
481
565
|
} catch (error) {
|
|
482
566
|
RnIapConsole.error('[fetchProducts] Failed:', error);
|
|
483
|
-
|
|
567
|
+
const parsedError = parseErrorStringToJsonObj(error);
|
|
568
|
+
throw createPurchaseError({
|
|
569
|
+
code: parsedError.code,
|
|
570
|
+
message: parsedError.message,
|
|
571
|
+
responseCode: parsedError.responseCode,
|
|
572
|
+
debugMessage: parsedError.debugMessage,
|
|
573
|
+
productId: parsedError.productId,
|
|
574
|
+
productIds: parsedError.productIds,
|
|
575
|
+
productType: parsedError.productType,
|
|
576
|
+
isEmptyProductList: parsedError.isEmptyProductList,
|
|
577
|
+
platform: Platform.OS === 'ios' ? 'ios' : 'android'
|
|
578
|
+
});
|
|
484
579
|
}
|
|
485
580
|
};
|
|
486
581
|
|
|
487
582
|
/**
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
* @param
|
|
583
|
+
* List the user's unfinished purchases — non-consumables, active subscriptions, and any
|
|
584
|
+
* pending transactions not yet finished.
|
|
585
|
+
*
|
|
586
|
+
* @param options Optional `PurchaseOptions`.
|
|
587
|
+
* - iOS: `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.
|
|
588
|
+
* - Android: `includeSuspendedAndroid` (include subscriptions in a paused/grace state).
|
|
589
|
+
* @returns Promise resolving to an array of `Purchase` currently held by the store.
|
|
590
|
+
* @throws When the platform query fails.
|
|
492
591
|
*
|
|
493
592
|
* @example
|
|
494
|
-
* ```
|
|
495
|
-
* const purchases = await getAvailablePurchases(
|
|
496
|
-
*
|
|
497
|
-
* });
|
|
593
|
+
* ```ts
|
|
594
|
+
* const purchases = await getAvailablePurchases();
|
|
595
|
+
* for (const p of purchases) {
|
|
596
|
+
* if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });
|
|
597
|
+
* }
|
|
498
598
|
* ```
|
|
599
|
+
*
|
|
600
|
+
* @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}
|
|
499
601
|
*/
|
|
500
602
|
export const getAvailablePurchases = async options => {
|
|
501
603
|
const alsoPublishToEventListenerIOS = Boolean(options?.alsoPublishToEventListenerIOS ?? false);
|
|
@@ -552,6 +654,8 @@ export const getAvailablePurchases = async options => {
|
|
|
552
654
|
* Request the promoted product from the App Store (iOS only)
|
|
553
655
|
* @returns Promise<Product | null> - The promoted product or null if none available
|
|
554
656
|
* @platform iOS
|
|
657
|
+
*
|
|
658
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios}
|
|
555
659
|
*/
|
|
556
660
|
export const getPromotedProductIOS = async () => {
|
|
557
661
|
if (Platform.OS !== 'ios') {
|
|
@@ -576,6 +680,20 @@ export const getPromotedProductIOS = async () => {
|
|
|
576
680
|
}
|
|
577
681
|
};
|
|
578
682
|
export const requestPromotedProductIOS = getPromotedProductIOS;
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Get the storefront identifier for the user's App Store account (iOS only)
|
|
686
|
+
* @returns Promise<string> - The storefront identifier (e.g., 'USA' for United States)
|
|
687
|
+
* @platform iOS
|
|
688
|
+
*
|
|
689
|
+
* @example
|
|
690
|
+
* ```typescript
|
|
691
|
+
* const storefront = await getStorefrontIOS();
|
|
692
|
+
* console.log('User storefront:', storefront); // e.g., 'USA', 'GBR', 'KOR'
|
|
693
|
+
* ```
|
|
694
|
+
*
|
|
695
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/get-storefront-ios}
|
|
696
|
+
*/
|
|
579
697
|
export const getStorefrontIOS = async () => {
|
|
580
698
|
if (Platform.OS !== 'ios') {
|
|
581
699
|
throw new Error('getStorefrontIOS is only available on iOS');
|
|
@@ -588,6 +706,12 @@ export const getStorefrontIOS = async () => {
|
|
|
588
706
|
throw error;
|
|
589
707
|
}
|
|
590
708
|
};
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Return the user's storefront country code.
|
|
712
|
+
*
|
|
713
|
+
* @see {@link https://www.openiap.dev/docs/apis/get-storefront}
|
|
714
|
+
*/
|
|
591
715
|
export const getStorefront = async () => {
|
|
592
716
|
if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
|
|
593
717
|
RnIapConsole.warn('[getStorefront] Storefront lookup is only supported on iOS and Android.');
|
|
@@ -609,6 +733,28 @@ export const getStorefront = async () => {
|
|
|
609
733
|
throw error;
|
|
610
734
|
}
|
|
611
735
|
};
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* iOS only - Gets the original app transaction ID if the app was purchased from the App Store
|
|
739
|
+
* @platform iOS
|
|
740
|
+
* @description
|
|
741
|
+
* This function retrieves the original app transaction information if the app was purchased
|
|
742
|
+
* from the App Store. Returns null if the app was not purchased (e.g., free app or TestFlight).
|
|
743
|
+
*
|
|
744
|
+
* @returns {Promise<string | null>} The original app transaction ID or null
|
|
745
|
+
*
|
|
746
|
+
* @example
|
|
747
|
+
* ```typescript
|
|
748
|
+
* const appTransaction = await getAppTransactionIOS();
|
|
749
|
+
* if (appTransaction) {
|
|
750
|
+
* console.log('App was purchased, transaction ID:', appTransaction);
|
|
751
|
+
* } else {
|
|
752
|
+
* console.log('App was not purchased from App Store');
|
|
753
|
+
* }
|
|
754
|
+
* ```
|
|
755
|
+
*
|
|
756
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios}
|
|
757
|
+
*/
|
|
612
758
|
export const getAppTransactionIOS = async () => {
|
|
613
759
|
if (Platform.OS !== 'ios') {
|
|
614
760
|
throw new Error('getAppTransactionIOS is only available on iOS');
|
|
@@ -634,6 +780,16 @@ export const getAppTransactionIOS = async () => {
|
|
|
634
780
|
throw error;
|
|
635
781
|
}
|
|
636
782
|
};
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Get subscription status for a product (iOS only)
|
|
786
|
+
* @param sku - The product SKU
|
|
787
|
+
* @returns Promise<SubscriptionStatusIOS[]> - Array of subscription status objects
|
|
788
|
+
* @throws Error when called on non-iOS platforms or when IAP is not initialized
|
|
789
|
+
* @platform iOS
|
|
790
|
+
*
|
|
791
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/subscription-status-ios}
|
|
792
|
+
*/
|
|
637
793
|
export const subscriptionStatusIOS = async sku => {
|
|
638
794
|
if (Platform.OS !== 'ios') {
|
|
639
795
|
throw new Error('subscriptionStatusIOS is only available on iOS');
|
|
@@ -653,6 +809,15 @@ export const subscriptionStatusIOS = async sku => {
|
|
|
653
809
|
});
|
|
654
810
|
}
|
|
655
811
|
};
|
|
812
|
+
|
|
813
|
+
/**
|
|
814
|
+
* Get current entitlement for a product (iOS only)
|
|
815
|
+
* @param sku - The product SKU
|
|
816
|
+
* @returns Promise<Purchase | null> - Current entitlement or null
|
|
817
|
+
* @platform iOS
|
|
818
|
+
*
|
|
819
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/current-entitlement-ios}
|
|
820
|
+
*/
|
|
656
821
|
export const currentEntitlementIOS = async sku => {
|
|
657
822
|
if (Platform.OS !== 'ios') {
|
|
658
823
|
return null;
|
|
@@ -675,6 +840,15 @@ export const currentEntitlementIOS = async sku => {
|
|
|
675
840
|
});
|
|
676
841
|
}
|
|
677
842
|
};
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Get latest transaction for a product (iOS only)
|
|
846
|
+
* @param sku - The product SKU
|
|
847
|
+
* @returns Promise<Purchase | null> - Latest transaction or null
|
|
848
|
+
* @platform iOS
|
|
849
|
+
*
|
|
850
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/latest-transaction-ios}
|
|
851
|
+
*/
|
|
678
852
|
export const latestTransactionIOS = async sku => {
|
|
679
853
|
if (Platform.OS !== 'ios') {
|
|
680
854
|
return null;
|
|
@@ -697,6 +871,14 @@ export const latestTransactionIOS = async sku => {
|
|
|
697
871
|
});
|
|
698
872
|
}
|
|
699
873
|
};
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Get pending transactions (iOS only)
|
|
877
|
+
* @returns Promise<Purchase[]> - Array of pending transactions
|
|
878
|
+
* @platform iOS
|
|
879
|
+
*
|
|
880
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios}
|
|
881
|
+
*/
|
|
700
882
|
export const getPendingTransactionsIOS = async () => {
|
|
701
883
|
if (Platform.OS !== 'ios') {
|
|
702
884
|
return [];
|
|
@@ -715,6 +897,38 @@ export const getPendingTransactionsIOS = async () => {
|
|
|
715
897
|
});
|
|
716
898
|
}
|
|
717
899
|
};
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
* List every StoreKit transaction (finished + unfinished) for the current user.
|
|
903
|
+
*
|
|
904
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios}
|
|
905
|
+
*/
|
|
906
|
+
export const getAllTransactionsIOS = async () => {
|
|
907
|
+
if (Platform.OS !== 'ios') {
|
|
908
|
+
return [];
|
|
909
|
+
}
|
|
910
|
+
try {
|
|
911
|
+
const nitroPurchases = await IAP.instance.getAllTransactionsIOS();
|
|
912
|
+
return nitroPurchases.map(convertNitroPurchaseToPurchase).filter(purchase => purchase.platform === 'ios');
|
|
913
|
+
} catch (error) {
|
|
914
|
+
RnIapConsole.error('[getAllTransactionsIOS] Failed:', error);
|
|
915
|
+
const parsedError = parseErrorStringToJsonObj(error);
|
|
916
|
+
throw createPurchaseError({
|
|
917
|
+
code: parsedError.code,
|
|
918
|
+
message: parsedError.message,
|
|
919
|
+
responseCode: parsedError.responseCode,
|
|
920
|
+
debugMessage: parsedError.debugMessage
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* Show manage subscriptions screen (iOS only)
|
|
927
|
+
* @returns Promise<Purchase[]> - Subscriptions where auto-renewal status changed
|
|
928
|
+
* @platform iOS
|
|
929
|
+
*
|
|
930
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios}
|
|
931
|
+
*/
|
|
718
932
|
export const showManageSubscriptionsIOS = async () => {
|
|
719
933
|
if (Platform.OS !== 'ios') {
|
|
720
934
|
return [];
|
|
@@ -733,6 +947,15 @@ export const showManageSubscriptionsIOS = async () => {
|
|
|
733
947
|
});
|
|
734
948
|
}
|
|
735
949
|
};
|
|
950
|
+
|
|
951
|
+
/**
|
|
952
|
+
* Check if user is eligible for intro offer (iOS only)
|
|
953
|
+
* @param groupID - The subscription group ID
|
|
954
|
+
* @returns Promise<boolean> - Eligibility status
|
|
955
|
+
* @platform iOS
|
|
956
|
+
*
|
|
957
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios}
|
|
958
|
+
*/
|
|
736
959
|
export const isEligibleForIntroOfferIOS = async groupID => {
|
|
737
960
|
if (Platform.OS !== 'ios') {
|
|
738
961
|
return false;
|
|
@@ -750,6 +973,14 @@ export const isEligibleForIntroOfferIOS = async groupID => {
|
|
|
750
973
|
});
|
|
751
974
|
}
|
|
752
975
|
};
|
|
976
|
+
|
|
977
|
+
/**
|
|
978
|
+
* Get receipt data (iOS only)
|
|
979
|
+
* @returns Promise<string> - Base64 encoded receipt data
|
|
980
|
+
* @platform iOS
|
|
981
|
+
*
|
|
982
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios}
|
|
983
|
+
*/
|
|
753
984
|
export const getReceiptDataIOS = async () => {
|
|
754
985
|
if (Platform.OS !== 'ios') {
|
|
755
986
|
throw new Error('getReceiptDataIOS is only available on iOS');
|
|
@@ -810,6 +1041,15 @@ export const requestReceiptRefreshIOS = async () => {
|
|
|
810
1041
|
});
|
|
811
1042
|
}
|
|
812
1043
|
};
|
|
1044
|
+
|
|
1045
|
+
/**
|
|
1046
|
+
* Check if transaction is verified (iOS only)
|
|
1047
|
+
* @param sku - The product SKU
|
|
1048
|
+
* @returns Promise<boolean> - Verification status
|
|
1049
|
+
* @platform iOS
|
|
1050
|
+
*
|
|
1051
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios}
|
|
1052
|
+
*/
|
|
813
1053
|
export const isTransactionVerifiedIOS = async sku => {
|
|
814
1054
|
if (Platform.OS !== 'ios') {
|
|
815
1055
|
return false;
|
|
@@ -827,6 +1067,15 @@ export const isTransactionVerifiedIOS = async sku => {
|
|
|
827
1067
|
});
|
|
828
1068
|
}
|
|
829
1069
|
};
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* Get transaction JWS representation (iOS only)
|
|
1073
|
+
* @param sku - The product SKU
|
|
1074
|
+
* @returns Promise<string | null> - JWS representation or null
|
|
1075
|
+
* @platform iOS
|
|
1076
|
+
*
|
|
1077
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios}
|
|
1078
|
+
*/
|
|
830
1079
|
export const getTransactionJwsIOS = async sku => {
|
|
831
1080
|
if (Platform.OS !== 'ios') {
|
|
832
1081
|
return null;
|
|
@@ -850,25 +1099,23 @@ export const getTransactionJwsIOS = async sku => {
|
|
|
850
1099
|
// ------------------------------
|
|
851
1100
|
|
|
852
1101
|
/**
|
|
853
|
-
* Initialize connection
|
|
854
|
-
*
|
|
855
|
-
* @param config
|
|
1102
|
+
* Initialize the store connection. Must be called before any other IAP API.
|
|
1103
|
+
*
|
|
1104
|
+
* @param config Optional connection config. Use `enableBillingProgramAndroid` (Android,
|
|
1105
|
+
* Play Billing 8.2.0+) to opt into External Payments etc. iOS ignores Android-specific fields.
|
|
1106
|
+
* @returns Promise resolving to `true` when the platform billing client is connected.
|
|
1107
|
+
* @throws When the platform billing client fails to initialize.
|
|
856
1108
|
*
|
|
857
1109
|
* @example
|
|
858
|
-
* ```
|
|
859
|
-
* // Standard billing (default)
|
|
1110
|
+
* ```ts
|
|
860
1111
|
* await initConnection();
|
|
1112
|
+
* await initConnection({ enableBillingProgramAndroid: 'external-offer' });
|
|
1113
|
+
* ```
|
|
861
1114
|
*
|
|
862
|
-
*
|
|
863
|
-
*
|
|
864
|
-
* alternativeBillingModeAndroid: 'user-choice'
|
|
865
|
-
* });
|
|
1115
|
+
* @remarks When using `useIAP()`, connection is auto-managed on mount/unmount —
|
|
1116
|
+
* pass options to the hook instead of calling this directly.
|
|
866
1117
|
*
|
|
867
|
-
*
|
|
868
|
-
* await initConnection({
|
|
869
|
-
* alternativeBillingModeAndroid: 'alternative-only'
|
|
870
|
-
* });
|
|
871
|
-
* ```
|
|
1118
|
+
* @see {@link https://www.openiap.dev/docs/apis/init-connection}
|
|
872
1119
|
*/
|
|
873
1120
|
export const initConnection = async config => {
|
|
874
1121
|
try {
|
|
@@ -886,7 +1133,9 @@ export const initConnection = async config => {
|
|
|
886
1133
|
};
|
|
887
1134
|
|
|
888
1135
|
/**
|
|
889
|
-
*
|
|
1136
|
+
* Close the store connection and release resources.
|
|
1137
|
+
*
|
|
1138
|
+
* @see {@link https://www.openiap.dev/docs/apis/end-connection}
|
|
890
1139
|
*/
|
|
891
1140
|
export const endConnection = async () => {
|
|
892
1141
|
try {
|
|
@@ -905,6 +1154,12 @@ export const endConnection = async () => {
|
|
|
905
1154
|
});
|
|
906
1155
|
}
|
|
907
1156
|
};
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
* Restore non-consumable and active subscription purchases.
|
|
1160
|
+
*
|
|
1161
|
+
* @see {@link https://www.openiap.dev/docs/apis/restore-purchases}
|
|
1162
|
+
*/
|
|
908
1163
|
export const restorePurchases = async () => {
|
|
909
1164
|
try {
|
|
910
1165
|
if (Platform.OS === 'ios') {
|
|
@@ -927,9 +1182,30 @@ export const restorePurchases = async () => {
|
|
|
927
1182
|
};
|
|
928
1183
|
|
|
929
1184
|
/**
|
|
930
|
-
*
|
|
931
|
-
*
|
|
932
|
-
*
|
|
1185
|
+
* Initiate a purchase or subscription flow. The result is delivered through
|
|
1186
|
+
* `purchaseUpdatedListener` — NOT the return value.
|
|
1187
|
+
*
|
|
1188
|
+
* @param request `RequestPurchaseProps`, discriminated by `type`:
|
|
1189
|
+
* - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).
|
|
1190
|
+
* - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.
|
|
1191
|
+
* @returns The dispatched purchase payload. **Do not rely on it** for the actual outcome.
|
|
1192
|
+
* @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).
|
|
1193
|
+
*
|
|
1194
|
+
* @example
|
|
1195
|
+
* ```ts
|
|
1196
|
+
* await requestPurchase({
|
|
1197
|
+
* request: {
|
|
1198
|
+
* apple: { sku: 'com.app.premium' },
|
|
1199
|
+
* google: { skus: ['com.app.premium'] },
|
|
1200
|
+
* },
|
|
1201
|
+
* type: 'in-app',
|
|
1202
|
+
* });
|
|
1203
|
+
* ```
|
|
1204
|
+
*
|
|
1205
|
+
* @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /
|
|
1206
|
+
* {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.
|
|
1207
|
+
*
|
|
1208
|
+
* @see {@link https://www.openiap.dev/docs/apis/request-purchase}
|
|
933
1209
|
*/
|
|
934
1210
|
export const requestPurchase = async request => {
|
|
935
1211
|
try {
|
|
@@ -1043,19 +1319,28 @@ export const requestPurchase = async request => {
|
|
|
1043
1319
|
};
|
|
1044
1320
|
|
|
1045
1321
|
/**
|
|
1046
|
-
*
|
|
1047
|
-
*
|
|
1048
|
-
*
|
|
1049
|
-
* @param
|
|
1050
|
-
* @
|
|
1322
|
+
* Complete a purchase transaction. Call after server-side verification to remove it
|
|
1323
|
+
* from the queue.
|
|
1324
|
+
*
|
|
1325
|
+
* @param args.purchase The `Purchase` to finalize.
|
|
1326
|
+
* @param args.isConsumable `true` for consumables (consumes the token so the SKU can be
|
|
1327
|
+
* re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.
|
|
1328
|
+
* @returns Promise that resolves once the platform finalizes the transaction.
|
|
1329
|
+
* @throws When the platform finalize call fails.
|
|
1051
1330
|
*
|
|
1052
1331
|
* @example
|
|
1053
|
-
* ```
|
|
1054
|
-
*
|
|
1055
|
-
* purchase
|
|
1056
|
-
*
|
|
1332
|
+
* ```ts
|
|
1333
|
+
* purchaseUpdatedListener(async (purchase) => {
|
|
1334
|
+
* if (await verifyOnServer(purchase)) {
|
|
1335
|
+
* await finishTransaction({ purchase, isConsumable: false });
|
|
1336
|
+
* }
|
|
1057
1337
|
* });
|
|
1058
1338
|
* ```
|
|
1339
|
+
*
|
|
1340
|
+
* @remarks **Critical:** Android purchases must be finalized within 3 days or Google
|
|
1341
|
+
* auto-refunds. iOS unfinished transactions replay on every app launch.
|
|
1342
|
+
*
|
|
1343
|
+
* @see {@link https://www.openiap.dev/docs/apis/finish-transaction}
|
|
1059
1344
|
*/
|
|
1060
1345
|
export const finishTransaction = async args => {
|
|
1061
1346
|
const {
|
|
@@ -1118,6 +1403,8 @@ export const finishTransaction = async args => {
|
|
|
1118
1403
|
* ```typescript
|
|
1119
1404
|
* await acknowledgePurchaseAndroid('purchase_token_here');
|
|
1120
1405
|
* ```
|
|
1406
|
+
*
|
|
1407
|
+
* @see {@link https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android}
|
|
1121
1408
|
*/
|
|
1122
1409
|
export const acknowledgePurchaseAndroid = async purchaseToken => {
|
|
1123
1410
|
try {
|
|
@@ -1152,6 +1439,8 @@ export const acknowledgePurchaseAndroid = async purchaseToken => {
|
|
|
1152
1439
|
* ```typescript
|
|
1153
1440
|
* await consumePurchaseAndroid('purchase_token_here');
|
|
1154
1441
|
* ```
|
|
1442
|
+
*
|
|
1443
|
+
* @see {@link https://www.openiap.dev/docs/apis/android/consume-purchase-android}
|
|
1155
1444
|
*/
|
|
1156
1445
|
export const consumePurchaseAndroid = async purchaseToken => {
|
|
1157
1446
|
try {
|
|
@@ -1204,6 +1493,8 @@ export const consumePurchaseAndroid = async purchaseToken => {
|
|
|
1204
1493
|
* }
|
|
1205
1494
|
* });
|
|
1206
1495
|
* ```
|
|
1496
|
+
*
|
|
1497
|
+
* @see {@link https://www.openiap.dev/docs/apis/validate-receipt}
|
|
1207
1498
|
*/
|
|
1208
1499
|
export const validateReceipt = async options => {
|
|
1209
1500
|
const {
|
|
@@ -1311,9 +1602,28 @@ export const validateReceipt = async options => {
|
|
|
1311
1602
|
*
|
|
1312
1603
|
* @param options - Receipt validation options containing the SKU
|
|
1313
1604
|
* @returns Promise resolving to receipt validation result
|
|
1605
|
+
*
|
|
1606
|
+
* @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}
|
|
1314
1607
|
*/
|
|
1315
1608
|
export const verifyPurchase = validateReceipt;
|
|
1316
1609
|
|
|
1610
|
+
/**
|
|
1611
|
+
* iOS-only receipt validation alias.
|
|
1612
|
+
*
|
|
1613
|
+
* @deprecated Use `verifyPurchase` (or `validateReceipt`) instead. Kept so
|
|
1614
|
+
* consumers who imported `validateReceiptIOS` — which is still declared on the
|
|
1615
|
+
* OpenIAP Query interface — keep working. Throws on non-iOS platforms.
|
|
1616
|
+
*
|
|
1617
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/validate-receipt-ios}
|
|
1618
|
+
*/
|
|
1619
|
+
export const validateReceiptIOS = async options => {
|
|
1620
|
+
if (Platform.OS !== 'ios') {
|
|
1621
|
+
throw new Error('validateReceiptIOS is only available on iOS');
|
|
1622
|
+
}
|
|
1623
|
+
const result = await validateReceipt(options);
|
|
1624
|
+
return result;
|
|
1625
|
+
};
|
|
1626
|
+
|
|
1317
1627
|
/**
|
|
1318
1628
|
* Verify purchase with a specific provider (e.g., IAPKit)
|
|
1319
1629
|
*
|
|
@@ -1334,6 +1644,8 @@ export const verifyPurchase = validateReceipt;
|
|
|
1334
1644
|
* },
|
|
1335
1645
|
* });
|
|
1336
1646
|
* ```
|
|
1647
|
+
*
|
|
1648
|
+
* @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}
|
|
1337
1649
|
*/
|
|
1338
1650
|
export const verifyPurchaseWithProvider = async options => {
|
|
1339
1651
|
try {
|
|
@@ -1373,6 +1685,8 @@ export const verifyPurchaseWithProvider = async options => {
|
|
|
1373
1685
|
* Sync iOS purchases with App Store (iOS only)
|
|
1374
1686
|
* @returns Promise<boolean>
|
|
1375
1687
|
* @platform iOS
|
|
1688
|
+
*
|
|
1689
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/sync-ios}
|
|
1376
1690
|
*/
|
|
1377
1691
|
export const syncIOS = async () => {
|
|
1378
1692
|
if (Platform.OS !== 'ios') {
|
|
@@ -1397,6 +1711,8 @@ export const syncIOS = async () => {
|
|
|
1397
1711
|
* Present the code redemption sheet for offer codes (iOS only)
|
|
1398
1712
|
* @returns Promise<boolean> - Indicates whether the redemption sheet was presented
|
|
1399
1713
|
* @platform iOS
|
|
1714
|
+
*
|
|
1715
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios}
|
|
1400
1716
|
*/
|
|
1401
1717
|
export const presentCodeRedemptionSheetIOS = async () => {
|
|
1402
1718
|
if (Platform.OS !== 'ios') {
|
|
@@ -1436,6 +1752,8 @@ export const presentCodeRedemptionSheetIOS = async () => {
|
|
|
1436
1752
|
*
|
|
1437
1753
|
* @returns Promise<boolean> - true when the request triggers successfully
|
|
1438
1754
|
* @platform iOS
|
|
1755
|
+
*
|
|
1756
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios}
|
|
1439
1757
|
*/
|
|
1440
1758
|
export const requestPurchaseOnPromotedProductIOS = async () => {
|
|
1441
1759
|
if (Platform.OS !== 'ios') {
|
|
@@ -1469,6 +1787,8 @@ export const requestPurchaseOnPromotedProductIOS = async () => {
|
|
|
1469
1787
|
* Clear unfinished transactions on iOS
|
|
1470
1788
|
* @returns Promise<boolean>
|
|
1471
1789
|
* @platform iOS
|
|
1790
|
+
*
|
|
1791
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/clear-transaction-ios}
|
|
1472
1792
|
*/
|
|
1473
1793
|
export const clearTransactionIOS = async () => {
|
|
1474
1794
|
if (Platform.OS !== 'ios') {
|
|
@@ -1494,6 +1814,8 @@ export const clearTransactionIOS = async () => {
|
|
|
1494
1814
|
* @param sku - The product SKU to refund
|
|
1495
1815
|
* @returns Promise<string | null> - The refund status or null if not available
|
|
1496
1816
|
* @platform iOS
|
|
1817
|
+
*
|
|
1818
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios}
|
|
1497
1819
|
*/
|
|
1498
1820
|
export const beginRefundRequestIOS = async sku => {
|
|
1499
1821
|
if (Platform.OS !== 'ios') {
|
|
@@ -1514,72 +1836,11 @@ export const beginRefundRequestIOS = async sku => {
|
|
|
1514
1836
|
}
|
|
1515
1837
|
};
|
|
1516
1838
|
|
|
1517
|
-
/**
|
|
1518
|
-
* Get subscription status for a product (iOS only)
|
|
1519
|
-
* @param sku - The product SKU
|
|
1520
|
-
* @returns Promise<SubscriptionStatusIOS[]> - Array of subscription status objects
|
|
1521
|
-
* @throws Error when called on non-iOS platforms or when IAP is not initialized
|
|
1522
|
-
* @platform iOS
|
|
1523
|
-
*/
|
|
1524
|
-
/**
|
|
1525
|
-
* Get current entitlement for a product (iOS only)
|
|
1526
|
-
* @param sku - The product SKU
|
|
1527
|
-
* @returns Promise<Purchase | null> - Current entitlement or null
|
|
1528
|
-
* @platform iOS
|
|
1529
|
-
*/
|
|
1530
|
-
/**
|
|
1531
|
-
* Get latest transaction for a product (iOS only)
|
|
1532
|
-
* @param sku - The product SKU
|
|
1533
|
-
* @returns Promise<Purchase | null> - Latest transaction or null
|
|
1534
|
-
* @platform iOS
|
|
1535
|
-
*/
|
|
1536
|
-
/**
|
|
1537
|
-
* Get pending transactions (iOS only)
|
|
1538
|
-
* @returns Promise<Purchase[]> - Array of pending transactions
|
|
1539
|
-
* @platform iOS
|
|
1540
|
-
*/
|
|
1541
|
-
/**
|
|
1542
|
-
* Show manage subscriptions screen (iOS only)
|
|
1543
|
-
* @returns Promise<Purchase[]> - Subscriptions where auto-renewal status changed
|
|
1544
|
-
* @platform iOS
|
|
1545
|
-
*/
|
|
1546
|
-
/**
|
|
1547
|
-
* Check if user is eligible for intro offer (iOS only)
|
|
1548
|
-
* @param groupID - The subscription group ID
|
|
1549
|
-
* @returns Promise<boolean> - Eligibility status
|
|
1550
|
-
* @platform iOS
|
|
1551
|
-
*/
|
|
1552
|
-
/**
|
|
1553
|
-
* Get receipt data (iOS only)
|
|
1554
|
-
* @returns Promise<string> - Base64 encoded receipt data
|
|
1555
|
-
* @platform iOS
|
|
1556
|
-
*/
|
|
1557
|
-
/**
|
|
1558
|
-
* Check if transaction is verified (iOS only)
|
|
1559
|
-
* @param sku - The product SKU
|
|
1560
|
-
* @returns Promise<boolean> - Verification status
|
|
1561
|
-
* @platform iOS
|
|
1562
|
-
*/
|
|
1563
|
-
/**
|
|
1564
|
-
* Get transaction JWS representation (iOS only)
|
|
1565
|
-
* @param sku - The product SKU
|
|
1566
|
-
* @returns Promise<string | null> - JWS representation or null
|
|
1567
|
-
* @platform iOS
|
|
1568
|
-
*/
|
|
1569
|
-
/**
|
|
1570
|
-
* Get the storefront identifier for the user's App Store account (iOS only)
|
|
1571
|
-
* @returns Promise<string> - The storefront identifier (e.g., 'USA' for United States)
|
|
1572
|
-
* @platform iOS
|
|
1573
|
-
*
|
|
1574
|
-
* @example
|
|
1575
|
-
* ```typescript
|
|
1576
|
-
* const storefront = await getStorefrontIOS();
|
|
1577
|
-
* console.log('User storefront:', storefront); // e.g., 'USA', 'GBR', 'KOR'
|
|
1578
|
-
* ```
|
|
1579
|
-
*/
|
|
1580
1839
|
/**
|
|
1581
1840
|
* Deeplinks to native interface that allows users to manage their subscriptions
|
|
1582
1841
|
* Cross-platform alias aligning with expo-iap
|
|
1842
|
+
*
|
|
1843
|
+
* @see {@link https://www.openiap.dev/docs/apis/deep-link-to-subscriptions}
|
|
1583
1844
|
*/
|
|
1584
1845
|
export const deepLinkToSubscriptions = async options => {
|
|
1585
1846
|
const resolvedOptions = options ?? undefined;
|
|
@@ -1624,25 +1885,6 @@ export const deepLinkToSubscriptionsIOS = async () => {
|
|
|
1624
1885
|
}
|
|
1625
1886
|
};
|
|
1626
1887
|
|
|
1627
|
-
/**
|
|
1628
|
-
* iOS only - Gets the original app transaction ID if the app was purchased from the App Store
|
|
1629
|
-
* @platform iOS
|
|
1630
|
-
* @description
|
|
1631
|
-
* This function retrieves the original app transaction information if the app was purchased
|
|
1632
|
-
* from the App Store. Returns null if the app was not purchased (e.g., free app or TestFlight).
|
|
1633
|
-
*
|
|
1634
|
-
* @returns {Promise<string | null>} The original app transaction ID or null
|
|
1635
|
-
*
|
|
1636
|
-
* @example
|
|
1637
|
-
* ```typescript
|
|
1638
|
-
* const appTransaction = await getAppTransactionIOS();
|
|
1639
|
-
* if (appTransaction) {
|
|
1640
|
-
* console.log('App was purchased, transaction ID:', appTransaction);
|
|
1641
|
-
* } else {
|
|
1642
|
-
* console.log('App was not purchased from App Store');
|
|
1643
|
-
* }
|
|
1644
|
-
* ```
|
|
1645
|
-
*/
|
|
1646
1888
|
/**
|
|
1647
1889
|
* Get all active subscriptions with detailed information (OpenIAP compliant)
|
|
1648
1890
|
* Returns an array of active subscriptions. If subscriptionIds is not provided,
|
|
@@ -1655,6 +1897,8 @@ export const deepLinkToSubscriptionsIOS = async () => {
|
|
|
1655
1897
|
*
|
|
1656
1898
|
* @param subscriptionIds - Optional array of subscription IDs to filter by
|
|
1657
1899
|
* @returns Promise<ActiveSubscription[]> - Array of active subscriptions
|
|
1900
|
+
*
|
|
1901
|
+
* @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}
|
|
1658
1902
|
*/
|
|
1659
1903
|
export const getActiveSubscriptions = async subscriptionIds => {
|
|
1660
1904
|
try {
|
|
@@ -1801,6 +2045,8 @@ export const getActiveSubscriptions_OLD: QueryField<
|
|
|
1801
2045
|
*
|
|
1802
2046
|
* @param subscriptionIds - Optional array of subscription IDs to check
|
|
1803
2047
|
* @returns Promise<boolean> - True if there are active subscriptions
|
|
2048
|
+
*
|
|
2049
|
+
* @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}
|
|
1804
2050
|
*/
|
|
1805
2051
|
export const hasActiveSubscriptions = async subscriptionIds => {
|
|
1806
2052
|
try {
|
|
@@ -1903,6 +2149,8 @@ const normalizeProductQueryType = type => {
|
|
|
1903
2149
|
* // Proceed with alternative billing flow
|
|
1904
2150
|
* }
|
|
1905
2151
|
* ```
|
|
2152
|
+
*
|
|
2153
|
+
* @see {@link https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android}
|
|
1906
2154
|
*/
|
|
1907
2155
|
export const checkAlternativeBillingAvailabilityAndroid = async () => {
|
|
1908
2156
|
if (Platform.OS !== 'android') {
|
|
@@ -1938,6 +2186,8 @@ export const checkAlternativeBillingAvailabilityAndroid = async () => {
|
|
|
1938
2186
|
* }
|
|
1939
2187
|
* }
|
|
1940
2188
|
* ```
|
|
2189
|
+
*
|
|
2190
|
+
* @see {@link https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android}
|
|
1941
2191
|
*/
|
|
1942
2192
|
export const showAlternativeBillingDialogAndroid = async () => {
|
|
1943
2193
|
if (Platform.OS !== 'android') {
|
|
@@ -1973,6 +2223,8 @@ export const showAlternativeBillingDialogAndroid = async () => {
|
|
|
1973
2223
|
* });
|
|
1974
2224
|
* }
|
|
1975
2225
|
* ```
|
|
2226
|
+
*
|
|
2227
|
+
* @see {@link https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android}
|
|
1976
2228
|
*/
|
|
1977
2229
|
export const createAlternativeBillingTokenAndroid = async sku => {
|
|
1978
2230
|
if (Platform.OS !== 'android') {
|
|
@@ -2040,6 +2292,8 @@ export const enableBillingProgramAndroid = program => {
|
|
|
2040
2292
|
* // External offers are available for this user
|
|
2041
2293
|
* }
|
|
2042
2294
|
* ```
|
|
2295
|
+
*
|
|
2296
|
+
* @see {@link https://www.openiap.dev/docs/apis/android/is-billing-program-available-android}
|
|
2043
2297
|
*/
|
|
2044
2298
|
export const isBillingProgramAvailableAndroid = async program => {
|
|
2045
2299
|
if (Platform.OS !== 'android') {
|
|
@@ -2075,6 +2329,8 @@ export const isBillingProgramAvailableAndroid = async program => {
|
|
|
2075
2329
|
* body: JSON.stringify({ token: details.externalTransactionToken })
|
|
2076
2330
|
* });
|
|
2077
2331
|
* ```
|
|
2332
|
+
*
|
|
2333
|
+
* @see {@link https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android}
|
|
2078
2334
|
*/
|
|
2079
2335
|
export const createBillingProgramReportingDetailsAndroid = async program => {
|
|
2080
2336
|
if (Platform.OS !== 'android') {
|
|
@@ -2112,6 +2368,8 @@ export const createBillingProgramReportingDetailsAndroid = async program => {
|
|
|
2112
2368
|
* console.log('User accepted external link');
|
|
2113
2369
|
* }
|
|
2114
2370
|
* ```
|
|
2371
|
+
*
|
|
2372
|
+
* @see {@link https://www.openiap.dev/docs/apis/android/launch-external-link-android}
|
|
2115
2373
|
*/
|
|
2116
2374
|
export const launchExternalLinkAndroid = async params => {
|
|
2117
2375
|
if (Platform.OS !== 'android') {
|
|
@@ -2135,7 +2393,11 @@ export const launchExternalLinkAndroid = async params => {
|
|
|
2135
2393
|
// ------------------------------
|
|
2136
2394
|
|
|
2137
2395
|
/**
|
|
2138
|
-
* Check if the device can present an external purchase notice sheet (iOS
|
|
2396
|
+
* Check if the device can present an external purchase notice sheet (iOS 17.4+).
|
|
2397
|
+
*
|
|
2398
|
+
* Wraps `ExternalPurchase.canPresent`, which Apple introduced in iOS 17.4.
|
|
2399
|
+
* Note: the notice sheet itself (`presentExternalPurchaseNoticeSheetIOS`)
|
|
2400
|
+
* still requires iOS 18.2+; only the eligibility check is available earlier.
|
|
2139
2401
|
*
|
|
2140
2402
|
* @returns Promise<boolean> - true if notice sheet can be presented
|
|
2141
2403
|
* @platform iOS
|
|
@@ -2148,6 +2410,8 @@ export const launchExternalLinkAndroid = async params => {
|
|
|
2148
2410
|
* const result = await presentExternalPurchaseNoticeSheetIOS();
|
|
2149
2411
|
* }
|
|
2150
2412
|
* ```
|
|
2413
|
+
*
|
|
2414
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios}
|
|
2151
2415
|
*/
|
|
2152
2416
|
export const canPresentExternalPurchaseNoticeIOS = async () => {
|
|
2153
2417
|
if (Platform.OS !== 'ios') {
|
|
@@ -2176,6 +2440,8 @@ export const canPresentExternalPurchaseNoticeIOS = async () => {
|
|
|
2176
2440
|
* await presentExternalPurchaseLinkIOS('https://your-website.com/purchase');
|
|
2177
2441
|
* }
|
|
2178
2442
|
* ```
|
|
2443
|
+
*
|
|
2444
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios}
|
|
2179
2445
|
*/
|
|
2180
2446
|
export const presentExternalPurchaseNoticeSheetIOS = async () => {
|
|
2181
2447
|
if (Platform.OS !== 'ios') {
|
|
@@ -2203,6 +2469,8 @@ export const presentExternalPurchaseNoticeSheetIOS = async () => {
|
|
|
2203
2469
|
* console.log('User completed external purchase');
|
|
2204
2470
|
* }
|
|
2205
2471
|
* ```
|
|
2472
|
+
*
|
|
2473
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios}
|
|
2206
2474
|
*/
|
|
2207
2475
|
export const presentExternalPurchaseLinkIOS = async url => {
|
|
2208
2476
|
if (Platform.OS !== 'ios') {
|
|
@@ -2235,6 +2503,8 @@ export const presentExternalPurchaseLinkIOS = async url => {
|
|
|
2235
2503
|
* // App can use custom external purchase links
|
|
2236
2504
|
* }
|
|
2237
2505
|
* ```
|
|
2506
|
+
*
|
|
2507
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios}
|
|
2238
2508
|
*/
|
|
2239
2509
|
export const isEligibleForExternalPurchaseCustomLinkIOS = async () => {
|
|
2240
2510
|
if (Platform.OS !== 'ios') {
|
|
@@ -2266,6 +2536,8 @@ export const isEligibleForExternalPurchaseCustomLinkIOS = async () => {
|
|
|
2266
2536
|
* await reportToApple(result.token);
|
|
2267
2537
|
* }
|
|
2268
2538
|
* ```
|
|
2539
|
+
*
|
|
2540
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios}
|
|
2269
2541
|
*/
|
|
2270
2542
|
export const getExternalPurchaseCustomLinkTokenIOS = async tokenType => {
|
|
2271
2543
|
if (Platform.OS !== 'ios') {
|
|
@@ -2297,6 +2569,8 @@ export const getExternalPurchaseCustomLinkTokenIOS = async tokenType => {
|
|
|
2297
2569
|
* await Linking.openURL('https://your-store.com/checkout');
|
|
2298
2570
|
* }
|
|
2299
2571
|
* ```
|
|
2572
|
+
*
|
|
2573
|
+
* @see {@link https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios}
|
|
2300
2574
|
*/
|
|
2301
2575
|
export const showExternalPurchaseCustomLinkNoticeIOS = async noticeType => {
|
|
2302
2576
|
if (Platform.OS !== 'ios') {
|