react-native-iap 14.2.3 → 14.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +2 -6
  2. package/android/build.gradle +4 -5
  3. package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +327 -547
  4. package/ios/HybridRnIap.swift +41 -19
  5. package/lib/module/helpers/subscription.js +2 -2
  6. package/lib/module/helpers/subscription.js.map +1 -1
  7. package/lib/module/index.js +44 -1
  8. package/lib/module/index.js.map +1 -1
  9. package/lib/module/types.js.map +1 -1
  10. package/lib/module/utils/type-bridge.js +1 -2
  11. package/lib/module/utils/type-bridge.js.map +1 -1
  12. package/lib/typescript/plugin/src/withIAP.d.ts.map +1 -1
  13. package/lib/typescript/src/helpers/subscription.d.ts.map +1 -1
  14. package/lib/typescript/src/index.d.ts +15 -0
  15. package/lib/typescript/src/index.d.ts.map +1 -1
  16. package/lib/typescript/src/specs/RnIap.nitro.d.ts +17 -0
  17. package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
  18. package/lib/typescript/src/types.d.ts +0 -2
  19. package/lib/typescript/src/types.d.ts.map +1 -1
  20. package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +35 -0
  21. package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +2 -0
  22. package/nitrogen/generated/android/c++/JNitroDeepLinkOptionsAndroid.hpp +58 -0
  23. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +8 -0
  24. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroDeepLinkOptionsAndroid.kt +32 -0
  25. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +3 -0
  26. package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +19 -0
  27. package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +2 -0
  28. package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +38 -0
  29. package/nitrogen/generated/ios/swift/NitroDeepLinkOptionsAndroid.swift +84 -0
  30. package/nitrogen/generated/shared/c++/HybridRnIapSpec.cpp +2 -0
  31. package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +5 -0
  32. package/nitrogen/generated/shared/c++/NitroDeepLinkOptionsAndroid.hpp +72 -0
  33. package/package.json +1 -1
  34. package/plugin/build/withIAP.js +21 -18
  35. package/plugin/src/withIAP.ts +31 -23
  36. package/src/helpers/subscription.ts +2 -5
  37. package/src/index.ts +49 -2
  38. package/src/specs/RnIap.nitro.ts +22 -0
  39. package/src/types.ts +0 -2
  40. package/src/utils/type-bridge.ts +1 -1
@@ -45,6 +45,8 @@ namespace margelo::nitro::iap { struct NitroFinishTransactionAndroidParams; }
45
45
  namespace margelo::nitro::iap { struct NitroReceiptValidationParams; }
46
46
  // Forward declaration of `NitroAndroidReceiptValidationOptions` to properly resolve imports.
47
47
  namespace margelo::nitro::iap { struct NitroAndroidReceiptValidationOptions; }
48
+ // Forward declaration of `NitroDeepLinkOptionsAndroid` to properly resolve imports.
49
+ namespace margelo::nitro::iap { struct NitroDeepLinkOptionsAndroid; }
48
50
 
49
51
  #include <NitroModules/Promise.hpp>
50
52
  #include <NitroModules/JPromise.hpp>
@@ -97,6 +99,8 @@ namespace margelo::nitro::iap { struct NitroAndroidReceiptValidationOptions; }
97
99
  #include "JNitroReceiptValidationParams.hpp"
98
100
  #include "NitroAndroidReceiptValidationOptions.hpp"
99
101
  #include "JNitroAndroidReceiptValidationOptions.hpp"
102
+ #include "NitroDeepLinkOptionsAndroid.hpp"
103
+ #include "JNitroDeepLinkOptionsAndroid.hpp"
100
104
 
101
105
  namespace margelo::nitro::iap {
102
106
 
@@ -582,5 +586,36 @@ namespace margelo::nitro::iap {
582
586
  return __promise;
583
587
  }();
584
588
  }
