react-native-iap 15.2.4 → 15.3.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/README.md +29 -49
- package/android/build.gradle +92 -22
- package/android/gradle.properties +5 -1
- package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +1 -1
- package/android/src/main/java/com/margelo/nitro/iap/RnIapLog.kt +3 -1
- package/ios/HybridRnIap.swift +12 -6
- package/lib/module/index.js +73 -158
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/hooks/useIAP.d.ts +15 -15
- package/lib/typescript/src/index.d.ts +59 -88
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/RnIap.nitro.d.ts +2 -15
- package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +47 -47
- package/nitro.json +0 -1
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +7 -7
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +1 -1
- package/nitrogen/generated/android/c++/{JNitroPurchaseUpdatedListenerOptions.hpp → JPurchaseUpdatedListenerOptions.hpp} +10 -10
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/{NitroPurchaseUpdatedListenerOptions.kt → PurchaseUpdatedListenerOptions.kt} +5 -5
- package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.hpp +10 -10
- package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +3 -3
- package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +4 -4
- package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +1 -1
- package/nitrogen/generated/ios/swift/{NitroPurchaseUpdatedListenerOptions.swift → PurchaseUpdatedListenerOptions.swift} +5 -5
- package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +4 -4
- package/nitrogen/generated/shared/c++/{NitroPurchaseUpdatedListenerOptions.hpp → PurchaseUpdatedListenerOptions.hpp} +11 -11
- package/openiap-versions.json +2 -2
- package/package.json +4 -6
- package/src/hooks/useIAP.ts +15 -15
- package/src/index.ts +93 -204
- package/src/specs/RnIap.nitro.ts +2 -15
- package/src/types.ts +47 -47
package/lib/module/index.js
CHANGED
|
@@ -28,13 +28,14 @@ import { parseAppTransactionPayload } from "./utils.js";
|
|
|
28
28
|
|
|
29
29
|
export * from "./types.js";
|
|
30
30
|
export * from "./utils/error.js";
|
|
31
|
-
const LEGACY_INAPP_WARNING = "[react-native-iap] `type: 'inapp'` is deprecated and will be removed in
|
|
31
|
+
const LEGACY_INAPP_WARNING = "[react-native-iap] `type: 'inapp'` is deprecated and will be removed in a future major version. Use 'in-app' instead.";
|
|
32
32
|
const toErrorMessage = error => {
|
|
33
33
|
if (typeof error === 'object' && error !== null && 'message' in error && error.message != null) {
|
|
34
34
|
return String(error.message);
|
|
35
35
|
}
|
|
36
36
|
return String(error ?? '');
|
|
37
37
|
};
|
|
38
|
+
const unsupportedPlatformError = () => new Error(`Unsupported platform: ${Platform.OS}`);
|
|
38
39
|
// ActiveSubscription and PurchaseError types are already exported via 'export * from ./types'
|
|
39
40
|
|
|
40
41
|
// Export hooks
|
|
@@ -330,7 +331,7 @@ export const promotedProductListenerIOS = listener => {
|
|
|
330
331
|
* const subscription = userChoiceBillingListenerAndroid((details) => {
|
|
331
332
|
* console.log('User chose alternative billing');
|
|
332
333
|
* console.log('Products:', details.products);
|
|
333
|
-
* console.log('
|
|
334
|
+
* console.log('External transaction token received; send it to your backend without logging it.');
|
|
334
335
|
*
|
|
335
336
|
* // Send token to backend for Google Play reporting
|
|
336
337
|
* await reportToGooglePlay(details.externalTransactionToken);
|
|
@@ -397,7 +398,7 @@ export const userChoiceBillingListenerAndroid = listener => {
|
|
|
397
398
|
* ```typescript
|
|
398
399
|
* const subscription = developerProvidedBillingListenerAndroid((details) => {
|
|
399
400
|
* console.log('User chose developer billing');
|
|
400
|
-
* console.log('
|
|
401
|
+
* console.log('External transaction token received; send it to your backend without logging it.');
|
|
401
402
|
*
|
|
402
403
|
* // Process payment through your external payment system
|
|
403
404
|
* await processExternalPayment();
|
|
@@ -548,7 +549,7 @@ export const subscriptionBillingIssueListener = listener => {
|
|
|
548
549
|
* @remarks This is a regular promise-based call. Don't confuse with `request*` APIs
|
|
549
550
|
* (`requestPurchase`), which are event-based.
|
|
550
551
|
*
|
|
551
|
-
* @see {@link https://
|
|
552
|
+
* @see {@link https://openiap.dev/docs/apis/fetch-products}
|
|
552
553
|
*/
|
|
553
554
|
export const fetchProducts = async request => {
|
|
554
555
|
const {
|
|
@@ -655,7 +656,7 @@ export const fetchProducts = async request => {
|
|
|
655
656
|
* }
|
|
656
657
|
* ```
|
|
657
658
|
*
|
|
658
|
-
* @see {@link https://
|
|
659
|
+
* @see {@link https://openiap.dev/docs/apis/get-available-purchases}
|
|
659
660
|
*/
|
|
660
661
|
export const getAvailablePurchases = async options => {
|
|
661
662
|
const alsoPublishToEventListenerIOS = Boolean(options?.alsoPublishToEventListenerIOS ?? false);
|
|
@@ -700,7 +701,7 @@ export const getAvailablePurchases = async options => {
|
|
|
700
701
|
}
|
|
701
702
|
return validPurchases.map(convertNitroPurchaseToPurchase);
|
|
702
703
|
} else {
|
|
703
|
-
throw
|
|
704
|
+
throw unsupportedPlatformError();
|
|
704
705
|
}
|
|
705
706
|
} catch (error) {
|
|
706
707
|
RnIapConsole.error('Failed to get available purchases:', error);
|
|
@@ -713,7 +714,7 @@ export const getAvailablePurchases = async options => {
|
|
|
713
714
|
* @returns Promise<Product | null> - The promoted product or null if none available
|
|
714
715
|
* @platform iOS
|
|
715
716
|
*
|
|
716
|
-
* @see {@link https://
|
|
717
|
+
* @see {@link https://openiap.dev/docs/apis/ios/get-promoted-product-ios}
|
|
717
718
|
*/
|
|
718
719
|
export const getPromotedProductIOS = async () => {
|
|
719
720
|
if (Platform.OS !== 'ios') {
|
|
@@ -750,7 +751,7 @@ export const requestPromotedProductIOS = getPromotedProductIOS;
|
|
|
750
751
|
* console.log('User storefront:', storefront); // e.g., 'USA', 'GBR', 'KOR'
|
|
751
752
|
* ```
|
|
752
753
|
*
|
|
753
|
-
* @see {@link https://
|
|
754
|
+
* @see {@link https://openiap.dev/docs/apis/ios/get-storefront-ios}
|
|
754
755
|
*/
|
|
755
756
|
export const getStorefrontIOS = async () => {
|
|
756
757
|
if (Platform.OS !== 'ios') {
|
|
@@ -768,7 +769,7 @@ export const getStorefrontIOS = async () => {
|
|
|
768
769
|
/**
|
|
769
770
|
* Return the user's storefront country code.
|
|
770
771
|
*
|
|
771
|
-
* @see {@link https://
|
|
772
|
+
* @see {@link https://openiap.dev/docs/apis/get-storefront}
|
|
772
773
|
*/
|
|
773
774
|
export const getStorefront = async () => {
|
|
774
775
|
if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
|
|
@@ -811,7 +812,7 @@ export const getStorefront = async () => {
|
|
|
811
812
|
* }
|
|
812
813
|
* ```
|
|
813
814
|
*
|
|
814
|
-
* @see {@link https://
|
|
815
|
+
* @see {@link https://openiap.dev/docs/apis/ios/get-app-transaction-ios}
|
|
815
816
|
*/
|
|
816
817
|
export const getAppTransactionIOS = async () => {
|
|
817
818
|
if (Platform.OS !== 'ios') {
|
|
@@ -846,7 +847,7 @@ export const getAppTransactionIOS = async () => {
|
|
|
846
847
|
* @throws Error when called on non-iOS platforms or when IAP is not initialized
|
|
847
848
|
* @platform iOS
|
|
848
849
|
*
|
|
849
|
-
* @see {@link https://
|
|
850
|
+
* @see {@link https://openiap.dev/docs/apis/ios/subscription-status-ios}
|
|
850
851
|
*/
|
|
851
852
|
export const subscriptionStatusIOS = async sku => {
|
|
852
853
|
if (Platform.OS !== 'ios') {
|
|
@@ -874,7 +875,7 @@ export const subscriptionStatusIOS = async sku => {
|
|
|
874
875
|
* @returns Promise<Purchase | null> - Current entitlement or null
|
|
875
876
|
* @platform iOS
|
|
876
877
|
*
|
|
877
|
-
* @see {@link https://
|
|
878
|
+
* @see {@link https://openiap.dev/docs/apis/ios/current-entitlement-ios}
|
|
878
879
|
*/
|
|
879
880
|
export const currentEntitlementIOS = async sku => {
|
|
880
881
|
if (Platform.OS !== 'ios') {
|
|
@@ -905,7 +906,7 @@ export const currentEntitlementIOS = async sku => {
|
|
|
905
906
|
* @returns Promise<Purchase | null> - Latest transaction or null
|
|
906
907
|
* @platform iOS
|
|
907
908
|
*
|
|
908
|
-
* @see {@link https://
|
|
909
|
+
* @see {@link https://openiap.dev/docs/apis/ios/latest-transaction-ios}
|
|
909
910
|
*/
|
|
910
911
|
export const latestTransactionIOS = async sku => {
|
|
911
912
|
if (Platform.OS !== 'ios') {
|
|
@@ -935,7 +936,7 @@ export const latestTransactionIOS = async sku => {
|
|
|
935
936
|
* @returns Promise<Purchase[]> - Array of pending transactions
|
|
936
937
|
* @platform iOS
|
|
937
938
|
*
|
|
938
|
-
* @see {@link https://
|
|
939
|
+
* @see {@link https://openiap.dev/docs/apis/ios/get-pending-transactions-ios}
|
|
939
940
|
*/
|
|
940
941
|
export const getPendingTransactionsIOS = async () => {
|
|
941
942
|
if (Platform.OS !== 'ios') {
|
|
@@ -959,7 +960,7 @@ export const getPendingTransactionsIOS = async () => {
|
|
|
959
960
|
/**
|
|
960
961
|
* List every StoreKit transaction (finished + unfinished) for the current user.
|
|
961
962
|
*
|
|
962
|
-
* @see {@link https://
|
|
963
|
+
* @see {@link https://openiap.dev/docs/apis/ios/get-all-transactions-ios}
|
|
963
964
|
*/
|
|
964
965
|
export const getAllTransactionsIOS = async () => {
|
|
965
966
|
if (Platform.OS !== 'ios') {
|
|
@@ -985,7 +986,7 @@ export const getAllTransactionsIOS = async () => {
|
|
|
985
986
|
* @returns Promise<Purchase[]> - Subscriptions where auto-renewal status changed
|
|
986
987
|
* @platform iOS
|
|
987
988
|
*
|
|
988
|
-
* @see {@link https://
|
|
989
|
+
* @see {@link https://openiap.dev/docs/apis/ios/show-manage-subscriptions-ios}
|
|
989
990
|
*/
|
|
990
991
|
export const showManageSubscriptionsIOS = async () => {
|
|
991
992
|
if (Platform.OS !== 'ios') {
|
|
@@ -1012,7 +1013,7 @@ export const showManageSubscriptionsIOS = async () => {
|
|
|
1012
1013
|
* @returns Promise<boolean> - Eligibility status
|
|
1013
1014
|
* @platform iOS
|
|
1014
1015
|
*
|
|
1015
|
-
* @see {@link https://
|
|
1016
|
+
* @see {@link https://openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios}
|
|
1016
1017
|
*/
|
|
1017
1018
|
export const isEligibleForIntroOfferIOS = async groupID => {
|
|
1018
1019
|
if (Platform.OS !== 'ios') {
|
|
@@ -1037,7 +1038,7 @@ export const isEligibleForIntroOfferIOS = async groupID => {
|
|
|
1037
1038
|
* @returns Promise<string> - Base64 encoded receipt data
|
|
1038
1039
|
* @platform iOS
|
|
1039
1040
|
*
|
|
1040
|
-
* @see {@link https://
|
|
1041
|
+
* @see {@link https://openiap.dev/docs/apis/ios/get-receipt-data-ios}
|
|
1041
1042
|
*/
|
|
1042
1043
|
export const getReceiptDataIOS = async () => {
|
|
1043
1044
|
if (Platform.OS !== 'ios') {
|
|
@@ -1106,7 +1107,7 @@ export const requestReceiptRefreshIOS = async () => {
|
|
|
1106
1107
|
* @returns Promise<boolean> - Verification status
|
|
1107
1108
|
* @platform iOS
|
|
1108
1109
|
*
|
|
1109
|
-
* @see {@link https://
|
|
1110
|
+
* @see {@link https://openiap.dev/docs/apis/ios/is-transaction-verified-ios}
|
|
1110
1111
|
*/
|
|
1111
1112
|
export const isTransactionVerifiedIOS = async sku => {
|
|
1112
1113
|
if (Platform.OS !== 'ios') {
|
|
@@ -1132,7 +1133,7 @@ export const isTransactionVerifiedIOS = async sku => {
|
|
|
1132
1133
|
* @returns Promise<string | null> - JWS representation or null
|
|
1133
1134
|
* @platform iOS
|
|
1134
1135
|
*
|
|
1135
|
-
* @see {@link https://
|
|
1136
|
+
* @see {@link https://openiap.dev/docs/apis/ios/get-transaction-jws-ios}
|
|
1136
1137
|
*/
|
|
1137
1138
|
export const getTransactionJwsIOS = async sku => {
|
|
1138
1139
|
if (Platform.OS !== 'ios') {
|
|
@@ -1173,7 +1174,7 @@ export const getTransactionJwsIOS = async sku => {
|
|
|
1173
1174
|
* @remarks When using `useIAP()`, connection is auto-managed on mount/unmount —
|
|
1174
1175
|
* pass options to the hook instead of calling this directly.
|
|
1175
1176
|
*
|
|
1176
|
-
* @see {@link https://
|
|
1177
|
+
* @see {@link https://openiap.dev/docs/apis/init-connection}
|
|
1177
1178
|
*/
|
|
1178
1179
|
export const initConnection = async config => {
|
|
1179
1180
|
try {
|
|
@@ -1193,7 +1194,7 @@ export const initConnection = async config => {
|
|
|
1193
1194
|
/**
|
|
1194
1195
|
* Close the store connection and release resources.
|
|
1195
1196
|
*
|
|
1196
|
-
* @see {@link https://
|
|
1197
|
+
* @see {@link https://openiap.dev/docs/apis/end-connection}
|
|
1197
1198
|
*/
|
|
1198
1199
|
export const endConnection = async () => {
|
|
1199
1200
|
try {
|
|
@@ -1216,7 +1217,7 @@ export const endConnection = async () => {
|
|
|
1216
1217
|
/**
|
|
1217
1218
|
* Restore non-consumable and active subscription purchases.
|
|
1218
1219
|
*
|
|
1219
|
-
* @see {@link https://
|
|
1220
|
+
* @see {@link https://openiap.dev/docs/apis/restore-purchases}
|
|
1220
1221
|
*/
|
|
1221
1222
|
export const restorePurchases = async () => {
|
|
1222
1223
|
try {
|
|
@@ -1263,7 +1264,7 @@ export const restorePurchases = async () => {
|
|
|
1263
1264
|
* @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /
|
|
1264
1265
|
* {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.
|
|
1265
1266
|
*
|
|
1266
|
-
* @see {@link https://
|
|
1267
|
+
* @see {@link https://openiap.dev/docs/apis/request-purchase}
|
|
1267
1268
|
*/
|
|
1268
1269
|
export const requestPurchase = async request => {
|
|
1269
1270
|
try {
|
|
@@ -1290,7 +1291,7 @@ export const requestPurchase = async request => {
|
|
|
1290
1291
|
throw new Error('Invalid request for Android. The `skus` property is required and must be a non-empty array.');
|
|
1291
1292
|
}
|
|
1292
1293
|
} else {
|
|
1293
|
-
throw
|
|
1294
|
+
throw unsupportedPlatformError();
|
|
1294
1295
|
}
|
|
1295
1296
|
const unifiedRequest = {};
|
|
1296
1297
|
|
|
@@ -1317,6 +1318,18 @@ export const requestPurchase = async request => {
|
|
|
1317
1318
|
if (iosRequest.advancedCommerceData) {
|
|
1318
1319
|
iosPayload.advancedCommerceData = iosRequest.advancedCommerceData;
|
|
1319
1320
|
}
|
|
1321
|
+
if (isSubs) {
|
|
1322
|
+
const subscriptionRequest = iosRequest;
|
|
1323
|
+
if (subscriptionRequest.introductoryOfferEligibility !== undefined) {
|
|
1324
|
+
iosPayload.introductoryOfferEligibility = subscriptionRequest.introductoryOfferEligibility;
|
|
1325
|
+
}
|
|
1326
|
+
if (subscriptionRequest.promotionalOfferJWS) {
|
|
1327
|
+
iosPayload.promotionalOfferJWS = subscriptionRequest.promotionalOfferJWS;
|
|
1328
|
+
}
|
|
1329
|
+
if (subscriptionRequest.winBackOffer) {
|
|
1330
|
+
iosPayload.winBackOffer = subscriptionRequest.winBackOffer;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1320
1333
|
unifiedRequest.ios = iosPayload;
|
|
1321
1334
|
}
|
|
1322
1335
|
|
|
@@ -1398,7 +1411,7 @@ export const requestPurchase = async request => {
|
|
|
1398
1411
|
* @remarks **Critical:** Android purchases must be finalized within 3 days or Google
|
|
1399
1412
|
* auto-refunds. iOS unfinished transactions replay on every app launch.
|
|
1400
1413
|
*
|
|
1401
|
-
* @see {@link https://
|
|
1414
|
+
* @see {@link https://openiap.dev/docs/apis/finish-transaction}
|
|
1402
1415
|
*/
|
|
1403
1416
|
export const finishTransaction = async args => {
|
|
1404
1417
|
const {
|
|
@@ -1428,7 +1441,7 @@ export const finishTransaction = async args => {
|
|
|
1428
1441
|
}
|
|
1429
1442
|
};
|
|
1430
1443
|
} else {
|
|
1431
|
-
throw
|
|
1444
|
+
throw unsupportedPlatformError();
|
|
1432
1445
|
}
|
|
1433
1446
|
const result = await IAP.instance.finishTransaction(params);
|
|
1434
1447
|
const success = getSuccessFromPurchaseVariant(result, 'finishTransaction');
|
|
@@ -1462,7 +1475,7 @@ export const finishTransaction = async args => {
|
|
|
1462
1475
|
* await acknowledgePurchaseAndroid('purchase_token_here');
|
|
1463
1476
|
* ```
|
|
1464
1477
|
*
|
|
1465
|
-
* @see {@link https://
|
|
1478
|
+
* @see {@link https://openiap.dev/docs/apis/android/acknowledge-purchase-android}
|
|
1466
1479
|
*/
|
|
1467
1480
|
export const acknowledgePurchaseAndroid = async purchaseToken => {
|
|
1468
1481
|
try {
|
|
@@ -1498,7 +1511,7 @@ export const acknowledgePurchaseAndroid = async purchaseToken => {
|
|
|
1498
1511
|
* await consumePurchaseAndroid('purchase_token_here');
|
|
1499
1512
|
* ```
|
|
1500
1513
|
*
|
|
1501
|
-
* @see {@link https://
|
|
1514
|
+
* @see {@link https://openiap.dev/docs/apis/android/consume-purchase-android}
|
|
1502
1515
|
*/
|
|
1503
1516
|
export const consumePurchaseAndroid = async purchaseToken => {
|
|
1504
1517
|
try {
|
|
@@ -1552,7 +1565,7 @@ export const consumePurchaseAndroid = async purchaseToken => {
|
|
|
1552
1565
|
* });
|
|
1553
1566
|
* ```
|
|
1554
1567
|
*
|
|
1555
|
-
* @see {@link https://
|
|
1568
|
+
* @see {@link https://openiap.dev/docs/apis/validate-receipt}
|
|
1556
1569
|
*/
|
|
1557
1570
|
export const validateReceipt = async options => {
|
|
1558
1571
|
const {
|
|
@@ -1661,7 +1674,7 @@ export const validateReceipt = async options => {
|
|
|
1661
1674
|
* @param options - Receipt validation options containing the SKU
|
|
1662
1675
|
* @returns Promise resolving to receipt validation result
|
|
1663
1676
|
*
|
|
1664
|
-
* @see {@link https://
|
|
1677
|
+
* @see {@link https://openiap.dev/docs/features/validation#verify-purchase}
|
|
1665
1678
|
*/
|
|
1666
1679
|
export const verifyPurchase = validateReceipt;
|
|
1667
1680
|
|
|
@@ -1672,7 +1685,7 @@ export const verifyPurchase = validateReceipt;
|
|
|
1672
1685
|
* consumers who imported `validateReceiptIOS` — which is still declared on the
|
|
1673
1686
|
* OpenIAP Query interface — keep working. Throws on non-iOS platforms.
|
|
1674
1687
|
*
|
|
1675
|
-
* @see {@link https://
|
|
1688
|
+
* @see {@link https://openiap.dev/docs/apis/ios/validate-receipt-ios}
|
|
1676
1689
|
*/
|
|
1677
1690
|
export const validateReceiptIOS = async options => {
|
|
1678
1691
|
if (Platform.OS !== 'ios') {
|
|
@@ -1703,7 +1716,7 @@ export const validateReceiptIOS = async options => {
|
|
|
1703
1716
|
* });
|
|
1704
1717
|
* ```
|
|
1705
1718
|
*
|
|
1706
|
-
* @see {@link https://
|
|
1719
|
+
* @see {@link https://openiap.dev/docs/features/validation#verify-purchase-with-provider}
|
|
1707
1720
|
*/
|
|
1708
1721
|
export const verifyPurchaseWithProvider = async options => {
|
|
1709
1722
|
try {
|
|
@@ -1744,7 +1757,7 @@ export const verifyPurchaseWithProvider = async options => {
|
|
|
1744
1757
|
* @returns Promise<boolean>
|
|
1745
1758
|
* @platform iOS
|
|
1746
1759
|
*
|
|
1747
|
-
* @see {@link https://
|
|
1760
|
+
* @see {@link https://openiap.dev/docs/apis/ios/sync-ios}
|
|
1748
1761
|
*/
|
|
1749
1762
|
export const syncIOS = async () => {
|
|
1750
1763
|
if (Platform.OS !== 'ios') {
|
|
@@ -1770,7 +1783,7 @@ export const syncIOS = async () => {
|
|
|
1770
1783
|
* @returns Promise<boolean> - Indicates whether the redemption sheet was presented
|
|
1771
1784
|
* @platform iOS
|
|
1772
1785
|
*
|
|
1773
|
-
* @see {@link https://
|
|
1786
|
+
* @see {@link https://openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios}
|
|
1774
1787
|
*/
|
|
1775
1788
|
export const presentCodeRedemptionSheetIOS = async () => {
|
|
1776
1789
|
if (Platform.OS !== 'ios') {
|
|
@@ -1811,7 +1824,7 @@ export const presentCodeRedemptionSheetIOS = async () => {
|
|
|
1811
1824
|
* @returns Promise<boolean> - true when the request triggers successfully
|
|
1812
1825
|
* @platform iOS
|
|
1813
1826
|
*
|
|
1814
|
-
* @see {@link https://
|
|
1827
|
+
* @see {@link https://openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios}
|
|
1815
1828
|
*/
|
|
1816
1829
|
export const requestPurchaseOnPromotedProductIOS = async () => {
|
|
1817
1830
|
if (Platform.OS !== 'ios') {
|
|
@@ -1846,7 +1859,7 @@ export const requestPurchaseOnPromotedProductIOS = async () => {
|
|
|
1846
1859
|
* @returns Promise<boolean>
|
|
1847
1860
|
* @platform iOS
|
|
1848
1861
|
*
|
|
1849
|
-
* @see {@link https://
|
|
1862
|
+
* @see {@link https://openiap.dev/docs/apis/ios/clear-transaction-ios}
|
|
1850
1863
|
*/
|
|
1851
1864
|
export const clearTransactionIOS = async () => {
|
|
1852
1865
|
if (Platform.OS !== 'ios') {
|
|
@@ -1873,7 +1886,7 @@ export const clearTransactionIOS = async () => {
|
|
|
1873
1886
|
* @returns Promise<string | null> - The refund status or null if not available
|
|
1874
1887
|
* @platform iOS
|
|
1875
1888
|
*
|
|
1876
|
-
* @see {@link https://
|
|
1889
|
+
* @see {@link https://openiap.dev/docs/apis/ios/begin-refund-request-ios}
|
|
1877
1890
|
*/
|
|
1878
1891
|
export const beginRefundRequestIOS = async sku => {
|
|
1879
1892
|
if (Platform.OS !== 'ios') {
|
|
@@ -1898,7 +1911,7 @@ export const beginRefundRequestIOS = async sku => {
|
|
|
1898
1911
|
* Deeplinks to native interface that allows users to manage their subscriptions
|
|
1899
1912
|
* Cross-platform alias aligning with expo-iap
|
|
1900
1913
|
*
|
|
1901
|
-
* @see {@link https://
|
|
1914
|
+
* @see {@link https://openiap.dev/docs/apis/deep-link-to-subscriptions}
|
|
1902
1915
|
*/
|
|
1903
1916
|
export const deepLinkToSubscriptions = async options => {
|
|
1904
1917
|
const resolvedOptions = options ?? undefined;
|
|
@@ -1910,16 +1923,14 @@ export const deepLinkToSubscriptions = async options => {
|
|
|
1910
1923
|
return;
|
|
1911
1924
|
}
|
|
1912
1925
|
if (Platform.OS === 'ios') {
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
await IAP.instance.showManageSubscriptionsIOS();
|
|
1918
|
-
}
|
|
1919
|
-
} catch (error) {
|
|
1920
|
-
RnIapConsole.warn('[deepLinkToSubscriptions] Failed on iOS:', error);
|
|
1926
|
+
if (typeof IAP.instance.deepLinkToSubscriptionsIOS === 'function') {
|
|
1927
|
+
await IAP.instance.deepLinkToSubscriptionsIOS();
|
|
1928
|
+
} else {
|
|
1929
|
+
await IAP.instance.showManageSubscriptionsIOS();
|
|
1921
1930
|
}
|
|
1931
|
+
return;
|
|
1922
1932
|
}
|
|
1933
|
+
throw unsupportedPlatformError();
|
|
1923
1934
|
};
|
|
1924
1935
|
export const deepLinkToSubscriptionsIOS = async () => {
|
|
1925
1936
|
if (Platform.OS !== 'ios') {
|
|
@@ -1956,7 +1967,7 @@ export const deepLinkToSubscriptionsIOS = async () => {
|
|
|
1956
1967
|
* @param subscriptionIds - Optional array of subscription IDs to filter by
|
|
1957
1968
|
* @returns Promise<ActiveSubscription[]> - Array of active subscriptions
|
|
1958
1969
|
*
|
|
1959
|
-
* @see {@link https://
|
|
1970
|
+
* @see {@link https://openiap.dev/docs/apis/get-active-subscriptions}
|
|
1960
1971
|
*/
|
|
1961
1972
|
export const getActiveSubscriptions = async subscriptionIds => {
|
|
1962
1973
|
try {
|
|
@@ -1977,7 +1988,7 @@ export const getActiveSubscriptions = async subscriptionIds => {
|
|
|
1977
1988
|
environmentIOS: sub.environmentIOS ?? null,
|
|
1978
1989
|
willExpireSoon: sub.willExpireSoon ?? null,
|
|
1979
1990
|
daysUntilExpirationIOS: sub.daysUntilExpirationIOS ?? null,
|
|
1980
|
-
//
|
|
1991
|
+
// renewalInfoIOS contains subscription lifecycle information on iOS.
|
|
1981
1992
|
renewalInfoIOS: sub.renewalInfoIOS ? {
|
|
1982
1993
|
willAutoRenew: sub.renewalInfoIOS.willAutoRenew ?? false,
|
|
1983
1994
|
autoRenewPreference: sub.renewalInfoIOS.autoRenewPreference ?? null,
|
|
@@ -2012,90 +2023,6 @@ export const getActiveSubscriptions = async subscriptionIds => {
|
|
|
2012
2023
|
}
|
|
2013
2024
|
};
|
|
2014
2025
|
|
|
2015
|
-
// OLD IMPLEMENTATION - REPLACED WITH NATIVE CALL
|
|
2016
|
-
/*
|
|
2017
|
-
export const getActiveSubscriptions_OLD: QueryField<
|
|
2018
|
-
'getActiveSubscriptions'
|
|
2019
|
-
> = async (subscriptionIds) => {
|
|
2020
|
-
try {
|
|
2021
|
-
// Get all available purchases first
|
|
2022
|
-
const allPurchases = await getAvailablePurchases();
|
|
2023
|
-
|
|
2024
|
-
// For the critical bug fix: this function was previously returning ALL purchases
|
|
2025
|
-
// Now we properly filter for subscriptions only
|
|
2026
|
-
|
|
2027
|
-
// In production with real data, Android subscription filtering is done via platform-specific calls
|
|
2028
|
-
// But for backward compatibility and test support, we also check platform-specific fields
|
|
2029
|
-
|
|
2030
|
-
// Since expirationDateIOS and subscriptionGroupIdIOS are not available in NitroPurchase,
|
|
2031
|
-
// we need to rely on other indicators or assume all purchases are subscriptions
|
|
2032
|
-
// when called from getActiveSubscriptions
|
|
2033
|
-
const purchases = allPurchases;
|
|
2034
|
-
|
|
2035
|
-
// Filter for subscriptions and map to ActiveSubscription format
|
|
2036
|
-
const subscriptions = purchases
|
|
2037
|
-
.filter((purchase) => {
|
|
2038
|
-
// Filter by subscription IDs if provided
|
|
2039
|
-
if (subscriptionIds && subscriptionIds.length > 0) {
|
|
2040
|
-
return subscriptionIds.includes(purchase.productId);
|
|
2041
|
-
}
|
|
2042
|
-
return true;
|
|
2043
|
-
})
|
|
2044
|
-
.map((purchase): ActiveSubscription => {
|
|
2045
|
-
// Safe access to platform-specific fields with type guards
|
|
2046
|
-
const expirationDateIOS =
|
|
2047
|
-
'expirationDateIOS' in purchase
|
|
2048
|
-
? ((purchase as PurchaseIOS).expirationDateIOS ?? null)
|
|
2049
|
-
: null;
|
|
2050
|
-
|
|
2051
|
-
const environmentIOS =
|
|
2052
|
-
'environmentIOS' in purchase
|
|
2053
|
-
? ((purchase as PurchaseIOS).environmentIOS ?? null)
|
|
2054
|
-
: null;
|
|
2055
|
-
|
|
2056
|
-
const autoRenewingAndroid =
|
|
2057
|
-
'autoRenewingAndroid' in purchase || 'isAutoRenewing' in purchase
|
|
2058
|
-
? ((purchase as PurchaseAndroid).autoRenewingAndroid ??
|
|
2059
|
-
(purchase as PurchaseAndroid).isAutoRenewing) // deprecated - use isAutoRenewing instead
|
|
2060
|
-
: null;
|
|
2061
|
-
|
|
2062
|
-
// 🆕 Extract renewalInfoIOS if available
|
|
2063
|
-
const renewalInfoIOS =
|
|
2064
|
-
'renewalInfoIOS' in purchase
|
|
2065
|
-
? ((purchase as PurchaseIOS).renewalInfoIOS ?? null)
|
|
2066
|
-
: null;
|
|
2067
|
-
|
|
2068
|
-
return {
|
|
2069
|
-
productId: purchase.productId,
|
|
2070
|
-
isActive: true, // If it's in availablePurchases, it's active
|
|
2071
|
-
// Backend validation fields - use transactionId ?? id for proper field mapping
|
|
2072
|
-
transactionId: purchase.transactionId ?? purchase.id,
|
|
2073
|
-
purchaseToken: purchase.purchaseToken,
|
|
2074
|
-
transactionDate: purchase.transactionDate,
|
|
2075
|
-
// Platform-specific fields
|
|
2076
|
-
expirationDateIOS,
|
|
2077
|
-
autoRenewingAndroid,
|
|
2078
|
-
environmentIOS,
|
|
2079
|
-
renewalInfoIOS,
|
|
2080
|
-
// Convenience fields
|
|
2081
|
-
willExpireSoon: false, // Would need to calculate based on expiration date
|
|
2082
|
-
daysUntilExpirationIOS:
|
|
2083
|
-
expirationDateIOS != null
|
|
2084
|
-
? Math.ceil(
|
|
2085
|
-
(expirationDateIOS - Date.now()) / (1000 * 60 * 60 * 24),
|
|
2086
|
-
)
|
|
2087
|
-
: null,
|
|
2088
|
-
};
|
|
2089
|
-
});
|
|
2090
|
-
|
|
2091
|
-
return subscriptions;
|
|
2092
|
-
} catch (error) {
|
|
2093
|
-
RnIapConsole.error('Failed to get active subscriptions:', error);
|
|
2094
|
-
const errorJson = parseErrorStringToJsonObj(error);
|
|
2095
|
-
throw new Error(errorJson.message);
|
|
2096
|
-
}
|
|
2097
|
-
};
|
|
2098
|
-
|
|
2099
2026
|
/**
|
|
2100
2027
|
* Check if the user has any active subscriptions (OpenIAP compliant)
|
|
2101
2028
|
* Returns true if the user has at least one active subscription, false otherwise.
|
|
@@ -2104,7 +2031,7 @@ export const getActiveSubscriptions_OLD: QueryField<
|
|
|
2104
2031
|
* @param subscriptionIds - Optional array of subscription IDs to check
|
|
2105
2032
|
* @returns Promise<boolean> - True if there are active subscriptions
|
|
2106
2033
|
*
|
|
2107
|
-
* @see {@link https://
|
|
2034
|
+
* @see {@link https://openiap.dev/docs/apis/has-active-subscriptions}
|
|
2108
2035
|
*/
|
|
2109
2036
|
export const hasActiveSubscriptions = async subscriptionIds => {
|
|
2110
2037
|
try {
|
|
@@ -2208,7 +2135,7 @@ const normalizeProductQueryType = type => {
|
|
|
2208
2135
|
* }
|
|
2209
2136
|
* ```
|
|
2210
2137
|
*
|
|
2211
|
-
* @see {@link https://
|
|
2138
|
+
* @see {@link https://openiap.dev/docs/apis/android/check-alternative-billing-availability-android}
|
|
2212
2139
|
*/
|
|
2213
2140
|
export const checkAlternativeBillingAvailabilityAndroid = async () => {
|
|
2214
2141
|
if (Platform.OS !== 'android') {
|
|
@@ -2245,7 +2172,7 @@ export const checkAlternativeBillingAvailabilityAndroid = async () => {
|
|
|
2245
2172
|
* }
|
|
2246
2173
|
* ```
|
|
2247
2174
|
*
|
|
2248
|
-
* @see {@link https://
|
|
2175
|
+
* @see {@link https://openiap.dev/docs/apis/android/show-alternative-billing-dialog-android}
|
|
2249
2176
|
*/
|
|
2250
2177
|
export const showAlternativeBillingDialogAndroid = async () => {
|
|
2251
2178
|
if (Platform.OS !== 'android') {
|
|
@@ -2282,7 +2209,7 @@ export const showAlternativeBillingDialogAndroid = async () => {
|
|
|
2282
2209
|
* }
|
|
2283
2210
|
* ```
|
|
2284
2211
|
*
|
|
2285
|
-
* @see {@link https://
|
|
2212
|
+
* @see {@link https://openiap.dev/docs/apis/android/create-alternative-billing-token-android}
|
|
2286
2213
|
*/
|
|
2287
2214
|
export const createAlternativeBillingTokenAndroid = async sku => {
|
|
2288
2215
|
if (Platform.OS !== 'android') {
|
|
@@ -2296,18 +2223,6 @@ export const createAlternativeBillingTokenAndroid = async sku => {
|
|
|
2296
2223
|
}
|
|
2297
2224
|
};
|
|
2298
2225
|
|
|
2299
|
-
/**
|
|
2300
|
-
* Parameters for launching an external link (Android 8.2.0+).
|
|
2301
|
-
*/
|
|
2302
|
-
|
|
2303
|
-
/**
|
|
2304
|
-
* Result of checking billing program availability (Android 8.2.0+).
|
|
2305
|
-
*/
|
|
2306
|
-
|
|
2307
|
-
/**
|
|
2308
|
-
* Reporting details for external transactions (Android 8.2.0+).
|
|
2309
|
-
*/
|
|
2310
|
-
|
|
2311
2226
|
/**
|
|
2312
2227
|
* Enable a billing program before initConnection (Android only).
|
|
2313
2228
|
* Must be called BEFORE initConnection() to configure the BillingClient.
|
|
@@ -2351,7 +2266,7 @@ export const enableBillingProgramAndroid = program => {
|
|
|
2351
2266
|
* }
|
|
2352
2267
|
* ```
|
|
2353
2268
|
*
|
|
2354
|
-
* @see {@link https://
|
|
2269
|
+
* @see {@link https://openiap.dev/docs/apis/android/is-billing-program-available-android}
|
|
2355
2270
|
*/
|
|
2356
2271
|
export const isBillingProgramAvailableAndroid = async program => {
|
|
2357
2272
|
if (Platform.OS !== 'android') {
|
|
@@ -2388,7 +2303,7 @@ export const isBillingProgramAvailableAndroid = async program => {
|
|
|
2388
2303
|
* });
|
|
2389
2304
|
* ```
|
|
2390
2305
|
*
|
|
2391
|
-
* @see {@link https://
|
|
2306
|
+
* @see {@link https://openiap.dev/docs/apis/android/create-billing-program-reporting-details-android}
|
|
2392
2307
|
*/
|
|
2393
2308
|
export const createBillingProgramReportingDetailsAndroid = async program => {
|
|
2394
2309
|
if (Platform.OS !== 'android') {
|
|
@@ -2427,7 +2342,7 @@ export const createBillingProgramReportingDetailsAndroid = async program => {
|
|
|
2427
2342
|
* }
|
|
2428
2343
|
* ```
|
|
2429
2344
|
*
|
|
2430
|
-
* @see {@link https://
|
|
2345
|
+
* @see {@link https://openiap.dev/docs/apis/android/launch-external-link-android}
|
|
2431
2346
|
*/
|
|
2432
2347
|
export const launchExternalLinkAndroid = async params => {
|
|
2433
2348
|
if (Platform.OS !== 'android') {
|
|
@@ -2469,7 +2384,7 @@ export const launchExternalLinkAndroid = async params => {
|
|
|
2469
2384
|
* }
|
|
2470
2385
|
* ```
|
|
2471
2386
|
*
|
|
2472
|
-
* @see {@link https://
|
|
2387
|
+
* @see {@link https://openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios}
|
|
2473
2388
|
*/
|
|
2474
2389
|
export const canPresentExternalPurchaseNoticeIOS = async () => {
|
|
2475
2390
|
if (Platform.OS !== 'ios') {
|
|
@@ -2499,7 +2414,7 @@ export const canPresentExternalPurchaseNoticeIOS = async () => {
|
|
|
2499
2414
|
* }
|
|
2500
2415
|
* ```
|
|
2501
2416
|
*
|
|
2502
|
-
* @see {@link https://
|
|
2417
|
+
* @see {@link https://openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios}
|
|
2503
2418
|
*/
|
|
2504
2419
|
export const presentExternalPurchaseNoticeSheetIOS = async () => {
|
|
2505
2420
|
if (Platform.OS !== 'ios') {
|
|
@@ -2528,7 +2443,7 @@ export const presentExternalPurchaseNoticeSheetIOS = async () => {
|
|
|
2528
2443
|
* }
|
|
2529
2444
|
* ```
|
|
2530
2445
|
*
|
|
2531
|
-
* @see {@link https://
|
|
2446
|
+
* @see {@link https://openiap.dev/docs/apis/ios/present-external-purchase-link-ios}
|
|
2532
2447
|
*/
|
|
2533
2448
|
export const presentExternalPurchaseLinkIOS = async url => {
|
|
2534
2449
|
if (Platform.OS !== 'ios') {
|
|
@@ -2562,7 +2477,7 @@ export const presentExternalPurchaseLinkIOS = async url => {
|
|
|
2562
2477
|
* }
|
|
2563
2478
|
* ```
|
|
2564
2479
|
*
|
|
2565
|
-
* @see {@link https://
|
|
2480
|
+
* @see {@link https://openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios}
|
|
2566
2481
|
*/
|
|
2567
2482
|
export const isEligibleForExternalPurchaseCustomLinkIOS = async () => {
|
|
2568
2483
|
if (Platform.OS !== 'ios') {
|
|
@@ -2595,7 +2510,7 @@ export const isEligibleForExternalPurchaseCustomLinkIOS = async () => {
|
|
|
2595
2510
|
* }
|
|
2596
2511
|
* ```
|
|
2597
2512
|
*
|
|
2598
|
-
* @see {@link https://
|
|
2513
|
+
* @see {@link https://openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios}
|
|
2599
2514
|
*/
|
|
2600
2515
|
export const getExternalPurchaseCustomLinkTokenIOS = async tokenType => {
|
|
2601
2516
|
if (Platform.OS !== 'ios') {
|
|
@@ -2628,7 +2543,7 @@ export const getExternalPurchaseCustomLinkTokenIOS = async tokenType => {
|
|
|
2628
2543
|
* }
|
|
2629
2544
|
* ```
|
|
2630
2545
|
*
|
|
2631
|
-
* @see {@link https://
|
|
2546
|
+
* @see {@link https://openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios}
|
|
2632
2547
|
*/
|
|
2633
2548
|
export const showExternalPurchaseCustomLinkNoticeIOS = async noticeType => {
|
|
2634
2549
|
if (Platform.OS !== 'ios') {
|