react-native-iap 14.4.11 → 14.4.12

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 (76) hide show
  1. package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +159 -10
  2. package/ios/HybridRnIap.swift +115 -2
  3. package/lib/module/hooks/useIAP.js +24 -3
  4. package/lib/module/hooks/useIAP.js.map +1 -1
  5. package/lib/module/index.js +275 -2
  6. package/lib/module/index.js.map +1 -1
  7. package/lib/module/types.js +18 -0
  8. package/lib/module/types.js.map +1 -1
  9. package/lib/typescript/plugin/src/withIAP.d.ts +27 -0
  10. package/lib/typescript/plugin/src/withIAP.d.ts.map +1 -1
  11. package/lib/typescript/src/hooks/useIAP.d.ts +6 -1
  12. package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
  13. package/lib/typescript/src/index.d.ts +133 -0
  14. package/lib/typescript/src/index.d.ts.map +1 -1
  15. package/lib/typescript/src/specs/RnIap.nitro.d.ts +72 -2
  16. package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
  17. package/lib/typescript/src/types.d.ts +116 -13
  18. package/lib/typescript/src/types.d.ts.map +1 -1
  19. package/nitrogen/generated/android/NitroIapOnLoad.cpp +2 -0
  20. package/nitrogen/generated/android/c++/JAlternativeBillingModeAndroid.hpp +62 -0
  21. package/nitrogen/generated/android/c++/JExternalPurchaseLinkResultIOS.hpp +58 -0
  22. package/nitrogen/generated/android/c++/JExternalPurchaseNoticeAction.hpp +59 -0
  23. package/nitrogen/generated/android/c++/JExternalPurchaseNoticeResultIOS.hpp +60 -0
  24. package/nitrogen/generated/android/c++/JFunc_void_UserChoiceBillingDetails.hpp +78 -0
  25. package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +132 -3
  26. package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +9 -1
  27. package/nitrogen/generated/android/c++/JInitConnectionConfig.hpp +55 -0
  28. package/nitrogen/generated/android/c++/JPurchaseAndroid.hpp +4 -0
  29. package/nitrogen/generated/android/c++/JPurchaseIOS.hpp +4 -0
  30. package/nitrogen/generated/android/c++/JUserChoiceBillingDetails.hpp +75 -0
  31. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/AlternativeBillingModeAndroid.kt +22 -0
  32. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/ExternalPurchaseLinkResultIOS.kt +32 -0
  33. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/ExternalPurchaseNoticeAction.kt +21 -0
  34. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/ExternalPurchaseNoticeResultIOS.kt +32 -0
  35. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Func_void_UserChoiceBillingDetails.kt +81 -0
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +43 -1
  37. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/InitConnectionConfig.kt +29 -0
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseAndroid.kt +3 -0
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseIOS.kt +3 -0
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/UserChoiceBillingDetails.kt +32 -0
  41. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.cpp +24 -0
  42. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.hpp +156 -0
  43. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +18 -0
  44. package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +81 -3
  45. package/nitrogen/generated/ios/swift/AlternativeBillingModeAndroid.swift +44 -0
  46. package/nitrogen/generated/ios/swift/ExternalPurchaseLinkResultIOS.swift +65 -0
  47. package/nitrogen/generated/ios/swift/ExternalPurchaseNoticeAction.swift +40 -0
  48. package/nitrogen/generated/ios/swift/ExternalPurchaseNoticeResultIOS.swift +65 -0
  49. package/nitrogen/generated/ios/swift/Func_void_ExternalPurchaseLinkResultIOS.swift +47 -0
  50. package/nitrogen/generated/ios/swift/Func_void_ExternalPurchaseNoticeResultIOS.swift +47 -0
  51. package/nitrogen/generated/ios/swift/Func_void_UserChoiceBillingDetails.swift +47 -0
  52. package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +9 -1
  53. package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +168 -2
  54. package/nitrogen/generated/ios/swift/InitConnectionConfig.swift +47 -0
  55. package/nitrogen/generated/ios/swift/PurchaseAndroid.swift +31 -1
  56. package/nitrogen/generated/ios/swift/PurchaseIOS.swift +31 -1
  57. package/nitrogen/generated/ios/swift/UserChoiceBillingDetails.swift +58 -0
  58. package/nitrogen/generated/shared/c++/AlternativeBillingModeAndroid.hpp +80 -0
  59. package/nitrogen/generated/shared/c++/ExternalPurchaseLinkResultIOS.hpp +72 -0
  60. package/nitrogen/generated/shared/c++/ExternalPurchaseNoticeAction.hpp +76 -0
  61. package/nitrogen/generated/shared/c++/ExternalPurchaseNoticeResultIOS.hpp +74 -0
  62. package/nitrogen/generated/shared/c++/HybridRnIapSpec.cpp +8 -0
  63. package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +22 -2
  64. package/nitrogen/generated/shared/c++/InitConnectionConfig.hpp +69 -0
  65. package/nitrogen/generated/shared/c++/PurchaseAndroid.hpp +5 -1
  66. package/nitrogen/generated/shared/c++/PurchaseIOS.hpp +5 -1
  67. package/nitrogen/generated/shared/c++/UserChoiceBillingDetails.hpp +72 -0
  68. package/openiap-versions.json +3 -3
  69. package/package.json +1 -1
  70. package/plugin/build/withIAP.d.ts +27 -0
  71. package/plugin/build/withIAP.js +91 -1
  72. package/plugin/src/withIAP.ts +162 -0
  73. package/src/hooks/useIAP.ts +47 -1
  74. package/src/index.ts +313 -2
  75. package/src/specs/RnIap.nitro.ts +99 -1
  76. package/src/types.ts +124 -13
