react-native-iap 14.0.1 → 14.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +81 -22
- package/ios/HybridRnIap.swift +151 -11
- package/ios/ProductStore.swift +10 -0
- package/lib/module/helpers/subscription.js +9 -1
- package/lib/module/helpers/subscription.js.map +1 -1
- package/lib/module/hooks/useIAP.js +9 -13
- package/lib/module/hooks/useIAP.js.map +1 -1
- package/lib/module/index.js +43 -28
- package/lib/module/index.js.map +1 -1
- package/lib/module/types.js +24 -16
- package/lib/module/types.js.map +1 -1
- package/lib/module/utils/type-bridge.js +64 -13
- package/lib/module/utils/type-bridge.js.map +1 -1
- package/lib/typescript/src/helpers/subscription.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +12 -22
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/RnIap.nitro.d.ts +15 -11
- package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +58 -58
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/utils/type-bridge.d.ts.map +1 -1
- package/nitro.json +5 -1
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +13 -4
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +1 -1
- package/nitrogen/generated/android/c++/JNitroProduct.hpp +40 -36
- package/nitrogen/generated/android/c++/JNitroPurchase.hpp +12 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +1 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroProduct.kt +12 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroPurchase.kt +9 -0
- package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +1 -1
- package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +13 -7
- package/nitrogen/generated/ios/swift/NitroProduct.swift +73 -43
- package/nitrogen/generated/ios/swift/NitroPurchase.swift +35 -2
- package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +1 -1
- package/nitrogen/generated/shared/c++/NitroProduct.hpp +41 -37
- package/nitrogen/generated/shared/c++/NitroPurchase.hpp +13 -1
- package/package.json +9 -2
- package/src/helpers/subscription.ts +13 -2
- package/src/hooks/useIAP.ts +8 -21
- package/src/index.ts +58 -38
- package/src/specs/RnIap.nitro.ts +15 -11
- package/src/types.ts +66 -62
- package/src/utils/type-bridge.ts +80 -16
|
@@ -106,7 +106,7 @@ namespace margelo::nitro::iap {
|
|
|
106
106
|
virtual std::shared_ptr<Promise<std::optional<NitroPurchase>>> latestTransactionIOS(const std::string& sku) = 0;
|
|
107
107
|
virtual std::shared_ptr<Promise<std::vector<NitroPurchase>>> getPendingTransactionsIOS() = 0;
|
|
108
108
|
virtual std::shared_ptr<Promise<bool>> syncIOS() = 0;
|
|
109
|
-
virtual std::shared_ptr<Promise<
|
|
109
|
+
virtual std::shared_ptr<Promise<std::vector<NitroPurchase>>> showManageSubscriptionsIOS() = 0;
|
|
110
110
|
virtual std::shared_ptr<Promise<bool>> isEligibleForIntroOfferIOS(const std::string& groupID) = 0;
|
|
111
111
|
virtual std::shared_ptr<Promise<std::string>> getReceiptDataIOS() = 0;
|
|
112
112
|
virtual std::shared_ptr<Promise<bool>> isTransactionVerifiedIOS(const std::string& sku) = 0;
|
|
@@ -39,8 +39,9 @@ namespace margelo::nitro::iap {
|
|
|
39
39
|
std::optional<std::string> currency SWIFT_PRIVATE;
|
|
40
40
|
std::optional<double> price SWIFT_PRIVATE;
|
|
41
41
|
std::string platform SWIFT_PRIVATE;
|
|
42
|
-
std::optional<
|
|
43
|
-
std::optional<
|
|
42
|
+
std::optional<std::string> typeIOS SWIFT_PRIVATE;
|
|
43
|
+
std::optional<bool> isFamilyShareableIOS SWIFT_PRIVATE;
|
|
44
|
+
std::optional<std::string> jsonRepresentationIOS SWIFT_PRIVATE;
|
|
44
45
|
std::optional<std::string> subscriptionPeriodUnitIOS SWIFT_PRIVATE;
|
|
45
46
|
std::optional<double> subscriptionPeriodNumberIOS SWIFT_PRIVATE;
|
|
46
47
|
std::optional<std::string> introductoryPriceIOS SWIFT_PRIVATE;
|
|
@@ -48,18 +49,18 @@ namespace margelo::nitro::iap {
|
|
|
48
49
|
std::optional<std::string> introductoryPricePaymentModeIOS SWIFT_PRIVATE;
|
|
49
50
|
std::optional<double> introductoryPriceNumberOfPeriodsIOS SWIFT_PRIVATE;
|
|
50
51
|
std::optional<std::string> introductoryPriceSubscriptionPeriodIOS SWIFT_PRIVATE;
|
|
51
|
-
std::optional<std::string>
|
|
52
|
-
std::optional<double>
|
|
53
|
-
std::optional<double>
|
|
54
|
-
std::optional<double>
|
|
55
|
-
std::optional<std::string>
|
|
56
|
-
std::optional<std::string>
|
|
57
|
-
std::optional<std::string>
|
|
52
|
+
std::optional<std::string> originalPriceAndroid SWIFT_PRIVATE;
|
|
53
|
+
std::optional<double> originalPriceAmountMicrosAndroid SWIFT_PRIVATE;
|
|
54
|
+
std::optional<double> introductoryPriceValueAndroid SWIFT_PRIVATE;
|
|
55
|
+
std::optional<double> introductoryPriceCyclesAndroid SWIFT_PRIVATE;
|
|
56
|
+
std::optional<std::string> introductoryPricePeriodAndroid SWIFT_PRIVATE;
|
|
57
|
+
std::optional<std::string> subscriptionPeriodAndroid SWIFT_PRIVATE;
|
|
58
|
+
std::optional<std::string> freeTrialPeriodAndroid SWIFT_PRIVATE;
|
|
58
59
|
std::optional<std::string> subscriptionOfferDetailsAndroid SWIFT_PRIVATE;
|
|
59
60
|
|
|
60
61
|
public:
|
|
61
62
|
NitroProduct() = default;
|
|
62
|
-
explicit NitroProduct(std::string id, std::string title, std::string description, std::string type, std::optional<std::string> displayName, std::optional<std::string> displayPrice, std::optional<std::string> currency, std::optional<double> price, std::string platform, std::optional<bool>
|
|
63
|
+
explicit NitroProduct(std::string id, std::string title, std::string description, std::string type, std::optional<std::string> displayName, std::optional<std::string> displayPrice, std::optional<std::string> currency, std::optional<double> price, std::string platform, std::optional<std::string> typeIOS, std::optional<bool> isFamilyShareableIOS, std::optional<std::string> jsonRepresentationIOS, std::optional<std::string> subscriptionPeriodUnitIOS, std::optional<double> subscriptionPeriodNumberIOS, std::optional<std::string> introductoryPriceIOS, std::optional<double> introductoryPriceAsAmountIOS, std::optional<std::string> introductoryPricePaymentModeIOS, std::optional<double> introductoryPriceNumberOfPeriodsIOS, std::optional<std::string> introductoryPriceSubscriptionPeriodIOS, std::optional<std::string> originalPriceAndroid, std::optional<double> originalPriceAmountMicrosAndroid, std::optional<double> introductoryPriceValueAndroid, std::optional<double> introductoryPriceCyclesAndroid, std::optional<std::string> introductoryPricePeriodAndroid, std::optional<std::string> subscriptionPeriodAndroid, std::optional<std::string> freeTrialPeriodAndroid, std::optional<std::string> subscriptionOfferDetailsAndroid): id(id), title(title), description(description), type(type), displayName(displayName), displayPrice(displayPrice), currency(currency), price(price), platform(platform), typeIOS(typeIOS), isFamilyShareableIOS(isFamilyShareableIOS), jsonRepresentationIOS(jsonRepresentationIOS), subscriptionPeriodUnitIOS(subscriptionPeriodUnitIOS), subscriptionPeriodNumberIOS(subscriptionPeriodNumberIOS), introductoryPriceIOS(introductoryPriceIOS), introductoryPriceAsAmountIOS(introductoryPriceAsAmountIOS), introductoryPricePaymentModeIOS(introductoryPricePaymentModeIOS), introductoryPriceNumberOfPeriodsIOS(introductoryPriceNumberOfPeriodsIOS), introductoryPriceSubscriptionPeriodIOS(introductoryPriceSubscriptionPeriodIOS), originalPriceAndroid(originalPriceAndroid), originalPriceAmountMicrosAndroid(originalPriceAmountMicrosAndroid), introductoryPriceValueAndroid(introductoryPriceValueAndroid), introductoryPriceCyclesAndroid(introductoryPriceCyclesAndroid), introductoryPricePeriodAndroid(introductoryPricePeriodAndroid), subscriptionPeriodAndroid(subscriptionPeriodAndroid), freeTrialPeriodAndroid(freeTrialPeriodAndroid), subscriptionOfferDetailsAndroid(subscriptionOfferDetailsAndroid) {}
|
|
63
64
|
};
|
|
64
65
|
|
|
65
66
|
} // namespace margelo::nitro::iap
|
|
@@ -81,8 +82,9 @@ namespace margelo::nitro {
|
|
|
81
82
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "currency")),
|
|
82
83
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "price")),
|
|
83
84
|
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, "platform")),
|
|
84
|
-
JSIConverter<std::optional<
|
|
85
|
-
JSIConverter<std::optional<
|
|
85
|
+
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "typeIOS")),
|
|
86
|
+
JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, "isFamilyShareableIOS")),
|
|
87
|
+
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "jsonRepresentationIOS")),
|
|
86
88
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "subscriptionPeriodUnitIOS")),
|
|
87
89
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "subscriptionPeriodNumberIOS")),
|
|
88
90
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "introductoryPriceIOS")),
|
|
@@ -90,13 +92,13 @@ namespace margelo::nitro {
|
|
|
90
92
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "introductoryPricePaymentModeIOS")),
|
|
91
93
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "introductoryPriceNumberOfPeriodsIOS")),
|
|
92
94
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "introductoryPriceSubscriptionPeriodIOS")),
|
|
93
|
-
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "
|
|
94
|
-
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "
|
|
95
|
-
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "
|
|
96
|
-
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "
|
|
97
|
-
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "
|
|
98
|
-
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "
|
|
99
|
-
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "
|
|
95
|
+
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "originalPriceAndroid")),
|
|
96
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "originalPriceAmountMicrosAndroid")),
|
|
97
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "introductoryPriceValueAndroid")),
|
|
98
|
+
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "introductoryPriceCyclesAndroid")),
|
|
99
|
+
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "introductoryPricePeriodAndroid")),
|
|
100
|
+
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "subscriptionPeriodAndroid")),
|
|
101
|
+
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "freeTrialPeriodAndroid")),
|
|
100
102
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "subscriptionOfferDetailsAndroid"))
|
|
101
103
|
);
|
|
102
104
|
}
|
|
@@ -111,8 +113,9 @@ namespace margelo::nitro {
|
|
|
111
113
|
obj.setProperty(runtime, "currency", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.currency));
|
|
112
114
|
obj.setProperty(runtime, "price", JSIConverter<std::optional<double>>::toJSI(runtime, arg.price));
|
|
113
115
|
obj.setProperty(runtime, "platform", JSIConverter<std::string>::toJSI(runtime, arg.platform));
|
|
114
|
-
obj.setProperty(runtime, "
|
|
115
|
-
obj.setProperty(runtime, "
|
|
116
|
+
obj.setProperty(runtime, "typeIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.typeIOS));
|
|
117
|
+
obj.setProperty(runtime, "isFamilyShareableIOS", JSIConverter<std::optional<bool>>::toJSI(runtime, arg.isFamilyShareableIOS));
|
|
118
|
+
obj.setProperty(runtime, "jsonRepresentationIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.jsonRepresentationIOS));
|
|
116
119
|
obj.setProperty(runtime, "subscriptionPeriodUnitIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.subscriptionPeriodUnitIOS));
|
|
117
120
|
obj.setProperty(runtime, "subscriptionPeriodNumberIOS", JSIConverter<std::optional<double>>::toJSI(runtime, arg.subscriptionPeriodNumberIOS));
|
|
118
121
|
obj.setProperty(runtime, "introductoryPriceIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.introductoryPriceIOS));
|
|
@@ -120,13 +123,13 @@ namespace margelo::nitro {
|
|
|
120
123
|
obj.setProperty(runtime, "introductoryPricePaymentModeIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.introductoryPricePaymentModeIOS));
|
|
121
124
|
obj.setProperty(runtime, "introductoryPriceNumberOfPeriodsIOS", JSIConverter<std::optional<double>>::toJSI(runtime, arg.introductoryPriceNumberOfPeriodsIOS));
|
|
122
125
|
obj.setProperty(runtime, "introductoryPriceSubscriptionPeriodIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.introductoryPriceSubscriptionPeriodIOS));
|
|
123
|
-
obj.setProperty(runtime, "
|
|
124
|
-
obj.setProperty(runtime, "
|
|
125
|
-
obj.setProperty(runtime, "
|
|
126
|
-
obj.setProperty(runtime, "
|
|
127
|
-
obj.setProperty(runtime, "
|
|
128
|
-
obj.setProperty(runtime, "
|
|
129
|
-
obj.setProperty(runtime, "
|
|
126
|
+
obj.setProperty(runtime, "originalPriceAndroid", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.originalPriceAndroid));
|
|
127
|
+
obj.setProperty(runtime, "originalPriceAmountMicrosAndroid", JSIConverter<std::optional<double>>::toJSI(runtime, arg.originalPriceAmountMicrosAndroid));
|
|
128
|
+
obj.setProperty(runtime, "introductoryPriceValueAndroid", JSIConverter<std::optional<double>>::toJSI(runtime, arg.introductoryPriceValueAndroid));
|
|
129
|
+
obj.setProperty(runtime, "introductoryPriceCyclesAndroid", JSIConverter<std::optional<double>>::toJSI(runtime, arg.introductoryPriceCyclesAndroid));
|
|
130
|
+
obj.setProperty(runtime, "introductoryPricePeriodAndroid", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.introductoryPricePeriodAndroid));
|
|
131
|
+
obj.setProperty(runtime, "subscriptionPeriodAndroid", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.subscriptionPeriodAndroid));
|
|
132
|
+
obj.setProperty(runtime, "freeTrialPeriodAndroid", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.freeTrialPeriodAndroid));
|
|
130
133
|
obj.setProperty(runtime, "subscriptionOfferDetailsAndroid", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.subscriptionOfferDetailsAndroid));
|
|
131
134
|
return obj;
|
|
132
135
|
}
|
|
@@ -144,8 +147,9 @@ namespace margelo::nitro {
|
|
|
144
147
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "currency"))) return false;
|
|
145
148
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "price"))) return false;
|
|
146
149
|
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, "platform"))) return false;
|
|
147
|
-
if (!JSIConverter<std::optional<
|
|
148
|
-
if (!JSIConverter<std::optional<
|
|
150
|
+
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "typeIOS"))) return false;
|
|
151
|
+
if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, "isFamilyShareableIOS"))) return false;
|
|
152
|
+
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "jsonRepresentationIOS"))) return false;
|
|
149
153
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "subscriptionPeriodUnitIOS"))) return false;
|
|
150
154
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "subscriptionPeriodNumberIOS"))) return false;
|
|
151
155
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "introductoryPriceIOS"))) return false;
|
|
@@ -153,13 +157,13 @@ namespace margelo::nitro {
|
|
|
153
157
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "introductoryPricePaymentModeIOS"))) return false;
|
|
154
158
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "introductoryPriceNumberOfPeriodsIOS"))) return false;
|
|
155
159
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "introductoryPriceSubscriptionPeriodIOS"))) return false;
|
|
156
|
-
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "
|
|
157
|
-
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "
|
|
158
|
-
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "
|
|
159
|
-
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "
|
|
160
|
-
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "
|
|
161
|
-
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "
|
|
162
|
-
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "
|
|
160
|
+
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "originalPriceAndroid"))) return false;
|
|
161
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "originalPriceAmountMicrosAndroid"))) return false;
|
|
162
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "introductoryPriceValueAndroid"))) return false;
|
|
163
|
+
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "introductoryPriceCyclesAndroid"))) return false;
|
|
164
|
+
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "introductoryPricePeriodAndroid"))) return false;
|
|
165
|
+
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "subscriptionPeriodAndroid"))) return false;
|
|
166
|
+
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "freeTrialPeriodAndroid"))) return false;
|
|
163
167
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "subscriptionOfferDetailsAndroid"))) return false;
|
|
164
168
|
return true;
|
|
165
169
|
}
|
|
@@ -35,6 +35,9 @@ namespace margelo::nitro::iap {
|
|
|
35
35
|
double transactionDate SWIFT_PRIVATE;
|
|
36
36
|
std::optional<std::string> purchaseToken SWIFT_PRIVATE;
|
|
37
37
|
std::string platform SWIFT_PRIVATE;
|
|
38
|
+
double quantity SWIFT_PRIVATE;
|
|
39
|
+
std::string purchaseState SWIFT_PRIVATE;
|
|
40
|
+
bool isAutoRenewing SWIFT_PRIVATE;
|
|
38
41
|
std::optional<double> quantityIOS SWIFT_PRIVATE;
|
|
39
42
|
std::optional<double> originalTransactionDateIOS SWIFT_PRIVATE;
|
|
40
43
|
std::optional<std::string> originalTransactionIdentifierIOS SWIFT_PRIVATE;
|
|
@@ -51,7 +54,7 @@ namespace margelo::nitro::iap {
|
|
|
51
54
|
|
|
52
55
|
public:
|
|
53
56
|
NitroPurchase() = default;
|
|
54
|
-
explicit NitroPurchase(std::string id, std::string productId, double transactionDate, std::optional<std::string> purchaseToken, std::string platform, std::optional<double> quantityIOS, std::optional<double> originalTransactionDateIOS, std::optional<std::string> originalTransactionIdentifierIOS, std::optional<std::string> appAccountToken, std::optional<std::string> purchaseTokenAndroid, std::optional<std::string> dataAndroid, std::optional<std::string> signatureAndroid, std::optional<bool> autoRenewingAndroid, std::optional<double> purchaseStateAndroid, std::optional<bool> isAcknowledgedAndroid, std::optional<std::string> packageNameAndroid, std::optional<std::string> obfuscatedAccountIdAndroid, std::optional<std::string> obfuscatedProfileIdAndroid): id(id), productId(productId), transactionDate(transactionDate), purchaseToken(purchaseToken), platform(platform), quantityIOS(quantityIOS), originalTransactionDateIOS(originalTransactionDateIOS), originalTransactionIdentifierIOS(originalTransactionIdentifierIOS), appAccountToken(appAccountToken), purchaseTokenAndroid(purchaseTokenAndroid), dataAndroid(dataAndroid), signatureAndroid(signatureAndroid), autoRenewingAndroid(autoRenewingAndroid), purchaseStateAndroid(purchaseStateAndroid), isAcknowledgedAndroid(isAcknowledgedAndroid), packageNameAndroid(packageNameAndroid), obfuscatedAccountIdAndroid(obfuscatedAccountIdAndroid), obfuscatedProfileIdAndroid(obfuscatedProfileIdAndroid) {}
|
|
57
|
+
explicit NitroPurchase(std::string id, std::string productId, double transactionDate, std::optional<std::string> purchaseToken, std::string platform, double quantity, std::string purchaseState, bool isAutoRenewing, std::optional<double> quantityIOS, std::optional<double> originalTransactionDateIOS, std::optional<std::string> originalTransactionIdentifierIOS, std::optional<std::string> appAccountToken, std::optional<std::string> purchaseTokenAndroid, std::optional<std::string> dataAndroid, std::optional<std::string> signatureAndroid, std::optional<bool> autoRenewingAndroid, std::optional<double> purchaseStateAndroid, std::optional<bool> isAcknowledgedAndroid, std::optional<std::string> packageNameAndroid, std::optional<std::string> obfuscatedAccountIdAndroid, std::optional<std::string> obfuscatedProfileIdAndroid): id(id), productId(productId), transactionDate(transactionDate), purchaseToken(purchaseToken), platform(platform), quantity(quantity), purchaseState(purchaseState), isAutoRenewing(isAutoRenewing), quantityIOS(quantityIOS), originalTransactionDateIOS(originalTransactionDateIOS), originalTransactionIdentifierIOS(originalTransactionIdentifierIOS), appAccountToken(appAccountToken), purchaseTokenAndroid(purchaseTokenAndroid), dataAndroid(dataAndroid), signatureAndroid(signatureAndroid), autoRenewingAndroid(autoRenewingAndroid), purchaseStateAndroid(purchaseStateAndroid), isAcknowledgedAndroid(isAcknowledgedAndroid), packageNameAndroid(packageNameAndroid), obfuscatedAccountIdAndroid(obfuscatedAccountIdAndroid), obfuscatedProfileIdAndroid(obfuscatedProfileIdAndroid) {}
|
|
55
58
|
};
|
|
56
59
|
|
|
57
60
|
} // namespace margelo::nitro::iap
|
|
@@ -69,6 +72,9 @@ namespace margelo::nitro {
|
|
|
69
72
|
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, "transactionDate")),
|
|
70
73
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "purchaseToken")),
|
|
71
74
|
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, "platform")),
|
|
75
|
+
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, "quantity")),
|
|
76
|
+
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, "purchaseState")),
|
|
77
|
+
JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, "isAutoRenewing")),
|
|
72
78
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "quantityIOS")),
|
|
73
79
|
JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "originalTransactionDateIOS")),
|
|
74
80
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "originalTransactionIdentifierIOS")),
|
|
@@ -91,6 +97,9 @@ namespace margelo::nitro {
|
|
|
91
97
|
obj.setProperty(runtime, "transactionDate", JSIConverter<double>::toJSI(runtime, arg.transactionDate));
|
|
92
98
|
obj.setProperty(runtime, "purchaseToken", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.purchaseToken));
|
|
93
99
|
obj.setProperty(runtime, "platform", JSIConverter<std::string>::toJSI(runtime, arg.platform));
|
|
100
|
+
obj.setProperty(runtime, "quantity", JSIConverter<double>::toJSI(runtime, arg.quantity));
|
|
101
|
+
obj.setProperty(runtime, "purchaseState", JSIConverter<std::string>::toJSI(runtime, arg.purchaseState));
|
|
102
|
+
obj.setProperty(runtime, "isAutoRenewing", JSIConverter<bool>::toJSI(runtime, arg.isAutoRenewing));
|
|
94
103
|
obj.setProperty(runtime, "quantityIOS", JSIConverter<std::optional<double>>::toJSI(runtime, arg.quantityIOS));
|
|
95
104
|
obj.setProperty(runtime, "originalTransactionDateIOS", JSIConverter<std::optional<double>>::toJSI(runtime, arg.originalTransactionDateIOS));
|
|
96
105
|
obj.setProperty(runtime, "originalTransactionIdentifierIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.originalTransactionIdentifierIOS));
|
|
@@ -116,6 +125,9 @@ namespace margelo::nitro {
|
|
|
116
125
|
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, "transactionDate"))) return false;
|
|
117
126
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "purchaseToken"))) return false;
|
|
118
127
|
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, "platform"))) return false;
|
|
128
|
+
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, "quantity"))) return false;
|
|
129
|
+
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, "purchaseState"))) return false;
|
|
130
|
+
if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, "isAutoRenewing"))) return false;
|
|
119
131
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "quantityIOS"))) return false;
|
|
120
132
|
if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "originalTransactionDateIOS"))) return false;
|
|
121
133
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "originalTransactionIdentifierIOS"))) return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-iap",
|
|
3
|
-
"version": "14.0
|
|
3
|
+
"version": "14.1.0",
|
|
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",
|
|
@@ -57,9 +57,13 @@
|
|
|
57
57
|
"prepare": "npx tsx scripts/check-nitro-versions.ts && bob build && yarn nitrogen && yarn build:plugin",
|
|
58
58
|
"nitrogen": "nitro-codegen",
|
|
59
59
|
"specs": "nitro-codegen --logLevel=\"debug\"",
|
|
60
|
-
"test": "
|
|
60
|
+
"test": "jest --coverage",
|
|
61
|
+
"test:library": "jest --coverage",
|
|
62
|
+
"test:example": "yarn workspace rn-iap-example test --coverage",
|
|
61
63
|
"test:plugin": "cd example-expo/plugin && bun test",
|
|
64
|
+
"test:all": "yarn test:library && yarn test:example",
|
|
62
65
|
"test:ci": "jest --maxWorkers=2 --coverage",
|
|
66
|
+
"test:ci:example": "yarn workspace rn-iap-example test --coverage",
|
|
63
67
|
"prepare:husky": "husky install",
|
|
64
68
|
"precommit": "lint-staged",
|
|
65
69
|
"ci:check": "./scripts/ci-check.sh",
|
|
@@ -85,6 +89,8 @@
|
|
|
85
89
|
"devDependencies": {
|
|
86
90
|
"@babel/plugin-proposal-private-methods": "^7.18.6",
|
|
87
91
|
"@react-native/eslint-config": "0.81.0",
|
|
92
|
+
"@testing-library/react": "^16.3.0",
|
|
93
|
+
"@testing-library/react-hooks": "^8.0.1",
|
|
88
94
|
"@types/jest": "^29.5.12",
|
|
89
95
|
"@types/react": "^19.1.12",
|
|
90
96
|
"babel-jest": "^30.1.1",
|
|
@@ -102,6 +108,7 @@
|
|
|
102
108
|
"react-native": "0.81.1",
|
|
103
109
|
"react-native-builder-bob": "^0.38.4",
|
|
104
110
|
"react-native-nitro-modules": "^0.29.2",
|
|
111
|
+
"react-test-renderer": "^19.1.1",
|
|
105
112
|
"typescript": "^5.9.2"
|
|
106
113
|
},
|
|
107
114
|
"peerDependencies": {
|
|
@@ -24,15 +24,26 @@ export const getActiveSubscriptions = async (
|
|
|
24
24
|
})
|
|
25
25
|
.map((purchase): ActiveSubscription => {
|
|
26
26
|
const iosPurchase = purchase as PurchaseIOS
|
|
27
|
+
const androidPurchase = purchase as PurchaseAndroid
|
|
27
28
|
return {
|
|
28
29
|
productId: purchase.productId,
|
|
29
30
|
isActive: true, // If it's in availablePurchases, it's active
|
|
31
|
+
// Backend validation fields
|
|
32
|
+
transactionId: purchase.transactionId || purchase.id,
|
|
33
|
+
purchaseToken:
|
|
34
|
+
androidPurchase.purchaseToken ||
|
|
35
|
+
androidPurchase.purchaseTokenAndroid ||
|
|
36
|
+
iosPurchase.purchaseToken,
|
|
37
|
+
transactionDate: purchase.transactionDate,
|
|
38
|
+
// Platform-specific fields
|
|
30
39
|
expirationDateIOS: iosPurchase.expirationDateIOS
|
|
31
40
|
? new Date(iosPurchase.expirationDateIOS)
|
|
32
41
|
: undefined,
|
|
33
|
-
autoRenewingAndroid:
|
|
34
|
-
.autoRenewingAndroid
|
|
42
|
+
autoRenewingAndroid:
|
|
43
|
+
androidPurchase.autoRenewingAndroid ??
|
|
44
|
+
androidPurchase.isAutoRenewing, // deprecated - use isAutoRenewing instead
|
|
35
45
|
environmentIOS: iosPurchase.environmentIOS,
|
|
46
|
+
// Convenience fields
|
|
36
47
|
willExpireSoon: false, // Would need to calculate based on expiration date
|
|
37
48
|
daysUntilExpirationIOS: iosPurchase.expirationDateIOS
|
|
38
49
|
? Math.ceil(
|
package/src/hooks/useIAP.ts
CHANGED
|
@@ -318,24 +318,6 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
318
318
|
[clearCurrentPurchase, clearCurrentPurchaseError]
|
|
319
319
|
)
|
|
320
320
|
|
|
321
|
-
const refreshSubscriptionStatus = useCallback(
|
|
322
|
-
async (productId: string) => {
|
|
323
|
-
try {
|
|
324
|
-
if (
|
|
325
|
-
subscriptionsRefState.current.some(
|
|
326
|
-
(sub: SubscriptionProduct) => sub.id === productId
|
|
327
|
-
)
|
|
328
|
-
) {
|
|
329
|
-
await getSubscriptionsInternal([productId])
|
|
330
|
-
await getAvailablePurchasesInternal()
|
|
331
|
-
}
|
|
332
|
-
} catch (error) {
|
|
333
|
-
console.warn('Failed to refresh subscription status:', error)
|
|
334
|
-
}
|
|
335
|
-
},
|
|
336
|
-
[getAvailablePurchasesInternal, getSubscriptionsInternal]
|
|
337
|
-
)
|
|
338
|
-
|
|
339
321
|
const restorePurchases = useCallback(async (): Promise<void> => {
|
|
340
322
|
try {
|
|
341
323
|
if (Platform.OS === 'ios') {
|
|
@@ -378,8 +360,13 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
378
360
|
setCurrentPurchaseError(undefined)
|
|
379
361
|
setCurrentPurchase(purchase)
|
|
380
362
|
|
|
381
|
-
|
|
382
|
-
|
|
363
|
+
// Always refresh subscription state after a purchase event
|
|
364
|
+
try {
|
|
365
|
+
await getActiveSubscriptionsInternal()
|
|
366
|
+
await getAvailablePurchasesInternal()
|
|
367
|
+
} catch (e) {
|
|
368
|
+
// Non-fatal: UI will still update from event data
|
|
369
|
+
console.warn('[useIAP] post-purchase refresh failed:', e)
|
|
383
370
|
}
|
|
384
371
|
|
|
385
372
|
if (optionsRef.current?.onPurchaseSuccess) {
|
|
@@ -411,7 +398,7 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
411
398
|
})
|
|
412
399
|
}
|
|
413
400
|
}
|
|
414
|
-
}, [
|
|
401
|
+
}, [getActiveSubscriptionsInternal, getAvailablePurchasesInternal])
|
|
415
402
|
|
|
416
403
|
useEffect(() => {
|
|
417
404
|
initIapWithSubscriptions()
|
package/src/index.ts
CHANGED
|
@@ -24,6 +24,7 @@ import type {
|
|
|
24
24
|
RequestPurchaseIosProps,
|
|
25
25
|
RequestPurchaseAndroidProps,
|
|
26
26
|
} from './types'
|
|
27
|
+
import type { ProductRequest } from './types'
|
|
27
28
|
import {
|
|
28
29
|
convertNitroProductToProduct,
|
|
29
30
|
convertNitroPurchaseToPurchase,
|
|
@@ -85,36 +86,42 @@ export const endConnection = async (): Promise<boolean> => {
|
|
|
85
86
|
* Fetch products from the store
|
|
86
87
|
* @param params - Product request configuration
|
|
87
88
|
* @param params.skus - Array of product SKUs to fetch
|
|
88
|
-
* @param params.type -
|
|
89
|
+
* @param params.type - Optional filter: 'inapp' (default) for products, 'subs' for subscriptions, or 'all' for both.
|
|
89
90
|
* @returns Promise<Product[]> - Array of products from the store
|
|
90
91
|
*
|
|
91
92
|
* @example
|
|
92
93
|
* ```typescript
|
|
93
94
|
* // Regular products
|
|
94
|
-
* const products = await fetchProducts({
|
|
95
|
-
* skus: ['product1', 'product2'],
|
|
96
|
-
* type: 'inapp'
|
|
97
|
-
* });
|
|
95
|
+
* const products = await fetchProducts({ skus: ['product1', 'product2'] });
|
|
98
96
|
*
|
|
99
97
|
* // Subscriptions
|
|
100
|
-
* const subscriptions = await fetchProducts({
|
|
101
|
-
* skus: ['sub1', 'sub2'],
|
|
102
|
-
* type: 'subs'
|
|
103
|
-
* });
|
|
98
|
+
* const subscriptions = await fetchProducts({ skus: ['sub1', 'sub2'], type: 'subs' });
|
|
104
99
|
* ```
|
|
105
100
|
*/
|
|
106
101
|
export const fetchProducts = async ({
|
|
107
102
|
skus,
|
|
108
103
|
type = 'inapp',
|
|
109
|
-
}: {
|
|
110
|
-
skus: string[]
|
|
111
|
-
type?: 'inapp' | 'subs'
|
|
112
|
-
}): Promise<Product[]> => {
|
|
104
|
+
}: ProductRequest): Promise<Product[]> => {
|
|
113
105
|
try {
|
|
114
106
|
if (!skus || skus.length === 0) {
|
|
115
107
|
throw new Error('No SKUs provided')
|
|
116
108
|
}
|
|
117
109
|
|
|
110
|
+
if (type === 'all') {
|
|
111
|
+
const [inappNitro, subsNitro] = await Promise.all([
|
|
112
|
+
iap.fetchProducts(skus, 'inapp'),
|
|
113
|
+
iap.fetchProducts(skus, 'subs'),
|
|
114
|
+
])
|
|
115
|
+
const allNitro = [...inappNitro, ...subsNitro]
|
|
116
|
+
const validAll = allNitro.filter(validateNitroProduct)
|
|
117
|
+
if (validAll.length !== allNitro.length) {
|
|
118
|
+
console.warn(
|
|
119
|
+
`[fetchProducts] Some products failed validation: ${allNitro.length - validAll.length} invalid`
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
return validAll.map(convertNitroProductToProduct)
|
|
123
|
+
}
|
|
124
|
+
|
|
118
125
|
const nitroProducts = await iap.fetchProducts(skus, type)
|
|
119
126
|
|
|
120
127
|
// Validate and convert NitroProducts to TypeScript Products
|
|
@@ -202,8 +209,16 @@ export const requestPurchase = async ({
|
|
|
202
209
|
const unifiedRequest: any = {}
|
|
203
210
|
|
|
204
211
|
if (Platform.OS === 'ios' && request.ios) {
|
|
212
|
+
const iosReq = request.ios as RequestPurchaseIosProps
|
|
213
|
+
const autoFinishSubs =
|
|
214
|
+
type === 'subs' &&
|
|
215
|
+
iosReq.andDangerouslyFinishTransactionAutomatically == null
|
|
205
216
|
unifiedRequest.ios = {
|
|
206
|
-
...
|
|
217
|
+
...iosReq,
|
|
218
|
+
// Align with native SwiftUI flow: auto-finish subscriptions by default
|
|
219
|
+
...(autoFinishSubs
|
|
220
|
+
? { andDangerouslyFinishTransactionAutomatically: true }
|
|
221
|
+
: {}),
|
|
207
222
|
} as RequestPurchaseIosProps
|
|
208
223
|
}
|
|
209
224
|
|
|
@@ -230,10 +245,8 @@ export const requestPurchase = async ({
|
|
|
230
245
|
/**
|
|
231
246
|
* Get available purchases (purchased items not yet consumed/finished)
|
|
232
247
|
* @param params - Options for getting available purchases
|
|
233
|
-
* @param params.
|
|
234
|
-
* @param params.
|
|
235
|
-
* @param params.alsoPublishToEventListener - @deprecated Use alsoPublishToEventListenerIOS instead
|
|
236
|
-
* @param params.onlyIncludeActiveItems - @deprecated Use onlyIncludeActiveItemsIOS instead
|
|
248
|
+
* @param params.alsoPublishToEventListener - Whether to also publish to event listener
|
|
249
|
+
* @param params.onlyIncludeActiveItems - Whether to only include active items
|
|
237
250
|
*
|
|
238
251
|
* @example
|
|
239
252
|
* ```typescript
|
|
@@ -243,27 +256,20 @@ export const requestPurchase = async ({
|
|
|
243
256
|
* ```
|
|
244
257
|
*/
|
|
245
258
|
export const getAvailablePurchases = async ({
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
alsoPublishToEventListenerIOS,
|
|
249
|
-
onlyIncludeActiveItemsIOS,
|
|
259
|
+
alsoPublishToEventListenerIOS = false,
|
|
260
|
+
onlyIncludeActiveItemsIOS = true,
|
|
250
261
|
}: PurchaseOptions = {}): Promise<Purchase[]> => {
|
|
251
262
|
try {
|
|
252
263
|
// Create unified options
|
|
253
264
|
const options: any = {}
|
|
254
265
|
|
|
255
266
|
if (Platform.OS === 'ios') {
|
|
256
|
-
//
|
|
267
|
+
// Provide both new and deprecated keys for compatibility
|
|
257
268
|
options.ios = {
|
|
258
|
-
alsoPublishToEventListenerIOS
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
// Keep deprecated parameters for backward compatibility
|
|
263
|
-
alsoPublishToEventListener:
|
|
264
|
-
alsoPublishToEventListenerIOS ?? alsoPublishToEventListener,
|
|
265
|
-
onlyIncludeActiveItems:
|
|
266
|
-
onlyIncludeActiveItemsIOS ?? onlyIncludeActiveItems,
|
|
269
|
+
alsoPublishToEventListenerIOS,
|
|
270
|
+
onlyIncludeActiveItemsIOS,
|
|
271
|
+
alsoPublishToEventListener: alsoPublishToEventListenerIOS,
|
|
272
|
+
onlyIncludeActiveItems: onlyIncludeActiveItemsIOS,
|
|
267
273
|
}
|
|
268
274
|
} else if (Platform.OS === 'android') {
|
|
269
275
|
// For Android, we need to call twice for inapp and subs
|
|
@@ -360,6 +366,19 @@ export const finishTransaction = async ({
|
|
|
360
366
|
// It's a PurchaseResult
|
|
361
367
|
return result as NitroPurchaseResult
|
|
362
368
|
} catch (error) {
|
|
369
|
+
// If iOS transaction has already been auto-finished natively, treat as success
|
|
370
|
+
if (Platform.OS === 'ios') {
|
|
371
|
+
const err = parseErrorStringToJsonObj(error)
|
|
372
|
+
const msg = (err?.message || '').toString()
|
|
373
|
+
const code = (err?.code || '').toString()
|
|
374
|
+
if (
|
|
375
|
+
msg.includes('Transaction not found') ||
|
|
376
|
+
code === 'E_ITEM_UNAVAILABLE'
|
|
377
|
+
) {
|
|
378
|
+
// Consider already finished
|
|
379
|
+
return true
|
|
380
|
+
}
|
|
381
|
+
}
|
|
363
382
|
console.error('Failed to finish transaction:', error)
|
|
364
383
|
throw error
|
|
365
384
|
}
|
|
@@ -623,7 +642,7 @@ export const validateReceipt = async (
|
|
|
623
642
|
accessToken: string
|
|
624
643
|
isSub?: boolean
|
|
625
644
|
}
|
|
626
|
-
): Promise<
|
|
645
|
+
): Promise<import('./types').ReceiptValidationResult> => {
|
|
627
646
|
if (!iap) {
|
|
628
647
|
const errorJson = parseErrorStringToJsonObj(
|
|
629
648
|
'RnIap: Service not initialized. Call initConnection() first.'
|
|
@@ -665,7 +684,7 @@ export const validateReceipt = async (
|
|
|
665
684
|
gracePeriodEndDate: androidResult.gracePeriodEndDate,
|
|
666
685
|
parentProductId: androidResult.parentProductId,
|
|
667
686
|
productId: androidResult.productId,
|
|
668
|
-
productType: androidResult.productType,
|
|
687
|
+
productType: androidResult.productType === 'subs' ? 'subs' : 'inapp',
|
|
669
688
|
purchaseDate: androidResult.purchaseDate,
|
|
670
689
|
quantity: androidResult.quantity,
|
|
671
690
|
receiptId: androidResult.receiptId,
|
|
@@ -969,12 +988,12 @@ export const getPendingTransactionsIOS = async (): Promise<Purchase[]> => {
|
|
|
969
988
|
|
|
970
989
|
/**
|
|
971
990
|
* Show manage subscriptions screen (iOS only)
|
|
972
|
-
* @returns Promise<
|
|
991
|
+
* @returns Promise<Purchase[]> - Subscriptions where auto-renewal status changed
|
|
973
992
|
* @platform iOS
|
|
974
993
|
*/
|
|
975
|
-
export const showManageSubscriptionsIOS = async (): Promise<
|
|
994
|
+
export const showManageSubscriptionsIOS = async (): Promise<Purchase[]> => {
|
|
976
995
|
if (Platform.OS !== 'ios') {
|
|
977
|
-
return
|
|
996
|
+
return []
|
|
978
997
|
}
|
|
979
998
|
|
|
980
999
|
if (!iap) {
|
|
@@ -985,7 +1004,8 @@ export const showManageSubscriptionsIOS = async (): Promise<boolean> => {
|
|
|
985
1004
|
}
|
|
986
1005
|
|
|
987
1006
|
try {
|
|
988
|
-
|
|
1007
|
+
const nitroPurchases = await iap.showManageSubscriptionsIOS()
|
|
1008
|
+
return nitroPurchases.map(convertNitroPurchaseToPurchase)
|
|
989
1009
|
} catch (error) {
|
|
990
1010
|
console.error('[showManageSubscriptionsIOS] Failed:', error)
|
|
991
1011
|
const errorJson = parseErrorStringToJsonObj(error)
|
package/src/specs/RnIap.nitro.ts
CHANGED
|
@@ -198,6 +198,9 @@ export interface NitroPurchase {
|
|
|
198
198
|
transactionDate: number
|
|
199
199
|
purchaseToken?: string
|
|
200
200
|
platform: string
|
|
201
|
+
quantity: number
|
|
202
|
+
purchaseState: string
|
|
203
|
+
isAutoRenewing: boolean
|
|
201
204
|
|
|
202
205
|
// iOS specific fields
|
|
203
206
|
quantityIOS?: number
|
|
@@ -233,8 +236,9 @@ export interface NitroProduct {
|
|
|
233
236
|
platform: string
|
|
234
237
|
|
|
235
238
|
// iOS specific fields
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
typeIOS?: string
|
|
240
|
+
isFamilyShareableIOS?: boolean
|
|
241
|
+
jsonRepresentationIOS?: string
|
|
238
242
|
subscriptionPeriodUnitIOS?: string
|
|
239
243
|
subscriptionPeriodNumberIOS?: number
|
|
240
244
|
introductoryPriceIOS?: string
|
|
@@ -244,13 +248,13 @@ export interface NitroProduct {
|
|
|
244
248
|
introductoryPriceSubscriptionPeriodIOS?: string
|
|
245
249
|
|
|
246
250
|
// Android specific fields
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
originalPriceAndroid?: string
|
|
252
|
+
originalPriceAmountMicrosAndroid?: number
|
|
253
|
+
introductoryPriceValueAndroid?: number
|
|
254
|
+
introductoryPriceCyclesAndroid?: number
|
|
255
|
+
introductoryPricePeriodAndroid?: string
|
|
256
|
+
subscriptionPeriodAndroid?: string
|
|
257
|
+
freeTrialPeriodAndroid?: string
|
|
254
258
|
subscriptionOfferDetailsAndroid?: string // Android subscription offer details as JSON string
|
|
255
259
|
}
|
|
256
260
|
|
|
@@ -452,10 +456,10 @@ export interface RnIap
|
|
|
452
456
|
|
|
453
457
|
/**
|
|
454
458
|
* Show manage subscriptions screen (iOS only)
|
|
455
|
-
* @returns Promise<
|
|
459
|
+
* @returns Promise<NitroPurchase[]> - Array of updated subscriptions with renewal info
|
|
456
460
|
* @platform iOS
|
|
457
461
|
*/
|
|
458
|
-
showManageSubscriptionsIOS(): Promise<
|
|
462
|
+
showManageSubscriptionsIOS(): Promise<NitroPurchase[]>
|
|
459
463
|
|
|
460
464
|
/**
|
|
461
465
|
* Check if user is eligible for intro offer (iOS only)
|