expo-iap 4.7.2 → 5.0.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.
Files changed (68) hide show
  1. package/CLAUDE.md +5 -6
  2. package/android/src/main/java/expo/modules/iap/ExpoIapHelper.kt +12 -87
  3. package/android/src/main/java/expo/modules/iap/ExpoIapLog.kt +0 -14
  4. package/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +48 -96
  5. package/build/index.d.ts +1 -19
  6. package/build/index.d.ts.map +1 -1
  7. package/build/index.js +19 -97
  8. package/build/index.js.map +1 -1
  9. package/build/index.kepler.d.ts +1 -42
  10. package/build/index.kepler.d.ts.map +1 -1
  11. package/build/index.kepler.js +11 -65
  12. package/build/index.kepler.js.map +1 -1
  13. package/build/modules/android.d.ts +1 -104
  14. package/build/modules/android.d.ts.map +1 -1
  15. package/build/modules/android.js +0 -124
  16. package/build/modules/android.js.map +1 -1
  17. package/build/modules/ios.d.ts +2 -57
  18. package/build/modules/ios.d.ts.map +1 -1
  19. package/build/modules/ios.js +7 -105
  20. package/build/modules/ios.js.map +1 -1
  21. package/build/types.d.ts +87 -284
  22. package/build/types.d.ts.map +1 -1
  23. package/build/types.js +0 -6
  24. package/build/types.js.map +1 -1
  25. package/build/useIAP.d.ts +1 -34
  26. package/build/useIAP.d.ts.map +1 -1
  27. package/build/useIAP.js +12 -54
  28. package/build/useIAP.js.map +1 -1
  29. package/build/utils/availablePurchases.d.ts +8 -0
  30. package/build/utils/availablePurchases.d.ts.map +1 -0
  31. package/build/utils/availablePurchases.js +74 -0
  32. package/build/utils/availablePurchases.js.map +1 -0
  33. package/build/utils/errorMapping.d.ts.map +1 -1
  34. package/build/utils/errorMapping.js +25 -7
  35. package/build/utils/errorMapping.js.map +1 -1
  36. package/build/utils/restorePurchases.d.ts +9 -0
  37. package/build/utils/restorePurchases.d.ts.map +1 -0
  38. package/build/utils/restorePurchases.js +29 -0
  39. package/build/utils/restorePurchases.js.map +1 -0
  40. package/build/vega-adapter.d.ts +1 -1
  41. package/build/vega-adapter.d.ts.map +1 -1
  42. package/build/vega-adapter.js +20 -34
  43. package/build/vega-adapter.js.map +1 -1
  44. package/ios/ExpoIapHelper.swift +46 -55
  45. package/ios/ExpoIapLog.swift +0 -11
  46. package/ios/ExpoIapModule.swift +26 -52
  47. package/ios/onside/OnsideIapModule.swift +1 -19
  48. package/openiap-versions.json +3 -3
  49. package/package.json +1 -1
  50. package/plugin/build/withIAP.d.ts +2 -14
  51. package/plugin/build/withIAP.js +6 -67
  52. package/plugin/src/expoConfig.augmentation.d.ts +6 -33
  53. package/plugin/src/withIAP.ts +8 -132
  54. package/src/index.kepler.ts +13 -92
  55. package/src/index.ts +21 -135
  56. package/src/modules/android.ts +0 -152
  57. package/src/modules/ios.ts +8 -125
  58. package/src/types.ts +88 -295
  59. package/src/useIAP.ts +14 -112
  60. package/src/utils/availablePurchases.ts +105 -0
  61. package/src/utils/errorMapping.ts +31 -7
  62. package/src/utils/restorePurchases.ts +31 -0
  63. package/src/vega-adapter.ts +37 -37
  64. package/build/utils/deprecation.d.ts +0 -3
  65. package/build/utils/deprecation.d.ts.map +0 -1
  66. package/build/utils/deprecation.js +0 -13
  67. package/build/utils/deprecation.js.map +0 -1
  68. package/src/utils/deprecation.ts +0 -16
package/CLAUDE.md CHANGED
@@ -51,18 +51,17 @@ Before committing any changes:
51
51
 
52
52
  #### Function Naming
53
53
 