@@ -0,0 +1,76 @@
1
+ ///
2
+ /// ExternalPurchaseNoticeAction.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/NitroHash.hpp>)
11
+ #include <NitroModules/NitroHash.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
16
+ #include <NitroModules/JSIConverter.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
21
+ #include <NitroModules/NitroDefines.hpp>
22
+ #else
23
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24
+ #endif
25
+
26
+ namespace margelo::nitro::iap {
27
+
28
+ /**
29
+ * An enum which can be represented as a JavaScript union (ExternalPurchaseNoticeAction).
30
+ */
31
+ enum class ExternalPurchaseNoticeAction {
32
+ CONTINUE SWIFT_NAME(continue) = 0,
33
+ DISMISSED SWIFT_NAME(dismissed) = 1,
34
+ } CLOSED_ENUM;
35
+
36
+ } // namespace margelo::nitro::iap
37
+
38
+ namespace margelo::nitro {
39
+
40
+ // C++ ExternalPurchaseNoticeAction <> JS ExternalPurchaseNoticeAction (union)
41
+ template <>
42
+ struct JSIConverter<margelo::nitro::iap::ExternalPurchaseNoticeAction> final {
43
+ static inline margelo::nitro::iap::ExternalPurchaseNoticeAction fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
44
+ std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);
45
+ switch (hashString(unionValue.c_str(), unionValue.size())) {
46
+ case hashString("continue"): return margelo::nitro::iap::ExternalPurchaseNoticeAction::CONTINUE;
47
+ case hashString("dismissed"): return margelo::nitro::iap::ExternalPurchaseNoticeAction::DISMISSED;
48
+ default: [[unlikely]]
49
+ throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum ExternalPurchaseNoticeAction - invalid value!");
50
+ }
51
+ }
52
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::iap::ExternalPurchaseNoticeAction arg) {
53
+ switch (arg) {
54
+ case margelo::nitro::iap::ExternalPurchaseNoticeAction::CONTINUE: return JSIConverter<std::string>::toJSI(runtime, "continue");
55
+ case margelo::nitro::iap::ExternalPurchaseNoticeAction::DISMISSED: return JSIConverter<std::string>::toJSI(runtime, "dismissed");
56
+ default: [[unlikely]]
57
+ throw std::invalid_argument("Cannot convert ExternalPurchaseNoticeAction to JS - invalid value: "
58
+ + std::to_string(static_cast<int>(arg)) + "!");
59
+ }
60
+ }
61
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
62
+ if (!value.isString()) {
63
+ return false;
64
+ }
65
+ std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);
66
+ switch (hashString(unionValue.c_str(), unionValue.size())) {
67
+ case hashString("continue"):
68
+ case hashString("dismissed"):
69
+ return true;
70
+ default:
71
+ return false;
72
+ }
73
+ }
74
+ };
75
+
76
+ } // namespace margelo::nitro
@@ -0,0 +1,74 @@
1
+ ///
2
+ /// ExternalPurchaseNoticeResultIOS.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
+ // Forward declaration of `ExternalPurchaseNoticeAction` to properly resolve imports.
22
+ namespace margelo::nitro::iap { enum class ExternalPurchaseNoticeAction; }
23
+
24
+ #include <string>
25
+ #include <optional>
26
+ #include "ExternalPurchaseNoticeAction.hpp"
27
+
28
+ namespace margelo::nitro::iap {
29
+
30
+ /**
31
+ * A struct which can be represented as a JavaScript object (ExternalPurchaseNoticeResultIOS).
32
+ */
33
+ struct ExternalPurchaseNoticeResultIOS {
34
+ public:
35
+ std::optional<std::string> error SWIFT_PRIVATE;
36
+ ExternalPurchaseNoticeAction result SWIFT_PRIVATE;
37
+
38
+ public:
39
+ ExternalPurchaseNoticeResultIOS() = default;
40
+ explicit ExternalPurchaseNoticeResultIOS(std::optional<std::string> error, ExternalPurchaseNoticeAction result): error(error), result(result) {}
41
+ };
42
+
43
+ } // namespace margelo::nitro::iap
44
+
45
+ namespace margelo::nitro {
46
+
47
+ // C++ ExternalPurchaseNoticeResultIOS <> JS ExternalPurchaseNoticeResultIOS (object)
48
+ template <>
49
+ struct JSIConverter<margelo::nitro::iap::ExternalPurchaseNoticeResultIOS> final {
50
+ static inline margelo::nitro::iap::ExternalPurchaseNoticeResultIOS fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
51
+ jsi::Object obj = arg.asObject(runtime);
52
+ return margelo::nitro::iap::ExternalPurchaseNoticeResultIOS(
53
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "error")),
54
+ JSIConverter<margelo::nitro::iap::ExternalPurchaseNoticeAction>::fromJSI(runtime, obj.getProperty(runtime, "result"))
55
+ );
56
+ }
57
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::iap::ExternalPurchaseNoticeResultIOS& arg) {
58
+ jsi::Object obj(runtime);
59
+ obj.setProperty(runtime, "error", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.error));
60
+ obj.setProperty(runtime, "result", JSIConverter<margelo::nitro::iap::ExternalPurchaseNoticeAction>::toJSI(runtime, arg.result));
61
+ return obj;
62
+ }
63
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
64
+ if (!value.isObject()) {
65
+ return false;
66
+ }
67
+ jsi::Object obj = value.getObject(runtime);
68
+ if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "error"))) return false;
69
+ if (!JSIConverter<margelo::nitro::iap::ExternalPurchaseNoticeAction>::canConvert(runtime, obj.getProperty(runtime, "result"))) return false;
70
+ return true;
71
+ }
72
+ };
73
+
74
+ } // namespace margelo::nitro
@@ -50,6 +50,14 @@ namespace margelo::nitro::iap {
50
50
  prototype.registerHybridMethod("validateReceipt", &HybridRnIapSpec::validateReceipt);
51
51
  prototype.registerHybridMethod("getStorefront", &HybridRnIapSpec::getStorefront);
52
52
  prototype.registerHybridMethod("deepLinkToSubscriptionsAndroid", &HybridRnIapSpec::deepLinkToSubscriptionsAndroid);
53
+ prototype.registerHybridMethod("checkAlternativeBillingAvailabilityAndroid", &HybridRnIapSpec::checkAlternativeBillingAvailabilityAndroid);
54
+ prototype.registerHybridMethod("showAlternativeBillingDialogAndroid", &HybridRnIapSpec::showAlternativeBillingDialogAndroid);
55
+ prototype.registerHybridMethod("createAlternativeBillingTokenAndroid", &HybridRnIapSpec::createAlternativeBillingTokenAndroid);
56
+ prototype.registerHybridMethod("addUserChoiceBillingListenerAndroid", &HybridRnIapSpec::addUserChoiceBillingListenerAndroid);
57
+ prototype.registerHybridMethod("removeUserChoiceBillingListenerAndroid", &HybridRnIapSpec::removeUserChoiceBillingListenerAndroid);
58
+ prototype.registerHybridMethod("canPresentExternalPurchaseNoticeIOS", &HybridRnIapSpec::canPresentExternalPurchaseNoticeIOS);
59
+ prototype.registerHybridMethod("presentExternalPurchaseNoticeSheetIOS", &HybridRnIapSpec::presentExternalPurchaseNoticeSheetIOS);
60
+ prototype.registerHybridMethod("presentExternalPurchaseLinkIOS", &HybridRnIapSpec::presentExternalPurchaseLinkIOS);
53
61
  });
