react-native-trustdevice 1.1.6 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Package.swift +35 -0
- package/README.md +55 -20
- package/android/src/main/java/com/trustdevice/TrustdeviceModule.java +66 -0
- package/android/src/main/java/com/trustdevice/TrustdeviceSeModule.java +32 -9
- package/android/src/main/java/com/trustdevice/TrustdeviceUiBridge.java +125 -0
- package/index.d.ts +40 -0
- package/index.js +2 -0
- package/ios/TrustDevice.h +2 -2
- package/ios/TrustDevice.m +120 -25
- package/ios/TrustDeviceSe.h +2 -2
- package/ios/TrustDeviceSe.m +111 -62
- package/package.json +6 -1
- package/react-native.config.js +10 -0
- package/src/TrustDevice.android.js +2 -1
- package/src/TrustDevice.ios.js +3 -3
package/Package.swift
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// swift-tools-version: 6.0
|
|
2
|
+
|
|
3
|
+
import PackageDescription
|
|
4
|
+
|
|
5
|
+
// React Native 0.88 links this package from
|
|
6
|
+
// ios/build/generated/autolinking/libs/ReactNativeTrustDevice. These relative
|
|
7
|
+
// paths point to the React Native packages generated by `react-native spm`.
|
|
8
|
+
let package = Package(
|
|
9
|
+
name: "ReactNativeTrustDevice",
|
|
10
|
+
platforms: [.iOS("15.1")],
|
|
11
|
+
products: [
|
|
12
|
+
.library(name: "ReactNativeTrustDevice", targets: ["ReactNativeTrustDevice"]),
|
|
13
|
+
],
|
|
14
|
+
dependencies: [
|
|
15
|
+
.package(name: "ReactNative", path: "../../../../xcframeworks"),
|
|
16
|
+
.package(name: "React-GeneratedCode", path: "../../../ios"),
|
|
17
|
+
.package(url: "https://github.com/trustdecision/trustdevice-pro-ios.git", from: "5.3.3"),
|
|
18
|
+
],
|
|
19
|
+
targets: [
|
|
20
|
+
.target(
|
|
21
|
+
name: "ReactNativeTrustDevice",
|
|
22
|
+
dependencies: [
|
|
23
|
+
.product(name: "ReactHeaders", package: "ReactNative"),
|
|
24
|
+
.product(name: "ReactNativeHeaders", package: "ReactNative"),
|
|
25
|
+
.product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"),
|
|
26
|
+
.product(name: "ReactAppHeaders", package: "React-GeneratedCode"),
|
|
27
|
+
.product(name: "TrustDecisionPro", package: "trustdevice-pro-ios"),
|
|
28
|
+
],
|
|
29
|
+
path: "ios",
|
|
30
|
+
sources: ["TrustDevice.m", "TrustDeviceSe.m"],
|
|
31
|
+
publicHeadersPath: ".",
|
|
32
|
+
linkerSettings: [.unsafeFlags(["-Xlinker", "-ObjC"]) ]
|
|
33
|
+
),
|
|
34
|
+
]
|
|
35
|
+
)
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Please note that when integrating SDK products provided by the TrustDecision in
|
|
|
20
20
|
|
|
21
21
|
| | Android | iOS |
|
|
22
22
|
| ------------------------- | ------------------------------------ | :----------------- |
|
|
23
|
-
| Supported System Versions | Android 5.0 and above | iOS
|
|
23
|
+
| Supported System Versions | Android 5.0 and above | iOS 17.6 and above with the RN 0.88 SPM example (check the native SDK minimum for your own app) |
|
|
24
24
|
| Supported Architectures | armeabi-v7a, arm64-v8a, x86 | armv7,arm64,x86_64 |
|
|
25
25
|
|
|
26
26
|
# Integrate
|
|
@@ -32,32 +32,44 @@ Please note that when integrating SDK products provided by the TrustDecision in
|
|
|
32
32
|
Please execute in your react native project root directory
|
|
33
33
|
|
|
34
34
|
```shell
|
|
35
|
-
npm install --save react-native-trustdevice
|
|
35
|
+
npm install --save react-native-trustdevice
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
### iOS
|
|
38
|
+
### iOS (React Native 0.88.1, Swift Package Manager)
|
|
39
39
|
|
|
40
|
-
The
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
1. Open `ios/<YourApp>.xcworkspace`.
|
|
45
|
-
2. Select **File > Add Package Dependencies...**.
|
|
46
|
-
3. Enter `https://github.com/trustdecision/TDBehavior_spm`.
|
|
47
|
-
4. Select **Exact Version** and enter `1.5.2`.
|
|
48
|
-
5. Add the `TDBehavior` product to the host application target. Do not add it
|
|
49
|
-
to the Pods project or a Pods target.
|
|
50
|
-
|
|
51
|
-
This app-target dependency cannot be declared by the plugin podspec. It is a
|
|
52
|
-
one-time host project setting and remains in the Xcode project after subsequent
|
|
53
|
-
`npm install` and `pod install` commands. CI can resolve it with:
|
|
40
|
+
The plugin contains a `Package.swift` that links the React Native bridge to
|
|
41
|
+
`TrustDecisionPro` (5.3.3 or later). `TDBehavior` is not included by default.
|
|
42
|
+
In an RN 0.88.1
|
|
43
|
+
SPM app, install the npm package, then run the RN SPM migration in the host app:
|
|
54
44
|
|
|
55
45
|
```shell
|
|
56
|
-
|
|
57
|
-
-workspace ios/<YourApp>.xcworkspace \
|
|
58
|
-
-scheme <YourApp>
|
|
46
|
+
npx react-native spm add --deintegrate
|
|
59
47
|
```
|
|
60
48
|
|
|
49
|
+
Open the generated Xcode project and build the app. The RN SPM autolinker
|
|
50
|
+
discovers this plugin's `Package.swift`; customers do not need to add a second
|
|
51
|
+
Swift package for the bridge manually. The fingerprint SDK is declared
|
|
52
|
+
in the bridge manifest. Run `npx react-native spm update` after changing native
|
|
53
|
+
dependencies. RN 0.88's SPM integration is experimental; use Xcode and Node
|
|
54
|
+
versions supported by RN 0.88.1 (Node 22.13+).
|
|
55
|
+
|
|
56
|
+
The example app keeps a comment-only `ios/Podfile` solely because CLI 20.2
|
|
57
|
+
uses that filename to detect an iOS project. It is not a CocoaPods integration.
|
|
58
|
+
|
|
59
|
+
The legacy `react-native-trustdevice.podspec` remains for existing CocoaPods
|
|
60
|
+
hosts. Do not link the SDK through both CocoaPods and SPM in the same target.
|
|
61
|
+
The native CocoaPods distribution is no longer maintained, so new iOS projects
|
|
62
|
+
should use the SPM path above.
|
|
63
|
+
|
|
64
|
+
### iOS behavior collection (optional)
|
|
65
|
+
|
|
66
|
+
Only if your app calls `start`, `stop`, or `collect`, add
|
|
67
|
+
`https://github.com/trustdecision/TDBehavior_spm` in Xcode via **File > Add
|
|
68
|
+
Package Dependencies...**. Select **Exact Version** `1.5.2` and add the
|
|
69
|
+
`TDBehavior` product to the host App target. Do not add it to the plugin's
|
|
70
|
+
`Package.swift` or link it a second time through CocoaPods. Fingerprint APIs
|
|
71
|
+
such as `getBlackBoxAsync` and `getDeviceInfoAsync` do not require this package.
|
|
72
|
+
|
|
61
73
|
### Android behavior collection dependency
|
|
62
74
|
|
|
63
75
|
The plugin does not bundle the Android behavior collection SDK. If behavior
|
|
@@ -73,6 +85,29 @@ dependencies {
|
|
|
73
85
|
Then rebuild the native application. Adding or removing this dependency cannot
|
|
74
86
|
be applied through Metro hot reload.
|
|
75
87
|
|
|
88
|
+
### Device information and verification UI
|
|
89
|
+
|
|
90
|
+
`TrustDevice` is the enterprise module (the package's default export), and
|
|
91
|
+
`TrustDeviceSe` is the standard module (named export). Both expose
|
|
92
|
+
`getDeviceInfo()` and `getDeviceInfoAsync()` as Promise methods returning
|
|
93
|
+
`blackBox`, `fpVersion`, `anonymousId`, `deviceRiskScore`, `sealedResult`, and
|
|
94
|
+
`apiStatus: {code, message}`. The standard iOS SDK has only a callback API, so
|
|
95
|
+
both methods use that asynchronous native call. Call them after initialization.
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
import TrustDevice, {TrustDeviceSe} from 'react-native-trustdevice';
|
|
99
|
+
|
|
100
|
+
const info = await TrustDevice.getDeviceInfoAsync();
|
|
101
|
+
// For a standard-edition integration:
|
|
102
|
+
// const info = await TrustDeviceSe.getDeviceInfoAsync();
|
|
103
|
+
|
|
104
|
+
const captcha = await TrustDevice.showCaptcha();
|
|
105
|
+
// captcha.function is onSuccess or onFailed; onReady is emitted as
|
|
106
|
+
// a TrustDeviceCaptcha event (TrustDeviceSeCaptcha for the standard module).
|
|
107
|
+
const liveness = await TrustDevice.showLiveness({license: 'YOUR_LICENSE'});
|
|
108
|
+
// liveness.function is onSuccess or onFailed.
|
|
109
|
+
```
|
|
110
|
+
|
|
76
111
|
### AndroidManifest.xml
|
|
77
112
|
|
|
78
113
|
Declare the following permissions in the AndroidManifest.xml file under the application module
|
|
@@ -18,6 +18,9 @@ import com.trustdecision.mobrisk.TDRisk;
|
|
|
18
18
|
import com.trustdecision.mobrisk.TDRiskCallback;
|
|
19
19
|
import com.trustdecision.mobrisk.TDAPISignResult;
|
|
20
20
|
import com.trustdecision.mobrisk.TDBehaviorResult;
|
|
21
|
+
import com.trustdecision.mobrisk.TDDeviceInfo;
|
|
22
|
+
import com.trustdecision.mobrisk.TDDeviceInfoCallbackAdapter;
|
|
23
|
+
import com.trustdecision.mobrisk.TDDeviceAPIStatus;
|
|
21
24
|
|
|
22
25
|
public class TrustdeviceModule extends ReactContextBaseJavaModule {
|
|
23
26
|
private final ReactApplicationContext reactContext;
|
|
@@ -74,6 +77,69 @@ public class TrustdeviceModule extends ReactContextBaseJavaModule {
|
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
79
|
|
|
80
|
+
private WritableMap deviceInfoResult(TDDeviceInfo info) {
|
|
81
|
+
WritableMap result = Arguments.createMap();
|
|
82
|
+
TDDeviceAPIStatus status = info.getApiStatus();
|
|
83
|
+
int code = status == null ? -1 : status.getCode();
|
|
84
|
+
String message = status == null ? "SDK returned no API status" : status.getMessage();
|
|
85
|
+
WritableMap apiStatus = Arguments.createMap();
|
|
86
|
+
apiStatus.putInt("code", code);
|
|
87
|
+
apiStatus.putString("message", message);
|
|
88
|
+
result.putString("blackBox", info.getBlackBox());
|
|
89
|
+
result.putString("fpVersion", info.getFpVersion());
|
|
90
|
+
result.putString("anonymousId", info.getAnonymousId());
|
|
91
|
+
result.putInt("deviceRiskScore", info.getDeviceRiskScore());
|
|
92
|
+
result.putString("sealedResult", info.getSealedResult());
|
|
93
|
+
result.putMap("apiStatus", apiStatus);
|
|
94
|
+
result.putInt("code", code);
|
|
95
|
+
result.putString("msg", message);
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@ReactMethod
|
|
100
|
+
public void getDeviceInfo(Promise promise) {
|
|
101
|
+
new Thread(() -> {
|
|
102
|
+
try {
|
|
103
|
+
TDDeviceInfo info = TDRisk.getDeviceInfo();
|
|
104
|
+
if (info == null) {
|
|
105
|
+
promise.reject("device_info_unavailable", "SDK returned null device info");
|
|
106
|
+
} else {
|
|
107
|
+
promise.resolve(deviceInfoResult(info));
|
|
108
|
+
}
|
|
109
|
+
} catch (Exception e) {
|
|
110
|
+
promise.reject("getDeviceInfo Error", e);
|
|
111
|
+
}
|
|
112
|
+
}, "TrustDevice-getDeviceInfo").start();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@ReactMethod
|
|
116
|
+
public void getDeviceInfoAsync(Promise promise) {
|
|
117
|
+
try {
|
|
118
|
+
TDRisk.getDeviceInfo(new TDDeviceInfoCallbackAdapter() {
|
|
119
|
+
@Override
|
|
120
|
+
public void onResult(TDDeviceInfo info) {
|
|
121
|
+
if (info == null) {
|
|
122
|
+
promise.reject("device_info_unavailable", "SDK returned null device info");
|
|
123
|
+
} else {
|
|
124
|
+
promise.resolve(deviceInfoResult(info));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
} catch (Exception e) {
|
|
129
|
+
promise.reject("getDeviceInfoAsync Error", e);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@ReactMethod
|
|
134
|
+
public void showCaptcha(Promise promise) {
|
|
135
|
+
TrustdeviceUiBridge.showCaptcha(reactContext, "TrustDeviceCaptcha", promise);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@ReactMethod
|
|
139
|
+
public void showLiveness(ReadableMap options, Promise promise) {
|
|
140
|
+
TrustdeviceUiBridge.showLiveness(reactContext, options, promise);
|
|
141
|
+
}
|
|
142
|
+
|
|
77
143
|
@ReactMethod
|
|
78
144
|
public void sign(String path, Promise promise) {
|
|
79
145
|
try {
|
|
@@ -38,11 +38,17 @@ public class TrustdeviceSeModule extends ReactContextBaseJavaModule {
|
|
|
38
38
|
|
|
39
39
|
@ReactMethod
|
|
40
40
|
public void initWithOptions(ReadableMap readableMap, Promise promise) {
|
|
41
|
-
if (readableMap
|
|
41
|
+
if (readableMap == null) {
|
|
42
|
+
promise.reject("initWithOptions Error", "options must not be null");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
42
46
|
HashMap<String, Object> options = readableMap.toHashMap();
|
|
43
47
|
TDDeviceManager.Builder builder = TDUniRiskUtils.mapToBuilderSe(options);
|
|
44
48
|
TDDeviceManager.initWithOptions(this.reactContext.getApplicationContext(), builder);
|
|
45
49
|
promise.resolve(null);
|
|
50
|
+
} catch (Exception e) {
|
|
51
|
+
promise.reject("initWithOptions Error", e);
|
|
46
52
|
}
|
|
47
53
|
}
|
|
48
54
|
|
|
@@ -79,18 +85,20 @@ public class TrustdeviceSeModule extends ReactContextBaseJavaModule {
|
|
|
79
85
|
// deviceRiskScore: 设备风险分数
|
|
80
86
|
// apiStatus: API状态信息
|
|
81
87
|
// sealedResult: 密封结果
|
|
82
|
-
int code = apiStatus.getCode();
|
|
83
|
-
|
|
84
|
-
// 创建 WritableMap 来返回结构化数据
|
|
85
88
|
WritableMap resultMap = Arguments.createMap();
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
int code = apiStatus == null ? -1 : apiStatus.getCode();
|
|
90
|
+
String message = apiStatus == null ? "SDK returned no API status" : apiStatus.getMessage();
|
|
91
|
+
WritableMap statusMap = Arguments.createMap();
|
|
92
|
+
statusMap.putInt("code", code);
|
|
93
|
+
statusMap.putString("message", message);
|
|
94
|
+
resultMap.putInt("code", code);
|
|
88
95
|
resultMap.putString("fpVersion", fpVersion);
|
|
89
96
|
resultMap.putString("blackBox", blackBox);
|
|
90
97
|
resultMap.putString("anonymousId", anonymousId);
|
|
91
98
|
resultMap.putInt("deviceRiskScore", deviceRiskScore);
|
|
92
99
|
resultMap.putString("sealedResult", sealedResult);
|
|
93
|
-
resultMap.
|
|
100
|
+
resultMap.putMap("apiStatus", statusMap);
|
|
101
|
+
resultMap.putString("msg", message);
|
|
94
102
|
|
|
95
103
|
promise.resolve(resultMap);
|
|
96
104
|
}
|
|
@@ -101,6 +109,21 @@ public class TrustdeviceSeModule extends ReactContextBaseJavaModule {
|
|
|
101
109
|
}
|
|
102
110
|
}
|
|
103
111
|
|
|
112
|
+
@ReactMethod
|
|
113
|
+
public void getDeviceInfoAsync(Promise promise) {
|
|
114
|
+
getDeviceInfo(promise);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@ReactMethod
|
|
118
|
+
public void showCaptcha(Promise promise) {
|
|
119
|
+
TrustdeviceUiBridge.showCaptcha(reactContext, "TrustDeviceSeCaptcha", promise);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@ReactMethod
|
|
123
|
+
public void showLiveness(ReadableMap options, Promise promise) {
|
|
124
|
+
TrustdeviceUiBridge.showLiveness(reactContext, options, promise);
|
|
125
|
+
}
|
|
126
|
+
|
|
104
127
|
@ReactMethod
|
|
105
128
|
public void sign(String path, Promise promise) {
|
|
106
129
|
try {
|
|
@@ -120,7 +143,7 @@ public class TrustdeviceSeModule extends ReactContextBaseJavaModule {
|
|
|
120
143
|
|
|
121
144
|
@ReactMethod
|
|
122
145
|
public void getSDKVersion(Promise promise) {
|
|
123
|
-
String sdkVersion =
|
|
146
|
+
String sdkVersion = TDDeviceManager.getSDKVersion();
|
|
124
147
|
promise.resolve(sdkVersion);
|
|
125
148
|
}
|
|
126
|
-
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
package com.trustdevice;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.bridge.Arguments;
|
|
6
|
+
import com.facebook.react.bridge.Promise;
|
|
7
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
8
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
9
|
+
import com.facebook.react.bridge.UiThreadUtil;
|
|
10
|
+
import com.facebook.react.bridge.WritableMap;
|
|
11
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
12
|
+
import com.trustdecision.mobrisk.TDRisk;
|
|
13
|
+
import com.trustdecision.mobrisk.TDRiskCaptchaCallback;
|
|
14
|
+
import com.trustdecision.mobrisk.TDRiskLivenessCallback;
|
|
15
|
+
|
|
16
|
+
import org.json.JSONObject;
|
|
17
|
+
|
|
18
|
+
import java.util.Iterator;
|
|
19
|
+
|
|
20
|
+
final class TrustdeviceUiBridge {
|
|
21
|
+
private TrustdeviceUiBridge() {}
|
|
22
|
+
|
|
23
|
+
static void showCaptcha(ReactApplicationContext context, String eventName, Promise promise) {
|
|
24
|
+
UiThreadUtil.runOnUiThread(() -> {
|
|
25
|
+
Activity activity = context.getCurrentActivity();
|
|
26
|
+
if (activity == null) {
|
|
27
|
+
promise.reject("captcha_no_activity", "No active Activity");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
TDRisk.showCaptcha(activity, new TDRiskCaptchaCallback() {
|
|
32
|
+
@Override
|
|
33
|
+
public void onReady() {
|
|
34
|
+
WritableMap ready = Arguments.createMap();
|
|
35
|
+
ready.putString("function", "onReady");
|
|
36
|
+
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
37
|
+
.emit(eventName, ready);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Override
|
|
41
|
+
public void onSuccess(String token) {
|
|
42
|
+
WritableMap result = Arguments.createMap();
|
|
43
|
+
result.putString("function", "onSuccess");
|
|
44
|
+
result.putString("token", token);
|
|
45
|
+
promise.resolve(result);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Override
|
|
49
|
+
public void onFailed(int code, String message) {
|
|
50
|
+
WritableMap result = Arguments.createMap();
|
|
51
|
+
result.putString("function", "onFailed");
|
|
52
|
+
result.putInt("errorCode", code);
|
|
53
|
+
result.putString("errorMsg", message);
|
|
54
|
+
promise.resolve(result);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
} catch (Exception e) {
|
|
58
|
+
promise.reject("showCaptcha Error", e);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static void showLiveness(ReactApplicationContext context, ReadableMap options, Promise promise) {
|
|
64
|
+
UiThreadUtil.runOnUiThread(() -> {
|
|
65
|
+
Activity activity = context.getCurrentActivity();
|
|
66
|
+
if (activity == null) {
|
|
67
|
+
promise.reject("liveness_no_activity", "No active Activity");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
String license = options != null && options.hasKey("license") && !options.isNull("license")
|
|
71
|
+
? options.getString("license") : null;
|
|
72
|
+
try {
|
|
73
|
+
TDRisk.showLiveness(activity, license, new TDRiskLivenessCallback() {
|
|
74
|
+
@Override
|
|
75
|
+
public void onSuccess(String json) {
|
|
76
|
+
WritableMap result = jsonResult(json);
|
|
77
|
+
result.putString("function", "onSuccess");
|
|
78
|
+
promise.resolve(result);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@Override
|
|
82
|
+
public void onError(String errorCode, String errorMsg, String sequenceId) {
|
|
83
|
+
WritableMap result = Arguments.createMap();
|
|
84
|
+
result.putString("function", "onFailed");
|
|
85
|
+
try {
|
|
86
|
+
result.putInt("code", Integer.parseInt(errorCode));
|
|
87
|
+
} catch (NumberFormatException ignored) {
|
|
88
|
+
result.putString("code", errorCode);
|
|
89
|
+
}
|
|
90
|
+
result.putString("message", errorMsg);
|
|
91
|
+
result.putString("sequence_id", sequenceId);
|
|
92
|
+
result.putString("liveness_id", "");
|
|
93
|
+
promise.resolve(result);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
} catch (Exception e) {
|
|
97
|
+
promise.reject("showLiveness Error", e);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private static WritableMap jsonResult(String json) {
|
|
103
|
+
WritableMap result = Arguments.createMap();
|
|
104
|
+
try {
|
|
105
|
+
JSONObject object = new JSONObject(json);
|
|
106
|
+
Iterator<String> keys = object.keys();
|
|
107
|
+
while (keys.hasNext()) {
|
|
108
|
+
String key = keys.next();
|
|
109
|
+
Object value = object.opt(key);
|
|
110
|
+
if (value instanceof Boolean) {
|
|
111
|
+
result.putBoolean(key, (Boolean) value);
|
|
112
|
+
} else if (value instanceof Number) {
|
|
113
|
+
result.putDouble(key, ((Number) value).doubleValue());
|
|
114
|
+
} else if (value == JSONObject.NULL) {
|
|
115
|
+
result.putNull(key);
|
|
116
|
+
} else if (value != null) {
|
|
117
|
+
result.putString(key, String.valueOf(value));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} catch (Exception ignored) {
|
|
121
|
+
result.putString("raw", json);
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -10,18 +10,58 @@ export interface TDBehaviorResult {
|
|
|
10
10
|
msg: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
export interface TDDeviceInfoResult {
|
|
14
|
+
blackBox: string;
|
|
15
|
+
fpVersion: string;
|
|
16
|
+
anonymousId: string;
|
|
17
|
+
deviceRiskScore: number;
|
|
18
|
+
sealedResult: string;
|
|
19
|
+
apiStatus: {code: number; message: string};
|
|
20
|
+
code: number;
|
|
21
|
+
msg: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type TDCaptchaResult =
|
|
25
|
+
| {function: 'onSuccess'; token: string}
|
|
26
|
+
| {function: 'onFailed'; errorCode: number; errorMsg: string};
|
|
27
|
+
|
|
28
|
+
export interface TDLivenessResult {
|
|
29
|
+
function: 'onSuccess' | 'onFailed';
|
|
30
|
+
code?: number | string;
|
|
31
|
+
message?: string;
|
|
32
|
+
sequence_id?: string;
|
|
33
|
+
liveness_id?: string;
|
|
34
|
+
image?: string;
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
|
|
13
38
|
export interface TrustDeviceModule {
|
|
14
39
|
initWithOptions(options: Record<string, unknown>): Promise<void> | void;
|
|
15
40
|
getSDKVersion(): Promise<string>;
|
|
16
41
|
getBlackBox(): Promise<string>;
|
|
17
42
|
getBlackBoxAsync(): Promise<string>;
|
|
43
|
+
getDeviceInfo(): Promise<TDDeviceInfoResult>;
|
|
44
|
+
getDeviceInfoAsync(): Promise<TDDeviceInfoResult>;
|
|
18
45
|
sign(path: string): Promise<TDSignResult>;
|
|
46
|
+
showCaptcha(): Promise<TDCaptchaResult>;
|
|
47
|
+
showLiveness(options: {license?: string; showStyle?: 'present' | 'push'}): Promise<TDLivenessResult>;
|
|
19
48
|
start(): Promise<void>;
|
|
20
49
|
stop(): Promise<void>;
|
|
21
50
|
collect(): Promise<TDBehaviorResult>;
|
|
22
51
|
}
|
|
23
52
|
|
|
53
|
+
export interface TrustDeviceSeModule {
|
|
54
|
+
initWithOptions(options: Record<string, unknown>): Promise<void> | void;
|
|
55
|
+
getSDKVersion(): Promise<string>;
|
|
56
|
+
getDeviceInfo(): Promise<TDDeviceInfoResult>;
|
|
57
|
+
getDeviceInfoAsync(): Promise<TDDeviceInfoResult>;
|
|
58
|
+
sign(path: string): Promise<TDSignResult>;
|
|
59
|
+
showCaptcha(): Promise<TDCaptchaResult>;
|
|
60
|
+
showLiveness(options: {license?: string; showStyle?: 'present' | 'push'}): Promise<TDLivenessResult>;
|
|
61
|
+
}
|
|
62
|
+
|
|
24
63
|
declare const TrustDevice: TrustDeviceModule;
|
|
25
64
|
|
|
26
65
|
export {TrustDevice};
|
|
66
|
+
export const TrustDeviceSe: TrustDeviceSeModule;
|
|
27
67
|
export default TrustDevice;
|
package/index.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
// export once and preserve all existing public import styles.
|
|
4
4
|
const platformModule = require('./src/TrustDevice');
|
|
5
5
|
const TrustDevice = platformModule.default || platformModule;
|
|
6
|
+
const TrustDeviceSe = platformModule.TrustDeviceSe;
|
|
6
7
|
|
|
7
8
|
module.exports = TrustDevice;
|
|
8
9
|
module.exports.default = TrustDevice;
|
|
9
10
|
module.exports.TrustDevice = TrustDevice;
|
|
11
|
+
module.exports.TrustDeviceSe = TrustDeviceSe;
|
package/ios/TrustDevice.h
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
//
|
|
7
7
|
|
|
8
8
|
#import <Foundation/Foundation.h>
|
|
9
|
-
#import <React/
|
|
9
|
+
#import <React/RCTEventEmitter.h>
|
|
10
10
|
|
|
11
11
|
NS_ASSUME_NONNULL_BEGIN
|
|
12
12
|
|
|
13
|
-
@interface TrustDevice :
|
|
13
|
+
@interface TrustDevice : RCTEventEmitter <RCTBridgeModule>
|
|
14
14
|
|
|
15
15
|
@end
|
|
16
16
|
|
package/ios/TrustDevice.m
CHANGED
|
@@ -10,10 +10,31 @@
|
|
|
10
10
|
#import <React/RCTConvert.h>
|
|
11
11
|
#import <TDMobRisk/TDMobRisk.h>
|
|
12
12
|
|
|
13
|
+
static NSString *TDString(const char *value) {
|
|
14
|
+
return value ? ([NSString stringWithUTF8String:value] ?: @"") : @"";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static NSDictionary *TDDeviceInfoDictionary(TDDeviceResponse response) {
|
|
18
|
+
NSString *message = TDString(response.apiStatus.message);
|
|
19
|
+
return @{
|
|
20
|
+
@"blackBox": TDString(response.blackBox),
|
|
21
|
+
@"fpVersion": TDString(response.fpVersion),
|
|
22
|
+
@"anonymousId": TDString(response.anonymousId),
|
|
23
|
+
@"deviceRiskScore": @(response.deviceRiskScore),
|
|
24
|
+
@"sealedResult": TDString(response.sealedResult),
|
|
25
|
+
@"apiStatus": @{ @"code": @(response.apiStatus.code), @"message": message },
|
|
26
|
+
@"code": @(response.apiStatus.code),
|
|
27
|
+
@"msg": message,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
13
31
|
@implementation TrustDevice
|
|
14
32
|
|
|
15
33
|
RCT_EXPORT_MODULE();
|
|
16
34
|
|
|
35
|
+
- (NSArray<NSString *> *)supportedEvents {
|
|
36
|
+
return @[@"TrustDeviceCaptcha"];
|
|
37
|
+
}
|
|
17
38
|
|
|
18
39
|
RCT_REMAP_METHOD(getSDKVersion,
|
|
19
40
|
getSDKVersionResolver:(RCTPromiseResolveBlock)resolve
|
|
@@ -26,21 +47,22 @@ RCT_REMAP_METHOD(getSDKVersion,
|
|
|
26
47
|
|
|
27
48
|
RCT_EXPORT_METHOD(initWithOptions:(NSDictionary*)options)
|
|
28
49
|
{
|
|
29
|
-
NSMutableDictionary*
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
id debugValue = options[@"debug"];
|
|
33
|
-
if (debugValue && debugValue != [NSNull null]) {
|
|
34
|
-
mutableOptions[@"allowd"] = debugValue; // 原逻辑保留
|
|
35
|
-
} else {
|
|
36
|
-
// debug 为空时,可能设置默认值或不设置
|
|
37
|
-
mutableOptions[@"allowd"] = @(NO); // 示例默认 false
|
|
50
|
+
NSMutableDictionary *mutableOptions = [options mutableCopy];
|
|
51
|
+
if ([options[@"debug"] isKindOfClass:[NSNumber class]] && [options[@"debug"] boolValue]) {
|
|
52
|
+
mutableOptions[@"allowed"] = @"allowed";
|
|
38
53
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
|
|
54
|
+
if ([options[@"location"] isKindOfClass:[NSNumber class]] && ![options[@"location"] boolValue]) {
|
|
55
|
+
mutableOptions[@"noLocation"] = @"noLocation";
|
|
56
|
+
}
|
|
57
|
+
if ([options[@"IDFA"] isKindOfClass:[NSNumber class]] && ![options[@"IDFA"] boolValue]) {
|
|
58
|
+
mutableOptions[@"noIDFA"] = @"noIDFA";
|
|
59
|
+
}
|
|
60
|
+
if ([options[@"deviceName"] isKindOfClass:[NSNumber class]] && ![options[@"deviceName"] boolValue]) {
|
|
61
|
+
mutableOptions[@"noDeviceName"] = @"noDeviceName";
|
|
62
|
+
}
|
|
63
|
+
NSString *dataCenter = options[@"dataCenter"];
|
|
64
|
+
if ([dataCenter isKindOfClass:[NSString class]] && dataCenter.length > 0) {
|
|
65
|
+
mutableOptions[@"country"] = dataCenter;
|
|
44
66
|
}
|
|
45
67
|
|
|
46
68
|
TDMobRiskManager_t *manager = [TDMobRiskManager sharedManager];
|
|
@@ -66,6 +88,35 @@ RCT_REMAP_METHOD(getBlackBoxAsync,
|
|
|
66
88
|
});
|
|
67
89
|
}
|
|
68
90
|
|
|
91
|
+
RCT_REMAP_METHOD(getDeviceInfo,
|
|
92
|
+
getDeviceInfoResolver:(RCTPromiseResolveBlock)resolve
|
|
93
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
94
|
+
{
|
|
95
|
+
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
|
|
96
|
+
TDMobRiskManager_t *manager = [TDMobRiskManager sharedManager];
|
|
97
|
+
if (manager == NULL || manager->getDeviceInfoSync == NULL) {
|
|
98
|
+
reject(@"device_info_unavailable", @"getDeviceInfoSync is unavailable", nil);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
TDDeviceResponse response = manager->getDeviceInfoSync();
|
|
102
|
+
resolve(TDDeviceInfoDictionary(response));
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
RCT_REMAP_METHOD(getDeviceInfoAsync,
|
|
107
|
+
getDeviceInfoAsyncResolver:(RCTPromiseResolveBlock)resolve
|
|
108
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
109
|
+
{
|
|
110
|
+
TDMobRiskManager_t *manager = [TDMobRiskManager sharedManager];
|
|
111
|
+
if (manager == NULL || manager->getDeviceInfo == NULL) {
|
|
112
|
+
reject(@"device_info_unavailable", @"getDeviceInfo is unavailable", nil);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
manager->getDeviceInfo(^(TDDeviceResponse response) {
|
|
116
|
+
resolve(TDDeviceInfoDictionary(response));
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
69
120
|
RCT_EXPORT_METHOD(sign:(NSString*)path
|
|
70
121
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
71
122
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
@@ -188,32 +239,76 @@ RCT_REMAP_METHOD(showCaptcha,
|
|
|
188
239
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
189
240
|
{
|
|
190
241
|
TDMobRiskManager_t *manager = [TDMobRiskManager sharedManager];
|
|
191
|
-
|
|
242
|
+
if (manager == NULL || manager->showCaptcha == NULL) {
|
|
243
|
+
reject(@"captcha_unavailable", @"showCaptcha is unavailable", nil);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
192
246
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
193
247
|
UIWindow *keyWindow = [self getKeyWindow];
|
|
248
|
+
if (keyWindow == nil) {
|
|
249
|
+
reject(@"captcha_no_window", @"No active application window", nil);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
194
252
|
manager->showCaptcha(keyWindow,^(TDShowCaptchaResultStruct resultStruct) {
|
|
195
|
-
|
|
253
|
+
NSDictionary *resultDictionary;
|
|
196
254
|
switch (resultStruct.resultType) {
|
|
197
255
|
case TDShowCaptchaResultTypeSuccess:
|
|
198
|
-
resultDictionary
|
|
199
|
-
resultDictionary[@"token"] = @(resultStruct.validateToken);
|
|
256
|
+
resultDictionary = @{ @"function": @"onSuccess", @"token": TDString(resultStruct.validateToken) };
|
|
200
257
|
break;
|
|
201
258
|
case TDShowCaptchaResultTypeFailed:
|
|
202
|
-
resultDictionary
|
|
203
|
-
|
|
204
|
-
resultDictionary[@"errorMsg"] = @(resultStruct.errorMsg);
|
|
205
|
-
break;
|
|
206
|
-
case TDShowCaptchaResultTypeReady:
|
|
207
|
-
resultDictionary[@"function"] = @"onReady";
|
|
259
|
+
resultDictionary = @{ @"function": @"onFailed", @"errorCode": @(resultStruct.errorCode),
|
|
260
|
+
@"errorMsg": TDString(resultStruct.errorMsg) };
|
|
208
261
|
break;
|
|
262
|
+
case TDShowCaptchaResultTypeReady: {
|
|
263
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
264
|
+
[self sendEventWithName:@"TrustDeviceCaptcha" body:@{ @"function": @"onReady" }];
|
|
265
|
+
});
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
209
268
|
default:
|
|
210
|
-
|
|
269
|
+
return;
|
|
211
270
|
}
|
|
212
271
|
resolve(resultDictionary);
|
|
213
272
|
});
|
|
214
273
|
});
|
|
215
274
|
}
|
|
216
275
|
|
|
276
|
+
RCT_REMAP_METHOD(showLiveness,
|
|
277
|
+
showLivenessWithOptions:(NSDictionary *)options
|
|
278
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
279
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
280
|
+
{
|
|
281
|
+
TDMobRiskManager_t *manager = [TDMobRiskManager sharedManager];
|
|
282
|
+
if (manager == NULL || manager->showLivenessWithShowStyle == NULL) {
|
|
283
|
+
reject(@"liveness_unavailable", @"showLiveness is unavailable", nil);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
288
|
+
UIViewController *controller = [self getKeyWindow].rootViewController;
|
|
289
|
+
while (controller.presentedViewController != nil) {
|
|
290
|
+
controller = controller.presentedViewController;
|
|
291
|
+
}
|
|
292
|
+
if (controller == nil) {
|
|
293
|
+
reject(@"liveness_no_controller", @"No active view controller", nil);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
NSString *license = [options[@"license"] isKindOfClass:[NSString class]] ? options[@"license"] : nil;
|
|
297
|
+
TDLivenessShowStyle style = [options[@"showStyle"] isEqual:@"push"]
|
|
298
|
+
? TDLivenessShowStylePush : TDLivenessShowStylePresent;
|
|
299
|
+
manager->showLivenessWithShowStyle(controller, license, style,
|
|
300
|
+
^(NSDictionary *success) {
|
|
301
|
+
NSMutableDictionary *result = [success mutableCopy] ?: [NSMutableDictionary dictionary];
|
|
302
|
+
result[@"function"] = @"onSuccess";
|
|
303
|
+
resolve(result);
|
|
304
|
+
},
|
|
305
|
+
^(NSDictionary *failure) {
|
|
306
|
+
NSMutableDictionary *result = [failure mutableCopy] ?: [NSMutableDictionary dictionary];
|
|
307
|
+
result[@"function"] = @"onFailed";
|
|
308
|
+
resolve(result);
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
}
|
|
217
312
|
|
|
218
313
|
|
|
219
314
|
|
package/ios/TrustDeviceSe.h
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
//
|
|
7
7
|
|
|
8
8
|
#import <Foundation/Foundation.h>
|
|
9
|
-
#import <React/
|
|
9
|
+
#import <React/RCTEventEmitter.h>
|
|
10
10
|
|
|
11
11
|
NS_ASSUME_NONNULL_BEGIN
|
|
12
12
|
|
|
13
|
-
@interface TrustDeviceSe :
|
|
13
|
+
@interface TrustDeviceSe : RCTEventEmitter <RCTBridgeModule>
|
|
14
14
|
|
|
15
15
|
@end
|
|
16
16
|
|
package/ios/TrustDeviceSe.m
CHANGED
|
@@ -10,10 +10,31 @@
|
|
|
10
10
|
#import <React/RCTConvert.h>
|
|
11
11
|
#import <TDMobRisk/TDMobRisk.h>
|
|
12
12
|
|
|
13
|
+
static NSString *TDSeString(const char *value) {
|
|
14
|
+
return value ? ([NSString stringWithUTF8String:value] ?: @"") : @"";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static NSDictionary *TDSeDeviceInfoDictionary(TDDeviceResponse response) {
|
|
18
|
+
NSString *message = TDSeString(response.apiStatus.message);
|
|
19
|
+
return @{
|
|
20
|
+
@"blackBox": TDSeString(response.blackBox),
|
|
21
|
+
@"fpVersion": TDSeString(response.fpVersion),
|
|
22
|
+
@"anonymousId": TDSeString(response.anonymousId),
|
|
23
|
+
@"deviceRiskScore": @(response.deviceRiskScore),
|
|
24
|
+
@"sealedResult": TDSeString(response.sealedResult),
|
|
25
|
+
@"apiStatus": @{ @"code": @(response.apiStatus.code), @"message": message },
|
|
26
|
+
@"code": @(response.apiStatus.code),
|
|
27
|
+
@"msg": message,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
13
31
|
@implementation TrustDeviceSe
|
|
14
32
|
|
|
15
33
|
RCT_EXPORT_MODULE();
|
|
16
34
|
|
|
35
|
+
- (NSArray<NSString *> *)supportedEvents {
|
|
36
|
+
return @[@"TrustDeviceSeCaptcha"];
|
|
37
|
+
}
|
|
17
38
|
|
|
18
39
|
RCT_REMAP_METHOD(getSDKVersion,
|
|
19
40
|
getSDKVersionResolver:(RCTPromiseResolveBlock)resolve
|
|
@@ -26,22 +47,23 @@ RCT_REMAP_METHOD(getSDKVersion,
|
|
|
26
47
|
|
|
27
48
|
RCT_EXPORT_METHOD(initWithOptions:(NSDictionary*)options)
|
|
28
49
|
{
|
|
29
|
-
NSMutableDictionary*
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
NSMutableDictionary *mutableOptions = [options mutableCopy];
|
|
51
|
+
if ([options[@"debug"] isKindOfClass:[NSNumber class]] && [options[@"debug"] boolValue]) {
|
|
52
|
+
mutableOptions[@"allowed"] = @"allowed";
|
|
53
|
+
}
|
|
54
|
+
if ([options[@"location"] isKindOfClass:[NSNumber class]] && ![options[@"location"] boolValue]) {
|
|
55
|
+
mutableOptions[@"noLocation"] = @"noLocation";
|
|
56
|
+
}
|
|
57
|
+
if ([options[@"IDFA"] isKindOfClass:[NSNumber class]] && ![options[@"IDFA"] boolValue]) {
|
|
58
|
+
mutableOptions[@"noIDFA"] = @"noIDFA";
|
|
59
|
+
}
|
|
60
|
+
if ([options[@"deviceName"] isKindOfClass:[NSNumber class]] && ![options[@"deviceName"] boolValue]) {
|
|
61
|
+
mutableOptions[@"noDeviceName"] = @"noDeviceName";
|
|
62
|
+
}
|
|
63
|
+
NSString *dataCenter = options[@"dataCenter"];
|
|
64
|
+
if ([dataCenter isKindOfClass:[NSString class]] && dataCenter.length > 0) {
|
|
65
|
+
mutableOptions[@"country"] = dataCenter;
|
|
66
|
+
}
|
|
45
67
|
|
|
46
68
|
TDDeviceManager_t *manager = [TDDeviceManager sharedManager];
|
|
47
69
|
manager->initWithOptions([mutableOptions copy]);
|
|
@@ -51,41 +73,25 @@ RCT_REMAP_METHOD(getDeviceInfo,
|
|
|
51
73
|
getDeviceInfoResolver:(RCTPromiseResolveBlock)resolve
|
|
52
74
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
53
75
|
{
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
} else {
|
|
74
|
-
message = response.apiStatus.message ? [NSString stringWithUTF8String:response.apiStatus.message] : @"";
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// 创建结果字典
|
|
78
|
-
NSMutableDictionary *resultDict = [NSMutableDictionary dictionary];
|
|
79
|
-
resultDict[@"code"] = @(code);
|
|
80
|
-
resultDict[@"blackBox"] = blackBox;
|
|
81
|
-
resultDict[@"fpVersion"] = fpVersion;
|
|
82
|
-
resultDict[@"anonymousId"] = anonymousId;
|
|
83
|
-
resultDict[@"sealedResult"] = sealedResult;
|
|
84
|
-
resultDict[@"deviceRiskScore"] = @(deviceRiskScore);
|
|
85
|
-
resultDict[@"msg"] = message;
|
|
86
|
-
|
|
87
|
-
resolve(resultDict);
|
|
88
|
-
});
|
|
76
|
+
[self resolveDeviceInfo:resolve rejecter:reject];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
RCT_REMAP_METHOD(getDeviceInfoAsync,
|
|
80
|
+
getDeviceInfoAsyncResolver:(RCTPromiseResolveBlock)resolve
|
|
81
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
82
|
+
{
|
|
83
|
+
[self resolveDeviceInfo:resolve rejecter:reject];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
- (void)resolveDeviceInfo:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
|
87
|
+
TDDeviceManager_t *manager = [TDDeviceManager sharedManager];
|
|
88
|
+
if (manager == NULL || manager->getDeviceInfo == NULL) {
|
|
89
|
+
reject(@"device_info_unavailable", @"getDeviceInfo is unavailable", nil);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
manager->getDeviceInfo(^(TDDeviceResponse response) {
|
|
93
|
+
resolve(TDSeDeviceInfoDictionary(response));
|
|
94
|
+
});
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
RCT_EXPORT_METHOD(sign:(NSString*)path
|
|
@@ -144,32 +150,75 @@ RCT_REMAP_METHOD(showCaptcha,
|
|
|
144
150
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
145
151
|
{
|
|
146
152
|
TDMobRiskManager_t *manager = [TDMobRiskManager sharedManager];
|
|
147
|
-
|
|
153
|
+
if (manager == NULL || manager->showCaptcha == NULL) {
|
|
154
|
+
reject(@"captcha_unavailable", @"showCaptcha is unavailable", nil);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
148
157
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
149
158
|
UIWindow *keyWindow = [self getKeyWindow];
|
|
159
|
+
if (keyWindow == nil) {
|
|
160
|
+
reject(@"captcha_no_window", @"No active application window", nil);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
150
163
|
manager->showCaptcha(keyWindow,^(TDShowCaptchaResultStruct resultStruct) {
|
|
151
|
-
|
|
164
|
+
NSDictionary *resultDictionary;
|
|
152
165
|
switch (resultStruct.resultType) {
|
|
153
166
|
case TDShowCaptchaResultTypeSuccess:
|
|
154
|
-
resultDictionary
|
|
155
|
-
resultDictionary[@"token"] = @(resultStruct.validateToken);
|
|
167
|
+
resultDictionary = @{ @"function": @"onSuccess", @"token": TDSeString(resultStruct.validateToken) };
|
|
156
168
|
break;
|
|
157
169
|
case TDShowCaptchaResultTypeFailed:
|
|
158
|
-
resultDictionary
|
|
159
|
-
|
|
160
|
-
resultDictionary[@"errorMsg"] = @(resultStruct.errorMsg);
|
|
161
|
-
break;
|
|
162
|
-
case TDShowCaptchaResultTypeReady:
|
|
163
|
-
resultDictionary[@"function"] = @"onReady";
|
|
170
|
+
resultDictionary = @{ @"function": @"onFailed", @"errorCode": @(resultStruct.errorCode),
|
|
171
|
+
@"errorMsg": TDSeString(resultStruct.errorMsg) };
|
|
164
172
|
break;
|
|
173
|
+
case TDShowCaptchaResultTypeReady: {
|
|
174
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
175
|
+
[self sendEventWithName:@"TrustDeviceSeCaptcha" body:@{ @"function": @"onReady" }];
|
|
176
|
+
});
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
165
179
|
default:
|
|
166
|
-
|
|
180
|
+
return;
|
|
167
181
|
}
|
|
168
182
|
resolve(resultDictionary);
|
|
169
183
|
});
|
|
170
184
|
});
|
|
171
185
|
}
|
|
172
186
|
|
|
187
|
+
RCT_REMAP_METHOD(showLiveness,
|
|
188
|
+
showLivenessWithOptions:(NSDictionary *)options
|
|
189
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
190
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
191
|
+
{
|
|
192
|
+
TDMobRiskManager_t *manager = [TDMobRiskManager sharedManager];
|
|
193
|
+
if (manager == NULL || manager->showLivenessWithShowStyle == NULL) {
|
|
194
|
+
reject(@"liveness_unavailable", @"showLiveness is unavailable", nil);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
198
|
+
UIViewController *controller = [self getKeyWindow].rootViewController;
|
|
199
|
+
while (controller.presentedViewController != nil) {
|
|
200
|
+
controller = controller.presentedViewController;
|
|
201
|
+
}
|
|
202
|
+
if (controller == nil) {
|
|
203
|
+
reject(@"liveness_no_controller", @"No active view controller", nil);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
NSString *license = [options[@"license"] isKindOfClass:[NSString class]] ? options[@"license"] : nil;
|
|
207
|
+
TDLivenessShowStyle style = [options[@"showStyle"] isEqual:@"push"]
|
|
208
|
+
? TDLivenessShowStylePush : TDLivenessShowStylePresent;
|
|
209
|
+
manager->showLivenessWithShowStyle(controller, license, style,
|
|
210
|
+
^(NSDictionary *success) {
|
|
211
|
+
NSMutableDictionary *result = [success mutableCopy] ?: [NSMutableDictionary dictionary];
|
|
212
|
+
result[@"function"] = @"onSuccess";
|
|
213
|
+
resolve(result);
|
|
214
|
+
},
|
|
215
|
+
^(NSDictionary *failure) {
|
|
216
|
+
NSMutableDictionary *result = [failure mutableCopy] ?: [NSMutableDictionary dictionary];
|
|
217
|
+
result[@"function"] = @"onFailed";
|
|
218
|
+
resolve(result);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
}
|
|
173
222
|
|
|
174
223
|
|
|
175
224
|
|
package/package.json
CHANGED
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "
|
|
6
|
+
"version": "2.0.0",
|
|
7
7
|
"description": "React Native TrustDevice component",
|
|
8
8
|
"main": "index.js",
|
|
9
9
|
"react-native": "index.js",
|
|
10
|
+
"swiftpmConfig": {
|
|
11
|
+
"name": "ReactNativeTrustDevice"
|
|
12
|
+
},
|
|
10
13
|
"scripts": {
|
|
11
14
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
15
|
},
|
|
@@ -24,9 +27,11 @@
|
|
|
24
27
|
"android/build.gradle",
|
|
25
28
|
"android/src",
|
|
26
29
|
"ios",
|
|
30
|
+
"Package.swift",
|
|
27
31
|
"src",
|
|
28
32
|
"index.js",
|
|
29
33
|
"index.d.ts",
|
|
34
|
+
"react-native.config.js",
|
|
30
35
|
"react-native-trustdevice.podspec"
|
|
31
36
|
],
|
|
32
37
|
|
package/src/TrustDevice.ios.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
import
|
|
3
|
-
import { requireNativeComponent,NativeModules } from 'react-native';
|
|
2
|
+
import {NativeModules} from 'react-native';
|
|
4
3
|
|
|
5
4
|
|
|
6
5
|
const TrustDevice = NativeModules.TrustDevice;
|
|
6
|
+
export const TrustDeviceSe = NativeModules.TrustDeviceSe;
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
export default TrustDevice;
|