589
+ std::shared_ptr<Promise<std::string>> JHybridRnIapSpec::getStorefrontAndroid() {
590
+ static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("getStorefrontAndroid");
591
+ auto __result = method(_javaPart);
592
+ return [&]() {
593
+ auto __promise = Promise<std::string>::create();
594
+ __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
595
+ auto __result = jni::static_ref_cast<jni::JString>(__boxedResult);
596
+ __promise->resolve(__result->toStdString());
597
+ });
598
+ __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
599
+ jni::JniException __jniError(__throwable);
600
+ __promise->reject(std::make_exception_ptr(__jniError));
601
+ });
602
+ return __promise;
603
+ }();
604
+ }
605
+ std::shared_ptr<Promise<void>> JHybridRnIapSpec::deepLinkToSubscriptionsAndroid(const NitroDeepLinkOptionsAndroid& options) {
606
+ static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<JNitroDeepLinkOptionsAndroid> /* options */)>("deepLinkToSubscriptionsAndroid");
607
+ auto __result = method(_javaPart, JNitroDeepLinkOptionsAndroid::fromCpp(options));
608
+ return [&]() {
609
+ auto __promise = Promise<void>::create();
610
+ __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {
611
+ __promise->resolve();
612
+ });
613
+ __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
614
+ jni::JniException __jniError(__throwable);
615
+ __promise->reject(std::make_exception_ptr(__jniError));
616
+ });
617
+ return __promise;
618
+ }();
619
+ }
585
620
 
586
621
  } // namespace margelo::nitro::iap