54
62
  }
55
63
 
@@ -13,6 +13,8 @@
13
13
  #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
14
  #endif
15
15
 
16
+ // Forward declaration of `InitConnectionConfig` to properly resolve imports.
17
+ namespace margelo::nitro::iap { struct InitConnectionConfig; }
16
18
  // Forward declaration of `NitroProduct` to properly resolve imports.
17
19
  namespace margelo::nitro::iap { struct NitroProduct; }
18
20
  // Forward declaration of `PurchaseAndroid` to properly resolve imports.
@@ -39,15 +41,22 @@ namespace margelo::nitro::iap { struct NitroReceiptValidationResultAndroid; }
39
41
  namespace margelo::nitro::iap { struct NitroReceiptValidationParams; }
40
42
  // Forward declaration of `NitroDeepLinkOptionsAndroid` to properly resolve imports.
41
43
  namespace margelo::nitro::iap { struct NitroDeepLinkOptionsAndroid; }
44
+ // Forward declaration of `UserChoiceBillingDetails` to properly resolve imports.
45
+ namespace margelo::nitro::iap { struct UserChoiceBillingDetails; }
46
+ // Forward declaration of `ExternalPurchaseNoticeResultIOS` to properly resolve imports.
47
+ namespace margelo::nitro::iap { struct ExternalPurchaseNoticeResultIOS; }
48
+ // Forward declaration of `ExternalPurchaseLinkResultIOS` to properly resolve imports.
49
+ namespace margelo::nitro::iap { struct ExternalPurchaseLinkResultIOS; }
42
50
 
43
51
  #include <NitroModules/Promise.hpp>
52
+ #include "InitConnectionConfig.hpp"
53
+ #include <optional>
44
54
  #include "NitroProduct.hpp"
45
55
  #include <vector>
46
56
  #include <string>
47
57
  #include "PurchaseAndroid.hpp"
48
58
  #include "PurchaseIOS.hpp"
49
59
  #include <variant>
50
- #include <optional>
51
60
  #include "NitroPurchaseRequest.hpp"
52
61
  #include "NitroPurchase.hpp"
53
62
  #include "NitroAvailablePurchasesOptions.hpp"
@@ -59,6 +68,9 @@ namespace margelo::nitro::iap { struct NitroDeepLinkOptionsAndroid; }
59
68
  #include "NitroReceiptValidationResultAndroid.hpp"
60
69
  #include "NitroReceiptValidationParams.hpp"
61
70
  #include "NitroDeepLinkOptionsAndroid.hpp"
71
+ #include "UserChoiceBillingDetails.hpp"
72
+ #include "ExternalPurchaseNoticeResultIOS.hpp"
73
+ #include "ExternalPurchaseLinkResultIOS.hpp"
62
74
 
