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.
- package/README.md +4 -6
- package/android/gradle.properties +1 -1
- package/android/src/amazon/java/com/dooboolab/rniap/PurchasingServiceProxy.kt +2 -8
- package/android/src/amazon/java/com/dooboolab/rniap/PurchasingServiceProxyAmazonImpl.kt +18 -12
- package/android/src/amazon/java/com/dooboolab/rniap/RNIapAmazonListener.kt +2 -4
- package/android/src/amazon/java/com/dooboolab/rniap/RNIapAmazonModule.kt +29 -45
- package/android/src/amazon/java/com/dooboolab/rniap/RNIapPackage.kt +4 -1
- package/android/src/main/java/com/dooboolab/rniap/PromiseUtils.kt +2 -9
- package/android/src/main/java/com/dooboolab/rniap/PromiseUtlis.kt +6 -15
- package/android/src/play/java/com/dooboolab/rniap/PlayUtils.kt +70 -86
- package/android/src/play/java/com/dooboolab/rniap/RNIapModule.kt +209 -196
- package/android/src/play/java/com/dooboolab/rniap/RNIapPackage.kt +4 -1
- package/android/src/testAmazon/java/com/dooboolab/rniap/RNIapAmazonModuleTest.kt +19 -23
- package/lib/commonjs/eventEmitter.js.map +1 -1
- package/lib/commonjs/modules/iosSk2.js.map +1 -1
- package/lib/module/eventEmitter.js.map +1 -1
- package/lib/module/modules/iosSk2.js.map +1 -1
- package/lib/typescript/plugin/src/withIAP.d.ts +1 -1
- package/lib/typescript/plugin/src/withIAP.d.ts.map +1 -1
- package/lib/typescript/src/eventEmitter.d.ts.map +1 -1
- package/lib/typescript/src/modules/iosSk2.d.ts.map +1 -1
- package/package.json +8 -8
- package/plugin/build/withIAP.d.ts +1 -1
- package/plugin/build/withIAP.js +7 -7
- package/src/eventEmitter.ts +7 -1
- 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
|
-
) :
|
|
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
|
-
|
|
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
|
-
|
|
61
|
-
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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.
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
.
|
|
214
|
-
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
-
.
|
|
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
|
-
|
|
264
|
-
|
|
265
|
-
|
|
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
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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
|
-
|
|
370
|
-
|
|
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
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
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
|
-
|
|
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
|
-
|
|
559
|
-
|
|
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
|
-
|
|
678
|
-
|
|
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
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
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
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
every {
|
|
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
|
-
|
|
109
|
-
|
|
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":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,IAAAC,QAAA,GAAAD,OAAA;AACA,IAAAE,IAAA,GAAAF,OAAA;AACA,IAAAG,SAAA,GAAAH,OAAA;
|
|
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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"}
|