@deuna/react-native-sdk 1.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.
Files changed (190) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +15 -0
  3. package/lib/module/DeunaLogs.js +18 -0
  4. package/lib/module/DeunaLogs.js.map +1 -0
  5. package/lib/module/DeunaSDK.js +207 -0
  6. package/lib/module/DeunaSDK.js.map +1 -0
  7. package/lib/module/components/DeunaWebView.js +37 -0
  8. package/lib/module/components/DeunaWebView.js.map +1 -0
  9. package/lib/module/components/DeunaWidget.js +82 -0
  10. package/lib/module/components/DeunaWidget.js.map +1 -0
  11. package/lib/module/components/NewTabWebView.js +55 -0
  12. package/lib/module/components/NewTabWebView.js.map +1 -0
  13. package/lib/module/components/WebViewLoader.js +25 -0
  14. package/lib/module/components/WebViewLoader.js.map +1 -0
  15. package/lib/module/controllers/BaseWebViewController.js +252 -0
  16. package/lib/module/controllers/BaseWebViewController.js.map +1 -0
  17. package/lib/module/controllers/ElementsWidgetController.js +64 -0
  18. package/lib/module/controllers/ElementsWidgetController.js.map +1 -0
  19. package/lib/module/controllers/OpenInNewTabController.js +34 -0
  20. package/lib/module/controllers/OpenInNewTabController.js.map +1 -0
  21. package/lib/module/controllers/PaymentWidgetController.js +98 -0
  22. package/lib/module/controllers/PaymentWidgetController.js.map +1 -0
  23. package/lib/module/helpers/Completer.js +30 -0
  24. package/lib/module/helpers/Completer.js.map +1 -0
  25. package/lib/module/helpers/getController.js +48 -0
  26. package/lib/module/helpers/getController.js.map +1 -0
  27. package/lib/module/index.js +7 -0
  28. package/lib/module/index.js.map +1 -0
  29. package/lib/module/interfaces/constants.js +8 -0
  30. package/lib/module/interfaces/constants.js.map +1 -0
  31. package/lib/module/interfaces/errors.js +36 -0
  32. package/lib/module/interfaces/errors.js.map +1 -0
  33. package/lib/module/interfaces/events/checkout.js +45 -0
  34. package/lib/module/interfaces/events/checkout.js.map +1 -0
  35. package/lib/module/interfaces/events/elements.js +28 -0
  36. package/lib/module/interfaces/events/elements.js.map +1 -0
  37. package/lib/module/interfaces/index.js +6 -0
  38. package/lib/module/interfaces/index.js.map +1 -0
  39. package/lib/module/interfaces/types.js +13 -0
  40. package/lib/module/interfaces/types.js.map +1 -0
  41. package/lib/module/package.json +1 -0
  42. package/lib/module/types/base.js +24 -0
  43. package/lib/module/types/base.js.map +1 -0
  44. package/lib/module/types/env.js +48 -0
  45. package/lib/module/types/env.js.map +1 -0
  46. package/lib/module/types/helpers/buildElementsLink.js +75 -0
  47. package/lib/module/types/helpers/buildElementsLink.js.map +1 -0
  48. package/lib/module/types/helpers/buildNextActionLink.js +33 -0
  49. package/lib/module/types/helpers/buildNextActionLink.js.map +1 -0
  50. package/lib/module/types/helpers/buildPaymentLink.js +54 -0
  51. package/lib/module/types/helpers/buildPaymentLink.js.map +1 -0
  52. package/lib/module/types/helpers/buildVoucherLink.js +48 -0
  53. package/lib/module/types/helpers/buildVoucherLink.js.map +1 -0
  54. package/lib/module/types/helpers/index.js +13 -0
  55. package/lib/module/types/helpers/index.js.map +1 -0
  56. package/lib/module/types/helpers/urlConfig.js +19 -0
  57. package/lib/module/types/helpers/urlConfig.js.map +1 -0
  58. package/lib/module/types/index.js +7 -0
  59. package/lib/module/types/index.js.map +1 -0
  60. package/lib/module/types/interfaces/callbacks.js +2 -0
  61. package/lib/module/types/interfaces/callbacks.js.map +1 -0
  62. package/lib/module/types/interfaces/customStyle.js +2 -0
  63. package/lib/module/types/interfaces/customStyle.js.map +1 -0
  64. package/lib/module/types/interfaces/index.js +9 -0
  65. package/lib/module/types/interfaces/index.js.map +1 -0
  66. package/lib/module/types/interfaces/initWidgetBase.js +4 -0
  67. package/lib/module/types/interfaces/initWidgetBase.js.map +1 -0
  68. package/lib/module/types/interfaces/merchant.js +2 -0
  69. package/lib/module/types/interfaces/merchant.js.map +1 -0
  70. package/lib/module/types/interfaces/order.js +2 -0
  71. package/lib/module/types/interfaces/order.js.map +1 -0
  72. package/lib/module/types/interfaces/user.js +2 -0
  73. package/lib/module/types/interfaces/user.js.map +1 -0
  74. package/lib/module/types/utils/hasKey.js +8 -0
  75. package/lib/module/types/utils/hasKey.js.map +1 -0
  76. package/lib/module/types/utils/index.js +4 -0
  77. package/lib/module/types/utils/index.js.map +1 -0
  78. package/lib/typescript/deuna-sdk-react-native/src/DeunaLogs.d.ts +6 -0
  79. package/lib/typescript/deuna-sdk-react-native/src/DeunaLogs.d.ts.map +1 -0
  80. package/lib/typescript/deuna-sdk-react-native/src/DeunaSDK.d.ts +88 -0
  81. package/lib/typescript/deuna-sdk-react-native/src/DeunaSDK.d.ts.map +1 -0
  82. package/lib/typescript/deuna-sdk-react-native/src/components/DeunaWebView.d.ts +11 -0
  83. package/lib/typescript/deuna-sdk-react-native/src/components/DeunaWebView.d.ts.map +1 -0
  84. package/lib/typescript/deuna-sdk-react-native/src/components/DeunaWidget.d.ts +7 -0
  85. package/lib/typescript/deuna-sdk-react-native/src/components/DeunaWidget.d.ts.map +1 -0
  86. package/lib/typescript/deuna-sdk-react-native/src/components/NewTabWebView.d.ts +7 -0
  87. package/lib/typescript/deuna-sdk-react-native/src/components/NewTabWebView.d.ts.map +1 -0
  88. package/lib/typescript/deuna-sdk-react-native/src/components/WebViewLoader.d.ts +2 -0
  89. package/lib/typescript/deuna-sdk-react-native/src/components/WebViewLoader.d.ts.map +1 -0
  90. package/lib/typescript/deuna-sdk-react-native/src/controllers/BaseWebViewController.d.ts +83 -0
  91. package/lib/typescript/deuna-sdk-react-native/src/controllers/BaseWebViewController.d.ts.map +1 -0
  92. package/lib/typescript/deuna-sdk-react-native/src/controllers/ElementsWidgetController.d.ts +9 -0
  93. package/lib/typescript/deuna-sdk-react-native/src/controllers/ElementsWidgetController.d.ts.map +1 -0
  94. package/lib/typescript/deuna-sdk-react-native/src/controllers/OpenInNewTabController.d.ts +12 -0
  95. package/lib/typescript/deuna-sdk-react-native/src/controllers/OpenInNewTabController.d.ts.map +1 -0
  96. package/lib/typescript/deuna-sdk-react-native/src/controllers/PaymentWidgetController.d.ts +12 -0
  97. package/lib/typescript/deuna-sdk-react-native/src/controllers/PaymentWidgetController.d.ts.map +1 -0
  98. package/lib/typescript/deuna-sdk-react-native/src/helpers/Completer.d.ts +12 -0
  99. package/lib/typescript/deuna-sdk-react-native/src/helpers/Completer.d.ts.map +1 -0
  100. package/lib/typescript/deuna-sdk-react-native/src/helpers/getController.d.ts +22 -0
  101. package/lib/typescript/deuna-sdk-react-native/src/helpers/getController.d.ts.map +1 -0
  102. package/lib/typescript/deuna-sdk-react-native/src/index.d.ts +5 -0
  103. package/lib/typescript/deuna-sdk-react-native/src/index.d.ts.map +1 -0
  104. package/lib/typescript/deuna-sdk-react-native/src/interfaces/constants.d.ts +6 -0
  105. package/lib/typescript/deuna-sdk-react-native/src/interfaces/constants.d.ts.map +1 -0
  106. package/lib/typescript/deuna-sdk-react-native/src/interfaces/errors.d.ts +32 -0
  107. package/lib/typescript/deuna-sdk-react-native/src/interfaces/errors.d.ts.map +1 -0
  108. package/lib/typescript/deuna-sdk-react-native/src/interfaces/events/checkout.d.ts +46 -0
  109. package/lib/typescript/deuna-sdk-react-native/src/interfaces/events/checkout.d.ts.map +1 -0
  110. package/lib/typescript/deuna-sdk-react-native/src/interfaces/events/elements.d.ts +29 -0
  111. package/lib/typescript/deuna-sdk-react-native/src/interfaces/events/elements.d.ts.map +1 -0
  112. package/lib/typescript/deuna-sdk-react-native/src/interfaces/index.d.ts +4 -0
  113. package/lib/typescript/deuna-sdk-react-native/src/interfaces/index.d.ts.map +1 -0
  114. package/lib/typescript/deuna-sdk-react-native/src/interfaces/types.d.ts +15 -0
  115. package/lib/typescript/deuna-sdk-react-native/src/interfaces/types.d.ts.map +1 -0
  116. package/lib/typescript/deuna-sdk-react-native/src/types/base.d.ts +91 -0
  117. package/lib/typescript/deuna-sdk-react-native/src/types/base.d.ts.map +1 -0
  118. package/lib/typescript/deuna-sdk-react-native/src/types/env.d.ts +45 -0
  119. package/lib/typescript/deuna-sdk-react-native/src/types/env.d.ts.map +1 -0
  120. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildElementsLink.d.ts +3 -0
  121. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildElementsLink.d.ts.map +1 -0
  122. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildNextActionLink.d.ts +3 -0
  123. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildNextActionLink.d.ts.map +1 -0
  124. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildPaymentLink.d.ts +8 -0
  125. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildPaymentLink.d.ts.map +1 -0
  126. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildVoucherLink.d.ts +8 -0
  127. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildVoucherLink.d.ts.map +1 -0
  128. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/index.d.ts +7 -0
  129. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/index.d.ts.map +1 -0
  130. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/urlConfig.d.ts +34 -0
  131. package/lib/typescript/deuna-sdk-react-native/src/types/helpers/urlConfig.d.ts.map +1 -0
  132. package/lib/typescript/deuna-sdk-react-native/src/types/index.d.ts +5 -0
  133. package/lib/typescript/deuna-sdk-react-native/src/types/index.d.ts.map +1 -0
  134. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/callbacks.d.ts +38 -0
  135. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/callbacks.d.ts.map +1 -0
  136. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/customStyle.d.ts +156 -0
  137. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/customStyle.d.ts.map +1 -0
  138. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/index.d.ts +7 -0
  139. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/index.d.ts.map +1 -0
  140. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/initWidgetBase.d.ts +78 -0
  141. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/initWidgetBase.d.ts.map +1 -0
  142. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/merchant.d.ts +76 -0
  143. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/merchant.d.ts.map +1 -0
  144. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/order.d.ts +3 -0
  145. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/order.d.ts.map +1 -0
  146. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/user.d.ts +23 -0
  147. package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/user.d.ts.map +1 -0
  148. package/lib/typescript/deuna-sdk-react-native/src/types/utils/hasKey.d.ts +2 -0
  149. package/lib/typescript/deuna-sdk-react-native/src/types/utils/hasKey.d.ts.map +1 -0
  150. package/lib/typescript/deuna-sdk-react-native/src/types/utils/index.d.ts +2 -0
  151. package/lib/typescript/deuna-sdk-react-native/src/types/utils/index.d.ts.map +1 -0
  152. package/lib/typescript/package.json +1 -0
  153. package/package.json +159 -0
  154. package/src/DeunaLogs.ts +17 -0
  155. package/src/DeunaSDK.ts +269 -0
  156. package/src/components/DeunaWebView.tsx +38 -0
  157. package/src/components/DeunaWidget.tsx +92 -0
  158. package/src/components/NewTabWebView.tsx +61 -0
  159. package/src/components/WebViewLoader.tsx +22 -0
  160. package/src/controllers/BaseWebViewController.ts +289 -0
  161. package/src/controllers/ElementsWidgetController.ts +78 -0
  162. package/src/controllers/OpenInNewTabController.ts +39 -0
  163. package/src/controllers/PaymentWidgetController.ts +118 -0
  164. package/src/helpers/Completer.ts +33 -0
  165. package/src/helpers/getController.ts +83 -0
  166. package/src/index.tsx +4 -0
  167. package/src/interfaces/constants.ts +5 -0
  168. package/src/interfaces/errors.ts +34 -0
  169. package/src/interfaces/events/checkout.ts +46 -0
  170. package/src/interfaces/events/elements.ts +29 -0
  171. package/src/interfaces/index.ts +3 -0
  172. package/src/interfaces/types.ts +13 -0
  173. package/src/types/base.ts +126 -0
  174. package/src/types/env.ts +51 -0
  175. package/src/types/helpers/buildElementsLink.ts +87 -0
  176. package/src/types/helpers/buildNextActionLink.ts +42 -0
  177. package/src/types/helpers/buildPaymentLink.ts +63 -0
  178. package/src/types/helpers/buildVoucherLink.ts +53 -0
  179. package/src/types/helpers/index.ts +11 -0
  180. package/src/types/helpers/urlConfig.ts +80 -0
  181. package/src/types/index.ts +4 -0
  182. package/src/types/interfaces/callbacks.ts +43 -0
  183. package/src/types/interfaces/customStyle.ts +189 -0
  184. package/src/types/interfaces/index.ts +6 -0
  185. package/src/types/interfaces/initWidgetBase.ts +97 -0
  186. package/src/types/interfaces/merchant.ts +79 -0
  187. package/src/types/interfaces/order.ts +1 -0
  188. package/src/types/interfaces/user.ts +22 -0
  189. package/src/types/utils/hasKey.ts +5 -0
  190. package/src/types/utils/index.ts +1 -0