@@ -83,6 +83,8 @@ namespace margelo::nitro::iap {
83
83
  std::shared_ptr<Promise<bool>> isTransactionVerifiedIOS(const std::string& sku) override;
84
84
  std::shared_ptr<Promise<std::optional<std::string>>> getTransactionJwsIOS(const std::string& sku) override;
85
85
  std::shared_ptr<Promise<std::variant<NitroReceiptValidationResultIOS, NitroReceiptValidationResultAndroid>>> validateReceipt(const NitroReceiptValidationParams& params) override;
86
+ std::shared_ptr<Promise<std::string>> getStorefrontAndroid() override;
87
+ std::shared_ptr<Promise<void>> deepLinkToSubscriptionsAndroid(const NitroDeepLinkOptionsAndroid& options) override;
86
88
 
87
89
  private:
88
90
  friend HybridBase;
@@ -0,0 +1,58 @@
1
+ ///
2
+ /// JNitroDeepLinkOptionsAndroid.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2025 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #include <fbjni/fbjni.h>
11
+ #include "NitroDeepLinkOptionsAndroid.hpp"
12
+
13
+ #include <optional>
14
+ #include <string>
15
+
16
+ namespace margelo::nitro::iap {
17
+
18
+ using namespace facebook;
19
+
20
+ /**
21
+ * The C++ JNI bridge between the C++ struct "NitroDeepLinkOptionsAndroid" and the the Kotlin data class "NitroDeepLinkOptionsAndroid".
22
+ */
23
+ struct JNitroDeepLinkOptionsAndroid final: public jni::JavaClass<JNitroDeepLinkOptionsAndroid> {
24
+ public:
25
+ static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/iap/NitroDeepLinkOptionsAndroid;";
26
+
27
+ public:
28
+ /**
29
+ * Convert this Java/Kotlin-based struct to the C++ struct NitroDeepLinkOptionsAndroid by copying all values to C++.
30
+ */
31
+ [[maybe_unused]]
32
+ [[nodiscard]]
33
+ NitroDeepLinkOptionsAndroid toCpp() const {
34
+ static const auto clazz = javaClassStatic();
35
+ static const auto fieldSkuAndroid = clazz->getField<jni::JString>("skuAndroid");
36
+ jni::local_ref<jni::JString> skuAndroid = this->getFieldValue(fieldSkuAndroid);
37
+ static const auto fieldPackageNameAndroid = clazz->getField<jni::JString>("packageNameAndroid");
38
+ jni::local_ref<jni::JString> packageNameAndroid = this->getFieldValue(fieldPackageNameAndroid);
39
+ return NitroDeepLinkOptionsAndroid(
40
+ skuAndroid != nullptr ? std::make_optional(skuAndroid->toStdString()) : std::nullopt,
41
+ packageNameAndroid != nullptr ? std::make_optional(packageNameAndroid->toStdString()) : std::nullopt
42
+ );
43
+ }
44
+
45
+ public:
46
+ /**
47
+ * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.
48
+ */
49
+ [[maybe_unused]]
50
+ static jni::local_ref<JNitroDeepLinkOptionsAndroid::javaobject> fromCpp(const NitroDeepLinkOptionsAndroid& value) {
51
+ return newInstance(
52
+ value.skuAndroid.has_value() ? jni::make_jstring(value.skuAndroid.value()) : nullptr,
53
+ value.packageNameAndroid.has_value() ? jni::make_jstring(value.packageNameAndroid.value()) : nullptr
54
+ );
55
+ }
56
+ };
57
+
58
+ } // namespace margelo::nitro::iap
@@ -189,6 +189,14 @@ abstract class HybridRnIapSpec: HybridObject() {
189
189
  @DoNotStrip
190
190
  @Keep
191
191
  abstract fun validateReceipt(params: NitroReceiptValidationParams): Promise<Variant_NitroReceiptValidationResultIOS_NitroReceiptValidationResultAndroid>
192
+
193
+ @DoNotStrip
194
+ @Keep
195
+ abstract fun getStorefrontAndroid(): Promise<String>
196
+
197
+ @DoNotStrip
198
+ @Keep
199
+ abstract fun deepLinkToSubscriptionsAndroid(options: NitroDeepLinkOptionsAndroid): Promise<Unit>
192
200
 
193
201
  private external fun initHybrid(): HybridData
194
202
 
@@ -0,0 +1,32 @@
1
+ ///
2
+ /// NitroDeepLinkOptionsAndroid.kt
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2025 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ package com.margelo.nitro.iap
9
+
10
+ import androidx.annotation.Keep
11
+ import com.facebook.proguard.annotations.DoNotStrip
12
+ import com.margelo.nitro.core.*
13
+
14
+
15
+ /**
16
+ * Represents the JavaScript object/struct "NitroDeepLinkOptionsAndroid".
17
+ */
18
+ @DoNotStrip
19
+ @Keep
20
+ data class NitroDeepLinkOptionsAndroid
21
+ @DoNotStrip
22
+ @Keep
23
+ constructor(
24
+ @DoNotStrip
25
+ @Keep
26
+ val skuAndroid: String?,
27
+ @DoNotStrip
28
+ @Keep
29
+ val packageNameAndroid: String?
30
+ ) {
31
+ /* main constructor */
32
+ }
@@ -18,6 +18,8 @@ namespace margelo::nitro::iap { struct NitroAvailablePurchasesAndroidOptions; }
18
18
  namespace margelo::nitro::iap { struct NitroAvailablePurchasesIosOptions; }
19
19
  // Forward declaration of `NitroAvailablePurchasesOptions` to properly resolve imports.
20
20
  namespace margelo::nitro::iap { struct NitroAvailablePurchasesOptions; }
21
+ // Forward declaration of `NitroDeepLinkOptionsAndroid` to properly resolve imports.
22
+ namespace margelo::nitro::iap { struct NitroDeepLinkOptionsAndroid; }
21
23
  // Forward declaration of `NitroFinishTransactionAndroidParams` to properly resolve imports.
22
24
  namespace margelo::nitro::iap { struct NitroFinishTransactionAndroidParams; }
23
25
  // Forward declaration of `NitroFinishTransactionIosParams` to properly resolve imports.
@@ -55,6 +57,7 @@ namespace margelo::nitro::iap { struct NitroSubscriptionStatus; }
55
57
  #include "NitroAvailablePurchasesAndroidOptions.hpp"
56
58
  #include "NitroAvailablePurchasesIosOptions.hpp"
57
59
  #include "NitroAvailablePurchasesOptions.hpp"
60
+ #include "NitroDeepLinkOptionsAndroid.hpp"
58
61
  #include "NitroFinishTransactionAndroidParams.hpp"
59
62
  #include "NitroFinishTransactionIosParams.hpp"
60
63
  #include "NitroFinishTransactionParams.hpp"
@@ -50,6 +50,8 @@ namespace margelo::nitro::iap { struct NitroReceiptValidationResultAndroid; }
50
50
  namespace margelo::nitro::iap { struct NitroReceiptValidationParams; }
51
51
  // Forward declaration of `NitroAndroidReceiptValidationOptions` to properly resolve imports.
52
52
  namespace margelo::nitro::iap { struct NitroAndroidReceiptValidationOptions; }
53
+ // Forward declaration of `NitroDeepLinkOptionsAndroid` to properly resolve imports.
54
+ namespace margelo::nitro::iap { struct NitroDeepLinkOptionsAndroid; }
53
55
 
54
56
  #include <NitroModules/Promise.hpp>
55
57
  #include "NitroProduct.hpp"
@@ -77,6 +79,7 @@ namespace margelo::nitro::iap { struct NitroAndroidReceiptValidationOptions; }
77
79
  #include "NitroReceiptValidationResultAndroid.hpp"
78
80
  #include "NitroReceiptValidationParams.hpp"
79
81
  #include "NitroAndroidReceiptValidationOptions.hpp"
82
+ #include "NitroDeepLinkOptionsAndroid.hpp"
80
83
 
81
84
  #include "NitroIap-Swift-Cxx-Umbrella.hpp"
82
85
 
@@ -347,6 +350,22 @@ namespace margelo::nitro::iap {
347
350
  auto __value = std::move(__result.value());
348
351
  return __value;
349
352
  }
353
+ inline std::shared_ptr<Promise<std::string>> getStorefrontAndroid() override {
354
+ auto __result = _swiftPart.getStorefrontAndroid();
355
+ if (__result.hasError()) [[unlikely]] {
356
+ std::rethrow_exception(__result.error());
357
+ }
358
+ auto __value = std::move(__result.value());
359
+ return __value;
360
+ }
361
+ inline std::shared_ptr<Promise<void>> deepLinkToSubscriptionsAndroid(const NitroDeepLinkOptionsAndroid& options) override {
362
+ auto __result = _swiftPart.deepLinkToSubscriptionsAndroid(options);
363
+ if (__result.hasError()) [[unlikely]] {
364
+ std::rethrow_exception(__result.error());
365
+ }
366
+ auto __value = std::move(__result.value());
367
+ return __value;
368
+ }
350
369
 
351
370
  private:
352
371
  NitroIap::HybridRnIapSpec_cxx _swiftPart;
@@ -44,6 +44,8 @@ public protocol HybridRnIapSpec_protocol: HybridObject {
44
44
  func isTransactionVerifiedIOS(sku: String) throws -> Promise<Bool>
45
45
  func getTransactionJwsIOS(sku: String) throws -> Promise<String?>
46
46
  func validateReceipt(params: NitroReceiptValidationParams) throws -> Promise<Variant_NitroReceiptValidationResultIOS_NitroReceiptValidationResultAndroid>
47
+ func getStorefrontAndroid() throws -> Promise<String>
48
+ func deepLinkToSubscriptionsAndroid(options: NitroDeepLinkOptionsAndroid) throws -> Promise<Void>
47
49
  }
48
50
 
49
51
  /// See ``HybridRnIapSpec``
@@ -753,4 +753,42 @@ open class HybridRnIapSpec_cxx {
753
753
  return bridge.create_Result_std__shared_ptr_Promise_std__variant_NitroReceiptValidationResultIOS__NitroReceiptValidationResultAndroid____(__exceptionPtr)
754
754
  }
755
755
  }
756
+
757
+ @inline(__always)
758
+ public final func getStorefrontAndroid() -> bridge.Result_std__shared_ptr_Promise_std__string___ {
759
+ do {
760
+ let __result = try self.__implementation.getStorefrontAndroid()
761
+ let __resultCpp = { () -> bridge.std__shared_ptr_Promise_std__string__ in
762
+ let __promise = bridge.create_std__shared_ptr_Promise_std__string__()
763
+ let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__string__(__promise)
764
+ __result
765
+ .then({ __result in __promiseHolder.resolve(std.string(__result)) })
766
+ .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
767
+ return __promise
768
+ }()
769
+ return bridge.create_Result_std__shared_ptr_Promise_std__string___(__resultCpp)
770
+ } catch (let __error) {
771
+ let __exceptionPtr = __error.toCpp()
772
+ return bridge.create_Result_std__shared_ptr_Promise_std__string___(__exceptionPtr)
773
+ }
774
+ }
775
+
776
+ @inline(__always)
777
+ public final func deepLinkToSubscriptionsAndroid(options: NitroDeepLinkOptionsAndroid) -> bridge.Result_std__shared_ptr_Promise_void___ {
778
+ do {
779
+ let __result = try self.__implementation.deepLinkToSubscriptionsAndroid(options: options)
780
+ let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in
781
+ let __promise = bridge.create_std__shared_ptr_Promise_void__()
782
+ let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise)
783
+ __result
784
+ .then({ __result in __promiseHolder.resolve() })
785
+ .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
786
+ return __promise
787
+ }()
788
+ return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp)
789
+ } catch (let __error) {
790
+ let __exceptionPtr = __error.toCpp()
791
+ return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)
792
+ }
793
+ }
756
794
  }