54
- - Functions that only operate on one platform must carry the suffix: `nameIOS` or `nameAndroid` (e.g. `getStorefrontIOS`, `deepLinkToSubscriptionsAndroid`).
54
+ - Functions that only operate on one platform must carry the suffix: `nameIOS` or `nameAndroid` (e.g. `getReceiptDataIOS`, `deepLinkToSubscriptionsAndroid`).
55
55
  - Cross-platform helpers should expose a single name and branch internally via `Platform.select` or equivalent.
56
56
 
57
57
  #### Field Naming
58
58
 
59
- - **iOS-related fields**: Use `IOS` suffix (e.g., `displayNameIOS`, `discountsIOS`, `introductoryPriceIOS`)
59
+ - **iOS-related fields**: Use `IOS` suffix (e.g., `displayNameIOS`, `subscriptionGroupIdIOS`, `introductoryPriceIOS`)
60
60
  - **Exception**: When an acronym appears at the end of a field name, use uppercase (e.g., `quantityIOS`, `appBundleIdIOS`, not `quantityIos`)
61
61
  - Platform-specific fields: `currencyCodeIOS`, `currencySymbolIOS`, `countryCodeIOS`
62
- - Product fields: `isFamilyShareableIOS`, `jsonRepresentationIOS`, `subscriptionInfoIOS`
62
+ - Product fields: `isFamilyShareableIOS`, `jsonRepresentationIOS`, `subscriptionGroupIdIOS`
63
63
  - **Android-related fields**: Use `Android` suffix (e.g., `nameAndroid`)
64
- - Platform-specific fields: `oneTimePurchaseOfferDetailsAndroid`, `subscriptionOfferDetailsAndroid`
65
- - In **Android-specific types** (e.g., `ProductSubscriptionAndroidOfferDetails`), keep `pricingPhases` without suffix for consistency with Google Play Billing
64
+ - Platform-specific fields: `productStatusAndroid`, `basePlanIdAndroid`
66
65
  - In **cross-platform types** (e.g., `SubscriptionOffer`, `DiscountOffer`), use `pricingPhasesAndroid` suffix to distinguish from common fields
67
66
  - **Common fields**: Fields shared across platforms go in Common types (e.g., `ids`, `platform`, `debugDescription`)
68
67
  - Use these for data that exists on both platforms without platform-specific variations
@@ -71,7 +70,7 @@ Before committing any changes:
71
70
 
72
71
  - **iOS types**: Use `IOS` suffix (e.g., `PurchaseIOS`, `ProductIOS`)
73
72
  - **Android types**: Use descriptive prefixes to identify subtypes:
74
- - ✅ Good: `ProductAndroidOneTimePurchaseOfferDetail`, `ProductSubscriptionAndroidOfferDetails`, `PurchaseAndroidState`
73
+ - ✅ Good: `BillingProgramAvailabilityResultAndroid`, `SubscriptionPeriodIOS`, `PurchaseAndroidState`
75
74
  - ❌ Avoid: `OneTimePurchaseOfferDetails`, `SubscriptionOfferAndroid`, `PurchaseStateAndroid`
76
75
  - **General IAP types**: Use `Iap` prefix (e.g., `IapPurchase`, not `IAPPurchase`)
77
76
 
@@ -64,76 +64,35 @@ object ExpoIapHelper {
64
64
  }
65
65
 
66
66
  fun parseProductQueryType(rawType: String?): ProductQueryType {
67
- val normalized =
68
- rawType
69
- ?.trim()
70
- ?.lowercase(Locale.US)
71
- ?.replace("-", "")
72
- ?.replace("_", "")
73
-
67
+ val normalized = rawType?.trim()?.lowercase(Locale.US)
74
68
  return when (normalized) {
69
+ null, "", "in-app" -> ProductQueryType.InApp
75
70
  "subs" -> ProductQueryType.Subs
76
71
  "all" -> ProductQueryType.All
77
- else -> ProductQueryType.InApp
72
+ else -> throw IllegalArgumentException(
73
+ "Unsupported product type: $rawType. Use in-app, subs, or all.",
74
+ )
78
75
  }
79
76
  }
80
77
 
