@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.
Files changed (82) hide show
  1. package/README.md +21 -0
  2. package/lib/module/DeunaSDK.js +34 -5
  3. package/lib/module/DeunaSDK.js.map +1 -1
  4. package/lib/module/components/DeunaWidget.js +30 -1
  5. package/lib/module/components/DeunaWidget.js.map +1 -1
  6. package/lib/module/components/DeviceFingerprintWebView.js +44 -0
  7. package/lib/module/components/DeviceFingerprintWebView.js.map +1 -0
  8. package/lib/module/controllers/BaseWebViewController.js +16 -9
  9. package/lib/module/controllers/BaseWebViewController.js.map +1 -1
  10. package/lib/module/controllers/DeviceFingerprintController.js +69 -0
  11. package/lib/module/controllers/DeviceFingerprintController.js.map +1 -0
  12. package/lib/module/controllers/ElementsWidgetController.js +3 -2
  13. package/lib/module/controllers/ElementsWidgetController.js.map +1 -1
  14. package/lib/module/controllers/OpenInNewTabController.js +3 -3
  15. package/lib/module/controllers/OpenInNewTabController.js.map +1 -1
  16. package/lib/module/controllers/PaymentWidgetController.js +3 -2
  17. package/lib/module/controllers/PaymentWidgetController.js.map +1 -1
  18. package/lib/module/helpers/SubmitStrategy.js +44 -0
  19. package/lib/module/helpers/SubmitStrategy.js.map +1 -0
  20. package/lib/module/helpers/getController.js +10 -2
  21. package/lib/module/helpers/getController.js.map +1 -1
  22. package/lib/module/helpers/getSubmitStrategy.js +32 -0
  23. package/lib/module/helpers/getSubmitStrategy.js.map +1 -0
  24. package/lib/module/interfaces/constants.js +2 -0
  25. package/lib/module/interfaces/constants.js.map +1 -1
  26. package/lib/module/interfaces/types.js.map +1 -1
  27. package/lib/module/types/helpers/buildElementsLink.js +13 -15
  28. package/lib/module/types/helpers/buildElementsLink.js.map +1 -1
  29. package/lib/module/types/helpers/buildNextActionLink.js +1 -2
  30. package/lib/module/types/helpers/buildNextActionLink.js.map +1 -1
  31. package/lib/module/types/helpers/buildPaymentLink.js +1 -2
  32. package/lib/module/types/helpers/buildPaymentLink.js.map +1 -1
  33. package/lib/module/types/helpers/buildVoucherLink.js +1 -2
  34. package/lib/module/types/helpers/buildVoucherLink.js.map +1 -1
  35. package/lib/typescript/deuna-sdk-react-native/src/DeunaSDK.d.ts +14 -4
  36. package/lib/typescript/deuna-sdk-react-native/src/DeunaSDK.d.ts.map +1 -1
  37. package/lib/typescript/deuna-sdk-react-native/src/components/DeunaWidget.d.ts.map +1 -1
  38. package/lib/typescript/deuna-sdk-react-native/src/components/DeviceFingerprintWebView.d.ts +7 -0
  39. package/lib/typescript/deuna-sdk-react-native/src/components/DeviceFingerprintWebView.d.ts.map +1 -0
  40. package/lib/typescript/deuna-sdk-react-native/src/controllers/BaseWebViewController.d.ts +5 -3
  41. package/lib/typescript/deuna-sdk-react-native/src/controllers/BaseWebViewController.d.ts.map +1 -1
  42. package/lib/typescript/deuna-sdk-react-native/src/controllers/DeviceFingerprintController.d.ts +15 -0
  43. package/lib/typescript/deuna-sdk-react-native/src/controllers/DeviceFingerprintController.d.ts.map +1 -0
  44. package/lib/typescript/deuna-sdk-react-native/src/controllers/ElementsWidgetController.d.ts +3 -1
  45. package/lib/typescript/deuna-sdk-react-native/src/controllers/ElementsWidgetController.d.ts.map +1 -1
  46. package/lib/typescript/deuna-sdk-react-native/src/controllers/OpenInNewTabController.d.ts +1 -2
  47. package/lib/typescript/deuna-sdk-react-native/src/controllers/OpenInNewTabController.d.ts.map +1 -1
  48. package/lib/typescript/deuna-sdk-react-native/src/controllers/PaymentWidgetController.d.ts +3 -2
  49. package/lib/typescript/deuna-sdk-react-native/src/controllers/PaymentWidgetController.d.ts.map +1 -1
  50. package/lib/typescript/deuna-sdk-react-native/src/helpers/SubmitStrategy.d.ts +23 -0
  51. package/lib/typescript/deuna-sdk-react-native/src/helpers/SubmitStrategy.d.ts.map +1 -0
  52. package/lib/typescript/deuna-sdk-react-native/src/helpers/getController.d.ts.map +1 -1
  53. package/lib/typescript/deuna-sdk-react-native/src/helpers/getSubmitStrategy.d.ts +4 -0
  54. package/lib/typescript/deuna-sdk-react-native/src/helpers/getSubmitStrategy.d.ts.map +1 -0
  55. package/lib/typescript/deuna-sdk-react-native/src/interfaces/constants.d.ts +2 -0
  56. package/lib/typescript/deuna-sdk-react-native/src/interfaces/constants.d.ts.map +1 -1
  57. package/lib/typescript/deuna-sdk-react-native/src/interfaces/types.d.ts +6 -0
  58. package/lib/typescript/deuna-sdk-react-native/src/interfaces/types.d.ts.map +1 -1
  59. package/lib/typescript/deuna-sdk-react-native/src/types/base.d.ts +2 -2
  60. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildElementsLink.d.ts +1 -1
  61. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildElementsLink.d.ts.map +1 -1
  62. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildNextActionLink.d.ts.map +1 -1
  63. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildPaymentLink.d.ts.map +1 -1
  64. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildVoucherLink.d.ts.map +1 -1
  65. package/package.json +5 -5
  66. package/src/DeunaSDK.ts +48 -6
  67. package/src/components/DeunaWidget.tsx +39 -0
  68. package/src/components/DeviceFingerprintWebView.tsx +58 -0
  69. package/src/controllers/BaseWebViewController.ts +19 -12
  70. package/src/controllers/DeviceFingerprintController.ts +86 -0
  71. package/src/controllers/ElementsWidgetController.ts +6 -3
  72. package/src/controllers/OpenInNewTabController.ts +4 -5
  73. package/src/controllers/PaymentWidgetController.ts +10 -3
  74. package/src/helpers/SubmitStrategy.ts +67 -0
  75. package/src/helpers/getController.ts +10 -3
  76. package/src/helpers/getSubmitStrategy.ts +42 -0
  77. package/src/interfaces/constants.ts +5 -0
  78. package/src/interfaces/types.ts +8 -0
  79. package/src/types/helpers/buildElementsLink.ts +16 -19
  80. package/src/types/helpers/buildNextActionLink.ts +1 -2
  81. package/src/types/helpers/buildPaymentLink.ts +1 -2
  82. 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.1",
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/darwinmorocho-deuna/deuna-sdk-react-native.git"
59
+ "url": "git+https://github.com/deuna-developers/deuna-sdk-react-native.git"
60
60
  },
