@react-native-kakao/cert 0.0.0-stage → 3.1.0-next.2
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/CHANGELOG.md +46 -0
- package/LICENSE +20 -0
- package/README.md +6 -2
- package/RNCKakaoCert.podspec +25 -0
- package/android/build.gradle +43 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/net/mjstudio/rnkakao/cert/RNCKakaoCertModule.kt +292 -0
- package/android/src/main/java/net/mjstudio/rnkakao/cert/RNCKakaoCertPackage.kt +34 -0
- package/ios/RNCKakaoCert.h +4 -0
- package/ios/RNCKakaoCert.mm +80 -0
- package/ios/RNCKakaoCertManager.swift +327 -0
- package/ios/RNCKakaoCertUtil.h +8 -0
- package/ios/RNCKakaoCertUtil.mm +17 -0
- package/lib/commonjs/index.js +126 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/index.web.js +73 -0
- package/lib/commonjs/index.web.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/spec/NativeKakaoCert.ts +30 -0
- package/lib/module/index.js +108 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/index.web.js +56 -0
- package/lib/module/index.web.js.map +1 -0
- package/lib/module/spec/NativeKakaoCert.ts +30 -0
- package/lib/typescript/src/index.d.ts +127 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/spec/NativeKakaoCert.d.ts +20 -0
- package/lib/typescript/src/spec/NativeKakaoCert.d.ts.map +1 -0
- package/package.json +96 -3
- package/src/index.ts +196 -0
- package/src/index.web.ts +64 -0
- package/src/spec/NativeKakaoCert.ts +30 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @react-native-kakao/cert
|
|
2
|
+
|
|
3
|
+
## 3.1.0-next.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f466ffa: Normalize APIs without success data to resolve without a value across platforms, while preserving friend-message results.
|
|
8
|
+
- Updated dependencies [f466ffa]
|
|
9
|
+
- Updated dependencies [f466ffa]
|
|
10
|
+
- Updated dependencies [23ca142]
|
|
11
|
+
- Updated dependencies [845f1f2]
|
|
12
|
+
- @react-native-kakao/user@3.1.0-next.2
|
|
13
|
+
- @react-native-kakao/core@3.1.0-next.2
|
|
14
|
+
|
|
15
|
+
## 3.1.0-next.1
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- 67cd4e2: Add Kakao certification login, device-local signing keys and sessions, abbreviated signatures, web certification authorization, and opt-in native callback configuration.
|
|
20
|
+
- d81f9b7: Expose iOS authorization-code and certification-code token exchange with PKCE options, normalized web token issuance, and explicit unsupported-platform errors.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- e25e428: Allow explicit native tokens when refreshing and normalize remaining token lifetimes across native responses.
|
|
25
|
+
- 87e8aa7: Allow a custom Android KakaoTalk login request code while preserving the SDK default when omitted. Accept the SDK's full 32-bit request code range for regular and certification login.
|
|
26
|
+
- Updated dependencies [250d066]
|
|
27
|
+
- Updated dependencies [3d92882]
|
|
28
|
+
- Updated dependencies [d5c5fb8]
|
|
29
|
+
- Updated dependencies [3027207]
|
|
30
|
+
- Updated dependencies [f1fd1e2]
|
|
31
|
+
- Updated dependencies [dfd32ca]
|
|
32
|
+
- Updated dependencies [da4db1c]
|
|
33
|
+
- Updated dependencies [f6e0207]
|
|
34
|
+
- Updated dependencies [a8a2e24]
|
|
35
|
+
- Updated dependencies [2b223bf]
|
|
36
|
+
- Updated dependencies [67cd4e2]
|
|
37
|
+
- Updated dependencies [d81f9b7]
|
|
38
|
+
- Updated dependencies [7fe7820]
|
|
39
|
+
- Updated dependencies [524be2c]
|
|
40
|
+
- Updated dependencies [e25e428]
|
|
41
|
+
- Updated dependencies [97a99b5]
|
|
42
|
+
- Updated dependencies [b6ff8a9]
|
|
43
|
+
- Updated dependencies [bd1bb64]
|
|
44
|
+
- Updated dependencies [87e8aa7]
|
|
45
|
+
- @react-native-kakao/user@3.1.0-next.1
|
|
46
|
+
- @react-native-kakao/core@3.1.0-next.1
|
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 MJ Studio
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
#
|
|
1
|
+
# React Native Kakao Cert
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@react-native-kakao/cert` exposes Kakao certification login, abbreviated signatures, and device-local signing sessions. Certification requires an approved Kakao app and server integration.
|
|
4
|
+
|
|
5
|
+
Install it with `@react-native-kakao/core` and `@react-native-kakao/user`. Native signing is available on Android and iOS; web supports the JavaScript SDK's certification authorization redirect.
|
|
6
|
+
|
|
7
|
+
See the [usage and setup guide](https://rnkakao.mjstudio.net/docs/cert/intro).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative "../core/ios/kakao-sdk"
|
|
3
|
+
|
|
4
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
5
|
+
core_package = JSON.parse(File.read(File.join(__dir__, "..", "core", "package.json")))
|
|
6
|
+
sdk_version = core_package['sdkVersions']['ios']['cert']
|
|
7
|
+
|
|
8
|
+
Pod::Spec.new do |s|
|
|
9
|
+
s.name = "RNCKakaoCert"
|
|
10
|
+
s.version = package["version"]
|
|
11
|
+
s.summary = package["description"]
|
|
12
|
+
s.homepage = package["homepage"]
|
|
13
|
+
s.license = package["license"]
|
|
14
|
+
s.authors = package["author"]
|
|
15
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
16
|
+
s.source = { :git => "https://github.com/mym0404/react-native-kakao.git", :tag => "#{s.version}" }
|
|
17
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
18
|
+
s.private_header_files = "ios/RNCKakaoCert.h"
|
|
19
|
+
|
|
20
|
+
install_modules_dependencies(s)
|
|
21
|
+
sdk_version = $KakaoCertSDKVersion if defined?($KakaoCertSDKVersion)
|
|
22
|
+
s.dependency 'RNCKakaoCore'
|
|
23
|
+
s.dependency 'RNCKakaoUser'
|
|
24
|
+
RNCKakaoSPM.dependency(s, sdk_version, %w[KakaoSDKCommon KakaoSDKAuth KakaoSDKUser KakaoSDKCert KakaoSDKCertCore])
|
|
25
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
apply from: file('./../../core/android/package-json.gradle')
|
|
2
|
+
def Versions = project.ext.RNCKakaoSdkVersions
|
|
3
|
+
Project coreProject = project.ext.getWorkspaceProject("core")
|
|
4
|
+
|
|
5
|
+
project.ext.applyPlugins()
|
|
6
|
+
|
|
7
|
+
android {
|
|
8
|
+
namespace "net.mjstudio.rnkakao.cert"
|
|
9
|
+
|
|
10
|
+
compileSdkVersion Versions.compileSdk
|
|
11
|
+
|
|
12
|
+
defaultConfig {
|
|
13
|
+
minSdkVersion Versions.minSdk
|
|
14
|
+
targetSdkVersion Versions.targetSdk
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
buildTypes {
|
|
18
|
+
release {
|
|
19
|
+
minifyEnabled false
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
lintOptions {
|
|
24
|
+
disable "GradleCompatible"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
compileOptions {
|
|
28
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
29
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
repositories {
|
|
34
|
+
mavenCentral()
|
|
35
|
+
google()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
dependencies {
|
|
39
|
+
implementation "com.facebook.react:react-android"
|
|
40
|
+
|
|
41
|
+
api coreProject
|
|
42
|
+
implementation "com.kakao.sdk:v2-cert:${Versions.cert}"
|
|
43
|
+
}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
package net.mjstudio.rnkakao.cert
|
|
2
|
+
|
|
3
|
+
import android.content.ActivityNotFoundException
|
|
4
|
+
import com.facebook.react.bridge.Promise
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReactMethod
|
|
7
|
+
import com.facebook.react.bridge.ReadableMap
|
|
8
|
+
import com.kakao.sdk.auth.AuthCodeClient
|
|
9
|
+
import com.kakao.sdk.auth.model.CertTokenInfo
|
|
10
|
+
import com.kakao.sdk.auth.model.CertType
|
|
11
|
+
import com.kakao.sdk.auth.model.IdentifyItem
|
|
12
|
+
import com.kakao.sdk.auth.model.OAuthToken
|
|
13
|
+
import com.kakao.sdk.auth.model.Prompt
|
|
14
|
+
import com.kakao.sdk.cert.CertApiClient
|
|
15
|
+
import com.kakao.sdk.cert.model.SessionInfo
|
|
16
|
+
import net.mjstudio.rnkakao.core.util.RNCKakaoResponseNotFoundException
|
|
17
|
+
import net.mjstudio.rnkakao.core.util.RNCKakaoUnsupportedPlatformException
|
|
18
|
+
import net.mjstudio.rnkakao.core.util.argArr
|
|
19
|
+
import net.mjstudio.rnkakao.core.util.argMap
|
|
20
|
+
import net.mjstudio.rnkakao.core.util.filterIsInstance
|
|
21
|
+
import net.mjstudio.rnkakao.core.util.getIntElseNull
|
|
22
|
+
import net.mjstudio.rnkakao.core.util.onMain
|
|
23
|
+
import net.mjstudio.rnkakao.core.util.pushStringList
|
|
24
|
+
import net.mjstudio.rnkakao.core.util.putD
|
|
25
|
+
import net.mjstudio.rnkakao.core.util.putL
|
|
26
|
+
import net.mjstudio.rnkakao.core.util.rejectWith
|
|
27
|
+
import net.mjstudio.rnkakao.core.util.unix
|
|
28
|
+
import java.util.Date
|
|
29
|
+
|
|
30
|
+
private const val TX_ID = "txId"
|
|
31
|
+
private const val MILLISECONDS_PER_SECOND = 1000.0
|
|
32
|
+
|
|
33
|
+
class RNCKakaoCertModule internal constructor(
|
|
34
|
+
context: ReactApplicationContext,
|
|
35
|
+
) : NativeKakaoCertSpec(context) {
|
|
36
|
+
@ReactMethod
|
|
37
|
+
override fun certLoginWithKakaoTalk(
|
|
38
|
+
options: ReadableMap,
|
|
39
|
+
promise: Promise,
|
|
40
|
+
) = login(options, true, promise)
|
|
41
|
+
|
|
42
|
+
@ReactMethod
|
|
43
|
+
override fun certLoginWithKakaoAccount(
|
|
44
|
+
options: ReadableMap,
|
|
45
|
+
promise: Promise,
|
|
46
|
+
) = login(options, false, promise)
|
|
47
|
+
|
|
48
|
+
@ReactMethod
|
|
49
|
+
override fun issueCertTokenWithCode(
|
|
50
|
+
code: String,
|
|
51
|
+
codeVerifier: String?,
|
|
52
|
+
redirectUri: String?,
|
|
53
|
+
promise: Promise,
|
|
54
|
+
) {
|
|
55
|
+
promise.rejectWith(RNCKakaoUnsupportedPlatformException("issueCertTokenWithCode", "iOS"))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private fun login(
|
|
59
|
+
options: ReadableMap,
|
|
60
|
+
isTalk: Boolean,
|
|
61
|
+
promise: Promise,
|
|
62
|
+
) = withCert(promise) { client ->
|
|
63
|
+
val activity =
|
|
64
|
+
reactApplicationContext.currentActivity ?: run {
|
|
65
|
+
promise.rejectWith(ActivityNotFoundException())
|
|
66
|
+
return@withCert
|
|
67
|
+
}
|
|
68
|
+
val certType = CertType.valueOf(requireNotNull(options.getString("certType")))
|
|
69
|
+
val prompts =
|
|
70
|
+
options
|
|
71
|
+
.getArray("prompts")
|
|
72
|
+
?.filterIsInstance<String>()
|
|
73
|
+
?.map {
|
|
74
|
+
when (it) {
|
|
75
|
+
"Login" -> Prompt.LOGIN
|
|
76
|
+
"Create" -> Prompt.CREATE
|
|
77
|
+
"SelectAccount" -> Prompt.SELECT_ACCOUNT
|
|
78
|
+
else -> throw IllegalArgumentException("Unsupported certification prompt: $it")
|
|
79
|
+
}
|
|
80
|
+
}?.ifEmpty { null }
|
|
81
|
+
val identifyItems =
|
|
82
|
+
options
|
|
83
|
+
.getArray("identifyItems")
|
|
84
|
+
?.filterIsInstance<String>()
|
|
85
|
+
?.map {
|
|
86
|
+
when (it) {
|
|
87
|
+
"ci" -> IdentifyItem.CI
|
|
88
|
+
"name" -> IdentifyItem.NAME
|
|
89
|
+
"birthday" -> IdentifyItem.BIRTHDAY
|
|
90
|
+
"phone_number" -> IdentifyItem.PHONE_NUMBER
|
|
91
|
+
else -> throw IllegalArgumentException("Unsupported signer information: $it")
|
|
92
|
+
}
|
|
93
|
+
}?.ifEmpty { null }
|
|
94
|
+
val signData = options.getString("signData")
|
|
95
|
+
val settleId = options.getString("settleId")
|
|
96
|
+
val nonce = options.getString("nonce")
|
|
97
|
+
val android = options.getMap("android")
|
|
98
|
+
val channelOptions = if (isTalk) options else android
|
|
99
|
+
val channelPublicIds = channelOptions?.getArray("channelPublicIds")?.filterIsInstance<String>()?.ifEmpty { null }
|
|
100
|
+
val serviceTerms = channelOptions?.getArray("serviceTerms")?.filterIsInstance<String>()?.ifEmpty { null }
|
|
101
|
+
val callback: (CertTokenInfo?, Throwable?) -> Unit = { info, error ->
|
|
102
|
+
if (error != null) {
|
|
103
|
+
promise.rejectWith(error)
|
|
104
|
+
} else if (info == null) {
|
|
105
|
+
promise.rejectWith(RNCKakaoResponseNotFoundException("certTokenInfo"))
|
|
106
|
+
} else {
|
|
107
|
+
promise.resolve(
|
|
108
|
+
argMap().apply {
|
|
109
|
+
putString(TX_ID, info.txId)
|
|
110
|
+
putMap("token", mapToken(info.token))
|
|
111
|
+
},
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (isTalk) {
|
|
116
|
+
client.certLoginWithKakaoTalk(
|
|
117
|
+
context = activity,
|
|
118
|
+
certType = certType,
|
|
119
|
+
signData = signData,
|
|
120
|
+
settleId = settleId,
|
|
121
|
+
txId = options.getString(TX_ID),
|
|
122
|
+
prompts = prompts,
|
|
123
|
+
identifyItems = identifyItems,
|
|
124
|
+
requestCode = android?.getIntElseNull("requestCode") ?: AuthCodeClient.DEFAULT_REQUEST_CODE,
|
|
125
|
+
nonce = nonce,
|
|
126
|
+
channelPublicIds = channelPublicIds,
|
|
127
|
+
serviceTerms = serviceTerms,
|
|
128
|
+
callback = callback,
|
|
129
|
+
)
|
|
130
|
+
} else {
|
|
131
|
+
client.certLoginWithKakaoAccount(
|
|
132
|
+
context = activity,
|
|
133
|
+
certType = certType,
|
|
134
|
+
prompts = prompts,
|
|
135
|
+
identifyItems = identifyItems,
|
|
136
|
+
signData = signData,
|
|
137
|
+
settleId = settleId,
|
|
138
|
+
nonce = nonce,
|
|
139
|
+
loginHint = options.getString("loginHint"),
|
|
140
|
+
channelPublicIds = channelPublicIds,
|
|
141
|
+
serviceTerms = serviceTerms,
|
|
142
|
+
callback = callback,
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@ReactMethod
|
|
148
|
+
override fun publicKey(
|
|
149
|
+
certType: String,
|
|
150
|
+
promise: Promise,
|
|
151
|
+
) = withCert(promise) {
|
|
152
|
+
promise.resolve(it.publicKey(CertType.valueOf(certType)))
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@ReactMethod
|
|
156
|
+
override fun sessionInfo(
|
|
157
|
+
certType: String,
|
|
158
|
+
promise: Promise,
|
|
159
|
+
) = withCert(promise) {
|
|
160
|
+
promise.resolve(it.sessionInfo(CertType.valueOf(certType))?.let(::mapSession))
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@ReactMethod
|
|
164
|
+
override fun fetchSessionInfo(
|
|
165
|
+
certType: String,
|
|
166
|
+
txId: String,
|
|
167
|
+
promise: Promise,
|
|
168
|
+
) = withCert(promise) {
|
|
169
|
+
it.sessionInfo(CertType.valueOf(certType), txId, sessionCallback(promise))
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@ReactMethod
|
|
173
|
+
override fun fetchSessionInfoByAppKey(
|
|
174
|
+
certType: String,
|
|
175
|
+
txId: String,
|
|
176
|
+
targetAppKey: String?,
|
|
177
|
+
promise: Promise,
|
|
178
|
+
) = withCert(promise) {
|
|
179
|
+
it.sessionInfoByAppKey(CertType.valueOf(certType), txId, targetAppKey, sessionCallback(promise))
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@ReactMethod
|
|
183
|
+
override fun isValidSession(
|
|
184
|
+
certType: String,
|
|
185
|
+
promise: Promise,
|
|
186
|
+
) = withCert(promise) {
|
|
187
|
+
promise.resolve(it.isValidSession(CertType.valueOf(certType)))
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@ReactMethod
|
|
191
|
+
override fun deleteKeyPair(
|
|
192
|
+
certType: String,
|
|
193
|
+
promise: Promise,
|
|
194
|
+
) = withCert(promise) {
|
|
195
|
+
it.deleteKeyPair(CertType.valueOf(certType))
|
|
196
|
+
promise.resolve(null)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@ReactMethod
|
|
200
|
+
override fun reducedSign(
|
|
201
|
+
certType: String,
|
|
202
|
+
data: String,
|
|
203
|
+
promise: Promise,
|
|
204
|
+
) = withCert(promise) {
|
|
205
|
+
it.reducedSign(CertType.valueOf(certType), data) { signature, error ->
|
|
206
|
+
if (error != null) {
|
|
207
|
+
promise.rejectWith(error)
|
|
208
|
+
} else if (signature == null) {
|
|
209
|
+
promise.rejectWith(RNCKakaoResponseNotFoundException("signature"))
|
|
210
|
+
} else {
|
|
211
|
+
promise.resolve(signature)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
@ReactMethod
|
|
217
|
+
override fun isKakaoTalkSignAvailable(promise: Promise) =
|
|
218
|
+
withCert(promise) {
|
|
219
|
+
promise.resolve(it.isKakaoTalkSignAvailable(reactApplicationContext))
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@ReactMethod
|
|
223
|
+
override fun signWithKakaoTalk(
|
|
224
|
+
txId: String,
|
|
225
|
+
targetAppKey: String?,
|
|
226
|
+
promise: Promise,
|
|
227
|
+
) = withCert(promise) {
|
|
228
|
+
val activity =
|
|
229
|
+
reactApplicationContext.currentActivity ?: run {
|
|
230
|
+
promise.rejectWith(ActivityNotFoundException())
|
|
231
|
+
return@withCert
|
|
232
|
+
}
|
|
233
|
+
it.signWithKakaoTalk(activity, CertType.K3220, txId, targetAppKey) { status, error ->
|
|
234
|
+
if (error != null) {
|
|
235
|
+
promise.rejectWith(error)
|
|
236
|
+
} else if (status == null) {
|
|
237
|
+
promise.rejectWith(RNCKakaoResponseNotFoundException("signStatusInfo"))
|
|
238
|
+
} else {
|
|
239
|
+
promise.resolve(
|
|
240
|
+
argMap().apply {
|
|
241
|
+
putString(TX_ID, status.txId)
|
|
242
|
+
putD("requestedAt", status.requestedAt?.time?.div(MILLISECONDS_PER_SECOND))
|
|
243
|
+
putD("requestExpiredAt", status.requestExpiredAt?.time?.div(MILLISECONDS_PER_SECOND))
|
|
244
|
+
putD("signedAt", status.signedAt?.time?.div(MILLISECONDS_PER_SECOND))
|
|
245
|
+
},
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private fun withCert(
|
|
252
|
+
promise: Promise,
|
|
253
|
+
operation: (CertApiClient) -> Unit,
|
|
254
|
+
) = onMain {
|
|
255
|
+
try {
|
|
256
|
+
operation(CertApiClient.instance)
|
|
257
|
+
} catch (error: Exception) {
|
|
258
|
+
promise.rejectWith(error)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private fun sessionCallback(promise: Promise): (SessionInfo?, Throwable?) -> Unit =
|
|
263
|
+
{ info, error ->
|
|
264
|
+
if (error != null) {
|
|
265
|
+
promise.rejectWith(error)
|
|
266
|
+
} else if (info == null) {
|
|
267
|
+
promise.rejectWith(RNCKakaoResponseNotFoundException("sessionInfo"))
|
|
268
|
+
} else {
|
|
269
|
+
promise.resolve(mapSession(info))
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private fun mapSession(info: SessionInfo) =
|
|
274
|
+
argMap().apply {
|
|
275
|
+
putL("userId", info.userId)
|
|
276
|
+
putDouble("sessionStartAt", info.sessionStartAt.time / MILLISECONDS_PER_SECOND)
|
|
277
|
+
putDouble("sessionEndAt", info.sessionEndAt.time / MILLISECONDS_PER_SECOND)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
private fun mapToken(token: OAuthToken) =
|
|
281
|
+
argMap().apply {
|
|
282
|
+
putString("accessToken", token.accessToken)
|
|
283
|
+
putString("refreshToken", token.refreshToken)
|
|
284
|
+
token.idToken?.let { putString("idToken", it) }
|
|
285
|
+
putDouble("accessTokenExpiresAt", token.accessTokenExpiresAt.unix.toDouble())
|
|
286
|
+
putDouble("refreshTokenExpiresAt", token.refreshTokenExpiresAt.unix.toDouble())
|
|
287
|
+
val now = Date().time
|
|
288
|
+
putDouble("accessTokenExpiresIn", (token.accessTokenExpiresAt.time - now) / MILLISECONDS_PER_SECOND)
|
|
289
|
+
putDouble("refreshTokenExpiresIn", (token.refreshTokenExpiresAt.time - now) / MILLISECONDS_PER_SECOND)
|
|
290
|
+
putArray("scopes", argArr().pushStringList(token.scopes.orEmpty()))
|
|
291
|
+
}
|
|
292
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
package net.mjstudio.rnkakao.cert
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
|
|
9
|
+
class RNCKakaoCertPackage : BaseReactPackage() {
|
|
10
|
+
override fun getModule(
|
|
11
|
+
name: String,
|
|
12
|
+
reactContext: ReactApplicationContext,
|
|
13
|
+
): NativeModule? =
|
|
14
|
+
if (name == NativeKakaoCertSpec.NAME) {
|
|
15
|
+
RNCKakaoCertModule(reactContext)
|
|
16
|
+
} else {
|
|
17
|
+
null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider =
|
|
21
|
+
ReactModuleInfoProvider {
|
|
22
|
+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
23
|
+
moduleInfos[NativeKakaoCertSpec.NAME] =
|
|
24
|
+
ReactModuleInfo(
|
|
25
|
+
NativeKakaoCertSpec.NAME,
|
|
26
|
+
RNCKakaoCertModule::class.java.name,
|
|
27
|
+
false, // canOverrideExistingModule
|
|
28
|
+
false, // needsEagerInit
|
|
29
|
+
false, // isCxxModule
|
|
30
|
+
true, // isTurboModule
|
|
31
|
+
)
|
|
32
|
+
moduleInfos
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#import "RNCKakaoCert.h"
|
|
2
|
+
|
|
3
|
+
#if __has_include("RNCKakaoCert-Swift.h")
|
|
4
|
+
#import "RNCKakaoCert-Swift.h"
|
|
5
|
+
#else
|
|
6
|
+
#import <RNCKakaoCert/RNCKakaoCert-Swift.h>
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
@implementation RNCKakaoCert
|
|
10
|
+
RCT_EXPORT_MODULE()
|
|
11
|
+
|
|
12
|
+
- (RNCKakaoCertManager*)manager {
|
|
13
|
+
return [RNCKakaoCertManager shared];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
RCT_EXPORT_METHOD(certLoginWithKakaoTalk : (NSDictionary*)options resolve : (RCTPromiseResolveBlock)
|
|
17
|
+
resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
18
|
+
[[self manager] certLoginWithKakaoTalk:options resolve:resolve reject:reject];
|
|
19
|
+
}
|
|
20
|
+
RCT_EXPORT_METHOD(certLoginWithKakaoAccount : (NSDictionary*)options resolve : (
|
|
21
|
+
RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
22
|
+
[[self manager] certLoginWithKakaoAccount:options resolve:resolve reject:reject];
|
|
23
|
+
}
|
|
24
|
+
RCT_EXPORT_METHOD(issueCertTokenWithCode : (NSString*)code codeVerifier : (
|
|
25
|
+
NSString*)codeVerifier redirectUri : (NSString*)redirectUri resolve : (RCTPromiseResolveBlock)
|
|
26
|
+
resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
27
|
+
[[self manager] issueCertTokenWithCode:code
|
|
28
|
+
codeVerifier:codeVerifier
|
|
29
|
+
redirectUri:redirectUri
|
|
30
|
+
resolve:resolve
|
|
31
|
+
reject:reject];
|
|
32
|
+
}
|
|
33
|
+
RCT_EXPORT_METHOD(publicKey : (NSString*)certType resolve : (RCTPromiseResolveBlock)
|
|
34
|
+
resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
35
|
+
[[self manager] publicKey:certType resolve:resolve reject:reject];
|
|
36
|
+
}
|
|
37
|
+
RCT_EXPORT_METHOD(sessionInfo : (NSString*)certType resolve : (RCTPromiseResolveBlock)
|
|
38
|
+
resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
39
|
+
[[self manager] sessionInfo:certType resolve:resolve reject:reject];
|
|
40
|
+
}
|
|
41
|
+
RCT_EXPORT_METHOD(fetchSessionInfo : (NSString*)certType txId : (NSString*)txId resolve : (
|
|
42
|
+
RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
43
|
+
[[self manager] fetchSessionInfo:certType txId:txId resolve:resolve reject:reject];
|
|
44
|
+
}
|
|
45
|
+
RCT_EXPORT_METHOD(fetchSessionInfoByAppKey : (NSString*)certType txId : (NSString*)
|
|
46
|
+
txId targetAppKey : (NSString*)targetAppKey resolve : (RCTPromiseResolveBlock)
|
|
47
|
+
resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
48
|
+
[[self manager] fetchSessionInfoByAppKey:certType
|
|
49
|
+
txId:txId
|
|
50
|
+
targetAppKey:targetAppKey
|
|
51
|
+
resolve:resolve
|
|
52
|
+
reject:reject];
|
|
53
|
+
}
|
|
54
|
+
RCT_EXPORT_METHOD(isValidSession : (NSString*)certType resolve : (RCTPromiseResolveBlock)
|
|
55
|
+
resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
56
|
+
[[self manager] isValidSession:certType resolve:resolve reject:reject];
|
|
57
|
+
}
|
|
58
|
+
RCT_EXPORT_METHOD(deleteKeyPair : (NSString*)certType resolve : (RCTPromiseResolveBlock)
|
|
59
|
+
resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
60
|
+
[[self manager] deleteKeyPair:certType resolve:resolve reject:reject];
|
|
61
|
+
}
|
|
62
|
+
RCT_EXPORT_METHOD(reducedSign : (NSString*)certType data : (NSString*)data resolve : (
|
|
63
|
+
RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
64
|
+
[[self manager] reducedSign:certType data:data resolve:resolve reject:reject];
|
|
65
|
+
}
|
|
66
|
+
RCT_EXPORT_METHOD(isKakaoTalkSignAvailable : (RCTPromiseResolveBlock)
|
|
67
|
+
resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
68
|
+
[[self manager] isKakaoTalkSignAvailable:resolve reject:reject];
|
|
69
|
+
}
|
|
70
|
+
RCT_EXPORT_METHOD(signWithKakaoTalk : (NSString*)txId targetAppKey : (NSString*)
|
|
71
|
+
targetAppKey resolve : (RCTPromiseResolveBlock)
|
|
72
|
+
resolve reject : (RCTPromiseRejectBlock)reject) {
|
|
73
|
+
[[self manager] signWithKakaoTalk:txId targetAppKey:targetAppKey resolve:resolve reject:reject];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
77
|
+
(const facebook::react::ObjCTurboModule::InitParams&)params {
|
|
78
|
+
return std::make_shared<facebook::react::NativeKakaoCertSpecJSI>(params);
|
|
79
|
+
}
|
|
80
|
+
@end
|