81
78
  internal fun parseDeepLinkSubscriptionParams(params: Map<String, Any?>): DeepLinkSubscriptionParams {
82
- val hasCanonicalSku = params.containsKey("skuAndroid")
83
- val hasCanonicalPackageName = params.containsKey("packageNameAndroid")
84
- val legacySku = params["sku"] as? String
85
- val legacyPackageName = params["packageName"] as? String
86
-
87
- if (!hasCanonicalSku && legacySku != null) {
88
- ExpoIapLog.deprecation(
89
- "deep-link.sku",
90
- "`sku` is deprecated and will be removed in expo-iap 5.0.0. Use `skuAndroid` instead.",
91
- )
92
- }
93
- if (!hasCanonicalPackageName && legacyPackageName != null) {
94
- ExpoIapLog.deprecation(
95
- "deep-link.packageName",
96
- "`packageName` is deprecated and will be removed in expo-iap 5.0.0. Use `packageNameAndroid` instead.",
97
- )
98
- }
99
-
100
79
  return DeepLinkSubscriptionParams(
101
- sku =
102
- if (hasCanonicalSku) {
103
- params["skuAndroid"] as? String
104
- } else {
105
- legacySku
106
- },
107
- packageName =
108
- if (hasCanonicalPackageName) {
109
- params["packageNameAndroid"] as? String
110
- } else {
111
- legacyPackageName
112
- },
80
+ sku = params["skuAndroid"] as? String,
81
+ packageName = params["packageNameAndroid"] as? String,
113
82
  )
114
83
  }
115
84
 
