react-native-iap 9.0.0-beta7 → 9.0.0-beta9

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 (91) hide show
  1. package/README.md +4 -20
  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 +55 -54
  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} +48 -34
  8. package/ios/RNIapIos-Bridging-Header.h +2 -0
  9. package/ios/RNIapIos.m +14 -1
  10. package/ios/RNIapIos.swift +903 -881
  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 +585 -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 +493 -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 +13 -11
  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 +23 -4
  57. package/package.json +84 -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 +699 -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 +209 -0
  67. package/.editorconfig +0 -10
  68. package/.flowconfig +0 -11
  69. package/.monolinterrc +0 -3
  70. package/.prettierignore +0 -6
  71. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  72. package/android/gradle/wrapper/gradle-wrapper.properties +0 -6
  73. package/android/gradlew +0 -160
  74. package/android/gradlew.bat +0 -90
  75. package/android/src/play/java/com/dooboolab/RNIap/RNIapModuleInterface.kt +0 -44
  76. package/android/src/play/java/com/dooboolab/RNIap/RNIapModuleV4.kt +0 -658
  77. package/babel.config.js +0 -12
  78. package/index.d.ts +0 -3
  79. package/index.js +0 -3
  80. package/index.js.flow +0 -9
  81. package/ios/RNIap.xcodeproj/xcshareddata/xcschemes/RNIap.xcscheme +0 -80
  82. package/jest.config.js +0 -190
  83. package/src/__test__/iap.test.js +0 -59
  84. package/src/hooks/useIAP.js +0 -141
  85. package/src/hooks/withIAPContext.js +0 -150
  86. package/src/iap.js +0 -638
  87. package/src/types/amazon.js +0 -1
  88. package/src/types/android.js +0 -22
  89. package/src/types/apple.js +0 -165
  90. package/src/types/index.js +0 -40
  91. package/test/mocks/react-native-modules.js +0 -14
package/README.md CHANGED
@@ -5,14 +5,14 @@
5
5
 