61
- "author": "DEUNA <dmorocho@deuna.com> (https://github.com/darwinmorocho-deuna)",
61
+ "author": "DEUNA (https://github.com/deuna-developers)",
62
62
  "license": "MIT",
63
63
  "bugs": {
64
- "url": "https://github.com/darwinmorocho-deuna/deuna-sdk-react-native/issues"
64
+ "url": "https://github.com/deuna-developers/deuna-sdk-react-native/issues"
65
65
  },
66
- "homepage": "https://github.com/darwinmorocho-deuna/deuna-sdk-react-native#readme",
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(private readonly config: InitializeParams) {
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
- private get safeWebViewController(): DeunaWebViewController {
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
- getSessionId(): Promise<string> {
65
- throw new Error('Method not implemented.');
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
- return this.safeWebViewController.submit();
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
- abstract onEventDispatch: (event: Record<string, any>) => void;
121
+ constructor(readonly widgetConfig: WidgetConfig) {
122
+ super();
123
+ }
118
124
 
119
- setWebView = (webView: WebView) => {
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.execute(`
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(readonly callbacks: ElementsWidgetCallbacks) {
11
- super();
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 WebView, { WebViewMessageEvent } from 'react-native-webview';
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 { DownloadType, OnDownloadFile } from '../interfaces/types';
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(readonly callbacks: Callbacks) {
22
- super();
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 ?? Mode.MODAL,
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
+ };
@@ -3,3 +3,8 @@ export const constants = {
3
3
  metadata: 'metadata',
4
4
  voucherPdfDownloadUrl: 'voucherPdfDownloadUrl',
5
5
  };
6
+
7
+ export const DEVICE_FINGERPRINT_URL =
8
+ 'https://cdn.stg.deuna.io/mobile-sdks/get_fraud_id.html';
9
+
10
+ export const TWO_STEP_FLOW = 'twoStep';
@@ -1,3 +1,11 @@
1
+ import { BehaviorWidget } from '../types';
2
+
3
+ export interface WidgetConfig {
4
+ behavior?: BehaviorWidget;
5
+ orderToken?: string;
6
+ userToken?: string;
7
+ }
8
+
1
9
  export enum Mode {
2
10
  MODAL = 'modal',
3
11
  EMBEDDED = 'embedded',