63
75
  namespace margelo::nitro::iap {
64
76
 
@@ -91,7 +103,7 @@ namespace margelo::nitro::iap {
91
103
 
92
104
  public:
93
105
  // Methods
94
- virtual std::shared_ptr<Promise<bool>> initConnection() = 0;
106
+ virtual std::shared_ptr<Promise<bool>> initConnection(const std::optional<InitConnectionConfig>& config) = 0;
95
107
  virtual std::shared_ptr<Promise<bool>> endConnection() = 0;
96
108
  virtual std::shared_ptr<Promise<std::vector<NitroProduct>>> fetchProducts(const std::vector<std::string>& skus, const std::string& type) = 0;
97
109
  virtual std::shared_ptr<Promise<std::optional<std::variant<PurchaseAndroid, PurchaseIOS, std::vector<std::variant<PurchaseAndroid, PurchaseIOS>>>>>> requestPurchase(const NitroPurchaseRequest& request) = 0;
@@ -127,6 +139,14 @@ namespace margelo::nitro::iap {
127
139
  virtual std::shared_ptr<Promise<std::variant<NitroReceiptValidationResultIOS, NitroReceiptValidationResultAndroid>>> validateReceipt(const NitroReceiptValidationParams& params) = 0;
128
140
  virtual std::shared_ptr<Promise<std::string>> getStorefront() = 0;
129
141
  virtual std::shared_ptr<Promise<void>> deepLinkToSubscriptionsAndroid(const NitroDeepLinkOptionsAndroid& options) = 0;
142
+ virtual std::shared_ptr<Promise<bool>> checkAlternativeBillingAvailabilityAndroid() = 0;
143
+ virtual std::shared_ptr<Promise<bool>> showAlternativeBillingDialogAndroid() = 0;
144
+ virtual std::shared_ptr<Promise<std::optional<std::string>>> createAlternativeBillingTokenAndroid(const std::optional<std::string>& sku) = 0;
145
+ virtual void addUserChoiceBillingListenerAndroid(const std::function<void(const UserChoiceBillingDetails& /* details */)>& listener) = 0;
146
+ virtual void removeUserChoiceBillingListenerAndroid(const std::function<void(const UserChoiceBillingDetails& /* details */)>& listener) = 0;
147
+ virtual std::shared_ptr<Promise<bool>> canPresentExternalPurchaseNoticeIOS() = 0;
148
+ virtual std::shared_ptr<Promise<ExternalPurchaseNoticeResultIOS>> presentExternalPurchaseNoticeSheetIOS() = 0;
149
+ virtual std::shared_ptr<Promise<ExternalPurchaseLinkResultIOS>> presentExternalPurchaseLinkIOS(const std::string& url) = 0;
130
150
 
131
151
  protected:
132
152
  // Hybrid Setup
@@ -0,0 +1,69 @@
1
+ ///
2
+ /// InitConnectionConfig.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
+ // Forward declaration of `AlternativeBillingModeAndroid` to properly resolve imports.
22
+ namespace margelo::nitro::iap { enum class AlternativeBillingModeAndroid; }
23
+
24
+ #include "AlternativeBillingModeAndroid.hpp"
25
+ #include <optional>
26
+
27
+ namespace margelo::nitro::iap {
28
+
29
+ /**
30
+ * A struct which can be represented as a JavaScript object (InitConnectionConfig).
31
+ */
32
+ struct InitConnectionConfig {
33
+ public:
34
+ std::optional<AlternativeBillingModeAndroid> alternativeBillingModeAndroid SWIFT_PRIVATE;
35
+
36
+ public:
37
+ InitConnectionConfig() = default;
38
+ explicit InitConnectionConfig(std::optional<AlternativeBillingModeAndroid> alternativeBillingModeAndroid): alternativeBillingModeAndroid(alternativeBillingModeAndroid) {}
39
+ };
40
+
41
+ } // namespace margelo::nitro::iap
42
+
43
+ namespace margelo::nitro {
44
+
45
+ // C++ InitConnectionConfig <> JS InitConnectionConfig (object)
46
+ template <>
47
+ struct JSIConverter<margelo::nitro::iap::InitConnectionConfig> final {
48
+ static inline margelo::nitro::iap::InitConnectionConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
49
+ jsi::Object obj = arg.asObject(runtime);
50
+ return margelo::nitro::iap::InitConnectionConfig(
51
+ JSIConverter<std::optional<margelo::nitro::iap::AlternativeBillingModeAndroid>>::fromJSI(runtime, obj.getProperty(runtime, "alternativeBillingModeAndroid"))
52
+ );
53
+ }
54
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::iap::InitConnectionConfig& arg) {
55
+ jsi::Object obj(runtime);
56
+ obj.setProperty(runtime, "alternativeBillingModeAndroid", JSIConverter<std::optional<margelo::nitro::iap::AlternativeBillingModeAndroid>>::toJSI(runtime, arg.alternativeBillingModeAndroid));
57
+ return obj;
58
+ }
59
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
60
+ if (!value.isObject()) {
61
+ return false;
62
+ }
63
+ jsi::Object obj = value.getObject(runtime);
64
+ if (!JSIConverter<std::optional<margelo::nitro::iap::AlternativeBillingModeAndroid>>::canConvert(runtime, obj.getProperty(runtime, "alternativeBillingModeAndroid"))) return false;
65
+ return true;
66
+ }
67
+ };
68
+
69
+ } // namespace margelo::nitro
@@ -37,6 +37,7 @@ namespace margelo::nitro::iap {
37
37
  struct PurchaseAndroid {
38
38
  public:
39
39
  std::optional<bool> autoRenewingAndroid SWIFT_PRIVATE;
40
+ std::optional<std::string> currentPlanId SWIFT_PRIVATE;
40
41
  std::optional<std::string> dataAndroid SWIFT_PRIVATE;
41
42
  std::optional<std::string> developerPayloadAndroid SWIFT_PRIVATE;
42
43
  std::string id SWIFT_PRIVATE;
@@ -57,7 +58,7 @@ namespace margelo::nitro::iap {
57
58
 
58
59
  public:
59
60
  PurchaseAndroid() = default;
60
- explicit PurchaseAndroid(std::optional<bool> autoRenewingAndroid, std::optional<std::string> dataAndroid, std::optional<std::string> developerPayloadAndroid, std::string id, std::optional<std::vector<std::string>> ids, std::optional<bool> isAcknowledgedAndroid, bool isAutoRenewing, std::optional<std::string> obfuscatedAccountIdAndroid, std::optional<std::string> obfuscatedProfileIdAndroid, std::optional<std::string> packageNameAndroid, IapPlatform platform, std::string productId, PurchaseState purchaseState, std::optional<std::string> purchaseToken, double quantity, std::optional<std::string> signatureAndroid, double transactionDate, std::optional<std::string> transactionId): autoRenewingAndroid(autoRenewingAndroid), dataAndroid(dataAndroid), developerPayloadAndroid(developerPayloadAndroid), id(id), ids(ids), isAcknowledgedAndroid(isAcknowledgedAndroid), isAutoRenewing(isAutoRenewing), obfuscatedAccountIdAndroid(obfuscatedAccountIdAndroid), obfuscatedProfileIdAndroid(obfuscatedProfileIdAndroid), packageNameAndroid(packageNameAndroid), platform(platform), productId(productId), purchaseState(purchaseState), purchaseToken(purchaseToken), quantity(quantity), signatureAndroid(signatureAndroid), transactionDate(transactionDate), transactionId(transactionId) {}
61
+ explicit PurchaseAndroid(std::optional<bool> autoRenewingAndroid, std::optional<std::string> currentPlanId, std::optional<std::string> dataAndroid, std::optional<std::string> developerPayloadAndroid, std::string id, std::optional<std::vector<std::string>> ids, std::optional<bool> isAcknowledgedAndroid, bool isAutoRenewing, std::optional<std::string> obfuscatedAccountIdAndroid, std::optional<std::string> obfuscatedProfileIdAndroid, std::optional<std::string> packageNameAndroid, IapPlatform platform, std::string productId, PurchaseState purchaseState, std::optional<std::string> purchaseToken, double quantity, std::optional<std::string> signatureAndroid, double transactionDate, std::optional<std::string> transactionId): autoRenewingAndroid(autoRenewingAndroid), currentPlanId(currentPlanId), dataAndroid(dataAndroid), developerPayloadAndroid(developerPayloadAndroid), id(id), ids(ids), isAcknowledgedAndroid(isAcknowledgedAndroid), isAutoRenewing(isAutoRenewing), obfuscatedAccountIdAndroid(obfuscatedAccountIdAndroid), obfuscatedProfileIdAndroid(obfuscatedProfileIdAndroid), packageNameAndroid(packageNameAndroid), platform(platform), productId(productId), purchaseState(purchaseState), purchaseToken(purchaseToken), quantity(quantity), signatureAndroid(signatureAndroid), transactionDate(transactionDate), transactionId(transactionId) {}
61
62
  };
62
63
 
63
64
  } // namespace margelo::nitro::iap
@@ -71,6 +72,7 @@ namespace margelo::nitro {
71
72
  jsi::Object obj = arg.asObject(runtime);
72
73
  return margelo::nitro::iap::PurchaseAndroid(
73
74
  JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, "autoRenewingAndroid")),
75
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "currentPlanId")),
74
76
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "dataAndroid")),
75
77
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "developerPayloadAndroid")),
76
78
  JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, "id")),