@@ -0,0 +1,289 @@
1
+ import type WebView from 'react-native-webview';
2
+ import { DeunaLogs } from '../DeunaLogs';
3
+ import { WebViewMessageEvent } from 'react-native-webview';
4
+ import {
5
+ ClosedAction,
6
+ CustomStyles,
7
+ Json,
8
+ State,
9
+ SubmitResult,
10
+ } from '../types';
11
+ import { submitError } from '../interfaces';
12
+
13
+ export interface WebViewDelegate {
14
+ onOpenInNewTab?: (url: string) => void;
15
+ onCloseButtonPressed?: () => void;
16
+ onCloseSubWebView?: () => void;
17
+ }
18
+
19
+ export enum WebViewEventType {
20
+ consoleLog = 'consoleLog',
21
+ eventDispatch = 'eventDispatch',
22
+ jsExecutor = 'jsExecutor',
23
+ openInNewTab = 'openInNewTab',
24
+ redirect = 'redirect',
25
+ }
26
+
27
+ export abstract class BaseWebViewController {
28
+ webView: WebView | null = null;
29
+ url: string | null = null;
30
+
31
+ delegate: WebViewDelegate | null = null;
32
+
33
+ abstract setWebView: (webView: WebView) => void;
34
+ abstract onMessage: (event: WebViewMessageEvent) => void;
35
+
36
+ /**
37
+ * Called when the web view url is loaded successfully
38
+ */
39
+ abstract onLoad: () => void;
40
+
41
+ /**
42
+ * Called when the web view fails to load a URL
43
+ */
44
+ abstract onError: (event: any) => void;
45
+
46
+ /**
47
+ * Release the web view resources
48
+ */
49
+ dispose() {
50
+ this.webView?.stopLoading();
51
+ this.webView = null;
52
+ }
53
+ }
54
+
55
+ export abstract class DeunaWebViewController extends BaseWebViewController {
56
+ hidePayButton = false;
57
+ redirectUrl: string | null = null;
58
+ closedAction: ClosedAction = 'systemAction';
59
+ jsExecutor = new JsExecutor();
60
+
61
+ abstract onEventDispatch: (event: Record<string, any>) => void;
62
+
63
+ setWebView = (webView: WebView) => {
64
+ this.webView = webView;
65
+ this.jsExecutor.webView = webView;
66
+ };
67
+
68
+ onLoad = () => {
69
+ this.setXprops();
70
+ };
71
+
72
+ onMessage = (event: WebViewMessageEvent) => {
73
+ const eventData = JSON.parse(event.nativeEvent.data);
74
+
75
+ const mapper = {
76
+ [WebViewEventType.consoleLog]: () => {
77
+ DeunaLogs.info(
78
+ `CONSOLE LOG`,
79
+ JSON.stringify(eventData.message, null, 2)
80
+ );
81
+ },
82
+ [WebViewEventType.eventDispatch]: () => {
83
+ this.onEventDispatch(eventData.event);
84
+ },
85
+ [WebViewEventType.jsExecutor]: () => {
86
+ const { data, requestId } = eventData as {
87
+ requestId: number;
88
+ data: Record<string, any> | null;
89
+ };
90
+ this.jsExecutor.requests.get(requestId)?.(data);
91
+ this.jsExecutor.requests.delete(requestId);
92
+ },
93
+ [WebViewEventType.openInNewTab]: () => {
94
+ this.delegate?.onOpenInNewTab?.(eventData.url);
95
+ },
96
+ [WebViewEventType.redirect]: () => {
97
+ if (this.redirectUrl) {
98
+ return;
99
+ }
100
+ this.redirectUrl = eventData.url;
101
+ this.delegate?.onOpenInNewTab?.(eventData.url);
102
+ },
103
+ };
104
+
105
+ mapper[eventData.type as WebViewEventType]?.();
106
+ };
107
+
108
+ setXprops = () => {
109
+ this.webView?.injectJavaScript(
110
+ `
111
+ document.addEventListener('click', function(event) {
112
+ if (event.target.tagName === 'A' && event.target.href) {
113
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.redirect}', url: event.target.href }));
114
+ event.preventDefault(); // Prevent default navigation
115
+ event.stopPropagation();
116
+ }
117
+ });
118
+ console.log = function(message) {
119
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.consoleLog}', message }));
120
+ };
121
+ window.open = function(url, target, features) {
122
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.openInNewTab}', url }));
123
+ };
124
+ window.xprops = {
125
+ hidePayButton: ${this.hidePayButton},
126
+ onEventDispatch: function (event) {
127
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.eventDispatch}', event }));
128
+ },
129
+ onCustomStyleSubscribe: function (fn) {
130
+ window.setCustomStyle = fn;
131
+ },
132
+ onRefetchOrderSubscribe: function (fn) {
133
+ window.deunaRefetchOrder = fn;
134
+ },
135
+ onGetStateSubscribe: function (state){
136
+ window.deunaWidgetState = state;
137
+ },
138
+ isValid: function(fn){
139
+ window.isValid = fn;
140
+ },
141
+ onSubmit: function (fn) {
142
+ window.submit = fn;
143
+ },
144
+ }
145
+ `
146
+ );
147
+ };
148
+
149
+ /**
150
+ * Gets the current widget state
151
+ * @returns The widget state
152
+ */
153
+ getWidgetState = async (): Promise<State> => {
154
+ const result = await this.jsExecutor.execute(`
155
+ if(!window.deunaWidgetState){
156
+ sendResult({ deunaWidgetState: null });
157
+ return;
158
+ }
159
+ sendResult({ deunaWidgetState: window.deunaWidgetState });
160
+ `);
161
+ return result?.deunaWidgetState;
162
+ };
163
+
164
+ /**
165
+ * Refetches the order
166
+ * @returns The order data | returns null if the order is not found or an error occurs
167
+ */
168
+ refetchOrder = async (): Promise<Json | null> => {
169
+ const result = await this.jsExecutor.execute(`
170
+ if(typeof window.deunaRefetchOrder !== 'function'){
171
+ sendResult({order: null});
172
+ return;
173
+ }
174
+ window.deunaRefetchOrder()
175
+ .then((order) => {
176
+ sendResult({order});
177
+ })
178
+ .catch(() => {
179
+ sendResult({data: null});
180
+ });
181
+ `);
182
+ return result?.order ?? null;
183
+ };
184
+
185
+ /**
186
+ * Sets the custom style for the widget
187
+ * @param style - The custom style to set
188
+ */
189
+ setCustomStyle = async (style: Partial<CustomStyles>): Promise<void> => {
190
+ await this.jsExecutor.execute(`
191
+ window.setCustomStyle(${JSON.stringify(style)});
192
+ `);
193
+ };
194
+
195
+ /**
196
+ * Checks if the widget form data is valid
197
+ */
198
+ isValid = async (): Promise<boolean> => {
199
+ const data = await this.jsExecutor.execute(`
200
+ if(typeof window.isValid !== 'function'){
201
+ console.log('❌ window.isValid is not a function');
202
+ sendResult({isValid:false});
203
+ return;
204
+ }
205
+ sendResult( {isValid: window.isValid() });
206
+ `);
207
+ return data?.isValid ?? false;
208
+ };
209
+
210
+ /**
211
+ * Submits the form data to the server
212
+ * @returns The result of the submission
213
+ */
214
+ submit = async (): Promise<SubmitResult> => {
215
+ const data = await this.jsExecutor.execute(`
216
+ if(typeof window.submit !== 'function'){
217
+ console.log('❌ window.submit is not a function');
218
+ sendResult({status:"${submitError.status}", code:"${submitError.code}", message:"${submitError.message}" });
219
+ return;
220
+ }
221
+ window.submit()
222
+ .then((data) => {
223
+ sendResult(data);
224
+ })
225
+ .catch((error) => {
226
+ sendResult({status:"${submitError.status}", code:"${submitError.code}", message: error.message ?? "${submitError.message}" });
227
+ });
228
+ `);
229
+ return data as SubmitResult;
230
+ };
231
+
232
+ takeScreenshot = async (): Promise<string> => {
233
+ const data = await this.jsExecutor.execute(`
234
+ function takeScreenshot() {
235
+ html2canvas(document.body, { allowTaint: true, useCORS: true })
236
+ .then((canvas) => {
237
+ // Convert the canvas to a base64 image
238
+ var imgData = canvas.toDataURL("image/png");
239
+ sendResult({imgData: imgData});
240
+ })
241
+ .catch((error) => {
242
+ sendResult({imgData: null});
243
+ });
244
+ }
245
+
246
+ // If html2canvas is not added
247
+ if (typeof html2canvas === "undefined") {
248
+ var script = document.createElement("script");
249
+ script.src = "https://html2canvas.hertzen.com/dist/html2canvas.min.js";
250
+ script.onload = function() {
251
+ takeScreenshot();
252
+ };
253
+ document.head.appendChild(script);
254
+ } else {
255
+ takeScreenshot();
256
+ }
257
+ `);
258
+ return data?.imgData ?? null;
259
+ };
260
+ }
261
+
262
+ class JsExecutor {
263
+ requestId = 0;
264
+ webView: WebView | null = null;
265
+ requests: Map<number, (data: Record<string, any> | null) => void> = new Map();
266
+
267
+ /**
268
+ * Executes javascript code in the web view
269
+ * @param jsCode - The javascript code to execute
270
+ * @returns The result of the javascript code
271
+ */
272
+
273
+ execute = (jsCode: string): Promise<Record<string, any> | null> => {
274
+ this.requestId++;
275
+ this.webView?.injectJavaScript(
276
+ `
277
+ (function() {
278
+ function sendResult(data){
279
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.jsExecutor}', data: data, requestId: ${this.requestId} }));
280
+ }
281
+ ${jsCode}
282
+ })();
283
+ `
284
+ );
285
+ return new Promise((resolve) => {
286
+ this.requests.set(this.requestId, resolve);
287
+ });
288
+ };
289
+ }
@@ -0,0 +1,78 @@
1
+ import { DeunaWebViewController } from './BaseWebViewController';
2
+ import {
3
+ ElementsEvent,
4
+ ElementsEventType,
5
+ } from '../interfaces/events/elements';
6
+ import { ElementsWidgetCallbacks } from '../types';
7
+ import { ElementsErrorType } from '../interfaces';
8
+
9
+ export class ElementsWidgetController extends DeunaWebViewController {
10
+ constructor(readonly callbacks: ElementsWidgetCallbacks) {
11
+ super();
12
+ }
13
+
14
+ onError = (event: any) => {
15
+ this.callbacks.onError?.({
16
+ type: ElementsErrorType.errorWhileLoadingTheURL,
17
+ metadata: {
18
+ code: ElementsErrorType.errorWhileLoadingTheURL,
19
+ message: event.message ?? 'Error while loading the URL',
20
+ },
21
+ });
22
+ };
23
+
24
+ onEventDispatch = (event: Record<string, any>) => {
25
+ const elementsEvent = event as ElementsEvent;
26
+
27
+ if (this.callbacks.onEventDispatch) {
28
+ this.callbacks.onEventDispatch(elementsEvent.type, elementsEvent.data);
29
+ }
30
+
31
+ const mapper: Partial<Record<ElementsEventType, () => void>> = {
32
+ [ElementsEventType.vaultClosed]: () => {
33
+ this.closedAction = 'userAction';
34
+ this.delegate?.onCloseButtonPressed?.();
35
+ },
36
+ [ElementsEventType.vaultSaveSuccess]: () => {
37
+ this.delegate?.onCloseSubWebView?.();
38
+ this.callbacks.onSuccess?.(event.data);
39
+ },
40
+ [ElementsEventType.vaultSaveError]: () => {
41
+ this.delegate?.onCloseSubWebView?.();
42
+ this.delegate?.onCloseSubWebView?.();
43
+ const { metadata } = elementsEvent.data;
44
+
45
+ if (metadata) {
46
+ const errorCode =
47
+ metadata.code ??
48
+ metadata.errorCode ??
49
+ ElementsErrorType.unknownError;
50
+
51
+ const errorMessage =
52
+ metadata.message ??
53
+ metadata.errorMessage ??
54
+ metadata.reason ??
55
+ 'unknown error';
56
+
57
+ this.callbacks.onError?.({
58
+ type: ElementsErrorType.vaultSaveError,
59
+ metadata: {
60
+ code: errorCode,
61
+ message: errorMessage,
62
+ },
63
+ });
64
+ } else {
65
+ this.callbacks.onError?.({
66
+ type: ElementsErrorType.unknownError,
67
+ metadata: {
68
+ code: ElementsErrorType.unknownError,
69
+ message: 'unknown error',
70
+ },
71
+ });
72
+ }
73
+ },
74
+ };
75
+
76
+ mapper[elementsEvent.type]?.();
77
+ };
78
+ }
@@ -0,0 +1,39 @@
1
+ import WebView, { WebViewMessageEvent } from 'react-native-webview';
2
+ import { BaseWebViewController } from './BaseWebViewController';
3
+ import { DeunaLogs } from '../DeunaLogs';
4
+
5
+ export class OpenInNewTabController extends BaseWebViewController {
6
+ constructor(readonly url: string) {
7
+ super();
8
+ this.url = url;
9
+ }
10
+
11
+ setWebView = (webView: WebView) => {
12
+ this.webView = webView;
13
+ };
14
+
15
+ onLoad = () => {
16
+ this.setXprops();
17
+ };
18
+
19
+ onError = (event: any) => {
20
+ console.warn(event);
21
+ };
22
+
23
+ onMessage = (event: WebViewMessageEvent) => {
24
+ const eventData = JSON.parse(event.nativeEvent.data);
25
+ if (eventData.type === 'console_log') {
26
+ DeunaLogs.info(`CONSOLE LOG`, eventData.message);
27
+ }
28
+ };
29
+
30
+ setXprops = () => {
31
+ this.webView?.injectJavaScript(
32
+ `
33
+ console.log = function(message) {
34
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'console_log', message }));
35
+ };
36
+ `
37
+ );
38
+ };
39
+ }
@@ -0,0 +1,118 @@
1
+ import {
2
+ CheckoutEvent,
3
+ CheckoutEventType,
4
+ PaymentErrorType,
5
+ } from '../interfaces';
6
+ import { constants } from '../interfaces/constants';
7
+ import { DownloadType, OnDownloadFile } from '../interfaces/types';
8
+ import {
9
+ PaymentWidgetCallbacks,
10
+ NextActionWidgetCallbacks,
11
+ VoucherWidgetCallbacks,
12
+ } from '../types';
13
+ import { DeunaWebViewController } from './BaseWebViewController';
14
+
15
+ type Callbacks = PaymentWidgetCallbacks &
16
+ NextActionWidgetCallbacks &
17
+ VoucherWidgetCallbacks &
18
+ OnDownloadFile;
19
+
20
+ export class PaymentWidgetController extends DeunaWebViewController {
21
+ constructor(readonly callbacks: Callbacks) {
22
+ super();
23
+ }
24
+
25
+ onError = (event: any) => {
26
+ this.callbacks.onError?.({
27
+ type: PaymentErrorType.errorWhileLoadingTheURL,
28
+ metadata: {
29
+ code: PaymentErrorType.errorWhileLoadingTheURL,
30
+ message: event.message ?? 'Error while loading the URL',
31
+ },
32
+ });
33
+ };
34
+
35
+ onEventDispatch = async (event: Record<string, any>) => {
36
+ const checkoutEvent = event as CheckoutEvent;
37
+
38
+ // This event is used to listen when a voucher save request is made
39
+ if (checkoutEvent.type === constants.apmSaveId) {
40
+ const { voucherPdfDownloadUrl }: { voucherPdfDownloadUrl?: string } =
41
+ checkoutEvent.data.metadata;
42
+
43
+ // If the file url is provided, download the file and save it to the device
44
+ if (voucherPdfDownloadUrl) {
45
+ this.callbacks.onDownloadFile?.({
46
+ type: DownloadType.URL,
47
+ data: voucherPdfDownloadUrl,
48
+ });
49
+ } else {
50
+ // Take a screenshot of current content in the webview
51
+ const base64Image = await this.takeScreenshot();
52
+ if (base64Image) {
53
+ this.callbacks.onDownloadFile?.({
54
+ type: DownloadType.BASE64,
55
+ data: base64Image,
56
+ });
57
+ }
58
+ }
59
+ return;
60
+ }
61
+
62
+ if (this.callbacks.onEventDispatch) {
63
+ this.callbacks.onEventDispatch(checkoutEvent.type, checkoutEvent.data);
64
+ }
65
+
66
+ const mapper: Partial<Record<CheckoutEventType, () => void>> = {
67
+ [CheckoutEventType.linkClose]: () => {
68
+ this.closedAction = 'userAction';
69
+ this.delegate?.onCloseButtonPressed?.();
70
+ },
71
+ [CheckoutEventType.onBinDetected]: () => {
72
+ this.callbacks.onCardBinDetected?.(checkoutEvent.data.metadata);
73
+ },
74
+ [CheckoutEventType.onInstallmentSelected]: () => {
75
+ this.callbacks.onInstallmentSelected?.(checkoutEvent.data.metadata);
76
+ },
77
+ [CheckoutEventType.paymentProcessing]: () => {
78
+ this.callbacks.onPaymentProcessing?.();
79
+ },
80
+ [CheckoutEventType.purchase]: () => {
81
+ this.delegate?.onCloseSubWebView?.();
82
+ this.callbacks.onSuccess?.(checkoutEvent.data.order);
83
+ },
84
+ [CheckoutEventType.purchaseError]: () => {
85
+ this.delegate?.onCloseSubWebView?.();
86
+ const { metadata } = checkoutEvent.data;
87
+
88
+ if (metadata) {
89
+ const errorCode =
90
+ metadata.code ??
91
+ metadata.errorCode ??
92
+ PaymentErrorType.unknownError;
93
+
94
+ const errorMessage =
95
+ metadata.message ??
96
+ metadata.errorMessage ??
97
+ metadata.reason ??
98
+ 'unknown error';
99
+
100
+ this.callbacks.onError?.({
101
+ type: PaymentErrorType.paymentError,
102
+ metadata: { code: errorCode, message: errorMessage },
103
+ });
104
+ } else {
105
+ this.callbacks.onError?.({
106
+ type: PaymentErrorType.unknownError,
107
+ metadata: {
108
+ code: PaymentErrorType.unknownError,
109
+ message: 'unknown error',
110
+ },
111
+ });
112
+ }
113
+ },
114
+ };
115
+
116
+ mapper[checkoutEvent.type]?.();
117
+ };
118
+ }
@@ -0,0 +1,33 @@
1
+ export class Completer<T> {
2
+ private promise: Promise<T>;
3
+ private resolvePromise: ((value: T | PromiseLike<T>) => void) | null = null;
4
+ private rejectPromise: ((reason?: any) => void) | null = null;
5
+ private completed = false;
6
+
7
+ constructor() {
8
+ this.promise = new Promise<T>((resolve, reject) => {
9
+ this.resolvePromise = resolve;
10
+ this.rejectPromise = reject;
11
+ });
12
+ }
13
+
14
+ get wait(): Promise<T> {
15
+ return this.promise;
16
+ }
17
+
18
+ complete(value: T): void {
19
+ if (this.completed) return;
20
+ this.completed = true;
21
+ this.resolvePromise?.(value);
22
+ }
23
+
24
+ completeError(error: any): void {
25
+ if (this.completed) return;
26
+ this.completed = true;
27
+ this.rejectPromise?.(error);
28
+ }
29
+
30
+ isCompleted(): boolean {
31
+ return this.completed;
32
+ }
33
+ }
@@ -0,0 +1,83 @@
1
+ import { DeunaWebViewController } from '../controllers/BaseWebViewController';
2
+ import { PaymentWidgetController } from '../controllers/PaymentWidgetController';
3
+ import { ElementsWidgetController } from '../controllers/ElementsWidgetController';
4
+ import {
5
+ InitElementsWidgetParams,
6
+ InitializeParams,
7
+ InitNextActionWidgetParams,
8
+ InitPaymentWidgetParams,
9
+ InitVoucherWidgetParams,
10
+ } from '../types';
11
+ import { linkBuilders } from '../types/helpers';
12
+ import { Mode } from '../interfaces/types';
13
+ import { DeunaLogs } from '../DeunaLogs';
14
+
15
+ type PaymentWidgetControllerProps = InitPaymentWidgetParams & {
16
+ widget: 'payment';
17
+ };
18
+
19
+ type NextActionWidgetControllerProps = InitNextActionWidgetParams & {
20
+ widget: 'nextAction';
21
+ };
22
+
23
+ type VoucherWidgetControllerProps = InitVoucherWidgetParams & {
24
+ widget: 'voucher';
25
+ };
26
+
27
+ type ElementsWidgetControllerProps = InitElementsWidgetParams & {
28
+ widget: 'elements';
29
+ };
30
+
31
+ type ControllerProps =
32
+ | PaymentWidgetControllerProps
33
+ | NextActionWidgetControllerProps
34
+ | VoucherWidgetControllerProps
35
+ | ElementsWidgetControllerProps;
36
+
37
+ export const getWidgetController = (
38
+ config: InitializeParams,
39
+ props: ControllerProps & { mode?: Mode; sessionId?: string }
40
+ ): DeunaWebViewController => {
41
+ const { widget, mode, callbacks, ...rest } = props;
42
+
43
+ const baseParams = {
44
+ env: config.environment!,
45
+ publicApiKey: config.publicApiKey,
46
+ orderToken: rest.orderToken ?? '',
47
+ userToken: rest.userToken ?? '',
48
+ language: rest.language ?? 'es',
49
+ sessionId: rest.sessionId ?? '',
50
+ mode: mode ?? Mode.MODAL,
51
+ };
52
+
53
+ const widgetMappers = {
54
+ elements: () => ({
55
+ ...baseParams,
56
+ userInfo: rest.userInfo,
57
+ styleFile: rest.styleFile,
58
+ behavior: rest.behavior,
59
+ widgetExperience: rest.widgetExperience,
60
+ types: (props as ElementsWidgetControllerProps).types,
61
+ }),
62
+ payment: () => ({
63
+ ...baseParams,
64
+ behavior: rest.behavior,
65
+ paymentMethods: (props as PaymentWidgetControllerProps).paymentMethods,
66
+ styleFile: rest.styleFile,
67
+ }),
68
+ nextAction: () => baseParams,
69
+ voucher: () => baseParams,
70
+ };
71
+
72
+ const controller =
73
+ widget === 'elements'
74
+ ? new ElementsWidgetController(callbacks)
75
+ : new PaymentWidgetController(callbacks);
76
+
77
+ controller.url = linkBuilders[widget](widgetMappers[widget]());
78
+ controller.hidePayButton = rest.hidePayButton ?? false;
79
+
80
+ DeunaLogs.info('👀 loading link', controller.url);
81
+
82
+ return controller;
83
+ };
package/src/index.tsx ADDED
@@ -0,0 +1,4 @@
1
+ export * from './DeunaSDK';
2
+ export * from './components/DeunaWidget';
3
+ export * from './types';
4
+ export * from './interfaces';
@@ -0,0 +1,5 @@
1
+ export const constants = {
2
+ apmSaveId: 'apmSaveId',
3
+ metadata: 'metadata',
4
+ voucherPdfDownloadUrl: 'voucherPdfDownloadUrl',
5
+ };
@@ -0,0 +1,34 @@
1
+ export const initializationError = {
2
+ type: 'INITIALIZATION_ERROR',
3
+ code: 'INITIALIZATION_ERROR',
4
+ message: 'Failed to initialize the widget',
5
+ };
6
+
7
+ export const submitError = {
8
+ status: 'error',
9
+ code: 'error',
10
+ message: 'Error al procesar la solicitud.',
11
+ };
12
+
13
+ export enum PaymentErrorType {
14
+ noInternetConnection = 'noInternetConnection',
15
+ invalidOrderToken = 'invalidOrderToken',
16
+ initializationFailed = 'initializationFailed',
17
+ errorWhileLoadingTheURL = 'errorWhileLoadingTheURL',
18
+ orderNotFound = 'orderNotFound',
19
+ orderCouldNotBeRetrieved = 'orderCouldNotBeRetrieved',
20
+ paymentError = 'paymentError',
21
+ userError = 'userError',
22
+ unknownError = 'unknownError',
23
+ }
24
+
25
+ export enum ElementsErrorType {
26
+ noInternetConnection = 'noInternetConnection',
27
+ initializationFailed = 'initializationFailed',
28
+ errorWhileLoadingTheURL = 'errorWhileLoadingTheURL',
29
+ userError = 'userError',
30
+ invalidUserToken = 'invalidUserToken',
31
+ unknownError = 'unknownError',
32
+ vaultSaveError = 'vaultSaveError',
33
+ vaultFailed = 'vaultFailed',
34
+ }