@deuna/react-native-sdk 1.0.1 → 1.0.3
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 +21 -0
- package/lib/module/DeunaSDK.js +34 -5
- package/lib/module/DeunaSDK.js.map +1 -1
- package/lib/module/components/DeunaWidget.js +30 -1
- package/lib/module/components/DeunaWidget.js.map +1 -1
- package/lib/module/components/DeviceFingerprintWebView.js +44 -0
- package/lib/module/components/DeviceFingerprintWebView.js.map +1 -0
- package/lib/module/controllers/BaseWebViewController.js +16 -9
- package/lib/module/controllers/BaseWebViewController.js.map +1 -1
- package/lib/module/controllers/DeviceFingerprintController.js +69 -0
- package/lib/module/controllers/DeviceFingerprintController.js.map +1 -0
- package/lib/module/controllers/ElementsWidgetController.js +3 -2
- package/lib/module/controllers/ElementsWidgetController.js.map +1 -1
- package/lib/module/controllers/OpenInNewTabController.js +3 -3
- package/lib/module/controllers/OpenInNewTabController.js.map +1 -1
- package/lib/module/controllers/PaymentWidgetController.js +3 -2
- package/lib/module/controllers/PaymentWidgetController.js.map +1 -1
- package/lib/module/helpers/SubmitStrategy.js +44 -0
- package/lib/module/helpers/SubmitStrategy.js.map +1 -0
- package/lib/module/helpers/getController.js +10 -2
- package/lib/module/helpers/getController.js.map +1 -1
- package/lib/module/helpers/getSubmitStrategy.js +32 -0
- package/lib/module/helpers/getSubmitStrategy.js.map +1 -0
- package/lib/module/interfaces/constants.js +2 -0
- package/lib/module/interfaces/constants.js.map +1 -1
- package/lib/module/interfaces/types.js.map +1 -1
- package/lib/module/types/helpers/buildElementsLink.js +13 -15
- package/lib/module/types/helpers/buildElementsLink.js.map +1 -1
- package/lib/module/types/helpers/buildNextActionLink.js +1 -2
- package/lib/module/types/helpers/buildNextActionLink.js.map +1 -1
- package/lib/module/types/helpers/buildPaymentLink.js +1 -2
- package/lib/module/types/helpers/buildPaymentLink.js.map +1 -1
- package/lib/module/types/helpers/buildVoucherLink.js +1 -2
- package/lib/module/types/helpers/buildVoucherLink.js.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/DeunaSDK.d.ts +14 -4
- package/lib/typescript/deuna-sdk-react-native/src/DeunaSDK.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/components/DeunaWidget.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/components/DeviceFingerprintWebView.d.ts +7 -0
- package/lib/typescript/deuna-sdk-react-native/src/components/DeviceFingerprintWebView.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/controllers/BaseWebViewController.d.ts +5 -3
- package/lib/typescript/deuna-sdk-react-native/src/controllers/BaseWebViewController.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/controllers/DeviceFingerprintController.d.ts +15 -0
- package/lib/typescript/deuna-sdk-react-native/src/controllers/DeviceFingerprintController.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/controllers/ElementsWidgetController.d.ts +3 -1
- package/lib/typescript/deuna-sdk-react-native/src/controllers/ElementsWidgetController.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/controllers/OpenInNewTabController.d.ts +1 -2
- package/lib/typescript/deuna-sdk-react-native/src/controllers/OpenInNewTabController.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/controllers/PaymentWidgetController.d.ts +3 -2
- package/lib/typescript/deuna-sdk-react-native/src/controllers/PaymentWidgetController.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/helpers/SubmitStrategy.d.ts +23 -0
- package/lib/typescript/deuna-sdk-react-native/src/helpers/SubmitStrategy.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/helpers/getController.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/helpers/getSubmitStrategy.d.ts +4 -0
- package/lib/typescript/deuna-sdk-react-native/src/helpers/getSubmitStrategy.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/interfaces/constants.d.ts +2 -0
- package/lib/typescript/deuna-sdk-react-native/src/interfaces/constants.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/interfaces/types.d.ts +6 -0
- package/lib/typescript/deuna-sdk-react-native/src/interfaces/types.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/base.d.ts +2 -2
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildElementsLink.d.ts +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildElementsLink.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildNextActionLink.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildPaymentLink.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildVoucherLink.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/DeunaSDK.ts +48 -6
- package/src/components/DeunaWidget.tsx +39 -0
- package/src/components/DeviceFingerprintWebView.tsx +58 -0
- package/src/controllers/BaseWebViewController.ts +19 -12
- package/src/controllers/DeviceFingerprintController.ts +86 -0
- package/src/controllers/ElementsWidgetController.ts +6 -3
- package/src/controllers/OpenInNewTabController.ts +4 -5
- package/src/controllers/PaymentWidgetController.ts +10 -3
- package/src/helpers/SubmitStrategy.ts +67 -0
- package/src/helpers/getController.ts +10 -3
- package/src/helpers/getSubmitStrategy.ts +42 -0
- package/src/interfaces/constants.ts +5 -0
- package/src/interfaces/types.ts +8 -0
- package/src/types/helpers/buildElementsLink.ts +16 -19
- package/src/types/helpers/buildNextActionLink.ts +1 -2
- package/src/types/helpers/buildPaymentLink.ts +1 -2
- package/src/types/helpers/buildVoucherLink.ts +1 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deuna/react-native-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "React Native SDK",
|
|
5
5
|
"source": "./src/index.tsx",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -56,14 +56,14 @@
|
|
|
56
56
|
],
|
|
57
57
|
"repository": {
|
|
58
58
|
"type": "git",
|
|
59
|
-
"url": "git+https://github.com/
|
|
59
|
+
"url": "git+https://github.com/deuna-developers/deuna-sdk-react-native.git"
|
|
60
60
|
},
|
|
61
|
-
"author": "DEUNA
|
|
61
|
+
"author": "DEUNA (https://github.com/deuna-developers)",
|
|
62
62
|
"license": "MIT",
|
|
63
63
|
"bugs": {
|
|
64
|
-
"url": "https://github.com/
|
|
64
|
+
"url": "https://github.com/deuna-developers/deuna-sdk-react-native/issues"
|
|
65
65
|
},
|
|
66
|
-
"homepage": "https://github.com/
|
|
66
|
+
"homepage": "https://github.com/deuna-developers/deuna-sdk-react-native#readme",
|
|
67
67
|
"publishConfig": {
|
|
68
68
|
"registry": "https://registry.npmjs.org/"
|
|
69
69
|
},
|
package/src/DeunaSDK.ts
CHANGED
|
@@ -29,9 +29,16 @@ import { Completer } from './helpers/Completer';
|
|
|
29
29
|
import { ElementsWidgetController } from './controllers/ElementsWidgetController';
|
|
30
30
|
import { DownloadType, Mode, OnDownloadFile } from './interfaces/types';
|
|
31
31
|
import { Platform } from 'react-native';
|
|
32
|
+
import { DeviceFingerprintController } from './controllers/DeviceFingerprintController';
|
|
33
|
+
import { DEVICE_FINGERPRINT_URL } from './interfaces/constants';
|
|
34
|
+
import { SubmitStrategy } from './helpers/SubmitStrategy';
|
|
35
|
+
import { getSubmitStrategy } from './helpers/getSubmitStrategy';
|
|
32
36
|
|
|
33
37
|
export class DeunaSDK extends BaseDeuna {
|
|
34
|
-
constructor(
|
|
38
|
+
constructor(
|
|
39
|
+
readonly config: InitializeParams,
|
|
40
|
+
readonly onDestroyed?: () => void
|
|
41
|
+
) {
|
|
35
42
|
super();
|
|
36
43
|
}
|
|
37
44
|
|
|
@@ -47,11 +54,13 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
47
54
|
private listeners: Set<() => void> = new Set();
|
|
48
55
|
webViewController: DeunaWebViewController | null = null;
|
|
49
56
|
newTabWebViewController: BaseWebViewController | null = null;
|
|
57
|
+
deviceFingerprintController: DeviceFingerprintController | null = null;
|
|
58
|
+
submitStrategy: SubmitStrategy | null = null;
|
|
50
59
|
|
|
51
60
|
modalDismissPromise: Completer<void> | null = null;
|
|
52
61
|
newTabModalDismissPromise: Completer<void> | null = null;
|
|
53
62
|
|
|
54
|
-
|
|
63
|
+
get safeWebViewController(): DeunaWebViewController {
|
|
55
64
|
if (!this.webViewController) {
|
|
56
65
|
const errorMessage =
|
|
57
66
|
'A variant of the init method must be called first. Please call initPaymentWidget, initVoucherWidget, or another init method before using this functionality.';
|
|
@@ -61,9 +70,28 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
61
70
|
return this.webViewController;
|
|
62
71
|
}
|
|
63
72
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Generates a device fingerprint, creates a invisible webview to get the device fingerprint
|
|
75
|
+
* and returns the device fingerprint
|
|
76
|
+
* @returns The device fingerprint
|
|
77
|
+
*/
|
|
78
|
+
getSessionId = async (params?: Record<string, any>): Promise<string> => {
|
|
79
|
+
this.deviceFingerprintController = new DeviceFingerprintController(
|
|
80
|
+
this.config.publicApiKey,
|
|
81
|
+
this.config.environment ?? 'production'
|
|
82
|
+
);
|
|
83
|
+
this.deviceFingerprintController.url = DEVICE_FINGERPRINT_URL;
|
|
84
|
+
this.notifyListeners();
|
|
85
|
+
|
|
86
|
+
const deviceFingerprint =
|
|
87
|
+
await this.deviceFingerprintController.generateDeviceFingerprint(
|
|
88
|
+
params ?? {}
|
|
89
|
+
);
|
|
90
|
+
this.deviceFingerprintController?.dispose();
|
|
91
|
+
this.deviceFingerprintController = null;
|
|
92
|
+
this.notifyListeners();
|
|
93
|
+
return deviceFingerprint ?? '';
|
|
94
|
+
};
|
|
67
95
|
|
|
68
96
|
static initialize(config: InitializeParams): DeunaSDK {
|
|
69
97
|
return new DeunaSDK(config);
|
|
@@ -166,7 +194,16 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
166
194
|
};
|
|
167
195
|
|
|
168
196
|
submit = async (): Promise<SubmitResult> => {
|
|
169
|
-
|
|
197
|
+
this.getStateFn = () => this.getWidgetState();
|
|
198
|
+
const submitStrategy = await getSubmitStrategy(this);
|
|
199
|
+
|
|
200
|
+
if (!submitStrategy) {
|
|
201
|
+
return this.safeWebViewController.submit();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.submitStrategy = submitStrategy;
|
|
205
|
+
this.notifyListeners();
|
|
206
|
+
return this.submitStrategy.submit();
|
|
170
207
|
};
|
|
171
208
|
|
|
172
209
|
setCustomStyle = async (style: Partial<CustomStyles>): Promise<void> => {
|
|
@@ -203,11 +240,16 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
203
240
|
this.newTabWebViewController = null;
|
|
204
241
|
this.webViewController = null;
|
|
205
242
|
this.mode = null;
|
|
243
|
+
|
|
244
|
+
await this.submitStrategy?.deunaSDK.close();
|
|
245
|
+
this.submitStrategy = null;
|
|
246
|
+
|
|
206
247
|
this.notifyListeners();
|
|
207
248
|
|
|
208
249
|
// if the widget was shown in modal mode, wait for the modal to be dismissed
|
|
209
250
|
await this.modalDismissPromise?.wait;
|
|
210
251
|
this.modalDismissPromise = null;
|
|
252
|
+
this.onDestroyed?.();
|
|
211
253
|
};
|
|
212
254
|
|
|
213
255
|
onModalDismissed = () => {
|
|
@@ -6,12 +6,50 @@ import { DeunaWebView } from './DeunaWebView';
|
|
|
6
6
|
import { NewTabWebView } from './NewTabWebView';
|
|
7
7
|
import { DeunaWebViewController } from '../controllers/BaseWebViewController';
|
|
8
8
|
import { Mode } from '../interfaces/types';
|
|
9
|
+
import { DeviceFingerprintWebView } from './DeviceFingerprintWebView';
|
|
9
10
|
|
|
10
11
|
interface DeunaWidgetProps {
|
|
11
12
|
instance: DeunaSDK;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export const DeunaWidget = (props: DeunaWidgetProps) => {
|
|
16
|
+
const { instance } = props;
|
|
17
|
+
const instanceRef = useRef(instance);
|
|
18
|
+
const [showPaymentStrategy, setShowPaymentStrategy] = useState(false);
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
instanceRef.current = instance;
|
|
22
|
+
}, [instance]);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const listener = () => {
|
|
26
|
+
setShowPaymentStrategy(instanceRef.current.submitStrategy !== null);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
instanceRef.current.addListener(listener);
|
|
30
|
+
|
|
31
|
+
return () => {
|
|
32
|
+
instanceRef.current.removeListener(listener);
|
|
33
|
+
};
|
|
34
|
+
}, []);
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<>
|
|
38
|
+
<DeunaWidgetContainer
|
|
39
|
+
key="MainDeunaWidget"
|
|
40
|
+
instance={instanceRef.current}
|
|
41
|
+
/>
|
|
42
|
+
{showPaymentStrategy && (
|
|
43
|
+
<DeunaWidgetContainer
|
|
44
|
+
key="PaymentStrategy"
|
|
45
|
+
instance={instanceRef.current.submitStrategy!.deunaSDK}
|
|
46
|
+
/>
|
|
47
|
+
)}
|
|
48
|
+
</>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const DeunaWidgetContainer = (props: DeunaWidgetProps) => {
|
|
15
53
|
const { instance } = props;
|
|
16
54
|
const instanceRef = useRef(instance);
|
|
17
55
|
const [mode, setMode] = useState<Mode | null>(instance.mode);
|
|
@@ -92,6 +130,7 @@ export const DeunaWidget = (props: DeunaWidgetProps) => {
|
|
|
92
130
|
}
|
|
93
131
|
/>
|
|
94
132
|
)}
|
|
133
|
+
<DeviceFingerprintWebView instance={instanceRef.current} />
|
|
95
134
|
</>
|
|
96
135
|
);
|
|
97
136
|
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { DeunaSDK } from '../DeunaSDK';
|
|
3
|
+
import { DeunaWebView } from './DeunaWebView';
|
|
4
|
+
import { View } from 'react-native';
|
|
5
|
+
|
|
6
|
+
interface DeviceFingerprintWebViewProps {
|
|
7
|
+
instance: DeunaSDK;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const DeviceFingerprintWebView = (
|
|
11
|
+
props: DeviceFingerprintWebViewProps
|
|
12
|
+
) => {
|
|
13
|
+
const { instance } = props;
|
|
14
|
+
const instanceRef = useRef<DeunaSDK>(instance);
|
|
15
|
+
const [visible, setVisible] = useState(false);
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
instanceRef.current = instance;
|
|
19
|
+
}, [instance]);
|
|
20
|
+
|
|
21
|
+
// Listen when the DeunaSDK instance configuration
|
|
22
|
+
// has changed
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const ref = instanceRef.current;
|
|
25
|
+
const listener = () => {
|
|
26
|
+
const isVisible = !!ref.deviceFingerprintController;
|
|
27
|
+
setVisible(isVisible);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
instanceRef.current.addListener(listener);
|
|
31
|
+
|
|
32
|
+
return () => {
|
|
33
|
+
ref.removeListener(listener);
|
|
34
|
+
};
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
37
|
+
const deviceFingerprintController =
|
|
38
|
+
instanceRef.current.deviceFingerprintController;
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<>
|
|
42
|
+
{visible && (
|
|
43
|
+
<View>
|
|
44
|
+
<DeunaWebView
|
|
45
|
+
url={deviceFingerprintController?.url ?? ''}
|
|
46
|
+
onWebView={deviceFingerprintController?.setWebView}
|
|
47
|
+
onMessage={deviceFingerprintController?.onMessage}
|
|
48
|
+
onLoad={deviceFingerprintController?.onLoad}
|
|
49
|
+
onError={deviceFingerprintController?.onError}
|
|
50
|
+
onShouldStartLoadWithRequest={
|
|
51
|
+
deviceFingerprintController?.onShouldStartLoadWithRequest
|
|
52
|
+
}
|
|
53
|
+
/>
|
|
54
|
+
</View>
|
|
55
|
+
)}
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
State,
|
|
9
9
|
SubmitResult,
|
|
10
10
|
} from '../types';
|
|
11
|
-
import { submitError } from '../interfaces';
|
|
11
|
+
import { submitError, WidgetConfig } from '../interfaces';
|
|
12
12
|
import { Platform } from 'react-native';
|
|
13
13
|
import { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes';
|
|
14
14
|
|
|
@@ -39,8 +39,13 @@ export abstract class BaseWebViewController {
|
|
|
39
39
|
url: string | null = null;
|
|
40
40
|
|
|
41
41
|
delegate: WebViewDelegate | null = null;
|
|
42
|
+
jsExecutor = new JsExecutor();
|
|
43
|
+
|
|
44
|
+
setWebView = (webView: WebView) => {
|
|
45
|
+
this.webView = webView;
|
|
46
|
+
this.jsExecutor.webView = webView;
|
|
47
|
+
};
|
|
42
48
|
|
|
43
|
-
abstract setWebView: (webView: WebView) => void;
|
|
44
49
|
abstract onMessage: (event: WebViewMessageEvent) => void;
|
|
45
50
|
|
|
46
51
|
/**
|
|
@@ -112,14 +117,12 @@ export abstract class DeunaWebViewController extends BaseWebViewController {
|
|
|
112
117
|
hidePayButton = false;
|
|
113
118
|
redirectUrl: string | null = null;
|
|
114
119
|
closedAction: ClosedAction = 'systemAction';
|
|
115
|
-
jsExecutor = new JsExecutor();
|
|
116
120
|
|
|
117
|
-
|
|
121
|
+
constructor(readonly widgetConfig: WidgetConfig) {
|
|
122
|
+
super();
|
|
123
|
+
}
|
|
118
124
|
|
|
119
|
-
|
|
120
|
-
this.webView = webView;
|
|
121
|
-
this.jsExecutor.webView = webView;
|
|
122
|
-
};
|
|
125
|
+
abstract onEventDispatch: (event: Record<string, any>) => void;
|
|
123
126
|
|
|
124
127
|
onLoad = () => {
|
|
125
128
|
this.setXprops();
|
|
@@ -130,7 +133,6 @@ export abstract class DeunaWebViewController extends BaseWebViewController {
|
|
|
130
133
|
this.delegate?.onFileDownload?.(url);
|
|
131
134
|
} else {
|
|
132
135
|
this.redirectUrl = url;
|
|
133
|
-
this.delegate?.onOpenInNewTab?.(url);
|
|
134
136
|
}
|
|
135
137
|
return false;
|
|
136
138
|
};
|
|
@@ -175,9 +177,14 @@ export abstract class DeunaWebViewController extends BaseWebViewController {
|
|
|
175
177
|
};
|
|
176
178
|
|
|
177
179
|
setXprops = () => {
|
|
178
|
-
// this.detectDownloadsAndRedirects(true);
|
|
179
180
|
this.webView?.injectJavaScript(
|
|
180
181
|
`
|
|
182
|
+
window.open = function(url, target, features) {
|
|
183
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.openInNewTab}', url }));
|
|
184
|
+
};
|
|
185
|
+
console.log = function(message) {
|
|
186
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.consoleLog}', message }));
|
|
187
|
+
};
|
|
181
188
|
window.xprops = {
|
|
182
189
|
hidePayButton: ${this.hidePayButton},
|
|
183
190
|
onEventDispatch: function (event) {
|
|
@@ -223,8 +230,8 @@ export abstract class DeunaWebViewController extends BaseWebViewController {
|
|
|
223
230
|
* @returns The order data | returns null if the order is not found or an error occurs
|
|
224
231
|
*/
|
|
225
232
|
refetchOrder = async (): Promise<Json | null> => {
|
|
226
|
-
const result = await this.jsExecutor
|
|
227
|
-
if(typeof window.deunaRefetchOrder !== 'function'){
|
|
233
|
+
const result = await this.jsExecutor
|
|
234
|
+
.execute(` if(typeof window.deunaRefetchOrder !== 'function'){
|
|
228
235
|
sendResult({order: null});
|
|
229
236
|
return;
|
|
230
237
|
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { WebViewMessageEvent } from 'react-native-webview';
|
|
2
|
+
import {
|
|
3
|
+
BaseWebViewController,
|
|
4
|
+
WebViewEventType,
|
|
5
|
+
} from './BaseWebViewController';
|
|
6
|
+
import { Completer } from '../helpers/Completer';
|
|
7
|
+
import { Environment } from '../types';
|
|
8
|
+
import { DeunaLogs } from '../DeunaLogs';
|
|
9
|
+
|
|
10
|
+
export class DeviceFingerprintController extends BaseWebViewController {
|
|
11
|
+
constructor(
|
|
12
|
+
private readonly publicApiKey: string,
|
|
13
|
+
private readonly environment: Environment
|
|
14
|
+
) {
|
|
15
|
+
super();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private completer = new Completer<boolean>();
|
|
19
|
+
|
|
20
|
+
onMessage = (event: WebViewMessageEvent) => {
|
|
21
|
+
const eventData = JSON.parse(event.nativeEvent.data);
|
|
22
|
+
|
|
23
|
+
const mapper = {
|
|
24
|
+
[WebViewEventType.consoleLog]: () => {
|
|
25
|
+
DeunaLogs.info(
|
|
26
|
+
`CONSOLE LOG`,
|
|
27
|
+
JSON.stringify(eventData.message, null, 2)
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
[WebViewEventType.jsExecutor]: () => {
|
|
31
|
+
const { data, requestId } = eventData as {
|
|
32
|
+
requestId: number;
|
|
33
|
+
data: Record<string, any> | null;
|
|
34
|
+
};
|
|
35
|
+
this.jsExecutor.requests.get(requestId)?.(data);
|
|
36
|
+
this.jsExecutor.requests.delete(requestId);
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
mapper[eventData.type as keyof typeof mapper]?.();
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
onLoad = () => {
|
|
43
|
+
this.webView?.injectJavaScript(`
|
|
44
|
+
console.log = function(message) {
|
|
45
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.consoleLog}', message:message }));
|
|
46
|
+
};
|
|
47
|
+
`);
|
|
48
|
+
this.completer.complete(true);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
onError = (_: any) => {
|
|
52
|
+
this.completer.complete(false);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
urlMustBeLoadedInTheSameWebView = (_: string) => true;
|
|
56
|
+
|
|
57
|
+
generateDeviceFingerprint = async (
|
|
58
|
+
params: Record<string, any>
|
|
59
|
+
): Promise<string | null> => {
|
|
60
|
+
const isLoaded = await this.completer.wait;
|
|
61
|
+
if (!isLoaded) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const data = await this.jsExecutor.execute(`
|
|
66
|
+
if (typeof window.generateFraudId !== 'function') {
|
|
67
|
+
console.log('❌ window.generateFraudId is not a function');
|
|
68
|
+
sendResult({fraudId: null});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
window.generateFraudId({
|
|
73
|
+
publicApiKey: "${this.publicApiKey}",
|
|
74
|
+
env: "${this.environment}",
|
|
75
|
+
params: ${JSON.stringify(params)}
|
|
76
|
+
})
|
|
77
|
+
.then((fraudId) => {
|
|
78
|
+
sendResult({ fraudId: fraudId });
|
|
79
|
+
})
|
|
80
|
+
.catch((error) => {
|
|
81
|
+
sendResult({ fraudId: null });
|
|
82
|
+
});
|
|
83
|
+
`);
|
|
84
|
+
return data?.fraudId ?? null;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
@@ -4,11 +4,14 @@ import {
|
|
|
4
4
|
ElementsEventType,
|
|
5
5
|
} from '../interfaces/events/elements';
|
|
6
6
|
import { ElementsWidgetCallbacks } from '../types';
|
|
7
|
-
import { ElementsErrorType } from '../interfaces';
|
|
7
|
+
import { ElementsErrorType, WidgetConfig } from '../interfaces';
|
|
8
8
|
|
|
9
9
|
export class ElementsWidgetController extends DeunaWebViewController {
|
|
10
|
-
constructor(
|
|
11
|
-
|
|
10
|
+
constructor(
|
|
11
|
+
readonly callbacks: ElementsWidgetCallbacks,
|
|
12
|
+
readonly widgetConfig: WidgetConfig
|
|
13
|
+
) {
|
|
14
|
+
super(widgetConfig);
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
onError = (event: any) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { WebViewMessageEvent } from 'react-native-webview';
|
|
2
2
|
import {
|
|
3
3
|
BaseWebViewController,
|
|
4
4
|
WebViewEventType,
|
|
@@ -11,10 +11,6 @@ export class OpenInNewTabController extends BaseWebViewController {
|
|
|
11
11
|
this.url = url;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
setWebView = (webView: WebView) => {
|
|
15
|
-
this.webView = webView;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
14
|
onLoad = () => {
|
|
19
15
|
this.setXprops();
|
|
20
16
|
};
|
|
@@ -41,6 +37,9 @@ export class OpenInNewTabController extends BaseWebViewController {
|
|
|
41
37
|
setXprops = () => {
|
|
42
38
|
// Hide the print button on the Efecty page
|
|
43
39
|
this.webView?.injectJavaScript(`
|
|
40
|
+
console.log = function(message) {
|
|
41
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.consoleLog}', message }));
|
|
42
|
+
};
|
|
44
43
|
window.close = function() {
|
|
45
44
|
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.newTabWindowClose}', data: '' }));
|
|
46
45
|
};
|
|
@@ -4,7 +4,11 @@ import {
|
|
|
4
4
|
PaymentErrorType,
|
|
5
5
|
} from '../interfaces';
|
|
6
6
|
import { constants } from '../interfaces/constants';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
DownloadType,
|
|
9
|
+
OnDownloadFile,
|
|
10
|
+
WidgetConfig,
|
|
11
|
+
} from '../interfaces/types';
|
|
8
12
|
import {
|
|
9
13
|
PaymentWidgetCallbacks,
|
|
10
14
|
NextActionWidgetCallbacks,
|
|
@@ -18,8 +22,11 @@ type Callbacks = PaymentWidgetCallbacks &
|
|
|
18
22
|
OnDownloadFile;
|
|
19
23
|
|
|
20
24
|
export class PaymentWidgetController extends DeunaWebViewController {
|
|
21
|
-
constructor(
|
|
22
|
-
|
|
25
|
+
constructor(
|
|
26
|
+
readonly callbacks: Callbacks,
|
|
27
|
+
readonly widgetConfig: WidgetConfig
|
|
28
|
+
) {
|
|
29
|
+
super(widgetConfig);
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
onError = (event: any) => {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { DeunaSDK } from '../DeunaSDK';
|
|
2
|
+
import { Mode } from '../interfaces';
|
|
3
|
+
import { Environment, SubmitResult } from '../types';
|
|
4
|
+
|
|
5
|
+
export type SubmitStrategyType = 'PayPal';
|
|
6
|
+
|
|
7
|
+
export type SubmitStrategyConfig = {
|
|
8
|
+
publicApiKey: string;
|
|
9
|
+
environment: Environment;
|
|
10
|
+
orderToken?: string;
|
|
11
|
+
userToken?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export abstract class SubmitStrategy {
|
|
15
|
+
abstract deunaSDK: DeunaSDK;
|
|
16
|
+
constructor(
|
|
17
|
+
readonly config: SubmitStrategyConfig,
|
|
18
|
+
readonly type: SubmitStrategyType
|
|
19
|
+
) {}
|
|
20
|
+
|
|
21
|
+
abstract submit(): Promise<SubmitResult>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class PayPalSubmitStrategy extends SubmitStrategy {
|
|
25
|
+
deunaSDK: DeunaSDK;
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
config: SubmitStrategyConfig,
|
|
29
|
+
readonly onDestroyed: () => void
|
|
30
|
+
) {
|
|
31
|
+
super(config, 'PayPal');
|
|
32
|
+
this.deunaSDK = new DeunaSDK(
|
|
33
|
+
{
|
|
34
|
+
publicApiKey: this.config.publicApiKey,
|
|
35
|
+
environment: this.config.environment,
|
|
36
|
+
},
|
|
37
|
+
this.onDestroyed
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async submit(): Promise<SubmitResult> {
|
|
42
|
+
await this.deunaSDK.initPaymentWidget({
|
|
43
|
+
mode: Mode.MODAL,
|
|
44
|
+
orderToken: this.config.orderToken ?? '',
|
|
45
|
+
userToken: this.config.userToken,
|
|
46
|
+
paymentMethods: [
|
|
47
|
+
{
|
|
48
|
+
paymentMethod: 'wallet',
|
|
49
|
+
processors: ['paypal_wallet'],
|
|
50
|
+
configuration: {
|
|
51
|
+
express: true,
|
|
52
|
+
flowType: {
|
|
53
|
+
type: 'twoStep',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
callbacks: {},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
status: 'success',
|
|
63
|
+
code: 'success',
|
|
64
|
+
message: 'Payment submitted successfully',
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -47,7 +47,8 @@ export const getWidgetController = (
|
|
|
47
47
|
userToken: rest.userToken ?? '',
|
|
48
48
|
language: rest.language ?? 'es',
|
|
49
49
|
sessionId: rest.sessionId ?? '',
|
|
50
|
-
mode: mode
|
|
50
|
+
mode: mode === Mode.MODAL ? 'modal' : 'target',
|
|
51
|
+
...(rest.domain && { domain: rest.domain }),
|
|
51
52
|
};
|
|
52
53
|
|
|
53
54
|
const widgetMappers = {
|
|
@@ -69,10 +70,16 @@ export const getWidgetController = (
|
|
|
69
70
|
voucher: () => baseParams,
|
|
70
71
|
};
|
|
71
72
|
|
|
73
|
+
const widgetConfig = {
|
|
74
|
+
orderToken: rest.orderToken,
|
|
75
|
+
behavior: rest.behavior,
|
|
76
|
+
userToken: rest.userToken,
|
|
77
|
+
};
|
|
78
|
+
|
|
72
79
|
const controller =
|
|
73
80
|
widget === 'elements'
|
|
74
|
-
? new ElementsWidgetController(callbacks)
|
|
75
|
-
: new PaymentWidgetController(callbacks);
|
|
81
|
+
? new ElementsWidgetController(callbacks, widgetConfig)
|
|
82
|
+
: new PaymentWidgetController(callbacks, widgetConfig);
|
|
76
83
|
|
|
77
84
|
controller.url = linkBuilders[widget](widgetMappers[widget]());
|
|
78
85
|
controller.hidePayButton = rest.hidePayButton ?? false;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DeunaSDK } from '../DeunaSDK';
|
|
2
|
+
import { TWO_STEP_FLOW } from '../interfaces/constants';
|
|
3
|
+
import { PayPalSubmitStrategy, SubmitStrategy } from './SubmitStrategy';
|
|
4
|
+
|
|
5
|
+
export const getSubmitStrategy = async (
|
|
6
|
+
deunaSDK: DeunaSDK
|
|
7
|
+
): Promise<SubmitStrategy | null> => {
|
|
8
|
+
const selectedPaymentMethod = await deunaSDK.getSelectedPaymentMethod();
|
|
9
|
+
if (!selectedPaymentMethod) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { widgetConfig } = deunaSDK.safeWebViewController;
|
|
14
|
+
|
|
15
|
+
const processorName = selectedPaymentMethod.processor_name as string;
|
|
16
|
+
|
|
17
|
+
const configFlowType = selectedPaymentMethod.configuration?.flowType?.type;
|
|
18
|
+
const behaviorFlowType =
|
|
19
|
+
widgetConfig.behavior?.paymentMethods?.flowType?.type;
|
|
20
|
+
|
|
21
|
+
const isTwoStepFlow =
|
|
22
|
+
configFlowType === TWO_STEP_FLOW ||
|
|
23
|
+
(!configFlowType && behaviorFlowType === TWO_STEP_FLOW);
|
|
24
|
+
|
|
25
|
+
if (isTwoStepFlow && processorName === 'paypal_wallet') {
|
|
26
|
+
return new PayPalSubmitStrategy(
|
|
27
|
+
{
|
|
28
|
+
publicApiKey: deunaSDK.config.publicApiKey,
|
|
29
|
+
environment: deunaSDK.config.environment ?? 'production',
|
|
30
|
+
orderToken: widgetConfig.orderToken,
|
|
31
|
+
userToken: widgetConfig.userToken,
|
|
32
|
+
},
|
|
33
|
+
() => {
|
|
34
|
+
if (deunaSDK.submitStrategy) {
|
|
35
|
+
deunaSDK.submitStrategy = null;
|
|
36
|
+
deunaSDK.notifyListeners();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
};
|
package/src/interfaces/types.ts
CHANGED