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
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import OpenIAP
|
|
3
|
+
|
|
4
|
+
@available(iOS 15.0, *)
|
|
5
|
+
enum RnIapHelper {
|
|
6
|
+
// MARK: - Sanitizers
|
|
7
|
+
|
|
8
|
+
static func sanitizeDictionary(_ dictionary: [String: Any?]) -> [String: Any] {
|
|
9
|
+
var sanitized: [String: Any] = [:]
|
|
10
|
+
for (key, value) in dictionary {
|
|
11
|
+
if let value {
|
|
12
|
+
sanitized[key] = value
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return sanitized
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static func sanitizeArray(_ array: [[String: Any?]]) -> [[String: Any]] {
|
|
19
|
+
array.map { sanitizeDictionary($0) }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// MARK: - Parsing helpers
|
|
23
|
+
|
|
24
|
+
static func parseProductQueryType(_ rawValue: String?) -> ProductQueryType {
|
|
25
|
+
guard let raw = rawValue?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else {
|
|
26
|
+
return .inApp
|
|
27
|
+
}
|
|
28
|
+
let normalized = raw
|
|
29
|
+
.lowercased()
|
|
30
|
+
.replacingOccurrences(of: "_", with: "")
|
|
31
|
+
.replacingOccurrences(of: "-", with: "")
|
|
32
|
+
switch normalized {
|
|
33
|
+
case "subs", "subscription", "subscriptions":
|
|
34
|
+
return .subs
|
|
35
|
+
case "all":
|
|
36
|
+
return .all
|
|
37
|
+
case "inapp":
|
|
38
|
+
return .inApp
|
|
39
|
+
default:
|
|
40
|
+
return .inApp
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// MARK: - Conversion helpers
|
|
45
|
+
|
|
46
|
+
static func convertProductDictionary(_ dictionary: [String: Any]) -> NitroProduct {
|
|
47
|
+
var product = NitroProduct()
|
|
48
|
+
|
|
49
|
+
if let id = dictionary["id"] as? String { product.id = id }
|
|
50
|
+
if let title = dictionary["title"] as? String { product.title = title }
|
|
51
|
+
if let description = dictionary["description"] as? String { product.description = description }
|
|
52
|
+
if let type = dictionary["type"] as? String { product.type = type }
|
|
53
|
+
if let displayName = dictionary["displayName"] as? String { product.displayName = displayName }
|
|
54
|
+
if let displayPrice = dictionary["displayPrice"] as? String { product.displayPrice = displayPrice }
|
|
55
|
+
if let currency = dictionary["currency"] as? String { product.currency = currency }
|
|
56
|
+
if let price = doubleValue(dictionary["price"]) { product.price = price }
|
|
57
|
+
|
|
58
|
+
if let platformString = dictionary["platform"] as? String,
|
|
59
|
+
let platform = IapPlatform(fromString: platformString) {
|
|
60
|
+
product.platform = platform
|
|
61
|
+
} else {
|
|
62
|
+
product.platform = .ios
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if let typeIOS = dictionary["typeIOS"] as? String { product.typeIOS = typeIOS }
|
|
66
|
+
if let familyShareable = boolValue(dictionary["isFamilyShareableIOS"]) { product.isFamilyShareableIOS = familyShareable }
|
|
67
|
+
if let jsonRepresentation = dictionary["jsonRepresentationIOS"] as? String { product.jsonRepresentationIOS = jsonRepresentation }
|
|
68
|
+
if let subscriptionUnit = dictionary["subscriptionPeriodUnitIOS"] as? String { product.subscriptionPeriodUnitIOS = subscriptionUnit }
|
|
69
|
+
if let subscriptionNumber = doubleValue(dictionary["subscriptionPeriodNumberIOS"]) { product.subscriptionPeriodNumberIOS = subscriptionNumber }
|
|
70
|
+
if let introductoryPrice = dictionary["introductoryPriceIOS"] as? String { product.introductoryPriceIOS = introductoryPrice }
|
|
71
|
+
if let introductoryAmount = doubleValue(dictionary["introductoryPriceAsAmountIOS"]) { product.introductoryPriceAsAmountIOS = introductoryAmount }
|
|
72
|
+
if let introductoryPeriods = doubleValue(dictionary["introductoryPriceNumberOfPeriodsIOS"]) { product.introductoryPriceNumberOfPeriodsIOS = introductoryPeriods }
|
|
73
|
+
if let introductoryPaymentMode = dictionary["introductoryPricePaymentModeIOS"] as? String { product.introductoryPricePaymentModeIOS = introductoryPaymentMode }
|
|
74
|
+
if let introductoryPeriod = dictionary["introductoryPriceSubscriptionPeriodIOS"] as? String { product.introductoryPriceSubscriptionPeriodIOS = introductoryPeriod }
|
|
75
|
+
if let displayNameIOS = dictionary["displayNameIOS"] as? String { product.displayName = displayNameIOS }
|
|
76
|
+
|
|
77
|
+
return product
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static func convertPurchaseDictionary(_ dictionary: [String: Any]) -> NitroPurchase {
|
|
81
|
+
var purchase = NitroPurchase()
|
|
82
|
+
|
|
83
|
+
if let id = dictionary["id"] as? String { purchase.id = id }
|
|
84
|
+
if let productId = dictionary["productId"] as? String { purchase.productId = productId }
|
|
85
|
+
if let transactionDate = doubleValue(dictionary["transactionDate"]) { purchase.transactionDate = transactionDate }
|
|
86
|
+
if let purchaseToken = dictionary["purchaseToken"] as? String { purchase.purchaseToken = purchaseToken }
|
|
87
|
+
|
|
88
|
+
if let platformString = dictionary["platform"] as? String,
|
|
89
|
+
let platform = IapPlatform(fromString: platformString) {
|
|
90
|
+
purchase.platform = platform
|
|
91
|
+
} else {
|
|
92
|
+
purchase.platform = .ios
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if let quantity = doubleValue(dictionary["quantity"]) { purchase.quantity = quantity }
|
|
96
|
+
if let purchaseStateString = dictionary["purchaseState"] as? String,
|
|
97
|
+
let state = PurchaseState(fromString: purchaseStateString) {
|
|
98
|
+
purchase.purchaseState = state
|
|
99
|
+
}
|
|
100
|
+
if let isAutoRenewing = boolValue(dictionary["isAutoRenewing"]) { purchase.isAutoRenewing = isAutoRenewing }
|
|
101
|
+
if let quantityIOS = doubleValue(dictionary["quantityIOS"]) { purchase.quantityIOS = quantityIOS }
|
|
102
|
+
if let originalDate = doubleValue(dictionary["originalTransactionDateIOS"]) { purchase.originalTransactionDateIOS = originalDate }
|
|
103
|
+
if let originalIdentifier = dictionary["originalTransactionIdentifierIOS"] as? String { purchase.originalTransactionIdentifierIOS = originalIdentifier }
|
|
104
|
+
if let appAccountToken = dictionary["appAccountToken"] as? String { purchase.appAccountToken = appAccountToken }
|
|
105
|
+
|
|
106
|
+
if let purchaseTokenAndroid = dictionary["purchaseTokenAndroid"] as? String { purchase.purchaseTokenAndroid = purchaseTokenAndroid }
|
|
107
|
+
if let dataAndroid = dictionary["dataAndroid"] as? String { purchase.dataAndroid = dataAndroid }
|
|
108
|
+
if let signatureAndroid = dictionary["signatureAndroid"] as? String { purchase.signatureAndroid = signatureAndroid }
|
|
109
|
+
if let autoRenewingAndroid = boolValue(dictionary["autoRenewingAndroid"]) { purchase.autoRenewingAndroid = autoRenewingAndroid }
|
|
110
|
+
if let purchaseStateAndroid = doubleValue(dictionary["purchaseStateAndroid"]) { purchase.purchaseStateAndroid = purchaseStateAndroid }
|
|
111
|
+
if let isAcknowledgedAndroid = boolValue(dictionary["isAcknowledgedAndroid"]) { purchase.isAcknowledgedAndroid = isAcknowledgedAndroid }
|
|
112
|
+
if let packageNameAndroid = dictionary["packageNameAndroid"] as? String { purchase.packageNameAndroid = packageNameAndroid }
|
|
113
|
+
if let obfuscatedAccountId = dictionary["obfuscatedAccountIdAndroid"] as? String { purchase.obfuscatedAccountIdAndroid = obfuscatedAccountId }
|
|
114
|
+
if let obfuscatedProfileId = dictionary["obfuscatedProfileIdAndroid"] as? String { purchase.obfuscatedProfileIdAndroid = obfuscatedProfileId }
|
|
115
|
+
|
|
116
|
+
return purchase
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static func convertRenewalInfo(_ dictionary: [String: Any]) -> NitroSubscriptionRenewalInfo? {
|
|
120
|
+
guard let autoRenewStatus = boolValue(dictionary["autoRenewStatus"]) else {
|
|
121
|
+
return nil
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let autoRenewPreference = dictionary["autoRenewPreference"] as? String
|
|
125
|
+
let expirationReason = doubleValue(dictionary["expirationReason"])
|
|
126
|
+
let gracePeriod = doubleValue(dictionary["gracePeriodExpirationDate"])
|
|
127
|
+
let currentProductID = dictionary["currentProductID"] as? String
|
|
128
|
+
let platform = dictionary["platform"] as? String ?? "ios"
|
|
129
|
+
|
|
130
|
+
return NitroSubscriptionRenewalInfo(
|
|
131
|
+
autoRenewStatus: autoRenewStatus,
|
|
132
|
+
autoRenewPreference: autoRenewPreference,
|
|
133
|
+
expirationReason: expirationReason,
|
|
134
|
+
gracePeriodExpirationDate: gracePeriod,
|
|
135
|
+
currentProductID: currentProductID,
|
|
136
|
+
platform: platform
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// MARK: - Request helpers
|
|
141
|
+
|
|
142
|
+
static func decodeRequestPurchaseProps(
|
|
143
|
+
iosPayload: [String: Any],
|
|
144
|
+
type: ProductQueryType
|
|
145
|
+
) throws -> RequestPurchaseProps {
|
|
146
|
+
let normalizedType: ProductQueryType = type == .all ? .inApp : type
|
|
147
|
+
var normalized: [String: Any] = ["type": normalizedType.rawValue]
|
|
148
|
+
|
|
149
|
+
switch normalizedType {
|
|
150
|
+
case .subs:
|
|
151
|
+
normalized["requestSubscription"] = ["ios": iosPayload]
|
|
152
|
+
case .inApp, .all:
|
|
153
|
+
normalized["requestPurchase"] = ["ios": iosPayload]
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return try OpenIapSerialization.decode(object: normalized, as: RequestPurchaseProps.self)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// MARK: - Shared helpers
|
|
160
|
+
|
|
161
|
+
static func makeErrorDedupKey(code: String, productId: String?) -> String {
|
|
162
|
+
"\(code)#\(productId ?? "-")"
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static func loadReceiptData(refresh: Bool) async throws -> String {
|
|
166
|
+
if refresh {
|
|
167
|
+
_ = try await OpenIapModule.shared.syncIOS()
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
do {
|
|
171
|
+
guard let receipt = try await OpenIapModule.shared.getReceiptDataIOS(), !receipt.isEmpty else {
|
|
172
|
+
throw PurchaseError.make(code: .receiptFailed)
|
|
173
|
+
}
|
|
174
|
+
return receipt
|
|
175
|
+
} catch let error as PurchaseError {
|
|
176
|
+
throw error
|
|
177
|
+
} catch {
|
|
178
|
+
throw PurchaseError.make(code: .receiptFailed, message: error.localizedDescription)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// MARK: - Error helpers
|
|
183
|
+
|
|
184
|
+
static func makePurchaseErrorResult(
|
|
185
|
+
code: ErrorCode,
|
|
186
|
+
message: String,
|
|
187
|
+
_ productId: String? = nil
|
|
188
|
+
) -> NitroPurchaseResult {
|
|
189
|
+
var result = NitroPurchaseResult()
|
|
190
|
+
result.responseCode = -1
|
|
191
|
+
result.code = code.rawValue
|
|
192
|
+
result.message = message
|
|
193
|
+
result.purchaseToken = nil
|
|
194
|
+
return result
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// MARK: - Primitive extractors
|
|
198
|
+
|
|
199
|
+
static func doubleValue(_ value: Any?) -> Double? {
|
|
200
|
+
switch value {
|
|
201
|
+
case let double as Double:
|
|
202
|
+
return double
|
|
203
|
+
case let number as NSNumber:
|
|
204
|
+
return number.doubleValue
|
|
205
|
+
case let string as String:
|
|
206
|
+
return Double(string)
|
|
207
|
+
default:
|
|
208
|
+
return nil
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
static func boolValue(_ value: Any?) -> Bool? {
|
|
213
|
+
switch value {
|
|
214
|
+
case let bool as Bool:
|
|
215
|
+
return bool
|
|
216
|
+
case let number as NSNumber:
|
|
217
|
+
return number.boolValue
|
|
218
|
+
case let string as String:
|
|
219
|
+
return (string as NSString).boolValue
|
|
220
|
+
default:
|
|
221
|
+
return nil
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
#if canImport(os)
|
|
3
|
+
import os
|
|
4
|
+
#endif
|
|
5
|
+
|
|
6
|
+
enum RnIapLog {
|
|
7
|
+
enum Level: String {
|
|
8
|
+
case debug
|
|
9
|
+
case info
|
|
10
|
+
case warn
|
|
11
|
+
case error
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private static var isEnabled: Bool = {
|
|
15
|
+
#if DEBUG
|
|
16
|
+
true
|
|
17
|
+
#else
|
|
18
|
+
false
|
|
19
|
+
#endif
|
|
20
|
+
}()
|
|
21
|
+
|
|
22
|
+
private static var customHandler: ((Level, String) -> Void)?
|
|
23
|
+
|
|
24
|
+
static func setEnabled(_ enabled: Bool) {
|
|
25
|
+
isEnabled = enabled
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static func setHandler(_ handler: ((Level, String) -> Void)?) {
|
|
29
|
+
customHandler = handler
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static func debug(_ message: String) { log(.debug, message) }
|
|
33
|
+
static func info(_ message: String) { log(.info, message) }
|
|
34
|
+
static func warn(_ message: String) { log(.warn, message) }
|
|
35
|
+
static func error(_ message: String) { log(.error, message) }
|
|
36
|
+
|
|
37
|
+
static func payload(_ name: String, _ payload: Any?) {
|
|
38
|
+
debug("\(name) payload: \(stringify(payload))")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static func result(_ name: String, _ value: Any?) {
|
|
42
|
+
debug("\(name) result: \(stringify(value))")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static func failure(_ name: String, error err: Error) {
|
|
46
|
+
Self.error("\(name) failed: \(err.localizedDescription)")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private static func log(_ level: Level, _ message: String) {
|
|
50
|
+
guard isEnabled else { return }
|
|
51
|
+
|
|
52
|
+
if let handler = customHandler {
|
|
53
|
+
handler(level, message)
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
#if canImport(os)
|
|
58
|
+
let logger = Logger(subsystem: "dev.hyo.react-native-iap", category: "RnIap")
|
|
59
|
+
let formatted = "[RnIap] \(message)"
|
|
60
|
+
switch level {
|
|
61
|
+
case .debug:
|
|
62
|
+
logger.debug("\(formatted, privacy: .public)")
|
|
63
|
+
case .info:
|
|
64
|
+
logger.info("\(formatted, privacy: .public)")
|
|
65
|
+
case .warn:
|
|
66
|
+
logger.warning("\(formatted, privacy: .public)")
|
|
67
|
+
case .error:
|
|
68
|
+
logger.error("\(formatted, privacy: .public)")
|
|
69
|
+
}
|
|
70
|
+
#else
|
|
71
|
+
NSLog("[RnIap][%@] %@", level.rawValue.uppercased(), message)
|
|
72
|
+
#endif
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private static func stringify(_ value: Any?) -> String {
|
|
76
|
+
guard let sanitized = sanitize(value) else {
|
|
77
|
+
return "null"
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if JSONSerialization.isValidJSONObject(sanitized),
|
|
81
|
+
let data = try? JSONSerialization.data(withJSONObject: sanitized, options: []) {
|
|
82
|
+
return String(data: data, encoding: .utf8) ?? String(describing: sanitized)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return String(describing: sanitized)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private static func sanitize(_ value: Any?) -> Any? {
|
|
89
|
+
guard let value else { return nil }
|
|
90
|
+
|
|
91
|
+
if let dictionary = value as? [String: Any] {
|
|
92
|
+
return sanitizeDictionary(dictionary)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if let optionalDictionary = value as? [String: Any?] {
|
|
96
|
+
var compact: [String: Any] = [:]
|
|
97
|
+
for (key, optionalValue) in optionalDictionary {
|
|
98
|
+
if let optionalValue {
|
|
99
|
+
compact[key] = optionalValue
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return sanitizeDictionary(compact)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if let array = value as? [Any] {
|
|
106
|
+
return array.compactMap { sanitize($0) }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if let optionalArray = value as? [Any?] {
|
|
110
|
+
return optionalArray.compactMap { sanitize($0) }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return value
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private static func sanitizeDictionary(_ dictionary: [String: Any]) -> [String: Any] {
|
|
117
|
+
var sanitized: [String: Any] = [:]
|
|
118
|
+
for (key, value) in dictionary {
|
|
119
|
+
if key.lowercased().contains("token") {
|
|
120
|
+
sanitized[key] = "hidden"
|
|
121
|
+
} else if let sanitizedValue = sanitize(value) {
|
|
122
|
+
sanitized[key] = sanitizedValue
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return sanitized
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -20,11 +20,9 @@ import { normalizeErrorCodeFromNative } from "../utils/errorMapping.js";
|
|
|
20
20
|
export function useIAP(options) {
|
|
21
21
|
const [connected, setConnected] = useState(false);
|
|
22
22
|
const [products, setProducts] = useState([]);
|
|
23
|
-
const [promotedProductsIOS] = useState([]);
|
|
24
23
|
const [subscriptions, setSubscriptions] = useState([]);
|
|
25
24
|
const [availablePurchases, setAvailablePurchases] = useState([]);
|
|
26
25
|
const [promotedProductIOS, setPromotedProductIOS] = useState();
|
|
27
|
-
const [promotedProductIdIOS] = useState();
|
|
28
26
|
const [activeSubscriptions, setActiveSubscriptions] = useState([]);
|
|
29
27
|
const optionsRef = useRef(options);
|
|
30
28
|
const connectedRef = useRef(false);
|
|
@@ -51,30 +49,6 @@ export function useIAP(options) {
|
|
|
51
49
|
useEffect(() => {
|
|
52
50
|
subscriptionsRefState.current = subscriptions;
|
|
53
51
|
}, [subscriptions]);
|
|
54
|
-
const getProductsInternal = useCallback(async skus => {
|
|
55
|
-
try {
|
|
56
|
-
const result = await fetchProducts({
|
|
57
|
-
skus,
|
|
58
|
-
type: 'in-app'
|
|
59
|
-
});
|
|
60
|
-
const newProducts = (result ?? []).filter(item => item.type === 'in-app');
|
|
61
|
-
setProducts(prevProducts => mergeWithDuplicateCheck(prevProducts, newProducts, product => product.id));
|
|
62
|
-
} catch (error) {
|
|
63
|
-
console.error('Error fetching products:', error);
|
|
64
|
-
}
|
|
65
|
-
}, [mergeWithDuplicateCheck]);
|
|
66
|
-
const getSubscriptionsInternal = useCallback(async skus => {
|
|
67
|
-
try {
|
|
68
|
-
const result = await fetchProducts({
|
|
69
|
-
skus,
|
|
70
|
-
type: 'subs'
|
|
71
|
-
});
|
|
72
|
-
const newSubscriptions = (result ?? []).filter(item => item.type === 'subs');
|
|
73
|
-
setSubscriptions(prevSubscriptions => mergeWithDuplicateCheck(prevSubscriptions, newSubscriptions, subscription => subscription.id));
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.error('Error fetching subscriptions:', error);
|
|
76
|
-
}
|
|
77
|
-
}, [mergeWithDuplicateCheck]);
|
|
78
52
|
const fetchProductsInternal = useCallback(async params => {
|
|
79
53
|
if (!connectedRef.current) {
|
|
80
54
|
console.warn('[useIAP] fetchProducts called before connection; skipping');
|
|
@@ -182,7 +156,8 @@ export function useIAP(options) {
|
|
|
182
156
|
}
|
|
183
157
|
});
|
|
184
158
|
if (Platform.OS === 'ios') {
|
|
185
|
-
|
|
159
|
+
// iOS promoted products listener
|
|
160
|
+
subscriptionsRef.current.promotedProductIOS = promotedProductListenerIOS(product => {
|
|
186
161
|
setPromotedProductIOS(product);
|
|
187
162
|
if (optionsRef.current?.onPromotedProductIOS) {
|
|
188
163
|
optionsRef.current.onPromotedProductIOS(product);
|
|
@@ -194,9 +169,7 @@ export function useIAP(options) {
|
|
|
194
169
|
if (!result) {
|
|
195
170
|
// Clean up some listeners but leave purchaseError for potential retries
|
|
196
171
|
subscriptionsRef.current.purchaseUpdate?.remove();
|
|
197
|
-
subscriptionsRef.current.promotedProductsIOS?.remove();
|
|
198
172
|
subscriptionsRef.current.purchaseUpdate = undefined;
|
|
199
|
-
subscriptionsRef.current.promotedProductsIOS = undefined;
|
|
200
173
|
return;
|
|
201
174
|
}
|
|
202
175
|
}, [getActiveSubscriptionsInternal, getAvailablePurchasesInternal]);
|
|
@@ -206,7 +179,6 @@ export function useIAP(options) {
|
|
|
206
179
|
return () => {
|
|
207
180
|
currentSubscriptions.purchaseUpdate?.remove();
|
|
208
181
|
currentSubscriptions.purchaseError?.remove();
|
|
209
|
-
currentSubscriptions.promotedProductsIOS?.remove();
|
|
210
182
|
currentSubscriptions.promotedProductIOS?.remove();
|
|
211
183
|
// Keep connection alive across screens to avoid race conditions
|
|
212
184
|
setConnected(false);
|
|
@@ -215,8 +187,6 @@ export function useIAP(options) {
|
|
|
215
187
|
return {
|
|
216
188
|
connected,
|
|
217
189
|
products,
|
|
218
|
-
promotedProductsIOS,
|
|
219
|
-
promotedProductIdIOS,
|
|
220
190
|
subscriptions,
|
|
221
191
|
finishTransaction,
|
|
222
192
|
availablePurchases,
|
|
@@ -234,8 +204,6 @@ export function useIAP(options) {
|
|
|
234
204
|
console.warn('Failed to restore purchases:', e);
|
|
235
205
|
}
|
|
236
206
|
},
|
|
237
|
-
getProducts: getProductsInternal,
|
|
238
|
-
getSubscriptions: getSubscriptionsInternal,
|
|
239
207
|
getPromotedProductIOS,
|
|
240
208
|
requestPurchaseOnPromotedProductIOS,
|
|
241
209
|
getActiveSubscriptions: getActiveSubscriptionsInternal,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useCallback","useEffect","useState","useRef","Platform","initConnection","purchaseErrorListener","purchaseUpdatedListener","promotedProductListenerIOS","getAvailablePurchases","finishTransaction","finishTransactionInternal","requestPurchase","requestPurchaseInternal","fetchProducts","validateReceipt","validateReceiptInternal","getActiveSubscriptions","hasActiveSubscriptions","restorePurchases","restorePurchasesTopLevel","getPromotedProductIOS","requestPurchaseOnPromotedProductIOS","ErrorCode","normalizeErrorCodeFromNative","useIAP","options","connected","setConnected","products","setProducts","
|
|
1
|
+
{"version":3,"names":["useCallback","useEffect","useState","useRef","Platform","initConnection","purchaseErrorListener","purchaseUpdatedListener","promotedProductListenerIOS","getAvailablePurchases","finishTransaction","finishTransactionInternal","requestPurchase","requestPurchaseInternal","fetchProducts","validateReceipt","validateReceiptInternal","getActiveSubscriptions","hasActiveSubscriptions","restorePurchases","restorePurchasesTopLevel","getPromotedProductIOS","requestPurchaseOnPromotedProductIOS","ErrorCode","normalizeErrorCodeFromNative","useIAP","options","connected","setConnected","products","setProducts","subscriptions","setSubscriptions","availablePurchases","setAvailablePurchases","promotedProductIOS","setPromotedProductIOS","activeSubscriptions","setActiveSubscriptions","optionsRef","connectedRef","mergeWithDuplicateCheck","existingItems","newItems","getKey","merged","forEach","newItem","isDuplicate","some","existingItem","push","current","subscriptionsRef","subscriptionsRefState","fetchProductsInternal","params","console","warn","requestType","type","result","skus","items","newSubscriptions","filter","item","prevSubscriptions","subscription","id","newProducts","prevProducts","product","error","getAvailablePurchasesInternal","_skus","alsoPublishToEventListenerIOS","onlyIncludeActiveItemsIOS","getActiveSubscriptionsInternal","subscriptionIds","hasActiveSubscriptionsInternal","args","err","requestObj","sku","androidOptions","initIapWithSubscriptions","purchaseUpdate","purchase","e","onPurchaseSuccess","purchaseError","mappedError","code","message","productId","undefined","InitConnection","onPurchaseError","OS","onPromotedProductIOS","remove","currentSubscriptions"],"sourceRoot":"../../../src","sources":["hooks/useIAP.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -300,7 +300,7 @@ export const getPromotedProductIOS = async () => {
|
|
|
300
300
|
return null;
|
|
301
301
|
}
|
|
302
302
|
try {
|
|
303
|
-
const nitroProduct = await IAP.instance.requestPromotedProductIOS();
|
|
303
|
+
const nitroProduct = typeof IAP.instance.getPromotedProductIOS === 'function' ? await IAP.instance.getPromotedProductIOS() : await IAP.instance.requestPromotedProductIOS();
|
|
304
304
|
if (!nitroProduct) {
|
|
305
305
|
return null;
|
|
306
306
|
}
|
|
@@ -448,6 +448,36 @@ export const getReceiptDataIOS = async () => {
|
|
|
448
448
|
throw new Error(errorJson.message);
|
|
449
449
|
}
|
|
450
450
|
};
|
|
451
|
+
export const getReceiptIOS = async () => {
|
|
452
|
+
if (Platform.OS !== 'ios') {
|
|
453
|
+
throw new Error('getReceiptIOS is only available on iOS');
|
|
454
|
+
}
|
|
455
|
+
try {
|
|
456
|
+
if (typeof IAP.instance.getReceiptIOS === 'function') {
|
|
457
|
+
return await IAP.instance.getReceiptIOS();
|
|
458
|
+
}
|
|
459
|
+
return await IAP.instance.getReceiptDataIOS();
|
|
460
|
+
} catch (error) {
|
|
461
|
+
console.error('[getReceiptIOS] Failed:', error);
|
|
462
|
+
const errorJson = parseErrorStringToJsonObj(error);
|
|
463
|
+
throw new Error(errorJson.message);
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
export const requestReceiptRefreshIOS = async () => {
|
|
467
|
+
if (Platform.OS !== 'ios') {
|
|
468
|
+
throw new Error('requestReceiptRefreshIOS is only available on iOS');
|
|
469
|
+
}
|
|
470
|
+
try {
|
|
471
|
+
if (typeof IAP.instance.requestReceiptRefreshIOS === 'function') {
|
|
472
|
+
return await IAP.instance.requestReceiptRefreshIOS();
|
|
473
|
+
}
|
|
474
|
+
return await IAP.instance.getReceiptDataIOS();
|
|
475
|
+
} catch (error) {
|
|
476
|
+
console.error('[requestReceiptRefreshIOS] Failed:', error);
|
|
477
|
+
const errorJson = parseErrorStringToJsonObj(error);
|
|
478
|
+
throw new Error(errorJson.message);
|
|
479
|
+
}
|
|
480
|
+
};
|
|
451
481
|
export const isTransactionVerifiedIOS = async sku => {
|
|
452
482
|
if (Platform.OS !== 'ios') {
|
|
453
483
|
return false;
|
|
@@ -978,12 +1008,32 @@ export const deepLinkToSubscriptions = async options => {
|
|
|
978
1008
|
}
|
|
979
1009
|
if (Platform.OS === 'ios') {
|
|
980
1010
|
try {
|
|
981
|
-
|
|
1011
|
+
if (typeof IAP.instance.deepLinkToSubscriptionsIOS === 'function') {
|
|
1012
|
+
await IAP.instance.deepLinkToSubscriptionsIOS();
|
|
1013
|
+
} else {
|
|
1014
|
+
await IAP.instance.showManageSubscriptionsIOS();
|
|
1015
|
+
}
|
|
982
1016
|
} catch (error) {
|
|
983
1017
|
console.warn('[deepLinkToSubscriptions] Failed on iOS:', error);
|
|
984
1018
|
}
|
|
985
1019
|
}
|
|
986
1020
|
};
|
|
1021
|
+
export const deepLinkToSubscriptionsIOS = async () => {
|
|
1022
|
+
if (Platform.OS !== 'ios') {
|
|
1023
|
+
throw new Error('deepLinkToSubscriptionsIOS is only available on iOS');
|
|
1024
|
+
}
|
|
1025
|
+
try {
|
|
1026
|
+
if (typeof IAP.instance.deepLinkToSubscriptionsIOS === 'function') {
|
|
1027
|
+
return await IAP.instance.deepLinkToSubscriptionsIOS();
|
|
1028
|
+
}
|
|
1029
|
+
await IAP.instance.showManageSubscriptionsIOS();
|
|
1030
|
+
return true;
|
|
1031
|
+
} catch (error) {
|
|
1032
|
+
console.error('[deepLinkToSubscriptionsIOS] Failed:', error);
|
|
1033
|
+
const errorJson = parseErrorStringToJsonObj(error);
|
|
1034
|
+
throw new Error(errorJson.message);
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
987
1037
|
|
|
988
1038
|
/**
|
|
989
1039
|
* iOS only - Gets the original app transaction ID if the app was purchased from the App Store
|