react-native-iap 12.13.2 → 12.14.1-rc.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.
Files changed (31) hide show
  1. package/README.md +10 -4
  2. package/RNIap.podspec +1 -1
  3. package/android/gradle.properties +1 -1
  4. package/android/src/amazon/java/com/dooboolab/rniap/PurchasingServiceProxy.kt +8 -2
  5. package/android/src/amazon/java/com/dooboolab/rniap/PurchasingServiceProxyAmazonImpl.kt +12 -18
  6. package/android/src/amazon/java/com/dooboolab/rniap/RNIapAmazonListener.kt +4 -2
  7. package/android/src/amazon/java/com/dooboolab/rniap/RNIapAmazonModule.kt +45 -29
  8. package/android/src/amazon/java/com/dooboolab/rniap/RNIapPackage.kt +1 -4
  9. package/android/src/main/java/com/dooboolab/rniap/PromiseUtils.kt +9 -2
  10. package/android/src/main/java/com/dooboolab/rniap/PromiseUtlis.kt +15 -6
  11. package/android/src/play/java/com/dooboolab/rniap/PlayUtils.kt +86 -70
  12. package/android/src/play/java/com/dooboolab/rniap/RNIapModule.kt +196 -209
  13. package/android/src/play/java/com/dooboolab/rniap/RNIapPackage.kt +1 -4
  14. package/android/src/testAmazon/java/com/dooboolab/rniap/RNIapAmazonModuleTest.kt +23 -19
  15. package/ios/IapSerializationUtils.swift +2 -0
  16. package/ios/IapUtils.swift +10 -0
  17. package/ios/LatestPromiseKeeper.swift +47 -0
  18. package/ios/RNIapIos.swift +16 -24
  19. package/ios/RNIapIos.xcodeproj/project.pbxproj +13 -7
  20. package/ios/RNIapIosSk2.m +1 -4
  21. package/ios/RNIapIosSk2.swift +25 -12
  22. package/ios/ThreadSafe.swift +18 -0
  23. package/lib/commonjs/eventEmitter.js.map +1 -1
  24. package/lib/commonjs/modules/iosSk2.js.map +1 -1
  25. package/lib/module/eventEmitter.js.map +1 -1
  26. package/lib/module/modules/iosSk2.js.map +1 -1
  27. package/lib/typescript/src/eventEmitter.d.ts.map +1 -1
  28. package/lib/typescript/src/modules/iosSk2.d.ts.map +1 -1
  29. package/package.json +3 -4
  30. package/src/eventEmitter.ts +1 -7
  31. package/src/modules/iosSk2.ts +2 -3
package/README.md CHANGED
@@ -10,11 +10,14 @@
10
10
 
11
11
  ---
12
12
 
