react-native-iap 9.0.0-beta → 9.0.0-beta10

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 (94) hide show
  1. package/README.md +11 -22
  2. package/RNIap.podspec +33 -18
  3. package/android/build.gradle +137 -38
  4. package/android/gradle.properties +8 -0
  5. package/android/src/play/java/com/dooboolab/RNIap/RNIapModule.kt +75 -62
  6. package/android/src/play/java/com/dooboolab/RNIap/RNIapPackage.kt +0 -1
  7. package/android/src/testPlay/java/com/dooboolab/RNIap/{RNIapModuleTestV4.kt → RNIapModuleTest.kt} +48 -34
  8. package/ios/RNIapIos-Bridging-Header.h +2 -0
  9. package/ios/RNIapIos.m +14 -1
  10. package/ios/RNIapIos.swift +903 -883
  11. package/ios/{RNIap.xcodeproj → RNIapIos.xcodeproj}/project.pbxproj +29 -116
  12. package/lib/commonjs/__test__/iap.test.js +21 -0
  13. package/lib/commonjs/__test__/iap.test.js.map +1 -0
  14. package/lib/commonjs/hooks/useIAP.js +78 -0
  15. package/lib/commonjs/hooks/useIAP.js.map +1 -0
  16. package/lib/commonjs/hooks/withIAPContext.js +92 -0
  17. package/lib/commonjs/hooks/withIAPContext.js.map +1 -0
  18. package/lib/commonjs/iap.js +585 -0
  19. package/lib/commonjs/iap.js.map +1 -0
  20. package/lib/commonjs/index.js +59 -0
  21. package/lib/commonjs/index.js.map +1 -0
  22. package/lib/commonjs/types/amazon.js +2 -0
  23. package/lib/commonjs/types/amazon.js.map +1 -0
  24. package/lib/commonjs/types/android.js +55 -0
  25. package/lib/commonjs/types/android.js.map +1 -0
  26. package/lib/commonjs/types/apple.js +165 -0
  27. package/lib/commonjs/types/apple.js.map +1 -0
  28. package/lib/commonjs/types/index.js +59 -0
  29. package/lib/commonjs/types/index.js.map +1 -0
  30. package/lib/module/__test__/iap.test.js +17 -0
  31. package/lib/module/__test__/iap.test.js.map +1 -0
  32. package/lib/module/hooks/useIAP.js +68 -0
  33. package/lib/module/hooks/useIAP.js.map +1 -0
  34. package/lib/module/hooks/withIAPContext.js +76 -0
  35. package/lib/module/hooks/withIAPContext.js.map +1 -0
  36. package/lib/module/iap.js +493 -0
  37. package/lib/module/iap.js.map +1 -0
  38. package/lib/module/index.js +6 -0
  39. package/lib/module/index.js.map +1 -0
  40. package/lib/module/types/amazon.js +2 -0
  41. package/lib/module/types/amazon.js.map +1 -0
  42. package/lib/module/types/android.js +44 -0
  43. package/lib/module/types/android.js.map +1 -0
  44. package/lib/module/types/apple.js +153 -0
  45. package/lib/module/types/apple.js.map +1 -0
  46. package/lib/module/types/index.js +48 -0
  47. package/lib/module/types/index.js.map +1 -0
  48. package/{src → lib/typescript}/__test__/iap.test.d.ts +0 -0
  49. package/{src → lib/typescript}/hooks/useIAP.d.ts +1 -1
  50. package/{src → lib/typescript}/hooks/withIAPContext.d.ts +1 -1
  51. package/{src → lib/typescript}/iap.d.ts +16 -12
  52. package/{src → lib/typescript}/index.d.ts +2 -1
  53. package/{src → lib/typescript}/types/amazon.d.ts +0 -0
  54. package/{src → lib/typescript}/types/android.d.ts +0 -0
  55. package/{src → lib/typescript}/types/apple.d.ts +0 -0
  56. package/{src → lib/typescript}/types/index.d.ts +53 -22
  57. package/package.json +87 -57
  58. package/src/__test__/iap.test.ts +20 -0
  59. package/src/hooks/useIAP.ts +130 -0
  60. package/src/hooks/withIAPContext.tsx +160 -0
  61. package/src/iap.ts +699 -0
  62. package/src/{index.js → index.ts} +4 -1
  63. package/src/types/amazon.ts +23 -0
  64. package/src/types/android.ts +51 -0
  65. package/src/types/apple.ts +467 -0
  66. package/src/types/index.ts +209 -0
  67. package/.editorconfig +0 -10
  68. package/.flowconfig +0 -11
  69. package/.monolinterrc +0 -3
  70. package/.yarn/install-state.gz +0 -0
  71. package/.yarn/releases/yarn-3.2.0.cjs +0 -785
  72. package/.yarnrc.yml +0 -3
  73. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  74. package/android/gradle/wrapper/gradle-wrapper.properties +0 -6
  75. package/android/gradlew +0 -160
  76. package/android/gradlew.bat +0 -90
  77. package/android/src/play/java/com/dooboolab/RNIap/RNIapModuleInterface.kt +0 -44
  78. package/android/src/play/java/com/dooboolab/RNIap/RNIapModuleV4.kt +0 -656
  79. package/babel.config.js +0 -10
  80. package/index.d.ts +0 -3
  81. package/index.js +0 -3
  82. package/index.js.flow +0 -9
  83. package/ios/RNIap.xcodeproj/xcshareddata/xcschemes/RNIap.xcscheme +0 -80
  84. package/ios/RNIapQueue.swift +0 -36
  85. package/jest.config.js +0 -194
  86. package/src/__test__/iap.test.js +0 -59
  87. package/src/hooks/useIAP.js +0 -141
  88. package/src/hooks/withIAPContext.js +0 -150
  89. package/src/iap.js +0 -640
  90. package/src/types/amazon.js +0 -1
  91. package/src/types/android.js +0 -22
  92. package/src/types/apple.js +0 -165
  93. package/src/types/index.js +0 -40
  94. package/test/mocks/react-native-modules.js +0 -14