6
6
  [![Download](http://img.shields.io/npm/dm/react-native-iap.svg?style=flat-square)](https://npmjs.org/package/react-native-iap)
7
7
  [![CI](https://github.com/dooboolab/react-native-iap/actions/workflows/ci.yml/badge.svg)](https://github.com/dooboolab/react-native-iap/actions/workflows/ci.yml)
8
- [![document](https://github.com/dooboolab/react-native-iap/actions/workflows/deploy-document.yml/badge.svg)](https://github.com/dooboolab/react-native-iap/actions/workflows/deploy-document.yml)
8
+ [![document](https://github.com/dooboolab/react-native-iap/actions/workflows/deploy-documentation.yml/badge.svg)](https://github.com/dooboolab/react-native-iap/actions/workflows/deploy-documentation.yml)
9
9
  [![License](https://img.shields.io/npm/l/react-native-iap.svg)](https://npmjs.org/package/react-native-iap)
10
10
  [![Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/dooboolab/react-native-iap.svg)](https://github.com/dooboolab/react-native-iap)
11
11
  [![Issue Opened](https://img.shields.io/opencollective/all/react-native-iap.svg)](https://opencollective.com/react-native-iap#backers)
12
12
  [![Issue Opened](https://img.shields.io/github/issues/dooboolab/react-native-iap.svg)](https://github.com/dooboolab/react-native-iap/issues)
13
13
  [![Issue Closed](https://img.shields.io/github/issues-closed/dooboolab/react-native-iap.svg)](https://github.com/dooboolab/react-native-iap/issues?q=is%3Aissue+is%3Aclosed)
14
14
  [![PR Opened](https://img.shields.io/github/issues-pr/dooboolab/react-native-iap.svg)](https://github.com/dooboolab/react-native-iap/pulls)
15
- [![PR Closed](https://img.shields.io/github/issues-pr-closed/dooboolab/react-native-iap.svg)](https://github.com/dooboolab/react-native-iap/pulls?q=is%3Apr+is%3Aclosed) [![Greenkeeper badge](https://badges.greenkeeper.io/dooboolab/react-native-iap.svg)](https://greenkeeper.io/)
15
+ [![PR Closed](https://img.shields.io/github/issues-pr-closed/dooboolab/react-native-iap.svg)](https://github.com/dooboolab/react-native-iap/pulls?q=is%3Apr+is%3Aclosed)
16
16
  [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fdooboolab%2Freact-native-iap.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fdooboolab%2Freact-native-iap?ref=badge_shield)
17
17
 
18
18
  ## Documentation
@@ -141,25 +141,9 @@ If you're looking for a module going further than react-native-iap, we recommend
141
141
 
142
142
  - Please refer to [Blog][blog-config-steps].
143
143
 
144
- ## [Deprecated README][readme-deprecated]
144
+ ## Example
145
145
 
146
- - If you are using `react-native-iap@^2.*`, please follow the above README.
147
-
148
- ## Usage
149
-
150
- You can look in the [`RNIapExample/`][example] folder to try the example.
151
-
152
- NOTE: To run `RNIapExample` on Android use the variant flag as follows:
153
-
154
- ```
155
- yarn android --variant=MY_VARIANT
156
- ```
157
-
158
- where `MY_VARIANT` is `PlayDebug` or `AmazonDebug`
159
-
160
- Below is basic implementation which is also provided in `RNIapExample` project.
161
-
162
- If you want more advanced one please refer to [dooboolab.com/sponsor.tsx](https://github.com/hyochan/dooboolab.com/blob/main/src/components/pages/Sponsor.tsx)
146
+ Follow [this guide](./IapExample/README.md) to get the example running.
163
147
 
164
148
  ## Sponsoring
165
149
 
package/RNIap.podspec CHANGED
@@ -1,23 +1,38 @@
1
- require 'json'
2
- package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+ folly_version = '2021.06.28.00-v2'
5
+ folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
3
6
 
4
7
  Pod::Spec.new do |s|
5
- s.name = "RNIap"
6
- s.version = package['version']
7
- s.summary = package['description']
8
- s.homepage = "https://github.com/dooboolab/react-native-iap"
9
- s.license = "MIT"
10
- s.author = package['author']
11
- s.platforms = { :ios => "9.0", :tvos => "9.0" }
12
- s.source = { :git => "https://github.com/dooboolab/react-native-iap.git", :tag => "#{s.version}" }
13
- s.source_files = "ios/*.{h,m,swift}"
14
- s.script_phase = {
15
- :name => 'Copy Swift Header',
16
- :script => 'ditto "${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h" "${PODS_ROOT}/Headers/Public/${PRODUCT_MODULE_NAME}/${PRODUCT_MODULE_NAME}-Swift.h"',
17
- :execution_position => :after_compile
18
- }
19
- s.swift_version = "4.2"
8
+ s.name = "RNIap"
9
+ s.version = package["version"]
10
+ s.summary = package["description"]
11
+ s.homepage = package["homepage"]
12
+ s.license = package["license"]
13
+ s.authors = package["author"]
14
+
15
+ s.platforms = { :ios => "10.0" }
16
+ s.source = { :git => "https://github.com/dooboolab/react-native-iap.git", :tag => "#{s.version}" }
17
+
18
+ s.source_files = "ios/*.{h,m,mm,swift}"
19
+
20
20
  s.requires_arc = true
21
21
 
22
- s.dependency 'React-Core'
22
+ s.dependency "React-Core"
23
+
24
+ # Don't install the dependencies when we run `pod install` in the old architecture.
25
+ if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
26
+ s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
27
+ s.pod_target_xcconfig = {
28
+ "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
29
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
30
+ }
31
+
32
+ s.dependency "React-Codegen"
33
+ s.dependency "RCT-Folly", folly_version
34
+ s.dependency "RCTRequired"
35
+ s.dependency "RCTTypeSafety"
36
+ s.dependency "ReactCommon/turbomodule/core"
37
+ end
23
38
  end
@@ -1,91 +1,190 @@
1
1
  buildscript {
2
- ext.DEFAULT_KOTLIN_VERSION = '1.7.10'
3
- ext.safeExtGet={prop, fallback->
4
- return rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
5
- }
6
- repositories {
2
+ // Buildscript is evaluated before everything else so we can't use getExtOrDefault
3
+ def kotlinVersion = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["RNIap_kotlinVersion"]
4
+
5
+ repositories {
7
6
  google()
8
7
  mavenCentral()
9
8
  }
10
9
 
11
-
12
10
  dependencies {
13
- classpath 'com.android.tools.build:gradle:4.2.2'
14
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${safeExtGet('kotlinVersion',DEFAULT_KOTLIN_VERSION)}"
11
+ classpath "com.android.tools.build:gradle:4.2.2"
12
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
15
13
  }
16
14
  }
17
15
 
18
- apply plugin: 'com.android.library'
19
- apply plugin: 'kotlin-android'
16
+ def isNewArchitectureEnabled() {
17
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
18
+ }
20
19
 
20
+ apply plugin: "com.android.library"
21
+ apply plugin: "kotlin-android"
21
22
 
22
- def DEFAULT_COMPILE_SDK_VERSION = 30
23
- def DEFAULT_BUILD_TOOLS_VERSION = "30.0.2"
24
- def DEFAULT_MIN_SDK_VERSION = 16
25
- def DEFAULT_TARGET_SDK_VERSION = 30
26
- def DEFAULT_PLAY_SERVICES_VERSION = "18.1.0"
23
+ if (isNewArchitectureEnabled()) {
24
+ apply plugin: "com.facebook.react"
25
+ }
26
+
27
+ def getExtOrDefault(name) {
28
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["RNIap_" + name]
29
+ }
30
+
31
+ def getExtOrIntegerDefault(name) {
32
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["RNIap_" + name]).toInteger()
33
+ }
27
34
 
28
35
  android {
29
- compileSdkVersion safeExtGet("compileSdkVersion", DEFAULT_COMPILE_SDK_VERSION)
36
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
30
37
 
31
38
  defaultConfig {
32
- minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION)
33
- targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION)
34
- versionCode 3
35
- versionName "3.0.0"
39
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
40
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
41
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
42
+ }
43
+
44
+ buildTypes {
45
+ release {
46
+ minifyEnabled false
47
+ }
36
48
  }
49
+
37
50
  lintOptions {
38
51
  abortOnError false
52
+ disable "GradleCompatible"
39
53
  }
54
+
40
55
  compileOptions {
41
56
  sourceCompatibility JavaVersion.VERSION_1_8
42
57
  targetCompatibility JavaVersion.VERSION_1_8
43
58
  }
59
+
44
60
  flavorDimensions "store"
61
+
45
62
  productFlavors {
46
- amazon{
63
+ amazon {
47
64
  dimension "store"
48
65
  }
49
- play{
66
+
67
+ play {
50
68
  dimension "store"
51
69
  }
52
70
  }
71
+
53
72
  testOptions {
54
73
  unitTests.returnDefaultValues = true
55
74
  }
56
75
  }
57
76
 
58
77
  repositories {
59
- maven {
60
- // All of React Native (JS, Android binaries) is installed from npm
61
- url "$rootDir/../node_modules/react-native/android"
62
- }
63
- google()
64
78
  mavenCentral()
79
+ google()
80
+
81
+ def found = false
82
+ def defaultDir = null
83
+ def androidSourcesName = "React Native sources"
84
+
85
+ if (rootProject.ext.has("reactNativeAndroidRoot")) {
86
+ defaultDir = rootProject.ext.get("reactNativeAndroidRoot")
87
+ } else {
88
+ defaultDir = new File(
89
+ projectDir,
90
+ "/../../../node_modules/react-native/android"
91
+ )
92
+ }
93
+
94
+ if (defaultDir.exists()) {
95
+ maven {
96
+ url defaultDir.toString()
97
+ name androidSourcesName
98
+ }
99
+
100
+ logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}")
101
+ found = true
102
+ } else {
103
+ def parentDir = rootProject.projectDir
104
+
105
+ 1.upto(5, {
106
+ if (found) return true
107
+ parentDir = parentDir.parentFile
108
+
109
+ def androidSourcesDir = new File(
110
+ parentDir,
111
+ "node_modules/react-native"
112
+ )
113
+
114
+ def androidPrebuiltBinaryDir = new File(
115
+ parentDir,
116
+ "node_modules/react-native/android"
117
+ )
118
+
119
+ if (androidPrebuiltBinaryDir.exists()) {
120
+ maven {
121
+ url androidPrebuiltBinaryDir.toString()
122
+ name androidSourcesName
123
+ }
124
+
125
+ logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}")
126
+ found = true
127
+ } else if (androidSourcesDir.exists()) {
128
+ maven {
129
+ url androidSourcesDir.toString()
130
+ name androidSourcesName
131
+ }
132
+
133
+ logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}")
134
+ found = true
135
+ }
136
+ })
137
+ }
138
+
139
+ if (!found) {
140
+ throw new GradleException(
141
+ "${project.name}: unable to locate React Native android sources. " +
142
+ "Ensure you have you installed React Native as a dependency in your project and try again."
143
+ )
144
+ }
65
145
  }
66
146
 
147
+ def kotlinVersion = getExtOrDefault("kotlinVersion")
148
+ def playServicesVersion = getExtOrDefault("playServicesVersion")
149
+ def supportLibVersion = getExtOrDefault("supportLibVersion")
150
+ def androidXVersion = getExtOrDefault("androidXVersion")
151
+ def androidXAnnotation = getExtOrDefault("androidXAnnotation")
152
+ def androidXBrowser = getExtOrDefault("androidXBrowser")
153
+
67
154
  dependencies {
68
- implementation 'com.facebook.react:react-native:+'
69
- testImplementation 'junit:junit:4.13.1'
155
+ implementation "com.facebook.react:react-native:+"
156
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
157
+
158
+ testImplementation "junit:junit:4.13.2"
70
159
  testImplementation "io.mockk:mockk:1.12.4"
71
- playImplementation 'com.android.billingclient:billing:5.0.0'
72
- def playServicesVersion = safeExtGet('playServicesVersion', DEFAULT_PLAY_SERVICES_VERSION)
160
+
161
+ playImplementation "com.android.billingclient:billing-ktx:5.0.0"
73
162
  playImplementation "com.google.android.gms:play-services-base:$playServicesVersion"
74
- amazonImplementation fileTree(dir: 'libs', include: ['*.jar'])
75
163
 
76
- def supportLibVersion = safeExtGet('supportLibVersion', safeExtGet('supportVersion', null))
77
- def androidXVersion = safeExtGet('androidXVersion', null)
164
+ amazonImplementation fileTree(dir: "libs", include: ["*.jar"])
165
+
78
166
  if (supportLibVersion && androidXVersion == null) {
79
167
  implementation "com.android.support:support-annotations:$supportLibVersion"
80
168
  implementation "com.android.support:customtabs:$supportLibVersion"
81
169
  } else {
82
170
  def defaultAndroidXVersion = "1.2.0"
171
+
83
172
  if (androidXVersion == null) {
84
173
  androidXVersion = defaultAndroidXVersion
85
174
  }
86
- def androidXAnnotation = safeExtGet('androidXAnnotation', androidXVersion)
87
- def androidXBrowser = safeExtGet('androidXBrowser', androidXVersion)
88
- implementation "androidx.annotation:annotation:$androidXAnnotation"
89
- implementation "androidx.browser:browser:$androidXBrowser"
175
+
176
+ def annotationVersion = androidXAnnotation ? androidXAnnotation : androidXVersion
177
+ def browserVersion = androidXBrowser ? androidXBrowser : androidXVersion
178
+
179
+ implementation "androidx.annotation:annotation:$annotationVersion"
180
+ implementation "androidx.browser:browser:$browserVersion"
181
+ }
182
+ }
183
+
184
+ if (isNewArchitectureEnabled()) {
185
+ react {
186
+ jsRootDir = file("../src/")
187
+ libraryName = "RNIap"
188
+ codegenJavaPackageName = "com.reactnativeiap"
90
189
  }
91
190
  }
@@ -1,2 +1,10 @@
1
+ RNIap_kotlinVersion=1.7.0
2
+ RNIap_minSdkVersion=21
3
+ RNIap_targetSdkVersion=31
4
+ RNIap_compileSdkVersion=31
5
+ RNIap_buildToolsVersion=30.0.2
6
+ RNIap_ndkversion=21.4.7075529
7
+ RNIap_playServicesVersion=17.6.0
8
+
1
9
  android.useAndroidX=true
2
10
  android.enableJetifier=true
@@ -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 ->
@@ -306,7 +306,7 @@ class RNIapModule(
306
306
  }
307
307
 
308
308
  @ReactMethod
309
- override fun getAvailableItemsByType(type: String, promise: Promise) {
309
+ fun getAvailableItemsByType(type: String, promise: Promise) {
310
310
  ensureConnection(
311
311
  promise
312
312
  ) { billingClient ->
@@ -355,7 +355,7 @@ class RNIapModule(
355
355
  }
356
356
 
357
357
  @ReactMethod
358
- override fun getPurchaseHistoryByType(type: String, promise: Promise) {
358
+ fun getPurchaseHistoryByType(type: String, promise: Promise) {
359
359
  ensureConnection(
360
360
  promise
361
361
  ) { billingClient ->
@@ -390,14 +390,14 @@ class RNIapModule(
390
390
  }
391
391
 
392
392
  @ReactMethod
393
- override fun buyItemByType(
393
+ fun buyItemByType(
394
394
  type: String,
395
- sku: String, // TODO: should this now be an array?
395
+ skuArr: ReadableArray,
396
396
  purchaseToken: String?,
397
397
  prorationMode: Int,
398
398
  obfuscatedAccountId: String?,
399
399
  obfuscatedProfileId: String?,
400
- selectedOfferIndex: Int, // New optional parameter in V5, TODO: should it be an array?
400
+ selectedOfferIndexArr: ReadableArray, // New optional parameter in V5
401
401
  promise: Promise
402
402
  ) {
403
403
  val activity = currentActivity
@@ -412,32 +412,36 @@ class RNIapModule(
412
412
  PROMISE_BUY_ITEM,
413
413
  promise
414
414
  )
415
- val builder = BillingFlowParams.newBuilder()
416
- val selectedSku: ProductDetails? = skus[sku]
417
- if (selectedSku == null) {
418
- val debugMessage =
419
- "The sku was not found. Please fetch products first by calling getItems"
420
- val error = Arguments.createMap()
421
- error.putString("debugMessage", debugMessage)
422
- error.putString("code", PROMISE_BUY_ITEM)
423
- error.putString("message", debugMessage)
424
- error.putString("productId", sku)
425
- sendEvent(reactContext, "purchase-error", error)
426
- promise.safeReject(PROMISE_BUY_ITEM, debugMessage)
427
- return@ensureConnection
428
- }
429
- var productParams = BillingFlowParams.ProductDetailsParams.newBuilder().setProductDetails(selectedSku)
430
- if (selectedOfferIndex > -1 && (
431
- selectedSku.subscriptionOfferDetails?.size
432
- ?: 0
433
- ) > selectedOfferIndex
434
- ) {
435
- val offerToken =
436
- selectedSku.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken
437
- offerToken?.let { productParams = productParams.setOfferToken(offerToken) }
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()
438
442
  }
439
-
440
- builder.setProductDetailsParamsList(listOf(productParams.build()))
443
+ val builder = BillingFlowParams.newBuilder()
444
+ builder.setProductDetailsParamsList(productParamsList)
441
445
  val subscriptionUpdateParamsBuilder = SubscriptionUpdateParams.newBuilder()
442
446
  if (purchaseToken != null) {
443
447
  subscriptionUpdateParamsBuilder.setOldPurchaseToken(purchaseToken)
@@ -465,7 +469,7 @@ class RNIapModule(
465
469
  error.putString("debugMessage", debugMessage)
466
470
  error.putString("code", PROMISE_BUY_ITEM)
467
471
  error.putString("message", debugMessage)
468
- error.putString("productId", sku)
472
+ error.putArray("productIds", skuArr)
469
473
  sendEvent(reactContext, "purchase-error", error)
470
474
  promise.safeReject(PROMISE_BUY_ITEM, debugMessage)
471
475
  return@ensureConnection
@@ -516,7 +520,7 @@ class RNIapModule(
516
520
  }
517
521
 
518
522
  @ReactMethod
519
- override fun acknowledgePurchase(
523
+ fun acknowledgePurchase(
520
524
  token: String,
521
525
  developerPayLoad: String?,
522
526
  promise: Promise
@@ -546,7 +550,7 @@ class RNIapModule(
546
550
  }
547
551
 
548
552
  @ReactMethod
549
- override fun consumeProduct(
553
+ fun consumeProduct(
550
554
  token: String,
551
555
  developerPayLoad: String?,
552
556
  promise: Promise
@@ -588,10 +592,9 @@ class RNIapModule(
588
592
  return
589
593
  }
590
594
  if (purchases != null) {
591
- var promiseItem: WritableMap? = null
592
- for (i in purchases.indices) {
595
+ val promiseItems: WritableArray = Arguments.createArray()
596
+ purchases.forEach { purchase ->
593
597
  val item = Arguments.createMap()
594
- val purchase = purchases[i]
595
598
  item.putString("productId", purchase.products[0])
596
599
  val products = Arguments.createArray()
597
600
  purchase.products.forEach { products.pushString(it) }
@@ -618,13 +621,10 @@ class RNIapModule(
618
621
  accountIdentifiers.obfuscatedProfileId
619
622
  )
620
623
  }
621
- promiseItem = WritableNativeMap()
622
- promiseItem.merge(item)
624
+ promiseItems.pushMap(item)
623
625
  sendEvent(reactContext, "purchase-updated", item)
624
626
  }
625
- if (promiseItem != null) {
626
- DoobooUtils.instance.resolvePromisesForKey(PROMISE_BUY_ITEM, promiseItem)
627
- }
627
+ DoobooUtils.instance.resolvePromisesForKey(PROMISE_BUY_ITEM, promiseItems)
628
628
  } else {
629
629
  val result = Arguments.createMap()
630
630
  result.putInt("responseCode", billingResult.responseCode)
@@ -661,22 +661,22 @@ class RNIapModule(
661
661
  }
662
662
 
663
663
  @ReactMethod
664
- override fun startListening(promise: Promise) {
664
+ fun startListening(promise: Promise) {
665
665
  sendUnconsumedPurchases(promise)
666
666
  }
667
667
 
668
668
  @ReactMethod
669
- override fun addListener(eventName: String) {
669
+ fun addListener(eventName: String) {
670
670
  // Keep: Required for RN built-in Event Emitter Calls.
671
671
  }
672
672
 
673
673
  @ReactMethod
674
- override fun removeListeners(count: Double) {
674
+ fun removeListeners(count: Double) {
675
675
  // Keep: Required for RN built-in Event Emitter Calls.
676
676
  }
677
677
 
678
678
  @ReactMethod
679
- override fun getPackageName(promise: Promise) = promise.resolve(reactApplicationContext.packageName)
679
+ fun getPackageName(promise: Promise) = promise.resolve(reactApplicationContext.packageName)
680
680
 
681
681
  private fun sendEvent(
682
682
  reactContext: ReactContext,
@@ -699,6 +699,7 @@ class RNIapModule(
699
699
  override fun onHostPause() {}
700
700
  override fun onHostDestroy() {
701
701
  billingClientCache?.endConnection()
702
+ billingClientCache = null
702
703
  }
703
704
  }
704
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
  }