react-native-iap 12.14.1-rc.1 → 12.14.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 (26) hide show
  1. package/README.md +4 -6
  2. package/android/gradle.properties +1 -1
  3. package/android/src/amazon/java/com/dooboolab/rniap/PurchasingServiceProxy.kt +2 -8
  4. package/android/src/amazon/java/com/dooboolab/rniap/PurchasingServiceProxyAmazonImpl.kt +18 -12
  5. package/android/src/amazon/java/com/dooboolab/rniap/RNIapAmazonListener.kt +2 -4
  6. package/android/src/amazon/java/com/dooboolab/rniap/RNIapAmazonModule.kt +29 -45
  7. package/android/src/amazon/java/com/dooboolab/rniap/RNIapPackage.kt +4 -1
  8. package/android/src/main/java/com/dooboolab/rniap/PromiseUtils.kt +2 -9
  9. package/android/src/main/java/com/dooboolab/rniap/PromiseUtlis.kt +6 -15
  10. package/android/src/play/java/com/dooboolab/rniap/PlayUtils.kt +70 -86
  11. package/android/src/play/java/com/dooboolab/rniap/RNIapModule.kt +209 -196
  12. package/android/src/play/java/com/dooboolab/rniap/RNIapPackage.kt +4 -1
  13. package/android/src/testAmazon/java/com/dooboolab/rniap/RNIapAmazonModuleTest.kt +19 -23
  14. package/lib/commonjs/eventEmitter.js.map +1 -1
  15. package/lib/commonjs/modules/iosSk2.js.map +1 -1
  16. package/lib/module/eventEmitter.js.map +1 -1
  17. package/lib/module/modules/iosSk2.js.map +1 -1
  18. package/lib/typescript/plugin/src/withIAP.d.ts +1 -1
  19. package/lib/typescript/plugin/src/withIAP.d.ts.map +1 -1
  20. package/lib/typescript/src/eventEmitter.d.ts.map +1 -1
  21. package/lib/typescript/src/modules/iosSk2.d.ts.map +1 -1
  22. package/package.json +8 -8
  23. package/plugin/build/withIAP.d.ts +1 -1
  24. package/plugin/build/withIAP.js +7 -7
  25. package/src/eventEmitter.ts +7 -1
  26. package/src/modules/iosSk2.ts +3 -2
@@ -34,18 +34,21 @@ import com.facebook.react.module.annotations.ReactModule
34
34
  import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter
35
35
  import com.google.android.gms.common.ConnectionResult
36
36
  import com.google.android.gms.common.GoogleApiAvailability
37
-
37
+ import java.util.ArrayList
38
38
  @ReactModule(name = RNIapModule.TAG)
