react-native-iap 9.0.0-beta → 9.0.0-beta12

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 +99 -89
  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} +47 -35
  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 +586 -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 +494 -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 +17 -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 +35 -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 +700 -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 +185 -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 ->
@@ -315,42 +317,42 @@ class RNIapModule(
315
317
  ).build()
316
318
  ) { billingResult: BillingResult, purchases: List<Purchase>? ->
317
319
  if (!isValidResult(billingResult, promise)) return@queryPurchasesAsync
318
- if (purchases != null) {
319
- for (i in purchases.indices) {
320
- val purchase = purchases[i]
321
- val item = WritableNativeMap()
322
- item.putString("productId", purchase.products[0]) // TODO: should be a list
323
- item.putString("transactionId", purchase.orderId)
324
- item.putDouble("transactionDate", purchase.purchaseTime.toDouble())
325
- item.putString("transactionReceipt", purchase.originalJson)
326
- item.putString("orderId", purchase.orderId)
327
- item.putString("purchaseToken", purchase.purchaseToken)
328
- item.putString("developerPayloadAndroid", purchase.developerPayload)
329
- item.putString("signatureAndroid", purchase.signature)
330
- item.putInt("purchaseStateAndroid", purchase.purchaseState)
331
- item.putBoolean("isAcknowledgedAndroid", purchase.isAcknowledged)
332
- item.putString("packageNameAndroid", purchase.packageName)
333
- item.putString(
334
- "obfuscatedAccountIdAndroid",
335
- purchase.accountIdentifiers?.obfuscatedAccountId
336
- )
337
- item.putString(
338
- "obfuscatedProfileIdAndroid",
339
- purchase.accountIdentifiers?.obfuscatedProfileId
340
- )
341
- if (type == BillingClient.ProductType.SUBS) {
342
- item.putBoolean("autoRenewingAndroid", purchase.isAutoRenewing)
343
- }
344
- items.pushMap(item)
320
+ purchases?.forEach { purchase ->
321
+ val item = WritableNativeMap()
322
+ item.putString("productId", purchase.products[0])// kept for convenience/backward-compatibility. productIds has the complete list
323
+ val products = Arguments.createArray()
324
+ purchase.products.forEach { products.pushString(it) }
325
+ item.putArray("productIds", products)
326
+ item.putString("transactionId", purchase.orderId)
327
+ item.putDouble("transactionDate", purchase.purchaseTime.toDouble())
328
+ item.putString("transactionReceipt", purchase.originalJson)
329
+ item.putString("orderId", purchase.orderId)
330
+ item.putString("purchaseToken", purchase.purchaseToken)
331
+ item.putString("developerPayloadAndroid", purchase.developerPayload)
332
+ item.putString("signatureAndroid", purchase.signature)
333
+ item.putInt("purchaseStateAndroid", purchase.purchaseState)
334
+ item.putBoolean("isAcknowledgedAndroid", purchase.isAcknowledged)
335
+ item.putString("packageNameAndroid", purchase.packageName)
336
+ item.putString(
337
+ "obfuscatedAccountIdAndroid",
338
+ purchase.accountIdentifiers?.obfuscatedAccountId
339
+ )
340
+ item.putString(
341
+ "obfuscatedProfileIdAndroid",
342
+ purchase.accountIdentifiers?.obfuscatedProfileId
343
+ )
344
+ if (type == BillingClient.ProductType.SUBS) {
345
+ item.putBoolean("autoRenewingAndroid", purchase.isAutoRenewing)
346
+ }
347
+ items.pushMap(item)
345
348
  }
346
- }
347
349
  promise.safeResolve(items)
348
350
  }
349
351
  }
350
352
  }
351
353
 
352
354
  @ReactMethod