@@ -93,6 +95,7 @@ namespace margelo::nitro {
93
95
  static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::iap::PurchaseAndroid& arg) {
94
96
  jsi::Object obj(runtime);
95
97
  obj.setProperty(runtime, "autoRenewingAndroid", JSIConverter<std::optional<bool>>::toJSI(runtime, arg.autoRenewingAndroid));
98
+ obj.setProperty(runtime, "currentPlanId", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.currentPlanId));
96
99
  obj.setProperty(runtime, "dataAndroid", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.dataAndroid));
97
100
  obj.setProperty(runtime, "developerPayloadAndroid", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.developerPayloadAndroid));
98
101
  obj.setProperty(runtime, "id", JSIConverter<std::string>::toJSI(runtime, arg.id));
@@ -118,6 +121,7 @@ namespace margelo::nitro {
118
121
  }
119
122
  jsi::Object obj = value.getObject(runtime);
120
123
  if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, "autoRenewingAndroid"))) return false;
124
+ if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "currentPlanId"))) return false;
121
125
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "dataAndroid"))) return false;
122
126
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "developerPayloadAndroid"))) return false;
123
127
  if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, "id"))) return false;
@@ -44,6 +44,7 @@ namespace margelo::nitro::iap {
44
44
  std::optional<std::string> countryCodeIOS SWIFT_PRIVATE;
45
45
  std::optional<std::string> currencyCodeIOS SWIFT_PRIVATE;
46
46
  std::optional<std::string> currencySymbolIOS SWIFT_PRIVATE;
47
+ std::optional<std::string> currentPlanId SWIFT_PRIVATE;
47
48
  std::optional<std::string> environmentIOS SWIFT_PRIVATE;
48
49
  std::optional<double> expirationDateIOS SWIFT_PRIVATE;
49
50
  std::string id SWIFT_PRIVATE;
@@ -73,7 +74,7 @@ namespace margelo::nitro::iap {
73
74
 
74
75
  public:
75
76
  PurchaseIOS() = default;
76
- explicit PurchaseIOS(std::optional<std::string> appAccountToken, std::optional<std::string> appBundleIdIOS, std::optional<std::string> countryCodeIOS, std::optional<std::string> currencyCodeIOS, std::optional<std::string> currencySymbolIOS, std::optional<std::string> environmentIOS, std::optional<double> expirationDateIOS, std::string id, std::optional<std::vector<std::string>> ids, bool isAutoRenewing, std::optional<bool> isUpgradedIOS, std::optional<PurchaseOfferIOS> offerIOS, std::optional<double> originalTransactionDateIOS, std::optional<std::string> originalTransactionIdentifierIOS, std::optional<std::string> ownershipTypeIOS, IapPlatform platform, std::string productId, PurchaseState purchaseState, std::optional<std::string> purchaseToken, double quantity, std::optional<double> quantityIOS, std::optional<std::string> reasonIOS, std::optional<std::string> reasonStringRepresentationIOS, std::optional<double> revocationDateIOS, std::optional<std::string> revocationReasonIOS, std::optional<std::string> storefrontCountryCodeIOS, std::optional<std::string> subscriptionGroupIdIOS, double transactionDate, std::string transactionId, std::optional<std::string> transactionReasonIOS, std::optional<std::string> webOrderLineItemIdIOS): appAccountToken(appAccountToken), appBundleIdIOS(appBundleIdIOS), countryCodeIOS(countryCodeIOS), currencyCodeIOS(currencyCodeIOS), currencySymbolIOS(currencySymbolIOS), environmentIOS(environmentIOS), expirationDateIOS(expirationDateIOS), id(id), ids(ids), isAutoRenewing(isAutoRenewing), isUpgradedIOS(isUpgradedIOS), offerIOS(offerIOS), originalTransactionDateIOS(originalTransactionDateIOS), originalTransactionIdentifierIOS(originalTransactionIdentifierIOS), ownershipTypeIOS(ownershipTypeIOS), platform(platform), productId(productId), purchaseState(purchaseState), purchaseToken(purchaseToken), quantity(quantity), quantityIOS(quantityIOS), reasonIOS(reasonIOS), reasonStringRepresentationIOS(reasonStringRepresentationIOS), revocationDateIOS(revocationDateIOS), revocationReasonIOS(revocationReasonIOS), storefrontCountryCodeIOS(storefrontCountryCodeIOS), subscriptionGroupIdIOS(subscriptionGroupIdIOS), transactionDate(transactionDate), transactionId(transactionId), transactionReasonIOS(transactionReasonIOS), webOrderLineItemIdIOS(webOrderLineItemIdIOS) {}
77
+ explicit PurchaseIOS(std::optional<std::string> appAccountToken, std::optional<std::string> appBundleIdIOS, std::optional<std::string> countryCodeIOS, std::optional<std::string> currencyCodeIOS, std::optional<std::string> currencySymbolIOS, std::optional<std::string> currentPlanId, std::optional<std::string> environmentIOS, std::optional<double> expirationDateIOS, std::string id, std::optional<std::vector<std::string>> ids, bool isAutoRenewing, std::optional<bool> isUpgradedIOS, std::optional<PurchaseOfferIOS> offerIOS, std::optional<double> originalTransactionDateIOS, std::optional<std::string> originalTransactionIdentifierIOS, std::optional<std::string> ownershipTypeIOS, IapPlatform platform, std::string productId, PurchaseState purchaseState, std::optional<std::string> purchaseToken, double quantity, std::optional<double> quantityIOS, std::optional<std::string> reasonIOS, std::optional<std::string> reasonStringRepresentationIOS, std::optional<double> revocationDateIOS, std::optional<std::string> revocationReasonIOS, std::optional<std::string> storefrontCountryCodeIOS, std::optional<std::string> subscriptionGroupIdIOS, double transactionDate, std::string transactionId, std::optional<std::string> transactionReasonIOS, std::optional<std::string> webOrderLineItemIdIOS): appAccountToken(appAccountToken), appBundleIdIOS(appBundleIdIOS), countryCodeIOS(countryCodeIOS), currencyCodeIOS(currencyCodeIOS), currencySymbolIOS(currencySymbolIOS), currentPlanId(currentPlanId), environmentIOS(environmentIOS), expirationDateIOS(expirationDateIOS), id(id), ids(ids), isAutoRenewing(isAutoRenewing), isUpgradedIOS(isUpgradedIOS), offerIOS(offerIOS), originalTransactionDateIOS(originalTransactionDateIOS), originalTransactionIdentifierIOS(originalTransactionIdentifierIOS), ownershipTypeIOS(ownershipTypeIOS), platform(platform), productId(productId), purchaseState(purchaseState), purchaseToken(purchaseToken), quantity(quantity), quantityIOS(quantityIOS), reasonIOS(reasonIOS), reasonStringRepresentationIOS(reasonStringRepresentationIOS), revocationDateIOS(revocationDateIOS), revocationReasonIOS(revocationReasonIOS), storefrontCountryCodeIOS(storefrontCountryCodeIOS), subscriptionGroupIdIOS(subscriptionGroupIdIOS), transactionDate(transactionDate), transactionId(transactionId), transactionReasonIOS(transactionReasonIOS), webOrderLineItemIdIOS(webOrderLineItemIdIOS) {}
77
78
  };
78
79
 
79
80
  } // namespace margelo::nitro::iap
