react-native-iap 14.3.9 → 14.4.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/NitroIap.podspec +11 -1
- package/README.md +2 -3
- package/android/build.gradle +24 -1
- package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +369 -124
- package/android/src/main/java/com/margelo/nitro/iap/RnIapLog.kt +64 -0
- package/ios/HybridRnIap.swift +525 -362
- package/ios/RnIapHelper.swift +224 -0
- package/ios/RnIapLog.swift +127 -0
- package/lib/module/hooks/useIAP.js +2 -34
- package/lib/module/hooks/useIAP.js.map +1 -1
- package/lib/module/index.js +52 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/plugin/src/withIAP.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useIAP.d.ts +0 -12
- package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/RnIap.nitro.d.ts +24 -0
- package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +8 -6
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +64 -0
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +4 -0
- package/nitrogen/generated/android/c++/JIapPlatform.hpp +3 -3
- package/nitrogen/generated/android/c++/JPurchaseAndroid.hpp +6 -2
- package/nitrogen/generated/android/c++/JPurchaseIOS.hpp +4 -0
- package/nitrogen/generated/android/c++/JPurchaseState.hpp +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +16 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/IapPlatform.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseAndroid.kt +4 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseIOS.kt +3 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseState.kt +5 -5
- package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +32 -0
- package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +4 -0
- package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +82 -0
- package/nitrogen/generated/ios/swift/IapPlatform.swift +4 -4
- package/nitrogen/generated/ios/swift/PurchaseAndroid.swift +32 -2
- package/nitrogen/generated/ios/swift/PurchaseIOS.swift +13 -2
- package/nitrogen/generated/ios/swift/PurchaseState.swift +8 -8
- package/nitrogen/generated/shared/c++/HybridRnIapSpec.cpp +4 -0
- package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +4 -0
- package/nitrogen/generated/shared/c++/IapPlatform.hpp +5 -5
- package/nitrogen/generated/shared/c++/PurchaseAndroid.hpp +6 -2
- package/nitrogen/generated/shared/c++/PurchaseIOS.hpp +5 -1
- package/nitrogen/generated/shared/c++/PurchaseState.hpp +11 -11
- package/openiap-versions.json +5 -0
- package/package.json +3 -2
- package/plugin/build/withIAP.js +35 -3
- package/plugin/src/withIAP.ts +44 -3
- package/src/hooks/useIAP.ts +3 -71
- package/src/index.ts +61 -2
- package/src/specs/RnIap.nitro.ts +28 -0
- package/src/types.ts +8 -6
|
@@ -67,12 +67,13 @@ namespace margelo::nitro::iap {
|
|
|
67
67
|
std::optional<std::string> storefrontCountryCodeIOS SWIFT_PRIVATE;
|
|
68
68
|
std::optional<std::string> subscriptionGroupIdIOS SWIFT_PRIVATE;
|
|
69
69
|
double transactionDate SWIFT_PRIVATE;
|
|
70
|
+
std::string transactionId SWIFT_PRIVATE;
|
|
70
71
|
std::optional<std::string> transactionReasonIOS SWIFT_PRIVATE;
|
|
71
72
|
std::optional<std::string> webOrderLineItemIdIOS SWIFT_PRIVATE;
|
|
72
73
|
|
|
73
74
|
public:
|
|
74
75
|
PurchaseIOS() = default;
|
|
75
|
-
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::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), transactionReasonIOS(transactionReasonIOS), webOrderLineItemIdIOS(webOrderLineItemIdIOS) {}
|
|
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) {}
|
|
76
77
|
};
|
|
77
78
|
|
|
78
79
|
} // namespace margelo::nitro::iap
|
|
@@ -113,6 +114,7 @@ namespace margelo::nitro {
|
|
|
113
114
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "storefrontCountryCodeIOS")),
|
|
114
115
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "subscriptionGroupIdIOS")),
|
|
115
116
|
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, "transactionDate")),
|
|
117
|
+
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, "transactionId")),
|
|
116
118
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "transactionReasonIOS")),
|
|
117
119
|
JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "webOrderLineItemIdIOS"))
|
|
118
120
|
);
|
|
@@ -147,6 +149,7 @@ namespace margelo::nitro {
|
|
|
147
149
|
obj.setProperty(runtime, "storefrontCountryCodeIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.storefrontCountryCodeIOS));
|
|
148
150
|
obj.setProperty(runtime, "subscriptionGroupIdIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.subscriptionGroupIdIOS));
|
|
149
151
|
obj.setProperty(runtime, "transactionDate", JSIConverter<double>::toJSI(runtime, arg.transactionDate));
|
|
152
|
+
obj.setProperty(runtime, "transactionId", JSIConverter<std::string>::toJSI(runtime, arg.transactionId));
|
|
150
153
|
obj.setProperty(runtime, "transactionReasonIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.transactionReasonIOS));
|
|
151
154
|
obj.setProperty(runtime, "webOrderLineItemIdIOS", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.webOrderLineItemIdIOS));
|
|
152
155
|
return obj;
|
|
@@ -184,6 +187,7 @@ namespace margelo::nitro {
|
|
|
184
187
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "storefrontCountryCodeIOS"))) return false;
|
|
185
188
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "subscriptionGroupIdIOS"))) return false;
|
|
186
189
|
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, "transactionDate"))) return false;
|
|
190
|
+
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, "transactionId"))) return false;
|
|
187
191
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "transactionReasonIOS"))) return false;
|
|
188
192
|
if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "webOrderLineItemIdIOS"))) return false;
|
|
189
193
|
return true;
|
|
@@ -29,11 +29,11 @@ namespace margelo::nitro::iap {
|
|
|
29
29
|
* An enum which can be represented as a JavaScript union (PurchaseState).
|
|
30
30
|
*/
|
|
31
31
|
enum class PurchaseState {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
PENDING SWIFT_NAME(pending) = 0,
|
|
33
|
+
PURCHASED SWIFT_NAME(purchased) = 1,
|
|
34
|
+
FAILED SWIFT_NAME(failed) = 2,
|
|
35
|
+
RESTORED SWIFT_NAME(restored) = 3,
|
|
36
|
+
DEFERRED SWIFT_NAME(deferred) = 4,
|
|
37
37
|
UNKNOWN SWIFT_NAME(unknown) = 5,
|
|
38
38
|
} CLOSED_ENUM;
|
|
39
39
|
|
|
@@ -47,11 +47,11 @@ namespace margelo::nitro {
|
|
|
47
47
|
static inline margelo::nitro::iap::PurchaseState fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
|
|
48
48
|
std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);
|
|
49
49
|
switch (hashString(unionValue.c_str(), unionValue.size())) {
|
|
50
|
-
case hashString("deferred"): return margelo::nitro::iap::PurchaseState::DEFERRED;
|
|
51
|
-
case hashString("failed"): return margelo::nitro::iap::PurchaseState::FAILED;
|
|
52
50
|
case hashString("pending"): return margelo::nitro::iap::PurchaseState::PENDING;
|
|
53
51
|
case hashString("purchased"): return margelo::nitro::iap::PurchaseState::PURCHASED;
|
|
52
|
+
case hashString("failed"): return margelo::nitro::iap::PurchaseState::FAILED;
|
|
54
53
|
case hashString("restored"): return margelo::nitro::iap::PurchaseState::RESTORED;
|
|
54
|
+
case hashString("deferred"): return margelo::nitro::iap::PurchaseState::DEFERRED;
|
|
55
55
|
case hashString("unknown"): return margelo::nitro::iap::PurchaseState::UNKNOWN;
|
|
56
56
|
default: [[unlikely]]
|
|
57
57
|
throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum PurchaseState - invalid value!");
|
|
@@ -59,11 +59,11 @@ namespace margelo::nitro {
|
|
|
59
59
|
}
|
|
60
60
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::iap::PurchaseState arg) {
|
|
61
61
|
switch (arg) {
|
|
62
|
-
case margelo::nitro::iap::PurchaseState::DEFERRED: return JSIConverter<std::string>::toJSI(runtime, "deferred");
|
|
63
|
-
case margelo::nitro::iap::PurchaseState::FAILED: return JSIConverter<std::string>::toJSI(runtime, "failed");
|
|
64
62
|
case margelo::nitro::iap::PurchaseState::PENDING: return JSIConverter<std::string>::toJSI(runtime, "pending");
|
|
65
63
|
case margelo::nitro::iap::PurchaseState::PURCHASED: return JSIConverter<std::string>::toJSI(runtime, "purchased");
|
|
64
|
+
case margelo::nitro::iap::PurchaseState::FAILED: return JSIConverter<std::string>::toJSI(runtime, "failed");
|
|
66
65
|
case margelo::nitro::iap::PurchaseState::RESTORED: return JSIConverter<std::string>::toJSI(runtime, "restored");
|
|
66
|
+
case margelo::nitro::iap::PurchaseState::DEFERRED: return JSIConverter<std::string>::toJSI(runtime, "deferred");
|
|
67
67
|
case margelo::nitro::iap::PurchaseState::UNKNOWN: return JSIConverter<std::string>::toJSI(runtime, "unknown");
|
|
68
68
|
default: [[unlikely]]
|
|
69
69
|
throw std::invalid_argument("Cannot convert PurchaseState to JS - invalid value: "
|
|
@@ -76,11 +76,11 @@ namespace margelo::nitro {
|
|
|
76
76
|
}
|
|
77
77
|
std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);
|
|
78
78
|
switch (hashString(unionValue.c_str(), unionValue.size())) {
|
|
79
|
-
case hashString("deferred"):
|
|
80
|
-
case hashString("failed"):
|
|
81
79
|
case hashString("pending"):
|
|
82
80
|
case hashString("purchased"):
|
|
81
|
+
case hashString("failed"):
|
|
83
82
|
case hashString("restored"):
|
|
83
|
+
case hashString("deferred"):
|
|
84
84
|
case hashString("unknown"):
|
|
85
85
|
return true;
|
|
86
86
|
default:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-iap",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.4.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",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"cpp",
|
|
25
25
|
"nitrogen",
|
|
26
26
|
"nitro.json",
|
|
27
|
+
"openiap-versions.json",
|
|
27
28
|
"*.podspec",
|
|
28
29
|
"app.plugin.js",
|
|
29
30
|
"react-native.config.js",
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
"prepare:husky": "husky install",
|
|
68
69
|
"precommit": "lint-staged",
|
|
69
70
|
"ci:check": "./scripts/ci-check.sh",
|
|
70
|
-
"generate:types": "node scripts/update-types.mjs
|
|
71
|
+
"generate:types": "node scripts/update-types.mjs",
|
|
71
72
|
"generate:icon": "cd docs/static/img && npx sharp-cli resize 32 32 --input icon.png --output favicon-32x32.png && npx sharp-cli resize 16 16 --input icon.png --output favicon-16x16.png && npx sharp-cli resize 192 192 --input icon.png --output android-chrome-192x192.png && npx sharp-cli resize 512 512 --input icon.png --output android-chrome-512x512.png && npx sharp-cli resize 180 180 --input icon.png --output apple-touch-icon.png && npx sharp-cli resize 1200 630 --input icon.png --output og-image.png && npx sharp-cli resize 150 150 --input icon.png --output favicon.png && npx sharp-cli --input favicon-32x32.png --output favicon.ico",
|
|
72
73
|
"commitlint": "commitlint"
|
|
73
74
|
},
|
package/plugin/build/withIAP.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = exports.modifyProjectBuildGradle = void 0;
|
|
4
4
|
const config_plugins_1 = require("expo/config-plugins");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
5
7
|
const pkg = require('../../package.json');
|
|
6
8
|
// Global flag to prevent duplicate logs
|
|
7
9
|
let hasLoggedPluginExecution = false;
|
|
@@ -31,16 +33,46 @@ const modifyProjectBuildGradle = (gradle) => {
|
|
|
31
33
|
};
|
|
32
34
|
exports.modifyProjectBuildGradle = modifyProjectBuildGradle;
|
|
33
35
|
const OPENIAP_COORD = 'io.github.hyochan.openiap:openiap-google';
|
|
34
|
-
|
|
36
|
+
function loadOpenIapConfig() {
|
|
37
|
+
const versionsPath = (0, node_path_1.resolve)(__dirname, '../../openiap-versions.json');
|
|
38
|
+
try {
|
|
39
|
+
const raw = (0, node_fs_1.readFileSync)(versionsPath, 'utf8');
|
|
40
|
+
const parsed = JSON.parse(raw);
|
|
41
|
+
const googleVersion = typeof parsed?.google === 'string' ? parsed.google.trim() : '';
|
|
42
|
+
if (!googleVersion) {
|
|
43
|
+
throw new Error('react-native-iap: "google" version missing or invalid in openiap-versions.json');
|
|
44
|
+
}
|
|
45
|
+
return { google: googleVersion };
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
throw new Error(`react-native-iap: Unable to load openiap-versions.json (${error instanceof Error ? error.message : error})`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
let cachedOpenIapVersion = null;
|
|
52
|
+
const getOpenIapVersion = () => {
|
|
53
|
+
if (cachedOpenIapVersion) {
|
|
54
|
+
return cachedOpenIapVersion;
|
|
55
|
+
}
|
|
56
|
+
cachedOpenIapVersion = loadOpenIapConfig().google;
|
|
57
|
+
return cachedOpenIapVersion;
|
|
58
|
+
};
|
|
35
59
|
const modifyAppBuildGradle = (gradle) => {
|
|
36
60
|
let modified = gradle;
|
|
61
|
+
let openiapVersion;
|
|
62
|
+
try {
|
|
63
|
+
openiapVersion = getOpenIapVersion();
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
config_plugins_1.WarningAggregator.addWarningAndroid('react-native-iap', `react-native-iap: Failed to resolve OpenIAP version (${error instanceof Error ? error.message : error})`);
|
|
67
|
+
return gradle;
|
|
68
|
+
}
|
|
37
69
|
// Replace legacy Billing/GMS instructions with OpenIAP Google library
|
|
38
70
|
// Remove any old billingclient or play-services-base lines we may have added previously
|
|
39
71
|
modified = modified
|
|
40
72
|
.replace(/^[ \t]*(implementation|api)[ \t]+["']com\.android\.billingclient:billing-ktx:[^"']+["'][ \t]*$/gim, '')
|
|
41
73
|
.replace(/^[ \t]*(implementation|api)[ \t]+["']com\.google\.android\.gms:play-services-base:[^"']+["'][ \t]*$/gim, '')
|
|
42
74
|
.replace(/\n{3,}/g, '\n\n');
|
|
43
|
-
const openiapDep = ` implementation "${OPENIAP_COORD}:${
|
|
75
|
+
const openiapDep = ` implementation "${OPENIAP_COORD}:${openiapVersion}"`;
|
|
44
76
|
if (!modified.includes(OPENIAP_COORD)) {
|
|
45
77
|
if (!/dependencies\s*{/.test(modified)) {
|
|
46
78
|
modified += `\n\ndependencies {\n${openiapDep}\n}\n`;
|
|
@@ -49,7 +81,7 @@ const modifyAppBuildGradle = (gradle) => {
|
|
|
49
81
|
modified = addLineToGradle(modified, /dependencies\s*{/, openiapDep);
|
|
50
82
|
}
|
|
51
83
|
if (!hasLoggedPluginExecution) {
|
|
52
|
-
console.log(`🛠️ react-native-iap: Added OpenIAP (${
|
|
84
|
+
console.log(`🛠️ react-native-iap: Added OpenIAP (${openiapVersion}) to build.gradle`);
|
|
53
85
|
}
|
|
54
86
|
}
|
|
55
87
|
return modified;
|
package/plugin/src/withIAP.ts
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
} from 'expo/config-plugins';
|
|
8
8
|
import type {ConfigPlugin} from 'expo/config-plugins';
|
|
9
9
|
import type {ExpoConfig} from '@expo/config-types';
|
|
10
|
+
import {readFileSync} from 'node:fs';
|
|
11
|
+
import {resolve as resolvePath} from 'node:path';
|
|
10
12
|
|
|
11
13
|
const pkg = require('../../package.json');
|
|
12
14
|
|
|
@@ -46,11 +48,50 @@ export const modifyProjectBuildGradle = (gradle: string): string => {
|
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
const OPENIAP_COORD = 'io.github.hyochan.openiap:openiap-google';
|
|
49
|
-
|
|
51
|
+
|
|
52
|
+
function loadOpenIapConfig(): {google: string} {
|
|
53
|
+
const versionsPath = resolvePath(__dirname, '../../openiap-versions.json');
|
|
54
|
+
try {
|
|
55
|
+
const raw = readFileSync(versionsPath, 'utf8');
|
|
56
|
+
const parsed = JSON.parse(raw);
|
|
57
|
+
const googleVersion =
|
|
58
|
+
typeof parsed?.google === 'string' ? parsed.google.trim() : '';
|
|
59
|
+
if (!googleVersion) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
'react-native-iap: "google" version missing or invalid in openiap-versions.json',
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return {google: googleVersion};
|
|
65
|
+
} catch (error) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`react-native-iap: Unable to load openiap-versions.json (${error instanceof Error ? error.message : error})`,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let cachedOpenIapVersion: string | null = null;
|
|
73
|
+
const getOpenIapVersion = (): string => {
|
|
74
|
+
if (cachedOpenIapVersion) {
|
|
75
|
+
return cachedOpenIapVersion;
|
|
76
|
+
}
|
|
77
|
+
cachedOpenIapVersion = loadOpenIapConfig().google;
|
|
78
|
+
return cachedOpenIapVersion;
|
|
79
|
+
};
|
|
50
80
|
|
|
51
81
|
const modifyAppBuildGradle = (gradle: string): string => {
|
|
52
82
|
let modified = gradle;
|
|
53
83
|
|
|
84
|
+
let openiapVersion: string;
|
|
85
|
+
try {
|
|
86
|
+
openiapVersion = getOpenIapVersion();
|
|
87
|
+
} catch (error) {
|
|
88
|
+
WarningAggregator.addWarningAndroid(
|
|
89
|
+
'react-native-iap',
|
|
90
|
+
`react-native-iap: Failed to resolve OpenIAP version (${error instanceof Error ? error.message : error})`,
|
|
91
|
+
);
|
|
92
|
+
return gradle;
|
|
93
|
+
}
|
|
94
|
+
|
|
54
95
|
// Replace legacy Billing/GMS instructions with OpenIAP Google library
|
|
55
96
|
// Remove any old billingclient or play-services-base lines we may have added previously
|
|
56
97
|
modified = modified
|
|
@@ -64,7 +105,7 @@ const modifyAppBuildGradle = (gradle: string): string => {
|
|
|
64
105
|
)
|
|
65
106
|
.replace(/\n{3,}/g, '\n\n');
|
|
66
107
|
|
|
67
|
-
const openiapDep = ` implementation "${OPENIAP_COORD}:${
|
|
108
|
+
const openiapDep = ` implementation "${OPENIAP_COORD}:${openiapVersion}"`;
|
|
68
109
|
|
|
69
110
|
if (!modified.includes(OPENIAP_COORD)) {
|
|
70
111
|
if (!/dependencies\s*{/.test(modified)) {
|
|
@@ -74,7 +115,7 @@ const modifyAppBuildGradle = (gradle: string): string => {
|
|
|
74
115
|
}
|
|
75
116
|
if (!hasLoggedPluginExecution) {
|
|
76
117
|
console.log(
|
|
77
|
-
`🛠️ react-native-iap: Added OpenIAP (${
|
|
118
|
+
`🛠️ react-native-iap: Added OpenIAP (${openiapVersion}) to build.gradle`,
|
|
78
119
|
);
|
|
79
120
|
}
|
|
80
121
|
}
|
package/src/hooks/useIAP.ts
CHANGED
|
@@ -45,8 +45,6 @@ interface EventSubscription {
|
|
|
45
45
|
type UseIap = {
|
|
46
46
|
connected: boolean;
|
|
47
47
|
products: Product[];
|
|
48
|
-
promotedProductsIOS: Purchase[];
|
|
49
|
-
promotedProductIdIOS?: string;
|
|
50
48
|
subscriptions: ProductSubscription[];
|
|
51
49
|
availablePurchases: Purchase[];
|
|
52
50
|
promotedProductIOS?: Product;
|
|
@@ -57,16 +55,6 @@ type UseIap = {
|
|
|
57
55
|
skus: string[];
|
|
58
56
|
type?: ProductQueryType | null;
|
|
59
57
|
}) => Promise<void>;
|
|
60
|
-
/**
|
|
61
|
-
* @deprecated Use fetchProducts({ skus, type: 'in-app' }) instead. This method will be removed in version 3.0.0.
|
|
62
|
-
* Note: This method internally uses fetchProducts, so no deprecation warning is shown.
|
|
63
|
-
*/
|
|
64
|
-
getProducts: (skus: string[]) => Promise<void>;
|
|
65
|
-
/**
|
|
66
|
-
* @deprecated Use fetchProducts({ skus, type: 'subs' }) instead. This method will be removed in version 3.0.0.
|
|
67
|
-
* Note: This method internally uses fetchProducts, so no deprecation warning is shown.
|
|
68
|
-
*/
|
|
69
|
-
getSubscriptions: (skus: string[]) => Promise<void>;
|
|
70
58
|
requestPurchase: (
|
|
71
59
|
params: RequestPurchaseProps,
|
|
72
60
|
) => Promise<RequestPurchaseResult | null>;
|
|
@@ -103,11 +91,9 @@ export interface UseIapOptions {
|
|
|
103
91
|
export function useIAP(options?: UseIapOptions): UseIap {
|
|
104
92
|
const [connected, setConnected] = useState<boolean>(false);
|
|
105
93
|
const [products, setProducts] = useState<Product[]>([]);
|
|
106
|
-
const [promotedProductsIOS] = useState<Purchase[]>([]);
|
|
107
94
|
const [subscriptions, setSubscriptions] = useState<ProductSubscription[]>([]);
|
|
108
95
|
const [availablePurchases, setAvailablePurchases] = useState<Purchase[]>([]);
|
|
109
96
|
const [promotedProductIOS, setPromotedProductIOS] = useState<Product>();
|
|
110
|
-
const [promotedProductIdIOS] = useState<string>();
|
|
111
97
|
const [activeSubscriptions, setActiveSubscriptions] = useState<
|
|
112
98
|
ActiveSubscription[]
|
|
113
99
|
>([]);
|
|
@@ -147,7 +133,6 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
147
133
|
const subscriptionsRef = useRef<{
|
|
148
134
|
purchaseUpdate?: EventSubscription;
|
|
149
135
|
purchaseError?: EventSubscription;
|
|
150
|
-
promotedProductsIOS?: EventSubscription;
|
|
151
136
|
promotedProductIOS?: EventSubscription;
|
|
152
137
|
}>({});
|
|
153
138
|
|
|
@@ -157,54 +142,6 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
157
142
|
subscriptionsRefState.current = subscriptions;
|
|
158
143
|
}, [subscriptions]);
|
|
159
144
|
|
|
160
|
-
const getProductsInternal = useCallback(
|
|
161
|
-
async (skus: string[]): Promise<void> => {
|
|
162
|
-
try {
|
|
163
|
-
const result = await fetchProducts({
|
|
164
|
-
skus,
|
|
165
|
-
type: 'in-app',
|
|
166
|
-
});
|
|
167
|
-
const newProducts = (result ?? []).filter(
|
|
168
|
-
(item): item is Product => item.type === 'in-app',
|
|
169
|
-
);
|
|
170
|
-
setProducts((prevProducts: Product[]) =>
|
|
171
|
-
mergeWithDuplicateCheck(
|
|
172
|
-
prevProducts,
|
|
173
|
-
newProducts,
|
|
174
|
-
(product: Product) => product.id,
|
|
175
|
-
),
|
|
176
|
-
);
|
|
177
|
-
} catch (error) {
|
|
178
|
-
console.error('Error fetching products:', error);
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
[mergeWithDuplicateCheck],
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
const getSubscriptionsInternal = useCallback(
|
|
185
|
-
async (skus: string[]): Promise<void> => {
|
|
186
|
-
try {
|
|
187
|
-
const result = await fetchProducts({
|
|
188
|
-
skus,
|
|
189
|
-
type: 'subs',
|
|
190
|
-
});
|
|
191
|
-
const newSubscriptions = (result ?? []).filter(
|
|
192
|
-
(item): item is ProductSubscription => item.type === 'subs',
|
|
193
|
-
);
|
|
194
|
-
setSubscriptions((prevSubscriptions: ProductSubscription[]) =>
|
|
195
|
-
mergeWithDuplicateCheck(
|
|
196
|
-
prevSubscriptions,
|
|
197
|
-
newSubscriptions,
|
|
198
|
-
(subscription: ProductSubscription) => subscription.id,
|
|
199
|
-
),
|
|
200
|
-
);
|
|
201
|
-
} catch (error) {
|
|
202
|
-
console.error('Error fetching subscriptions:', error);
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
[mergeWithDuplicateCheck],
|
|
206
|
-
);
|
|
207
|
-
|
|
208
145
|
const fetchProductsInternal = useCallback(
|
|
209
146
|
async (params: {
|
|
210
147
|
skus: string[];
|
|
@@ -395,9 +332,11 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
395
332
|
});
|
|
396
333
|
|
|
397
334
|
if (Platform.OS === 'ios') {
|
|
398
|
-
|
|
335
|
+
// iOS promoted products listener
|
|
336
|
+
subscriptionsRef.current.promotedProductIOS = promotedProductListenerIOS(
|
|
399
337
|
(product: Product) => {
|
|
400
338
|
setPromotedProductIOS(product);
|
|
339
|
+
|
|
401
340
|
if (optionsRef.current?.onPromotedProductIOS) {
|
|
402
341
|
optionsRef.current.onPromotedProductIOS(product);
|
|
403
342
|
}
|
|
@@ -410,9 +349,7 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
410
349
|
if (!result) {
|
|
411
350
|
// Clean up some listeners but leave purchaseError for potential retries
|
|
412
351
|
subscriptionsRef.current.purchaseUpdate?.remove();
|
|
413
|
-
subscriptionsRef.current.promotedProductsIOS?.remove();
|
|
414
352
|
subscriptionsRef.current.purchaseUpdate = undefined;
|
|
415
|
-
subscriptionsRef.current.promotedProductsIOS = undefined;
|
|
416
353
|
return;
|
|
417
354
|
}
|
|
418
355
|
}, [getActiveSubscriptionsInternal, getAvailablePurchasesInternal]);
|
|
@@ -424,7 +361,6 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
424
361
|
return () => {
|
|
425
362
|
currentSubscriptions.purchaseUpdate?.remove();
|
|
426
363
|
currentSubscriptions.purchaseError?.remove();
|
|
427
|
-
currentSubscriptions.promotedProductsIOS?.remove();
|
|
428
364
|
currentSubscriptions.promotedProductIOS?.remove();
|
|
429
365
|
// Keep connection alive across screens to avoid race conditions
|
|
430
366
|
setConnected(false);
|
|
@@ -434,8 +370,6 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
434
370
|
return {
|
|
435
371
|
connected,
|
|
436
372
|
products,
|
|
437
|
-
promotedProductsIOS,
|
|
438
|
-
promotedProductIdIOS,
|
|
439
373
|
subscriptions,
|
|
440
374
|
finishTransaction,
|
|
441
375
|
availablePurchases,
|
|
@@ -453,8 +387,6 @@ export function useIAP(options?: UseIapOptions): UseIap {
|
|
|
453
387
|
console.warn('Failed to restore purchases:', e);
|
|
454
388
|
}
|
|
455
389
|
},
|
|
456
|
-
getProducts: getProductsInternal,
|
|
457
|
-
getSubscriptions: getSubscriptionsInternal,
|
|
458
390
|
getPromotedProductIOS,
|
|
459
391
|
requestPurchaseOnPromotedProductIOS,
|
|
460
392
|
getActiveSubscriptions: getActiveSubscriptionsInternal,
|
package/src/index.ts
CHANGED
|
@@ -443,7 +443,10 @@ export const getPromotedProductIOS: QueryField<
|
|
|
443
443
|
}
|
|
444
444
|
|
|
445
445
|
try {
|
|
446
|
-
const nitroProduct =
|
|
446
|
+
const nitroProduct =
|
|
447
|
+
typeof IAP.instance.getPromotedProductIOS === 'function'
|
|
448
|
+
? await IAP.instance.getPromotedProductIOS()
|
|
449
|
+
: await IAP.instance.requestPromotedProductIOS();
|
|
447
450
|
if (!nitroProduct) {
|
|
448
451
|
return null;
|
|
449
452
|
}
|
|
@@ -638,6 +641,40 @@ export const getReceiptDataIOS: QueryField<'getReceiptDataIOS'> = async () => {
|
|
|
638
641
|
}
|
|
639
642
|
};
|
|
640
643
|
|
|
644
|
+
export const getReceiptIOS = async (): Promise<string> => {
|
|
645
|
+
if (Platform.OS !== 'ios') {
|
|
646
|
+
throw new Error('getReceiptIOS is only available on iOS');
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
try {
|
|
650
|
+
if (typeof IAP.instance.getReceiptIOS === 'function') {
|
|
651
|
+
return await IAP.instance.getReceiptIOS();
|
|
652
|
+
}
|
|
653
|
+
return await IAP.instance.getReceiptDataIOS();
|
|
654
|
+
} catch (error) {
|
|
655
|
+
console.error('[getReceiptIOS] Failed:', error);
|
|
656
|
+
const errorJson = parseErrorStringToJsonObj(error);
|
|
657
|
+
throw new Error(errorJson.message);
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
export const requestReceiptRefreshIOS = async (): Promise<string> => {
|
|
662
|
+
if (Platform.OS !== 'ios') {
|
|
663
|
+
throw new Error('requestReceiptRefreshIOS is only available on iOS');
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
try {
|
|
667
|
+
if (typeof IAP.instance.requestReceiptRefreshIOS === 'function') {
|
|
668
|
+
return await IAP.instance.requestReceiptRefreshIOS();
|
|
669
|
+
}
|
|
670
|
+
return await IAP.instance.getReceiptDataIOS();
|
|
671
|
+
} catch (error) {
|
|
672
|
+
console.error('[requestReceiptRefreshIOS] Failed:', error);
|
|
673
|
+
const errorJson = parseErrorStringToJsonObj(error);
|
|
674
|
+
throw new Error(errorJson.message);
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
|
|
641
678
|
export const isTransactionVerifiedIOS: QueryField<
|
|
642
679
|
'isTransactionVerifiedIOS'
|
|
643
680
|
> = async (sku) => {
|
|
@@ -1258,13 +1295,35 @@ export const deepLinkToSubscriptions: MutationField<
|
|
|
1258
1295
|
}
|
|
1259
1296
|
if (Platform.OS === 'ios') {
|
|
1260
1297
|
try {
|
|
1261
|
-
|
|
1298
|
+
if (typeof IAP.instance.deepLinkToSubscriptionsIOS === 'function') {
|
|
1299
|
+
await IAP.instance.deepLinkToSubscriptionsIOS();
|
|
1300
|
+
} else {
|
|
1301
|
+
await IAP.instance.showManageSubscriptionsIOS();
|
|
1302
|
+
}
|
|
1262
1303
|
} catch (error) {
|
|
1263
1304
|
console.warn('[deepLinkToSubscriptions] Failed on iOS:', error);
|
|
1264
1305
|
}
|
|
1265
1306
|
}
|
|
1266
1307
|
};
|
|
1267
1308
|
|
|
1309
|
+
export const deepLinkToSubscriptionsIOS = async (): Promise<boolean> => {
|
|
1310
|
+
if (Platform.OS !== 'ios') {
|
|
1311
|
+
throw new Error('deepLinkToSubscriptionsIOS is only available on iOS');
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
try {
|
|
1315
|
+
if (typeof IAP.instance.deepLinkToSubscriptionsIOS === 'function') {
|
|
1316
|
+
return await IAP.instance.deepLinkToSubscriptionsIOS();
|
|
1317
|
+
}
|
|
1318
|
+
await IAP.instance.showManageSubscriptionsIOS();
|
|
1319
|
+
return true;
|
|
1320
|
+
} catch (error) {
|
|
1321
|
+
console.error('[deepLinkToSubscriptionsIOS] Failed:', error);
|
|
1322
|
+
const errorJson = parseErrorStringToJsonObj(error);
|
|
1323
|
+
throw new Error(errorJson.message);
|
|
1324
|
+
}
|
|
1325
|
+
};
|
|
1326
|
+
|
|
1268
1327
|
/**
|
|
1269
1328
|
* iOS only - Gets the original app transaction ID if the app was purchased from the App Store
|
|
1270
1329
|
* @platform iOS
|
package/src/specs/RnIap.nitro.ts
CHANGED
|
@@ -369,6 +369,13 @@ export interface RnIap extends HybridObject<{ios: 'swift'; android: 'kotlin'}> {
|
|
|
369
369
|
*/
|
|
370
370
|
requestPromotedProductIOS(): Promise<NitroProduct | null>;
|
|
371
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Retrieve the currently promoted product without initiating a purchase flow (iOS only)
|
|
374
|
+
* @returns Promise<NitroProduct | null> - The promoted product or null if none available
|
|
375
|
+
* @platform iOS
|
|
376
|
+
*/
|
|
377
|
+
getPromotedProductIOS(): Promise<NitroProduct | null>;
|
|
378
|
+
|
|
372
379
|
/**
|
|
373
380
|
* Buy the promoted product from the App Store (iOS only)
|
|
374
381
|
* @returns Promise<void>
|
|
@@ -443,6 +450,13 @@ export interface RnIap extends HybridObject<{ios: 'swift'; android: 'kotlin'}> {
|
|
|
443
450
|
*/
|
|
444
451
|
showManageSubscriptionsIOS(): Promise<NitroPurchase[]>;
|
|
445
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Deep link to the native subscription management UI (iOS only)
|
|
455
|
+
* @returns Promise<boolean> - True if the deep link request succeeded
|
|
456
|
+
* @platform iOS
|
|
457
|
+
*/
|
|
458
|
+
deepLinkToSubscriptionsIOS(): Promise<boolean>;
|
|
459
|
+
|
|
446
460
|
/**
|
|
447
461
|
* Check if user is eligible for intro offer (iOS only)
|
|
448
462
|
* @param groupID - The subscription group ID
|
|
@@ -458,6 +472,20 @@ export interface RnIap extends HybridObject<{ios: 'swift'; android: 'kotlin'}> {
|
|
|
458
472
|
*/
|
|
459
473
|
getReceiptDataIOS(): Promise<string>;
|
|
460
474
|
|
|
475
|
+
/**
|
|
476
|
+
* Alias for getReceiptDataIOS maintained for compatibility (iOS only)
|
|
477
|
+
* @returns Promise<string> - Base64 encoded receipt data
|
|
478
|
+
* @platform iOS
|
|
479
|
+
*/
|
|
480
|
+
getReceiptIOS(): Promise<string>;
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Request a refreshed receipt from the App Store (iOS only)
|
|
484
|
+
* @returns Promise<string> - Updated Base64 encoded receipt data
|
|
485
|
+
* @platform iOS
|
|
486
|
+
*/
|
|
487
|
+
requestReceiptRefreshIOS(): Promise<string>;
|
|
488
|
+
|
|
461
489
|
/**
|
|
462
490
|
* Check if transaction is verified (iOS only)
|
|
463
491
|
* @param sku - The product SKU
|
package/src/types.ts
CHANGED
|
@@ -128,9 +128,9 @@ export enum ErrorCode {
|
|
|
128
128
|
|
|
129
129
|
export type FetchProductsResult = Product[] | ProductSubscription[] | null;
|
|
130
130
|
|
|
131
|
-
export type IapEvent = '
|
|
131
|
+
export type IapEvent = 'purchase-updated' | 'purchase-error' | 'promoted-product-ios';
|
|
132
132
|
|
|
133
|
-
export type IapPlatform = '
|
|
133
|
+
export type IapPlatform = 'ios' | 'android';
|
|
134
134
|
|
|
135
135
|
export interface Mutation {
|
|
136
136
|
/** Acknowledge a non-consumable purchase or subscription */
|
|
@@ -266,7 +266,7 @@ export interface ProductIOS extends ProductCommon {
|
|
|
266
266
|
typeIOS: ProductTypeIOS;
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
export type ProductQueryType = '
|
|
269
|
+
export type ProductQueryType = 'in-app' | 'subs' | 'all';
|
|
270
270
|
|
|
271
271
|
export interface ProductRequest {
|
|
272
272
|
skus: string[];
|
|
@@ -327,7 +327,7 @@ export interface ProductSubscriptionIOS extends ProductCommon {
|
|
|
327
327
|
|
|
328
328
|
export type ProductType = 'in-app' | 'subs';
|
|
329
329
|
|
|
330
|
-
export type ProductTypeIOS = '
|
|
330
|
+
export type ProductTypeIOS = 'consumable' | 'non-consumable' | 'auto-renewable-subscription' | 'non-renewing-subscription';
|
|
331
331
|
|
|
332
332
|
export type Purchase = PurchaseAndroid | PurchaseIOS;
|
|
333
333
|
|
|
@@ -349,6 +349,7 @@ export interface PurchaseAndroid extends PurchaseCommon {
|
|
|
349
349
|
quantity: number;
|
|
350
350
|
signatureAndroid?: (string | null);
|
|
351
351
|
transactionDate: number;
|
|
352
|
+
transactionId?: (string | null);
|
|
352
353
|
}
|
|
353
354
|
|
|
354
355
|
export interface PurchaseCommon {
|
|
@@ -399,6 +400,7 @@ export interface PurchaseIOS extends PurchaseCommon {
|
|
|
399
400
|
storefrontCountryCodeIOS?: (string | null);
|
|
400
401
|
subscriptionGroupIdIOS?: (string | null);
|
|
401
402
|
transactionDate: number;
|
|
403
|
+
transactionId: string;
|
|
402
404
|
transactionReasonIOS?: (string | null);
|
|
403
405
|
webOrderLineItemIdIOS?: (string | null);
|
|
404
406
|
}
|
|
@@ -428,7 +430,7 @@ export interface PurchaseOptions {
|
|
|
428
430
|
onlyIncludeActiveItemsIOS?: (boolean | null);
|
|
429
431
|
}
|
|
430
432
|
|
|
431
|
-
export type PurchaseState = '
|
|
433
|
+
export type PurchaseState = 'pending' | 'purchased' | 'failed' | 'restored' | 'deferred' | 'unknown';
|
|
432
434
|
|
|
433
435
|
export interface Query {
|
|
434
436
|
/** Get current StoreKit 2 entitlements (iOS 15+) */
|
|
@@ -654,7 +656,7 @@ export interface SubscriptionOfferIOS {
|
|
|
654
656
|
|
|
655
657
|
export type SubscriptionOfferTypeIOS = 'introductory' | 'promotional';
|
|
656
658
|
|
|
657
|
-
export type SubscriptionPeriodIOS = 'day' | '
|
|
659
|
+
export type SubscriptionPeriodIOS = 'day' | 'week' | 'month' | 'year' | 'empty';
|
|
658
660
|
|
|
659
661
|
export interface SubscriptionPeriodValueIOS {
|
|
660
662
|
unit: SubscriptionPeriodIOS;
|