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.
- package/README.md +11 -22
- package/RNIap.podspec +33 -18
- package/android/build.gradle +137 -38
- package/android/gradle.properties +8 -0
- package/android/src/play/java/com/dooboolab/RNIap/RNIapModule.kt +75 -62
- package/android/src/play/java/com/dooboolab/RNIap/RNIapPackage.kt +0 -1
- package/android/src/testPlay/java/com/dooboolab/RNIap/{RNIapModuleTestV4.kt → RNIapModuleTest.kt} +48 -34
- package/ios/RNIapIos-Bridging-Header.h +2 -0
- package/ios/RNIapIos.m +14 -1
- package/ios/RNIapIos.swift +903 -883
- package/ios/{RNIap.xcodeproj → RNIapIos.xcodeproj}/project.pbxproj +29 -116
- package/lib/commonjs/__test__/iap.test.js +21 -0
- package/lib/commonjs/__test__/iap.test.js.map +1 -0
- package/lib/commonjs/hooks/useIAP.js +78 -0
- package/lib/commonjs/hooks/useIAP.js.map +1 -0
- package/lib/commonjs/hooks/withIAPContext.js +92 -0
- package/lib/commonjs/hooks/withIAPContext.js.map +1 -0
- package/lib/commonjs/iap.js +585 -0
- package/lib/commonjs/iap.js.map +1 -0
- package/lib/commonjs/index.js +59 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types/amazon.js +2 -0
- package/lib/commonjs/types/amazon.js.map +1 -0
- package/lib/commonjs/types/android.js +55 -0
- package/lib/commonjs/types/android.js.map +1 -0
- package/lib/commonjs/types/apple.js +165 -0
- package/lib/commonjs/types/apple.js.map +1 -0
- package/lib/commonjs/types/index.js +59 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/module/__test__/iap.test.js +17 -0
- package/lib/module/__test__/iap.test.js.map +1 -0
- package/lib/module/hooks/useIAP.js +68 -0
- package/lib/module/hooks/useIAP.js.map +1 -0
- package/lib/module/hooks/withIAPContext.js +76 -0
- package/lib/module/hooks/withIAPContext.js.map +1 -0
- package/lib/module/iap.js +493 -0
- package/lib/module/iap.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types/amazon.js +2 -0
- package/lib/module/types/amazon.js.map +1 -0
- package/lib/module/types/android.js +44 -0
- package/lib/module/types/android.js.map +1 -0
- package/lib/module/types/apple.js +153 -0
- package/lib/module/types/apple.js.map +1 -0
- package/lib/module/types/index.js +48 -0
- package/lib/module/types/index.js.map +1 -0
- package/{src → lib/typescript}/__test__/iap.test.d.ts +0 -0
- package/{src → lib/typescript}/hooks/useIAP.d.ts +1 -1
- package/{src → lib/typescript}/hooks/withIAPContext.d.ts +1 -1
- package/{src → lib/typescript}/iap.d.ts +16 -12
- package/{src → lib/typescript}/index.d.ts +2 -1
- package/{src → lib/typescript}/types/amazon.d.ts +0 -0
- package/{src → lib/typescript}/types/android.d.ts +0 -0
- package/{src → lib/typescript}/types/apple.d.ts +0 -0
- package/{src → lib/typescript}/types/index.d.ts +53 -22
- package/package.json +87 -57
- package/src/__test__/iap.test.ts +20 -0
- package/src/hooks/useIAP.ts +130 -0
- package/src/hooks/withIAPContext.tsx +160 -0
- package/src/iap.ts +699 -0
- package/src/{index.js → index.ts} +4 -1
- package/src/types/amazon.ts +23 -0
- package/src/types/android.ts +51 -0
- package/src/types/apple.ts +467 -0
- package/src/types/index.ts +209 -0
- package/.editorconfig +0 -10
- package/.flowconfig +0 -11
- package/.monolinterrc +0 -3
- package/.yarn/install-state.gz +0 -0
- package/.yarn/releases/yarn-3.2.0.cjs +0 -785
- package/.yarnrc.yml +0 -3
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +0 -6
- package/android/gradlew +0 -160
- package/android/gradlew.bat +0 -90
- package/android/src/play/java/com/dooboolab/RNIap/RNIapModuleInterface.kt +0 -44
- package/android/src/play/java/com/dooboolab/RNIap/RNIapModuleV4.kt +0 -656
- package/babel.config.js +0 -10
- package/index.d.ts +0 -3
- package/index.js +0 -3
- package/index.js.flow +0 -9
- package/ios/RNIap.xcodeproj/xcshareddata/xcschemes/RNIap.xcscheme +0 -80
- package/ios/RNIapQueue.swift +0 -36
- package/jest.config.js +0 -194
- package/src/__test__/iap.test.js +0 -59
- package/src/hooks/useIAP.js +0 -141
- package/src/hooks/withIAPContext.js +0 -150
- package/src/iap.js +0 -640
- package/src/types/amazon.js +0 -1
- package/src/types/android.js +0 -22
- package/src/types/apple.js +0 -165
- package/src/types/index.js +0 -40
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
.
|
|
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
|
-
|
|
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])
|
|
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
|
-
|
|
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
|
-
|
|
393
|
+
fun buyItemByType(
|
|
386
394
|
type: String,
|
|
387
|
-
|
|
395
|
+
skuArr: ReadableArray,
|
|
388
396
|
purchaseToken: String?,
|
|
389
|
-
prorationMode: Int
|
|
397
|
+
prorationMode: Int,
|
|
390
398
|
obfuscatedAccountId: String?,
|
|
391
399
|
obfuscatedProfileId: String?,
|
|
392
|
-
|
|
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
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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(
|
|
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 !=
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
583
|
-
|
|
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
|
-
|
|
610
|
-
promiseItem.merge(item)
|
|
624
|
+
promiseItems.pushMap(item)
|
|
611
625
|
sendEvent(reactContext, "purchase-updated", item)
|
|
612
626
|
}
|
|
613
|
-
|
|
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
|
-
|
|
664
|
+
fun startListening(promise: Promise) {
|
|
653
665
|
sendUnconsumedPurchases(promise)
|
|
654
666
|
}
|
|
655
667
|
|
|
656
668
|
@ReactMethod
|
|
657
|
-
|
|
669
|
+
fun addListener(eventName: String) {
|
|
658
670
|
// Keep: Required for RN built-in Event Emitter Calls.
|
|
659
671
|
}
|
|
660
672
|
|
|
661
673
|
@ReactMethod
|
|
662
|
-
|
|
674
|
+
fun removeListeners(count: Double) {
|
|
663
675
|
// Keep: Required for RN built-in Event Emitter Calls.
|
|
664
676
|
}
|
|
665
677
|
|
|
666
678
|
@ReactMethod
|
|
667
|
-
|
|
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
|
}
|
package/android/src/testPlay/java/com/dooboolab/RNIap/{RNIapModuleTestV4.kt → RNIapModuleTest.kt}
RENAMED
|
@@ -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
|
|
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:
|
|
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 =
|
|
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<
|
|
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<
|
|
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<
|
|
211
|
-
every { billingClient.
|
|
212
|
-
listener.captured.
|
|
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 {
|
|
217
|
-
|
|
218
|
-
every {
|
|
219
|
-
every {
|
|
220
|
-
|
|
221
|
-
every {
|
|
222
|
-
every {
|
|
223
|
-
every {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
every {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
|
|
252
|
-
|
|
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(
|
|
271
|
+
assertEquals(3, itemsSize)
|
|
258
272
|
}
|
|
259
273
|
|
|
260
274
|
@Test
|
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
|