@@ -91,6 +92,7 @@ namespace margelo::nitro {
91
92
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "countryCodeIOS")),
92
93
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "currencyCodeIOS")),
93
94
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "currencySymbolIOS")),
95
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "currentPlanId")),
94
96
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "environmentIOS")),
95
97
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "expirationDateIOS")),
96
98
  JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, "id")),
@@ -126,6 +128,7 @@ namespace margelo::nitro {
126
128
  obj.setProperty(runtime, "countryCodeIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.countryCodeIOS));
127
129
  obj.setProperty(runtime, "currencyCodeIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.currencyCodeIOS));
128
130
  obj.setProperty(runtime, "currencySymbolIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.currencySymbolIOS));
131
+ obj.setProperty(runtime, "currentPlanId", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.currentPlanId));
129
132
  obj.setProperty(runtime, "environmentIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.environmentIOS));
130
133
  obj.setProperty(runtime, "expirationDateIOS", JSIConverter<std::optional<double>>::toJSI(runtime, arg.expirationDateIOS));
131
134
  obj.setProperty(runtime, "id", JSIConverter<std::string>::toJSI(runtime, arg.id));
@@ -164,6 +167,7 @@ namespace margelo::nitro {
164
167
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "countryCodeIOS"))) return false;
165
168
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "currencyCodeIOS"))) return false;
166
169
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "currencySymbolIOS"))) return false;
170
+ if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "currentPlanId"))) return false;
167
171
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "environmentIOS"))) return false;
168
172
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "expirationDateIOS"))) return false;
169
173
  if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, "id"))) return false;
