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