expo-iap 5.8.3 → 6.0.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/build.gradle +8 -13
- package/android/openiap-store.gradle +84 -8
- package/android/src/main/java/expo/modules/iap/ExpoIapHelper.kt +4 -3
- package/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +82 -38
- package/build/ExpoIapModule.d.ts +3 -1
- package/build/ExpoIapModule.d.ts.map +1 -1
- package/build/ExpoIapModule.js +19 -0
- package/build/ExpoIapModule.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +18 -19
- package/build/index.js.map +1 -1
- package/build/index.kepler.d.ts +0 -9
- package/build/index.kepler.d.ts.map +1 -1
- package/build/index.kepler.js +0 -9
- package/build/index.kepler.js.map +1 -1
- package/build/modules/android.d.ts +0 -14
- package/build/modules/android.d.ts.map +1 -1
- package/build/modules/android.js +0 -20
- package/build/modules/android.js.map +1 -1
- package/build/modules/ios.d.ts +0 -17
- package/build/modules/ios.d.ts.map +1 -1
- package/build/modules/ios.js +3 -21
- package/build/modules/ios.js.map +1 -1
- package/build/types.d.ts +38 -48
- package/build/types.d.ts.map +1 -1
- package/build/types.js +15 -0
- package/build/types.js.map +1 -1
- package/build/useIAP.d.ts +0 -5
- package/build/useIAP.d.ts.map +1 -1
- package/build/useIAP.js +4 -15
- package/build/useIAP.js.map +1 -1
- package/build/utils/availablePurchases.d.ts +1 -1
- package/build/utils/availablePurchases.d.ts.map +1 -1
- package/build/utils/availablePurchases.js +20 -6
- package/build/utils/availablePurchases.js.map +1 -1
- package/build/utils/restorePurchases.d.ts +2 -8
- package/build/utils/restorePurchases.d.ts.map +1 -1
- package/build/utils/restorePurchases.js +14 -15
- package/build/utils/restorePurchases.js.map +1 -1
- package/build/vega-adapter.d.ts.map +1 -1
- package/build/vega-adapter.js +3 -0
- package/build/vega-adapter.js.map +1 -1
- package/bun.lock +3 -2
- package/ios/ExpoIapModule.swift +22 -8
- package/ios/onside/OnsideIapModule.swift +1 -0
- package/openiap-versions.json +3 -3
- package/package.json +3 -2
- package/plugin/build/withIAP.d.ts +7 -2
- package/plugin/build/withIAP.js +66 -5
- package/plugin/build/withLocalOpenIAP.js +20 -9
- package/plugin/src/expoConfig.augmentation.d.ts +5 -2
- package/plugin/src/withIAP.ts +104 -10
- package/plugin/src/withLocalOpenIAP.ts +28 -9
- package/src/ExpoIapModule.ts +22 -2
- package/src/index.kepler.ts +0 -13
- package/src/index.ts +27 -31
- package/src/modules/android.ts +0 -23
- package/src/modules/ios.ts +7 -30
- package/src/types.ts +49 -48
- package/src/useIAP.ts +5 -22
- package/src/utils/availablePurchases.ts +28 -6
- package/src/utils/restorePurchases.ts +13 -15
- package/src/vega-adapter.ts +3 -0
package/android/build.gradle
CHANGED
|
@@ -55,7 +55,8 @@ apply from: project.file('openiap-android-sdk.gradle')
|
|
|
55
55
|
|
|
56
56
|
// Store selection: explicit property > task flavor > connected debug device > play.
|
|
57
57
|
apply from: project.file('openiap-store.gradle')
|
|
58
|
-
def
|
|
58
|
+
def openiapSelection = openIapResolveStore('expo-iap')
|
|
59
|
+
def openiapFlavor = openiapSelection.store
|
|
59
60
|
|
|
60
61
|
// If you want to use the managed Android SDK versions from expo-modules-core, set this to true.
|
|
61
62
|
// The Android SDK versions will be bumped from time to time in SDK releases and may introduce breaking changes in your module code.
|
|
@@ -86,7 +87,10 @@ android {
|
|
|
86
87
|
versionCode = 1
|
|
87
88
|
versionName = expoIapPackageVersion
|
|
88
89
|
// When using local openiap-google with flavors, select the appropriate flavor
|
|
89
|
-
missingDimensionStrategy "platform",
|
|
90
|
+
missingDimensionStrategy "platform", openiapSelection.platform
|
|
91
|
+
}
|
|
92
|
+
testOptions {
|
|
93
|
+
unitTests.includeAndroidResources = true
|
|
90
94
|
}
|
|
91
95
|
lint {
|
|
92
96
|
abortOnError = false
|
|
@@ -106,17 +110,8 @@ kotlin {
|
|
|
106
110
|
|
|
107
111
|
dependencies {
|
|
108
112
|
testImplementation "junit:junit:4.13.2"
|
|
113
|
+
testImplementation "org.robolectric:robolectric:4.16.1"
|
|
109
114
|
testImplementation "org.json:json:20260719"
|
|
110
115
|
|
|
111
|
-
|
|
112
|
-
if (findProject(":openiap-google") != null) {
|
|
113
|
-
api project(":openiap-google")
|
|
114
|
-
} else if (openiapFlavor == 'amazon') {
|
|
115
|
-
api "io.github.hyochan.openiap:openiap-google-amazon:${googleVersionString}"
|
|
116
|
-
} else if (openiapFlavor == 'horizon') {
|
|
117
|
-
api "io.github.hyochan.openiap:openiap-google-horizon:${googleVersionString}"
|
|
118
|
-
} else {
|
|
119
|
-
// Fallback to published artifact when local project isn't linked
|
|
120
|
-
api "io.github.hyochan.openiap:openiap-google:${googleVersionString}"
|
|
121
|
-
}
|
|
116
|
+
openIapAddStoreDependencies('api', googleVersionString, ':openiap-google')
|
|
122
117
|
}
|
|
@@ -16,10 +16,21 @@
|
|
|
16
16
|
// builds another store (an abbreviation such as aHR) fails once the graph is ready.
|
|
17
17
|
|
|
18
18
|
ext.openIapStoreAliases = [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
'play': 'play',
|
|
20
|
+
'google': 'play',
|
|
21
|
+
'gplay': 'play',
|
|
22
|
+
'googleplay': 'play',
|
|
23
|
+
'google-play': 'play',
|
|
24
|
+
'gms': 'play',
|
|
25
|
+
'horizon': 'horizon',
|
|
26
|
+
'meta': 'horizon',
|
|
27
|
+
'quest': 'horizon',
|
|
28
|
+
'amazon': 'amazon',
|
|
29
|
+
'fire': 'amazon',
|
|
30
|
+
'fireos': 'amazon',
|
|
31
|
+
'fire-os': 'amazon',
|
|
32
|
+
'auto': 'auto',
|
|
33
|
+
'none': 'none',
|
|
23
34
|
]
|
|
24
35
|
|
|
25
36
|
ext.openIapNormalizeStore = { Object value, String label ->
|
|
@@ -28,10 +39,9 @@ ext.openIapNormalizeStore = { Object value, String label ->
|
|
|
28
39
|
return null
|
|
29
40
|
}
|
|
30
41
|
def store = openIapStoreAliases[key]
|
|
31
|
-
if (store
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
return store
|
|
42
|
+
if (store != null) return store
|
|
43
|
+
if (key ==~ /[a-z][a-z0-9_]*/ && !(key in ['apple', 'unknown']) && project.findProperty('openiapProvider')) return key
|
|
44
|
+
throw new GradleException("${label}: unknown openiapStore '${value}'; use play, horizon, amazon, auto, or none where the library allows it, or supply openiapProvider for a lowercase community store id")
|
|
35
45
|
}
|
|
36
46
|
|
|
37
47
|
// assembleHorizonRelease -> [assemble, horizon, release]
|
|
@@ -327,6 +337,53 @@ ext.openIapDeviceStore = {
|
|
|
327
337
|
return [store: store, reason: "device ${serial}, manufacturer ${manufacturer ?: 'unknown'}"]
|
|
328
338
|
}
|
|
329
339
|
|
|
340
|
+
// Validates openiapProvider against the explicit store, for the plain path
|
|
341
|
+
// and the provider platform flavor alike. Returns the coordinates, or null
|
|
342
|
+
// when no provider is involved.
|
|
343
|
+
ext.openIapCheckProvider = { String label, String store, String explicit ->
|
|
344
|
+
def provider = project.findProperty('openiapProvider')?.toString()?.trim()
|
|
345
|
+
def official = store in ['play', 'horizon', 'amazon']
|
|
346
|
+
if (provider) {
|
|
347
|
+
if (official || store == 'none' || explicit == null) {
|
|
348
|
+
throw new GradleException("${label}: openiapProvider requires an explicit community openiapStore id")
|
|
349
|
+
}
|
|
350
|
+
if (!(provider ==~ /[A-Za-z0-9_.-]+:[A-Za-z0-9_.-]+:[0-9][A-Za-z0-9_.-]*/)) {
|
|
351
|
+
throw new GradleException("${label}: openiapProvider must be group:artifact:version with a fixed version")
|
|
352
|
+
}
|
|
353
|
+
// A snapshot in any letter case is a moving target, not a fixed version.
|
|
354
|
+
def providerVersion = provider.split(':')[2]
|
|
355
|
+
if (providerVersion.toLowerCase(Locale.ROOT).contains('snapshot')) {
|
|
356
|
+
throw new GradleException("${label}: openiapProvider must be group:artifact:version with a fixed version")
|
|
357
|
+
}
|
|
358
|
+
def module = provider.split(':').take(2).join(':')
|
|
359
|
+
if (module.startsWith('io.github.hyochan.openiap:openiap-')) {
|
|
360
|
+
throw new GradleException("${label}: openiapProvider must name a community provider, not an OpenIAP core or official artifact")
|
|
361
|
+
}
|
|
362
|
+
return provider
|
|
363
|
+
}
|
|
364
|
+
if (!official && store != 'none') {
|
|
365
|
+
throw new GradleException("${label}: openiapStore=${store} requires openiapProvider=group:artifact:version")
|
|
366
|
+
}
|
|
367
|
+
return null
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// The provider platform flavor's coordinates. The pin selects that flavor
|
|
371
|
+
// only, so the task-flavor rule does not apply: each official flavor of the
|
|
372
|
+
// same app still links its own store.
|
|
373
|
+
ext.openIapResolveFlavorProvider = { String label ->
|
|
374
|
+
if (rootProject.ext.has('openIapProviderResolution')) {
|
|
375
|
+
return rootProject.ext.openIapProviderResolution
|
|
376
|
+
}
|
|
377
|
+
def explicit = openIapExplicitStore(label, false)
|
|
378
|
+
def provider = openIapCheckProvider(label, explicit ?: 'play', explicit)
|
|
379
|
+
def resolution = [store: explicit, provider: provider]
|
|
380
|
+
rootProject.ext.openIapProviderResolution = resolution
|
|
381
|
+
if (provider) {
|
|
382
|
+
logger.quiet("${label}: provider=${provider} for the provider platform flavor")
|
|
383
|
+
}
|
|
384
|
+
return resolution
|
|
385
|
+
}
|
|
386
|
+
|
|
330
387
|
ext.openIapResolveStore = { String label, Map options = [:] ->
|
|
331
388
|
def allowNone = options.allowNone == true
|
|
332
389
|
if (rootProject.ext.has('openIapStoreResolution')) {
|
|
@@ -361,8 +418,27 @@ ext.openIapResolveStore = { String label, Map options = [:] ->
|
|
|
361
418
|
if (resolution == null) {
|
|
362
419
|
resolution = [store: 'play', source: 'default', reason: 'no store signal']
|
|
363
420
|
}
|
|
421
|
+
resolution.official = resolution.store in ['play', 'horizon', 'amazon']
|
|
422
|
+
resolution.platform = resolution.official ? resolution.store : 'provider'
|
|
423
|
+
def provider = openIapCheckProvider(label, resolution.store, explicit)
|
|
424
|
+
if (provider) resolution.provider = provider
|
|
364
425
|
rootProject.ext.openIapStoreResolution = resolution
|
|
365
426
|
logger.quiet("openiap: store=${resolution.store} (source=${resolution.source}; ${resolution.reason})")
|
|
366
427
|
openIapVerifyTaskGraph(label, resolution)
|
|
367
428
|
return resolution
|
|
368
429
|
}
|
|
430
|
+
|
|
431
|
+
// All framework wrappers use this dependency path, including embedded local builds.
|
|
432
|
+
ext.openIapAddStoreDependencies = { String configuration, String version, String localProject = ':openiap' ->
|
|
433
|
+
def resolution = openIapResolveStore('openiap', [allowNone: true])
|
|
434
|
+
if (resolution.store == 'none') return
|
|
435
|
+
if (resolution.provider) {
|
|
436
|
+
def core = findProject(':openiap-core')
|
|
437
|
+
dependencies.add(configuration, core != null ? core : "io.github.hyochan.openiap:openiap-core:${version}")
|
|
438
|
+
dependencies.add(configuration, resolution.provider)
|
|
439
|
+
} else {
|
|
440
|
+
def local = findProject(localProject)
|
|
441
|
+
def artifact = resolution.store == 'play' ? 'openiap-google' : "openiap-google-${resolution.store}"
|
|
442
|
+
dependencies.add(configuration, local != null ? local : "io.github.hyochan.openiap:${artifact}:${version}")
|
|
443
|
+
}
|
|
444
|
+
}
|
|
@@ -3,7 +3,8 @@ package expo.modules.iap
|
|
|
3
3
|
import dev.hyo.openiap.AndroidSubscriptionOfferInput
|
|
4
4
|
import dev.hyo.openiap.DeveloperBillingOptionParamsAndroid
|
|
5
5
|
import dev.hyo.openiap.OpenIapError
|
|
6
|
-
import dev.hyo.openiap.
|
|
6
|
+
import dev.hyo.openiap.OpenIapProvider
|
|
7
|
+
import dev.hyo.openiap.OpenIapProtocol
|
|
7
8
|
import dev.hyo.openiap.ProductQueryType
|
|
8
9
|
import dev.hyo.openiap.SubscriptionProductReplacementParamsAndroid
|
|
9
10
|
import dev.hyo.openiap.SubscriptionReplacementModeAndroid
|
|
@@ -301,7 +302,7 @@ object ExpoIapHelper {
|
|
|
301
302
|
}
|
|
302
303
|
|
|
303
304
|
fun setupListeners(
|
|
304
|
-
openIap:
|
|
305
|
+
openIap: OpenIapProtocol,
|
|
305
306
|
module: Module,
|
|
306
307
|
scope: CoroutineScope,
|
|
307
308
|
connectionReady: java.util.concurrent.atomic.AtomicBoolean,
|
|
@@ -458,7 +459,7 @@ object ExpoIapHelper {
|
|
|
458
459
|
}
|
|
459
460
|
|
|
460
461
|
fun cleanupListeners(
|
|
461
|
-
openIap:
|
|
462
|
+
openIap: OpenIapProtocol,
|
|
462
463
|
handles: ListenerHandles?,
|
|
463
464
|
) {
|
|
464
465
|
if (handles == null) return
|
|
@@ -7,7 +7,8 @@ import dev.hyo.openiap.FetchProductsResultProducts
|
|
|
7
7
|
import dev.hyo.openiap.FetchProductsResultSubscriptions
|
|
8
8
|
import dev.hyo.openiap.InitConnectionConfig
|
|
9
9
|
import dev.hyo.openiap.OpenIapError
|
|
10
|
-
import dev.hyo.openiap.
|
|
10
|
+
import dev.hyo.openiap.OpenIapProvider
|
|
11
|
+
import dev.hyo.openiap.OpenIapProtocol
|
|
11
12
|
import dev.hyo.openiap.ProductQueryType
|
|
12
13
|
import dev.hyo.openiap.ProductRequest
|
|
13
14
|
import dev.hyo.openiap.Purchase
|
|
@@ -48,6 +49,7 @@ import dev.hyo.openiap.GetBillingChoiceInfoParamsAndroid as OpenIapGetBillingCho
|
|
|
48
49
|
import dev.hyo.openiap.InAppMessageCategoryAndroid as OpenIapInAppMessageCategory
|
|
49
50
|
import dev.hyo.openiap.InAppMessageParamsAndroid as OpenIapInAppMessageParams
|
|
50
51
|
import dev.hyo.openiap.LaunchExternalLinkParamsAndroid as OpenIapLaunchExternalLinkParams
|
|
52
|
+
import dev.hyo.openiap.utils.redeemOfferCode
|
|
51
53
|
|
|
52
54
|
internal suspend fun endExpoConnectionWithCleanup(
|
|
53
55
|
endConnection: suspend () -> Boolean,
|
|
@@ -58,6 +60,18 @@ internal suspend fun endExpoConnectionWithCleanup(
|
|
|
58
60
|
cleanup()
|
|
59
61
|
}
|
|
60
62
|
|
|
63
|
+
internal suspend fun endExpoConnectionOrReset(
|
|
64
|
+
provider: Lazy<*>,
|
|
65
|
+
endConnection: suspend () -> Boolean,
|
|
66
|
+
cleanup: () -> Unit,
|
|
67
|
+
): Boolean {
|
|
68
|
+
if (!provider.isInitialized()) {
|
|
69
|
+
cleanup()
|
|
70
|
+
return true
|
|
71
|
+
}
|
|
72
|
+
return endExpoConnectionWithCleanup(endConnection, cleanup)
|
|
73
|
+
}
|
|
74
|
+
|
|
61
75
|
internal fun endConnectionErrorCode(error: Exception): String =
|
|
62
76
|
(error as? OpenIapError)?.code ?: OpenIapError.ServiceDisconnected.CODE
|
|
63
77
|
|
|
@@ -118,9 +132,10 @@ class ExpoIapModule : Module() {
|
|
|
118
132
|
private val currentActivity
|
|
119
133
|
get() = appContext.activityProvider?.currentActivity ?: throw Exceptions.MissingActivity()
|
|
120
134
|
|
|
121
|
-
private val
|
|
135
|
+
private val openIapLazy: Lazy<OpenIapProtocol> = lazy { OpenIapProvider.create(context) }
|
|
136
|
+
private val openIap: OpenIapProtocol get() = openIapLazy.value
|
|
122
137
|
|
|
123
|
-
//
|
|
138
|
+
// The bridge and store share one provider instance.
|
|
124
139
|
private val openIapStore: OpenIapStore by lazy { OpenIapStore(openIap) }
|
|
125
140
|
private var listenerHandles: ExpoIapHelper.ListenerHandles? = null
|
|
126
141
|
private val pendingEvents = ConcurrentLinkedQueue<Pair<String, Map<String, Any?>>>()
|
|
@@ -185,9 +200,10 @@ class ExpoIapModule : Module() {
|
|
|
185
200
|
// Clear any buffered events from a failed init
|
|
186
201
|
pendingEvents.clear()
|
|
187
202
|
ExpoIapLog.failure("initConnection", IllegalStateException("Failed to initialize connection"))
|
|
203
|
+
val error = OpenIapError.InitConnection.forProvider(context)
|
|
188
204
|
promise.reject(
|
|
189
|
-
|
|
190
|
-
|
|
205
|
+
error.code,
|
|
206
|
+
error.message,
|
|
191
207
|
null,
|
|
192
208
|
)
|
|
193
209
|
return@withLock
|
|
@@ -206,7 +222,7 @@ class ExpoIapModule : Module() {
|
|
|
206
222
|
promise.resolve(true)
|
|
207
223
|
} catch (e: Exception) {
|
|
208
224
|
ExpoIapLog.failure("initConnection", e)
|
|
209
|
-
promise.reject(OpenIapError.InitConnection.CODE, e.message, e)
|
|
225
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.InitConnection.CODE, e.message, e)
|
|
210
226
|
}
|
|
211
227
|
}
|
|
212
228
|
}
|
|
@@ -217,10 +233,11 @@ class ExpoIapModule : Module() {
|
|
|
217
233
|
scope.launch {
|
|
218
234
|
connectionMutex.withLock {
|
|
219
235
|
try {
|
|
220
|
-
val result =
|
|
236
|
+
val result = endExpoConnectionOrReset(
|
|
237
|
+
provider = openIapLazy,
|
|
221
238
|
endConnection = { openIap.endConnection() },
|
|
222
239
|
cleanup = {
|
|
223
|
-
ExpoIapHelper.cleanupListeners(openIap,
|
|
240
|
+
listenerHandles?.let { ExpoIapHelper.cleanupListeners(openIap, it) }
|
|
224
241
|
listenerHandles = null
|
|
225
242
|
PromiseUtils.rejectAllPendingPromises()
|
|
226
243
|
connectionReady.set(false)
|
|
@@ -296,7 +313,7 @@ class ExpoIapModule : Module() {
|
|
|
296
313
|
promise.resolve(payload)
|
|
297
314
|
} catch (e: Exception) {
|
|
298
315
|
ExpoIapLog.failure("getAvailableItems", e)
|
|
299
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, null)
|
|
316
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, null)
|
|
300
317
|
}
|
|
301
318
|
}
|
|
302
319
|
}
|
|
@@ -314,23 +331,20 @@ class ExpoIapModule : Module() {
|
|
|
314
331
|
promise.resolve(null)
|
|
315
332
|
} catch (e: Exception) {
|
|
316
333
|
ExpoIapLog.failure("deepLinkToSubscriptionsAndroid", e)
|
|
317
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, null)
|
|
334
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, null)
|
|
318
335
|
}
|
|
319
336
|
}
|
|
320
337
|
}
|
|
321
338
|
|
|
322
|
-
AsyncFunction("
|
|
323
|
-
ExpoIapLog.payload("
|
|
339
|
+
AsyncFunction("openRedeemOfferCode") { promise: Promise ->
|
|
340
|
+
ExpoIapLog.payload("openRedeemOfferCode", null)
|
|
324
341
|
scope.launch {
|
|
325
342
|
try {
|
|
326
|
-
runCatching { currentActivity }.getOrNull()
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
val launched = handler()
|
|
330
|
-
ExpoIapLog.result("openRedeemOfferCodeAndroid", launched)
|
|
331
|
-
promise.resolve(launched)
|
|
343
|
+
val purchase = redeemOfferCode(openIap, runCatching { currentActivity }.getOrNull())
|
|
344
|
+
ExpoIapLog.result("openRedeemOfferCode", purchase != null)
|
|
345
|
+
promise.resolve(purchase?.toJson())
|
|
332
346
|
} catch (e: Exception) {
|
|
333
|
-
ExpoIapLog.failure("
|
|
347
|
+
ExpoIapLog.failure("openRedeemOfferCode", e)
|
|
334
348
|
val errorMap =
|
|
335
349
|
if (e is OpenIapError) {
|
|
336
350
|
ExpoIapHelper.serializeOpenIapError(e)
|
|
@@ -362,7 +376,7 @@ class ExpoIapModule : Module() {
|
|
|
362
376
|
promise.resolve(code)
|
|
363
377
|
} catch (e: Exception) {
|
|
364
378
|
ExpoIapLog.failure("getStorefront", e)
|
|
365
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
379
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
366
380
|
}
|
|
367
381
|
}
|
|
368
382
|
}
|
|
@@ -487,6 +501,30 @@ class ExpoIapModule : Module() {
|
|
|
487
501
|
}
|
|
488
502
|
}
|
|
489
503
|
|
|
504
|
+
AsyncFunction("restorePurchases") { promise: Promise ->
|
|
505
|
+
scope.launch {
|
|
506
|
+
try {
|
|
507
|
+
openIap.restorePurchases()
|
|
508
|
+
promise.resolve(true)
|
|
509
|
+
} catch (e: Exception) {
|
|
510
|
+
ExpoIapLog.failure("restorePurchases", e)
|
|
511
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, null)
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
AsyncFunction("finishTransaction") { purchase: Map<String, Any?>, isConsumable: Boolean, promise: Promise ->
|
|
517
|
+
scope.launch {
|
|
518
|
+
try {
|
|
519
|
+
openIap.finishTransaction(dev.hyo.openiap.PurchaseAndroid.fromJson(purchase), isConsumable)
|
|
520
|
+
promise.resolve(null)
|
|
521
|
+
} catch (e: Exception) {
|
|
522
|
+
ExpoIapLog.failure("finishTransaction", e)
|
|
523
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.DeveloperError.CODE, e.message, null)
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
490
528
|
AsyncFunction("acknowledgePurchaseAndroid") { token: String, promise: Promise ->
|
|
491
529
|
ExpoIapLog.payload("acknowledgePurchaseAndroid", mapOf("token" to token))
|
|
492
530
|
scope.launch {
|
|
@@ -497,7 +535,7 @@ class ExpoIapModule : Module() {
|
|
|
497
535
|
promise.resolve(response)
|
|
498
536
|
} catch (e: Exception) {
|
|
499
537
|
ExpoIapLog.failure("acknowledgePurchaseAndroid", e)
|
|
500
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, null)
|
|
538
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, null)
|
|
501
539
|
}
|
|
502
540
|
}
|
|
503
541
|
}
|
|
@@ -515,7 +553,7 @@ class ExpoIapModule : Module() {
|
|
|
515
553
|
promise.resolve(response)
|
|
516
554
|
} catch (e: Exception) {
|
|
517
555
|
ExpoIapLog.failure("consumePurchaseAndroid", e)
|
|
518
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, null)
|
|
556
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, null)
|
|
519
557
|
}
|
|
520
558
|
}
|
|
521
559
|
}
|
|
@@ -542,7 +580,7 @@ class ExpoIapModule : Module() {
|
|
|
542
580
|
promise.resolve(resultMap)
|
|
543
581
|
} catch (e: Exception) {
|
|
544
582
|
ExpoIapLog.failure("verifyPurchase", e)
|
|
545
|
-
promise.reject(OpenIapError.VerificationFailed.CODE, e.message, e)
|
|
583
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.VerificationFailed.CODE, e.message, e)
|
|
546
584
|
}
|
|
547
585
|
}
|
|
548
586
|
}
|
|
@@ -566,7 +604,7 @@ class ExpoIapModule : Module() {
|
|
|
566
604
|
promise.resolve(resultMap)
|
|
567
605
|
} catch (e: Exception) {
|
|
568
606
|
ExpoIapLog.failure("verifyPurchaseWithProvider", e)
|
|
569
|
-
promise.reject(OpenIapError.VerificationFailed.CODE, e.message, e)
|
|
607
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.VerificationFailed.CODE, e.message, e)
|
|
570
608
|
}
|
|
571
609
|
}
|
|
572
610
|
}
|
|
@@ -584,7 +622,7 @@ class ExpoIapModule : Module() {
|
|
|
584
622
|
promise.resolve(result)
|
|
585
623
|
} catch (e: Exception) {
|
|
586
624
|
ExpoIapLog.failure("getActiveSubscriptions", e)
|
|
587
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
625
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
588
626
|
}
|
|
589
627
|
}
|
|
590
628
|
}
|
|
@@ -601,7 +639,7 @@ class ExpoIapModule : Module() {
|
|
|
601
639
|
promise.resolve(hasActive)
|
|
602
640
|
} catch (e: Exception) {
|
|
603
641
|
ExpoIapLog.failure("hasActiveSubscriptions", e)
|
|
604
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
642
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
605
643
|
}
|
|
606
644
|
}
|
|
607
645
|
}
|
|
@@ -627,7 +665,7 @@ class ExpoIapModule : Module() {
|
|
|
627
665
|
promise.resolve(response)
|
|
628
666
|
} catch (e: Exception) {
|
|
629
667
|
ExpoIapLog.failure("isBillingProgramAvailableAndroid", e)
|
|
630
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
668
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
631
669
|
}
|
|
632
670
|
}
|
|
633
671
|
}
|
|
@@ -653,7 +691,7 @@ class ExpoIapModule : Module() {
|
|
|
653
691
|
promise.resolve(result.toJson())
|
|
654
692
|
} catch (e: Exception) {
|
|
655
693
|
ExpoIapLog.failure("getBillingChoiceInfoAndroid", e)
|
|
656
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
694
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
657
695
|
}
|
|
658
696
|
}
|
|
659
697
|
}
|
|
@@ -685,7 +723,7 @@ class ExpoIapModule : Module() {
|
|
|
685
723
|
promise.resolve(response)
|
|
686
724
|
} catch (e: Exception) {
|
|
687
725
|
ExpoIapLog.failure("createBillingProgramReportingDetailsAndroid", e)
|
|
688
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
726
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
689
727
|
}
|
|
690
728
|
}
|
|
691
729
|
}
|
|
@@ -719,7 +757,7 @@ class ExpoIapModule : Module() {
|
|
|
719
757
|
promise.resolve(result.toJson())
|
|
720
758
|
} catch (e: Exception) {
|
|
721
759
|
ExpoIapLog.failure("showBillingProgramInformationDialogAndroid", e)
|
|
722
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
760
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
723
761
|
}
|
|
724
762
|
}
|
|
725
763
|
}
|
|
@@ -754,7 +792,7 @@ class ExpoIapModule : Module() {
|
|
|
754
792
|
promise.resolve(result.toJson())
|
|
755
793
|
} catch (e: Exception) {
|
|
756
794
|
ExpoIapLog.failure("showInAppMessagesAndroid", e)
|
|
757
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
795
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
758
796
|
}
|
|
759
797
|
}
|
|
760
798
|
}
|
|
@@ -802,18 +840,24 @@ class ExpoIapModule : Module() {
|
|
|
802
840
|
promise.resolve(result)
|
|
803
841
|
} catch (e: Exception) {
|
|
804
842
|
ExpoIapLog.failure("launchExternalLinkAndroid", e)
|
|
805
|
-
promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
843
|
+
promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, e)
|
|
806
844
|
}
|
|
807
845
|
}
|
|
808
846
|
}
|
|
809
847
|
|
|
810
848
|
OnDestroy {
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
849
|
+
try {
|
|
850
|
+
listenerHandles?.let { ExpoIapHelper.cleanupListeners(openIap, it) }
|
|
851
|
+
} finally {
|
|
852
|
+
listenerHandles = null
|
|
853
|
+
connectionReady.set(false)
|
|
854
|
+
pendingEvents.clear()
|
|
855
|
+
try {
|
|
856
|
+
PromiseUtils.rejectAllPendingPromises()
|
|
857
|
+
} finally {
|
|
858
|
+
job.cancel()
|
|
859
|
+
}
|
|
860
|
+
}
|
|
817
861
|
}
|
|
818
862
|
}
|
|
819
863
|
|
package/build/ExpoIapModule.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { BillingProgramAndroid, BillingProgramReportingDetailsAndroid, Deve
|
|
|
3
3
|
/** Members read from the raw module; every store module provides them. */
|
|
4
4
|
type NativeEventModule = {
|
|
5
5
|
ERROR_CODES?: Record<string, unknown>;
|
|
6
|
+
HAS_EXPLICIT_STORE_PROVIDER?: boolean;
|
|
6
7
|
addListener<T>(eventName: string, listener: (payload: T) => void): EventSubscription | undefined;
|
|
7
8
|
removeListener?<T>(eventName: string, listener: (payload: T) => void): void;
|
|
8
9
|
setPurchaseUpdatedListenerOptions?(options?: PurchaseUpdatedListenerOptions | null): Promise<void>;
|
|
@@ -17,7 +18,7 @@ type MutationFields<K extends keyof Mutation> = {
|
|
|
17
18
|
* Native surface behind the default export. Results the wrappers decode stay
|
|
18
19
|
* `unknown`; the rest match the generated operation signatures.
|
|
19
20
|
*/
|
|
20
|
-
export type ExpoIapNativeModule = NativeEventModule & QueryFields<'canPresentExternalPurchaseNoticeIOS' | 'currentEntitlementIOS' | 'getActiveSubscriptions' | 'getAppTransactionIOS' | 'getBillingChoiceInfoAndroid' | 'getExternalPurchaseCustomLinkTokenIOS' | 'getPromotedProductIOS' | 'getReceiptDataIOS' | 'getTransactionJwsIOS' | 'hasActiveSubscriptions' | 'isEligibleForExternalPurchaseCustomLinkIOS' | 'isEligibleForIntroOfferIOS' | 'isTransactionVerifiedIOS' | 'latestTransactionIOS'> & MutationFields<'beginRefundRequestIOS' | 'clearTransactionIOS' | 'endConnection' | 'initConnection' | 'isBillingProgramAvailableAndroid' | 'launchExternalLinkAndroid' | '
|
|
21
|
+
export type ExpoIapNativeModule = NativeEventModule & QueryFields<'canPresentExternalPurchaseNoticeIOS' | 'currentEntitlementIOS' | 'getActiveSubscriptions' | 'getAppTransactionIOS' | 'getBillingChoiceInfoAndroid' | 'getExternalPurchaseCustomLinkTokenIOS' | 'getPromotedProductIOS' | 'getReceiptDataIOS' | 'getTransactionJwsIOS' | 'hasActiveSubscriptions' | 'isEligibleForExternalPurchaseCustomLinkIOS' | 'isEligibleForIntroOfferIOS' | 'isTransactionVerifiedIOS' | 'latestTransactionIOS'> & MutationFields<'beginRefundRequestIOS' | 'clearTransactionIOS' | 'endConnection' | 'initConnection' | 'isBillingProgramAvailableAndroid' | 'launchExternalLinkAndroid' | 'openRedeemOfferCode' | 'presentExternalPurchaseLinkIOS' | 'presentExternalPurchaseNoticeSheetIOS' | 'showBillingProgramInformationDialogAndroid' | 'showExternalPurchaseCustomLinkNoticeIOS' | 'showInAppMessagesAndroid' | 'syncIOS' | 'verifyPurchase' | 'verifyPurchaseWithProvider'> & {
|
|
21
22
|
USING_ONSIDE_SDK: boolean;
|
|
22
23
|
USING_VEGA_SDK: boolean;
|
|
23
24
|
fetchProducts(request: {
|
|
@@ -30,6 +31,7 @@ export type ExpoIapNativeModule = NativeEventModule & QueryFields<'canPresentExt
|
|
|
30
31
|
getAllTransactionsIOS(): Promise<unknown>;
|
|
31
32
|
getPendingTransactionsIOS(): Promise<unknown>;
|
|
32
33
|
showManageSubscriptionsIOS(): Promise<unknown>;
|
|
34
|
+
deepLinkToSubscriptionsIOS(): Promise<boolean>;
|
|
33
35
|
requestPurchase(request: object): Promise<unknown>;
|
|
34
36
|
finishTransaction(purchase: PurchaseInput, isConsumable: boolean | null): Promise<boolean>;
|
|
35
37
|
/** Internal: the once-per-install flag behind the first-purchase notice. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoIapModule.d.ts","sourceRoot":"","sources":["../src/ExpoIapModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EACV,qBAAqB,EACrB,qCAAqC,EACrC,2BAA2B,EAC3B,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,8BAA8B,EAC9B,KAAK,EACL,UAAU,EACV,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAMjB,0EAA0E;AAC1E,KAAK,iBAAiB,GAAG;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,WAAW,CAAC,CAAC,EACX,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,GAC7B,iBAAiB,GAAG,SAAS,CAAC;IACjC,cAAc,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAC5E,iCAAiC,CAAC,CAChC,OAAO,CAAC,EAAE,8BAA8B,GAAG,IAAI,GAC9C,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB,CAAC;AAEF,KAAK,WAAW,CAAC,CAAC,SAAS,MAAM,KAAK,IAAI;KAAE,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC;CAAC,CAAC;AACpE,KAAK,cAAc,CAAC,CAAC,SAAS,MAAM,QAAQ,IAAI;KAAE,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;CAAC,CAAC;AAE7E;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,GACjD,WAAW,CACP,qCAAqC,GACrC,uBAAuB,GACvB,wBAAwB,GACxB,sBAAsB,GACtB,6BAA6B,GAC7B,uCAAuC,GACvC,uBAAuB,GACvB,mBAAmB,GACnB,sBAAsB,GACtB,wBAAwB,GACxB,4CAA4C,GAC5C,4BAA4B,GAC5B,0BAA0B,GAC1B,sBAAsB,CACzB,GACD,cAAc,CACV,uBAAuB,GACvB,qBAAqB,GACrB,eAAe,GACf,gBAAgB,GAChB,kCAAkC,GAClC,2BAA2B,GAC3B,
|
|
1
|
+
{"version":3,"file":"ExpoIapModule.d.ts","sourceRoot":"","sources":["../src/ExpoIapModule.ts"],"names":[],"mappings":"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"}
|
package/build/ExpoIapModule.js
CHANGED
|
@@ -4,8 +4,27 @@ import { getVegaIapModule, isVegaOS } from './vega';
|
|
|
4
4
|
const ONSIDE_MARKETPLACE_ID = 'com.onside.marketplace-app';
|
|
5
5
|
let cached = null;
|
|
6
6
|
let onsideModuleUnavailable = false;
|
|
7
|
+
let explicitStoreProvider;
|
|
7
8
|
function getResolved() {
|
|
8
9
|
function shouldUseOnsideModule() {
|
|
10
|
+
if (installedFromOnside === true ||
|
|
11
|
+
typeof installedFromOnside === 'string') {
|
|
12
|
+
if (explicitStoreProvider === undefined) {
|
|
13
|
+
try {
|
|
14
|
+
const module = cached?.name === 'ExpoIap'
|
|
15
|
+
? cached.module
|
|
16
|
+
: requireNativeModule('ExpoIap');
|
|
17
|
+
explicitStoreProvider = module.HAS_EXPLICIT_STORE_PROVIDER === true;
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (!isMissingModuleError(error, 'ExpoIap'))
|
|
21
|
+
throw error;
|
|
22
|
+
explicitStoreProvider = false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (explicitStoreProvider)
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
9
28
|
if (installedFromOnside === true) {
|
|
10
29
|
return true;
|
|
11
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoIapModule.js","sourceRoot":"","sources":["../src/ExpoIapModule.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n requireNativeModule,\n UnavailabilityError,\n type EventSubscription,\n} from 'expo-modules-core';\nimport {installedFromOnside} from './onside';\nimport type {\n BillingProgramAndroid,\n BillingProgramReportingDetailsAndroid,\n DeveloperBillingTypeAndroid,\n Mutation,\n MutationField,\n ProductQueryType,\n PurchaseInput,\n PurchaseOptions,\n PurchaseUpdatedListenerOptions,\n Query,\n QueryField,\n SubscriptionStatusIOS,\n} from './types';\nimport {getVegaIapModule, isVegaOS} from './vega';\n\ntype NativeIapModuleName = 'ExpoIapVega' | 'ExpoIapOnside' | 'ExpoIap';\nconst ONSIDE_MARKETPLACE_ID = 'com.onside.marketplace-app';\n\n/** Members read from the raw module; every store module provides them. */\ntype NativeEventModule = {\n ERROR_CODES?: Record<string, unknown>;\n addListener<T>(\n eventName: string,\n listener: (payload: T) => void,\n ): EventSubscription | undefined;\n removeListener?<T>(eventName: string, listener: (payload: T) => void): void;\n setPurchaseUpdatedListenerOptions?(\n options?: PurchaseUpdatedListenerOptions | null,\n ): Promise<void>;\n};\n\ntype QueryFields<K extends keyof Query> = {[P in K]: QueryField<P>};\ntype MutationFields<K extends keyof Mutation> = {[P in K]: MutationField<P>};\n\n/**\n * Native surface behind the default export. Results the wrappers decode stay\n * `unknown`; the rest match the generated operation signatures.\n */\nexport type ExpoIapNativeModule = NativeEventModule &\n QueryFields<\n | 'canPresentExternalPurchaseNoticeIOS'\n | 'currentEntitlementIOS'\n | 'getActiveSubscriptions'\n | 'getAppTransactionIOS'\n | 'getBillingChoiceInfoAndroid'\n | 'getExternalPurchaseCustomLinkTokenIOS'\n | 'getPromotedProductIOS'\n | 'getReceiptDataIOS'\n | 'getTransactionJwsIOS'\n | 'hasActiveSubscriptions'\n | 'isEligibleForExternalPurchaseCustomLinkIOS'\n | 'isEligibleForIntroOfferIOS'\n | 'isTransactionVerifiedIOS'\n | 'latestTransactionIOS'\n > &\n MutationFields<\n | 'beginRefundRequestIOS'\n | 'clearTransactionIOS'\n | 'endConnection'\n | 'initConnection'\n | 'isBillingProgramAvailableAndroid'\n | 'launchExternalLinkAndroid'\n | 'openRedeemOfferCodeAndroid'\n | 'presentCodeRedemptionSheetIOS'\n | 'presentExternalPurchaseLinkIOS'\n | 'presentExternalPurchaseNoticeSheetIOS'\n | 'showBillingProgramInformationDialogAndroid'\n | 'showExternalPurchaseCustomLinkNoticeIOS'\n | 'showInAppMessagesAndroid'\n | 'syncIOS'\n | 'verifyPurchase'\n | 'verifyPurchaseWithProvider'\n > & {\n USING_ONSIDE_SDK: boolean;\n USING_VEGA_SDK: boolean;\n fetchProducts(request: {\n skus: string[];\n type: ProductQueryType;\n }): Promise<unknown[]>;\n fetchProducts(type: ProductQueryType, skus: string[]): Promise<unknown[]>;\n getAvailableItems(\n alsoPublishToEventListenerIOS: boolean,\n onlyIncludeActiveItemsIOS: boolean,\n ): Promise<unknown>;\n getAvailableItems(options: PurchaseOptions): Promise<unknown>;\n getAllTransactionsIOS(): Promise<unknown>;\n getPendingTransactionsIOS(): Promise<unknown>;\n showManageSubscriptionsIOS(): Promise<unknown>;\n requestPurchase(request: object): Promise<unknown>;\n finishTransaction(\n purchase: PurchaseInput,\n isConsumable: boolean | null,\n ): Promise<boolean>;\n /** Internal: the once-per-install flag behind the first-purchase notice. */\n claimFirstPurchaseNotice(): Promise<boolean>;\n acknowledgePurchaseAndroid(purchaseToken: string): Promise<unknown>;\n consumePurchaseAndroid(purchaseToken: string): Promise<unknown>;\n createBillingProgramReportingDetailsAndroid(\n program: BillingProgramAndroid,\n developerBillingType: DeveloperBillingTypeAndroid | null,\n ): Promise<BillingProgramReportingDetailsAndroid>;\n subscriptionStatusIOS(sku: string): Promise<SubscriptionStatusIOS[] | null>;\n requestReceiptRefreshIOS(): Promise<string>;\n deepLinkToSubscriptionsAndroid?(options: {\n skuAndroid?: string;\n packageNameAndroid?: string;\n }): Promise<void> | void;\n getStorefront?(): Promise<string> | string;\n restorePurchases?(): Promise<boolean>;\n };\n\ntype ResolvedNativeModule = {\n module: NativeEventModule;\n name: NativeIapModuleName;\n};\n\nlet cached: ResolvedNativeModule | null = null;\nlet onsideModuleUnavailable = false;\n\nfunction getResolved(): ResolvedNativeModule {\n function shouldUseOnsideModule(): boolean {\n if (installedFromOnside === true) {\n return true;\n }\n\n if (typeof installedFromOnside !== 'string') {\n return false;\n }\n\n const normalized = installedFromOnside.trim().toLowerCase();\n return normalized === 'true' || normalized === ONSIDE_MARKETPLACE_ID;\n }\n\n function getExpectedModuleName(): NativeIapModuleName {\n if (isVegaOS()) {\n return 'ExpoIapVega';\n }\n\n return shouldUseOnsideModule() ? 'ExpoIapOnside' : 'ExpoIap';\n }\n\n function resolveNativeModule(): ResolvedNativeModule {\n if (isVegaOS()) {\n const vegaModule = getVegaIapModule();\n if (!vegaModule) {\n throw new UnavailabilityError(\n 'expo-iap',\n '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.',\n );\n }\n return {module: vegaModule, name: 'ExpoIapVega'};\n }\n\n if (shouldUseOnsideModule()) {\n if (onsideModuleUnavailable) {\n throw new UnavailabilityError(\n 'expo-iap',\n 'The Onside marketplace build does not contain ExpoIapOnside. Rebuild with ios.onside.enabled instead of routing purchases through Apple StoreKit.',\n );\n }\n try {\n return {\n module: requireNativeModule<NativeEventModule>('ExpoIapOnside'),\n name: 'ExpoIapOnside',\n };\n } catch (error) {\n if (!isMissingModuleError(error, 'ExpoIapOnside')) {\n throw error;\n }\n onsideModuleUnavailable = true;\n throw new UnavailabilityError(\n 'expo-iap',\n 'The Onside marketplace build does not contain ExpoIapOnside. Rebuild with ios.onside.enabled instead of routing purchases through Apple StoreKit.',\n );\n }\n }\n\n return {\n module: requireNativeModule<NativeEventModule>('ExpoIap'),\n name: 'ExpoIap',\n };\n }\n\n const expectedName = getExpectedModuleName();\n if (!cached || cached.name !== expectedName) {\n cached = resolveNativeModule();\n }\n return cached;\n}\n\nfunction isMissingModuleError(error: unknown, moduleName: string): boolean {\n if (error instanceof UnavailabilityError) {\n return true;\n }\n\n if (error instanceof Error) {\n return error.message.includes(`Cannot find native module '${moduleName}'`);\n }\n\n return false;\n}\n\nexport const NATIVE_ERROR_CODES: Record<string, unknown> = new Proxy(\n {} as Record<string, unknown>,\n {\n get(target, prop) {\n if (typeof prop === 'symbol') return Reflect.get(target, prop);\n const errorCodes: Record<string, unknown> =\n getResolved().module.ERROR_CODES || {};\n return errorCodes[prop];\n },\n },\n);\n\n/**\n * Returns the raw native module, not the Proxy. Use it for addListener: a JSI\n * HostObject needs the real module as `this`, and a Proxy throws \"native state\n * unsupported on Proxy\" on New Architecture / Hermes.\n */\nexport function getNativeModule(): NativeEventModule {\n return getResolved().module;\n}\n\n// The Proxy forwards every member to the lazily resolved store module.\nexport default new Proxy({} as ExpoIapNativeModule, {\n get(target, prop) {\n if (typeof prop === 'symbol') return Reflect.get(target, prop);\n const resolved = getResolved();\n if (prop === 'USING_ONSIDE_SDK') {\n return resolved.name === 'ExpoIapOnside';\n }\n if (prop === 'USING_VEGA_SDK') {\n return resolved.name === 'ExpoIapVega';\n }\n\n const value: unknown = Reflect.get(resolved.module, prop);\n if (value !== undefined || resolved.name !== 'ExpoIapOnside') {\n return value;\n }\n\n return () => {\n throw new UnavailabilityError(\n 'expo-iap',\n `The Onside marketplace does not support ${String(\n prop,\n )}. The call was not routed through Apple StoreKit.`,\n );\n };\n },\n});\n"]}
|
|
1
|
+
{"version":3,"file":"ExpoIapModule.js","sourceRoot":"","sources":["../src/ExpoIapModule.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GAEpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAC,mBAAmB,EAAC,MAAM,UAAU,CAAC;AAe7C,OAAO,EAAC,gBAAgB,EAAE,QAAQ,EAAC,MAAM,QAAQ,CAAC;AAGlD,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAqG3D,IAAI,MAAM,GAAgC,IAAI,CAAC;AAC/C,IAAI,uBAAuB,GAAG,KAAK,CAAC;AACpC,IAAI,qBAA0C,CAAC;AAE/C,SAAS,WAAW;IAClB,SAAS,qBAAqB;QAC5B,IACE,mBAAmB,KAAK,IAAI;YAC5B,OAAO,mBAAmB,KAAK,QAAQ,EACvC,CAAC;YACD,IAAI,qBAAqB,KAAK,SAAS,EAAE,CAAC;gBACxC,IAAI,CAAC;oBACH,MAAM,MAAM,GACV,MAAM,EAAE,IAAI,KAAK,SAAS;wBACxB,CAAC,CAAC,MAAM,CAAC,MAAM;wBACf,CAAC,CAAC,mBAAmB,CAAoB,SAAS,CAAC,CAAC;oBACxD,qBAAqB,GAAG,MAAM,CAAC,2BAA2B,KAAK,IAAI,CAAC;gBACtE,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,SAAS,CAAC;wBAAE,MAAM,KAAK,CAAC;oBACzD,qBAAqB,GAAG,KAAK,CAAC;gBAChC,CAAC;YACH,CAAC;YACD,IAAI,qBAAqB;gBAAE,OAAO,KAAK,CAAC;QAC1C,CAAC;QACD,IAAI,mBAAmB,KAAK,IAAI,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,OAAO,mBAAmB,KAAK,QAAQ,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC5D,OAAO,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,qBAAqB,CAAC;IACvE,CAAC;IAED,SAAS,qBAAqB;QAC5B,IAAI,QAAQ,EAAE,EAAE,CAAC;YACf,OAAO,aAAa,CAAC;QACvB,CAAC;QAED,OAAO,qBAAqB,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/D,CAAC;IAED,SAAS,mBAAmB;QAC1B,IAAI,QAAQ,EAAE,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;YACtC,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,mBAAmB,CAC3B,UAAU,EACV,+KAA+K,CAChL,CAAC;YACJ,CAAC;YACD,OAAO,EAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAC,CAAC;QACnD,CAAC;QAED,IAAI,qBAAqB,EAAE,EAAE,CAAC;YAC5B,IAAI,uBAAuB,EAAE,CAAC;gBAC5B,MAAM,IAAI,mBAAmB,CAC3B,UAAU,EACV,mJAAmJ,CACpJ,CAAC;YACJ,CAAC;YACD,IAAI,CAAC;gBACH,OAAO;oBACL,MAAM,EAAE,mBAAmB,CAAoB,eAAe,CAAC;oBAC/D,IAAI,EAAE,eAAe;iBACtB,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,eAAe,CAAC,EAAE,CAAC;oBAClD,MAAM,KAAK,CAAC;gBACd,CAAC;gBACD,uBAAuB,GAAG,IAAI,CAAC;gBAC/B,MAAM,IAAI,mBAAmB,CAC3B,UAAU,EACV,mJAAmJ,CACpJ,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO;YACL,MAAM,EAAE,mBAAmB,CAAoB,SAAS,CAAC;YACzD,IAAI,EAAE,SAAS;SAChB,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,qBAAqB,EAAE,CAAC;IAC7C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC5C,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc,EAAE,UAAkB;IAC9D,IAAI,KAAK,YAAY,mBAAmB,EAAE,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,8BAA8B,UAAU,GAAG,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAA4B,IAAI,KAAK,CAClE,EAA6B,EAC7B;IACE,GAAG,CAAC,MAAM,EAAE,IAAI;QACd,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC/D,MAAM,UAAU,GACd,WAAW,EAAE,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;QACzC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF,CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,WAAW,EAAE,CAAC,MAAM,CAAC;AAC9B,CAAC;AAED,uEAAuE;AACvE,eAAe,IAAI,KAAK,CAAC,EAAyB,EAAE;IAClD,GAAG,CAAC,MAAM,EAAE,IAAI;QACd,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,IAAI,IAAI,KAAK,kBAAkB,EAAE,CAAC;YAChC,OAAO,QAAQ,CAAC,IAAI,KAAK,eAAe,CAAC;QAC3C,CAAC;QACD,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;YAC9B,OAAO,QAAQ,CAAC,IAAI,KAAK,aAAa,CAAC;QACzC,CAAC;QAED,MAAM,KAAK,GAAY,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC1D,IAAI,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YAC7D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,GAAG,EAAE;YACV,MAAM,IAAI,mBAAmB,CAC3B,UAAU,EACV,2CAA2C,MAAM,CAC/C,IAAI,CACL,mDAAmD,CACrD,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import {\n requireNativeModule,\n UnavailabilityError,\n type EventSubscription,\n} from 'expo-modules-core';\nimport {installedFromOnside} from './onside';\nimport type {\n BillingProgramAndroid,\n BillingProgramReportingDetailsAndroid,\n DeveloperBillingTypeAndroid,\n Mutation,\n MutationField,\n ProductQueryType,\n PurchaseInput,\n PurchaseOptions,\n PurchaseUpdatedListenerOptions,\n Query,\n QueryField,\n SubscriptionStatusIOS,\n} from './types';\nimport {getVegaIapModule, isVegaOS} from './vega';\n\ntype NativeIapModuleName = 'ExpoIapVega' | 'ExpoIapOnside' | 'ExpoIap';\nconst ONSIDE_MARKETPLACE_ID = 'com.onside.marketplace-app';\n\n/** Members read from the raw module; every store module provides them. */\ntype NativeEventModule = {\n ERROR_CODES?: Record<string, unknown>;\n HAS_EXPLICIT_STORE_PROVIDER?: boolean;\n addListener<T>(\n eventName: string,\n listener: (payload: T) => void,\n ): EventSubscription | undefined;\n removeListener?<T>(eventName: string, listener: (payload: T) => void): void;\n setPurchaseUpdatedListenerOptions?(\n options?: PurchaseUpdatedListenerOptions | null,\n ): Promise<void>;\n};\n\ntype QueryFields<K extends keyof Query> = {[P in K]: QueryField<P>};\ntype MutationFields<K extends keyof Mutation> = {[P in K]: MutationField<P>};\n\n/**\n * Native surface behind the default export. Results the wrappers decode stay\n * `unknown`; the rest match the generated operation signatures.\n */\nexport type ExpoIapNativeModule = NativeEventModule &\n QueryFields<\n | 'canPresentExternalPurchaseNoticeIOS'\n | 'currentEntitlementIOS'\n | 'getActiveSubscriptions'\n | 'getAppTransactionIOS'\n | 'getBillingChoiceInfoAndroid'\n | 'getExternalPurchaseCustomLinkTokenIOS'\n | 'getPromotedProductIOS'\n | 'getReceiptDataIOS'\n | 'getTransactionJwsIOS'\n | 'hasActiveSubscriptions'\n | 'isEligibleForExternalPurchaseCustomLinkIOS'\n | 'isEligibleForIntroOfferIOS'\n | 'isTransactionVerifiedIOS'\n | 'latestTransactionIOS'\n > &\n MutationFields<\n | 'beginRefundRequestIOS'\n | 'clearTransactionIOS'\n | 'endConnection'\n | 'initConnection'\n | 'isBillingProgramAvailableAndroid'\n | 'launchExternalLinkAndroid'\n | 'openRedeemOfferCode'\n | 'presentExternalPurchaseLinkIOS'\n | 'presentExternalPurchaseNoticeSheetIOS'\n | 'showBillingProgramInformationDialogAndroid'\n | 'showExternalPurchaseCustomLinkNoticeIOS'\n | 'showInAppMessagesAndroid'\n | 'syncIOS'\n | 'verifyPurchase'\n | 'verifyPurchaseWithProvider'\n > & {\n USING_ONSIDE_SDK: boolean;\n USING_VEGA_SDK: boolean;\n fetchProducts(request: {\n skus: string[];\n type: ProductQueryType;\n }): Promise<unknown[]>;\n fetchProducts(type: ProductQueryType, skus: string[]): Promise<unknown[]>;\n getAvailableItems(\n alsoPublishToEventListenerIOS: boolean,\n onlyIncludeActiveItemsIOS: boolean,\n ): Promise<unknown>;\n getAvailableItems(options: PurchaseOptions): Promise<unknown>;\n getAllTransactionsIOS(): Promise<unknown>;\n getPendingTransactionsIOS(): Promise<unknown>;\n showManageSubscriptionsIOS(): Promise<unknown>;\n deepLinkToSubscriptionsIOS(): Promise<boolean>;\n requestPurchase(request: object): Promise<unknown>;\n finishTransaction(\n purchase: PurchaseInput,\n isConsumable: boolean | null,\n ): Promise<boolean>;\n /** Internal: the once-per-install flag behind the first-purchase notice. */\n claimFirstPurchaseNotice(): Promise<boolean>;\n acknowledgePurchaseAndroid(purchaseToken: string): Promise<unknown>;\n consumePurchaseAndroid(purchaseToken: string): Promise<unknown>;\n createBillingProgramReportingDetailsAndroid(\n program: BillingProgramAndroid,\n developerBillingType: DeveloperBillingTypeAndroid | null,\n ): Promise<BillingProgramReportingDetailsAndroid>;\n subscriptionStatusIOS(sku: string): Promise<SubscriptionStatusIOS[] | null>;\n requestReceiptRefreshIOS(): Promise<string>;\n deepLinkToSubscriptionsAndroid?(options: {\n skuAndroid?: string;\n packageNameAndroid?: string;\n }): Promise<void> | void;\n getStorefront?(): Promise<string> | string;\n restorePurchases?(): Promise<boolean>;\n };\n\ntype ResolvedNativeModule = {\n module: NativeEventModule;\n name: NativeIapModuleName;\n};\n\nlet cached: ResolvedNativeModule | null = null;\nlet onsideModuleUnavailable = false;\nlet explicitStoreProvider: boolean | undefined;\n\nfunction getResolved(): ResolvedNativeModule {\n function shouldUseOnsideModule(): boolean {\n if (\n installedFromOnside === true ||\n typeof installedFromOnside === 'string'\n ) {\n if (explicitStoreProvider === undefined) {\n try {\n const module =\n cached?.name === 'ExpoIap'\n ? cached.module\n : requireNativeModule<NativeEventModule>('ExpoIap');\n explicitStoreProvider = module.HAS_EXPLICIT_STORE_PROVIDER === true;\n } catch (error) {\n if (!isMissingModuleError(error, 'ExpoIap')) throw error;\n explicitStoreProvider = false;\n }\n }\n if (explicitStoreProvider) return false;\n }\n if (installedFromOnside === true) {\n return true;\n }\n\n if (typeof installedFromOnside !== 'string') {\n return false;\n }\n\n const normalized = installedFromOnside.trim().toLowerCase();\n return normalized === 'true' || normalized === ONSIDE_MARKETPLACE_ID;\n }\n\n function getExpectedModuleName(): NativeIapModuleName {\n if (isVegaOS()) {\n return 'ExpoIapVega';\n }\n\n return shouldUseOnsideModule() ? 'ExpoIapOnside' : 'ExpoIap';\n }\n\n function resolveNativeModule(): ResolvedNativeModule {\n if (isVegaOS()) {\n const vegaModule = getVegaIapModule();\n if (!vegaModule) {\n throw new UnavailabilityError(\n 'expo-iap',\n '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.',\n );\n }\n return {module: vegaModule, name: 'ExpoIapVega'};\n }\n\n if (shouldUseOnsideModule()) {\n if (onsideModuleUnavailable) {\n throw new UnavailabilityError(\n 'expo-iap',\n 'The Onside marketplace build does not contain ExpoIapOnside. Rebuild with ios.onside.enabled instead of routing purchases through Apple StoreKit.',\n );\n }\n try {\n return {\n module: requireNativeModule<NativeEventModule>('ExpoIapOnside'),\n name: 'ExpoIapOnside',\n };\n } catch (error) {\n if (!isMissingModuleError(error, 'ExpoIapOnside')) {\n throw error;\n }\n onsideModuleUnavailable = true;\n throw new UnavailabilityError(\n 'expo-iap',\n 'The Onside marketplace build does not contain ExpoIapOnside. Rebuild with ios.onside.enabled instead of routing purchases through Apple StoreKit.',\n );\n }\n }\n\n return {\n module: requireNativeModule<NativeEventModule>('ExpoIap'),\n name: 'ExpoIap',\n };\n }\n\n const expectedName = getExpectedModuleName();\n if (!cached || cached.name !== expectedName) {\n cached = resolveNativeModule();\n }\n return cached;\n}\n\nfunction isMissingModuleError(error: unknown, moduleName: string): boolean {\n if (error instanceof UnavailabilityError) {\n return true;\n }\n\n if (error instanceof Error) {\n return error.message.includes(`Cannot find native module '${moduleName}'`);\n }\n\n return false;\n}\n\nexport const NATIVE_ERROR_CODES: Record<string, unknown> = new Proxy(\n {} as Record<string, unknown>,\n {\n get(target, prop) {\n if (typeof prop === 'symbol') return Reflect.get(target, prop);\n const errorCodes: Record<string, unknown> =\n getResolved().module.ERROR_CODES || {};\n return errorCodes[prop];\n },\n },\n);\n\n/**\n * Returns the raw native module, not the Proxy. Use it for addListener: a JSI\n * HostObject needs the real module as `this`, and a Proxy throws \"native state\n * unsupported on Proxy\" on New Architecture / Hermes.\n */\nexport function getNativeModule(): NativeEventModule {\n return getResolved().module;\n}\n\n// The Proxy forwards every member to the lazily resolved store module.\nexport default new Proxy({} as ExpoIapNativeModule, {\n get(target, prop) {\n if (typeof prop === 'symbol') return Reflect.get(target, prop);\n const resolved = getResolved();\n if (prop === 'USING_ONSIDE_SDK') {\n return resolved.name === 'ExpoIapOnside';\n }\n if (prop === 'USING_VEGA_SDK') {\n return resolved.name === 'ExpoIapVega';\n }\n\n const value: unknown = Reflect.get(resolved.module, prop);\n if (value !== undefined || resolved.name !== 'ExpoIapOnside') {\n return value;\n }\n\n return () => {\n throw new UnavailabilityError(\n 'expo-iap',\n `The Onside marketplace does not support ${String(\n prop,\n )}. The call was not routed through Apple StoreKit.`,\n );\n };\n },\n});\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -327,7 +327,7 @@ export declare const finishTransaction: MutationField<'finishTransaction'>;
|
|
|
327
327
|
* `getAvailablePurchases` or from hook state.
|
|
328
328
|
*
|
|
329
329
|
* - iOS: sync (or Onside restore when OnsideKit is active), then fetch available purchases.
|
|
330
|
-
* - Android:
|
|
330
|
+
* - Android: run the provider's restore, then fetch available purchases.
|
|
331
331
|
*
|
|
332
332
|
* @see {@link https://openiap.dev/docs/apis/restore-purchases}
|
|
333
333
|
*/
|