@@ -0,0 +1,72 @@
1
+ ///
2
+ /// UserChoiceBillingDetails.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 <vector>
25
+
26
+ namespace margelo::nitro::iap {
27
+
28
+ /**
29
+ * A struct which can be represented as a JavaScript object (UserChoiceBillingDetails).
30
+ */
31
+ struct UserChoiceBillingDetails {
32
+ public:
33
+ std::string externalTransactionToken SWIFT_PRIVATE;
34
+ std::vector<std::string> products SWIFT_PRIVATE;
35
+
36
+ public:
37
+ UserChoiceBillingDetails() = default;
38
+ explicit UserChoiceBillingDetails(std::string externalTransactionToken, std::vector<std::string> products): externalTransactionToken(externalTransactionToken), products(products) {}
39
+ };
40
+
41
+ } // namespace margelo::nitro::iap
42
+
43
+ namespace margelo::nitro {
44
+
45
+ // C++ UserChoiceBillingDetails <> JS UserChoiceBillingDetails (object)
46
+ template <>
47
+ struct JSIConverter<margelo::nitro::iap::UserChoiceBillingDetails> final {
48
+ static inline margelo::nitro::iap::UserChoiceBillingDetails fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
49
+ jsi::Object obj = arg.asObject(runtime);
50
+ return margelo::nitro::iap::UserChoiceBillingDetails(
51
+ JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, "externalTransactionToken")),
52
+ JSIConverter<std::vector<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "products"))
53
+ );
54
+ }
55
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::iap::UserChoiceBillingDetails& arg) {
56
+ jsi::Object obj(runtime);
57
+ obj.setProperty(runtime, "externalTransactionToken", JSIConverter<std::string>::toJSI(runtime, arg.externalTransactionToken));
58
+ obj.setProperty(runtime, "products", JSIConverter<std::vector<std::string>>::toJSI(runtime, arg.products));
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::string>::canConvert(runtime, obj.getProperty(runtime, "externalTransactionToken"))) return false;
67
+ if (!JSIConverter<std::vector<std::string>>::canConvert(runtime, obj.getProperty(runtime, "products"))) return false;
68
+ return true;
69
+ }
70
+ };
71
+
72
+ } // namespace margelo::nitro
@@ -1,5 +1,5 @@
1
1
  {
2
- "apple": "1.2.6",
3
- "google": "1.2.10",
4
- "gql": "1.0.9"
2
+ "apple": "1.2.10",
3
+ "google": "1.2.12",
4
+ "gql": "1.0.12"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-iap",
3
- "version": "14.4.11",
3
+ "version": "14.4.12",
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",
@@ -1,14 +1,41 @@
1
+ import type { ConfigPlugin } from 'expo/config-plugins';
1
2
  import type { ExpoConfig } from '@expo/config-types';
2
3
  export declare const modifyProjectBuildGradle: (gradle: string) => string;
4
+ export interface IosAlternativeBillingConfig {
5
+ /** Country codes where external purchases are supported (ISO 3166-1 alpha-2) */
6
+ countries?: string[];
7
+ /** External purchase URLs per country (iOS 15.4+) */
8
+ links?: Record<string, string>;
9
+ /** Multiple external purchase URLs per country (iOS 17.5+, up to 5 per country) */
10
+ multiLinks?: Record<string, string[]>;
11
+ /** Custom link regions (iOS 18.1+) */
12
+ customLinkRegions?: string[];
13
+ /** Streaming link regions for music apps (iOS 18.2+) */
14
+ streamingLinkRegions?: string[];
15
+ /** Enable external purchase link entitlement */
16
+ enableExternalPurchaseLink?: boolean;
17
+ /** Enable external purchase link streaming entitlement (music apps only) */
18
+ enableExternalPurchaseLinkStreaming?: boolean;
19
+ }
20
+ /** Add external purchase entitlements and Info.plist configuration */
21
+ declare const withIosAlternativeBilling: ConfigPlugin<IosAlternativeBillingConfig | undefined>;
3
22
  type IapPluginProps = {
4
23
  ios?: {
5
24
  'with-folly-no-coroutines'?: boolean;
6
25
  'with-folly-no-couroutines'?: boolean;
7
26
  };
27
+ /**
28
+ * iOS Alternative Billing configuration.
29
+ * Configure external purchase countries, links, and entitlements.
30
+ * Requires approval from Apple.
31
+ * @platform ios
32
+ */
33
+ iosAlternativeBilling?: IosAlternativeBillingConfig;
8
34
  };
9
35
  type IapPluginCallable = {
10
36
  (config: ExpoConfig): ExpoConfig;
11
37
  (config: ExpoConfig, props?: IapPluginProps): ExpoConfig;
12
38
  };
13
39
  declare const pluginExport: IapPluginCallable;
40
+ export { withIosAlternativeBilling };
14
41
  export { pluginExport as default };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = exports.modifyProjectBuildGradle = void 0;
3
+ exports.default = exports.withIosAlternativeBilling = exports.modifyProjectBuildGradle = void 0;
4
4
  const config_plugins_1 = require("expo/config-plugins");
5
5
  const node_fs_1 = require("node:fs");
6
6
  const node_path_1 = require("node:path");
@@ -115,6 +115,92 @@ const withIapAndroid = (config) => {
115
115
  });