39
39
  class RNIapModule(
40
40
  private val reactContext: ReactApplicationContext,
41
41
  private val builder: BillingClient.Builder = BillingClient.newBuilder(reactContext).enablePendingPurchases(),
42
42
  private val googleApiAvailability: GoogleApiAvailability = GoogleApiAvailability.getInstance(),
43
- ) : ReactContextBaseJavaModule(reactContext),
43
+ ) :
44
+ ReactContextBaseJavaModule(reactContext),
44
45
  PurchasesUpdatedListener {
46
+
45
47
  private var billingClientCache: BillingClient? = null
46
48
  private val skus: MutableMap<String, ProductDetails> = mutableMapOf()
47
-
48
- override fun getName(): String = TAG
49
+ override fun getName(): String {
50
+ return TAG
51
+ }
49
52
 
50
53
  fun ensureConnection(
51
54
  promise: Promise,
@@ -56,73 +59,68 @@ class RNIapModule(
56
59
  callback(billingClient)
57
60
  return
58
61
  } else {
59
- val nested =
60
- PromiseImpl(
61
- {
62
- if (it.isNotEmpty() && it[0] is Boolean && it[0] as Boolean) {
63
- val connectedBillingClient = billingClientCache
64
- if (connectedBillingClient?.isReady == true) {
65
- callback(connectedBillingClient)
66
- } else {
67
- promise.safeReject(PromiseUtils.E_NOT_PREPARED, "Unable to auto-initialize connection")
68
- }
62
+ val nested = PromiseImpl(
63
+ {
64
+ if (it.isNotEmpty() && it[0] is Boolean && it[0] as Boolean) {
65
+ val connectedBillingClient = billingClientCache
66
+ if (connectedBillingClient?.isReady == true) {
67
+ callback(connectedBillingClient)
69
68
  } else {
70
- promise.safeReject(PromiseUtils.E_UNKNOWN, "ensureConnection - incorrect parameter in resolve")
71
- Log.i(TAG, "Incorrect parameter in resolve")
72
- }
73
- },
74
- {
75
- var errorCode: String? = null
76
- var errorMessage: String? = null
77
- if (it.size > 1 && it[0] is String && it[1] is String) {
78
- errorCode = it[0] as String
79
- errorMessage = it[1] as String
80
- } else if (it.isNotEmpty() && it[0] is WritableNativeMap) {
81
- val errorMap = it[0] as WritableNativeMap
82
- errorCode = errorMap.getString("code")
83
- errorMessage = errorMap.getString("message")
69
+ promise.safeReject(PromiseUtils.E_NOT_PREPARED, "Unable to auto-initialize connection")
84
70
  }
71
+ } else {
72
+ promise.safeReject(PromiseUtils.E_UNKNOWN, "ensureConnection - incorrect parameter in resolve")
73
+ Log.i(TAG, "Incorrect parameter in resolve")
74
+ }
75
+ },
76
+ {
77
+ var errorCode: String? = null
78
+ var errorMessage: String? = null
79
+ if (it.size > 1 && it[0] is String && it[1] is String) {
80
+ errorCode = it[0] as String
81
+ errorMessage = it[1] as String
82
+ } else if (it.isNotEmpty() && it[0] is WritableNativeMap) {
83
+ val errorMap = it[0] as WritableNativeMap
84
+ errorCode = errorMap.getString("code")
85
+ errorMessage = errorMap.getString("message")
86
+ }
85
87
 
86
- if (errorCode is String && errorMessage is String) {
87
- promise.safeReject(
88
- errorCode,
89
- errorMessage,
90
- )
91
- } else {
92
- promise.safeReject(PromiseUtils.E_UNKNOWN, "ensureConnection - incorrect parameter in reject")
93
- Log.i(TAG, "Incorrect parameters in reject")
94
- }
95
- },
96
- )
88
+ if (errorCode is String && errorMessage is String) {
89
+ promise.safeReject(
90
+ errorCode,
91
+ errorMessage,
92
+ )
93
+ } else {
94
+ promise.safeReject(PromiseUtils.E_UNKNOWN, "ensureConnection - incorrect parameter in reject")
95
+ Log.i(TAG, "Incorrect parameters in reject")
96
+ }
97
+ },
98
+ )
97
99
  initConnection(nested)
98
100
  }
99
101
  }
100
102
 
101
103
  @ReactMethod
102
- fun isFeatureSupported(
103
- feature: String,
104
- promise: Promise,
105
- ) {
104
+ fun isFeatureSupported(feature: String, promise: Promise) {
106
105
  ensureConnection(
107
106
  promise,
108
107
  ) { billingClient ->
109
- val f =
110
- when (feature) {
111
- "IN_APP_MESSAGING" ->
112
- BillingClient.FeatureType.IN_APP_MESSAGING
113
- "PRICE_CHANGE_CONFIRMATION" ->
114
- BillingClient.FeatureType.PRICE_CHANGE_CONFIRMATION
115
- "PRODUCT_DETAILS" ->
116
- BillingClient.FeatureType.PRODUCT_DETAILS
117
- "SUBSCRIPTIONS" ->
118
- BillingClient.FeatureType.SUBSCRIPTIONS
119
- "SUBSCRIPTIONS_UPDATE" ->
120
- BillingClient.FeatureType.SUBSCRIPTIONS_UPDATE
121
- else -> {
122
- promise.safeReject("Invalid Feature name")
123
- return@ensureConnection
124
- }
108
+ val f = when (feature) {
109
+ "IN_APP_MESSAGING" ->
110
+ BillingClient.FeatureType.IN_APP_MESSAGING
111
+ "PRICE_CHANGE_CONFIRMATION" ->
112
+ BillingClient.FeatureType.PRICE_CHANGE_CONFIRMATION
113
+ "PRODUCT_DETAILS" ->
114
+ BillingClient.FeatureType.PRODUCT_DETAILS
115
+ "SUBSCRIPTIONS" ->
116
+ BillingClient.FeatureType.SUBSCRIPTIONS
117
+ "SUBSCRIPTIONS_UPDATE" ->
118
+ BillingClient.FeatureType.SUBSCRIPTIONS_UPDATE
119
+ else -> {
120
+ promise.safeReject("Invalid Feature name")
121
+ return@ensureConnection
125
122
  }
123
+ }
126
124
  promise.safeResolve(billingClient.isFeatureSupported(f))
127
125
  }
128
126
  }
@@ -182,9 +180,7 @@ class RNIapModule(
182
180
  promise,
183
181
  ) { billingClient ->
184
182
  val consumeParams =
185
- ConsumeParams
186
- .newBuilder()
187
- .setPurchaseToken(purchase.purchaseToken)
183
+ ConsumeParams.newBuilder().setPurchaseToken(purchase.purchaseToken)
188
184
  .build()
189
185
  val listener =
190
186
  ConsumeResponseListener { billingResult: BillingResult, outToken: String? ->
@@ -209,11 +205,9 @@ class RNIapModule(
209
205
  promise,
210
206
  ) { billingClient ->
211
207
  billingClient.queryPurchasesAsync(
212
- QueryPurchasesParams
213
- .newBuilder()
214
- .setProductType(
215
- BillingClient.ProductType.INAPP,
216
- ).build(),
208
+ QueryPurchasesParams.newBuilder().setProductType(
209
+ BillingClient.ProductType.INAPP,
210
+ ).build(),
217
211
  ) { billingResult: BillingResult, list: List<Purchase>? ->
218
212
  if (!isValidResult(billingResult, promise)) return@queryPurchasesAsync
219
213
  if (list == null) {
@@ -239,39 +233,25 @@ class RNIapModule(
239
233
  }
240
234
 
241
235
  @ReactMethod
242
- fun getItemsByType(
243
- type: String,
244
- skuArr: ReadableArray,
245
- promise: Promise,
246
- ) {
247
- ensureConnection(promise) { billingClient ->
248
- val skuList = mutableListOf<QueryProductDetailsParams.Product>()
236
+ fun getItemsByType(type: String, skuArr: ReadableArray, promise: Promise) {
237
+ ensureConnection(
238
+ promise,
239
+ ) { billingClient ->
240
+ val skuList = ArrayList<QueryProductDetailsParams.Product>()
249
241
  for (i in 0 until skuArr.size()) {
250
242
  if (skuArr.getType(i) == ReadableType.String) {
251
- skuArr.getString(i)?.let { sku ->
243
+ skuArr.getString(i)?.let { sku -> // null check for older versions of RN
252
244
  skuList.add(
253
- QueryProductDetailsParams.Product
254
- .newBuilder()
255
- .setProductId(sku)
256
- .setProductType(type)
257
- .build(),
245
+ QueryProductDetailsParams.Product.newBuilder().setProductId(sku)
246
+ .setProductType(type).build(),
258
247
  )
259
248
  }
260
249
  }
261
250
  }
262
-
263
- if (skuList.isEmpty()) {
264
- promise.safeReject("EMPTY_SKU_LIST", "The SKU list is empty.")
265
- return@ensureConnection
266
- }
267
-
268
- val params =
269
- QueryProductDetailsParams
270
- .newBuilder()
271
- .setProductList(skuList)
272
- .build()
273
-
274
- billingClient.queryProductDetailsAsync(params) { billingResult, skuDetailsList ->
251
+ val params = QueryProductDetailsParams.newBuilder().setProductList(skuList)
252
+ billingClient.queryProductDetailsAsync(
253
+ params.build(),
254
+ ) { billingResult: BillingResult, skuDetailsList: List<ProductDetails> ->
275
255
  if (!isValidResult(billingResult, promise)) return@queryProductDetailsAsync
276
256
 
277
257
  val items = Arguments.createArray()
@@ -284,51 +264,68 @@ class RNIapModule(
284
264
  item.putString("description", skuDetails.description)
285
265
  item.putString("productType", skuDetails.productType)
286
266
  item.putString("name", skuDetails.name)
287
-
267
+ val oneTimePurchaseOfferDetails = Arguments.createMap()
288
268
  skuDetails.oneTimePurchaseOfferDetails?.let {
289
- val oneTimePurchaseOfferDetails =
290
- Arguments.createMap().apply {
291
- putString("priceCurrencyCode", it.priceCurrencyCode)
292
- putString("formattedPrice", it.formattedPrice)
293
- putString("priceAmountMicros", it.priceAmountMicros.toString())
294
- }
269
+ oneTimePurchaseOfferDetails.putString(
270
+ "priceCurrencyCode",
271
+ it.priceCurrencyCode,
272
+ )
273
+ oneTimePurchaseOfferDetails.putString("formattedPrice", it.formattedPrice)
274
+ oneTimePurchaseOfferDetails.putString(
275
+ "priceAmountMicros",
276
+ it.priceAmountMicros.toString(),
277
+ )
295
278
  item.putMap("oneTimePurchaseOfferDetails", oneTimePurchaseOfferDetails)
296
279
  }
297
-
298
280
  skuDetails.subscriptionOfferDetails?.let {
299
281
  val subscriptionOfferDetails = Arguments.createArray()
300
282
  it.forEach { subscriptionOfferDetailsItem ->
301
- val offerDetails =
302
- Arguments.createMap().apply {
303
- putString("basePlanId", subscriptionOfferDetailsItem.basePlanId)
304
- putString("offerId", subscriptionOfferDetailsItem.offerId)
305
- putString("offerToken", subscriptionOfferDetailsItem.offerToken)
306
-
307
- val offerTags = Arguments.createArray()
308
- subscriptionOfferDetailsItem.offerTags.forEach { offerTag ->
309
- offerTags.pushString(offerTag)
310
- }
311
- putArray("offerTags", offerTags)
312
-
313
- val pricingPhasesList = Arguments.createArray()
314
- subscriptionOfferDetailsItem.pricingPhases.pricingPhaseList.forEach { pricingPhaseItem ->
315
- val pricingPhase =
316
- Arguments.createMap().apply {
317
- putString("formattedPrice", pricingPhaseItem.formattedPrice)
318
- putString("priceCurrencyCode", pricingPhaseItem.priceCurrencyCode)
319
- putString("billingPeriod", pricingPhaseItem.billingPeriod)
320
- putInt("billingCycleCount", pricingPhaseItem.billingCycleCount)
321
- putString("priceAmountMicros", pricingPhaseItem.priceAmountMicros.toString())
322
- putInt("recurrenceMode", pricingPhaseItem.recurrenceMode)
323
- }
324
- pricingPhasesList.pushMap(pricingPhase)
325
- }
326
- val pricingPhases =
327
- Arguments.createMap().apply {
328
- putArray("pricingPhaseList", pricingPhasesList)
329
- }
330
- putMap("pricingPhases", pricingPhases)
331
- }
283
+ val offerDetails = Arguments.createMap()
284
+ offerDetails.putString(
285
+ "basePlanId",
286
+ subscriptionOfferDetailsItem.basePlanId,
287
+ )
288
+ offerDetails.putString(
289
+ "offerId",
290
+ subscriptionOfferDetailsItem.offerId,
291
+ )
292
+ offerDetails.putString(
293
+ "offerToken",
294
+ subscriptionOfferDetailsItem.offerToken,
295
+ )
296
+ val offerTags = Arguments.createArray()
297
+ subscriptionOfferDetailsItem.offerTags.forEach { offerTag ->
298
+ offerTags.pushString(offerTag)
299
+ }
300
+ offerDetails.putArray("offerTags", offerTags)
301
+
302
+ val pricingPhasesList = Arguments.createArray()
303
+ subscriptionOfferDetailsItem.pricingPhases.pricingPhaseList.forEach { pricingPhaseItem ->
304
+ val pricingPhase = Arguments.createMap()
305
+ pricingPhase.putString(
306
+ "formattedPrice",
307
+ pricingPhaseItem.formattedPrice,
308
+ )
309
+ pricingPhase.putString(
310
+ "priceCurrencyCode",
311
+ pricingPhaseItem.priceCurrencyCode,
312
+ )
313
+ pricingPhase.putString("billingPeriod", pricingPhaseItem.billingPeriod)
314
+ pricingPhase.putInt(
315
+ "billingCycleCount",
316
+ pricingPhaseItem.billingCycleCount,
317
+ )
318
+ pricingPhase.putString(
319
+ "priceAmountMicros",
320
+ pricingPhaseItem.priceAmountMicros.toString(),
321
+ )
322
+ pricingPhase.putInt("recurrenceMode", pricingPhaseItem.recurrenceMode)
323
+
324
+ pricingPhasesList.pushMap(pricingPhase)
325
+ }
326
+ val pricingPhases = Arguments.createMap()
327
+ pricingPhases.putArray("pricingPhaseList", pricingPhasesList)
328
+ offerDetails.putMap("pricingPhases", pricingPhases)
332
329
  subscriptionOfferDetails.pushMap(offerDetails)
333
330
  }
334
331
  item.putArray("subscriptionOfferDetails", subscriptionOfferDetails)
@@ -356,20 +353,15 @@ class RNIapModule(
356
353
  }
357
354
 
358
355
  @ReactMethod
359
- fun getAvailableItemsByType(
360
- type: String,
361
- promise: Promise,
362
- ) {
356
+ fun getAvailableItemsByType(type: String, promise: Promise) {
363
357
  ensureConnection(
364
358
  promise,
365
359
  ) { billingClient ->
366
360
  val items = WritableNativeArray()
367
361
  billingClient.queryPurchasesAsync(
368
- QueryPurchasesParams
369
- .newBuilder()
370
- .setProductType(
371
- if (type == "subs") BillingClient.ProductType.SUBS else BillingClient.ProductType.INAPP,
372
- ).build(),
362
+ QueryPurchasesParams.newBuilder().setProductType(
363
+ if (type == "subs") BillingClient.ProductType.SUBS else BillingClient.ProductType.INAPP,
364
+ ).build(),
373
365
  ) { billingResult: BillingResult, purchases: List<Purchase>? ->
374
366
  if (!isValidResult(billingResult, promise)) return@queryPurchasesAsync
375
367
  purchases?.forEach { purchase ->
@@ -407,20 +399,16 @@ class RNIapModule(
407
399
  }
408
400
 
409
401
  @ReactMethod
410
- fun getPurchaseHistoryByType(
411
- type: String,
412
- promise: Promise,
413
- ) {
402
+ fun getPurchaseHistoryByType(type: String, promise: Promise) {
414
403
  ensureConnection(
415
404
  promise,
416
405
  ) { billingClient ->
417
406
  billingClient.queryPurchaseHistoryAsync(
418
- QueryPurchaseHistoryParams
419
- .newBuilder()
420
- .setProductType(
421
- if (type == "subs") BillingClient.ProductType.SUBS else BillingClient.ProductType.INAPP,
422
- ).build(),
423
- ) { billingResult: BillingResult, purchaseHistoryRecordList: MutableList<PurchaseHistoryRecord>? ->
407
+ QueryPurchaseHistoryParams.newBuilder().setProductType(
408
+ if (type == "subs") BillingClient.ProductType.SUBS else BillingClient.ProductType.INAPP,
409
+ ).build(),
410
+ ) {
411
+ billingResult: BillingResult, purchaseHistoryRecordList: MutableList<PurchaseHistoryRecord>? ->
424
412
 
425
413
  if (!isValidResult(billingResult, promise)) return@queryPurchaseHistoryAsync
426
414
 
@@ -450,7 +438,7 @@ class RNIapModule(
450
438
  type: String,
451
439
  skuArr: ReadableArray,
452
440
  purchaseToken: String?,
453
- replacementMode: Int,
441
+ prorationMode: Int,
454
442
  obfuscatedAccountId: String?,
455
443
  obfuscatedProfileId: String?,
456
444
  offerTokenArr: ReadableArray, // New parameter in V5
@@ -497,8 +485,7 @@ class RNIapModule(
497
485
  }
498
486
  var productDetailParams = BillingFlowParams.ProductDetailsParams.newBuilder().setProductDetails(selectedSku)
499
487
  if (type == BillingClient.ProductType.SUBS) {
500
- offerTokenArr.getString(index)?.let { offerToken ->
501
- // null check for older versions of RN
488
+ offerTokenArr.getString(index)?.let { offerToken -> // null check for older versions of RN
502
489
  productDetailParams = productDetailParams.setOfferToken(offerToken)
503
490
  }
504
491
  }
@@ -510,23 +497,6 @@ class RNIapModule(
510
497
  val subscriptionUpdateParamsBuilder = SubscriptionUpdateParams.newBuilder()
511
498
  if (purchaseToken != null) {
512
499
  subscriptionUpdateParamsBuilder.setOldPurchaseToken(purchaseToken)
513
-
514
- if (type == BillingClient.ProductType.SUBS && replacementMode != -1) {
515
- val replacementMode =
516
- when (replacementMode) {
517
- BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.CHARGE_PRORATED_PRICE -> BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.CHARGE_PRORATED_PRICE
518
- BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.WITHOUT_PRORATION -> BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.WITHOUT_PRORATION
519
- BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.DEFERRED -> BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.DEFERRED
520
- BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.WITH_TIME_PRORATION -> BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.WITH_TIME_PRORATION
521
- BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.CHARGE_FULL_PRICE -> BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.CHARGE_FULL_PRICE
522
- else -> BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.UNKNOWN_REPLACEMENT_MODE
523
- }
524
- subscriptionUpdateParamsBuilder.setSubscriptionReplacementMode(replacementMode)
525
- }
526
- if (purchaseToken != null) {
527
- val subscriptionUpdateParams = subscriptionUpdateParamsBuilder.build()
528
- builder.setSubscriptionUpdateParams(subscriptionUpdateParams)
529
- }
530
500
  }
531
501
  if (obfuscatedAccountId != null) {
532
502
  builder.setObfuscatedAccountId(obfuscatedAccountId)
@@ -534,7 +504,60 @@ class RNIapModule(
534
504
  if (obfuscatedProfileId != null) {
535
505
  builder.setObfuscatedProfileId(obfuscatedProfileId)
536
506
  }
537
-
507
+ if (prorationMode != -1) {
508
+ if (prorationMode
509
+ == BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE
510
+ ) {
511
+ subscriptionUpdateParamsBuilder.setReplaceProrationMode(
512
+ BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE,
513
+ )
514
+ if (type != BillingClient.ProductType.SUBS) {
515
+ val debugMessage =
516
+ (
517
+ "IMMEDIATE_AND_CHARGE_PRORATED_PRICE for proration mode only works in" +
518
+ " subscription purchase."
519
+ )
520
+ val error = Arguments.createMap()
521
+ error.putString("debugMessage", debugMessage)
522
+ error.putString("code", PROMISE_BUY_ITEM)
523
+ error.putString("message", debugMessage)
524
+ error.putArray("productIds", skuArr)
525
+ sendEvent(reactContext, "purchase-error", error)
526
+ promise.safeReject(PROMISE_BUY_ITEM, debugMessage)
527
+ return@ensureConnection
528
+ }
529
+ } else if (prorationMode
530
+ == BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION
531
+ ) {
532
+ subscriptionUpdateParamsBuilder.setReplaceProrationMode(
533
+ BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION,
534
+ )
535
+ } else if (prorationMode == BillingFlowParams.ProrationMode.DEFERRED) {
536
+ subscriptionUpdateParamsBuilder.setReplaceProrationMode(
537
+ BillingFlowParams.ProrationMode.DEFERRED,
538
+ )
539
+ } else if (prorationMode
540
+ == BillingFlowParams.ProrationMode.IMMEDIATE_WITH_TIME_PRORATION
541
+ ) {
542
+ subscriptionUpdateParamsBuilder.setReplaceProrationMode(
543
+ BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION,
544
+ )
545
+ } else if (prorationMode
546
+ == BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE
547
+ ) {
548
+ subscriptionUpdateParamsBuilder.setReplaceProrationMode(
549
+ BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE,
550
+ )
551
+ } else {
552
+ subscriptionUpdateParamsBuilder.setReplaceProrationMode(
553
+ BillingFlowParams.ProrationMode.UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY,
554
+ )
555
+ }
556
+ }
557
+ if (purchaseToken != null) {
558
+ val subscriptionUpdateParams = subscriptionUpdateParamsBuilder.build()
559
+ builder.setSubscriptionUpdateParams(subscriptionUpdateParams)
560
+ }
538
561
  val flowParams = builder.build()
539
562
  val billingResultCode = billingClient.launchBillingFlow(activity, flowParams).responseCode
540
563
  if (billingResultCode != BillingClient.BillingResponseCode.OK) {
@@ -554,11 +577,9 @@ class RNIapModule(
554
577
  promise,
555
578
  ) { billingClient ->
556
579
  val acknowledgePurchaseParams =
557
- AcknowledgePurchaseParams
558
- .newBuilder()
559
- .setPurchaseToken(
560
- token,
561
- ).build()
580
+ AcknowledgePurchaseParams.newBuilder().setPurchaseToken(
581
+ token,
582
+ ).build()
562
583
  billingClient.acknowledgePurchase(
563
584
  acknowledgePurchaseParams,
564
585
  ) { billingResult: BillingResult ->
@@ -602,10 +623,7 @@ class RNIapModule(
602
623
  }
603
624
  }
604
625
 
605
- override fun onPurchasesUpdated(
606
- billingResult: BillingResult,
607
- purchases: List<Purchase>?,
608
- ) {
626
+ override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
609
627
  val responseCode = billingResult.responseCode
610
628
  if (responseCode != BillingClient.BillingResponseCode.OK) {
611
629
  val error = Arguments.createMap()
@@ -673,11 +691,9 @@ class RNIapModule(
673
691
  val types = arrayOf(BillingClient.ProductType.INAPP, BillingClient.ProductType.SUBS)
674
692
  for (type in types) {
675
693
  billingClient.queryPurchasesAsync(
676
- QueryPurchasesParams
677
- .newBuilder()
678
- .setProductType(
679
- type,
680
- ).build(),
694
+ QueryPurchasesParams.newBuilder().setProductType(
695
+ type,
696
+ ).build(),
681
697
  ) { billingResult: BillingResult, list: List<Purchase> ->
682
698
  if (!isValidResult(billingResult, promise)) return@queryPurchasesAsync
683
699
 
@@ -723,17 +739,14 @@ class RNIapModule(
723
739
  }
724
740
 
725
741
  init {
726
- val lifecycleEventListener: LifecycleEventListener =
727
- object : LifecycleEventListener {
728
- override fun onHostResume() {}
729
-
730
- override fun onHostPause() {}
731
-
732
- override fun onHostDestroy() {
733
- billingClientCache?.endConnection()
734
- billingClientCache = null
735
- }
742
+ val lifecycleEventListener: LifecycleEventListener = object : LifecycleEventListener {
743
+ override fun onHostResume() {}
744
+ override fun onHostPause() {}
745
+ override fun onHostDestroy() {
746
+ billingClientCache?.endConnection()
747
+ billingClientCache = null
736
748
  }
749
+ }
737
750
  reactContext.addLifecycleEventListener(lifecycleEventListener)
738
751
  }
739
752
  }
@@ -7,7 +7,10 @@ import com.facebook.react.uimanager.ViewManager
7
7
  import java.util.ArrayList
8
8
 
9
9
  class RNIapPackage : ReactPackage {
10
- override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = emptyList()
10
+
11
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
12
+ return emptyList()
13
+ }
11
14
 
12
15
  override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
13
16
  val modules: MutableList<NativeModule> = ArrayList()
@@ -26,6 +26,7 @@ import org.junit.Test
26
26
  import java.util.*
27
27
 
28
28
  class RNIapAmazonModuleTest {
29
+
29
30
  @MockK
30
31
  lateinit var context: ReactApplicationContext
31
32
 
@@ -76,38 +77,33 @@ class RNIapAmazonModuleTest {
76
77
 
77
78
  @Test
78
79
  fun `Purchase Item`() {
79
- val purchaseResponse =
80
- mockk<PurchaseResponse> {
81
- every { requestId } returns RequestId.fromString("0")
82
-
83
- every { requestStatus } returns PurchaseResponse.RequestStatus.SUCCESSFUL
84
- val mReceipt =
85
- mockk<Receipt>(relaxed = true) {
86
- every { sku } returns "mySku"
87
- every { purchaseDate } returns Date()
88
- every { receiptId } returns "rId"
89
- }
90
- every { receipt } returns mReceipt
91
- val mUserData =
92
- mockk<UserData>(relaxed = true) {
93
- every { userId } returns "uid1"
94
- }
95
- every { userData } returns mUserData
80
+ val purchaseResponse = mockk<PurchaseResponse>() {
81
+ every { requestId } returns RequestId.fromString("0")
82
+
83
+ every { requestStatus } returns PurchaseResponse.RequestStatus.SUCCESSFUL
84
+ val mReceipt = mockk<Receipt>(relaxed = true) {
85
+ every { sku } returns "mySku"
86
+ every { purchaseDate } returns Date()
87
+ every { receiptId } returns "rId"
88
+ }
89
+ every { receipt } returns mReceipt
90
+ val mUserData = mockk<UserData>(relaxed = true) {
91
+ every { userId } returns "uid1"
96
92
  }
93
+ every { userData } returns mUserData
94
+ }
97
95
 
98
96
  every { eventSender.sendEvent(any(), any()) } just Runs
99
97
 
100
98
  every { purchasingServiceProxy.purchase(any()) } answers {
101
99
  listener.onPurchaseResponse(
102
100
  purchaseResponse,
103
- )
104
- RequestId.fromString("0")
101
+ ); RequestId.fromString("0")
105
102
  }
106
103
 
107
- val itemsMap =
108
- mockk<WritableMap>(relaxed = true) {
109
- every { getString("productId") } returns "mySku"
110
- }
104
+ val itemsMap = mockk<WritableMap>(relaxed = true) {
105
+ every { getString("productId") } returns "mySku"
106
+ }
111
107
  mockkStatic(Arguments::class)
112
108
 
113
109
  every { Arguments.createMap() } returns itemsMap
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_appleSk","_iap","_internal","purchaseUpdatedListener","listener","eventEmitter","NativeEventEmitter","getNativeModule","proxyListener","isIosStorekit2","event","transactionSk2ToPurchaseMap","emitterSubscription","addListener","isAndroid","getAndroidModule","startListening","exports","purchaseErrorListener","promotedProductListener","isIos","getIosModule","transactionListener"],"sourceRoot":"../../src","sources":["eventEmitter.ts"],"mappings":"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"}
1
+ {"version":3,"names":["_reactNative","require","_appleSk","_iap","_internal","purchaseUpdatedListener","listener","eventEmitter","NativeEventEmitter","getNativeModule","proxyListener","isIosStorekit2","event","transactionSk2ToPurchaseMap","emitterSubscription","addListener","isAndroid","getAndroidModule","startListening","exports","purchaseErrorListener","promotedProductListener","isIos","getIosModule","transactionListener"],"sourceRoot":"../../src","sources":["eventEmitter.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,IAAAC,QAAA,GAAAD,OAAA;AACA,IAAAE,IAAA,GAAAF,OAAA;AACA,IAAAG,SAAA,GAAAH,OAAA;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMI,uBAAuB,GAClCC,QAAmC,IAChC;EACH,MAAMC,YAAY,GAAG,IAAIC,+BAAkB,CAAC,IAAAC,yBAAe,EAAC,CAAC,CAAC;EAC9D,MAAMC,aAAa,GAAG,IAAAC,mBAAc,EAAC,CAAC,GACjCC,KAAe,IAAK;IACnBN,QAAQ,CAAC,IAAAO,oCAA2B,EAACD,KAAY,CAAC,CAAC;EACrD,CAAC,GACDN,QAAQ;EACZ,MAAMQ,mBAAmB,GAAGP,YAAY,CAACQ,WAAW,CAClD,kBAAkB,EAClBL,aACF,CAAC;EAED,IAAIM,mBAAS,EAAE;IACb,IAAAC,0BAAgB,EAAC,CAAC,CAACC,cAAc,CAAC,CAAC;EACrC;EAEA,OAAOJ,mBAAmB;AAC5B,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAhCAK,OAAA,CAAAd,uBAAA,GAAAA,uBAAA;AAiCO,MAAMe,qBAAqB,GAChCd,QAAwC,IAChB;EACxB,MAAMC,YAAY,GAAG,IAAIC,+BAAkB,CAAC,IAAAC,yBAAe,EAAC,CAAC,CAAC;EAC9D,OAAOF,YAAY,CAACQ,WAAW,CAAC,gBAAgB,EAAET,QAAQ,CAAC;AAC7D,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAlCAa,OAAA,CAAAC,qBAAA,GAAAA,qBAAA;AAmCO,MAAMC,uBAAuB,GAAIf,QAAoB,IAAK;EAC/D,IAAIgB,eAAK,IAAI,CAAC,IAAAX,mBAAc,EAAC,CAAC,EAAE;IAC9B,MAAMJ,YAAY,GAAG,IAAIC,+BAAkB,CAAC,IAAAe,sBAAY,EAAC,CAAC,CAAC;IAC3D,OAAOhB,YAAY,CAACQ,WAAW,CAAC,sBAAsB,EAAET,QAAQ,CAAC;EACnE;EAEA,OAAO,IAAI;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAzCAa,OAAA,CAAAE,uBAAA,GAAAA,uBAAA;AA0CO,MAAMG,mBAAmB,GAC9BlB,QAA2C,IACxC;EACH,IAAIgB,eAAK,IAAI,IAAAX,mBAAc,EAAC,CAAC,EAAE;IAC7B,MAAMJ,YAAY,GAAG,IAAIC,+BAAkB,CAAC,IAAAe,sBAAY,EAAC,CAAC,CAAC;IAC3D,OAAOhB,YAAY,CAACQ,WAAW,CAAC,yBAAyB,EAAET,QAAQ,CAAC;EACtE;EAEA,OAAO,IAAI;AACb,CAAC;AAACa,OAAA,CAAAK,mBAAA,GAAAA,mBAAA"}