@@ -0,0 +1,84 @@
1
+ ///
2
+ /// NitroDeepLinkOptionsAndroid.swift
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2025 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ import NitroModules
9
+
10
+ /**
11
+ * Represents an instance of `NitroDeepLinkOptionsAndroid`, backed by a C++ struct.
12
+ */
13
+ public typealias NitroDeepLinkOptionsAndroid = margelo.nitro.iap.NitroDeepLinkOptionsAndroid
14
+
15
+ public extension NitroDeepLinkOptionsAndroid {
16
+ private typealias bridge = margelo.nitro.iap.bridge.swift
17
+
18
+ /**
19
+ * Create a new instance of `NitroDeepLinkOptionsAndroid`.
20
+ */
21
+ init(skuAndroid: String?, packageNameAndroid: String?) {
22
+ self.init({ () -> bridge.std__optional_std__string_ in
23
+ if let __unwrappedValue = skuAndroid {
24
+ return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
25
+ } else {
26
+ return .init()
27
+ }
28
+ }(), { () -> bridge.std__optional_std__string_ in
29
+ if let __unwrappedValue = packageNameAndroid {
30
+ return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
31
+ } else {
32
+ return .init()
33
+ }
34
+ }())
35
+ }
36
+
37
+ var skuAndroid: String? {
38
+ @inline(__always)
39
+ get {
40
+ return { () -> String? in
41
+ if bridge.has_value_std__optional_std__string_(self.__skuAndroid) {
42
+ let __unwrapped = bridge.get_std__optional_std__string_(self.__skuAndroid)
43
+ return String(__unwrapped)
44
+ } else {
45
+ return nil
46
+ }
47
+ }()
48
+ }
49
+ @inline(__always)
50
+ set {
51
+ self.__skuAndroid = { () -> bridge.std__optional_std__string_ in
52
+ if let __unwrappedValue = newValue {
53
+ return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
54
+ } else {
55
+ return .init()
56
+ }
57
+ }()
58
+ }
59
+ }
60
+
61
+ var packageNameAndroid: String? {
62
+ @inline(__always)
63
+ get {
64
+ return { () -> String? in
65
+ if bridge.has_value_std__optional_std__string_(self.__packageNameAndroid) {
66
+ let __unwrapped = bridge.get_std__optional_std__string_(self.__packageNameAndroid)
67
+ return String(__unwrapped)
68
+ } else {
69
+ return nil
70
+ }
71
+ }()
72
+ }
73
+ @inline(__always)
74
+ set {
75
+ self.__packageNameAndroid = { () -> bridge.std__optional_std__string_ in
76
+ if let __unwrappedValue = newValue {
77
+ return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
78
+ } else {
79
+ return .init()
80
+ }
81
+ }()
82
+ }
83
+ }
84
+ }
@@ -44,6 +44,8 @@ namespace margelo::nitro::iap {
44
44
  prototype.registerHybridMethod("isTransactionVerifiedIOS", &HybridRnIapSpec::isTransactionVerifiedIOS);
45
45
  prototype.registerHybridMethod("getTransactionJwsIOS", &HybridRnIapSpec::getTransactionJwsIOS);
46
46
  prototype.registerHybridMethod("validateReceipt", &HybridRnIapSpec::validateReceipt);
47
+ prototype.registerHybridMethod("getStorefrontAndroid", &HybridRnIapSpec::getStorefrontAndroid);
48
+ prototype.registerHybridMethod("deepLinkToSubscriptionsAndroid", &HybridRnIapSpec::deepLinkToSubscriptionsAndroid);
47
49
  });