116
116
  return config;
117
117
  };
118
+ /** Add external purchase entitlements and Info.plist configuration */
119
+ const withIosAlternativeBilling = (config, options) => {
120
+ if (!options || !options.countries || options.countries.length === 0) {
121
+ return config;
122
+ }
123
+ // Add entitlements
124
+ config = (0, config_plugins_1.withEntitlementsPlist)(config, (config) => {
125
+ // Always add basic external purchase entitlement when countries are specified
126
+ config.modResults['com.apple.developer.storekit.external-purchase'] = true;
127
+ if (!hasLoggedPluginExecution) {
128
+ console.log('✅ Added com.apple.developer.storekit.external-purchase to entitlements');
129
+ }
130
+ // Add external purchase link entitlement if enabled
131
+ if (options.enableExternalPurchaseLink) {
132
+ config.modResults['com.apple.developer.storekit.external-purchase-link'] =
133
+ true;
134
+ if (!hasLoggedPluginExecution) {
135
+ console.log('✅ Added com.apple.developer.storekit.external-purchase-link to entitlements');
136
+ }
137
+ }
138
+ // Add streaming entitlement if enabled
139
+ if (options.enableExternalPurchaseLinkStreaming) {
140
+ config.modResults['com.apple.developer.storekit.external-purchase-link-streaming'] = true;
141
+ if (!hasLoggedPluginExecution) {
142
+ console.log('✅ Added com.apple.developer.storekit.external-purchase-link-streaming to entitlements');
143
+ }
144
+ }
145
+ return config;
146
+ });
147
+ // Add Info.plist configuration
148
+ config = (0, config_plugins_1.withInfoPlist)(config, (config) => {
149
+ const plist = config.modResults;
150
+ // Helper function to normalize country codes to uppercase
151
+ const normalize = (code) => code.trim().toUpperCase();
152
+ // 1. SKExternalPurchase (Required)
153
+ const normalizedCountries = options.countries?.map(normalize);
154
+ plist.SKExternalPurchase = normalizedCountries;
155
+ if (!hasLoggedPluginExecution) {
156
+ console.log(`✅ Added SKExternalPurchase with countries: ${normalizedCountries?.join(', ')}`);
157
+ }
158
+ // 2. SKExternalPurchaseLink (Optional - iOS 15.4+)
159
+ if (options.links && Object.keys(options.links).length > 0) {
160
+ plist.SKExternalPurchaseLink = Object.fromEntries(Object.entries(options.links).map(([code, url]) => [
161
+ normalize(code),
162
+ url,
163
+ ]));
164
+ if (!hasLoggedPluginExecution) {
165
+ console.log(`✅ Added SKExternalPurchaseLink for ${Object.keys(options.links).length} countries`);
166
+ }
167
+ }
168
+ // 3. SKExternalPurchaseMultiLink (iOS 17.5+)
169
+ if (options.multiLinks && Object.keys(options.multiLinks).length > 0) {
170
+ plist.SKExternalPurchaseMultiLink = Object.fromEntries(Object.entries(options.multiLinks).map(([code, urls]) => [
171
+ normalize(code),
172
+ urls,
173
+ ]));
174
+ if (!hasLoggedPluginExecution) {
175
+ console.log(`✅ Added SKExternalPurchaseMultiLink for ${Object.keys(options.multiLinks).length} countries`);
176
+ }
177
+ }
178
+ // 4. SKExternalPurchaseCustomLinkRegions (iOS 18.1+)
179
+ if (options.customLinkRegions && options.customLinkRegions.length > 0) {
180
+ plist.SKExternalPurchaseCustomLinkRegions =
181
+ options.customLinkRegions.map(normalize);
182
+ if (!hasLoggedPluginExecution) {
183
+ console.log(`✅ Added SKExternalPurchaseCustomLinkRegions: ${options.customLinkRegions
184
+ .map(normalize)
185
+ .join(', ')}`);
186
+ }
187
+ }
188
+ // 5. SKExternalPurchaseLinkStreamingRegions (iOS 18.2+)
189
+ if (options.streamingLinkRegions &&
190
+ options.streamingLinkRegions.length > 0) {
191
+ plist.SKExternalPurchaseLinkStreamingRegions =
192
+ options.streamingLinkRegions.map(normalize);
193
+ if (!hasLoggedPluginExecution) {
194
+ console.log(`✅ Added SKExternalPurchaseLinkStreamingRegions: ${options.streamingLinkRegions
195
+ .map(normalize)
196
+ .join(', ')}`);
197
+ }
198
+ }
199
+ return config;
200
+ });
201
+ return config;
202
+ };
203
+ exports.withIosAlternativeBilling = withIosAlternativeBilling;
118
204
  const withIapIosFollyWorkaround = (config, props) => {
119
205
  const newKey = props?.ios?.['with-folly-no-coroutines'];
120
206
  const oldKey = props?.ios?.['with-folly-no-couroutines'];
@@ -165,6 +251,10 @@ const withIAP = (config, props) => {
165
251
  try {
166
252
  let result = withIapAndroid(config);
167
253
  result = withIapIosFollyWorkaround(result, props);
254
+ // Add iOS alternative billing configuration if provided
255
+ if (props?.iosAlternativeBilling) {
256
+ result = withIosAlternativeBilling(result, props.iosAlternativeBilling);
257
+ }
168
258
  // Set flag after first execution to prevent duplicate logs
169
259
  hasLoggedPluginExecution = true;
170
260
  return result;