react-native-iap 15.3.6 → 15.4.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/android/build.gradle +13 -5
- package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +16 -3
- package/ios/HybridRnIap.swift +12 -0
- package/lib/module/index.js +56 -16
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.kepler.js +170 -0
- package/lib/module/index.kepler.js.map +1 -0
- package/lib/module/types/amazon-devices-kepler/index.d.js +2 -0
- package/lib/module/types/amazon-devices-kepler/index.d.js.map +1 -0
- package/lib/module/types.js +5 -2
- package/lib/module/types.js.map +1 -1
- package/lib/module/utils/error.js +2 -2
- package/lib/module/utils/error.js.map +1 -1
- package/lib/module/utils/type-bridge.js +4 -1
- package/lib/module/utils/type-bridge.js.map +1 -1
- package/lib/module/vega-adapter.js +981 -0
- package/lib/module/vega-adapter.js.map +1 -0
- package/lib/module/vega.js +10 -0
- package/lib/module/vega.js.map +1 -0
- package/lib/module/vega.kepler.js +18 -0
- package/lib/module/vega.kepler.js.map +1 -0
- package/lib/typescript/plugin/src/withIAP.d.ts +33 -0
- package/lib/typescript/plugin/src/withIAP.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +9 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.kepler.d.ts +55 -0
- package/lib/typescript/src/index.kepler.d.ts.map +1 -0
- package/lib/typescript/src/specs/RnIap.nitro.d.ts +10 -1
- package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +16 -3
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/utils/type-bridge.d.ts.map +1 -1
- package/lib/typescript/src/vega-adapter.d.ts +76 -0
- package/lib/typescript/src/vega-adapter.d.ts.map +1 -0
- package/lib/typescript/src/vega.d.ts +4 -0
- package/lib/typescript/src/vega.d.ts.map +1 -0
- package/lib/typescript/src/vega.kepler.d.ts +4 -0
- package/lib/typescript/src/vega.kepler.d.ts.map +1 -0
- package/nitrogen/generated/android/NitroIap+autolinking.cmake +1 -0
- package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +5 -0
- package/nitrogen/generated/android/c++/JIapStore.hpp +3 -0
- package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithIapkitAmazonProps.hpp +71 -0
- package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithIapkitProps.hpp +9 -1
- package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithProviderProps.hpp +4 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_NitroVerifyPurchaseWithIapkitAmazonProps.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_NitroVerifyPurchaseWithIapkitAmazonProps.hpp +75 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_NitroVerifyPurchaseWithIapkitProps.hpp +4 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/IapStore.kt +2 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroVerifyPurchaseWithIapkitAmazonProps.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroVerifyPurchaseWithIapkitProps.kt +5 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_NullType_NitroVerifyPurchaseWithIapkitAmazonProps.kt +53 -0
- package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.hpp +47 -0
- package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +3 -0
- package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +3 -0
- package/nitrogen/generated/ios/swift/IapStore.swift +4 -0
- package/nitrogen/generated/ios/swift/NitroVerifyPurchaseWithIapkitAmazonProps.swift +103 -0
- package/nitrogen/generated/ios/swift/NitroVerifyPurchaseWithIapkitProps.swift +38 -1
- package/nitrogen/generated/ios/swift/Variant_NullType_NitroVerifyPurchaseWithIapkitAmazonProps.swift +18 -0
- package/nitrogen/generated/shared/c++/IapStore.hpp +4 -0
- package/nitrogen/generated/shared/c++/NitroVerifyPurchaseWithIapkitAmazonProps.hpp +94 -0
- package/nitrogen/generated/shared/c++/NitroVerifyPurchaseWithIapkitProps.hpp +8 -1
- package/openiap-versions.json +1 -1
- package/package.json +17 -4
- package/plugin/build/withIAP.d.ts +33 -0
- package/plugin/build/withIAP.js +109 -42
- package/plugin/src/withIAP.ts +185 -55
- package/src/index.kepler.ts +311 -0
- package/src/index.ts +65 -19
- package/src/specs/RnIap.nitro.ts +13 -2
- package/src/types/amazon-devices-kepler/index.d.ts +14 -0
- package/src/types.ts +17 -3
- package/src/utils/error.ts +2 -2
- package/src/utils/type-bridge.ts +4 -1
- package/src/vega-adapter.ts +1503 -0
- package/src/vega.kepler.ts +21 -0
- package/src/vega.ts +10 -0
- package/android/src/test/java/com/margelo/nitro/iap/ListenerThreadSafetyTest.kt +0 -154
- package/android/src/test/java/com/margelo/nitro/iap/OpenIapExceptionTest.kt +0 -93
- package/android/src/test/java/com/margelo/nitro/iap/ProductQueryHelpersTest.kt +0 -140
- package/plugin/tsconfig.tsbuildinfo +0 -1
package/README.md
CHANGED
|
@@ -105,7 +105,7 @@ Before installing React Native IAP, make sure you have:
|
|
|
105
105
|
|
|
106
106
|
#### Android Configuration
|
|
107
107
|
|
|
108
|
-
**Kotlin Version Requirement:** This library requires Kotlin 2.
|
|
108
|
+
**Kotlin Version Requirement:** This library requires Kotlin 2.2+. Configure your project's Kotlin version:
|
|
109
109
|
|
|
110
110
|
In your root `android/build.gradle`:
|
|
111
111
|
|
package/android/build.gradle
CHANGED
|
@@ -107,8 +107,13 @@ def getExtOrIntegerDefault(name) {
|
|
|
107
107
|
return getExtOrDefault(name).toString().toInteger()
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
// Read
|
|
110
|
+
// Read store flags from gradle.properties, default to play
|
|
111
111
|
def horizonEnabled = project.findProperty('horizonEnabled')?.toBoolean() ?: false
|
|
112
|
+
def fireOsEnabled = project.findProperty('fireOsEnabled')?.toBoolean() ?: false
|
|
113
|
+
if (horizonEnabled && fireOsEnabled) {
|
|
114
|
+
throw new GradleException("react-native-iap: horizonEnabled and fireOsEnabled cannot both be true")
|
|
115
|
+
}
|
|
116
|
+
def openiapFlavor = fireOsEnabled ? 'amazon' : (horizonEnabled ? 'horizon' : 'play')
|
|
112
117
|
|
|
113
118
|
def resolveOpenIapGoogleBuildFile() {
|
|
114
119
|
def candidates = [
|
|
@@ -155,9 +160,8 @@ android {
|
|
|
155
160
|
// Ship consumer keep rules so Nitro HybridObjects aren't stripped in app release builds
|
|
156
161
|
consumerProguardFiles 'consumer-rules.pro'
|
|
157
162
|
|
|
158
|
-
// Use
|
|
159
|
-
|
|
160
|
-
missingDimensionStrategy "platform", flavor
|
|
163
|
+
// Use explicit store flags to determine platform flavor
|
|
164
|
+
missingDimensionStrategy "platform", openiapFlavor
|
|
161
165
|
|
|
162
166
|
externalNativeBuild {
|
|
163
167
|
cmake {
|
|
@@ -251,7 +255,9 @@ dependencies {
|
|
|
251
255
|
}
|
|
252
256
|
|
|
253
257
|
// Google Play Services
|
|
254
|
-
|
|
258
|
+
if (!fireOsEnabled && !horizonEnabled) {
|
|
259
|
+
implementation "com.google.android.gms:play-services-base:$playServicesBaseVersion"
|
|
260
|
+
}
|
|
255
261
|
|
|
256
262
|
// Kotlin coroutines
|
|
257
263
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
|
|
@@ -261,6 +267,8 @@ dependencies {
|
|
|
261
267
|
def localGoogleProject = findProject(':openiap')
|
|
262
268
|
if (localGoogleProject != null) {
|
|
263
269
|
implementation project(':openiap')
|
|
270
|
+
} else if (fireOsEnabled) {
|
|
271
|
+
implementation "io.github.hyochan.openiap:openiap-google-amazon:${googleVersionString}"
|
|
264
272
|
} else if (horizonEnabled) {
|
|
265
273
|
implementation "io.github.hyochan.openiap:openiap-google-horizon:${googleVersionString}"
|
|
266
274
|
} else {
|
|
@@ -43,13 +43,13 @@ import dev.hyo.openiap.ExternalLinkLaunchModeAndroid as OpenIapExternalLinkLaunc
|
|
|
43
43
|
import dev.hyo.openiap.ExternalLinkTypeAndroid as OpenIapExternalLinkType
|
|
44
44
|
import dev.hyo.openiap.listener.OpenIapDeveloperProvidedBillingListener
|
|
45
45
|
import dev.hyo.openiap.store.OpenIapStore
|
|
46
|
+
import java.util.Locale
|
|
46
47
|
import kotlin.coroutines.cancellation.CancellationException
|
|
47
48
|
import kotlinx.coroutines.Dispatchers
|
|
48
49
|
import kotlinx.coroutines.withContext
|
|
49
50
|
import kotlinx.coroutines.CompletableDeferred
|
|
50
51
|
import org.json.JSONArray
|
|
51
52
|
import org.json.JSONObject
|
|
52
|
-
import java.util.Locale
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
55
|
* Custom exception for OpenIAP errors that only includes the error JSON without stack traces.
|
|
@@ -575,7 +575,7 @@ class HybridRnIap : HybridRnIapSpec() {
|
|
|
575
575
|
mapOf("type" to androidOptions?.type?.name, "includeSuspended" to includeSuspended)
|
|
576
576
|
)
|
|
577
577
|
|
|
578
|
-
val typeName = androidOptions?.type?.name?.lowercase()
|
|
578
|
+
val typeName = androidOptions?.type?.name?.lowercase(java.util.Locale.ROOT)
|
|
579
579
|
val normalizedType = when (typeName) {
|
|
580
580
|
"inapp" -> {
|
|
581
581
|
RnIapLog.warn("getAvailablePurchases received legacy type 'inapp'; forwarding as 'in-app'")
|
|
@@ -1279,6 +1279,7 @@ class HybridRnIap : HybridRnIapSpec() {
|
|
|
1279
1279
|
dev.hyo.openiap.IapStore.Apple -> IapStore.APPLE
|
|
1280
1280
|
dev.hyo.openiap.IapStore.Google -> IapStore.GOOGLE
|
|
1281
1281
|
dev.hyo.openiap.IapStore.Horizon -> IapStore.HORIZON
|
|
1282
|
+
dev.hyo.openiap.IapStore.Amazon -> IapStore.AMAZON
|
|
1282
1283
|
dev.hyo.openiap.IapStore.Unknown -> IapStore.UNKNOWN
|
|
1283
1284
|
}
|
|
1284
1285
|
}
|
|
@@ -1469,7 +1470,7 @@ class HybridRnIap : HybridRnIapSpec() {
|
|
|
1469
1470
|
return Promise.async {
|
|
1470
1471
|
try {
|
|
1471
1472
|
// Convert Nitro enum to string (e.g., IAPKIT -> "iapkit")
|
|
1472
|
-
val providerString = params.provider.name.lowercase()
|
|
1473
|
+
val providerString = params.provider.name.lowercase(java.util.Locale.ROOT)
|
|
1473
1474
|
RnIapLog.payload("verifyPurchaseWithProvider", mapOf("provider" to providerString))
|
|
1474
1475
|
|
|
1475
1476
|
// Build the props map for OpenIAP - use string value for provider
|
|
@@ -1482,6 +1483,14 @@ class HybridRnIap : HybridRnIapSpec() {
|
|
|
1482
1483
|
(iapkit.google as? Variant_NullType_NitroVerifyPurchaseWithIapkitGoogleProps.Second)?.value?.let { google ->
|
|
1483
1484
|
iapkitMap["google"] = mapOf("purchaseToken" to google.purchaseToken)
|
|
1484
1485
|
}
|
|
1486
|
+
(iapkit.amazon as? Variant_NullType_NitroVerifyPurchaseWithIapkitAmazonProps.Second)?.value?.let { amazon ->
|
|
1487
|
+
val amazonMap = mutableMapOf<String, Any?>(
|
|
1488
|
+
"receiptId" to amazon.receiptId
|
|
1489
|
+
)
|
|
1490
|
+
amazon.userId.unwrapString()?.let { amazonMap["userId"] = it }
|
|
1491
|
+
amazon.sandbox.unwrapBool()?.let { amazonMap["sandbox"] = it }
|
|
1492
|
+
iapkitMap["amazon"] = amazonMap
|
|
1493
|
+
}
|
|
1485
1494
|
(iapkit.apple as? Variant_NullType_NitroVerifyPurchaseWithIapkitAppleProps.Second)?.value?.let { apple ->
|
|
1486
1495
|
iapkitMap["apple"] = mapOf("jws" to apple.jws)
|
|
1487
1496
|
}
|
|
@@ -1609,6 +1618,7 @@ class HybridRnIap : HybridRnIapSpec() {
|
|
|
1609
1618
|
// Alternative Billing (Android)
|
|
1610
1619
|
// -------------------------------------------------------------------------
|
|
1611
1620
|
|
|
1621
|
+
@Suppress("DEPRECATION")
|
|
1612
1622
|
override fun checkAlternativeBillingAvailabilityAndroid(): Promise<Boolean> {
|
|
1613
1623
|
return Promise.async {
|
|
1614
1624
|
RnIapLog.payload("checkAlternativeBillingAvailabilityAndroid", null)
|
|
@@ -1626,6 +1636,7 @@ class HybridRnIap : HybridRnIapSpec() {
|
|
|
1626
1636
|
}
|
|
1627
1637
|
}
|
|
1628
1638
|
|
|
1639
|
+
@Suppress("DEPRECATION")
|
|
1629
1640
|
override fun showAlternativeBillingDialogAndroid(): Promise<Boolean> {
|
|
1630
1641
|
return Promise.async {
|
|
1631
1642
|
RnIapLog.payload("showAlternativeBillingDialogAndroid", null)
|
|
@@ -1647,6 +1658,7 @@ class HybridRnIap : HybridRnIapSpec() {
|
|
|
1647
1658
|
}
|
|
1648
1659
|
}
|
|
1649
1660
|
|
|
1661
|
+
@Suppress("DEPRECATION")
|
|
1650
1662
|
override fun createAlternativeBillingTokenAndroid(sku: Variant_NullType_String?): Promise<Variant_NullType_String> {
|
|
1651
1663
|
return Promise.async {
|
|
1652
1664
|
val skuValue = sku.unwrapString()
|
|
@@ -2000,6 +2012,7 @@ class HybridRnIap : HybridRnIapSpec() {
|
|
|
2000
2012
|
"APPLE" -> IapStore.APPLE
|
|
2001
2013
|
"GOOGLE" -> IapStore.GOOGLE
|
|
2002
2014
|
"HORIZON" -> IapStore.HORIZON
|
|
2015
|
+
"AMAZON" -> IapStore.AMAZON
|
|
2003
2016
|
else -> IapStore.UNKNOWN
|
|
2004
2017
|
}
|
|
2005
2018
|
}
|
package/ios/HybridRnIap.swift
CHANGED
|
@@ -446,6 +446,18 @@ class HybridRnIap: HybridRnIapSpec {
|
|
|
446
446
|
if case .second(let google) = iapkit.google {
|
|
447
447
|
iapkitDict["google"] = ["purchaseToken": google.purchaseToken]
|
|
448
448
|
}
|
|
449
|
+
if case .second(let amazon) = iapkit.amazon {
|
|
450
|
+
var amazonDict: [String: Any] = [
|
|
451
|
+
"receiptId": amazon.receiptId
|
|
452
|
+
]
|
|
453
|
+
if case .second(let sandbox) = amazon.sandbox {
|
|
454
|
+
amazonDict["sandbox"] = sandbox
|
|
455
|
+
}
|
|
456
|
+
if case .second(let userId) = amazon.userId {
|
|
457
|
+
amazonDict["userId"] = userId
|
|
458
|
+
}
|
|
459
|
+
iapkitDict["amazon"] = amazonDict
|
|
460
|
+
}
|
|
449
461
|
propsDict["iapkit"] = iapkitDict
|
|
450
462
|
}
|
|
451
463
|
// Use JSONSerialization + JSONDecoder like expo-iap does
|
package/lib/module/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import { normalizeErrorCodeFromNative, createPurchaseError, DUPLICATE_PURCHASE_C
|
|
|
15
15
|
import { RnIapConsole } from "./utils/debug.js";
|
|
16
16
|
import { getSuccessFromPurchaseVariant } from "./utils/purchase.js";
|
|
17
17
|
import { parseAppTransactionPayload } from "./utils.js";
|
|
18
|
+
import { getVegaIapModule, isVegaOS } from "./vega.js";
|
|
18
19
|
|
|
19
20
|
// ------------------------------
|
|
20
21
|
// Billing Programs API (Android 8.2.0+)
|
|
@@ -28,6 +29,7 @@ import { parseAppTransactionPayload } from "./utils.js";
|
|
|
28
29
|
|
|
29
30
|
export * from "./types.js";
|
|
30
31
|
export * from "./utils/error.js";
|
|
32
|
+
export * from "./vega.js";
|
|
31
33
|
const LEGACY_INAPP_WARNING = "[react-native-iap] `type: 'inapp'` is deprecated and will be removed in a future major version. Use 'in-app' instead.";
|
|
32
34
|
const toErrorMessage = error => {
|
|
33
35
|
if (typeof error === 'object' && error !== null && 'message' in error && error.message != null) {
|
|
@@ -63,6 +65,10 @@ let iapRef = null;
|
|
|
63
65
|
*/
|
|
64
66
|
export const isNitroReady = () => {
|
|
65
67
|
if (iapRef) return true;
|
|
68
|
+
if (isVegaOS()) {
|
|
69
|
+
iapRef = getVegaIapModule();
|
|
70
|
+
return Boolean(iapRef);
|
|
71
|
+
}
|
|
66
72
|
try {
|
|
67
73
|
iapRef = NitroModules.createHybridObject('RnIap');
|
|
68
74
|
return true;
|
|
@@ -93,9 +99,20 @@ export const isMacOS = () => {
|
|
|
93
99
|
export const isStandardIOS = () => {
|
|
94
100
|
return Platform.OS === 'ios' && !isTVOS() && !isMacOS();
|
|
95
101
|
};
|
|
102
|
+
const isAndroidStoreRuntime = () => {
|
|
103
|
+
return Platform.OS === 'android' || isVegaOS();
|
|
104
|
+
};
|
|
96
105
|
const IAP = {
|
|
97
106
|
get instance() {
|
|
98
107
|
if (iapRef) return iapRef;
|
|
108
|
+
if (isVegaOS()) {
|
|
109
|
+
const vegaModule = getVegaIapModule();
|
|
110
|
+
if (!vegaModule) {
|
|
111
|
+
throw new Error('Amazon Vega IAP module is unavailable. Install @amazon-devices/keplerscript-appstore-iap-lib in the Vega app target and build with the React Native for Vega kepler platform.');
|
|
112
|
+
}
|
|
113
|
+
iapRef = vegaModule;
|
|
114
|
+
return iapRef;
|
|
115
|
+
}
|
|
99
116
|
|
|
100
117
|
// Attempt to create the HybridObject and map common Nitro/JSI readiness errors
|
|
101
118
|
try {
|
|
@@ -507,7 +524,7 @@ function tryAttachSubscriptionBillingIssueNative() {
|
|
|
507
524
|
} catch (e) {
|
|
508
525
|
const msg = toErrorMessage(e);
|
|
509
526
|
if (msg.includes('Nitro runtime not installed')) {
|
|
510
|
-
RnIapConsole.warn('[subscriptionBillingIssueListener] Nitro not ready yet; will retry
|
|
527
|
+
RnIapConsole.warn('[subscriptionBillingIssueListener] Nitro not ready yet; will retry after initConnection()');
|
|
511
528
|
} else {
|
|
512
529
|
throw e;
|
|
513
530
|
}
|
|
@@ -597,7 +614,7 @@ export const fetchProducts = async request => {
|
|
|
597
614
|
|
|
598
615
|
// item.type === 'subs' case
|
|
599
616
|
// For Android, check if subscription items have actual offers
|
|
600
|
-
if (
|
|
617
|
+
if (isAndroidStoreRuntime() && item.platform === 'android' && item.type === 'subs') {
|
|
601
618
|
// TypeScript now knows this is ProductSubscriptionAndroid
|
|
602
619
|
const hasSubscriptionOffers = item.subscriptionOfferDetailsAndroid && Array.isArray(item.subscriptionOfferDetailsAndroid) && item.subscriptionOfferDetailsAndroid.length > 0;
|
|
603
620
|
RnIapConsole.debug(`[fetchProducts] ${item.id}: type=${item.type}, hasOffers=${hasSubscriptionOffers}`);
|
|
@@ -683,9 +700,22 @@ export const getAvailablePurchases = async options => {
|
|
|
683
700
|
RnIapConsole.warn(`[getAvailablePurchases] Some purchases failed validation: ${nitroPurchases.length - validPurchases.length} invalid`);
|
|
684
701
|
}
|
|
685
702
|
return validPurchases.map(convertNitroPurchaseToPurchase);
|
|
686
|
-
} else if (
|
|
687
|
-
// For Android, we need to call twice for inapp and subs
|
|
703
|
+
} else if (isAndroidStoreRuntime()) {
|
|
688
704
|
const includeSuspended = Boolean(options?.includeSuspendedAndroid ?? false);
|
|
705
|
+
if (isVegaOS()) {
|
|
706
|
+
const nitroPurchases = await IAP.instance.getAvailablePurchases({
|
|
707
|
+
android: {
|
|
708
|
+
includeSuspended
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
const validPurchases = nitroPurchases.filter(validateNitroPurchase);
|
|
712
|
+
if (validPurchases.length !== nitroPurchases.length) {
|
|
713
|
+
RnIapConsole.warn(`[getAvailablePurchases] Some Vega purchases failed validation: ${nitroPurchases.length - validPurchases.length} invalid`);
|
|
714
|
+
}
|
|
715
|
+
return validPurchases.map(convertNitroPurchaseToPurchase);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// For Android Play/Horizon/Fire OS, query in-app items and subscriptions separately.
|
|
689
719
|
const inappNitroPurchases = await IAP.instance.getAvailablePurchases({
|
|
690
720
|
android: {
|
|
691
721
|
type: 'inapp',
|
|
@@ -777,8 +807,8 @@ export const getStorefrontIOS = async () => {
|
|
|
777
807
|
* @see {@link https://openiap.dev/docs/apis/get-storefront}
|
|
778
808
|
*/
|
|
779
809
|
export const getStorefront = async () => {
|
|
780
|
-
if (Platform.OS !== 'ios' &&
|
|
781
|
-
RnIapConsole.warn('[getStorefront] Storefront lookup is only supported on iOS and
|
|
810
|
+
if (Platform.OS !== 'ios' && !isAndroidStoreRuntime()) {
|
|
811
|
+
RnIapConsole.warn('[getStorefront] Storefront lookup is only supported on iOS, Android, and Vega OS.');
|
|
782
812
|
return '';
|
|
783
813
|
}
|
|
784
814
|
const hasUnifiedMethod = typeof IAP.instance.getStorefront === 'function';
|
|
@@ -1171,7 +1201,11 @@ export const getTransactionJwsIOS = async sku => {
|
|
|
1171
1201
|
*/
|
|
1172
1202
|
export const initConnection = async config => {
|
|
1173
1203
|
try {
|
|
1174
|
-
|
|
1204
|
+
const result = await IAP.instance.initConnection(config);
|
|
1205
|
+
if (subscriptionBillingIssueJsListeners.size > 0) {
|
|
1206
|
+
tryAttachSubscriptionBillingIssueNative();
|
|
1207
|
+
}
|
|
1208
|
+
return result;
|
|
1175
1209
|
} catch (error) {
|
|
1176
1210
|
const parsedError = parseErrorAndLogIfNeeded('Failed to initialize IAP connection:', error);
|
|
1177
1211
|
throw createPurchaseError({
|
|
@@ -1274,7 +1308,7 @@ export const requestPurchase = async request => {
|
|
|
1274
1308
|
if (!iosRequest?.sku) {
|
|
1275
1309
|
throw new Error('Invalid request for iOS. The `sku` property is required.');
|
|
1276
1310
|
}
|
|
1277
|
-
} else if (
|
|
1311
|
+
} else if (isAndroidStoreRuntime()) {
|
|
1278
1312
|
// Support both 'google' (recommended) and 'android' (deprecated) fields
|
|
1279
1313
|
const androidRequest = perPlatformRequest.google ?? perPlatformRequest.android;
|
|
1280
1314
|
if (!androidRequest?.skus?.length) {
|
|
@@ -1328,7 +1362,7 @@ export const requestPurchase = async request => {
|
|
|
1328
1362
|
|
|
1329
1363
|
// Support both 'google' (recommended) and 'android' (deprecated) fields
|
|
1330
1364
|
const androidRequestSource = perPlatformRequest.google ?? perPlatformRequest.android;
|
|
1331
|
-
if (
|
|
1365
|
+
if (isAndroidStoreRuntime() && androidRequestSource) {
|
|
1332
1366
|
const androidRequest = isSubs ? androidRequestSource : androidRequestSource;
|
|
1333
1367
|
const androidPayload = {
|
|
1334
1368
|
skus: androidRequest.skus
|
|
@@ -1421,7 +1455,7 @@ export const finishTransaction = async args => {
|
|
|
1421
1455
|
transactionId: purchase.id
|
|
1422
1456
|
}
|
|
1423
1457
|
};
|
|
1424
|
-
} else if (
|
|
1458
|
+
} else if (isAndroidStoreRuntime()) {
|
|
1425
1459
|
const token = purchase.purchaseToken ?? undefined;
|
|
1426
1460
|
if (!token) {
|
|
1427
1461
|
throw new Error('purchaseToken required to finish Android transaction');
|
|
@@ -1471,8 +1505,8 @@ export const finishTransaction = async args => {
|
|
|
1471
1505
|
*/
|
|
1472
1506
|
export const acknowledgePurchaseAndroid = async purchaseToken => {
|
|
1473
1507
|
try {
|
|
1474
|
-
if (
|
|
1475
|
-
throw new Error('acknowledgePurchaseAndroid is only available on Android');
|
|
1508
|
+
if (!isAndroidStoreRuntime()) {
|
|
1509
|
+
throw new Error('acknowledgePurchaseAndroid is only available on Android and Vega OS');
|
|
1476
1510
|
}
|
|
1477
1511
|
const result = await IAP.instance.finishTransaction({
|
|
1478
1512
|
android: {
|
|
@@ -1506,8 +1540,8 @@ export const acknowledgePurchaseAndroid = async purchaseToken => {
|
|
|
1506
1540
|
*/
|
|
1507
1541
|
export const consumePurchaseAndroid = async purchaseToken => {
|
|
1508
1542
|
try {
|
|
1509
|
-
if (
|
|
1510
|
-
throw new Error('consumePurchaseAndroid is only available on Android');
|
|
1543
|
+
if (!isAndroidStoreRuntime()) {
|
|
1544
|
+
throw new Error('consumePurchaseAndroid is only available on Android and Vega OS');
|
|
1511
1545
|
}
|
|
1512
1546
|
const result = await IAP.instance.finishTransaction({
|
|
1513
1547
|
android: {
|
|
@@ -1699,8 +1733,14 @@ export const validateReceiptIOS = async options => {
|
|
|
1699
1733
|
* provider: 'iapkit',
|
|
1700
1734
|
* iapkit: {
|
|
1701
1735
|
* apiKey: 'your-api-key',
|
|
1702
|
-
*
|
|
1703
|
-
*
|
|
1736
|
+
* // Choose exactly one store payload.
|
|
1737
|
+
* // apple: { jws: purchase.purchaseToken },
|
|
1738
|
+
* // google: { purchaseToken: purchase.purchaseToken },
|
|
1739
|
+
* amazon: {
|
|
1740
|
+
* userId: amazonUserId,
|
|
1741
|
+
* receiptId: purchase.purchaseToken,
|
|
1742
|
+
* sandbox: __DEV__,
|
|
1743
|
+
* },
|
|
1704
1744
|
* },
|
|
1705
1745
|
* });
|
|
1706
1746
|
* ```
|