353
- override fun getPurchaseHistoryByType(type: String, promise: Promise) {
355
+ fun getPurchaseHistoryByType(type: String, promise: Promise) {
354
356
  ensureConnection(
355
357
  promise
356
358
  ) { billingClient ->
@@ -368,6 +370,9 @@ class RNIapModule(
368
370
  purchaseHistoryRecordList?.forEach { purchase ->
369
371
  val item = Arguments.createMap()
370
372
  item.putString("productId", purchase.products[0])
373
+ val products = Arguments.createArray()
374
+ purchase.products.forEach { products.pushString(it) }
375
+ item.putArray("productIds", products)
371
376
  item.putDouble("transactionDate", purchase.purchaseTime.toDouble())
372
377
  item.putString("transactionReceipt", purchase.originalJson)
373
378
  item.putString("purchaseToken", purchase.purchaseToken)
@@ -382,14 +387,14 @@ class RNIapModule(
382
387
  }
383
388
 
384
389
  @ReactMethod
385
- override fun buyItemByType(
390
+ fun buyItemByType(
386
391
  type: String,
387
- sku: String, // TODO: should this now be an array?
392
+ skuArr: ReadableArray,
388
393
  purchaseToken: String?,
389
- prorationMode: Int?,
394
+ prorationMode: Int,
390
395
  obfuscatedAccountId: String?,
391
396
  obfuscatedProfileId: String?,
392
- selectedOfferIndex: Int?, // New optional parameter in V5, TODO: should it be an array?
397
+ selectedOfferIndices: ReadableArray, // New optional parameter in V5
393
398
  promise: Promise
394
399
  ) {
395
400
  val activity = currentActivity
@@ -404,32 +409,36 @@ class RNIapModule(
404
409
  PROMISE_BUY_ITEM,
405
410
  promise
406
411
  )
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) }
412
+ val productParamsList =
413
+ skuArr.toArrayList().map { it.toString() }.mapIndexed{ index,sku ->
414
+ val selectedSku: ProductDetails? = skus[sku]
415
+ if (selectedSku == null) {
416
+ val debugMessage =
417
+ "The sku was not found. Please fetch products first by calling getItems"
418
+ val error = Arguments.createMap()
419
+ error.putString("debugMessage", debugMessage)
420
+ error.putString("code", PROMISE_BUY_ITEM)
421
+ error.putString("message", debugMessage)
422
+ error.putString("productId", sku)
423
+ sendEvent(reactContext, "purchase-error", error)
424
+ promise.safeReject(PROMISE_BUY_ITEM, debugMessage)
425
+ return@ensureConnection
426
+ }
427
+ var productParams = BillingFlowParams.ProductDetailsParams.newBuilder().setProductDetails(selectedSku)
428
+ val selectedOfferIndex = selectedOfferIndices.getInt(index)
429
+ if (selectedOfferIndex > -1 && (
430
+ selectedSku.subscriptionOfferDetails?.size
431
+ ?: 0
432
+ ) > selectedOfferIndex
433
+ ) {
434
+ val offerToken =
435
+ selectedSku.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken
436
+ offerToken?.let { productParams = productParams.setOfferToken(offerToken) }
437
+ }
438
+ productParams.build()
430
439
  }
431
-
432
- builder.setProductDetailsParamsList(listOf(productParams.build()))
440
+ val builder = BillingFlowParams.newBuilder()
441
+ builder.setProductDetailsParamsList(productParamsList)
433
442
  val subscriptionUpdateParamsBuilder = SubscriptionUpdateParams.newBuilder()
434
443
  if (purchaseToken != null) {
435
444
  subscriptionUpdateParamsBuilder.setOldPurchaseToken(purchaseToken)
@@ -440,14 +449,14 @@ class RNIapModule(
440
449
  if (obfuscatedProfileId != null) {
441
450
  builder.setObfuscatedProfileId(obfuscatedProfileId)
442
451
  }
443
- if (prorationMode != null && prorationMode != -1) {
452
+ if (prorationMode != -1) {
444
453
  if (prorationMode
445
454
  == BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE
446
455
  ) {
447
456
  subscriptionUpdateParamsBuilder.setReplaceProrationMode(
448
457
  BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE
449
458
  )
450
- if (type != BillingClient.SkuType.SUBS) {
459
+ if (type != BillingClient.ProductType.SUBS) {
451
460
  val debugMessage =
452
461
  (
453
462
  "IMMEDIATE_AND_CHARGE_PRORATED_PRICE for proration mode only works in" +
@@ -457,7 +466,7 @@ class RNIapModule(
457
466
  error.putString("debugMessage", debugMessage)
458
467
  error.putString("code", PROMISE_BUY_ITEM)
459
468
  error.putString("message", debugMessage)
460
- error.putString("productId", sku)
469
+ error.putArray("productIds", skuArr)
461
470
  sendEvent(reactContext, "purchase-error", error)
462
471
  promise.safeReject(PROMISE_BUY_ITEM, debugMessage)
463
472
  return@ensureConnection
@@ -508,7 +517,7 @@ class RNIapModule(
508
517
  }
509
518
 
510
519
  @ReactMethod
511
- override fun acknowledgePurchase(
520
+ fun acknowledgePurchase(
512
521
  token: String,
513
522
  developerPayLoad: String?,
514
523
  promise: Promise
@@ -538,7 +547,7 @@ class RNIapModule(
538
547
  }
539
548
 
540
549
  @ReactMethod
541
- override fun consumeProduct(
550
+ fun consumeProduct(
542
551
  token: String,
543
552
  developerPayLoad: String?,
544
553
  promise: Promise
@@ -559,6 +568,7 @@ class RNIapModule(
559
568
  .getBillingResponseData(billingResult.responseCode)
560
569
  map.putString("code", errorData[0])
561
570
  map.putString("message", errorData[1])
571
+ map.putString("purchaseToken",purchaseToken)
562
572
  promise.safeResolve(map)
563
573
  }
564
574
  }
@@ -579,11 +589,13 @@ class RNIapModule(
579
589
  return
580
590
  }
581
591
  if (purchases != null) {
582
- var promiseItem: WritableMap? = null
583
- for (i in purchases.indices) {
592
+ val promiseItems: WritableArray = Arguments.createArray()
593
+ purchases.forEach { purchase ->
584
594
  val item = Arguments.createMap()
585
- val purchase = purchases[i]
586
595
  item.putString("productId", purchase.products[0])
596
+ val products = Arguments.createArray()
597
+ purchase.products.forEach { products.pushString(it) }
598
+ item.putArray("productIds", products)
587
599
  item.putString("transactionId", purchase.orderId)
588
600
  item.putDouble("transactionDate", purchase.purchaseTime.toDouble())
589
601
  item.putString("transactionReceipt", purchase.originalJson)
@@ -606,13 +618,10 @@ class RNIapModule(
606
618
  accountIdentifiers.obfuscatedProfileId
607
619
  )
608
620
  }
609
- promiseItem = WritableNativeMap()
610
- promiseItem.merge(item)
621
+ promiseItems.pushMap(item)
611
622
  sendEvent(reactContext, "purchase-updated", item)
612
623
  }
613
- if (promiseItem != null) {
614
- DoobooUtils.instance.resolvePromisesForKey(PROMISE_BUY_ITEM, promiseItem)
615
- }
624
+ DoobooUtils.instance.resolvePromisesForKey(PROMISE_BUY_ITEM, promiseItems)
616
625
  } else {
617
626
  val result = Arguments.createMap()
618
627
  result.putInt("responseCode", billingResult.responseCode)
@@ -649,22 +658,22 @@ class RNIapModule(
649
658
  }
650
659
 
651
660
  @ReactMethod
652
- override fun startListening(promise: Promise) {
661
+ fun startListening(promise: Promise) {
653
662
  sendUnconsumedPurchases(promise)
654
663
  }
655
664
 
656
665
  @ReactMethod
657
- override fun addListener(eventName: String) {
666
+ fun addListener(eventName: String) {
658
667
  // Keep: Required for RN built-in Event Emitter Calls.
659
668
  }
660
669
 
661
670
  @ReactMethod
662
- override fun removeListeners(count: Double) {
671
+ fun removeListeners(count: Double) {
663
672
  // Keep: Required for RN built-in Event Emitter Calls.
664
673
  }
665
674
 
666
675
  @ReactMethod
667
- override fun getPackageName(promise: Promise) = promise.resolve(reactApplicationContext.packageName)
676
+ fun getPackageName(promise: Promise) = promise.resolve(reactApplicationContext.packageName)
668
677
 
669
678
  private fun sendEvent(
670
679
  reactContext: ReactContext,
@@ -687,6 +696,7 @@ class RNIapModule(
687
696
  override fun onHostPause() {}
688
697
  override fun onHostDestroy() {
689
698
  billingClientCache?.endConnection()
699
+ billingClientCache = null
690
700
  }
691
701
  }
692
702
  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,9 +4,10 @@ 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.ProductDetailsResponseListener
7
8
  import com.android.billingclient.api.Purchase
8
9
  import com.android.billingclient.api.PurchasesResponseListener
9
- import com.android.billingclient.api.SkuDetailsResponseListener
10
+ import com.android.billingclient.api.QueryPurchasesParams
10
11
  import com.facebook.react.bridge.Arguments
11
12
  import com.facebook.react.bridge.Promise
12
13
  import com.facebook.react.bridge.ReactApplicationContext
@@ -30,7 +31,7 @@ import org.junit.Assert.assertTrue
30
31
  import org.junit.Before
31
32
  import org.junit.Test
32
33
 
33
- class RNIapModuleTestV4 {
34
+ class RNIapModuleTest {
34
35
 
35
36
  @MockK
36
37
  lateinit var context: ReactApplicationContext
@@ -44,14 +45,14 @@ class RNIapModuleTestV4 {
44
45
  @MockK
45
46
  lateinit var availability: GoogleApiAvailability
46
47
 
47
- private lateinit var module: RNIapModuleV4
48
+ private lateinit var module: RNIapModule
48
49
 
49
50
  @Before
50
51
  fun setUp() {
51
52
  MockKAnnotations.init(this, relaxUnitFun = true)
52
53
  every { builder.setListener(any()) } returns builder
53
54
  every { builder.build() } returns billingClient
54
- module = RNIapModuleV4(context, builder, availability)
55
+ module = RNIapModule(context, builder, availability)
55
56
  }
56
57
 
57
58
  @Test
@@ -134,7 +135,7 @@ class RNIapModuleTestV4 {
134
135
  every { billingClient.isReady } returns true
135
136
  val promise = mockk<Promise>(relaxed = true)
136
137
  val listener = slot<PurchasesResponseListener>()
137
- every { billingClient.queryPurchasesAsync(any<String>(), capture(listener)) } answers {
138
+ every { billingClient.queryPurchasesAsync(any<QueryPurchasesParams>(), capture(listener)) } answers {
138
139
  listener.captured.onQueryPurchasesResponse(BillingResult.newBuilder().build(), listOf())
139
140
  }
140
141
  module.initConnection(mockk())
@@ -150,7 +151,7 @@ class RNIapModuleTestV4 {
150
151
  every { billingClient.isReady } returns true
151
152
  val promise = mockk<Promise>(relaxed = true)
152
153
  val listener = slot<PurchasesResponseListener>()
153
- every { billingClient.queryPurchasesAsync(any<String>(), capture(listener)) } answers {
154
+ every { billingClient.queryPurchasesAsync(any<QueryPurchasesParams>(), capture(listener)) } answers {
154
155
  listener.captured.onQueryPurchasesResponse(
155
156
  BillingResult.newBuilder().build(),
156
157
  listOf(
@@ -207,30 +208,39 @@ class RNIapModuleTestV4 {
207
208
  every { availability.isGooglePlayServicesAvailable(any()) } returns ConnectionResult.SUCCESS
208
209
  every { billingClient.isReady } returns true
209
210
  val promise = mockk<Promise>(relaxed = true)
210
- val listener = slot<SkuDetailsResponseListener>()
211
- every { billingClient.querySkuDetailsAsync(any(), capture(listener)) } answers {
212
- listener.captured.onSkuDetailsResponse(
211
+ val listener = slot<ProductDetailsResponseListener>()
212
+ every { billingClient.queryProductDetailsAsync(any(), capture(listener)) } answers {
213
+ listener.captured.onProductDetailsResponse(
213
214
  BillingResult.newBuilder().build(),
214
215
  listOf(
215
216
  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
217
+ every { productId } returns "sku1"
218
+
219
+ every { title } returns "title2"
220
+ every { description } returns "My product"
221
+
222
+ every { productType } returns "sub"
223
+ every { name } returns "name of product"
224
+ every { oneTimePurchaseOfferDetails } returns mockk {
225
+ every { priceCurrencyCode} returns "my code"
226
+ every {formattedPrice} returns "$20.00"
227
+ every { priceAmountMicros } returns 20000
228
+
229
+ }
230
+ every { subscriptionOfferDetails } returns listOf( mockk {
231
+ every { offerToken } returns "sToken"
232
+ every { offerTags } returns listOf("offerTag1","offerTag2")
233
+ every { pricingPhases} returns mockk{
234
+ every { pricingPhaseList } returns listOf(mockk{
235
+ every { formattedPrice } returns "$13.0"
236
+ every { priceCurrencyCode } returns "USD"
237
+ every { billingPeriod } returns "1 week"
238
+ every { billingCycleCount } returns 1
239
+ every { priceAmountMicros } returns 13000
240
+ every { recurrenceMode } returns 2
241
+ })
242
+ }
243
+ })
234
244
  }
235
245
  )
236
246
  )
@@ -242,19 +252,21 @@ class RNIapModuleTestV4 {
242
252
  }
243
253
  mockkStatic(Arguments::class)
244
254
 
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
255
+ val itemsMap = mockk<WritableMap>(relaxed = true)
250
256
  var itemsSize = 0
251
- every { itemsArr.pushMap(any()) } answers {
252
- itemsSize++
257
+ val itemsArr = mockk<WritableArray>{
258
+ every { pushString(any()) } just runs
259
+ every { pushMap(any()) } answers {
260
+ itemsSize++
261
+ }
253
262
  }
263
+ every { Arguments.createMap() } returns itemsMap
264
+ every { Arguments.createArray() } returns itemsArr
265
+
254
266
  module.initConnection(mockk())
255
267
  module.getItemsByType("subs", skus, promise)
256
268
  verify { promise.resolve(any()) }
257
- assertEquals(itemsSize, 1)
269
+ assertEquals(3, itemsSize)
258
270
  }
259
271
 
260
272
  @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