13
+ ## Announcement
14
+ Announcing the Migration of react-native-iap to an Expo Module for Improved Maintenance and Compatibility in [discussion #2754](https://github.com/dooboolab-community/react-native-iap/discussions/2754).
15
+
13
16
  ## Documentation
14
17
 
15
18
  Read the [documentation](https://react-native-iap.dooboolab.com). See the [troubleshooting](https://react-native-iap.dooboolab.com/docs/guides/troubleshooting#common-issues) for the common issues to avoid.
16
19
 
17
- ## Announcement
20
+ ## Logs
18
21
 
19
22
  - Version `12.0.0`: Implements Amazon 3.x SDK including the new DRM verification.
20
23
 
@@ -50,14 +53,16 @@ Follow [this guide](./IapExample/README.md) to get the example running.
50
53
 
51
54
  ### <p style="color: gold;">Gold Tier</p>
52
55
 
53
- | [NAMI](https://namiml.com) |
54
- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
56
+ | [NAMI](https://namiml.com) |
57
+ |:--:|
55
58
  | <a href="https://namiml.com"><img src="https://github.com/dooboolab-community/react-native-iap/assets/27461460/89d71f61-bb73-400a-83bd-fe0f96eb726e" width="450"/></a> |
56
59
 
57
- ## Past Sponsors
60
+
61
+ ## Past Sponsors
58
62
 
59
63
  <a href="https://www.revenuecat.com"><img src="https://github.com/dooboolab-community/react-native-iap/assets/27461460/1e387a47-afe0-4b85-ad78-1064ca6623fa" width="200"/></a>
60
64
 
65
+
61
66
  Support this project by becoming a sponsor. Your logo will show up here with
62
67
  a link to your website. [Buy me a coffee](https://www.buymeacoffee.com/dooboolab) or
63
68
  [Become a sponsor](https://opencollective.com/react-native-iap#sponsor).
@@ -78,3 +83,4 @@ Thank you to all the people who helped to maintain and upgrade this project!
78
83
  ---
79
84
 
80
85
  [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fdooboolab%2Freact-native-iap.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fdooboolab%2Freact-native-iap?ref=badge_large)
86
+
package/RNIap.podspec CHANGED
@@ -11,7 +11,7 @@ Pod::Spec.new do |s|
11
11
  s.license = package["license"]
12
12
  s.authors = package["author"]
13
13
 
14
- s.platforms = { :ios => "10.0" , :tvos => "10.0"}
14
+ s.platforms = { :ios => "10.0" , :tvos => "10.0", :visionos => "1.0" }
15
15
  s.source = { :git => "https://github.com/dooboolab-community/react-native-iap.git", :tag => "#{s.version}" }
16
16
 
17
17
  s.source_files = "ios/*.{h,m,mm,swift}"
@@ -6,7 +6,7 @@ RNIap_buildToolsVersion=33.0.0
6
6
  RNIap_ndkversion=23.1.7779620
7
7
  RNIap_playServicesVersion=18.1.0
8
8
  RNIap_amazonSdkVersion=3.0.4
9
- RNIap_playBillingSdkVersion=6.1.0
9
+ RNIap_playBillingSdkVersion=7.0.0
10
10
 
11
11
  android.useAndroidX=true
12
12
  android.enableJetifier=true
@@ -6,7 +6,10 @@ import com.amazon.device.iap.model.FulfillmentResult
6
6
  import com.amazon.device.iap.model.RequestId
7
7
 
8
8
  interface PurchasingServiceProxy {
9
- fun registerListener(var0: Context?, var1: PurchasingListener?)
9
+ fun registerListener(
10
+ var0: Context?,
11
+ var1: PurchasingListener?,
12
+ )
10
13
 
11
14
  fun getUserData(): RequestId
12
15
 
@@ -16,5 +19,8 @@ interface PurchasingServiceProxy {
16
19
 
17
20
  fun getPurchaseUpdates(var0: Boolean): RequestId
18
21
 
19
- fun notifyFulfillment(var0: String?, var1: FulfillmentResult?)
22
+ fun notifyFulfillment(
23
+ var0: String?,
24
+ var1: FulfillmentResult?,
25
+ )
20
26
  }
@@ -7,27 +7,21 @@ import com.amazon.device.iap.model.FulfillmentResult
7
7
  import com.amazon.device.iap.model.RequestId
8
8
 
9
9
  class PurchasingServiceProxyAmazonImpl : PurchasingServiceProxy {
10
- override fun registerListener(var0: Context?, var1: PurchasingListener?) {
11
- return PurchasingService.registerListener(var0, var1)
12
- }
10
+ override fun registerListener(
11
+ var0: Context?,
12
+ var1: PurchasingListener?,
13
+ ) = PurchasingService.registerListener(var0, var1)
13
14
 
14
- override fun getUserData(): RequestId {
15
- return PurchasingService.getUserData()
16
- }
15
+ override fun getUserData(): RequestId = PurchasingService.getUserData()
17
16
 
18
- override fun purchase(var0: String?): RequestId {
19
- return PurchasingService.purchase(var0)
20
- }
17
+ override fun purchase(var0: String?): RequestId = PurchasingService.purchase(var0)
21
18
 
22
- override fun getProductData(var0: Set<String?>?): RequestId {
23
- return PurchasingService.getProductData(var0)
24
- }
19
+ override fun getProductData(var0: Set<String?>?): RequestId = PurchasingService.getProductData(var0)
25
20
 
26
- override fun getPurchaseUpdates(var0: Boolean): RequestId {
27
- return PurchasingService.getPurchaseUpdates(var0)
28
- }
21
+ override fun getPurchaseUpdates(var0: Boolean): RequestId = PurchasingService.getPurchaseUpdates(var0)
29
22
 
30
- override fun notifyFulfillment(var0: String?, var1: FulfillmentResult?) {
31
- return PurchasingService.notifyFulfillment(var0, var1)
32
- }
23
+ override fun notifyFulfillment(
24
+ var0: String?,
25
+ var1: FulfillmentResult?,
26
+ ) = PurchasingService.notifyFulfillment(var0, var1)
33
27
  }
@@ -22,7 +22,6 @@ class RNIapAmazonListener(
22
22
  var eventSender: EventSender?,
23
23
  var purchasingService: PurchasingServiceProxy?,
24
24
  ) : PurchasingListener {
25
-
26
25
  override fun onProductDataResponse(response: ProductDataResponse) {
27
26
  when (response.requestStatus) {
28
27
  ProductDataResponse.RequestStatus.SUCCESSFUL -> {
@@ -170,7 +169,10 @@ class RNIapAmazonListener(
170
169
  }
171
170
  }
172
171
 
173
- private fun receiptToMap(userData: UserData, receipt: Receipt): WritableMap {
172
+ private fun receiptToMap(
173
+ userData: UserData,
174
+ receipt: Receipt,
175
+ ): WritableMap {
174
176
  val item = Arguments.createMap()
175
177
  item.putString("productId", receipt.sku)
176
178
  item.putDouble("transactionDate", receipt.purchaseDate.time.toDouble())
@@ -22,28 +22,33 @@ class RNIapAmazonModule(
22
22
  private val reactContext: ReactApplicationContext,
23
23
  private val purchasingService: PurchasingServiceProxy = PurchasingServiceProxyAmazonImpl(),
24
24
  private var eventSender: EventSender? = null,
25
- ) :
26
- ReactContextBaseJavaModule(reactContext) {
27
- override fun getName(): String {
28
- return TAG
29
- }
25
+ ) : ReactContextBaseJavaModule(reactContext) {
26
+ override fun getName(): String = TAG
30
27
 
31
28
  @ReactMethod
32
29
  fun initConnection(promise: Promise) {
33
30
  if (RNIapActivityListener.amazonListener == null) {
34
- promise.safeReject(PromiseUtils.E_DEVELOPER_ERROR, Exception("RNIapActivityListener is not registered in your MainActivity.onCreate"))
31
+ promise.safeReject(
32
+ PromiseUtils.E_DEVELOPER_ERROR,
33
+ Exception("RNIapActivityListener is not registered in your MainActivity.onCreate"),
34
+ )
35
35
  return
36
36
  }
37
37
  if (eventSender == null) {
38
- eventSender = object : EventSender {
39
- private val rctDeviceEventEmitter = reactContext
40
- .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
41
-
42
- override fun sendEvent(eventName: String, params: WritableMap?) {
43
- rctDeviceEventEmitter
44
- .emit(eventName, params)
38
+ eventSender =
39
+ object : EventSender {
40
+ private val rctDeviceEventEmitter =
41
+ reactContext
42
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
43
+
44
+ override fun sendEvent(
45
+ eventName: String,
46
+ params: WritableMap?,
47
+ ) {
48
+ rctDeviceEventEmitter
49
+ .emit(eventName, params)
50
+ }
45
51
  }
46
- }
47
52
  }
48
53
  RNIapActivityListener.amazonListener?.eventSender = eventSender
49
54
  RNIapActivityListener.amazonListener?.purchasingService = purchasingService
@@ -109,7 +114,11 @@ class RNIapAmazonModule(
109
114
  }
110
115
 
111
116
  @ReactMethod
112
- fun getItemsByType(type: String?, skuArr: ReadableArray, promise: Promise) {
117
+ fun getItemsByType(
118
+ type: String?,
119
+ skuArr: ReadableArray,
120
+ promise: Promise,
121
+ ) {
113
122
  val productSkus: MutableSet<String> = HashSet()
114
123
  var ii = 0
115
124
  val skuSize = skuArr.size()
@@ -171,7 +180,10 @@ class RNIapAmazonModule(
171
180
  * From https://amazon.developer.forums.answerhub.com/questions/175720/how-to-open-store-subscription-screen-directly-use.html?childToView=179402#answer-179402
172
181
  */
173
182
  @ReactMethod
174
- fun deepLinkToSubscriptions(isAmazonDevice: Boolean, promise: Promise) {
183
+ fun deepLinkToSubscriptions(
184
+ isAmazonDevice: Boolean,
185
+ promise: Promise,
186
+ ) {
175
187
  if (isAmazonDevice) {
176
188
  val intent =
177
189
  Intent("android.intent.action.VIEW", Uri.parse("amzn://apps/library/subscriptions"))
@@ -210,22 +222,26 @@ class RNIapAmazonModule(
210
222
 
211
223
  const val TAG = "RNIapAmazonModule"
212
224
  }
225
+
213
226
  init {
214
- val lifecycleEventListener: LifecycleEventListener = object : LifecycleEventListener {
215
- /**
216
- * From https://developer.amazon.com/docs/in-app-purchasing/iap-implement-iap.html#getpurchaseupdates-responses
217
- * We should fetch updates on resume
218
- */
219
- override fun onHostResume() {
220
- if (RNIapActivityListener.hasListener) {
221
- purchasingService.getUserData()
222
- purchasingService.getPurchaseUpdates(false)
227
+ val lifecycleEventListener: LifecycleEventListener =
228
+ object : LifecycleEventListener {
229
+ /**
230
+ * From https://developer.amazon.com/docs/in-app-purchasing/iap-implement-iap.html#getpurchaseupdates-responses
231
+ * We should fetch updates on resume
232
+ */
233
+ override fun onHostResume() {
234
+ if (RNIapActivityListener.hasListener) {
235
+ purchasingService.getUserData()
236
+ purchasingService.getPurchaseUpdates(false)
237
+ }
238
+ }
239
+
240
+ override fun onHostPause() {}
241
+
242
+ override fun onHostDestroy() {
223
243
  }
224
244
  }
225
- override fun onHostPause() {}
226
- override fun onHostDestroy() {
227
- }
228
- }
229
245
  reactContext.addLifecycleEventListener(lifecycleEventListener)
230
246
  }
231
247
  }
@@ -7,10 +7,7 @@ import com.facebook.react.uimanager.ViewManager
7
7
  import java.util.ArrayList
8
8
 
9
9
  class RNIapPackage : ReactPackage {
10
-
11
- override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
12
- return emptyList()
13
- }
10
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = emptyList()
14
11
 
15
12
  override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
16
13
  val modules: MutableList<NativeModule> = ArrayList()
@@ -6,11 +6,18 @@ import java.util.HashMap
6
6
 
7
7
  object PromiseUtils {
8
8
  private val promises = HashMap<String, MutableList<Promise>>()
9
- fun addPromiseForKey(key: String, promise: Promise) {
9
+
10
+ fun addPromiseForKey(
11
+ key: String,
12
+ promise: Promise,
13
+ ) {
10
14
  promises.getOrPut(key) { mutableListOf() }.add(promise)
11
15
  }
12
16
 
13
- fun resolvePromisesForKey(key: String, value: Any?) {
17
+ fun resolvePromisesForKey(
18
+ key: String,
19
+ value: Any?,
20
+ ) {
14
21
  promises[key]?.forEach { promise ->
15
22
  promise.safeResolve(value)
16
23
  }
@@ -21,12 +21,21 @@ fun Promise.safeResolve(value: Any?) {
21
21
 
22
22
  fun Promise.safeReject(message: String) = this.safeReject(message, null, null)
23
23
 
24
- fun Promise.safeReject(code: String?, message: String?) = this.safeReject(code, message, null)
25
-
26
- fun Promise.safeReject(code: String?, throwable: Throwable?) =
27
- this.safeReject(code, null, throwable)
28
-
29
- fun Promise.safeReject(code: String?, message: String?, throwable: Throwable?) {
24
+ fun Promise.safeReject(
25
+ code: String?,
26
+ message: String?,
27
+ ) = this.safeReject(code, message, null)
28
+
29
+ fun Promise.safeReject(
30
+ code: String?,
31
+ throwable: Throwable?,
32
+ ) = this.safeReject(code, null, throwable)
33
+
34
+ fun Promise.safeReject(
35
+ code: String?,
36
+ message: String?,
37
+ throwable: Throwable?,
38
+ ) {
30
39
  try {
31
40
  this.reject(code, message, throwable)
32
41
  } catch (oce: ObjectAlreadyConsumedException) {
@@ -4,88 +4,104 @@ import android.util.Log
4
4
  import com.android.billingclient.api.BillingClient
5
5
  import com.facebook.react.bridge.Promise
6
6
 
7
- data class BillingResponse(val code: String, val message: String)
7
+ data class BillingResponse(
8
+ val code: String,
9
+ val message: String,
10
+ )
8
11
 
9
12
  object PlayUtils {
10
- fun rejectPromiseWithBillingError(promise: Promise, responseCode: Int) {
13
+ fun rejectPromiseWithBillingError(
14
+ promise: Promise,
15
+ responseCode: Int,
16
+ ) {
11
17
  val errorData = getBillingResponseData(responseCode)
12
18
  promise.safeReject(errorData.code, errorData.message)
13
19
  }
14
20
 
15
21
  fun getBillingResponseData(responseCode: Int): BillingResponse {
16
- val errorData = when (responseCode) {
17
- BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED -> {
18
- BillingResponse(
19
- PromiseUtils.E_SERVICE_ERROR,
20
- "This feature is not available on your device.",
21
- )
22
+ val errorData =
23
+ when (responseCode) {
24
+ BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED -> {
25
+ BillingResponse(
26
+ PromiseUtils.E_SERVICE_ERROR,
27
+ "This feature is not available on your device.",
28
+ )
29
+ }
30
+ BillingClient.BillingResponseCode.SERVICE_DISCONNECTED -> {
31
+ BillingResponse(
32
+ PromiseUtils.E_NETWORK_ERROR,
33
+ "The service is disconnected (check your internet connection.)",
34
+ )
35
+ }
36
+ BillingClient.BillingResponseCode.NETWORK_ERROR -> {
37
+ BillingResponse(
38
+ PromiseUtils.E_NETWORK_ERROR,
39
+ "You have problem with network connection.",
40
+ )
41
+ }
42
+ BillingClient.BillingResponseCode.OK -> {
43
+ BillingResponse(
44
+ "OK",
45
+ "",
46
+ )
47
+ }
48
+ BillingClient.BillingResponseCode.USER_CANCELED -> {
49
+ BillingResponse(
50
+ PromiseUtils.E_USER_CANCELLED,
51
+ "Payment is Cancelled.",
52
+ )
53
+ }
54
+ BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE -> {
55
+ BillingResponse(
56
+ PromiseUtils.E_SERVICE_ERROR,
57
+ "The service is unreachable. This may be your internet connection, or the Play Store may be down.",
58
+ )
59
+ }
60
+ BillingClient.BillingResponseCode.BILLING_UNAVAILABLE -> {
61
+ BillingResponse(
62
+ PromiseUtils.E_SERVICE_ERROR,
63
+ "Billing is unavailable. This may be a problem with your device, or the Play Store may be down.",
64
+ )
65
+ }
66
+ BillingClient.BillingResponseCode.ITEM_UNAVAILABLE -> {
67
+ BillingResponse(
68
+ PromiseUtils.E_ITEM_UNAVAILABLE,
69
+ "That item is unavailable.",
70
+ )
71
+ }
72
+ BillingClient.BillingResponseCode.DEVELOPER_ERROR -> {
73
+ BillingResponse(
74
+ PromiseUtils.E_DEVELOPER_ERROR,
75
+ "Google is indicating that we have some issue connecting to payment.",
76
+ )
77
+ }
78
+ BillingClient.BillingResponseCode.ERROR -> {
79
+ BillingResponse(
80
+ PromiseUtils.E_UNKNOWN,
81
+ "An unknown or unexpected error has occurred. Please try again later.",
82
+ )
83
+ }
84
+ BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED -> {
85
+ BillingResponse(
86
+ PromiseUtils.E_ALREADY_OWNED,
87
+ "You already own this item.",
88
+ )
89
+ }
90
+ else -> {
91
+ BillingResponse(
92
+ PromiseUtils.E_UNKNOWN,
93
+ "Purchase failed with code: $responseCode",
94
+ )
95
+ }
22
96
  }
23
- BillingClient.BillingResponseCode.SERVICE_DISCONNECTED -> {
24
- BillingResponse(
25
- PromiseUtils.E_NETWORK_ERROR,
26
- "The service is disconnected (check your internet connection.)",
27
- )
28
- }
29
- BillingClient.BillingResponseCode.OK -> {
30
- BillingResponse(
31
- "OK",
32
- "",
33
- )
34
- }
35
- BillingClient.BillingResponseCode.USER_CANCELED -> {
36
- BillingResponse(
37
- PromiseUtils.E_USER_CANCELLED,
38
- "Payment is Cancelled.",
39
- )
40
- }
41
- BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE -> {
42
- BillingResponse(
43
- PromiseUtils.E_SERVICE_ERROR,
44
- "The service is unreachable. This may be your internet connection, or the Play Store may be down.",
45
- )
46
- }
47
- BillingClient.BillingResponseCode.BILLING_UNAVAILABLE -> {
48
- BillingResponse(
49
- PromiseUtils.E_SERVICE_ERROR,
50
- "Billing is unavailable. This may be a problem with your device, or the Play Store may be down.",
51
- )
52
- }
53
- BillingClient.BillingResponseCode.ITEM_UNAVAILABLE -> {
54
- BillingResponse(
55
- PromiseUtils.E_ITEM_UNAVAILABLE,
56
- "That item is unavailable.",
57
- )
58
- }
59
- BillingClient.BillingResponseCode.DEVELOPER_ERROR -> {
60
- BillingResponse(
61
- PromiseUtils.E_DEVELOPER_ERROR,
62
- "Google is indicating that we have some issue connecting to payment.",
63
- )
64
- }
65
- BillingClient.BillingResponseCode.ERROR -> {
66
- BillingResponse(
67
- PromiseUtils.E_UNKNOWN,
68
- "An unknown or unexpected error has occurred. Please try again later.",
69
- )
70
- }
71
- BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED -> {
72
- BillingResponse(
73
- PromiseUtils.E_ALREADY_OWNED,
74
- "You already own this item.",
75
- )
76
- }
77
- else -> {
78
- BillingResponse(
79
- PromiseUtils.E_UNKNOWN,
80
- "Purchase failed with code: $responseCode",
81
- )
82
- }
83
- }
84
97
  Log.e(TAG, "Error Code : $responseCode")
85
98
  return errorData
86
99
  }
87
100
 
88
- fun rejectPromisesWithBillingError(key: String, responseCode: Int) {
101
+ fun rejectPromisesWithBillingError(
102
+ key: String,
103
+ responseCode: Int,
104
+ ) {
89
105
  val errorData = getBillingResponseData(responseCode)
90
106
  PromiseUtils.rejectPromisesForKey(key, errorData.code, errorData.message, null)
91
107
  }