116
85
  fun parseRequestPurchaseParams(params: Map<String, Any?>): RequestPurchaseParams {
117
- // Support nested request.google / request.android structure
118
- // If the params contain a "request" key with nested platform-specific data,
119
- // extract and flatten it before parsing.
86
+ // If the params contain a canonical request.google envelope, flatten it
87
+ // before parsing the native request.
120
88
  val effective: Map<String, Any?> =
121
89
  run {
122
90
  val request = params["request"] as? Map<*, *>
123
91
  if (request != null) {
124
- val hasCanonicalGoogle = request.containsKey("google")
125
- val canonicalGoogle = request["google"] as? Map<*, *>
126
- val legacyAndroid = request["android"] as? Map<*, *>
127
- if (!hasCanonicalGoogle && legacyAndroid != null) {
128
- ExpoIapLog.deprecation(
129
- "request-purchase.android",
130
- "`request.android` is deprecated and will be removed in expo-iap 5.0.0. Use `request.google` instead.",
131
- )
132
- }
133
- val nested = if (hasCanonicalGoogle) canonicalGoogle else legacyAndroid
92
+ val nested = request["google"] as? Map<*, *>
134
93
  if (nested != null) {
135
94
  val flat = mutableMapOf<String, Any?>()
136
- // Carry over top-level fields like type, useAlternativeBilling
95
+ // Carry over top-level fields such as the purchase type.
137
96
  for ((k, v) in params) {
138
97
  if (k != "request") flat[k] = v
139
98
  }
@@ -151,33 +110,10 @@ object ExpoIapHelper {
151
110
  }
152
111
 
153
112
  val type = effective["type"] as? String
154
- val hasCanonicalSkus = effective.containsKey("skus")
155
- val canonicalSkus = (effective["skus"] as? List<*>)?.filterIsInstance<String>()
156
- val legacySkuArr = (effective["skuArr"] as? List<*>)?.filterIsInstance<String>()
157
- if (!hasCanonicalSkus && legacySkuArr != null) {
158
- ExpoIapLog.deprecation(
159
- "request-purchase.skuArr",
160
- "`skuArr` is deprecated and will be removed in expo-iap 5.0.0. Use `skus` instead.",
161
- )
162
- }
163
- val skus: List<String> =
164
- if (hasCanonicalSkus) {
165
- canonicalSkus ?: emptyList()
166
- } else {
167
- legacySkuArr ?: emptyList()
168
- }
113
+ val skus = (effective["skus"] as? List<*>)?.filterIsInstance<String>() ?: emptyList()
169
114
  val obfuscatedAccountId = effective["obfuscatedAccountId"] as? String
170
115
  val obfuscatedProfileId = effective["obfuscatedProfileId"] as? String
171
116
  val isOfferPersonalized = effective["isOfferPersonalized"] as? Boolean ?: false
172
- val hasCanonicalSubscriptionOffers = effective.containsKey("subscriptionOffers")
173
- val legacyOfferTokenArr =
174
- (effective["offerTokenArr"] as? List<*>)?.filterIsInstance<String>() ?: emptyList()
175
- val offerTokenArr =
176
- if (hasCanonicalSubscriptionOffers) {
177
- emptyList()
178
- } else {
179
- legacyOfferTokenArr
180
- }
181
117
  val explicitSubscriptionOffers =
182
118
  (effective["subscriptionOffers"] as? List<*>)?.mapNotNull { rawOffer ->
183
119
  val offerMap = rawOffer as? Map<*, *> ?: return@mapNotNull null
@@ -189,15 +125,8 @@ object ExpoIapHelper {
189
125
  AndroidSubscriptionOfferInput(offerToken = offerToken, sku = sku)
190
126
  }
191
127
  } ?: emptyList()
192
- if (!hasCanonicalSubscriptionOffers && offerTokenArr.isNotEmpty()) {
193
- ExpoIapLog.deprecation(
194
- "request-purchase.offerTokenArr",
195
- "`offerTokenArr` is deprecated and will be removed in expo-iap 5.0.0. Use `subscriptionOffers` instead.",
196
- )
197
- }
198
128
  val purchaseToken = effective["purchaseToken"] as? String
199
129
  val originalExternalTransactionId = effective["originalExternalTransactionId"] as? String
200
- val replacementMode = effective["replacementMode"] as? Number
201
130
  val developerBillingOption =
202
131
  (effective["developerBillingOption"] as? Map<*, *>)?.let { optionMap ->
203
132
  val json =
@@ -230,12 +159,10 @@ object ExpoIapHelper {
230
159
  obfuscatedProfileId = obfuscatedProfileId,
231
160
  isOfferPersonalized = isOfferPersonalized,
232
161
  offerToken = offerToken,
233
- offerTokenArr = offerTokenArr,
234
162
  explicitSubscriptionOffers = explicitSubscriptionOffers,
235
163
  developerBillingOption = developerBillingOption,
236
164
  originalExternalTransactionId = originalExternalTransactionId,
237
165
  purchaseToken = purchaseToken,
238
- replacementMode = replacementMode,
239
166
  subscriptionProductReplacementParams = subscriptionProductReplacementParams,
240
167
  )
241
168
  }
@@ -259,12 +186,10 @@ object ExpoIapHelper {
259
186
  val isOfferPersonalized: Boolean,
260
187
  /** Offer token for one-time purchase discounts (Android 8.0+) */
261
188
  val offerToken: String?,
262
- val offerTokenArr: List<String>,
263
189
  val explicitSubscriptionOffers: List<AndroidSubscriptionOfferInput>,
264
190
  val developerBillingOption: DeveloperBillingOptionParamsAndroid?,
265
191
  val originalExternalTransactionId: String?,
266
192
  val purchaseToken: String?,
267
- val replacementMode: Number?,
268
193
  val subscriptionProductReplacementParams: SubscriptionProductReplacementParamsAndroid?,
269
194
  )
270
195
 
@@ -3,14 +3,10 @@ package expo.modules.iap
3
3
  import android.util.Log
4
4
  import org.json.JSONArray
5
5
  import org.json.JSONObject
6
- import java.util.Collections
7
6
  import java.util.Locale
8
- import java.util.concurrent.ConcurrentHashMap
9
7
 
10
8
  internal object ExpoIapLog {
11
9
  private const val TAG = "ExpoIap"
12
- private val emittedDeprecations: MutableSet<String> =
13
- Collections.newSetFromMap(ConcurrentHashMap())
14
10
  private val SENSITIVE_KEY_FRAGMENTS =
15
11
  setOf(
16
12
  "token",
@@ -57,16 +53,6 @@ internal object ExpoIapLog {
57
53
  Log.w(TAG, message)
58
54
  }
59
55
 
60
- fun deprecation(
61
- key: String,
62
- message: String,
63
- ) {
64
- if (!emittedDeprecations.add(key)) {
65
- return
66
- }
67
- Log.w(TAG, message)
68
- }
69
-
70
56
  fun debug(message: String) {
71
57
  if (BuildConfig.DEBUG || Log.isLoggable(TAG, Log.DEBUG)) {
72
58
  Log.d(TAG, message)
@@ -1,7 +1,6 @@
1
1
  package expo.modules.iap
2
2
 
3
3
  import android.content.Context
4
- import dev.hyo.openiap.AndroidSubscriptionOfferInput
5
4
  import dev.hyo.openiap.DeepLinkOptions
6
5
  import dev.hyo.openiap.FetchProductsResultAll
7
6
  import dev.hyo.openiap.FetchProductsResultProducts
@@ -28,6 +27,7 @@ import expo.modules.kotlin.Promise
28
27
  import expo.modules.kotlin.exception.Exceptions
29
28
  import expo.modules.kotlin.modules.Module
30
29
  import expo.modules.kotlin.modules.ModuleDefinition
30
+ import kotlinx.coroutines.CancellationException
31
31
  import kotlinx.coroutines.CoroutineScope
32
32
  import kotlinx.coroutines.Dispatchers
33
33
  import kotlinx.coroutines.Job
@@ -59,6 +59,20 @@ internal suspend fun endExpoConnectionWithCleanup(
59
59
  internal fun endConnectionErrorCode(error: Exception): String =
60
60
  (error as? OpenIapError)?.code ?: OpenIapError.ServiceDisconnected.CODE
61
61
 
62
+ internal fun deliverPurchaseRequestFailure(
63
+ reachedOpenIapRequest: Boolean,
64
+ isCancellation: Boolean = false,
65
+ errorCode: String,
66
+ errorEnvelope: String,
67
+ emitLocalError: () -> Unit,
68
+ rejectPendingPromises: (String, String) -> Unit,
69
+ ) {
70
+ if (!reachedOpenIapRequest && !isCancellation) {
71
+ emitLocalError()
72
+ }
73
+ rejectPendingPromises(errorCode, errorEnvelope)
74
+ }
75
+
62
76
  class ExpoIapModule : Module() {
63
77
  companion object {
64
78
  const val TAG = "ExpoIapModule"
@@ -203,15 +217,15 @@ class ExpoIapModule : Module() {
203
217
  }
204
218
  }
205
219
 
206
- AsyncFunction("fetchProducts") { type: String, skuArr: Array<String>, promise: Promise ->
220
+ AsyncFunction("fetchProducts") { type: String, skus: Array<String>, promise: Promise ->
207
221
  ExpoIapLog.payload(
208
222
  "fetchProducts",
209
- mapOf("type" to type, "skus" to skuArr.toList()),
223
+ mapOf("type" to type, "skus" to skus.toList()),
210
224
  )
211
225
  scope.launch {
212
226
  try {
213
227
  val queryType = ExpoIapHelper.parseProductQueryType(type)
214
- val request = ProductRequest(skuArr.toList(), queryType)
228
+ val request = ProductRequest(skus.toList(), queryType)
215
229
  val result = openIap.fetchProducts(request)
216
230
  val payload =
217
231
  when (result) {
@@ -232,7 +246,7 @@ class ExpoIapModule : Module() {
232
246
  "message" to "Failed to query products",
233
247
  "debugMessage" to e.message,
234
248
  "platform" to "android",
235
- "productIds" to skuArr.toList(),
249
+ "productIds" to skus.toList(),
236
250
  "productType" to type,
237
251
  )
238
252
  }
@@ -339,22 +353,8 @@ class ExpoIapModule : Module() {
339
353
  else -> ProductQueryType.InApp
340
354
  }
341
355
 
342
- val fallbackOffers =
343
- if (parsedParams.explicitSubscriptionOffers.isEmpty() && parsedParams.offerTokenArr.isNotEmpty()) {
344
- parsedParams.skus.zip(parsedParams.offerTokenArr).mapNotNull { (sku, token) ->
345
- if (token.isNotEmpty()) {
346
- AndroidSubscriptionOfferInput(offerToken = token, sku = sku)
347
- } else {
348
- null
349
- }
350
- }
351
- } else {
352
- emptyList()
353
- }
354
-
355
356
  val subscriptionOffers =
356
- (parsedParams.explicitSubscriptionOffers.ifEmpty { fallbackOffers })
357
- .takeIf { it.isNotEmpty() }
357
+ parsedParams.explicitSubscriptionOffers.takeIf { it.isNotEmpty() }
358
358
 
359
359
  val requestProps =
360
360
  when (productType) {
@@ -367,7 +367,6 @@ class ExpoIapModule : Module() {
367
367
  developerBillingOption = parsedParams.developerBillingOption,
368
368
  originalExternalTransactionId = parsedParams.originalExternalTransactionId,
369
369
  purchaseToken = parsedParams.purchaseToken,
370
- replacementMode = parsedParams.replacementMode?.toInt(),
371
370
  skus = parsedParams.skus,
372
371
  subscriptionOffers = subscriptionOffers,
373
372
  subscriptionProductReplacementParams = parsedParams.subscriptionProductReplacementParams,
@@ -403,9 +402,11 @@ class ExpoIapModule : Module() {
403
402
 
404
403
  ExpoIapHelper.addPurchasePromise(promise)
405
404
  scope.launch {
405
+ var reachedOpenIapRequest = false
406
406
  try {
407
407
  val activity = currentActivity
408
408
  openIap.setActivity(activity)
409
+ reachedOpenIapRequest = true
409
410
  val result = openIap.requestPurchase(requestProps)
410
411
  val purchases =
411
412
  when (result) {
@@ -431,23 +432,33 @@ class ExpoIapModule : Module() {
431
432
  )
432
433
  }
433
434
  val errorCode = errorMap["code"] as? String ?: OpenIapError.PurchaseFailed.CODE
434
- runCatching {
435
- ExpoIapHelper.emitOrQueue(
436
- this@ExpoIapModule,
437
- scope,
438
- connectionReady,
439
- pendingEvents,
440
- EVENT_PURCHASE_ERROR,
441
- errorMap,
442
- )
443
- }.onFailure { ex ->
444
- ExpoIapLog.failure("send PURCHASE_ERROR event requestPurchase", ex)
445
- }
446
- ExpoIapHelper.rejectPurchasePromises(
447
- errorCode,
448
- ExpoIapHelper.serializeErrorEnvelope(errorMap),
449
- null,
435
+ val errorEnvelope = ExpoIapHelper.serializeErrorEnvelope(errorMap)
436
+ deliverPurchaseRequestFailure(
437
+ reachedOpenIapRequest = reachedOpenIapRequest,
438
+ isCancellation = e is CancellationException,
439
+ errorCode = errorCode,
440
+ errorEnvelope = errorEnvelope,
441
+ emitLocalError = {
442
+ runCatching {
443
+ ExpoIapHelper.emitOrQueue(
444
+ this@ExpoIapModule,
445
+ scope,
446
+ connectionReady,
447
+ pendingEvents,
448
+ EVENT_PURCHASE_ERROR,
449
+ errorMap,
450
+ )
451
+ }.onFailure { ex ->
452
+ ExpoIapLog.failure("send PURCHASE_ERROR event requestPurchase", ex)
453
+ }
454
+ },
455
+ rejectPendingPromises = { code, message ->
456
+ ExpoIapHelper.rejectPurchasePromises(code, message, null)
457
+ },
450
458
  )
459
+ if (e is CancellationException) {
460
+ throw e
461
+ }
451
462
  }
452
463
  }
453
464
  }
@@ -486,65 +497,6 @@ class ExpoIapModule : Module() {
486
497
  }
487
498
  }
488
499
 
489
- @Suppress("DEPRECATION")
490
- AsyncFunction("checkAlternativeBillingAvailabilityAndroid") { promise: Promise ->
491
- ExpoIapLog.payload("checkAlternativeBillingAvailabilityAndroid", null)
492
- scope.launch {
493
- try {
494
- val isAvailable = openIap.checkAlternativeBillingAvailability()
495
- ExpoIapLog.result("checkAlternativeBillingAvailabilityAndroid", isAvailable)
496
- promise.resolve(isAvailable)
497
- } catch (e: Exception) {
498
- ExpoIapLog.failure("checkAlternativeBillingAvailabilityAndroid", e)
499
- promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, null)
500
- }
501
- }
502
- }
503
-
504
- @Suppress("DEPRECATION")
505
- AsyncFunction("showAlternativeBillingDialogAndroid") { promise: Promise ->
506
- ExpoIapLog.payload("showAlternativeBillingDialogAndroid", null)
507
- scope.launch {
508
- try {
509
- val activity =
510
- runCatching { currentActivity }
511
- .onFailure {
512
- ExpoIapLog.failure("showAlternativeBillingDialogAndroid activity", it)
513
- }.getOrNull() ?: run {
514
- promise.reject(OpenIapError.ServiceUnavailable.CODE, "Activity not available", null)
515
- return@launch
516
- }
517
- openIap.setActivity(activity)
518
- val userAccepted = openIap.showAlternativeBillingInformationDialog(activity)
519
- ExpoIapLog.result("showAlternativeBillingDialogAndroid", userAccepted)
520
- promise.resolve(userAccepted)
521
- } catch (e: Exception) {
522
- ExpoIapLog.failure("showAlternativeBillingDialogAndroid", e)
523
- promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, null)
524
- }
525
- }
526
- }
527
-
528
- @Suppress("DEPRECATION")
529
- AsyncFunction("createAlternativeBillingTokenAndroid") { sku: String?, promise: Promise ->
530
- ExpoIapLog.payload("createAlternativeBillingTokenAndroid", mapOf("sku" to sku))
531
- scope.launch {
532
- try {
533
- // Note: OpenIapModule.createAlternativeBillingReportingToken() doesn't accept sku parameter
534
- // The sku parameter is ignored for now - may be used in future versions
535
- val token = openIap.createAlternativeBillingReportingToken()
536
- ExpoIapLog.result(
537
- "createAlternativeBillingTokenAndroid",
538
- if (token.isNullOrBlank()) "<empty>" else "<token>",
539
- )
540
- promise.resolve(token)
541
- } catch (e: Exception) {
542
- ExpoIapLog.failure("createAlternativeBillingTokenAndroid", e)
543
- promise.reject(OpenIapError.ServiceUnavailable.CODE, e.message, null)
544
- }
545
- }
546
- }
547
-
548
500
  @Suppress("UNCHECKED_CAST")
549
501
  AsyncFunction("verifyPurchase") { params: Map<String, Any?>, promise: Promise ->
550
502
  ExpoIapLog.payload("verifyPurchase", params)
package/build/index.d.ts CHANGED
@@ -41,11 +41,7 @@ type ExpoIapEmitter = {
41
41
  removeListener<E extends OpenIapEvent>(eventName: E, listener: ExpoIapEventListener<E>): void;
42
42
  };
43
43
  export declare const emitter: ExpoIapEmitter;
44
- /**
45
- * Accepts the legacy 'inapp' alias for backward compatibility. The alias is
46
- * deprecated and scheduled for removal in expo-iap 5.0.0 — use 'in-app'.
47
- */
48
- export type ProductTypeInput = ProductQueryType | 'inapp';
44
+ export type ProductTypeInput = ProductQueryType;
49
45
  export declare const purchaseUpdatedListener: (listener: (event: Purchase) => void, options?: PurchaseUpdatedListenerOptions | null) => {
50
46
  remove: () => void;
51
47
  };
@@ -373,20 +369,6 @@ export declare const restorePurchases: MutationField<'restorePurchases'>;
373
369
  * @see {@link https://openiap.dev/docs/apis/deep-link-to-subscriptions}
374
370
  */
375
371
  export declare const deepLinkToSubscriptions: MutationField<'deepLinkToSubscriptions'>;
376
- /**
377
- * Internal receipt validation function (NOT RECOMMENDED for production use)
378
- *
379
- * WARNING: This function performs client-side validation which is NOT secure.
380
- * For production apps, always validate receipts on your secure server:
381
- * - iOS: Send receipt data to Apple's verification endpoint from your server
382
- * - Android: Use Google Play Developer API with service account credentials
383
- *
384
- * @deprecated Use verifyPurchase instead. This function will be removed in
385
- * expo-iap 5.0.0.
386
- *
387
- * @see {@link https://openiap.dev/docs/apis/validate-receipt}
388
- */
389
- export declare const validateReceipt: MutationField<'validateReceipt'>;
390
372
  /**
391
373
  * Verify purchase with the configured providers
392
374
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}