react-native-iap 9.0.0-beta5 → 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.
- package/README.md +4 -20
- package/RNIap.podspec +33 -18
- package/android/build.gradle +137 -38
- package/android/gradle.properties +8 -0
- package/android/src/play/java/com/dooboolab/RNIap/RNIapModule.kt +68 -57
- package/android/src/play/java/com/dooboolab/RNIap/RNIapPackage.kt +0 -1
- package/android/src/testPlay/java/com/dooboolab/RNIap/{RNIapModuleTestV4.kt → RNIapModuleTest.kt} +48 -34
- package/ios/RNIapIos-Bridging-Header.h +2 -0
- package/ios/RNIapIos.m +14 -2
- package/ios/RNIapIos.swift +903 -881
- package/ios/{RNIap.xcodeproj → RNIapIos.xcodeproj}/project.pbxproj +29 -116
- package/lib/commonjs/__test__/iap.test.js +21 -0
- package/lib/commonjs/__test__/iap.test.js.map +1 -0
- package/lib/commonjs/hooks/useIAP.js +78 -0
- package/lib/commonjs/hooks/useIAP.js.map +1 -0
- package/lib/commonjs/hooks/withIAPContext.js +92 -0
- package/lib/commonjs/hooks/withIAPContext.js.map +1 -0
- package/lib/commonjs/iap.js +585 -0
- package/lib/commonjs/iap.js.map +1 -0
- package/lib/commonjs/index.js +59 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types/amazon.js +2 -0
- package/lib/commonjs/types/amazon.js.map +1 -0
- package/lib/commonjs/types/android.js +55 -0
- package/lib/commonjs/types/android.js.map +1 -0
- package/lib/commonjs/types/apple.js +165 -0
- package/lib/commonjs/types/apple.js.map +1 -0
- package/lib/commonjs/types/index.js +59 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/module/__test__/iap.test.js +17 -0
- package/lib/module/__test__/iap.test.js.map +1 -0
- package/lib/module/hooks/useIAP.js +68 -0
- package/lib/module/hooks/useIAP.js.map +1 -0
- package/lib/module/hooks/withIAPContext.js +76 -0
- package/lib/module/hooks/withIAPContext.js.map +1 -0
- package/lib/module/iap.js +493 -0
- package/lib/module/iap.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types/amazon.js +2 -0
- package/lib/module/types/amazon.js.map +1 -0
- package/lib/module/types/android.js +44 -0
- package/lib/module/types/android.js.map +1 -0
- package/lib/module/types/apple.js +153 -0
- package/lib/module/types/apple.js.map +1 -0
- package/lib/module/types/index.js +48 -0
- package/lib/module/types/index.js.map +1 -0
- package/{src → lib/typescript}/__test__/iap.test.d.ts +0 -0
- package/{src → lib/typescript}/hooks/useIAP.d.ts +1 -1
- package/{src → lib/typescript}/hooks/withIAPContext.d.ts +1 -1
- package/{src → lib/typescript}/iap.d.ts +13 -11
- package/{src → lib/typescript}/index.d.ts +2 -1
- package/{src → lib/typescript}/types/amazon.d.ts +0 -0
- package/{src → lib/typescript}/types/android.d.ts +0 -0
- package/{src → lib/typescript}/types/apple.d.ts +0 -0
- package/{src → lib/typescript}/types/index.d.ts +25 -8
- package/package.json +87 -57
- package/src/__test__/iap.test.ts +20 -0
- package/src/hooks/useIAP.ts +130 -0
- package/src/hooks/withIAPContext.tsx +160 -0
- package/src/iap.ts +699 -0
- package/src/{index.js → index.ts} +4 -1
- package/src/types/amazon.ts +23 -0
- package/src/types/android.ts +51 -0
- package/src/types/apple.ts +467 -0
- package/src/types/index.ts +209 -0
- package/.editorconfig +0 -10
- package/.flowconfig +0 -11
- package/.monolinterrc +0 -3
- package/.yarn/install-state.gz +0 -0
- package/.yarn/releases/yarn-3.2.0.cjs +0 -785
- package/.yarnrc.yml +0 -3
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +0 -6
- package/android/gradlew +0 -160
- package/android/gradlew.bat +0 -90
- package/android/src/play/java/com/dooboolab/RNIap/RNIapModuleInterface.kt +0 -44
- package/android/src/play/java/com/dooboolab/RNIap/RNIapModuleV4.kt +0 -658
- package/babel.config.js +0 -10
- package/index.d.ts +0 -3
- package/index.js +0 -3
- package/index.js.flow +0 -9
- package/ios/RNIap.xcodeproj/xcshareddata/xcschemes/RNIap.xcscheme +0 -80
- package/jest.config.js +0 -194
- package/src/__test__/iap.test.js +0 -59
- package/src/hooks/useIAP.js +0 -141
- package/src/hooks/withIAPContext.js +0 -150
- package/src/iap.js +0 -638
- package/src/types/amazon.js +0 -1
- package/src/types/android.js +0 -22
- package/src/types/apple.js +0 -165
- package/src/types/index.js +0 -40
- package/test/mocks/react-native-modules.js +0 -14
package/README.md
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
[](https://npmjs.org/package/react-native-iap)
|
|
7
7
|
[](https://github.com/dooboolab/react-native-iap/actions/workflows/ci.yml)
|
|
8
|
-
[](https://github.com/dooboolab/react-native-iap/actions/workflows/deploy-documentation.yml)
|
|
9
9
|
[](https://npmjs.org/package/react-native-iap)
|
|
10
10
|
[](https://github.com/dooboolab/react-native-iap)
|
|
11
11
|
[](https://opencollective.com/react-native-iap#backers)
|
|
12
12
|
[](https://github.com/dooboolab/react-native-iap/issues)
|
|
13
13
|
[](https://github.com/dooboolab/react-native-iap/issues?q=is%3Aissue+is%3Aclosed)
|
|
14
14
|
[](https://github.com/dooboolab/react-native-iap/pulls)
|
|
15
|
-
[](https://github.com/dooboolab/react-native-iap/pulls?q=is%3Apr+is%3Aclosed)
|
|
15
|
+
[](https://github.com/dooboolab/react-native-iap/pulls?q=is%3Apr+is%3Aclosed)
|
|
16
16
|
[](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
|
-
##
|
|
144
|
+
## Example
|
|
145
145
|
|
|
146
|
-
|
|
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
|
|
2
|
-
|
|
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
|
|
6
|
-
s.version
|
|
7
|
-
s.summary
|
|
8
|
-
s.homepage
|
|
9
|
-
s.license
|
|
10
|
-
s.
|
|
11
|
-
|
|
12
|
-
s.
|
|
13
|
-
s.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
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
|
package/android/build.gradle
CHANGED
|
@@ -1,91 +1,190 @@
|
|
|
1
1
|
buildscript {
|
|
2
|
-
|
|
3
|
-
ext.
|
|
4
|
-
|
|
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
|
|
14
|
-
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def
|
|
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
|
|
36
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
30
37
|
|
|
31
38
|
defaultConfig {
|
|
32
|
-
minSdkVersion
|
|
33
|
-
targetSdkVersion
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
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
|
|
69
|
-
|
|
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
|
-
|
|
72
|
-
|
|
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
|
-
|
|
77
|
-
|
|
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
|
-
|
|
87
|
-
def
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
52
|
+
fun ensureConnection(
|
|
53
53
|
promise: Promise,
|
|
54
54
|
callback: (billingClient: BillingClient) -> Unit
|
|
55
55
|
) {
|
|
@@ -87,7 +87,7 @@ class RNIapModule(
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
@ReactMethod
|
|
90
|
-
|
|
90
|
+
fun initConnection(promise: Promise) {
|
|
91
91
|
if (googleApiAvailability.isGooglePlayServicesAvailable(reactContext)
|
|
92
92
|
!= ConnectionResult.SUCCESS
|
|
93
93
|
) {
|
|
@@ -108,13 +108,13 @@ class RNIapModule(
|
|
|
108
108
|
billingClientCache = it
|
|
109
109
|
it.startConnection(
|
|
110
110
|
object : BillingClientStateListener {
|
|
111
|
-
|
|
111
|
+
override fun onBillingSetupFinished(billingResult: BillingResult) {
|
|
112
112
|
if (!isValidResult(billingResult, promise)) return
|
|
113
113
|
|
|
114
114
|
promise.safeResolve(true)
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
override fun onBillingServiceDisconnected() {
|
|
118
118
|
Log.i(TAG, "Billing service disconnected")
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -123,7 +123,7 @@ class RNIapModule(
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
@ReactMethod
|
|
126
|
-
|
|
126
|
+
fun endConnection(promise: Promise) {
|
|
127
127
|
billingClientCache?.endConnection()
|
|
128
128
|
billingClientCache = null
|
|
129
129
|
promise.safeResolve(true)
|
|
@@ -160,7 +160,7 @@ class RNIapModule(
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
@ReactMethod
|
|
163
|
-
|
|
163
|
+
fun flushFailedPurchasesCachedAsPending(promise: Promise) {
|
|
164
164
|
ensureConnection(
|
|
165
165
|
promise
|
|
166
166
|
) { billingClient ->
|
|
@@ -193,7 +193,7 @@ class RNIapModule(
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
@ReactMethod
|
|
196
|
-
|
|
196
|
+
fun getItemsByType(type: String, skuArr: ReadableArray, promise: Promise) {
|
|
197
197
|
ensureConnection(
|
|
198
198
|
promise
|
|
199
199
|
) { billingClient ->
|
|
@@ -306,7 +306,7 @@ class RNIapModule(
|
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
@ReactMethod
|
|
309
|
-
|
|
309
|
+
fun getAvailableItemsByType(type: String, promise: Promise) {
|
|
310
310
|
ensureConnection(
|
|
311
311
|
promise
|
|
312
312
|
) { billingClient ->
|
|
@@ -321,7 +321,10 @@ class RNIapModule(
|
|
|
321
321
|
for (i in purchases.indices) {
|
|
322
322
|
val purchase = purchases[i]
|
|
323
323
|
val item = WritableNativeMap()
|
|
324
|
-
item.putString("productId", purchase.products[0])
|
|
324
|
+
item.putString("productId", purchase.products[0])// kept for convenience/backward-compatibility. productIds has the complete list
|
|
325
|
+
val products = Arguments.createArray()
|
|
326
|
+
purchase.products.forEach { products.pushString(it) }
|
|
327
|
+
item.putArray("productIds", products)
|
|
325
328
|
item.putString("transactionId", purchase.orderId)
|
|
326
329
|
item.putDouble("transactionDate", purchase.purchaseTime.toDouble())
|
|
327
330
|
item.putString("transactionReceipt", purchase.originalJson)
|
|
@@ -352,7 +355,7 @@ class RNIapModule(
|
|
|
352
355
|
}
|
|
353
356
|
|
|
354
357
|
@ReactMethod
|
|
355
|
-
|
|
358
|
+
fun getPurchaseHistoryByType(type: String, promise: Promise) {
|
|
356
359
|
ensureConnection(
|
|
357
360
|
promise
|
|
358
361
|
) { billingClient ->
|
|
@@ -370,6 +373,9 @@ class RNIapModule(
|
|
|
370
373
|
purchaseHistoryRecordList?.forEach { purchase ->
|
|
371
374
|
val item = Arguments.createMap()
|
|
372
375
|
item.putString("productId", purchase.products[0])
|
|
376
|
+
val products = Arguments.createArray()
|
|
377
|
+
purchase.products.forEach { products.pushString(it) }
|
|
378
|
+
item.putArray("productIds", products)
|
|
373
379
|
item.putDouble("transactionDate", purchase.purchaseTime.toDouble())
|
|
374
380
|
item.putString("transactionReceipt", purchase.originalJson)
|
|
375
381
|
item.putString("purchaseToken", purchase.purchaseToken)
|
|
@@ -384,14 +390,14 @@ class RNIapModule(
|
|
|
384
390
|
}
|
|
385
391
|
|
|
386
392
|
@ReactMethod
|
|
387
|
-
|
|
393
|
+
fun buyItemByType(
|
|
388
394
|
type: String,
|
|
389
|
-
|
|
395
|
+
skuArr: ReadableArray,
|
|
390
396
|
purchaseToken: String?,
|
|
391
397
|
prorationMode: Int,
|
|
392
398
|
obfuscatedAccountId: String?,
|
|
393
399
|
obfuscatedProfileId: String?,
|
|
394
|
-
|
|
400
|
+
selectedOfferIndexArr: ReadableArray, // New optional parameter in V5
|
|
395
401
|
promise: Promise
|
|
396
402
|
) {
|
|
397
403
|
val activity = currentActivity
|
|
@@ -406,32 +412,36 @@ class RNIapModule(
|
|
|
406
412
|
PROMISE_BUY_ITEM,
|
|
407
413
|
promise
|
|
408
414
|
)
|
|
409
|
-
val
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
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()
|
|
432
442
|
}
|
|
433
|
-
|
|
434
|
-
builder.setProductDetailsParamsList(
|
|
443
|
+
val builder = BillingFlowParams.newBuilder()
|
|
444
|
+
builder.setProductDetailsParamsList(productParamsList)
|
|
435
445
|
val subscriptionUpdateParamsBuilder = SubscriptionUpdateParams.newBuilder()
|
|
436
446
|
if (purchaseToken != null) {
|
|
437
447
|
subscriptionUpdateParamsBuilder.setOldPurchaseToken(purchaseToken)
|
|
@@ -442,14 +452,14 @@ class RNIapModule(
|
|
|
442
452
|
if (obfuscatedProfileId != null) {
|
|
443
453
|
builder.setObfuscatedProfileId(obfuscatedProfileId)
|
|
444
454
|
}
|
|
445
|
-
if (prorationMode !=
|
|
455
|
+
if (prorationMode != -1) {
|
|
446
456
|
if (prorationMode
|
|
447
457
|
== BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE
|
|
448
458
|
) {
|
|
449
459
|
subscriptionUpdateParamsBuilder.setReplaceProrationMode(
|
|
450
460
|
BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE
|
|
451
461
|
)
|
|
452
|
-
if (type != BillingClient.
|
|
462
|
+
if (type != BillingClient.ProductType.SUBS) {
|
|
453
463
|
val debugMessage =
|
|
454
464
|
(
|
|
455
465
|
"IMMEDIATE_AND_CHARGE_PRORATED_PRICE for proration mode only works in" +
|
|
@@ -459,7 +469,7 @@ class RNIapModule(
|
|
|
459
469
|
error.putString("debugMessage", debugMessage)
|
|
460
470
|
error.putString("code", PROMISE_BUY_ITEM)
|
|
461
471
|
error.putString("message", debugMessage)
|
|
462
|
-
error.
|
|
472
|
+
error.putArray("productIds", skuArr)
|
|
463
473
|
sendEvent(reactContext, "purchase-error", error)
|
|
464
474
|
promise.safeReject(PROMISE_BUY_ITEM, debugMessage)
|
|
465
475
|
return@ensureConnection
|
|
@@ -510,7 +520,7 @@ class RNIapModule(
|
|
|
510
520
|
}
|
|
511
521
|
|
|
512
522
|
@ReactMethod
|
|
513
|
-
|
|
523
|
+
fun acknowledgePurchase(
|
|
514
524
|
token: String,
|
|
515
525
|
developerPayLoad: String?,
|
|
516
526
|
promise: Promise
|
|
@@ -540,7 +550,7 @@ class RNIapModule(
|
|
|
540
550
|
}
|
|
541
551
|
|
|
542
552
|
@ReactMethod
|
|
543
|
-
|
|
553
|
+
fun consumeProduct(
|
|
544
554
|
token: String,
|
|
545
555
|
developerPayLoad: String?,
|
|
546
556
|
promise: Promise
|
|
@@ -561,6 +571,7 @@ class RNIapModule(
|
|
|
561
571
|
.getBillingResponseData(billingResult.responseCode)
|
|
562
572
|
map.putString("code", errorData[0])
|
|
563
573
|
map.putString("message", errorData[1])
|
|
574
|
+
map.putString("purchaseToken",purchaseToken)
|
|
564
575
|
promise.safeResolve(map)
|
|
565
576
|
}
|
|
566
577
|
}
|
|
@@ -581,11 +592,13 @@ class RNIapModule(
|
|
|
581
592
|
return
|
|
582
593
|
}
|
|
583
594
|
if (purchases != null) {
|
|
584
|
-
|
|
585
|
-
|
|
595
|
+
val promiseItems: WritableArray = Arguments.createArray()
|
|
596
|
+
purchases.forEach { purchase ->
|
|
586
597
|
val item = Arguments.createMap()
|
|
587
|
-
val purchase = purchases[i]
|
|
588
598
|
item.putString("productId", purchase.products[0])
|
|
599
|
+
val products = Arguments.createArray()
|
|
600
|
+
purchase.products.forEach { products.pushString(it) }
|
|
601
|
+
item.putArray("productIds", products)
|
|
589
602
|
item.putString("transactionId", purchase.orderId)
|
|
590
603
|
item.putDouble("transactionDate", purchase.purchaseTime.toDouble())
|
|
591
604
|
item.putString("transactionReceipt", purchase.originalJson)
|
|
@@ -608,13 +621,10 @@ class RNIapModule(
|
|
|
608
621
|
accountIdentifiers.obfuscatedProfileId
|
|
609
622
|
)
|
|
610
623
|
}
|
|
611
|
-
|
|
612
|
-
promiseItem.merge(item)
|
|
624
|
+
promiseItems.pushMap(item)
|
|
613
625
|
sendEvent(reactContext, "purchase-updated", item)
|
|
614
626
|
}
|
|
615
|
-
|
|
616
|
-
DoobooUtils.instance.resolvePromisesForKey(PROMISE_BUY_ITEM, promiseItem)
|
|
617
|
-
}
|
|
627
|
+
DoobooUtils.instance.resolvePromisesForKey(PROMISE_BUY_ITEM, promiseItems)
|
|
618
628
|
} else {
|
|
619
629
|
val result = Arguments.createMap()
|
|
620
630
|
result.putInt("responseCode", billingResult.responseCode)
|
|
@@ -651,22 +661,22 @@ class RNIapModule(
|
|
|
651
661
|
}
|
|
652
662
|
|
|
653
663
|
@ReactMethod
|
|
654
|
-
|
|
664
|
+
fun startListening(promise: Promise) {
|
|
655
665
|
sendUnconsumedPurchases(promise)
|
|
656
666
|
}
|
|
657
667
|
|
|
658
668
|
@ReactMethod
|
|
659
|
-
|
|
669
|
+
fun addListener(eventName: String) {
|
|
660
670
|
// Keep: Required for RN built-in Event Emitter Calls.
|
|
661
671
|
}
|
|
662
672
|
|
|
663
673
|
@ReactMethod
|
|
664
|
-
|
|
674
|
+
fun removeListeners(count: Double) {
|
|
665
675
|
// Keep: Required for RN built-in Event Emitter Calls.
|
|
666
676
|
}
|
|
667
677
|
|
|
668
678
|
@ReactMethod
|
|
669
|
-
|
|
679
|
+
fun getPackageName(promise: Promise) = promise.resolve(reactApplicationContext.packageName)
|
|
670
680
|
|
|
671
681
|
private fun sendEvent(
|
|
672
682
|
reactContext: ReactContext,
|
|
@@ -689,6 +699,7 @@ class RNIapModule(
|
|
|
689
699
|
override fun onHostPause() {}
|
|
690
700
|
override fun onHostDestroy() {
|
|
691
701
|
billingClientCache?.endConnection()
|
|
702
|
+
billingClientCache = null
|
|
692
703
|
}
|
|
693
704
|
}
|
|
694
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
|
}
|