48
50
  }
49
51
 
@@ -33,6 +33,8 @@ namespace margelo::nitro::iap { struct NitroReceiptValidationResultIOS; }
33
33
  namespace margelo::nitro::iap { struct NitroReceiptValidationResultAndroid; }
34
34
  // Forward declaration of `NitroReceiptValidationParams` to properly resolve imports.
35
35
  namespace margelo::nitro::iap { struct NitroReceiptValidationParams; }
36
+ // Forward declaration of `NitroDeepLinkOptionsAndroid` to properly resolve imports.
37
+ namespace margelo::nitro::iap { struct NitroDeepLinkOptionsAndroid; }
36
38
 
37
39
  #include <NitroModules/Promise.hpp>
38
40
  #include "NitroProduct.hpp"
@@ -50,6 +52,7 @@ namespace margelo::nitro::iap { struct NitroReceiptValidationParams; }
50
52
  #include "NitroReceiptValidationResultIOS.hpp"
51
53
  #include "NitroReceiptValidationResultAndroid.hpp"
52
54
  #include "NitroReceiptValidationParams.hpp"
55
+ #include "NitroDeepLinkOptionsAndroid.hpp"
53
56
 
54
57
  namespace margelo::nitro::iap {
55
58
 
@@ -112,6 +115,8 @@ namespace margelo::nitro::iap {
112
115
  virtual std::shared_ptr<Promise<bool>> isTransactionVerifiedIOS(const std::string& sku) = 0;
113
116
  virtual std::shared_ptr<Promise<std::optional<std::string>>> getTransactionJwsIOS(const std::string& sku) = 0;
114
117
  virtual std::shared_ptr<Promise<std::variant<NitroReceiptValidationResultIOS, NitroReceiptValidationResultAndroid>>> validateReceipt(const NitroReceiptValidationParams& params) = 0;
118
+ virtual std::shared_ptr<Promise<std::string>> getStorefrontAndroid() = 0;
119
+ virtual std::shared_ptr<Promise<void>> deepLinkToSubscriptionsAndroid(const NitroDeepLinkOptionsAndroid& options) = 0;
115
120
 
116
121
  protected:
117
122
  // Hybrid Setup
@@ -0,0 +1,72 @@
1
+ ///
2
+ /// NitroDeepLinkOptionsAndroid.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2025 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
11
+ #include <NitroModules/JSIConverter.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
16
+ #include <NitroModules/NitroDefines.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+
21
+
22
+
23
+ #include <string>
24
+ #include <optional>
25
+
26
+ namespace margelo::nitro::iap {
27
+
28
+ /**
29
+ * A struct which can be represented as a JavaScript object (NitroDeepLinkOptionsAndroid).
30
+ */
31
+ struct NitroDeepLinkOptionsAndroid {
32
+ public:
33
+ std::optional<std::string> skuAndroid SWIFT_PRIVATE;
34
+ std::optional<std::string> packageNameAndroid SWIFT_PRIVATE;
35
+
36
+ public:
37
+ NitroDeepLinkOptionsAndroid() = default;
38
+ explicit NitroDeepLinkOptionsAndroid(std::optional<std::string> skuAndroid, std::optional<std::string> packageNameAndroid): skuAndroid(skuAndroid), packageNameAndroid(packageNameAndroid) {}
39
+ };
40
+
41
+ } // namespace margelo::nitro::iap
42
+
43
+ namespace margelo::nitro {
44
+
45
+ // C++ NitroDeepLinkOptionsAndroid <> JS NitroDeepLinkOptionsAndroid (object)
46
+ template <>
47
+ struct JSIConverter<margelo::nitro::iap::NitroDeepLinkOptionsAndroid> final {
48
+ static inline margelo::nitro::iap::NitroDeepLinkOptionsAndroid fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
49
+ jsi::Object obj = arg.asObject(runtime);
50
+ return margelo::nitro::iap::NitroDeepLinkOptionsAndroid(
51
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "skuAndroid")),
52
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "packageNameAndroid"))
53
+ );
54
+ }
55
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::iap::NitroDeepLinkOptionsAndroid& arg) {
56
+ jsi::Object obj(runtime);
57
+ obj.setProperty(runtime, "skuAndroid", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.skuAndroid));
58
+ obj.setProperty(runtime, "packageNameAndroid", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.packageNameAndroid));
59
+ return obj;
60
+ }
61
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
62
+ if (!value.isObject()) {
63
+ return false;
64
+ }
65
+ jsi::Object obj = value.getObject(runtime);
66
+ if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "skuAndroid"))) return false;
67
+ if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "packageNameAndroid"))) return false;
68
+ return true;
69
+ }
70
+ };
71
+
72
+ } // namespace margelo::nitro
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-iap",
3
- "version": "14.2.3",
3
+ "version": "14.3.1",
4
4
  "description": "React Native In-App Purchases module for iOS and Android using Nitro",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -18,12 +18,11 @@ const addLineToGradle = (content, anchor, lineToAdd, offset = 1) => {
18
18
  return lines.join('\n');
19
19
  };
