react-native-iap 13.0.4 → 14.0.0-rc.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/NitroIap.podspec +33 -0
- package/README.md +163 -51
- package/android/CMakeLists.txt +32 -0
- package/android/build.gradle +107 -138
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +5 -13
- package/android/src/main/AndroidManifest.xml +1 -4
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +843 -0
- package/android/src/main/java/com/margelo/nitro/iap/NitroIapPackage.java +33 -0
- package/android/src/main/java/com/margelo/nitro/iap/Types.kt +173 -0
- package/ios/Bridge.h +8 -0
- package/ios/ErrorUtils.swift +153 -0
- package/ios/HybridRnIap.swift +1326 -0
- package/ios/ProductStore.swift +33 -0
- package/ios/reactnativeiap.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/ios/reactnativeiap.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/lib/module/helpers/subscription.js +56 -0
- package/lib/module/helpers/subscription.js.map +1 -0
- package/lib/module/hooks/useIAP.js +175 -123
- package/lib/module/hooks/useIAP.js.map +1 -1
- package/lib/module/index.js +1015 -9
- package/lib/module/index.js.map +1 -1
- package/lib/module/package.json +1 -0
- package/lib/module/specs/RnIap.nitro.js +4 -0
- package/lib/{commonjs/modules/common.js.map → module/specs/RnIap.nitro.js.map} +1 -1
- package/lib/module/types.js +187 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/error.js +80 -0
- package/lib/module/utils/error.js.map +1 -0
- package/lib/module/utils/type-bridge.js +202 -0
- package/lib/module/utils/type-bridge.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/plugin/src/withIAP.d.ts +2 -7
- package/lib/typescript/plugin/src/withIAP.d.ts.map +1 -1
- package/lib/typescript/scripts/check-nitro-versions.d.ts +3 -0
- package/lib/typescript/scripts/check-nitro-versions.d.ts.map +1 -0
- package/lib/typescript/src/helpers/subscription.d.ts +14 -0
- package/lib/typescript/src/helpers/subscription.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useIAP.d.ts +42 -26
- package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +356 -8
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/RnIap.nitro.d.ts +404 -0
- package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +544 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utils/error.d.ts +30 -0
- package/lib/typescript/src/utils/error.d.ts.map +1 -0
- package/lib/typescript/src/utils/type-bridge.d.ts +40 -0
- package/lib/typescript/src/utils/type-bridge.d.ts.map +1 -0
- package/nitro.json +17 -0
- package/nitrogen/generated/android/NitroIap+autolinking.cmake +80 -0
- package/nitrogen/generated/android/NitroIap+autolinking.gradle +27 -0
- package/nitrogen/generated/android/NitroIapOnLoad.cpp +50 -0
- package/nitrogen/generated/android/NitroIapOnLoad.hpp +25 -0
- package/nitrogen/generated/android/c++/JFunc_void_NitroProduct.hpp +78 -0
- package/nitrogen/generated/android/c++/JFunc_void_NitroPurchase.hpp +78 -0
- package/nitrogen/generated/android/c++/JFunc_void_NitroPurchaseResult.hpp +78 -0
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +577 -0
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +93 -0
- package/nitrogen/generated/android/c++/JNitroAndroidReceiptValidationOptions.hpp +66 -0
- package/nitrogen/generated/android/c++/JNitroAvailablePurchasesAndroidOptions.hpp +54 -0
- package/nitrogen/generated/android/c++/JNitroAvailablePurchasesIosOptions.hpp +65 -0
- package/nitrogen/generated/android/c++/JNitroAvailablePurchasesOptions.hpp +62 -0
- package/nitrogen/generated/android/c++/JNitroFinishTransactionAndroidParams.hpp +58 -0
- package/nitrogen/generated/android/c++/JNitroFinishTransactionIosParams.hpp +53 -0
- package/nitrogen/generated/android/c++/JNitroFinishTransactionParams.hpp +62 -0
- package/nitrogen/generated/android/c++/JNitroProduct.hpp +154 -0
- package/nitrogen/generated/android/c++/JNitroPurchase.hpp +122 -0
- package/nitrogen/generated/android/c++/JNitroPurchaseRequest.hpp +66 -0
- package/nitrogen/generated/android/c++/JNitroPurchaseResult.hpp +70 -0
- package/nitrogen/generated/android/c++/JNitroReceiptValidationParams.hpp +60 -0
- package/nitrogen/generated/android/c++/JNitroReceiptValidationResultAndroid.hpp +122 -0
- package/nitrogen/generated/android/c++/JNitroReceiptValidationResultIOS.hpp +68 -0
- package/nitrogen/generated/android/c++/JNitroRequestPurchaseAndroid.hpp +115 -0
- package/nitrogen/generated/android/c++/JNitroRequestPurchaseIos.hpp +84 -0
- package/nitrogen/generated/android/c++/JNitroSubscriptionOffer.hpp +57 -0
- package/nitrogen/generated/android/c++/JNitroSubscriptionRenewalInfo.hpp +74 -0
- package/nitrogen/generated/android/c++/JNitroSubscriptionStatus.hpp +64 -0
- package/nitrogen/generated/android/c++/JVariant_Boolean_NitroPurchaseResult.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_Boolean_NitroPurchaseResult.hpp +71 -0
- package/nitrogen/generated/android/c++/JVariant_NitroReceiptValidationResultIOS_NitroReceiptValidationResultAndroid.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NitroReceiptValidationResultIOS_NitroReceiptValidationResultAndroid.hpp +75 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Func_void_NitroProduct.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Func_void_NitroPurchase.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Func_void_NitroPurchaseResult.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +198 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroAndroidReceiptValidationOptions.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroAvailablePurchasesAndroidOptions.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroAvailablePurchasesIosOptions.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroAvailablePurchasesOptions.kt +32 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroFinishTransactionAndroidParams.kt +32 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroFinishTransactionIosParams.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroFinishTransactionParams.kt +32 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroIapOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroProduct.kt +104 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroPurchase.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroPurchaseRequest.kt +32 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroPurchaseResult.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroReceiptValidationParams.kt +32 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroReceiptValidationResultAndroid.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroReceiptValidationResultIOS.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroRequestPurchaseAndroid.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroRequestPurchaseIos.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroSubscriptionOffer.kt +32 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroSubscriptionRenewalInfo.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroSubscriptionStatus.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_Boolean_NitroPurchaseResult.kt +42 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_NitroReceiptValidationResultIOS_NitroReceiptValidationResultAndroid.kt +42 -0
- package/nitrogen/generated/ios/NitroIap+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.cpp +152 -0
- package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.hpp +1061 -0
- package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +107 -0
- package/nitrogen/generated/ios/NitroIapAutolinking.mm +33 -0
- package/nitrogen/generated/ios/NitroIapAutolinking.swift +25 -0
- package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +355 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_NitroProduct.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_NitroPurchase.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_NitroPurchaseResult.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_NitroProduct_.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_NitroPurchase_.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__vector_NitroSubscriptionStatus__.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__variant_NitroReceiptValidationResultIOS__NitroReceiptValidationResultAndroid_.swift +59 -0
- package/nitrogen/generated/ios/swift/Func_void_std__variant_bool__NitroPurchaseResult_.swift +59 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_NitroProduct_.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_NitroPurchase_.swift +47 -0
- package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +78 -0
- package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +750 -0
- package/nitrogen/generated/ios/swift/NitroAndroidReceiptValidationOptions.swift +80 -0
- package/nitrogen/generated/ios/swift/NitroAvailablePurchasesAndroidOptions.swift +54 -0
- package/nitrogen/generated/ios/swift/NitroAvailablePurchasesIosOptions.swift +116 -0
- package/nitrogen/generated/ios/swift/NitroAvailablePurchasesOptions.swift +84 -0
- package/nitrogen/generated/ios/swift/NitroFinishTransactionAndroidParams.swift +58 -0
- package/nitrogen/generated/ios/swift/NitroFinishTransactionIosParams.swift +35 -0
- package/nitrogen/generated/ios/swift/NitroFinishTransactionParams.swift +84 -0
- package/nitrogen/generated/ios/swift/NitroProduct.swift +653 -0
- package/nitrogen/generated/ios/swift/NitroPurchase.swift +453 -0
- package/nitrogen/generated/ios/swift/NitroPurchaseRequest.swift +84 -0
- package/nitrogen/generated/ios/swift/NitroPurchaseResult.swift +117 -0
- package/nitrogen/generated/ios/swift/NitroReceiptValidationParams.swift +65 -0
- package/nitrogen/generated/ios/swift/NitroReceiptValidationResultAndroid.swift +258 -0
- package/nitrogen/generated/ios/swift/NitroReceiptValidationResultIOS.swift +87 -0
- package/nitrogen/generated/ios/swift/NitroRequestPurchaseAndroid.swift +225 -0
- package/nitrogen/generated/ios/swift/NitroRequestPurchaseIos.swift +161 -0
- package/nitrogen/generated/ios/swift/NitroSubscriptionOffer.swift +46 -0
- package/nitrogen/generated/ios/swift/NitroSubscriptionRenewalInfo.swift +152 -0
- package/nitrogen/generated/ios/swift/NitroSubscriptionStatus.swift +76 -0
- package/nitrogen/generated/ios/swift/Variant_Bool_NitroPurchaseResult.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_NitroReceiptValidationResultIOS_NitroReceiptValidationResultAndroid.swift +18 -0
- package/nitrogen/generated/shared/c++/HybridRnIapSpec.cpp +50 -0
- package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +125 -0
- package/nitrogen/generated/shared/c++/NitroAndroidReceiptValidationOptions.hpp +80 -0
- package/nitrogen/generated/shared/c++/NitroAvailablePurchasesAndroidOptions.hpp +68 -0
- package/nitrogen/generated/shared/c++/NitroAvailablePurchasesIosOptions.hpp +79 -0
- package/nitrogen/generated/shared/c++/NitroAvailablePurchasesOptions.hpp +76 -0
- package/nitrogen/generated/shared/c++/NitroFinishTransactionAndroidParams.hpp +72 -0
- package/nitrogen/generated/shared/c++/NitroFinishTransactionIosParams.hpp +67 -0
- package/nitrogen/generated/shared/c++/NitroFinishTransactionParams.hpp +76 -0
- package/nitrogen/generated/shared/c++/NitroProduct.hpp +168 -0
- package/nitrogen/generated/shared/c++/NitroPurchase.hpp +136 -0
- package/nitrogen/generated/shared/c++/NitroPurchaseRequest.hpp +76 -0
- package/nitrogen/generated/shared/c++/NitroPurchaseResult.hpp +84 -0
- package/nitrogen/generated/shared/c++/NitroReceiptValidationParams.hpp +74 -0
- package/nitrogen/generated/shared/c++/NitroReceiptValidationResultAndroid.hpp +136 -0
- package/nitrogen/generated/shared/c++/NitroReceiptValidationResultIOS.hpp +82 -0
- package/nitrogen/generated/shared/c++/NitroRequestPurchaseAndroid.hpp +95 -0
- package/nitrogen/generated/shared/c++/NitroRequestPurchaseIos.hpp +85 -0
- package/nitrogen/generated/shared/c++/NitroSubscriptionOffer.hpp +71 -0
- package/nitrogen/generated/shared/c++/NitroSubscriptionRenewalInfo.hpp +88 -0
- package/nitrogen/generated/shared/c++/NitroSubscriptionStatus.hpp +78 -0
- package/package.json +145 -104
- package/plugin/build/src/withIAP.d.ts +3 -0
- package/plugin/build/src/withIAP.js +81 -0
- package/plugin/build/tsconfig.tsbuildinfo +1 -0
- package/plugin/build/withIAP.d.ts +2 -7
- package/plugin/build/withIAP.js +62 -51
- package/plugin/src/withIAP.ts +119 -0
- package/plugin/tsconfig.json +18 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/src/helpers/subscription.ts +65 -0
- package/src/hooks/useIAP.ts +361 -222
- package/src/index.ts +1194 -9
- package/src/specs/RnIap.nitro.ts +501 -0
- package/src/types.ts +680 -0
- package/src/utils/error.ts +97 -0
- package/src/utils/type-bridge.ts +209 -0
- package/LICENSE +0 -21
- package/RNIap.podspec +0 -36
- package/android/src/amazon/AndroidManifest.xml +0 -14
- package/android/src/amazon/java/com/dooboolab/rniap/EventSender.kt +0 -10
- package/android/src/amazon/java/com/dooboolab/rniap/PurchasingServiceProxy.kt +0 -29
- package/android/src/amazon/java/com/dooboolab/rniap/PurchasingServiceProxyAmazonImpl.kt +0 -31
- package/android/src/amazon/java/com/dooboolab/rniap/RNIapActivityListener.kt +0 -55
- package/android/src/amazon/java/com/dooboolab/rniap/RNIapAmazonListener.kt +0 -325
- package/android/src/amazon/java/com/dooboolab/rniap/RNIapAmazonModule.kt +0 -244
- package/android/src/amazon/java/com/dooboolab/rniap/RNIapPackage.kt +0 -17
- package/android/src/amazon/java/com/dooboolab/rniap/modifysubscription/RNIapAmazonModifySubscriptionListener.kt +0 -88
- package/android/src/amazon/java/com/dooboolab/rniap/utils/Extensions.kt +0 -22
- package/android/src/main/java/com/dooboolab/rniap/PromiseUtils.kt +0 -62
- package/android/src/main/java/com/dooboolab/rniap/PromiseUtlis.kt +0 -43
- package/android/src/play/java/com/dooboolab/rniap/PlayUtils.kt +0 -114
- package/android/src/play/java/com/dooboolab/rniap/RNIapActivityListener.kt +0 -15
- package/android/src/play/java/com/dooboolab/rniap/RNIapModule.kt +0 -911
- package/android/src/play/java/com/dooboolab/rniap/RNIapPackage.kt +0 -17
- package/android/src/testAmazon/java/com/dooboolab/rniap/RNIapAmazonModuleTest.kt +0 -170
- package/app.plugin.js +0 -1
- package/ios/IapSerializationUtils.swift +0 -290
- package/ios/IapTypes.swift +0 -56
- package/ios/IapUtils.swift +0 -40
- package/ios/LatestPromiseKeeper.swift +0 -52
- package/ios/RNIapIos-Bridging-Header.h +0 -2
- package/ios/RNIapIos.m +0 -69
- package/ios/RNIapIos.swift +0 -868
- package/ios/RNIapIos.xcodeproj/project.pbxproj +0 -289
- package/ios/RNIapIosSk2.m +0 -126
- package/ios/RNIapIosSk2.swift +0 -1413
- package/ios/ThreadSafe.swift +0 -18
- package/lib/commonjs/eventEmitter.js +0 -195
- package/lib/commonjs/eventEmitter.js.map +0 -1
- package/lib/commonjs/hooks/index.js +0 -17
- package/lib/commonjs/hooks/index.js.map +0 -1
- package/lib/commonjs/hooks/useIAP.js +0 -203
- package/lib/commonjs/hooks/useIAP.js.map +0 -1
- package/lib/commonjs/hooks/withIAPContext.js +0 -95
- package/lib/commonjs/hooks/withIAPContext.js.map +0 -1
- package/lib/commonjs/iap.js +0 -836
- package/lib/commonjs/iap.js.map +0 -1
- package/lib/commonjs/index.js +0 -105
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/internal/enhancedFetch.js +0 -26
- package/lib/commonjs/internal/enhancedFetch.js.map +0 -1
- package/lib/commonjs/internal/fillProductsWithAdditionalData.js +0 -50
- package/lib/commonjs/internal/fillProductsWithAdditionalData.js.map +0 -1
- package/lib/commonjs/internal/index.js +0 -39
- package/lib/commonjs/internal/index.js.map +0 -1
- package/lib/commonjs/internal/platform.js +0 -119
- package/lib/commonjs/internal/platform.js.map +0 -1
- package/lib/commonjs/modules/amazon.js +0 -50
- package/lib/commonjs/modules/amazon.js.map +0 -1
- package/lib/commonjs/modules/android.js +0 -92
- package/lib/commonjs/modules/android.js.map +0 -1
- package/lib/commonjs/modules/common.js +0 -2
- package/lib/commonjs/modules/index.js +0 -50
- package/lib/commonjs/modules/index.js.map +0 -1
- package/lib/commonjs/modules/ios.js +0 -160
- package/lib/commonjs/modules/ios.js.map +0 -1
- package/lib/commonjs/modules/iosSk2.js +0 -113
- package/lib/commonjs/modules/iosSk2.js.map +0 -1
- package/lib/commonjs/purchaseError.js +0 -170
- package/lib/commonjs/purchaseError.js.map +0 -1
- package/lib/commonjs/types/amazon.js +0 -2
- package/lib/commonjs/types/amazon.js.map +0 -1
- package/lib/commonjs/types/android.js +0 -67
- package/lib/commonjs/types/android.js.map +0 -1
- package/lib/commonjs/types/apple.js +0 -24
- package/lib/commonjs/types/apple.js.map +0 -1
- package/lib/commonjs/types/appleSk2.js +0 -137
- package/lib/commonjs/types/appleSk2.js.map +0 -1
- package/lib/commonjs/types/index.js +0 -67
- package/lib/commonjs/types/index.js.map +0 -1
- package/lib/commonjs/utils/errorMapping.js +0 -83
- package/lib/commonjs/utils/errorMapping.js.map +0 -1
- package/lib/commonjs/utils/typeGuards.js +0 -74
- package/lib/commonjs/utils/typeGuards.js.map +0 -1
- package/lib/module/eventEmitter.js +0 -185
- package/lib/module/eventEmitter.js.map +0 -1
- package/lib/module/hooks/index.js +0 -2
- package/lib/module/hooks/index.js.map +0 -1
- package/lib/module/hooks/withIAPContext.js +0 -86
- package/lib/module/hooks/withIAPContext.js.map +0 -1
- package/lib/module/iap.js +0 -805
- package/lib/module/iap.js.map +0 -1
- package/lib/module/internal/enhancedFetch.js +0 -19
- package/lib/module/internal/enhancedFetch.js.map +0 -1
- package/lib/module/internal/fillProductsWithAdditionalData.js +0 -43
- package/lib/module/internal/fillProductsWithAdditionalData.js.map +0 -1
- package/lib/module/internal/index.js +0 -4
- package/lib/module/internal/index.js.map +0 -1
- package/lib/module/internal/platform.js +0 -102
- package/lib/module/internal/platform.js.map +0 -1
- package/lib/module/modules/amazon.js +0 -42
- package/lib/module/modules/amazon.js.map +0 -1
- package/lib/module/modules/android.js +0 -81
- package/lib/module/modules/android.js.map +0 -1
- package/lib/module/modules/common.js +0 -2
- package/lib/module/modules/common.js.map +0 -1
- package/lib/module/modules/index.js +0 -5
- package/lib/module/modules/index.js.map +0 -1
- package/lib/module/modules/ios.js +0 -145
- package/lib/module/modules/ios.js.map +0 -1
- package/lib/module/modules/iosSk2.js +0 -96
- package/lib/module/modules/iosSk2.js.map +0 -1
- package/lib/module/purchaseError.js +0 -164
- package/lib/module/purchaseError.js.map +0 -1
- package/lib/module/types/amazon.js +0 -2
- package/lib/module/types/amazon.js.map +0 -1
- package/lib/module/types/android.js +0 -63
- package/lib/module/types/android.js.map +0 -1
- package/lib/module/types/apple.js +0 -17
- package/lib/module/types/apple.js.map +0 -1
- package/lib/module/types/appleSk2.js +0 -129
- package/lib/module/types/appleSk2.js.map +0 -1
- package/lib/module/types/index.js +0 -75
- package/lib/module/types/index.js.map +0 -1
- package/lib/module/utils/errorMapping.js +0 -75
- package/lib/module/utils/errorMapping.js.map +0 -1
- package/lib/module/utils/typeGuards.js +0 -61
- package/lib/module/utils/typeGuards.js.map +0 -1
- package/lib/typescript/src/eventEmitter.d.ts +0 -151
- package/lib/typescript/src/eventEmitter.d.ts.map +0 -1
- package/lib/typescript/src/hooks/index.d.ts +0 -2
- package/lib/typescript/src/hooks/index.d.ts.map +0 -1
- package/lib/typescript/src/hooks/withIAPContext.d.ts +0 -27
- package/lib/typescript/src/hooks/withIAPContext.d.ts.map +0 -1
- package/lib/typescript/src/iap.d.ts +0 -503
- package/lib/typescript/src/iap.d.ts.map +0 -1
- package/lib/typescript/src/internal/enhancedFetch.d.ts +0 -6
- package/lib/typescript/src/internal/enhancedFetch.d.ts.map +0 -1
- package/lib/typescript/src/internal/fillProductsWithAdditionalData.d.ts +0 -7
- package/lib/typescript/src/internal/fillProductsWithAdditionalData.d.ts.map +0 -1
- package/lib/typescript/src/internal/index.d.ts +0 -4
- package/lib/typescript/src/internal/index.d.ts.map +0 -1
- package/lib/typescript/src/internal/platform.d.ts +0 -27
- package/lib/typescript/src/internal/platform.d.ts.map +0 -1
- package/lib/typescript/src/modules/amazon.d.ts +0 -55
- package/lib/typescript/src/modules/amazon.d.ts.map +0 -1
- package/lib/typescript/src/modules/android.d.ts +0 -74
- package/lib/typescript/src/modules/android.d.ts.map +0 -1
- package/lib/typescript/src/modules/common.d.ts +0 -14
- package/lib/typescript/src/modules/common.d.ts.map +0 -1
- package/lib/typescript/src/modules/index.d.ts +0 -5
- package/lib/typescript/src/modules/index.d.ts.map +0 -1
- package/lib/typescript/src/modules/ios.d.ts +0 -117
- package/lib/typescript/src/modules/ios.d.ts.map +0 -1
- package/lib/typescript/src/modules/iosSk2.d.ts +0 -140
- package/lib/typescript/src/modules/iosSk2.d.ts.map +0 -1
- package/lib/typescript/src/purchaseError.d.ts +0 -133
- package/lib/typescript/src/purchaseError.d.ts.map +0 -1
- package/lib/typescript/src/types/amazon.d.ts +0 -33
- package/lib/typescript/src/types/amazon.d.ts.map +0 -1
- package/lib/typescript/src/types/android.d.ts +0 -66
- package/lib/typescript/src/types/android.d.ts.map +0 -1
- package/lib/typescript/src/types/apple.d.ts +0 -27
- package/lib/typescript/src/types/apple.d.ts.map +0 -1
- package/lib/typescript/src/types/appleSk2.d.ts +0 -129
- package/lib/typescript/src/types/appleSk2.d.ts.map +0 -1
- package/lib/typescript/src/types/index.d.ts +0 -302
- package/lib/typescript/src/types/index.d.ts.map +0 -1
- package/lib/typescript/src/utils/errorMapping.d.ts +0 -29
- package/lib/typescript/src/utils/errorMapping.d.ts.map +0 -1
- package/lib/typescript/src/utils/typeGuards.d.ts +0 -53
- package/lib/typescript/src/utils/typeGuards.d.ts.map +0 -1
- package/src/eventEmitter.ts +0 -212
- package/src/hooks/index.ts +0 -1
- package/src/hooks/withIAPContext.tsx +0 -179
- package/src/iap.ts +0 -1046
- package/src/internal/enhancedFetch.ts +0 -25
- package/src/internal/fillProductsWithAdditionalData.ts +0 -47
- package/src/internal/index.ts +0 -3
- package/src/internal/platform.ts +0 -135
- package/src/modules/amazon.ts +0 -94
- package/src/modules/android.ts +0 -179
- package/src/modules/common.ts +0 -16
- package/src/modules/index.ts +0 -4
- package/src/modules/ios.ts +0 -229
- package/src/modules/iosSk2.ts +0 -194
- package/src/purchaseError.ts +0 -196
- package/src/types/amazon.ts +0 -40
- package/src/types/android.ts +0 -89
- package/src/types/apple.ts +0 -44
- package/src/types/appleSk2.ts +0 -275
- package/src/types/index.ts +0 -379
- package/src/utils/errorMapping.ts +0 -88
- package/src/utils/typeGuards.ts +0 -90
package/ios/RNIapIosSk2.swift
DELETED
|
@@ -1,1413 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import React
|
|
3
|
-
import StoreKit
|
|
4
|
-
|
|
5
|
-
protocol Sk2Delegate {
|
|
6
|
-
func disable(
|
|
7
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
8
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
func initConnection(
|
|
12
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
13
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
func endConnection(
|
|
17
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
18
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
func getItems(
|
|
22
|
-
_ skus: [String],
|
|
23
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
24
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
func getAvailableItems(
|
|
28
|
-
_ alsoPublishToEventListener: Bool,
|
|
29
|
-
onlyIncludeActiveItems: Bool,
|
|
30
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
31
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
func buyProduct(
|
|
35
|
-
_ sku: String,
|
|
36
|
-
andDangerouslyFinishTransactionAutomatically: Bool,
|
|
37
|
-
appAccountToken: String?,
|
|
38
|
-
quantity: Int,
|
|
39
|
-
withOffer: [String: String],
|
|
40
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
41
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
func isEligibleForIntroOffer(
|
|
45
|
-
_ groupID: String,
|
|
46
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
47
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
func subscriptionStatus(
|
|
51
|
-
_ sku: String,
|
|
52
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
53
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
func currentEntitlement(
|
|
57
|
-
_ sku: String,
|
|
58
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
59
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
func latestTransaction(
|
|
63
|
-
_ sku: String,
|
|
64
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
65
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
func finishTransaction(
|
|
69
|
-
_ transactionIdentifier: String,
|
|
70
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
71
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
func getPendingTransactions (
|
|
75
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
76
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
func sync(
|
|
80
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
81
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
func presentCodeRedemptionSheet(
|
|
85
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
86
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
func showManageSubscriptions(
|
|
90
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
91
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
func clearTransaction(
|
|
95
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
96
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
func beginRefundRequest(
|
|
100
|
-
_ sku: String,
|
|
101
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
102
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
func getStorefront(
|
|
106
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
107
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
func getAppTransaction(
|
|
111
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
112
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
func getReceiptDataIos(
|
|
116
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
117
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
func isTransactionVerifiedIos(
|
|
121
|
-
_ sku: String,
|
|
122
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
123
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
func getTransactionJwsIos(
|
|
127
|
-
_ sku: String,
|
|
128
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
129
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
func validateReceiptIos(
|
|
133
|
-
_ sku: String,
|
|
134
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
135
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
func startObserving()
|
|
139
|
-
func stopObserving()
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
class DummySk2: Sk2Delegate {
|
|
143
|
-
let errorCode = IapErrors.E_DEVELOPER_ERROR.rawValue
|
|
144
|
-
let errorMessage = "Method only available on iOS 15 and up"
|
|
145
|
-
|
|
146
|
-
func disable(
|
|
147
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
148
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
149
|
-
) {
|
|
150
|
-
reject(errorCode, errorMessage, nil)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
func initConnection(
|
|
154
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
155
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
156
|
-
) {
|
|
157
|
-
reject(errorCode, errorMessage, nil)
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
func endConnection(
|
|
161
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
162
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
163
|
-
) {
|
|
164
|
-
reject(errorCode, errorMessage, nil)
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
func getItems(
|
|
168
|
-
_ skus: [String],
|
|
169
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
170
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
171
|
-
) {
|
|
172
|
-
reject(errorCode, errorMessage, nil)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
func getAvailableItems(
|
|
176
|
-
_ alsoPublishToEventListener: Bool,
|
|
177
|
-
onlyIncludeActiveItems: Bool,
|
|
178
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
179
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
180
|
-
) {
|
|
181
|
-
reject(errorCode, errorMessage, nil)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
func buyProduct(
|
|
185
|
-
_ sku: String,
|
|
186
|
-
andDangerouslyFinishTransactionAutomatically: Bool,
|
|
187
|
-
appAccountToken: String?,
|
|
188
|
-
quantity: Int,
|
|
189
|
-
withOffer: [String: String],
|
|
190
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
191
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
192
|
-
) {
|
|
193
|
-
reject(errorCode, errorMessage, nil)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
func isEligibleForIntroOffer(
|
|
197
|
-
_ groupID: String,
|
|
198
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
199
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
200
|
-
) {
|
|
201
|
-
reject(errorCode, errorMessage, nil)
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
func subscriptionStatus(
|
|
205
|
-
_ sku: String,
|
|
206
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
207
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
208
|
-
) {
|
|
209
|
-
reject(errorCode, errorMessage, nil)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
func currentEntitlement(
|
|
213
|
-
_ sku: String,
|
|
214
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
215
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
216
|
-
) {
|
|
217
|
-
reject(errorCode, errorMessage, nil)
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
func latestTransaction(
|
|
221
|
-
_ sku: String,
|
|
222
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
223
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
224
|
-
) {
|
|
225
|
-
reject(errorCode, errorMessage, nil)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
func finishTransaction(
|
|
229
|
-
_ transactionIdentifier: String,
|
|
230
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
231
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
232
|
-
) {
|
|
233
|
-
reject(errorCode, errorMessage, nil)
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
func getPendingTransactions (
|
|
237
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
238
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
239
|
-
) {
|
|
240
|
-
reject(errorCode, errorMessage, nil)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
func sync(
|
|
244
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
245
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
246
|
-
) {
|
|
247
|
-
reject(errorCode, errorMessage, nil)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
func presentCodeRedemptionSheet(
|
|
251
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
252
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
253
|
-
) {
|
|
254
|
-
reject(errorCode, errorMessage, nil)
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
func showManageSubscriptions(
|
|
258
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
259
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
260
|
-
) {
|
|
261
|
-
reject(errorCode, errorMessage, nil)
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
func clearTransaction(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
265
|
-
reject(errorCode, errorMessage, nil)
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
func beginRefundRequest(
|
|
269
|
-
_ sku: String,
|
|
270
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
271
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
272
|
-
) {
|
|
273
|
-
reject(errorCode, errorMessage, nil)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
func getStorefront(
|
|
277
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
278
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
279
|
-
) {
|
|
280
|
-
reject(errorCode, errorMessage, nil)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
func getAppTransaction(
|
|
284
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
285
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
286
|
-
) {
|
|
287
|
-
reject(errorCode, errorMessage, nil)
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
func getReceiptDataIos(
|
|
291
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
292
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
293
|
-
) {
|
|
294
|
-
reject(errorCode, errorMessage, nil)
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
func isTransactionVerifiedIos(
|
|
298
|
-
_ sku: String,
|
|
299
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
300
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
301
|
-
) {
|
|
302
|
-
reject(errorCode, errorMessage, nil)
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
func getTransactionJwsIos(
|
|
306
|
-
_ sku: String,
|
|
307
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
308
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
309
|
-
) {
|
|
310
|
-
reject(errorCode, errorMessage, nil)
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
func validateReceiptIos(
|
|
314
|
-
_ sku: String,
|
|
315
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
316
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
317
|
-
) {
|
|
318
|
-
reject(errorCode, errorMessage, nil)
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
func startObserving() {
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
func stopObserving() {
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
@objc(RNIapIosSk2)
|
|
329
|
-
class RNIapIosSk2: RCTEventEmitter, Sk2Delegate {
|
|
330
|
-
private var delegate: Sk2Delegate = DummySk2()
|
|
331
|
-
|
|
332
|
-
override init() {
|
|
333
|
-
super.init()
|
|
334
|
-
if #available(iOS 15.0, tvOS 15.0, *) {
|
|
335
|
-
delegate = RNIapIosSk2iOS15(sendEvent: self.sendEvent)
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
@objc public func disable(
|
|
340
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
341
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
342
|
-
) {
|
|
343
|
-
delegate.disable(resolve, reject: reject)
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
override class func requiresMainQueueSetup() -> Bool {
|
|
347
|
-
return true
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
override func startObserving() {
|
|
351
|
-
delegate.startObserving()
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
override func stopObserving() {
|
|
355
|
-
delegate.stopObserving()
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
"iap-transaction-updated" is unique to Sk2.
|
|
360
|
-
"iap-promoted-product" is only avaiable on Sk1
|
|
361
|
-
"purchase-updated", "purchase-error" are for backward compatibility
|
|
362
|
-
*/
|
|
363
|
-
override func supportedEvents() -> [String]? {
|
|
364
|
-
return [ "purchase-updated", "purchase-error", "iap-transaction-updated"]
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
@objc public func initConnection(
|
|
368
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
369
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
370
|
-
) {
|
|
371
|
-
delegate.initConnection(resolve, reject: reject)
|
|
372
|
-
}
|
|
373
|
-
@objc public func endConnection(
|
|
374
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
375
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
376
|
-
) {
|
|
377
|
-
delegate.endConnection(resolve, reject: reject)
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
@objc public func getItems(
|
|
381
|
-
_ skus: [String],
|
|
382
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
383
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
384
|
-
) {
|
|
385
|
-
delegate.getItems(skus, resolve: resolve, reject: reject)
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
@objc public func getAvailableItems(
|
|
389
|
-
_ alsoPublishToEventListener: Bool,
|
|
390
|
-
onlyIncludeActiveItems: Bool,
|
|
391
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
392
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
393
|
-
) {
|
|
394
|
-
delegate.getAvailableItems(alsoPublishToEventListener, onlyIncludeActiveItems: onlyIncludeActiveItems, resolve: resolve, reject: reject)
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
@objc public func buyProduct(
|
|
398
|
-
_ sku: String,
|
|
399
|
-
andDangerouslyFinishTransactionAutomatically: Bool,
|
|
400
|
-
appAccountToken: String?,
|
|
401
|
-
quantity: Int,
|
|
402
|
-
withOffer: [String: String],
|
|
403
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
404
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
405
|
-
) {
|
|
406
|
-
delegate.buyProduct(
|
|
407
|
-
sku,
|
|
408
|
-
andDangerouslyFinishTransactionAutomatically: andDangerouslyFinishTransactionAutomatically,
|
|
409
|
-
appAccountToken: appAccountToken,
|
|
410
|
-
quantity: quantity,
|
|
411
|
-
withOffer: withOffer,
|
|
412
|
-
resolve: resolve,
|
|
413
|
-
reject: reject)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
@objc public func isEligibleForIntroOffer(
|
|
417
|
-
_ groupID: String,
|
|
418
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
419
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
420
|
-
) {
|
|
421
|
-
delegate.isEligibleForIntroOffer(groupID, resolve: resolve, reject: reject)
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
@objc public func subscriptionStatus(
|
|
425
|
-
_ sku: String,
|
|
426
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
427
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
428
|
-
) {
|
|
429
|
-
delegate.subscriptionStatus(sku, resolve: resolve, reject: reject)
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
@objc public func currentEntitlement(
|
|
433
|
-
_ sku: String,
|
|
434
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
435
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
436
|
-
) {
|
|
437
|
-
delegate.currentEntitlement(sku, resolve: resolve, reject: reject)
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
@objc public func latestTransaction(
|
|
441
|
-
_ sku: String,
|
|
442
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
443
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
444
|
-
) {
|
|
445
|
-
delegate.latestTransaction(sku, resolve: resolve, reject: reject)
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
@objc public func finishTransaction(
|
|
449
|
-
_ transactionIdentifier: String,
|
|
450
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
451
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
452
|
-
) {
|
|
453
|
-
delegate.finishTransaction(transactionIdentifier, resolve: resolve, reject: reject)
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
@objc public func getPendingTransactions (
|
|
457
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
458
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
459
|
-
) {
|
|
460
|
-
delegate.getPendingTransactions(resolve, reject: reject)
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
@objc public func sync(
|
|
464
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in},
|
|
465
|
-
reject: @escaping RCTPromiseRejectBlock = {_, _, _ in}
|
|
466
|
-
) {
|
|
467
|
-
delegate.sync(resolve, reject: reject)
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
@objc public func presentCodeRedemptionSheet(
|
|
471
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
472
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
473
|
-
) {
|
|
474
|
-
delegate.presentCodeRedemptionSheet(resolve, reject: reject)
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
@objc public func showManageSubscriptions(
|
|
478
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
479
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
480
|
-
) {
|
|
481
|
-
delegate.showManageSubscriptions(resolve, reject: reject)
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
@objc func clearTransaction(
|
|
485
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
486
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }) {
|
|
487
|
-
delegate.clearTransaction(resolve, reject: reject)
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
@objc public func beginRefundRequest(
|
|
491
|
-
_ sku: String,
|
|
492
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
493
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
494
|
-
) {
|
|
495
|
-
delegate.beginRefundRequest(sku, resolve: resolve, reject: reject)
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
@objc public func getStorefront(
|
|
499
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
500
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
501
|
-
) {
|
|
502
|
-
delegate.getStorefront(resolve, reject: reject)
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
@objc public func getAppTransaction(
|
|
506
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
507
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
508
|
-
) {
|
|
509
|
-
delegate.getAppTransaction(resolve, reject: reject)
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
@objc public func getReceiptDataIos(
|
|
513
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
514
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
515
|
-
) {
|
|
516
|
-
delegate.getReceiptDataIos(resolve, reject: reject)
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
@objc public func isTransactionVerifiedIos(
|
|
520
|
-
_ sku: String,
|
|
521
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
522
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
523
|
-
) {
|
|
524
|
-
delegate.isTransactionVerifiedIos(sku, resolve: resolve, reject: reject)
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
@objc public func getTransactionJwsIos(
|
|
528
|
-
_ sku: String,
|
|
529
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
530
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
531
|
-
) {
|
|
532
|
-
delegate.getTransactionJwsIos(sku, resolve: resolve, reject: reject)
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
@objc public func validateReceiptIos(
|
|
536
|
-
_ sku: String,
|
|
537
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
538
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
539
|
-
) {
|
|
540
|
-
delegate.validateReceiptIos(sku, resolve: resolve, reject: reject)
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
@available(iOS 15.0, tvOS 15.0, *)
|
|
545
|
-
class RNIapIosSk2iOS15: Sk2Delegate {
|
|
546
|
-
private var _hasListeners = false
|
|
547
|
-
private let _hasListenersQueue = DispatchQueue(label: "com.dooboolab.rniap.hasListenersQueue", attributes: .concurrent)
|
|
548
|
-
private var transactions: [String: Transaction]
|
|
549
|
-
private var updateListenerTask: Task<Void, Error>?
|
|
550
|
-
private var subscriptionPollingTask: Task<Void, Never>?
|
|
551
|
-
private var pollingSkus: Set<String> = []
|
|
552
|
-
fileprivate var sendEvent: ((String?, Any?) -> Void)?
|
|
553
|
-
var hasListeners: Bool {
|
|
554
|
-
get {
|
|
555
|
-
return _hasListenersQueue.sync { _hasListeners }
|
|
556
|
-
}
|
|
557
|
-
set {
|
|
558
|
-
_hasListenersQueue.async(flags: .barrier) { [weak self] in
|
|
559
|
-
self?._hasListeners = newValue
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
init(sendEvent: ((String?, Any?) -> Void)? ) {
|
|
564
|
-
self.sendEvent = sendEvent
|
|
565
|
-
transactions = [String: Transaction]()
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
deinit {
|
|
569
|
-
removeTransactionObserver()
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
actor ProductStore {
|
|
573
|
-
private(set) var products: [String: Product] = [:]
|
|
574
|
-
|
|
575
|
-
func addProduct(_ product: Product) {
|
|
576
|
-
self.products[product.id] = product
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
func getAllProducts() -> [Product] {
|
|
580
|
-
return Array(self.products.values)
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
func getProduct(productID: String) -> Product? {
|
|
584
|
-
return self.products[productID]
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
func removeAll() {
|
|
588
|
-
products.removeAll()
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
func performOnActor(_ action: @escaping (isolated ProductStore) -> Void) async {
|
|
592
|
-
action(self)
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
private let productStore = ProductStore()
|
|
597
|
-
|
|
598
|
-
@objc public func disable(
|
|
599
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
600
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
601
|
-
) {
|
|
602
|
-
removeTransactionObserver()
|
|
603
|
-
resolve(nil)
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
func addTransactionObserver() {
|
|
607
|
-
if updateListenerTask == nil {
|
|
608
|
-
updateListenerTask = listenForTransactions()
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
func removeTransactionObserver() {
|
|
613
|
-
updateListenerTask?.cancel()
|
|
614
|
-
updateListenerTask = nil
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
func addTransaction(_ transaction: Transaction) {
|
|
618
|
-
let transactionId = String(transaction.id)
|
|
619
|
-
self.transactions[transactionId] = transaction
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
func listenForTransactions() -> Task<Void, Error> {
|
|
623
|
-
return Task.detached {
|
|
624
|
-
// Iterate through any transactions that don't come from a direct call to `purchase()`.
|
|
625
|
-
for await result in Transaction.updates {
|
|
626
|
-
do {
|
|
627
|
-
let transaction = try checkVerified(result)
|
|
628
|
-
self.addTransaction(transaction)
|
|
629
|
-
// Deliver products to the user.
|
|
630
|
-
// await self.updateCustomerProductStatus()
|
|
631
|
-
|
|
632
|
-
if self.hasListeners {
|
|
633
|
-
self.sendEvent?("purchase-updated", serialize(transaction, result))
|
|
634
|
-
self.sendEvent?("iap-transaction-updated", ["transaction": serialize(transaction, result)])
|
|
635
|
-
}
|
|
636
|
-
// Always finish a transaction.
|
|
637
|
-
// await transaction.finish()
|
|
638
|
-
// The transaction is returned to the user. Once it has fullfilled the order,
|
|
639
|
-
// they can call finishTransaction
|
|
640
|
-
} catch {
|
|
641
|
-
// StoreKit has a transaction that fails verification. Don't deliver content to the user.
|
|
642
|
-
debugMessage("Transaction failed verification")
|
|
643
|
-
if self.hasListeners {
|
|
644
|
-
let err = [
|
|
645
|
-
"responseCode": IapErrors.E_TRANSACTION_VALIDATION_FAILED.rawValue,
|
|
646
|
-
"debugMessage": error.localizedDescription,
|
|
647
|
-
"code": IapErrors.E_TRANSACTION_VALIDATION_FAILED.rawValue,
|
|
648
|
-
"message": error.localizedDescription
|
|
649
|
-
]
|
|
650
|
-
|
|
651
|
-
self.sendEvent?("purchase-error", err)
|
|
652
|
-
self.sendEvent?("iap-transaction-updated", ["error": err])
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
func startObserving() {
|
|
660
|
-
hasListeners = true
|
|
661
|
-
addTransactionObserver()
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
func stopObserving() {
|
|
665
|
-
hasListeners = false
|
|
666
|
-
removeTransactionObserver()
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
public func initConnection(
|
|
670
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
671
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
672
|
-
) {
|
|
673
|
-
resolve(AppStore.canMakePayments)
|
|
674
|
-
}
|
|
675
|
-
public func endConnection(
|
|
676
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
677
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
678
|
-
) {
|
|
679
|
-
Task {
|
|
680
|
-
await productStore.removeAll()
|
|
681
|
-
}
|
|
682
|
-
transactions.removeAll()
|
|
683
|
-
removeTransactionObserver()
|
|
684
|
-
resolve(nil)
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
public func getItems(
|
|
688
|
-
_ skus: [String],
|
|
689
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
690
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
691
|
-
) {
|
|
692
|
-
Task {
|
|
693
|
-
do {
|
|
694
|
-
let fetchedProducts = try await Product.products(for: skus)
|
|
695
|
-
|
|
696
|
-
await productStore.performOnActor { isolatedStore in
|
|
697
|
-
fetchedProducts.forEach({ product in
|
|
698
|
-
isolatedStore.addProduct(product)
|
|
699
|
-
})
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
let products = await productStore.getAllProducts()
|
|
703
|
-
|
|
704
|
-
resolve(products.map({ (prod: Product) -> [String: Any?]? in
|
|
705
|
-
return serialize(prod)
|
|
706
|
-
}).compactMap({$0}))
|
|
707
|
-
} catch {
|
|
708
|
-
reject(IapErrors.E_UNKNOWN.rawValue, "Error fetching items", error)
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
public func getAvailableItems(
|
|
714
|
-
_ alsoPublishToEventListener: Bool,
|
|
715
|
-
onlyIncludeActiveItems: Bool,
|
|
716
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
717
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
718
|
-
) {
|
|
719
|
-
Task {
|
|
720
|
-
var purchasedItemsSerialized: [[String: Any?]] = []
|
|
721
|
-
|
|
722
|
-
func addTransaction(transaction: Transaction, verification: VerificationResult<Transaction>) {
|
|
723
|
-
purchasedItemsSerialized.append(serialize(transaction, verification))
|
|
724
|
-
if alsoPublishToEventListener {
|
|
725
|
-
self.sendEvent?("purchase-updated", serialize(transaction))
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
func addError( error: Error, errorDict: [String: String]) {
|
|
729
|
-
if alsoPublishToEventListener {
|
|
730
|
-
self.sendEvent?("purchase-error", errorDict)
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
// Iterate through all of the user's purchased products.
|
|
734
|
-
for await verification in onlyIncludeActiveItems ? Transaction.currentEntitlements : Transaction.all {
|
|
735
|
-
do {
|
|
736
|
-
// Check whether the transaction is verified. If it isn’t, catch `failedVerification` error.
|
|
737
|
-
let transaction = try checkVerified(verification)
|
|
738
|
-
// Check the `productType` of the transaction and get the corresponding product from the store.
|
|
739
|
-
if !onlyIncludeActiveItems {
|
|
740
|
-
addTransaction(transaction: transaction, verification: verification)
|
|
741
|
-
continue
|
|
742
|
-
}
|
|
743
|
-
switch transaction.productType {
|
|
744
|
-
case .nonConsumable:
|
|
745
|
-
if await productStore.getProduct(productID: transaction.productID) != nil {
|
|
746
|
-
addTransaction(transaction: transaction, verification: verification)
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
case .nonRenewable:
|
|
750
|
-
if await productStore.getProduct(productID: transaction.productID) != nil {
|
|
751
|
-
// Non-renewing subscriptions have no inherent expiration date, so they're always
|
|
752
|
-
// contained in `Transaction.currentEntitlements` after the user purchases them.
|
|
753
|
-
// This app defines this non-renewing subscription's expiration date to be one year after purchase.
|
|
754
|
-
// If the current date is within one year of the `purchaseDate`, the user is still entitled to this
|
|
755
|
-
// product.
|
|
756
|
-
let currentDate = Date()
|
|
757
|
-
let expirationDate = Calendar(identifier: .gregorian).date(byAdding: DateComponents(year: 1),
|
|
758
|
-
to: transaction.purchaseDate)!
|
|
759
|
-
|
|
760
|
-
if currentDate < expirationDate {
|
|
761
|
-
addTransaction(transaction: transaction, verification: verification)
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
case .autoRenewable:
|
|
766
|
-
if await productStore.getProduct(productID: transaction.productID) != nil {
|
|
767
|
-
addTransaction(transaction: transaction, verification: verification)
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
case .consumable:
|
|
771
|
-
if await productStore.getProduct(productID: transaction.productID) != nil {
|
|
772
|
-
addTransaction(transaction: transaction, verification: verification)
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
default:
|
|
776
|
-
break
|
|
777
|
-
}
|
|
778
|
-
} catch StoreError.failedVerification {
|
|
779
|
-
let err = [ "responseCode": IapErrors.E_TRANSACTION_VALIDATION_FAILED.rawValue,
|
|
780
|
-
"debugMessage": StoreError.failedVerification.localizedDescription,
|
|
781
|
-
"code": IapErrors.E_TRANSACTION_VALIDATION_FAILED.rawValue,
|
|
782
|
-
"message": StoreError.failedVerification.localizedDescription,
|
|
783
|
-
"productId": "unknown"
|
|
784
|
-
]
|
|
785
|
-
addError(error: StoreError.failedVerification, errorDict: err)
|
|
786
|
-
} catch {
|
|
787
|
-
debugMessage(error)
|
|
788
|
-
let err = [ "responseCode": IapErrors.E_UNKNOWN.rawValue,
|
|
789
|
-
"debugMessage": error.localizedDescription,
|
|
790
|
-
"code": IapErrors.E_UNKNOWN.rawValue,
|
|
791
|
-
"message": error.localizedDescription,
|
|
792
|
-
"productId": "unknown"
|
|
793
|
-
]
|
|
794
|
-
addError(error: StoreError.failedVerification, errorDict: err)
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
// Check the `subscriptionGroupStatus` to learn the auto-renewable subscription state to determine whether the customer
|
|
798
|
-
// is new (never subscribed), active, or inactive (expired subscription). This app has only one subscription
|
|
799
|
-
// group, so products in the subscriptions array all belong to the same group. The statuses that
|
|
800
|
-
// `product.subscription.status` returns apply to the entire subscription group.
|
|
801
|
-
// subscriptionGroupStatus = try? await subscriptions.first?.subscription?.status.first?.state
|
|
802
|
-
resolve(purchasedItemsSerialized)
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
public func buyProduct(
|
|
807
|
-
_ sku: String,
|
|
808
|
-
andDangerouslyFinishTransactionAutomatically: Bool,
|
|
809
|
-
appAccountToken: String?,
|
|
810
|
-
quantity: Int,
|
|
811
|
-
withOffer: [String: String],
|
|
812
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
813
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
814
|
-
) {
|
|
815
|
-
Task {
|
|
816
|
-
let product: Product? = await productStore.getProduct(productID: sku)
|
|
817
|
-
|
|
818
|
-
if let product = product {
|
|
819
|
-
do {
|
|
820
|
-
var options: Set<Product.PurchaseOption> = []
|
|
821
|
-
if quantity > -1 {
|
|
822
|
-
options.insert(.quantity(quantity))
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
let offerID = withOffer["offerID"]
|
|
826
|
-
let keyID = withOffer["keyID"]
|
|
827
|
-
let nonce = withOffer["nonce"]
|
|
828
|
-
let signature = withOffer["signature"]
|
|
829
|
-
let timestamp = withOffer["timestamp"]
|
|
830
|
-
|
|
831
|
-
if let offerID = offerID, let keyID = keyID, let nonce = nonce, let nonce = UUID(uuidString: nonce), let signature = signature, let signature = signature.data(using: .utf8), let timestamp = timestamp, let timestamp = Int(timestamp) {
|
|
832
|
-
options.insert(.promotionalOffer(offerID: offerID, keyID: keyID, nonce: nonce, signature: signature, timestamp: timestamp ))
|
|
833
|
-
}
|
|
834
|
-
if let appAccountToken = appAccountToken, let appAccountToken = UUID(uuidString: appAccountToken) {
|
|
835
|
-
options.insert(.appAccountToken(appAccountToken))
|
|
836
|
-
}
|
|
837
|
-
debugMessage("Purchase Started")
|
|
838
|
-
|
|
839
|
-
guard let windowScene = await currentWindow()?.windowScene else {
|
|
840
|
-
reject(IapErrors.E_DEVELOPER_ERROR.rawValue, "Could not find window scene", nil)
|
|
841
|
-
return
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
var result: Product.PurchaseResult?
|
|
845
|
-
|
|
846
|
-
#if swift(>=5.9)
|
|
847
|
-
if #available(iOS 17.0, tvOS 17.0, *) {
|
|
848
|
-
result = try await product.purchase(confirmIn: windowScene, options: options)
|
|
849
|
-
} else {
|
|
850
|
-
#if !os(visionOS)
|
|
851
|
-
result = try await product.purchase(options: options)
|
|
852
|
-
#endif
|
|
853
|
-
}
|
|
854
|
-
#elseif !os(visionOS)
|
|
855
|
-
result = try await product.purchase(options: options)
|
|
856
|
-
#endif
|
|
857
|
-
|
|
858
|
-
switch result {
|
|
859
|
-
case .success(let verification):
|
|
860
|
-
debugMessage("Purchase Successful")
|
|
861
|
-
|
|
862
|
-
// Check whether the transaction is verified. If it isn't,
|
|
863
|
-
// this function rethrows the verification error.
|
|
864
|
-
let transaction = try checkVerified(verification)
|
|
865
|
-
|
|
866
|
-
// The transaction is verified. Deliver content to the user.
|
|
867
|
-
// Do on JS :await updateCustomerProductStatus()
|
|
868
|
-
|
|
869
|
-
// Always finish a transaction.
|
|
870
|
-
if andDangerouslyFinishTransactionAutomatically {
|
|
871
|
-
await transaction.finish()
|
|
872
|
-
resolve(nil)
|
|
873
|
-
} else {
|
|
874
|
-
self.addTransaction(transaction)
|
|
875
|
-
self.sendEvent?("purchase-updated", serialize(transaction, verification))
|
|
876
|
-
resolve(serialize(transaction, verification))
|
|
877
|
-
}
|
|
878
|
-
return
|
|
879
|
-
|
|
880
|
-
case .userCancelled:
|
|
881
|
-
debugMessage("User cancelled the purchase")
|
|
882
|
-
|
|
883
|
-
let err = [
|
|
884
|
-
"debugMessage": "User cancelled the purchase",
|
|
885
|
-
"code": IapErrors.E_USER_CANCELLED.rawValue,
|
|
886
|
-
"message": "User cancelled the purchase",
|
|
887
|
-
"productId": sku,
|
|
888
|
-
"quantity": "\(quantity)"
|
|
889
|
-
]
|
|
890
|
-
debugMessage(err)
|
|
891
|
-
|
|
892
|
-
reject(
|
|
893
|
-
IapErrors.E_USER_CANCELLED.rawValue,
|
|
894
|
-
"User cancelled the purchase",
|
|
895
|
-
nil)
|
|
896
|
-
|
|
897
|
-
return
|
|
898
|
-
|
|
899
|
-
case .pending:
|
|
900
|
-
debugMessage("Deferred (awaiting approval via parental controls, etc.)")
|
|
901
|
-
|
|
902
|
-
let err = [
|
|
903
|
-
"debugMessage": "The payment was deferred (awaiting approval via parental controls for instance)",
|
|
904
|
-
"code": IapErrors.E_DEFERRED_PAYMENT.rawValue,
|
|
905
|
-
"message": "The payment was deferred (awaiting approval via parental controls for instance)",
|
|
906
|
-
"productId": sku,
|
|
907
|
-
"quantity": "\(quantity)"
|
|
908
|
-
]
|
|
909
|
-
debugMessage(err)
|
|
910
|
-
|
|
911
|
-
reject(
|
|
912
|
-
IapErrors.E_DEFERRED_PAYMENT.rawValue,
|
|
913
|
-
"The payment was deferred for \(sku) (awaiting approval via parental controls for instance)",
|
|
914
|
-
nil)
|
|
915
|
-
|
|
916
|
-
return
|
|
917
|
-
|
|
918
|
-
default:
|
|
919
|
-
reject(IapErrors.E_UNKNOWN.rawValue, "Unknown response from purchase", nil)
|
|
920
|
-
return
|
|
921
|
-
}
|
|
922
|
-
} catch {
|
|
923
|
-
debugMessage("Purchase Failed")
|
|
924
|
-
|
|
925
|
-
let err = [
|
|
926
|
-
"responseCode": IapErrors.E_PURCHASE_ERROR.rawValue,
|
|
927
|
-
"debugMessage": error.localizedDescription,
|
|
928
|
-
"message": error.localizedDescription,
|
|
929
|
-
"productId": sku
|
|
930
|
-
]
|
|
931
|
-
print(err)
|
|
932
|
-
|
|
933
|
-
reject(
|
|
934
|
-
IapErrors.E_UNKNOWN.rawValue,
|
|
935
|
-
"Purchased failed for sku:\(sku): \(error.localizedDescription)",
|
|
936
|
-
error)
|
|
937
|
-
}
|
|
938
|
-
} else {
|
|
939
|
-
reject("E_DEVELOPER_ERROR", "Invalid product ID. Did you call getProducts/Subscriptions", nil)
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
public func isEligibleForIntroOffer(
|
|
945
|
-
_ groupID: String,
|
|
946
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
947
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
948
|
-
) {
|
|
949
|
-
Task {
|
|
950
|
-
let isEligibleForIntroOffer = await Product.SubscriptionInfo.isEligibleForIntroOffer(for: groupID)
|
|
951
|
-
resolve(isEligibleForIntroOffer)
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
public func subscriptionStatus(
|
|
956
|
-
_ sku: String,
|
|
957
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
958
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
959
|
-
) {
|
|
960
|
-
Task {
|
|
961
|
-
do {
|
|
962
|
-
let product = await productStore.getProduct(productID: sku)
|
|
963
|
-
let status: [Product.SubscriptionInfo.Status]? = try await product?.subscription?.status
|
|
964
|
-
guard let status = status else {
|
|
965
|
-
resolve(nil)
|
|
966
|
-
return
|
|
967
|
-
}
|
|
968
|
-
resolve(status.map({s in serialize(s)}))
|
|
969
|
-
} catch {
|
|
970
|
-
reject(IapErrors.E_UNKNOWN.rawValue, "Error getting subscription status", error)
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
public func currentEntitlement(
|
|
976
|
-
_ sku: String,
|
|
977
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
978
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
979
|
-
) {
|
|
980
|
-
Task {
|
|
981
|
-
if let product = await productStore.getProduct(productID: sku) {
|
|
982
|
-
if let result = await product.currentEntitlement {
|
|
983
|
-
do {
|
|
984
|
-
// Check whether the transaction is verified. If it isn’t, catch `failedVerification` error.
|
|
985
|
-
let transaction = try checkVerified(result)
|
|
986
|
-
resolve(serialize(transaction, result))
|
|
987
|
-
} catch StoreError.failedVerification {
|
|
988
|
-
reject(IapErrors.E_UNKNOWN.rawValue, "Failed to verify transaction for sku \(sku)", StoreError.failedVerification)
|
|
989
|
-
} catch {
|
|
990
|
-
debugMessage(error)
|
|
991
|
-
reject(IapErrors.E_UNKNOWN.rawValue, "Error fetching entitlement for sku \(sku)", error)
|
|
992
|
-
}
|
|
993
|
-
} else {
|
|
994
|
-
reject(IapErrors.E_DEVELOPER_ERROR.rawValue, "Can't find entitlement for sku \(sku)", nil)
|
|
995
|
-
}
|
|
996
|
-
} else {
|
|
997
|
-
reject(IapErrors.E_DEVELOPER_ERROR.rawValue, "Can't find product for sku \(sku)", nil)
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
public func latestTransaction(
|
|
1003
|
-
_ sku: String,
|
|
1004
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
1005
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
1006
|
-
) {
|
|
1007
|
-
Task {
|
|
1008
|
-
if let product = await productStore.getProduct(productID: sku) {
|
|
1009
|
-
if let result = await product.latestTransaction {
|
|
1010
|
-
do {
|
|
1011
|
-
// Check whether the transaction is verified. If it isn’t, catch `failedVerification` error.
|
|
1012
|
-
let transaction = try checkVerified(result)
|
|
1013
|
-
resolve(serialize(transaction, result))
|
|
1014
|
-
} catch StoreError.failedVerification {
|
|
1015
|
-
reject(IapErrors.E_UNKNOWN.rawValue, "Failed to verify transaction for sku \(sku)", StoreError.failedVerification)
|
|
1016
|
-
} catch {
|
|
1017
|
-
debugMessage(error)
|
|
1018
|
-
reject(IapErrors.E_UNKNOWN.rawValue, "Error fetching latest transaction for sku \(sku)", error)
|
|
1019
|
-
}
|
|
1020
|
-
} else {
|
|
1021
|
-
reject(IapErrors.E_DEVELOPER_ERROR.rawValue, "Can't find latest transaction for sku \(sku)", nil)
|
|
1022
|
-
}
|
|
1023
|
-
} else {
|
|
1024
|
-
reject(IapErrors.E_DEVELOPER_ERROR.rawValue, "Can't find product for sku \(sku)", nil)
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
public func finishTransaction(
|
|
1030
|
-
_ transactionIdentifier: String,
|
|
1031
|
-
resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
1032
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
1033
|
-
) {
|
|
1034
|
-
Task {
|
|
1035
|
-
if let transaction = transactions[transactionIdentifier] {
|
|
1036
|
-
debugMessage("Finishing transaction")
|
|
1037
|
-
await transaction.finish()
|
|
1038
|
-
debugMessage("Finished transaction")
|
|
1039
|
-
transactions.removeValue(forKey: transactionIdentifier)
|
|
1040
|
-
resolve(nil)
|
|
1041
|
-
} else {
|
|
1042
|
-
reject(IapErrors.E_DEVELOPER_ERROR.rawValue, "Invalid transaction Id", nil)
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
public func getPendingTransactions (
|
|
1048
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
1049
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
1050
|
-
) {
|
|
1051
|
-
resolve(transactions.values.map({(t: Transaction) in serialize(t)}))
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
public func sync(
|
|
1055
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in},
|
|
1056
|
-
reject: @escaping RCTPromiseRejectBlock = {_, _, _ in}
|
|
1057
|
-
) {
|
|
1058
|
-
Task {
|
|
1059
|
-
do {
|
|
1060
|
-
try await AppStore.sync()
|
|
1061
|
-
resolve(nil)
|
|
1062
|
-
} catch {
|
|
1063
|
-
if "\(error)" == "userCancelled" {
|
|
1064
|
-
reject( IapErrors.E_USER_CANCELLED.rawValue, "User cancelled synchronizing with the AppStore", error)
|
|
1065
|
-
} else {
|
|
1066
|
-
reject( IapErrors.E_SYNC_ERROR.rawValue, "Error synchronizing with the AppStore", error)
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
|
|
1072
|
-
/**
|
|
1073
|
-
Should remain the same according to:
|
|
1074
|
-
https://stackoverflow.com/a/72789651/570612
|
|
1075
|
-
*/
|
|
1076
|
-
public func presentCodeRedemptionSheet(
|
|
1077
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
1078
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
1079
|
-
) {
|
|
1080
|
-
#if !os(tvOS)
|
|
1081
|
-
SKPaymentQueue.default().presentCodeRedemptionSheet()
|
|
1082
|
-
resolve(nil)
|
|
1083
|
-
#else
|
|
1084
|
-
reject(IapErrors.E_USER_CANCELLED.rawValue, "This method is not available on tvOS", nil)
|
|
1085
|
-
#endif
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
public func showManageSubscriptions(
|
|
1089
|
-
_ resolve: @escaping RCTPromiseResolveBlock = { _ in },
|
|
1090
|
-
reject: @escaping RCTPromiseRejectBlock = { _, _, _ in }
|
|
1091
|
-
) {
|
|
1092
|
-
#if !os(tvOS)
|
|
1093
|
-
Task {
|
|
1094
|
-
guard let scene = await currentWindow()?.windowScene as? UIWindowScene,
|
|
1095
|
-
!ProcessInfo.processInfo.isiOSAppOnMac else {
|
|
1096
|
-
return
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
// Get all subscription SKUs before showing the management UI
|
|
1100
|
-
let subscriptionSkus = await getAllSubscriptionProductIds()
|
|
1101
|
-
self.pollingSkus = Set(subscriptionSkus)
|
|
1102
|
-
|
|
1103
|
-
do {
|
|
1104
|
-
try await AppStore.showManageSubscriptions(in: scene)
|
|
1105
|
-
|
|
1106
|
-
// Start polling for subscription status changes after UI is shown
|
|
1107
|
-
if !self.pollingSkus.isEmpty {
|
|
1108
|
-
self.pollForSubscriptionStatusChanges()
|
|
1109
|
-
}
|
|
1110
|
-
} catch {
|
|
1111
|
-
print("Error:(error)")
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
resolve(nil)
|
|
1116
|
-
#else
|
|
1117
|
-
reject(IapErrors.E_USER_CANCELLED.rawValue, "This method is not available on tvOS", nil)
|
|
1118
|
-
#endif
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
func clearTransaction(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1122
|
-
Task {
|
|
1123
|
-
for await result in Transaction.unfinished {
|
|
1124
|
-
do {
|
|
1125
|
-
// Check whether the transaction is verified. If it isn’t, catch `failedVerification` error.
|
|
1126
|
-
let transaction = try checkVerified(result)
|
|
1127
|
-
debugMessage("Finishing transaction")
|
|
1128
|
-
await transaction.finish()
|
|
1129
|
-
debugMessage("Finished transaction")
|
|
1130
|
-
transactions.removeValue(forKey: String(transaction.id))
|
|
1131
|
-
} catch {
|
|
1132
|
-
debugMessage("Failed to finish transaction")
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
resolve(nil)
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
// TODO: Duplicated code to get the latest transaction, can be cleaned up.
|
|
1140
|
-
func beginRefundRequest(_ sku: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1141
|
-
#if !os(tvOS)
|
|
1142
|
-
@Sendable func serialize(_ rs: Transaction.RefundRequestStatus?) -> String? {
|
|
1143
|
-
guard let rs = rs else {return nil}
|
|
1144
|
-
switch rs {
|
|
1145
|
-
case .success: return "success"
|
|
1146
|
-
case .userCancelled: return "userCancelled"
|
|
1147
|
-
|
|
1148
|
-
default:
|
|
1149
|
-
return nil
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
Task {
|
|
1154
|
-
let window = await currentWindow()
|
|
1155
|
-
if let windowScene = await window?.windowScene {
|
|
1156
|
-
if let product = await productStore.getProduct(productID: sku) {
|
|
1157
|
-
if let result = await product.latestTransaction {
|
|
1158
|
-
do {
|
|
1159
|
-
// Check whether the transaction is verified. If it isn’t, catch `failedVerification` error.
|
|
1160
|
-
let transaction = try checkVerified(result)
|
|
1161
|
-
let refund = try await transaction.beginRefundRequest(in: windowScene )
|
|
1162
|
-
resolve(serialize(refund))
|
|
1163
|
-
} catch StoreError.failedVerification {
|
|
1164
|
-
reject(IapErrors.E_UNKNOWN.rawValue, "Failed to verify transaction for sku \(sku)", StoreError.failedVerification)
|
|
1165
|
-
} catch {
|
|
1166
|
-
debugMessage(error)
|
|
1167
|
-
reject(IapErrors.E_UNKNOWN.rawValue, "Failed to refund purchase", error)
|
|
1168
|
-
}
|
|
1169
|
-
} else {
|
|
1170
|
-
reject(IapErrors.E_DEVELOPER_ERROR.rawValue, "Can't find latest transaction for sku \(sku)", nil)
|
|
1171
|
-
}
|
|
1172
|
-
} else {
|
|
1173
|
-
reject(IapErrors.E_DEVELOPER_ERROR.rawValue, "Can't find product for sku \(sku)", nil)
|
|
1174
|
-
}
|
|
1175
|
-
} else {
|
|
1176
|
-
reject(IapErrors.E_DEVELOPER_ERROR.rawValue, "Cannon find window Scene", nil)
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
#else
|
|
1180
|
-
reject(IapErrors.E_USER_CANCELLED.rawValue, "This method is not available on tvOS", nil)
|
|
1181
|
-
#endif
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
public func getStorefront(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1185
|
-
Task {
|
|
1186
|
-
let storefront = await Storefront.current
|
|
1187
|
-
resolve(storefront?.countryCode)
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
public func getAppTransaction(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1192
|
-
if #available(iOS 16.0, tvOS 16.0, *) {
|
|
1193
|
-
Task {
|
|
1194
|
-
do {
|
|
1195
|
-
let shared = try await AppTransaction.shared
|
|
1196
|
-
|
|
1197
|
-
switch shared {
|
|
1198
|
-
case .verified(let appTransaction):
|
|
1199
|
-
var result: [String: Any] = [:]
|
|
1200
|
-
|
|
1201
|
-
// Add iOS 18.4+ properties
|
|
1202
|
-
if #available(iOS 18.4, tvOS 18.4, *) {
|
|
1203
|
-
result["appTransactionID"] = appTransaction.appTransactionID
|
|
1204
|
-
result["originalPlatform"] = appTransaction.originalPlatform
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1207
|
-
// Add other AppTransaction properties
|
|
1208
|
-
result["originalAppVersion"] = appTransaction.originalAppVersion
|
|
1209
|
-
result["originalPurchaseDate"] = appTransaction.originalPurchaseDate.timeIntervalSince1970 * 1000
|
|
1210
|
-
result["deviceVerification"] = appTransaction.deviceVerification.base64EncodedString()
|
|
1211
|
-
result["deviceVerificationNonce"] = appTransaction.deviceVerificationNonce.uuidString
|
|
1212
|
-
result["appVersion"] = appTransaction.appVersion
|
|
1213
|
-
result["signedDate"] = appTransaction.signedDate.timeIntervalSince1970 * 1000
|
|
1214
|
-
result["environment"] = appTransaction.environment.rawValue
|
|
1215
|
-
|
|
1216
|
-
resolve(result)
|
|
1217
|
-
|
|
1218
|
-
case .unverified(_, let error):
|
|
1219
|
-
reject(IapErrors.E_TRANSACTION_VALIDATION_FAILED.rawValue,
|
|
1220
|
-
"AppTransaction verification failed: \(error.localizedDescription)",
|
|
1221
|
-
error)
|
|
1222
|
-
}
|
|
1223
|
-
} catch {
|
|
1224
|
-
reject(IapErrors.E_UNKNOWN.rawValue,
|
|
1225
|
-
"Failed to get AppTransaction: \(error.localizedDescription)",
|
|
1226
|
-
error)
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
} else {
|
|
1230
|
-
reject(IapErrors.E_SERVICE_ERROR.rawValue, "AppTransaction is only available on iOS 16.0+", nil)
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
// MARK: - New methods from expo-iap
|
|
1235
|
-
|
|
1236
|
-
public func getReceiptDataIos(
|
|
1237
|
-
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
1238
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
1239
|
-
) {
|
|
1240
|
-
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
|
|
1241
|
-
FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
|
|
1242
|
-
do {
|
|
1243
|
-
let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
|
|
1244
|
-
let receiptString = receiptData.base64EncodedString(options: [])
|
|
1245
|
-
resolve(receiptString)
|
|
1246
|
-
} catch {
|
|
1247
|
-
reject(IapErrors.E_RECEIPT_FAILED.rawValue, "Error reading receipt data: \(error.localizedDescription)", error)
|
|
1248
|
-
}
|
|
1249
|
-
} else {
|
|
1250
|
-
reject(IapErrors.E_RECEIPT_FAILED.rawValue, "App Store receipt not found", nil)
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
public func isTransactionVerifiedIos(
|
|
1255
|
-
_ sku: String,
|
|
1256
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
1257
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
1258
|
-
) {
|
|
1259
|
-
Task {
|
|
1260
|
-
if let product = await productStore.getProduct(productID: sku),
|
|
1261
|
-
let result = await product.latestTransaction {
|
|
1262
|
-
do {
|
|
1263
|
-
// If this doesn't throw, the transaction is verified
|
|
1264
|
-
_ = try checkVerified(result)
|
|
1265
|
-
resolve(true)
|
|
1266
|
-
} catch {
|
|
1267
|
-
resolve(false)
|
|
1268
|
-
}
|
|
1269
|
-
} else {
|
|
1270
|
-
resolve(false)
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
public func getTransactionJwsIos(
|
|
1276
|
-
_ sku: String,
|
|
1277
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
1278
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
1279
|
-
) {
|
|
1280
|
-
Task {
|
|
1281
|
-
if let product = await productStore.getProduct(productID: sku),
|
|
1282
|
-
let result = await product.latestTransaction {
|
|
1283
|
-
resolve(result.jwsRepresentation)
|
|
1284
|
-
} else {
|
|
1285
|
-
reject(IapErrors.E_DEVELOPER_ERROR.rawValue, "Can't find transaction for sku \(sku)", nil)
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
public func validateReceiptIos(
|
|
1291
|
-
_ sku: String,
|
|
1292
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
1293
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
1294
|
-
) {
|
|
1295
|
-
Task {
|
|
1296
|
-
// Get receipt data
|
|
1297
|
-
var receiptData: String = ""
|
|
1298
|
-
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
|
|
1299
|
-
FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
|
|
1300
|
-
do {
|
|
1301
|
-
let data = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
|
|
1302
|
-
receiptData = data.base64EncodedString(options: [])
|
|
1303
|
-
} catch {
|
|
1304
|
-
// Continue with validation even if receipt retrieval fails
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
var isValid = false
|
|
1309
|
-
var jwsRepresentation: String?
|
|
1310
|
-
var latestTransaction: [String: Any?]?
|
|
1311
|
-
|
|
1312
|
-
// Get JWS representation and verify transaction
|
|
1313
|
-
if let product = await productStore.getProduct(productID: sku),
|
|
1314
|
-
let result = await product.latestTransaction {
|
|
1315
|
-
jwsRepresentation = result.jwsRepresentation
|
|
1316
|
-
|
|
1317
|
-
do {
|
|
1318
|
-
// If this doesn't throw, the transaction is verified
|
|
1319
|
-
let transaction = try checkVerified(result)
|
|
1320
|
-
isValid = true
|
|
1321
|
-
latestTransaction = serialize(transaction, result)
|
|
1322
|
-
} catch {
|
|
1323
|
-
isValid = false
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1327
|
-
let response: [String: Any] = [
|
|
1328
|
-
"isValid": isValid,
|
|
1329
|
-
"receiptData": receiptData,
|
|
1330
|
-
"jwsRepresentation": jwsRepresentation ?? "",
|
|
1331
|
-
"latestTransaction": latestTransaction as Any
|
|
1332
|
-
]
|
|
1333
|
-
|
|
1334
|
-
resolve(response)
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
|
-
|
|
1338
|
-
// MARK: - Subscription polling helpers
|
|
1339
|
-
|
|
1340
|
-
private func getAllSubscriptionProductIds() async -> [String] {
|
|
1341
|
-
let products = await productStore.getAllProducts()
|
|
1342
|
-
return products.compactMap { product in
|
|
1343
|
-
if product.subscription != nil {
|
|
1344
|
-
return product.id
|
|
1345
|
-
}
|
|
1346
|
-
return nil
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
private func pollForSubscriptionStatusChanges() {
|
|
1351
|
-
subscriptionPollingTask?.cancel()
|
|
1352
|
-
subscriptionPollingTask = Task {
|
|
1353
|
-
try? await Task.sleep(nanoseconds: 1_500_000_000) // 1.5 seconds
|
|
1354
|
-
|
|
1355
|
-
var previousStatuses: [String: Bool] = [:] // Track auto-renewal state with Bool
|
|
1356
|
-
|
|
1357
|
-
for sku in self.pollingSkus {
|
|
1358
|
-
guard let product = await self.productStore.getProduct(productID: sku),
|
|
1359
|
-
let status = try? await product.subscription?.status.first else { continue }
|
|
1360
|
-
|
|
1361
|
-
// Track willAutoRenew as a bool value
|
|
1362
|
-
var willAutoRenew = false
|
|
1363
|
-
if case .verified(let info) = status.renewalInfo {
|
|
1364
|
-
willAutoRenew = info.willAutoRenew
|
|
1365
|
-
}
|
|
1366
|
-
previousStatuses[sku] = willAutoRenew
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
for _ in 1...5 {
|
|
1370
|
-
try? await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds
|
|
1371
|
-
if Task.isCancelled {
|
|
1372
|
-
return
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
|
-
for sku in self.pollingSkus {
|
|
1376
|
-
guard let product = await self.productStore.getProduct(productID: sku),
|
|
1377
|
-
let status = try? await product.subscription?.status.first,
|
|
1378
|
-
let result = await product.latestTransaction else { continue }
|
|
1379
|
-
// Try to verify the transaction
|
|
1380
|
-
let transaction: Transaction
|
|
1381
|
-
do {
|
|
1382
|
-
transaction = try checkVerified(result)
|
|
1383
|
-
} catch {
|
|
1384
|
-
continue // Skip if verification fails
|
|
1385
|
-
}
|
|
1386
|
-
|
|
1387
|
-
// Track current auto-renewal state
|
|
1388
|
-
var currentWillAutoRenew = false
|
|
1389
|
-
if case .verified(let info) = status.renewalInfo {
|
|
1390
|
-
currentWillAutoRenew = info.willAutoRenew
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
// Compare with previous state
|
|
1394
|
-
if let previousWillAutoRenew = previousStatuses[sku],
|
|
1395
|
-
previousWillAutoRenew != currentWillAutoRenew {
|
|
1396
|
-
// Use the jwsRepresentation when serializing the transaction
|
|
1397
|
-
var purchaseMap = serialize(transaction, result)
|
|
1398
|
-
|
|
1399
|
-
if case .verified(let renewalInfo) = status.renewalInfo {
|
|
1400
|
-
if let renewalInfoDict = serialize(renewalInfo) {
|
|
1401
|
-
purchaseMap["renewalInfo"] = renewalInfoDict
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
|
|
1405
|
-
self.sendEvent?("purchase-updated", purchaseMap)
|
|
1406
|
-
previousStatuses[sku] = currentWillAutoRenew
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
self.pollingSkus.removeAll()
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
}
|