@@ -26,6 +26,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule
26
26
  import com.facebook.react.bridge.ReactMethod
27
27
  import com.facebook.react.bridge.ReadableArray
28
28
  import com.facebook.react.bridge.ReadableType
29
+ import com.facebook.react.bridge.WritableArray
29
30
  import com.facebook.react.bridge.WritableMap
30
31
  import com.facebook.react.bridge.WritableNativeArray
31
32
  import com.facebook.react.bridge.WritableNativeMap
@@ -40,8 +41,7 @@ class RNIapModule(
40
41
  private val googleApiAvailability: GoogleApiAvailability = GoogleApiAvailability.getInstance()
41
42
  ) :
42
43
  ReactContextBaseJavaModule(reactContext),
43
- PurchasesUpdatedListener,
44
- RNIapModuleInterface {
44
+ PurchasesUpdatedListener {
45
45
 
46
46
  private var billingClientCache: BillingClient? = null
47
47
  private val skus: MutableMap<String, ProductDetails> = mutableMapOf()
@@ -49,7 +49,7 @@ class RNIapModule(
49
49
  return TAG
50
50
  }
51
51
 
52
- internal fun ensureConnection(
52
+ fun ensureConnection(
53
53
  promise: Promise,
54
54
  callback: (billingClient: BillingClient) -> Unit
55
55
  ) {
@@ -87,7 +87,7 @@ class RNIapModule(
87
87
  }
88
88
 
89
89
  @ReactMethod
90
- override fun initConnection(promise: Promise) {
90
+ fun initConnection(promise: Promise) {
91
91
  if (googleApiAvailability.isGooglePlayServicesAvailable(reactContext)
92
92
  != ConnectionResult.SUCCESS
93
93
  ) {
@@ -108,13 +108,13 @@ class RNIapModule(
108
108
  billingClientCache = it
109
109
  it.startConnection(
110
110
  object : BillingClientStateListener {
111
- override fun onBillingSetupFinished(billingResult: BillingResult) {
111
+ override fun onBillingSetupFinished(billingResult: BillingResult) {
112
112
  if (!isValidResult(billingResult, promise)) return
113
113
 
114
114
  promise.safeResolve(true)
115
115
  }
116
116
 
117
- override fun onBillingServiceDisconnected() {
117
+ override fun onBillingServiceDisconnected() {
118
118
  Log.i(TAG, "Billing service disconnected")
119
119
  }
120
120
  }
@@ -123,7 +123,7 @@ class RNIapModule(
123
123
  }
124
124
 
125
125
  @ReactMethod
126
- override fun endConnection(promise: Promise) {
126
+ fun endConnection(promise: Promise) {
127
127
  billingClientCache?.endConnection()
128
128
  billingClientCache = null
129
129
  promise.safeResolve(true)
@@ -160,7 +160,7 @@ class RNIapModule(
160
160
  }
161
161
 
162
162
  @ReactMethod
163
- override fun flushFailedPurchasesCachedAsPending(promise: Promise) {
163
+ fun flushFailedPurchasesCachedAsPending(promise: Promise) {
164
164
  ensureConnection(
165
165
  promise
166
166
  ) { billingClient ->
@@ -193,7 +193,7 @@ class RNIapModule(
193
193
  }
194
194
 
195
195
  @ReactMethod
196
- override fun getItemsByType(type: String, skuArr: ReadableArray, promise: Promise) {
196
+ fun getItemsByType(type: String, skuArr: ReadableArray, promise: Promise) {
197
197
  ensureConnection(
198
198
  promise
199
199
  ) { billingClient ->
@@ -201,10 +201,12 @@ class RNIapModule(
201
201
  for (i in 0 until skuArr.size()) {
202
202
  if (skuArr.getType(i) == ReadableType.String) {
203
203
  val sku = skuArr.getString(i)
204
- skuList.add(
205
- QueryProductDetailsParams.Product.newBuilder().setProductId(sku)
206
- .setProductType(type).build()
207
- )
204
+ sku?.let {
205
+ skuList.add(
206
+ QueryProductDetailsParams.Product.newBuilder().setProductId(sku)
207
+ .setProductType(type).build()
208
+ )
209
+ }
208
210
  }
209
211
  }
210
212
  val params = QueryProductDetailsParams.newBuilder().setProductList(skuList)
@@ -304,7 +306,7 @@ class RNIapModule(
304
306
  }
305
307
 
306
308
  @ReactMethod
307
- override fun getAvailableItemsByType(type: String, promise: Promise) {
309
+ fun getAvailableItemsByType(type: String, promise: Promise) {
308
310
  ensureConnection(
309
311
  promise
310
312
  ) { billingClient ->
@@ -319,7 +321,10 @@ class RNIapModule(
319
321
  for (i in purchases.indices) {
320
322
  val purchase = purchases[i]
321
323
  val item = WritableNativeMap()
322
- item.putString("productId", purchase.products[0]) // TODO: should be a list
324
+ item.putString("productId", purchase.products[0])// kept for convenience/backward-compatibility. productIds has the complete list
325
+ val products = Arguments.createArray()
326
+ purchase.products.forEach { products.pushString(it) }
327
+ item.putArray("productIds", products)
323
328
  item.putString("transactionId", purchase.orderId)
324
329
  item.putDouble("transactionDate", purchase.purchaseTime.toDouble())
325
330
  item.putString("transactionReceipt", purchase.originalJson)
@@ -350,7 +355,7 @@ class RNIapModule(
350
355
  }
351
356
 
352
357
  @ReactMethod
353
- override fun getPurchaseHistoryByType(type: String, promise: Promise) {
358
+ fun getPurchaseHistoryByType(type: String, promise: Promise) {
354
359
  ensureConnection(
355
360
  promise
356
361
  ) { billingClient ->
@@ -368,6 +373,9 @@ class RNIapModule(
368
373
  purchaseHistoryRecordList?.forEach { purchase ->
369
374
  val item = Arguments.createMap()
370
375
  item.putString("productId", purchase.products[0])
376
+ val products = Arguments.createArray()
377
+ purchase.products.forEach { products.pushString(it) }
378
+ item.putArray("productIds", products)
371
379
  item.putDouble("transactionDate", purchase.purchaseTime.toDouble())
372
380
  item.putString("transactionReceipt", purchase.originalJson)
373
381
  item.putString("purchaseToken", purchase.purchaseToken)
@@ -382,14 +390,14 @@ class RNIapModule(
382
390
  }
383
391
 
384
392
  @ReactMethod
385
- override fun buyItemByType(
393
+ fun buyItemByType(
386
394
  type: String,
387
- sku: String, // TODO: should this now be an array?
395
+ skuArr: ReadableArray,
388
396
  purchaseToken: String?,
389
- prorationMode: Int?,
397
+ prorationMode: Int,
390
398
  obfuscatedAccountId: String?,
391
399
  obfuscatedProfileId: String?,
392
- selectedOfferIndex: Int?, // New optional parameter in V5, TODO: should it be an array?
400
+ selectedOfferIndexArr: ReadableArray, // New optional parameter in V5
393
401
  promise: Promise
394
402
  ) {
395
403
  val activity = currentActivity
@@ -404,32 +412,36 @@ class RNIapModule(
404
412
  PROMISE_BUY_ITEM,
405
413
  promise
406
414
  )
407
- val builder = BillingFlowParams.newBuilder()
408
- val selectedSku: ProductDetails? = skus[sku]
409
- if (selectedSku == null) {
410
- val debugMessage =
411
- "The sku was not found. Please fetch products first by calling getItems"
412
- val error = Arguments.createMap()
413
- error.putString("debugMessage", debugMessage)
414
- error.putString("code", PROMISE_BUY_ITEM)
415
- error.putString("message", debugMessage)
416
- error.putString("productId", sku)
417
- sendEvent(reactContext, "purchase-error", error)
418
- promise.safeReject(PROMISE_BUY_ITEM, debugMessage)
419
- return@ensureConnection
420
- }
421
- var productParams = BillingFlowParams.ProductDetailsParams.newBuilder().setProductDetails(selectedSku)
422
- if (selectedOfferIndex != null && (
423
- selectedSku.subscriptionOfferDetails?.size
424
- ?: 0
425
- ) > selectedOfferIndex
426
- ) {
427
- val offerToken =
428
- selectedSku.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken
429
- offerToken?.let { productParams = productParams.setOfferToken(offerToken) }
415
+ val productParamsList =
416
+ skuArr.toArrayList().map { it.toString() }.mapIndexed{ index,sku ->
417
+ val selectedSku: ProductDetails? = skus[sku]
418
+ if (selectedSku == null) {
419
+ val debugMessage =
420
+ "The sku was not found. Please fetch products first by calling getItems"
421
+ val error = Arguments.createMap()
422
+ error.putString("debugMessage", debugMessage)
423
+ error.putString("code", PROMISE_BUY_ITEM)
424
+ error.putString("message", debugMessage)
425
+ error.putString("productId", sku)
426
+ sendEvent(reactContext, "purchase-error", error)
427
+ promise.safeReject(PROMISE_BUY_ITEM, debugMessage)
428
+ return@ensureConnection
429
+ }
430
+ var productParams = BillingFlowParams.ProductDetailsParams.newBuilder().setProductDetails(selectedSku)
431
+ val selectedOfferIndex = selectedOfferIndexArr.getInt(index)
432
+ if (selectedOfferIndex > -1 && (
433
+ selectedSku.subscriptionOfferDetails?.size
434
+ ?: 0
435
+ ) > selectedOfferIndex
436
+ ) {
437
+ val offerToken =
438
+ selectedSku.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken
439
+ offerToken?.let { productParams = productParams.setOfferToken(offerToken) }
440
+ }
441
+ productParams.build()
430
442
  }
431
-
432
- builder.setProductDetailsParamsList(listOf(productParams.build()))
443
+ val builder = BillingFlowParams.newBuilder()
444
+ builder.setProductDetailsParamsList(productParamsList)
433
445
  val subscriptionUpdateParamsBuilder = SubscriptionUpdateParams.newBuilder()
434
446
  if (purchaseToken != null) {
435
447
  subscriptionUpdateParamsBuilder.setOldPurchaseToken(purchaseToken)
@@ -440,14 +452,14 @@ class RNIapModule(
440
452
  if (obfuscatedProfileId != null) {
441
453
  builder.setObfuscatedProfileId(obfuscatedProfileId)
442
454
  }
443
- if (prorationMode != null && prorationMode != -1) {
455
+ if (prorationMode != -1) {
444
456
  if (prorationMode
445
457
  == BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE
446
458
  ) {
447
459
  subscriptionUpdateParamsBuilder.setReplaceProrationMode(
448
460
  BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE
449
461
  )
450
- if (type != BillingClient.SkuType.SUBS) {
462
+ if (type != BillingClient.ProductType.SUBS) {
451
463
  val debugMessage =
452
464
  (
453
465
  "IMMEDIATE_AND_CHARGE_PRORATED_PRICE for proration mode only works in" +
@@ -457,7 +469,7 @@ class RNIapModule(
457
469
  error.putString("debugMessage", debugMessage)
458
470
  error.putString("code", PROMISE_BUY_ITEM)
459
471
  error.putString("message", debugMessage)
460
- error.putString("productId", sku)
472
+ error.putArray("productIds", skuArr)
461
473
  sendEvent(reactContext, "purchase-error", error)
462
474
  promise.safeReject(PROMISE_BUY_ITEM, debugMessage)
463
475
  return@ensureConnection
@@ -508,7 +520,7 @@ class RNIapModule(
508
520
  }
509
521
 
510
522
  @ReactMethod
511
- override fun acknowledgePurchase(
523
+ fun acknowledgePurchase(
512
524
  token: String,
513
525
  developerPayLoad: String?,
514
526
  promise: Promise
@@ -538,7 +550,7 @@ class RNIapModule(
538
550
  }
539
551
 
540
552
  @ReactMethod
541
- override fun consumeProduct(
553
+ fun consumeProduct(
542
554
  token: String,
543
555
  developerPayLoad: String?,
544
556
  promise: Promise
@@ -559,6 +571,7 @@ class RNIapModule(
559
571
  .getBillingResponseData(billingResult.responseCode)
560
572
  map.putString("code", errorData[0])
561
573
  map.putString("message", errorData[1])
574
+ map.putString("purchaseToken",purchaseToken)
562
575
  promise.safeResolve(map)
563
576
  }
564
577
  }
@@ -579,11 +592,13 @@ class RNIapModule(
579
592
  return
580
593
  }
581
594
  if (purchases != null) {
582
- var promiseItem: WritableMap? = null
583
- for (i in purchases.indices) {
595
+ val promiseItems: WritableArray = Arguments.createArray()
596
+ purchases.forEach { purchase ->
584
597
  val item = Arguments.createMap()
585
- val purchase = purchases[i]
586
598
  item.putString("productId", purchase.products[0])
599
+ val products = Arguments.createArray()
600
+ purchase.products.forEach { products.pushString(it) }
601
+ item.putArray("productIds", products)
587
602
  item.putString("transactionId", purchase.orderId)
588
603
  item.putDouble("transactionDate", purchase.purchaseTime.toDouble())
589
604
  item.putString("transactionReceipt", purchase.originalJson)
@@ -606,13 +621,10 @@ class RNIapModule(
606
621
  accountIdentifiers.obfuscatedProfileId
607
622
  )
608
623
  }
609
- promiseItem = WritableNativeMap()
610
- promiseItem.merge(item)
624
+ promiseItems.pushMap(item)
611
625
  sendEvent(reactContext, "purchase-updated", item)
612
626
  }
613
- if (promiseItem != null) {
614
- DoobooUtils.instance.resolvePromisesForKey(PROMISE_BUY_ITEM, promiseItem)
615
- }
627
+ DoobooUtils.instance.resolvePromisesForKey(PROMISE_BUY_ITEM, promiseItems)
616
628
  } else {
617
629
  val result = Arguments.createMap()
618
630
  result.putInt("responseCode", billingResult.responseCode)
@@ -649,22 +661,22 @@ class RNIapModule(
649
661
  }
650
662
 
651
663
  @ReactMethod
652
- override fun startListening(promise: Promise) {
664
+ fun startListening(promise: Promise) {
653
665
  sendUnconsumedPurchases(promise)
654
666
  }
655
667
 
656
668
  @ReactMethod
657
- override fun addListener(eventName: String) {
669
+ fun addListener(eventName: String) {
658
670
  // Keep: Required for RN built-in Event Emitter Calls.
659
671
  }
660
672
 
661
673
  @ReactMethod
662
- override fun removeListeners(count: Double) {
674
+ fun removeListeners(count: Double) {
663
675
  // Keep: Required for RN built-in Event Emitter Calls.
664
676
  }
665
677
 
666
678
  @ReactMethod
667
- override fun getPackageName(promise: Promise) = promise.resolve(reactApplicationContext.packageName)
679
+ fun getPackageName(promise: Promise) = promise.resolve(reactApplicationContext.packageName)
668
680
 
669
681
  private fun sendEvent(
670
682
  reactContext: ReactContext,
@@ -687,6 +699,7 @@ class RNIapModule(
687
699
  override fun onHostPause() {}
688
700
  override fun onHostDestroy() {
689
701
  billingClientCache?.endConnection()
702
+ billingClientCache = null
690
703
  }
691
704
  }
692
705
  reactContext.addLifecycleEventListener(lifecycleEventListener)
@@ -15,7 +15,6 @@ class RNIapPackage : ReactPackage {
15
15
  override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
16
16
  val modules: MutableList<NativeModule> = ArrayList()
17
17
  modules.add(RNIapModule(reactContext))
18
- modules.add(RNIapModuleV4(reactContext))
19
18
  return modules
20
19
  }
21
20
  }
@@ -4,8 +4,11 @@ import com.android.billingclient.api.BillingClient
4
4
  import com.android.billingclient.api.BillingClientStateListener
5
5
  import com.android.billingclient.api.BillingResult
6
6
  import com.android.billingclient.api.ConsumeResponseListener
7
+ import com.android.billingclient.api.ProductDetails
8
+ import com.android.billingclient.api.ProductDetailsResponseListener
7
9
  import com.android.billingclient.api.Purchase
8
10
  import com.android.billingclient.api.PurchasesResponseListener
11
+ import com.android.billingclient.api.QueryPurchasesParams
9
12
  import com.android.billingclient.api.SkuDetailsResponseListener
10
13
  import com.facebook.react.bridge.Arguments
11
14
  import com.facebook.react.bridge.Promise
@@ -30,7 +33,7 @@ import org.junit.Assert.assertTrue
30
33
  import org.junit.Before
31
34
  import org.junit.Test
32
35
 
33
- class RNIapModuleTestV4 {
36
+ class RNIapModuleTest {
34
37
 
35
38
  @MockK
36
39
  lateinit var context: ReactApplicationContext
@@ -44,14 +47,14 @@ class RNIapModuleTestV4 {
44
47
  @MockK
45
48
  lateinit var availability: GoogleApiAvailability
46
49
 
47
- private lateinit var module: RNIapModuleV4
50
+ private lateinit var module: RNIapModule
48
51
 
49
52
  @Before
50
53
  fun setUp() {
51
54
  MockKAnnotations.init(this, relaxUnitFun = true)
52
55
  every { builder.setListener(any()) } returns builder
53
56
  every { builder.build() } returns billingClient
54
- module = RNIapModuleV4(context, builder, availability)
57
+ module = RNIapModule(context, builder, availability)
55
58
  }
56
59
 
57
60
  @Test
@@ -134,7 +137,7 @@ class RNIapModuleTestV4 {
134
137
  every { billingClient.isReady } returns true
135
138
  val promise = mockk<Promise>(relaxed = true)
136
139
  val listener = slot<PurchasesResponseListener>()
137
- every { billingClient.queryPurchasesAsync(any<String>(), capture(listener)) } answers {
140
+ every { billingClient.queryPurchasesAsync(any<QueryPurchasesParams>(), capture(listener)) } answers {
138
141
  listener.captured.onQueryPurchasesResponse(BillingResult.newBuilder().build(), listOf())
139
142
  }
140
143
  module.initConnection(mockk())
@@ -150,7 +153,7 @@ class RNIapModuleTestV4 {
150
153
  every { billingClient.isReady } returns true
151
154
  val promise = mockk<Promise>(relaxed = true)
152
155
  val listener = slot<PurchasesResponseListener>()
153
- every { billingClient.queryPurchasesAsync(any<String>(), capture(listener)) } answers {
156
+ every { billingClient.queryPurchasesAsync(any<QueryPurchasesParams>(), capture(listener)) } answers {
154
157
  listener.captured.onQueryPurchasesResponse(
155
158
  BillingResult.newBuilder().build(),
156
159
  listOf(
@@ -207,30 +210,39 @@ class RNIapModuleTestV4 {
207
210
  every { availability.isGooglePlayServicesAvailable(any()) } returns ConnectionResult.SUCCESS
208
211
  every { billingClient.isReady } returns true
209
212
  val promise = mockk<Promise>(relaxed = true)
210
- val listener = slot<SkuDetailsResponseListener>()
211
- every { billingClient.querySkuDetailsAsync(any(), capture(listener)) } answers {
212
- listener.captured.onSkuDetailsResponse(
213
+ val listener = slot<ProductDetailsResponseListener>()
214
+ every { billingClient.queryProductDetailsAsync(any(), capture(listener)) } answers {
215
+ listener.captured.onProductDetailsResponse(
213
216
  BillingResult.newBuilder().build(),
214
217
  listOf(
215
218
  mockk {
216
- every { sku } returns "sku1"
217
- every { introductoryPriceAmountMicros } returns 0
218
- every { priceAmountMicros } returns 1
219
- every { priceCurrencyCode } returns "USD"
220
- every { type } returns "sub"
221
- every { price } returns "$10.0"
222
- every { title } returns "My product"
223
- every { description } returns "My desc"
224
- every { introductoryPrice } returns "$5.0"
225
- every { zzc() } returns "com.mypackage"
226
- every { originalPrice } returns "$13.0"
227
- every { subscriptionPeriod } returns "3 months"
228
- every { freeTrialPeriod } returns "1 week"
229
- every { introductoryPriceCycles } returns 1
230
- every { introductoryPricePeriod } returns "1"
231
- every { iconUrl } returns "http://myicon.com/icon"
232
- every { originalJson } returns "{}"
233
- every { originalPriceAmountMicros } returns 2
219
+ every { productId } returns "sku1"
220
+
221
+ every { title } returns "title2"
222
+ every { description } returns "My product"
223
+
224
+ every { productType } returns "sub"
225
+ every { name } returns "name of product"
226
+ every { oneTimePurchaseOfferDetails } returns mockk {
227
+ every { priceCurrencyCode} returns "my code"
228
+ every {formattedPrice} returns "$20.00"
229
+ every { priceAmountMicros } returns 20000
230
+
231
+ }
232
+ every { subscriptionOfferDetails } returns listOf( mockk {
233
+ every { offerToken } returns "sToken"
234
+ every { offerTags } returns listOf("offerTag1","offerTag2")
235
+ every { pricingPhases} returns mockk{
236
+ every { pricingPhaseList } returns listOf(mockk{
237
+ every { formattedPrice } returns "$13.0"
238
+ every { priceCurrencyCode } returns "USD"
239
+ every { billingPeriod } returns "1 week"
240
+ every { billingCycleCount } returns 1
241
+ every { priceAmountMicros } returns 13000
242
+ every { recurrenceMode } returns 2
243
+ })
244
+ }
245
+ })
234
246
  }
235
247
  )
236
248
  )
@@ -242,19 +254,21 @@ class RNIapModuleTestV4 {
242
254
  }
243
255
  mockkStatic(Arguments::class)
244
256
 
245
- val itemsMap = mockk<WritableMap>()
246
- val itemsArr = mockk<WritableArray>()
247
- every { Arguments.createMap() } returns itemsMap
248
- every { Arguments.createArray() } returns itemsArr
249
- every { itemsMap.putString(any(), any()) } just runs
257
+ val itemsMap = mockk<WritableMap>(relaxed = true)
250
258
  var itemsSize = 0
251
- every { itemsArr.pushMap(any()) } answers {
252
- itemsSize++
259
+ val itemsArr = mockk<WritableArray>{
260
+ every { pushString(any()) } just runs
261
+ every { pushMap(any()) } answers {
262
+ itemsSize++
263
+ }
253
264
  }
265
+ every { Arguments.createMap() } returns itemsMap
266
+ every { Arguments.createArray() } returns itemsArr
267
+
254
268
  module.initConnection(mockk())
255
269
  module.getItemsByType("subs", skus, promise)
256
270
  verify { promise.resolve(any()) }
257
- assertEquals(itemsSize, 1)
271
+ assertEquals(3, itemsSize)
258
272
  }
259
273
 
260
274
  @Test
@@ -0,0 +1,2 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTViewManager.h>
package/ios/RNIapIos.m CHANGED
@@ -3,23 +3,28 @@
3
3
  #import <React/RCTBridgeModule.h>
4
4
 
5
5
  @interface RCT_EXTERN_MODULE (RNIapIos, NSObject)
6
+
6
7
  RCT_EXTERN_METHOD(initConnection:
7
8
  (RCTPromiseResolveBlock)resolve
8
9
  reject:(RCTPromiseRejectBlock)reject)
10
+
9
11
  RCT_EXTERN_METHOD(endConnection:
10
12
  (RCTPromiseResolveBlock)resolve
11
13
  reject:(RCTPromiseRejectBlock)reject)
14
+
12
15
  RCT_EXTERN_METHOD(getItems:
13
16
  (NSArray*)skus
14
17
  resolve:(RCTPromiseResolveBlock)resolve
15
18
  reject:(RCTPromiseRejectBlock)reject)
19
+
16
20
  RCT_EXTERN_METHOD(getAvailableItems:
17
21
  (RCTPromiseResolveBlock)resolve
18
22
  reject:(RCTPromiseRejectBlock)reject)
23
+
19
24
  RCT_EXTERN_METHOD(buyProduct:
20
25
  (NSString*)sku
21
- appAccountToken:(NSString*)appAccountToken
22
26
  andDangerouslyFinishTransactionAutomatically:(BOOL)andDangerouslyFinishTransactionAutomatically
27
+ applicationUsername:(NSString*)applicationUsername
23
28
  resolve:(RCTPromiseResolveBlock)resolve
24
29
  reject:(RCTPromiseRejectBlock)reject)
25
30
  RCT_EXTERN_METHOD(buyProductWithOffer:
@@ -33,17 +38,22 @@ RCT_EXTERN_METHOD(buyProductWithQuantityIOS:
33
38
  quantity:(NSInteger)quantity
34
39
  resolve:(RCTPromiseResolveBlock)resolve
35
40
  reject:(RCTPromiseRejectBlock)reject)
41
+
36
42
  RCT_EXTERN_METHOD(clearTransaction:
37
43
  (RCTPromiseResolveBlock)resolve
38
44
  reject:(RCTPromiseRejectBlock)reject)
45
+
39
46
  RCT_EXTERN_METHOD(clearProducts:
40
47
  (RCTPromiseResolveBlock)resolve
41
48
  reject:(RCTPromiseRejectBlock)reject)
49
+
42
50
  RCT_EXTERN_METHOD(promotedProduct:
43
51
  (RCTPromiseResolveBlock)resolve
44
52
  reject:(RCTPromiseRejectBlock)reject)
53
+
45
54
  RCT_EXTERN_METHOD(buyPromotedProduct:(RCTPromiseResolveBlock)resolve
46
55
  reject:(RCTPromiseRejectBlock)reject)
56
+
47
57
  RCT_EXTERN_METHOD(requestReceipt:
48
58
  (BOOL)refresh
49
59
  resolve:(RCTPromiseResolveBlock)resolve
@@ -52,10 +62,13 @@ RCT_EXTERN_METHOD(finishTransaction:
52
62
  (NSString*)transactionIdentifier
53
63
  resolve:(RCTPromiseResolveBlock)resolve
54
64
  reject:(RCTPromiseRejectBlock)reject)
65
+
55
66
  RCT_EXTERN_METHOD(getPendingTransactions:
56
67
  (RCTPromiseResolveBlock)resolve
57
68
  reject:(RCTPromiseRejectBlock)reject)
69
+
58
70
  RCT_EXTERN_METHOD(presentCodeRedemptionSheet:
59
71
  (RCTPromiseResolveBlock)resolve
60
72
  reject:(RCTPromiseRejectBlock)reject)
73
+
61
74
  @end