20
20
  const modifyProjectBuildGradle = (gradle) => {
21
- // Add supportLibVersion to project build.gradle if not present
21
+ // Keep backward-compatible behavior: add supportLibVersion inside ext { } if missing
22
22
  if (!gradle.includes('supportLibVersion')) {
23
23
  const lines = gradle.split('\n');
24
24
  const extIndex = lines.findIndex((line) => line.trim() === 'ext {');
25
25
  if (extIndex !== -1) {
26
- // Insert supportLibVersion right after 'ext {' with proper indentation
27
26
  lines.splice(extIndex + 1, 0, 'supportLibVersion = "28.0.0"');
28
27
  return lines.join('\n');
29
28
  }
@@ -31,28 +30,32 @@ const modifyProjectBuildGradle = (gradle) => {
31
30
  return gradle;
32
31
  };
33
32
  exports.modifyProjectBuildGradle = modifyProjectBuildGradle;
33
+ const OPENIAP_COORD = 'io.github.hyochan.openiap:openiap-google';
34
+ const OPENIAP_VERSION = '1.1.0';
34
35
  const modifyAppBuildGradle = (gradle) => {
35
36
  let modified = gradle;
36
- // Add billing library dependencies to app-level build.gradle
37
- const billingDep = ` implementation "com.android.billingclient:billing-ktx:8.0.0"`;
38
- const gmsDep = ` implementation "com.google.android.gms:play-services-base:18.1.0"`;
39
- let hasAddedDependency = false;
40
- if (!modified.includes(billingDep)) {
41
- modified = addLineToGradle(modified, /dependencies\s*{/, billingDep);
42
- hasAddedDependency = true;
43
- }
44
- if (!modified.includes(gmsDep)) {
45
- modified = addLineToGradle(modified, /dependencies\s*{/, gmsDep, 1);
46
- hasAddedDependency = true;
47
- }
48
- // Log only once and only if we actually added dependencies
49
- if (hasAddedDependency && !hasLoggedPluginExecution) {
50
- console.log('🛠️ react-native-iap: Added billing dependencies to build.gradle');
37
+ // Replace legacy Billing/GMS instructions with OpenIAP Google library
38
+ // Remove any old billingclient or play-services-base lines we may have added previously
39
+ modified = modified
40
+ .replace(/^[ \t]*(implementation|api)[ \t]+["']com\.android\.billingclient:billing-ktx:[^"']+["'][ \t]*$/gim, '')
41
+ .replace(/^[ \t]*(implementation|api)[ \t]+["']com\.google\.android\.gms:play-services-base:[^"']+["'][ \t]*$/gim, '')
42
+ .replace(/\n{3,}/g, '\n\n');
43
+ const openiapDep = ` implementation "${OPENIAP_COORD}:${OPENIAP_VERSION}"`;
44
+ if (!modified.includes(OPENIAP_COORD)) {
45
+ if (!/dependencies\s*{/.test(modified)) {
46
+ modified += `\n\ndependencies {\n${openiapDep}\n}\n`;
47
+ }
48
+ else {
49
+ modified = addLineToGradle(modified, /dependencies\s*{/, openiapDep);
50
+ }
51
+ if (!hasLoggedPluginExecution) {
52
+ console.log(`🛠️ react-native-iap: Added OpenIAP (${OPENIAP_VERSION}) to build.gradle`);
53
+ }
51
54
  }
52
55
  return modified;
53
56
  };
54
57
  const withIapAndroid = (config) => {
55
- // Add IAP dependencies to app build.gradle
58
+ // Add OpenIAP dependency to app build.gradle
56
59
  config = (0, config_plugins_1.withAppBuildGradle)(config, (config) => {
57
60
  config.modResults.contents = modifyAppBuildGradle(config.modResults.contents);
58
61
  return config;
@@ -31,12 +31,11 @@ const addLineToGradle = (
31
31
  };
32
32
 
33
33
  export const modifyProjectBuildGradle = (gradle: string): string => {
34
- // Add supportLibVersion to project build.gradle if not present
34
+ // Keep backward-compatible behavior: add supportLibVersion inside ext { } if missing
35
35
  if (!gradle.includes('supportLibVersion')) {
36
36
  const lines = gradle.split('\n');
37
37
  const extIndex = lines.findIndex((line) => line.trim() === 'ext {');
38
38
  if (extIndex !== -1) {
39
- // Insert supportLibVersion right after 'ext {' with proper indentation
40
39
  lines.splice(extIndex + 1, 0, 'supportLibVersion = "28.0.0"');
41
40
  return lines.join('\n');
42
41
  }
@@ -44,36 +43,45 @@ export const modifyProjectBuildGradle = (gradle: string): string => {
44
43
  return gradle;
45
44
  };
46
45
 
46
+ const OPENIAP_COORD = 'io.github.hyochan.openiap:openiap-google';
47
+ const OPENIAP_VERSION = '1.1.0';
48
+
47
49
  const modifyAppBuildGradle = (gradle: string): string => {
48
50
  let modified = gradle;
49
51
 
50
- // Add billing library dependencies to app-level build.gradle
51
- const billingDep = ` implementation "com.android.billingclient:billing-ktx:8.0.0"`;
52
- const gmsDep = ` implementation "com.google.android.gms:play-services-base:18.1.0"`;
53
-
54
- let hasAddedDependency = false;
55
-
56
- if (!modified.includes(billingDep)) {
57
- modified = addLineToGradle(modified, /dependencies\s*{/, billingDep);
58
- hasAddedDependency = true;
59
- }
60
- if (!modified.includes(gmsDep)) {
61
- modified = addLineToGradle(modified, /dependencies\s*{/, gmsDep, 1);
62
- hasAddedDependency = true;
63
- }
64
-
65
- // Log only once and only if we actually added dependencies
66
- if (hasAddedDependency && !hasLoggedPluginExecution) {
67
- console.log(
68
- '🛠️ react-native-iap: Added billing dependencies to build.gradle',
69
- );
52
+ // Replace legacy Billing/GMS instructions with OpenIAP Google library
53
+ // Remove any old billingclient or play-services-base lines we may have added previously
54
+ modified = modified
55
+ .replace(
56
+ /^[ \t]*(implementation|api)[ \t]+["']com\.android\.billingclient:billing-ktx:[^"']+["'][ \t]*$/gim,
57
+ '',
58
+ )
59
+ .replace(
60
+ /^[ \t]*(implementation|api)[ \t]+["']com\.google\.android\.gms:play-services-base:[^"']+["'][ \t]*$/gim,
61
+ '',
62
+ )
63
+ .replace(/\n{3,}/g, '\n\n');
64
+
65
+ const openiapDep = ` implementation "${OPENIAP_COORD}:${OPENIAP_VERSION}"`;
66
+
67
+ if (!modified.includes(OPENIAP_COORD)) {
68
+ if (!/dependencies\s*{/.test(modified)) {
69
+ modified += `\n\ndependencies {\n${openiapDep}\n}\n`;
70
+ } else {
71
+ modified = addLineToGradle(modified, /dependencies\s*{/, openiapDep);
72
+ }
73
+ if (!hasLoggedPluginExecution) {
74
+ console.log(
75
+ `🛠️ react-native-iap: Added OpenIAP (${OPENIAP_VERSION}) to build.gradle`,
76
+ );
77
+ }
70
78
  }
71
79
 
72
80
  return modified;
73
81
  };
74
82
 
75
83
  const withIapAndroid: ConfigPlugin = (config) => {
76
- // Add IAP dependencies to app build.gradle
84
+ // Add OpenIAP dependency to app build.gradle
77
85
  config = withAppBuildGradle(config, (config) => {
78
86
  config.modResults.contents = modifyAppBuildGradle(
79
87
  config.modResults.contents,
@@ -29,11 +29,8 @@ export const getActiveSubscriptions = async (
29
29
  productId: purchase.productId,
30
30
  isActive: true, // If it's in availablePurchases, it's active
31
31
  // Backend validation fields
32
- transactionId: purchase.transactionId || purchase.id,
33
- purchaseToken:
34
- androidPurchase.purchaseToken ||
35
- androidPurchase.purchaseTokenAndroid ||
36
- iosPurchase.purchaseToken,
32
+ transactionId: purchase.id,
33
+ purchaseToken: purchase.purchaseToken,
37
34
  transactionDate: purchase.transactionDate,
38
35
  // Platform-specific fields
39
36
  expirationDateIOS: iosPurchase.expirationDateIOS