react-native-iap 12.4.13 → 12.5.0
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/android/src/amazon/java/com/dooboolab/RNIap/EventSender.kt +10 -0
- package/android/src/amazon/java/com/dooboolab/RNIap/RNIapActivityListener.kt +33 -0
- package/android/src/amazon/java/com/dooboolab/RNIap/RNIapAmazonListener.kt +11 -23
- package/android/src/amazon/java/com/dooboolab/RNIap/RNIapAmazonModule.kt +23 -22
- package/android/src/play/java/com/dooboolab/RNIap/RNIapActivityListener.kt +15 -0
- package/android/src/testAmazon/java/com/dooboolab/RNIap/RNIapAmazonModuleTest.kt +26 -11
- package/package.json +1 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.dooboolab.RNIap
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.amazon.device.iap.PurchasingService
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* In order of the IAP process to show correctly, AmazonPurchasingService must be registered on Activity.onCreate
|
|
9
|
+
* registering it in on Application.onCreate will not throw an error but it will now show the Native purchasing screen
|
|
10
|
+
*/
|
|
11
|
+
class RNIapActivityListener {
|
|
12
|
+
companion object {
|
|
13
|
+
@JvmStatic
|
|
14
|
+
var hasListener = false
|
|
15
|
+
|
|
16
|
+
@JvmStatic
|
|
17
|
+
var amazonListener: RNIapAmazonListener? = null
|
|
18
|
+
|
|
19
|
+
@JvmStatic
|
|
20
|
+
fun registerActivity(activity: Activity) {
|
|
21
|
+
amazonListener = RNIapAmazonListener(null, null)
|
|
22
|
+
try {
|
|
23
|
+
PurchasingService.registerListener(activity, amazonListener)
|
|
24
|
+
hasListener = true
|
|
25
|
+
// Prefetch user and purchases as per Amazon SDK documentation:
|
|
26
|
+
PurchasingService.getUserData()
|
|
27
|
+
PurchasingService.getPurchaseUpdates(false)
|
|
28
|
+
} catch (e: Exception) {
|
|
29
|
+
Log.e(RNIapAmazonModule.TAG, "Error initializing Amazon appstore sdk", e)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -10,19 +10,17 @@ import com.amazon.device.iap.model.Receipt
|
|
|
10
10
|
import com.amazon.device.iap.model.UserData
|
|
11
11
|
import com.amazon.device.iap.model.UserDataResponse
|
|
12
12
|
import com.facebook.react.bridge.Arguments
|
|
13
|
-
import com.facebook.react.bridge.ReactContext
|
|
14
13
|
import com.facebook.react.bridge.WritableMap
|
|
15
14
|
import com.facebook.react.bridge.WritableNativeArray
|
|
16
15
|
import com.facebook.react.bridge.WritableNativeMap
|
|
17
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter
|
|
18
16
|
import java.lang.NumberFormatException
|
|
19
17
|
|
|
20
18
|
val ProductType.typeString: String
|
|
21
19
|
get() = if (this == ProductType.ENTITLED || this == ProductType.CONSUMABLE) "inapp" else "subs"
|
|
22
20
|
|
|
23
21
|
class RNIapAmazonListener(
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
var eventSender: EventSender?,
|
|
23
|
+
var purchasingService: PurchasingServiceProxy?
|
|
26
24
|
) : PurchasingListener {
|
|
27
25
|
|
|
28
26
|
override fun onProductDataResponse(response: ProductDataResponse) {
|
|
@@ -96,11 +94,11 @@ class RNIapAmazonListener(
|
|
|
96
94
|
val item = receiptToMap(userData, receipt)
|
|
97
95
|
promiseItem = WritableNativeMap()
|
|
98
96
|
promiseItem.merge(item)
|
|
99
|
-
sendEvent(
|
|
97
|
+
eventSender?.sendEvent("purchase-updated", item)
|
|
100
98
|
availableItems.pushMap(promiseItem)
|
|
101
99
|
}
|
|
102
100
|
if (response.hasMore()) {
|
|
103
|
-
purchasingService
|
|
101
|
+
purchasingService?.getPurchaseUpdates(false)
|
|
104
102
|
} else {
|
|
105
103
|
if (purchases.size > 0 && promiseItem != null) {
|
|
106
104
|
PromiseUtils
|
|
@@ -129,7 +127,7 @@ class RNIapAmazonListener(
|
|
|
129
127
|
error.putString("debugMessage", debugMessage)
|
|
130
128
|
error.putString("code", errorCode)
|
|
131
129
|
error.putString("message", debugMessage)
|
|
132
|
-
sendEvent(
|
|
130
|
+
eventSender?.sendEvent("purchase-error", error)
|
|
133
131
|
PromiseUtils
|
|
134
132
|
.rejectPromisesForKey(
|
|
135
133
|
RNIapAmazonModule.PROMISE_QUERY_PURCHASES,
|
|
@@ -153,7 +151,7 @@ class RNIapAmazonListener(
|
|
|
153
151
|
error.putString("debugMessage", debugMessage)
|
|
154
152
|
error.putString("code", errorCode)
|
|
155
153
|
error.putString("message", debugMessage)
|
|
156
|
-
sendEvent(
|
|
154
|
+
eventSender?.sendEvent("purchase-error", error)
|
|
157
155
|
PromiseUtils
|
|
158
156
|
.rejectPromisesForKey(
|
|
159
157
|
RNIapAmazonModule.PROMISE_QUERY_PURCHASES,
|
|
@@ -198,7 +196,7 @@ class RNIapAmazonListener(
|
|
|
198
196
|
val item = receiptToMap(userData, receipt)
|
|
199
197
|
val promiseItem: WritableMap = Arguments.createMap()
|
|
200
198
|
promiseItem.merge(item)
|
|
201
|
-
sendEvent(
|
|
199
|
+
eventSender?.sendEvent("purchase-updated", item)
|
|
202
200
|
PromiseUtils
|
|
203
201
|
.resolvePromisesForKey(
|
|
204
202
|
RNIapAmazonModule.PROMISE_BUY_ITEM,
|
|
@@ -213,7 +211,7 @@ class RNIapAmazonListener(
|
|
|
213
211
|
error.putString("debugMessage", debugMessage)
|
|
214
212
|
error.putString("code", errorCode)
|
|
215
213
|
error.putString("message", debugMessage)
|
|
216
|
-
sendEvent(
|
|
214
|
+
eventSender?.sendEvent("purchase-error", error)
|
|
217
215
|
PromiseUtils
|
|
218
216
|
.rejectPromisesForKey(
|
|
219
217
|
RNIapAmazonModule.PROMISE_BUY_ITEM,
|
|
@@ -231,7 +229,7 @@ class RNIapAmazonListener(
|
|
|
231
229
|
error.putString("debugMessage", debugMessage)
|
|
232
230
|
error.putString("code", errorCode)
|
|
233
231
|
error.putString("message", debugMessage)
|
|
234
|
-
sendEvent(
|
|
232
|
+
eventSender?.sendEvent("purchase-error", error)
|
|
235
233
|
PromiseUtils
|
|
236
234
|
.rejectPromisesForKey(
|
|
237
235
|
RNIapAmazonModule.PROMISE_BUY_ITEM,
|
|
@@ -248,7 +246,7 @@ class RNIapAmazonListener(
|
|
|
248
246
|
error.putString("debugMessage", debugMessage)
|
|
249
247
|
error.putString("code", errorCode)
|
|
250
248
|
error.putString("message", debugMessage)
|
|
251
|
-
sendEvent(
|
|
249
|
+
eventSender?.sendEvent("purchase-error", error)
|
|
252
250
|
PromiseUtils
|
|
253
251
|
.rejectPromisesForKey(
|
|
254
252
|
RNIapAmazonModule.PROMISE_BUY_ITEM,
|
|
@@ -265,7 +263,7 @@ class RNIapAmazonListener(
|
|
|
265
263
|
error.putString("debugMessage", debugMessage)
|
|
266
264
|
error.putString("code", errorCode)
|
|
267
265
|
error.putString("message", debugMessage)
|
|
268
|
-
sendEvent(
|
|
266
|
+
eventSender?.sendEvent("purchase-error", error)
|
|
269
267
|
PromiseUtils
|
|
270
268
|
.rejectPromisesForKey(
|
|
271
269
|
RNIapAmazonModule.PROMISE_BUY_ITEM,
|
|
@@ -307,16 +305,6 @@ class RNIapAmazonListener(
|
|
|
307
305
|
}
|
|
308
306
|
}
|
|
309
307
|
|
|
310
|
-
fun sendEvent(
|
|
311
|
-
reactContext: ReactContext,
|
|
312
|
-
eventName: String,
|
|
313
|
-
params: WritableMap?
|
|
314
|
-
) {
|
|
315
|
-
reactContext
|
|
316
|
-
.getJSModule(RCTDeviceEventEmitter::class.java)
|
|
317
|
-
.emit(eventName, params)
|
|
318
|
-
}
|
|
319
|
-
|
|
320
308
|
companion object {
|
|
321
309
|
private const val E_PRODUCT_DATA_RESPONSE_FAILED = "E_PRODUCT_DATA_RESPONSE_FAILED"
|
|
322
310
|
private const val E_PRODUCT_DATA_RESPONSE_NOT_SUPPORTED =
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
package com.dooboolab.RNIap
|
|
2
2
|
|
|
3
|
-
import android.os.Handler
|
|
4
|
-
import android.os.Looper
|
|
5
3
|
import android.util.Log
|
|
6
4
|
import com.amazon.device.drm.LicensingService
|
|
7
5
|
import com.amazon.device.drm.model.LicenseResponse
|
|
8
|
-
import com.amazon.device.iap.PurchasingListener
|
|
9
6
|
import com.amazon.device.iap.model.FulfillmentResult
|
|
10
7
|
import com.facebook.react.bridge.LifecycleEventListener
|
|
11
8
|
import com.facebook.react.bridge.Promise
|
|
@@ -13,37 +10,41 @@ import com.facebook.react.bridge.ReactApplicationContext
|
|
|
13
10
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
14
11
|
import com.facebook.react.bridge.ReactMethod
|
|
15
12
|
import com.facebook.react.bridge.ReadableArray
|
|
13
|
+
import com.facebook.react.bridge.WritableMap
|
|
16
14
|
import com.facebook.react.module.annotations.ReactModule
|
|
15
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
17
16
|
|
|
18
17
|
@ReactModule(name = RNIapAmazonModule.TAG)
|
|
19
18
|
class RNIapAmazonModule(
|
|
20
|
-
reactContext: ReactApplicationContext,
|
|
19
|
+
private val reactContext: ReactApplicationContext,
|
|
21
20
|
private val purchasingService: PurchasingServiceProxy = PurchasingServiceProxyAmazonImpl(),
|
|
22
|
-
private
|
|
23
|
-
private val amazonListener: PurchasingListener = RNIapAmazonListener(reactContext, purchasingService)
|
|
21
|
+
private var eventSender: EventSender? = null
|
|
24
22
|
) :
|
|
25
23
|
ReactContextBaseJavaModule(reactContext) {
|
|
26
|
-
var hasListener = false
|
|
27
24
|
override fun getName(): String {
|
|
28
25
|
return TAG
|
|
29
26
|
}
|
|
30
27
|
|
|
31
28
|
@ReactMethod
|
|
32
29
|
fun initConnection(promise: Promise) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
30
|
+
if (RNIapActivityListener.amazonListener == null) {
|
|
31
|
+
promise.safeReject(PromiseUtils.E_DEVELOPER_ERROR, Exception("RNIapActivityListener is not registered in your MainActivity.onCreate"))
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if (eventSender == null) {
|
|
35
|
+
eventSender = object : EventSender {
|
|
36
|
+
private val rctDeviceEventEmitter = reactContext
|
|
37
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
38
|
+
|
|
39
|
+
override fun sendEvent(eventName: String, params: WritableMap?) {
|
|
40
|
+
rctDeviceEventEmitter
|
|
41
|
+
.emit(eventName, params)
|
|
42
|
+
}
|
|
45
43
|
}
|
|
46
|
-
}
|
|
44
|
+
}
|
|
45
|
+
RNIapActivityListener.amazonListener?.eventSender = eventSender
|
|
46
|
+
RNIapActivityListener.amazonListener?.purchasingService = purchasingService
|
|
47
|
+
promise.resolve(true)
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
@ReactMethod
|
|
@@ -88,7 +89,7 @@ class RNIapAmazonModule(
|
|
|
88
89
|
@ReactMethod
|
|
89
90
|
fun endConnection(promise: Promise) {
|
|
90
91
|
PromiseUtils.rejectAllPendingPromises()
|
|
91
|
-
hasListener = false
|
|
92
|
+
RNIapActivityListener.hasListener = false
|
|
92
93
|
promise.resolve(true)
|
|
93
94
|
}
|
|
94
95
|
|
|
@@ -191,7 +192,7 @@ class RNIapAmazonModule(
|
|
|
191
192
|
* We should fetch updates on resume
|
|
192
193
|
*/
|
|
193
194
|
override fun onHostResume() {
|
|
194
|
-
if (hasListener) {
|
|
195
|
+
if (RNIapActivityListener.hasListener) {
|
|
195
196
|
purchasingService.getUserData()
|
|
196
197
|
purchasingService.getPurchaseUpdates(false)
|
|
197
198
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package com.dooboolab.RNIap
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Currently only needed for Amazon IAP
|
|
7
|
+
*/
|
|
8
|
+
class RNIapActivityListener {
|
|
9
|
+
companion object {
|
|
10
|
+
@JvmStatic
|
|
11
|
+
fun registerActivity(activity: Activity) {
|
|
12
|
+
// No op
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
package com.dooboolab.RNIap
|
|
2
2
|
|
|
3
|
-
import android.os.Handler
|
|
4
3
|
import com.amazon.device.iap.model.PurchaseResponse
|
|
5
4
|
import com.amazon.device.iap.model.Receipt
|
|
6
5
|
import com.amazon.device.iap.model.RequestId
|
|
@@ -21,6 +20,7 @@ import io.mockk.slot
|
|
|
21
20
|
import io.mockk.spyk
|
|
22
21
|
import io.mockk.verify
|
|
23
22
|
import org.junit.Assert.assertEquals
|
|
23
|
+
import org.junit.Assert.assertNotNull
|
|
24
24
|
import org.junit.Before
|
|
25
25
|
import org.junit.Test
|
|
26
26
|
import java.util.*
|
|
@@ -34,7 +34,7 @@ class RNIapAmazonModuleTest {
|
|
|
34
34
|
lateinit var purchasingServiceProxy: PurchasingServiceProxy
|
|
35
35
|
|
|
36
36
|
@MockK
|
|
37
|
-
lateinit var
|
|
37
|
+
lateinit var eventSender: EventSender
|
|
38
38
|
|
|
39
39
|
private lateinit var listener: RNIapAmazonListener
|
|
40
40
|
|
|
@@ -43,21 +43,36 @@ class RNIapAmazonModuleTest {
|
|
|
43
43
|
@Before
|
|
44
44
|
fun setUp() {
|
|
45
45
|
MockKAnnotations.init(this, relaxUnitFun = true)
|
|
46
|
-
listener = spyk(RNIapAmazonListener(
|
|
47
|
-
module = RNIapAmazonModule(context, purchasingServiceProxy,
|
|
46
|
+
listener = spyk(RNIapAmazonListener(eventSender, purchasingServiceProxy))
|
|
47
|
+
module = RNIapAmazonModule(context, purchasingServiceProxy, eventSender)
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
@Test
|
|
51
|
-
fun `initConnection should resolve to true`() {
|
|
51
|
+
fun `initConnection should resolve to true if RNIapActivityListener is configured`() {
|
|
52
52
|
every { context.applicationContext } returns mockk()
|
|
53
53
|
|
|
54
54
|
val promise = mockk<Promise>(relaxed = true)
|
|
55
|
-
|
|
56
|
-
every { mainThreadHandler.postDelayed(capture(slot), any()) } answers { slot.captured.run(); true }
|
|
57
|
-
module.initConnection(promise)
|
|
55
|
+
|
|
58
56
|
verify(exactly = 0) { promise.reject(any(), any<String>()) }
|
|
57
|
+
|
|
58
|
+
RNIapActivityListener.registerActivity(mockk())
|
|
59
|
+
|
|
60
|
+
module.initConnection(promise)
|
|
61
|
+
// should set eventSender and purchase service
|
|
62
|
+
assertNotNull(RNIapActivityListener.amazonListener?.purchasingService)
|
|
63
|
+
assertNotNull(RNIapActivityListener.amazonListener?.eventSender)
|
|
64
|
+
|
|
59
65
|
verify { promise.resolve(true) }
|
|
60
|
-
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@Test
|
|
69
|
+
fun `initConnection should reject if RNIapActivityListener is not configured`() {
|
|
70
|
+
every { context.applicationContext } returns mockk()
|
|
71
|
+
|
|
72
|
+
val promise = mockk<Promise>(relaxed = true)
|
|
73
|
+
module.initConnection(promise)
|
|
74
|
+
verify(exactly = 0) { promise.reject(any(), any<String>()) }
|
|
75
|
+
verify { promise.reject(PromiseUtils.E_DEVELOPER_ERROR, any(), any<Throwable>()) }
|
|
61
76
|
}
|
|
62
77
|
|
|
63
78
|
@Test
|
|
@@ -78,7 +93,7 @@ class RNIapAmazonModuleTest {
|
|
|
78
93
|
every { userData } returns mUserData
|
|
79
94
|
}
|
|
80
95
|
|
|
81
|
-
every {
|
|
96
|
+
every { eventSender.sendEvent(any(), any()) } just Runs
|
|
82
97
|
|
|
83
98
|
every { purchasingServiceProxy.purchase(any()) } answers {
|
|
84
99
|
listener.onPurchaseResponse(
|
|
@@ -100,7 +115,7 @@ class RNIapAmazonModuleTest {
|
|
|
100
115
|
val response = slot<WritableMap>()
|
|
101
116
|
verify { promise.resolve(capture(response)) }
|
|
102
117
|
assertEquals("mySku", response.captured.getString("productId"))
|
|
103
|
-
verify {
|
|
118
|
+
verify { eventSender.sendEvent("purchase-updated", any()) }
|
|
104
119
|
verify(exactly = 0) { purchasingServiceProxy.getPurchaseUpdates(false) }
|
|
105
120
|
}
|
|
106
121
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-iap",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.5.0",
|
|
4
4
|
"description": "React Native In App Purchase Module.",
|
|
5
5
|
"repository": "https://github.com/dooboolab/react-native-iap",
|
|
6
6
|
"author": "dooboolab <support@dooboolab.com> (https://github.com/dooboolab)",
|