@glomopay/react-native-sdk 4.0.0 → 5.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/CHANGELOG.md +29 -0
- package/MIGRATION.md +112 -0
- package/README.md +173 -36
- package/lib/bridge/file-input-handler.d.ts +25 -0
- package/lib/bridge/file-input-handler.d.ts.map +1 -0
- package/lib/bridge/file-input-handler.js +38 -0
- package/lib/bridge/file-save-handler.d.ts +32 -0
- package/lib/bridge/file-save-handler.d.ts.map +1 -0
- package/lib/bridge/file-save-handler.js +92 -0
- package/lib/bridge/message-router.d.ts +44 -0
- package/lib/bridge/message-router.d.ts.map +1 -0
- package/lib/bridge/message-router.js +48 -0
- package/lib/bridge/payment-payload.d.ts +18 -0
- package/lib/bridge/payment-payload.d.ts.map +1 -0
- package/lib/bridge/payment-payload.js +31 -0
- package/lib/capabilities/file-save.d.ts +40 -0
- package/lib/capabilities/file-save.d.ts.map +1 -0
- package/lib/capabilities/file-save.js +101 -0
- package/lib/capabilities/index.d.ts +22 -0
- package/lib/capabilities/index.d.ts.map +1 -0
- package/lib/capabilities/index.js +34 -0
- package/lib/capabilities/use-capability-reporting.d.ts +24 -0
- package/lib/capabilities/use-capability-reporting.d.ts.map +1 -0
- package/lib/capabilities/use-capability-reporting.js +44 -0
- package/lib/config/base.d.ts +12 -0
- package/lib/config/base.d.ts.map +1 -1
- package/lib/config/base.js +13 -1
- package/lib/glomo-checkout.d.ts +9 -1
- package/lib/glomo-checkout.d.ts.map +1 -1
- package/lib/glomo-checkout.js +14 -5
- package/lib/glomo-lrs-checkout.d.ts +3 -0
- package/lib/glomo-lrs-checkout.d.ts.map +1 -1
- package/lib/glomo-lrs-checkout.js +34 -11
- package/lib/glomo-standard-checkout.d.ts +4 -1
- package/lib/glomo-standard-checkout.d.ts.map +1 -1
- package/lib/glomo-standard-checkout.js +21 -13
- package/lib/glomo-subscriptions-checkout.d.ts.map +1 -1
- package/lib/glomo-subscriptions-checkout.js +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -3
- package/lib/injections/index.d.ts +24 -0
- package/lib/injections/index.d.ts.map +1 -1
- package/lib/injections/index.js +41 -0
- package/lib/injections/webview-flow.injection.d.ts.map +1 -1
- package/lib/injections/webview-flow.injection.js +76 -0
- package/lib/injections/webview-main.injection.d.ts.map +1 -1
- package/lib/injections/webview-main.injection.js +31 -0
- package/lib/injections/webview-standard.injection.d.ts.map +1 -1
- package/lib/injections/webview-standard.injection.js +31 -0
- package/lib/services/file-saver.d.ts +109 -0
- package/lib/services/file-saver.d.ts.map +1 -0
- package/lib/services/file-saver.js +416 -0
- package/lib/types/checkout.d.ts +67 -6
- package/lib/types/checkout.d.ts.map +1 -1
- package/lib/types/checkout.js +24 -2
- package/lib/types/standard-checkout.d.ts +6 -6
- package/lib/types/standard-checkout.d.ts.map +1 -1
- package/lib/types/subscriptions-checkout.d.ts +5 -3
- package/lib/types/subscriptions-checkout.d.ts.map +1 -1
- package/lib/use-glomo-checkout.d.ts +2 -2
- package/lib/use-glomo-checkout.d.ts.map +1 -1
- package/lib/use-glomo-checkout.js +25 -4
- package/lib/use-lrs-checkout.d.ts +18 -6
- package/lib/use-lrs-checkout.d.ts.map +1 -1
- package/lib/use-lrs-checkout.js +330 -171
- package/lib/use-standard-checkout.d.ts +18 -13
- package/lib/use-standard-checkout.d.ts.map +1 -1
- package/lib/use-standard-checkout.js +282 -206
- package/lib/utils/analytics.d.ts +177 -51
- package/lib/utils/analytics.d.ts.map +1 -1
- package/lib/utils/analytics.js +299 -81
- package/lib/utils/device-compliance.d.ts +57 -12
- package/lib/utils/device-compliance.d.ts.map +1 -1
- package/lib/utils/device-compliance.js +101 -37
- package/lib/utils/event-projections.d.ts +56 -0
- package/lib/utils/event-projections.d.ts.map +1 -0
- package/lib/utils/event-projections.js +42 -0
- package/lib/utils/file-metadata.d.ts +52 -0
- package/lib/utils/file-metadata.d.ts.map +1 -0
- package/lib/utils/file-metadata.js +134 -0
- package/lib/utils/use-sdk-session.d.ts +12 -0
- package/lib/utils/use-sdk-session.d.ts.map +1 -0
- package/lib/utils/use-sdk-session.js +37 -0
- package/lib/utils/validation.d.ts +37 -3
- package/lib/utils/validation.d.ts.map +1 -1
- package/lib/utils/validation.js +64 -8
- package/lib/webview/capability-props.d.ts +27 -0
- package/lib/webview/capability-props.d.ts.map +1 -0
- package/lib/webview/capability-props.js +61 -0
- package/lib/webview/use-permission-request.d.ts +33 -0
- package/lib/webview/use-permission-request.d.ts.map +1 -0
- package/lib/webview/use-permission-request.js +89 -0
- package/package.json +13 -3
- package/src/bridge/file-input-handler.ts +66 -0
- package/src/bridge/file-save-handler.ts +141 -0
- package/src/bridge/message-router.ts +92 -0
- package/src/bridge/payment-payload.ts +31 -0
- package/src/capabilities/file-save.ts +124 -0
- package/src/capabilities/index.ts +34 -0
- package/src/capabilities/use-capability-reporting.ts +55 -0
- package/src/config/base.ts +13 -0
- package/src/glomo-checkout.tsx +28 -11
- package/src/glomo-lrs-checkout.tsx +49 -27
- package/src/glomo-standard-checkout.tsx +33 -34
- package/src/glomo-subscriptions-checkout.tsx +1 -0
- package/src/index.ts +4 -2
- package/src/injections/index.ts +43 -0
- package/src/injections/webview-flow.injection.ts +76 -0
- package/src/injections/webview-main.injection.ts +31 -0
- package/src/injections/webview-standard.injection.ts +31 -0
- package/src/services/file-saver.ts +497 -0
- package/src/types/checkout.ts +72 -6
- package/src/types/standard-checkout.ts +6 -6
- package/src/types/subscriptions-checkout.ts +9 -3
- package/src/use-glomo-checkout.tsx +32 -7
- package/src/use-lrs-checkout.tsx +684 -366
- package/src/use-standard-checkout.tsx +731 -465
- package/src/utils/analytics.ts +422 -117
- package/src/utils/device-compliance.ts +148 -38
- package/src/utils/event-projections.ts +74 -0
- package/src/utils/file-metadata.ts +140 -0
- package/src/utils/use-sdk-session.ts +41 -0
- package/src/utils/validation.ts +70 -10
- package/src/webview/capability-props.ts +86 -0
- package/src/webview/use-permission-request.ts +114 -0
- package/src/jail-monkey.d.ts +0 -19
package/lib/use-lrs-checkout.js
CHANGED
|
@@ -8,10 +8,21 @@ const index_1 = require("./injections/index");
|
|
|
8
8
|
const segment_1 = require("./config/segment");
|
|
9
9
|
const base_1 = require("./config/base");
|
|
10
10
|
const validation_1 = require("./utils/validation");
|
|
11
|
+
const payment_payload_1 = require("./bridge/payment-payload");
|
|
12
|
+
const event_projections_1 = require("./utils/event-projections");
|
|
11
13
|
const device_compliance_1 = require("./utils/device-compliance");
|
|
14
|
+
const use_permission_request_1 = require("./webview/use-permission-request");
|
|
15
|
+
const message_router_1 = require("./bridge/message-router");
|
|
16
|
+
const file_save_handler_1 = require("./bridge/file-save-handler");
|
|
17
|
+
const file_input_handler_1 = require("./bridge/file-input-handler");
|
|
18
|
+
const index_2 = require("./capabilities/index");
|
|
19
|
+
const use_capability_reporting_1 = require("./capabilities/use-capability-reporting");
|
|
20
|
+
const use_sdk_session_1 = require("./utils/use-sdk-session");
|
|
12
21
|
const analytics_1 = require("./utils/analytics");
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
const checkout_1 = require("./types/checkout");
|
|
23
|
+
/** Log prefix for everything this flow emits */
|
|
24
|
+
const LOG_PREFIX = "[Glomo-RN-SDK LRS]";
|
|
25
|
+
function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymentFailure, onConnectionError, onPaymentTerminate, onSdkError, onUserRefusedDevicePermissions, devMode = false, }, mockMode, internalOptions) {
|
|
15
26
|
// Refs for the WebViews
|
|
16
27
|
const mainWebViewRef = (0, react_1.useRef)(null);
|
|
17
28
|
const flowWebViewRef = (0, react_1.useRef)(null);
|
|
@@ -28,7 +39,7 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
28
39
|
// Building the query string manually since URLSearchParams is not fully supported in React Native
|
|
29
40
|
const baseParams = [`orderId=${encodeURIComponent(orderId)}`];
|
|
30
41
|
const mode = mockMode ? "mock" : "live";
|
|
31
|
-
const params = baseParams.concat(`mode=${encodeURIComponent(mode)}`, `publicKey=${encodeURIComponent(publicKey)}`);
|
|
42
|
+
const params = baseParams.concat(`mode=${encodeURIComponent(mode)}`, `publicKey=${encodeURIComponent(publicKey)}`, `product=${encodeURIComponent(base_1.ANALYTICS_PRODUCT)}`, `surface=${encodeURIComponent(base_1.ANALYTICS_SURFACE)}`);
|
|
32
43
|
const queryString = params.join("&");
|
|
33
44
|
// Handling base URL with or without existing query parameters
|
|
34
45
|
const separator = baseCheckoutUrl.includes("?") ? "&" : "?";
|
|
@@ -61,7 +72,9 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
61
72
|
const baseEducationCarouselUrl = serverConfig.baseUrl.lrsEducationCarousel;
|
|
62
73
|
const separator = baseEducationCarouselUrl.includes("?") ? "&" : "?";
|
|
63
74
|
const finalUrl = `${baseEducationCarouselUrl}${separator}orderId=${encodeURIComponent(orderId)}` +
|
|
64
|
-
`&publicKey=${encodeURIComponent(publicKey)}
|
|
75
|
+
`&publicKey=${encodeURIComponent(publicKey)}` +
|
|
76
|
+
`&product=${encodeURIComponent(base_1.ANALYTICS_PRODUCT)}` +
|
|
77
|
+
`&surface=${encodeURIComponent(base_1.ANALYTICS_SURFACE)}`;
|
|
65
78
|
if (!(0, validation_1.isValidUrl)(finalUrl)) {
|
|
66
79
|
if (devMode) {
|
|
67
80
|
console.error("[Glomo-RN-SDK LRS] Generated invalid education carousel URL:", finalUrl);
|
|
@@ -86,7 +99,17 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
86
99
|
const [showCheckout, setShowCheckout] = (0, react_1.useState)(false);
|
|
87
100
|
const [showFlowWebView, setShowFlowWebView] = (0, react_1.useState)(false);
|
|
88
101
|
const [flowWebViewUrl, setFlowWebViewUrl] = (0, react_1.useState)("");
|
|
89
|
-
const [educationCarouselState,
|
|
102
|
+
const [educationCarouselState, setEducationCarouselStateRaw] = (0, react_1.useState)("pending");
|
|
103
|
+
/** Wrapping the raw state setter to also fire the internal test callback */
|
|
104
|
+
const testCarouselCallbackRef = (0, react_1.useRef)(internalOptions === null || internalOptions === void 0 ? void 0 : internalOptions._onEducationCarouselStateChange);
|
|
105
|
+
testCarouselCallbackRef.current = internalOptions === null || internalOptions === void 0 ? void 0 : internalOptions._onEducationCarouselStateChange;
|
|
106
|
+
const setEducationCarouselState = (0, react_1.useCallback)((nextState) => {
|
|
107
|
+
var _a;
|
|
108
|
+
setEducationCarouselStateRaw(nextState);
|
|
109
|
+
if (__DEV__) {
|
|
110
|
+
(_a = testCarouselCallbackRef.current) === null || _a === void 0 ? void 0 : _a.call(testCarouselCallbackRef, nextState);
|
|
111
|
+
}
|
|
112
|
+
}, []);
|
|
90
113
|
(0, react_1.useEffect)(() => {
|
|
91
114
|
if (devMode) {
|
|
92
115
|
console.log(`[Glomo-RN-SDK LRS] Carousel state snapshot: status=${status}, showCheckout=${showCheckout}, showFlowWebView=${showFlowWebView}, flowWebViewUrl=${flowWebViewUrl || "<empty>"}, educationCarouselState=${educationCarouselState}, educationCarouselUrl=${educationCarouselUrl || "<empty>"}`);
|
|
@@ -158,35 +181,62 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
158
181
|
}
|
|
159
182
|
}
|
|
160
183
|
}, [devMode]);
|
|
184
|
+
// Correlates every event from this mount, and keeps checkoutStatus current on all of them
|
|
185
|
+
(0, use_sdk_session_1.useSdkSession)(() => status);
|
|
186
|
+
// Missing optional dependencies reach the host here; start() warns on the console separately
|
|
187
|
+
(0, use_capability_reporting_1.useCapabilityReporting)({ onSdkError, devMode });
|
|
188
|
+
/**
|
|
189
|
+
* Handler for `file.input` - the user tapping a file input on a bank's page.
|
|
190
|
+
*
|
|
191
|
+
* Registered beside `file.save` on the same WebViews, for the same reason: uploads are not a
|
|
192
|
+
* property of one flow, and until now this message had no handler anywhere.
|
|
193
|
+
*/
|
|
194
|
+
const fileInputHandler = (0, react_1.useMemo)(() => (0, file_input_handler_1.createFileInputHandler)({
|
|
195
|
+
flowType: "lrs",
|
|
196
|
+
orderId,
|
|
197
|
+
publicKey,
|
|
198
|
+
checkoutUrl,
|
|
199
|
+
mockMode,
|
|
200
|
+
devMode,
|
|
201
|
+
}), [orderId, publicKey, checkoutUrl, mockMode, devMode]);
|
|
202
|
+
/**
|
|
203
|
+
* Handler for `file.save` - the page asking the SDK to put a document on the device.
|
|
204
|
+
*
|
|
205
|
+
* One handler, registered on the main and flow WebViews both. Not on the education carousel:
|
|
206
|
+
* that renders our own content, which has nothing to gate, and the capability is not advertised
|
|
207
|
+
* there either.
|
|
208
|
+
*/
|
|
209
|
+
const fileSaveHandler = (0, react_1.useMemo)(() => (0, file_save_handler_1.createFileSaveHandler)({
|
|
210
|
+
flowType: "lrs",
|
|
211
|
+
orderId,
|
|
212
|
+
publicKey,
|
|
213
|
+
checkoutUrl,
|
|
214
|
+
mockMode,
|
|
215
|
+
devMode,
|
|
216
|
+
onSdkError,
|
|
217
|
+
}), [orderId, publicKey, checkoutUrl, mockMode, devMode, onSdkError]);
|
|
161
218
|
// Handler for the main WebView messages
|
|
162
|
-
const handleMainWebViewMessage = (0, react_1.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
const message = JSON.parse(data);
|
|
175
|
-
if (devMode) {
|
|
176
|
-
console.log("[Glomo-RN-SDK LRS] MainWebView Message received:", message.type, message);
|
|
177
|
-
}
|
|
178
|
-
if (message.type === "console") {
|
|
219
|
+
const handleMainWebViewMessage = (0, react_1.useMemo)(() => (0, message_router_1.createMessageRouter)({
|
|
220
|
+
logPrefix: LOG_PREFIX,
|
|
221
|
+
source: "MainWebView",
|
|
222
|
+
devMode,
|
|
223
|
+
onInvalidMessage: (data) => {
|
|
224
|
+
(0, analytics_1.trackInvalidMessageReceived)("main", data, checkoutUrl, orderId, publicKey, devMode, mockMode, checkoutUrl);
|
|
225
|
+
},
|
|
226
|
+
handlers: {
|
|
227
|
+
"file.save": fileSaveHandler,
|
|
228
|
+
"file.input": fileInputHandler,
|
|
229
|
+
console: (message) => {
|
|
179
230
|
if (devMode) {
|
|
180
|
-
const level = message.level || "log";
|
|
181
|
-
console.log(
|
|
231
|
+
const level = (typeof message.level === "string" && message.level) || "log";
|
|
232
|
+
console.log(`${LOG_PREFIX} [WebView ${level.toUpperCase()}]`, message.message);
|
|
182
233
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (message.type === "window.open") {
|
|
234
|
+
},
|
|
235
|
+
"window.open": (message) => {
|
|
186
236
|
const url = message.url;
|
|
187
237
|
if (url && typeof url === "string" && (0, validation_1.isValidUrl)(url)) {
|
|
188
238
|
if (devMode) {
|
|
189
|
-
console.log(
|
|
239
|
+
console.log(`${LOG_PREFIX} window.open called from MainWebView: ${url}`);
|
|
190
240
|
}
|
|
191
241
|
setFlowWebViewUrl(url);
|
|
192
242
|
setShowFlowWebView(true);
|
|
@@ -196,32 +246,31 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
196
246
|
}
|
|
197
247
|
else {
|
|
198
248
|
if (devMode) {
|
|
199
|
-
console.log(
|
|
249
|
+
console.log(`${LOG_PREFIX} Invalid URL in window.open from MainWebView:`, url, typeof url === "undefined" ? "undefined" : "");
|
|
200
250
|
}
|
|
201
251
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (message.type === "window.close") {
|
|
252
|
+
},
|
|
253
|
+
"window.close": () => {
|
|
205
254
|
if (devMode) {
|
|
206
|
-
console.log(
|
|
255
|
+
console.log(`${LOG_PREFIX} Child window close requested from MainWebView`);
|
|
207
256
|
}
|
|
208
257
|
setShowFlowWebView(false);
|
|
209
258
|
setFlowWebViewUrl("");
|
|
210
259
|
setEducationCarouselState("pending");
|
|
211
260
|
// Tracking window.close interception
|
|
212
261
|
(0, analytics_1.trackWindowClose)("main", orderId, publicKey, devMode, mockMode, checkoutUrl);
|
|
213
|
-
|
|
214
|
-
}
|
|
262
|
+
},
|
|
215
263
|
// Handling merchant JS callbacks on flow completion
|
|
216
|
-
|
|
264
|
+
message: (message) => {
|
|
217
265
|
const messageData = message.message;
|
|
218
|
-
|
|
266
|
+
if (!messageData)
|
|
267
|
+
return;
|
|
268
|
+
const messageType = messageData.type;
|
|
219
269
|
if (messageType === "payment.success" || messageType === "payment.complete") {
|
|
220
|
-
const
|
|
221
|
-
const payload = paymentMessage === null || paymentMessage === void 0 ? void 0 : paymentMessage.payload;
|
|
270
|
+
const payload = messageData.payload;
|
|
222
271
|
if ((0, validation_1.isValidPaymentPayload)(payload)) {
|
|
223
272
|
if (devMode) {
|
|
224
|
-
console.log(
|
|
273
|
+
console.log(`${LOG_PREFIX} Payment successful via merchant callback!`);
|
|
225
274
|
}
|
|
226
275
|
setShowCheckout(false);
|
|
227
276
|
setShowFlowWebView(false);
|
|
@@ -230,21 +279,32 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
230
279
|
setStatus("payment_successful");
|
|
231
280
|
(0, validation_1.safeCallback)(onPaymentSuccess, [payload], "onPaymentSuccess", devMode);
|
|
232
281
|
// Tracking payment success callback
|
|
233
|
-
(0, analytics_1.trackPaymentSuccess)(
|
|
282
|
+
(0, analytics_1.trackPaymentSuccess)((0, event_projections_1.toPaymentEventData)(payload), publicKey, devMode, mockMode, checkoutUrl);
|
|
283
|
+
// Fires alongside the callback, not instead of it - the outcome is real, the payload is thin
|
|
284
|
+
const missingFields = (0, validation_1.missingPaymentFields)(payload);
|
|
285
|
+
if (missingFields.length > 0) {
|
|
286
|
+
(0, analytics_1.trackIncompletePaymentPayload)("payment.success", missingFields, "main", payload.orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
287
|
+
}
|
|
234
288
|
}
|
|
235
289
|
else {
|
|
290
|
+
/**
|
|
291
|
+
* Reported, not dropped. Before v5 this branch was a devMode-only console.error, so in a
|
|
292
|
+
* release build a terminal payment outcome the SDK could not route left no trace
|
|
293
|
+
* anywhere - no callback, no telemetry, nothing for support to find.
|
|
294
|
+
*/
|
|
236
295
|
if (devMode) {
|
|
237
|
-
console.error(
|
|
296
|
+
console.error(`${LOG_PREFIX} Unroutable payment.success payload from main:`, payload);
|
|
238
297
|
}
|
|
298
|
+
(0, analytics_1.trackDroppedPaymentPayload)("payment.success", (0, payment_payload_1.payloadKeysOf)(payload), "main", orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
299
|
+
(0, validation_1.safeCallback)(onSdkError, [[(0, payment_payload_1.droppedPayloadSdkError)("payment.success")]], "onSdkError", devMode);
|
|
239
300
|
}
|
|
240
301
|
return;
|
|
241
302
|
}
|
|
242
303
|
if (messageType === "payment.failure" || messageType === "payment.error") {
|
|
243
|
-
const
|
|
244
|
-
const payload = paymentMessage === null || paymentMessage === void 0 ? void 0 : paymentMessage.payload;
|
|
304
|
+
const payload = messageData.payload;
|
|
245
305
|
if ((0, validation_1.isValidPaymentPayload)(payload)) {
|
|
246
306
|
if (devMode) {
|
|
247
|
-
console.error(
|
|
307
|
+
console.error(`${LOG_PREFIX} Payment failed via merchant callback`);
|
|
248
308
|
}
|
|
249
309
|
setShowCheckout(false);
|
|
250
310
|
setShowFlowWebView(false);
|
|
@@ -253,65 +313,86 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
253
313
|
setStatus("payment_failed");
|
|
254
314
|
(0, validation_1.safeCallback)(onPaymentFailure, [payload], "onPaymentFailure", devMode);
|
|
255
315
|
// Tracking payment failure callback
|
|
256
|
-
(0, analytics_1.trackPaymentFailure)(
|
|
316
|
+
(0, analytics_1.trackPaymentFailure)((0, event_projections_1.toPaymentEventData)(payload), publicKey, devMode, mockMode, checkoutUrl);
|
|
317
|
+
// Fires alongside the callback, not instead of it - the outcome is real, the payload is thin
|
|
318
|
+
const missingFields = (0, validation_1.missingPaymentFields)(payload);
|
|
319
|
+
if (missingFields.length > 0) {
|
|
320
|
+
(0, analytics_1.trackIncompletePaymentPayload)("payment.failure", missingFields, "main", payload.orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
321
|
+
}
|
|
257
322
|
}
|
|
258
323
|
else {
|
|
324
|
+
/**
|
|
325
|
+
* Reported, not dropped. Before v5 this branch was a devMode-only console.error, so in a
|
|
326
|
+
* release build a terminal payment outcome the SDK could not route left no trace
|
|
327
|
+
* anywhere - no callback, no telemetry, nothing for support to find.
|
|
328
|
+
*/
|
|
259
329
|
if (devMode) {
|
|
260
|
-
console.error(
|
|
330
|
+
console.error(`${LOG_PREFIX} Unroutable payment.failure payload from main:`, payload);
|
|
261
331
|
}
|
|
332
|
+
(0, analytics_1.trackDroppedPaymentPayload)("payment.failure", (0, payment_payload_1.payloadKeysOf)(payload), "main", orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
333
|
+
(0, validation_1.safeCallback)(onSdkError, [[(0, payment_payload_1.droppedPayloadSdkError)("payment.failure")]], "onSdkError", devMode);
|
|
262
334
|
}
|
|
263
335
|
return;
|
|
264
336
|
}
|
|
265
337
|
// Handling checkout.closed events
|
|
266
338
|
if (messageType === "checkout.closed") {
|
|
267
339
|
if (devMode) {
|
|
268
|
-
console.log(
|
|
340
|
+
console.log(`${LOG_PREFIX} Checkout closed event received`);
|
|
269
341
|
}
|
|
270
342
|
setShowCheckout(false);
|
|
271
343
|
setShowFlowWebView(false);
|
|
272
344
|
setFlowWebViewUrl("");
|
|
273
345
|
setEducationCarouselState("pending");
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
346
|
+
const termination = { source: checkout_1.TERMINATION_SOURCES.CHECKOUT_CLOSED };
|
|
347
|
+
(0, validation_1.safeCallback)(onPaymentTerminate, [termination], "onPaymentTerminate", devMode);
|
|
348
|
+
// One object to the host and to telemetry, so the two cannot drift
|
|
349
|
+
(0, analytics_1.trackPaymentTerminate)(orderId, (0, event_projections_1.toTerminationEventData)(termination), publicKey, devMode, mockMode, checkoutUrl);
|
|
278
350
|
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
}), [
|
|
354
|
+
onPaymentSuccess,
|
|
355
|
+
onPaymentFailure,
|
|
356
|
+
onPaymentTerminate,
|
|
357
|
+
devMode,
|
|
358
|
+
mockMode,
|
|
359
|
+
orderId,
|
|
360
|
+
publicKey,
|
|
361
|
+
checkoutUrl,
|
|
362
|
+
fileSaveHandler,
|
|
363
|
+
onSdkError,
|
|
364
|
+
fileInputHandler,
|
|
365
|
+
]);
|
|
287
366
|
// Handler for the flow WebView messages
|
|
288
|
-
const handleFlowWebViewMessage = (0, react_1.
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
367
|
+
const handleFlowWebViewMessage = (0, react_1.useMemo)(() => (0, message_router_1.createMessageRouter)({
|
|
368
|
+
logPrefix: LOG_PREFIX,
|
|
369
|
+
source: "FlowWebView",
|
|
370
|
+
devMode,
|
|
371
|
+
onInvalidMessage: (data) => {
|
|
372
|
+
(0, analytics_1.trackInvalidMessageReceived)("flow", data, flowWebViewUrl, orderId, publicKey, devMode, mockMode, checkoutUrl);
|
|
373
|
+
},
|
|
374
|
+
handlers: {
|
|
375
|
+
/**
|
|
376
|
+
* Telemetry only, and deliberately not wired to onUserRefusedDevicePermissions.
|
|
377
|
+
* The flow injection sees this by watching getUserMedia, so coverage depends on
|
|
378
|
+
* whether a given bank uses it - partial coverage on a merchant callback is
|
|
379
|
+
* worse than none, because silence would stop being unambiguous.
|
|
380
|
+
*/
|
|
381
|
+
"permission.denied": (message) => {
|
|
382
|
+
(0, analytics_1.trackDevicePermissionRefused)(typeof message.resource === "string" ? message.resource : "camera", "get_user_media", orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
383
|
+
},
|
|
384
|
+
"file.save": fileSaveHandler,
|
|
385
|
+
"file.input": fileInputHandler,
|
|
386
|
+
console: (message) => {
|
|
305
387
|
if (devMode) {
|
|
306
|
-
console.log(
|
|
388
|
+
console.log(`${LOG_PREFIX} [Flow] ${message.message}`);
|
|
307
389
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
if (message.type === "window.open") {
|
|
390
|
+
},
|
|
391
|
+
"window.open": (message) => {
|
|
311
392
|
const url = message.url;
|
|
312
393
|
if (url && typeof url === "string" && (0, validation_1.isValidUrl)(url)) {
|
|
313
394
|
if (devMode) {
|
|
314
|
-
console.log(
|
|
395
|
+
console.log(`${LOG_PREFIX} window.open called from FlowWebView: ${url}`);
|
|
315
396
|
}
|
|
316
397
|
setFlowWebViewUrl(url);
|
|
317
398
|
setEducationCarouselState("pending");
|
|
@@ -320,31 +401,31 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
320
401
|
}
|
|
321
402
|
else {
|
|
322
403
|
if (devMode) {
|
|
323
|
-
console.log(
|
|
404
|
+
console.log(`${LOG_PREFIX} Invalid URL in window.open from FlowWebView:`, url, typeof url === "undefined" ? "undefined" : "");
|
|
324
405
|
}
|
|
325
406
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
if (message.type === "window.close") {
|
|
407
|
+
},
|
|
408
|
+
"window.close": () => {
|
|
329
409
|
if (devMode) {
|
|
330
|
-
console.log(
|
|
410
|
+
console.log(`${LOG_PREFIX} FlowWebView close requested`);
|
|
331
411
|
}
|
|
332
412
|
setShowFlowWebView(false);
|
|
333
413
|
setFlowWebViewUrl("");
|
|
334
414
|
setEducationCarouselState("pending");
|
|
335
415
|
// Tracking window.close interception
|
|
336
416
|
(0, analytics_1.trackWindowClose)("flow", orderId, publicKey, devMode, mockMode, checkoutUrl);
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
417
|
+
},
|
|
418
|
+
// Handling merchant JS callbacks on flow completion
|
|
419
|
+
message: (message) => {
|
|
340
420
|
const messageData = message.message;
|
|
341
|
-
|
|
421
|
+
if (!messageData)
|
|
422
|
+
return;
|
|
423
|
+
const messageType = messageData.type;
|
|
342
424
|
if (messageType === "payment.success" || messageType === "payment.complete") {
|
|
343
|
-
const
|
|
344
|
-
const payload = paymentMessage === null || paymentMessage === void 0 ? void 0 : paymentMessage.payload;
|
|
425
|
+
const payload = messageData.payload;
|
|
345
426
|
if ((0, validation_1.isValidPaymentPayload)(payload)) {
|
|
346
427
|
if (devMode) {
|
|
347
|
-
console.log(
|
|
428
|
+
console.log(`${LOG_PREFIX} Payment successful via FlowWebView callback!`);
|
|
348
429
|
}
|
|
349
430
|
setShowFlowWebView(false);
|
|
350
431
|
setShowCheckout(false);
|
|
@@ -353,21 +434,32 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
353
434
|
setStatus("payment_successful");
|
|
354
435
|
(0, validation_1.safeCallback)(onPaymentSuccess, [payload], "onPaymentSuccess", devMode);
|
|
355
436
|
// Tracking payment success callback
|
|
356
|
-
(0, analytics_1.trackPaymentSuccess)(
|
|
437
|
+
(0, analytics_1.trackPaymentSuccess)((0, event_projections_1.toPaymentEventData)(payload), publicKey, devMode, mockMode, checkoutUrl);
|
|
438
|
+
// Fires alongside the callback, not instead of it - the outcome is real, the payload is thin
|
|
439
|
+
const missingFields = (0, validation_1.missingPaymentFields)(payload);
|
|
440
|
+
if (missingFields.length > 0) {
|
|
441
|
+
(0, analytics_1.trackIncompletePaymentPayload)("payment.success", missingFields, "flow", payload.orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
442
|
+
}
|
|
357
443
|
}
|
|
358
444
|
else {
|
|
445
|
+
/**
|
|
446
|
+
* Reported, not dropped. Before v5 this branch was a devMode-only console.error, so in a
|
|
447
|
+
* release build a terminal payment outcome the SDK could not route left no trace
|
|
448
|
+
* anywhere - no callback, no telemetry, nothing for support to find.
|
|
449
|
+
*/
|
|
359
450
|
if (devMode) {
|
|
360
|
-
console.error(
|
|
451
|
+
console.error(`${LOG_PREFIX} Unroutable payment.success payload from flow:`, payload);
|
|
361
452
|
}
|
|
453
|
+
(0, analytics_1.trackDroppedPaymentPayload)("payment.success", (0, payment_payload_1.payloadKeysOf)(payload), "flow", orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
454
|
+
(0, validation_1.safeCallback)(onSdkError, [[(0, payment_payload_1.droppedPayloadSdkError)("payment.success")]], "onSdkError", devMode);
|
|
362
455
|
}
|
|
363
456
|
return;
|
|
364
457
|
}
|
|
365
458
|
if (messageType === "payment.failure" || messageType === "payment.error") {
|
|
366
|
-
const
|
|
367
|
-
const payload = paymentMessage === null || paymentMessage === void 0 ? void 0 : paymentMessage.payload;
|
|
459
|
+
const payload = messageData.payload;
|
|
368
460
|
if ((0, validation_1.isValidPaymentPayload)(payload)) {
|
|
369
461
|
if (devMode) {
|
|
370
|
-
console.error(
|
|
462
|
+
console.error(`${LOG_PREFIX} Payment failed via FlowWebView callback`);
|
|
371
463
|
}
|
|
372
464
|
setShowFlowWebView(false);
|
|
373
465
|
setShowCheckout(false);
|
|
@@ -376,60 +468,61 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
376
468
|
setStatus("payment_failed");
|
|
377
469
|
(0, validation_1.safeCallback)(onPaymentFailure, [payload], "onPaymentFailure", devMode);
|
|
378
470
|
// Tracking payment failure callback
|
|
379
|
-
(0, analytics_1.trackPaymentFailure)(
|
|
471
|
+
(0, analytics_1.trackPaymentFailure)((0, event_projections_1.toPaymentEventData)(payload), publicKey, devMode, mockMode, checkoutUrl);
|
|
472
|
+
// Fires alongside the callback, not instead of it - the outcome is real, the payload is thin
|
|
473
|
+
const missingFields = (0, validation_1.missingPaymentFields)(payload);
|
|
474
|
+
if (missingFields.length > 0) {
|
|
475
|
+
(0, analytics_1.trackIncompletePaymentPayload)("payment.failure", missingFields, "flow", payload.orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
476
|
+
}
|
|
380
477
|
}
|
|
381
478
|
else {
|
|
479
|
+
/**
|
|
480
|
+
* Reported, not dropped. Before v5 this branch was a devMode-only console.error, so in a
|
|
481
|
+
* release build a terminal payment outcome the SDK could not route left no trace
|
|
482
|
+
* anywhere - no callback, no telemetry, nothing for support to find.
|
|
483
|
+
*/
|
|
382
484
|
if (devMode) {
|
|
383
|
-
console.error(
|
|
485
|
+
console.error(`${LOG_PREFIX} Unroutable payment.failure payload from flow:`, payload);
|
|
384
486
|
}
|
|
487
|
+
(0, analytics_1.trackDroppedPaymentPayload)("payment.failure", (0, payment_payload_1.payloadKeysOf)(payload), "flow", orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
488
|
+
(0, validation_1.safeCallback)(onSdkError, [[(0, payment_payload_1.droppedPayloadSdkError)("payment.failure")]], "onSdkError", devMode);
|
|
385
489
|
}
|
|
386
|
-
return;
|
|
387
490
|
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
491
|
+
},
|
|
492
|
+
},
|
|
493
|
+
}), [
|
|
494
|
+
onPaymentSuccess,
|
|
495
|
+
onPaymentFailure,
|
|
496
|
+
devMode,
|
|
497
|
+
mockMode,
|
|
498
|
+
orderId,
|
|
499
|
+
publicKey,
|
|
500
|
+
flowWebViewUrl,
|
|
501
|
+
checkoutUrl,
|
|
502
|
+
fileSaveHandler,
|
|
503
|
+
onSdkError,
|
|
504
|
+
fileInputHandler,
|
|
505
|
+
]);
|
|
396
506
|
// Handler for the education carousel WebView messages
|
|
397
|
-
const handleEducationCarouselWebViewMessage = (0, react_1.
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
console.warn("[Glomo-RN-SDK LRS] Invalid message data from EducationCarouselWebView");
|
|
404
|
-
}
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
|
-
const message = JSON.parse(data);
|
|
408
|
-
if (devMode) {
|
|
409
|
-
console.log("[Glomo-RN-SDK LRS] EducationCarouselWebView Message received:", message.type, message);
|
|
410
|
-
}
|
|
411
|
-
if (message.type === "console") {
|
|
507
|
+
const handleEducationCarouselWebViewMessage = (0, react_1.useMemo)(() => (0, message_router_1.createMessageRouter)({
|
|
508
|
+
logPrefix: LOG_PREFIX,
|
|
509
|
+
source: "EducationCarouselWebView",
|
|
510
|
+
devMode,
|
|
511
|
+
handlers: {
|
|
512
|
+
console: (message) => {
|
|
412
513
|
if (devMode) {
|
|
413
|
-
console.log(
|
|
514
|
+
console.log(`${LOG_PREFIX} [EducationCarousel] ${message.message}`);
|
|
414
515
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
if (message.type === "lrs.has_education_steps") {
|
|
418
|
-
const nextState = "hasContent";
|
|
516
|
+
},
|
|
517
|
+
"lrs.has_education_steps": (message) => {
|
|
419
518
|
if (devMode) {
|
|
420
|
-
console.log(
|
|
519
|
+
console.log(`${LOG_PREFIX} Education carousel signal received: value=${String(message.value)} source=${message.source || "unknown"} payload=${JSON.stringify(message.payload || {})}`);
|
|
421
520
|
}
|
|
422
|
-
(0, analytics_1.trackEducationStepsShown)(orderId, publicKey, devMode, mockMode, checkoutUrl, message.source);
|
|
423
|
-
setEducationCarouselState(
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
catch (error) {
|
|
428
|
-
if (devMode) {
|
|
429
|
-
console.error("[Glomo-RN-SDK LRS] Error parsing EducationCarouselWebView message:", error);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}, [checkoutUrl, devMode, mockMode, orderId, publicKey]);
|
|
521
|
+
(0, analytics_1.trackEducationStepsShown)(orderId, publicKey, devMode, mockMode, checkoutUrl, typeof message.source === "string" ? message.source : undefined);
|
|
522
|
+
setEducationCarouselState("hasContent");
|
|
523
|
+
},
|
|
524
|
+
},
|
|
525
|
+
}), [checkoutUrl, devMode, mockMode, orderId, publicKey]);
|
|
433
526
|
// Handler for the navigation state changes
|
|
434
527
|
const handleNavigationStateChange = (0, react_1.useCallback)((navState) => {
|
|
435
528
|
if (devMode) {
|
|
@@ -460,10 +553,18 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
460
553
|
console.log("[Glomo-RN-SDK LRS] Ignoring checkout status update for: " + status);
|
|
461
554
|
}
|
|
462
555
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
556
|
+
/**
|
|
557
|
+
* Inferred from the platform rather than read off an event, because `onRequestClose` is
|
|
558
|
+
* the only wiring here and the two platforms raise it for different gestures: Android
|
|
559
|
+
* for hardware back and the back gesture, iOS for swipe-down on the pageSheet. Nothing
|
|
560
|
+
* else routes through it, so the inference is sound - but it is an inference.
|
|
561
|
+
*/
|
|
562
|
+
const termination = {
|
|
563
|
+
source: react_native_1.Platform.OS === "ios" ? checkout_1.TERMINATION_SOURCES.MODAL_DISMISS : checkout_1.TERMINATION_SOURCES.DEVICE_BACK_BUTTON,
|
|
564
|
+
};
|
|
565
|
+
(0, validation_1.safeCallback)(onPaymentTerminate, [termination], "onPaymentTerminate", devMode);
|
|
566
|
+
// One object to the host and to telemetry, so the two cannot drift
|
|
567
|
+
(0, analytics_1.trackPaymentTerminate)(orderId, (0, event_projections_1.toTerminationEventData)(termination), publicKey, devMode, mockMode, checkoutUrl);
|
|
467
568
|
}
|
|
468
569
|
catch (error) {
|
|
469
570
|
if (devMode) {
|
|
@@ -471,6 +572,28 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
471
572
|
}
|
|
472
573
|
}
|
|
473
574
|
}, [showFlowWebView, devMode, onPaymentTerminate, status, orderId, publicKey, mockMode, checkoutUrl]);
|
|
575
|
+
/**
|
|
576
|
+
* Closing the checkout when the user refuses camera access, since the bank page cannot
|
|
577
|
+
* proceed without it. Kept here rather than inside usePermissionRequest because moving the
|
|
578
|
+
* status and notifying the merchant are flow concerns.
|
|
579
|
+
*/
|
|
580
|
+
const handleDevicePermissionDenied = (0, react_1.useCallback)(() => {
|
|
581
|
+
setShowCheckout(false);
|
|
582
|
+
setShowFlowWebView(false);
|
|
583
|
+
setFlowWebViewUrl("");
|
|
584
|
+
setEducationCarouselState("pending");
|
|
585
|
+
if (status === "payment_in_progress") {
|
|
586
|
+
setStatus("payment_cancelled");
|
|
587
|
+
}
|
|
588
|
+
(0, validation_1.safeCallback)(onUserRefusedDevicePermissions, [], "onUserRefusedDevicePermissions", devMode);
|
|
589
|
+
// The permission hook only reaches here for camera; anything else is denied without notifying
|
|
590
|
+
(0, analytics_1.trackDevicePermissionRefused)("camera", "permission_request", orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
591
|
+
}, [status, onUserRefusedDevicePermissions, devMode, orderId, publicKey, mockMode, checkoutUrl]);
|
|
592
|
+
const handlePermissionRequest = (0, use_permission_request_1.usePermissionRequest)({
|
|
593
|
+
logPrefix: "[Glomo-RN-SDK LRS]",
|
|
594
|
+
onDenied: handleDevicePermissionDenied,
|
|
595
|
+
devMode,
|
|
596
|
+
});
|
|
474
597
|
/** Closes the flow WebView and returns to the main checkout */
|
|
475
598
|
const handleFlowBack = (0, react_1.useCallback)(() => {
|
|
476
599
|
if (devMode) {
|
|
@@ -479,7 +602,7 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
479
602
|
setShowFlowWebView(false);
|
|
480
603
|
setFlowWebViewUrl("");
|
|
481
604
|
setEducationCarouselState("pending");
|
|
482
|
-
(0, analytics_1.
|
|
605
|
+
(0, analytics_1.trackBackNavigationViaSdkBackButton)(orderId, publicKey, devMode, mockMode, checkoutUrl, "lrs");
|
|
483
606
|
}, [devMode, orderId, publicKey, mockMode, checkoutUrl]);
|
|
484
607
|
/**
|
|
485
608
|
* Initiator method for the LRS Checkout flow.
|
|
@@ -498,38 +621,62 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
498
621
|
* Checking device security compliance (if peerDependencies are available)
|
|
499
622
|
* A null value indicates that recommended security dependencies were not installed and compliance checks will be skipped in this case
|
|
500
623
|
*/
|
|
501
|
-
const
|
|
502
|
-
const
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
|
|
624
|
+
const compliance = (0, device_compliance_1.resolveDeviceCompliance)(devMode);
|
|
625
|
+
const complianceLibraryInstalled = (0, device_compliance_1.isComplianceCheckAvailable)();
|
|
626
|
+
const fileSave = (0, index_2.resolveFileSaveAvailability)();
|
|
627
|
+
const dependencyInfo = {
|
|
628
|
+
jailbreakDetectionLibraryInstalled: complianceLibraryInstalled,
|
|
629
|
+
jailbreakDetected: compliance.compromised,
|
|
630
|
+
complianceSource: compliance.source,
|
|
631
|
+
complianceSignals: compliance.trippedSignals,
|
|
632
|
+
fileSaveAvailable: fileSave.available,
|
|
633
|
+
missingFileSavePackages: fileSave.missing,
|
|
506
634
|
};
|
|
507
635
|
if (devMode) {
|
|
508
636
|
console.log(`[Glomo-RN-SDK LRS] Attempting to start checkout of ${checkoutUrl} from status: ${status}`);
|
|
509
637
|
}
|
|
510
638
|
// Tracking start attempt with current status
|
|
511
|
-
(0, analytics_1.trackStartAttempt)(status, orderId, publicKey, devMode, mockMode, checkoutUrl,
|
|
512
|
-
|
|
513
|
-
|
|
639
|
+
(0, analytics_1.trackStartAttempt)(status, orderId, publicKey, devMode, mockMode, checkoutUrl, dependencyInfo);
|
|
640
|
+
/**
|
|
641
|
+
* Ungated on purpose, both of them. An absent optional dependency degrades silently by
|
|
642
|
+
* design, so a console warning is the only thing that reaches a merchant who has not
|
|
643
|
+
* noticed - and the compliance one now precedes a hard block on live keys.
|
|
644
|
+
*/
|
|
645
|
+
if (!complianceLibraryInstalled) {
|
|
646
|
+
console.warn("[Glomo-RN-SDK LRS] jail-monkey is not installed or its native module is not linked, so " +
|
|
647
|
+
"rooted and jailbroken devices cannot be detected. As of v5 this BLOCKS live checkouts. " +
|
|
648
|
+
"Install jail-monkey and rebuild the app - see the README.");
|
|
649
|
+
}
|
|
650
|
+
if (!fileSave.available) {
|
|
651
|
+
console.warn(`[Glomo-RN-SDK LRS] Document downloads are disabled: ${fileSave.missing.join(" and ")} ` +
|
|
652
|
+
"could not be loaded. Install the package(s) and rebuild the app, or ignore this if your " +
|
|
653
|
+
"checkout does not offer downloads - the page falls back to its own behaviour.");
|
|
654
|
+
}
|
|
655
|
+
if ((0, device_compliance_1.blocksCheckout)(compliance, publicKey)) {
|
|
656
|
+
/**
|
|
657
|
+
* Two conditions, one refusal. `compromised === true` is a rooted or jailbroken device;
|
|
658
|
+
* `null` is a device we could not check, which on RN overwhelmingly means jail-monkey is
|
|
659
|
+
* absent rather than that a platform probe failed. Both fail closed on a live key, and
|
|
660
|
+
* neither fires on a test or mock key.
|
|
661
|
+
*/
|
|
662
|
+
const unknown = compliance.compromised === null;
|
|
514
663
|
if (devMode) {
|
|
515
|
-
console.error(
|
|
664
|
+
console.error(`[Glomo-RN-SDK LRS] Cannot start checkout. ${unknown ? "Device security could not be verified." : "Device is rooted or jailbroken."}`);
|
|
516
665
|
}
|
|
517
666
|
const errors = [
|
|
518
667
|
{
|
|
519
668
|
type: "device_forbidden",
|
|
520
|
-
message:
|
|
669
|
+
message: unknown
|
|
670
|
+
? "LRS checkout could not verify this device's security. Install jail-monkey and rebuild the app."
|
|
671
|
+
: "LRS checkout is not allowed on rooted or jailbroken devices.",
|
|
521
672
|
},
|
|
522
673
|
];
|
|
523
674
|
(0, validation_1.safeCallback)(onSdkError, [errors], "onSdkError", devMode);
|
|
524
675
|
// Tracking start() failure
|
|
525
|
-
(0, analytics_1.trackStartFailure)("device_forbidden", orderId, publicKey, devMode, mockMode, checkoutUrl,
|
|
676
|
+
(0, analytics_1.trackStartFailure)(unknown ? "device_compliance_unknown" : "device_forbidden", orderId, publicKey, devMode, mockMode, checkoutUrl, dependencyInfo);
|
|
526
677
|
setShowCheckout(false);
|
|
527
678
|
return false;
|
|
528
679
|
}
|
|
529
|
-
else if (deviceComplianceCheck === null) {
|
|
530
|
-
// This warning was intentionally not gated behind a devMode check to ensure merchants are aware of the strong recommendation to install jail-monkey for enhanced security compliance.
|
|
531
|
-
console.warn("[Glomo-RN-SDK LRS] Device security library not installed - the SDK won't be able to automatically detect rooted/jailbroken devices. It is HIGHLY recommended to install jail-monkey as per the README, and prevent LRS checkouts from compromised devices.");
|
|
532
|
-
}
|
|
533
680
|
// Enforcing devMode requirement for development servers
|
|
534
681
|
const resolvedServer = server || "prod";
|
|
535
682
|
if (!devMode && resolvedServer !== "prod") {
|
|
@@ -541,7 +688,7 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
541
688
|
];
|
|
542
689
|
(0, validation_1.safeCallback)(onSdkError, [errors], "onSdkError", devMode);
|
|
543
690
|
(0, analytics_1.trackSdkError)(errors, orderId, publicKey, devMode, mockMode, checkoutUrl);
|
|
544
|
-
(0, analytics_1.trackStartFailure)("validation_error", orderId, publicKey, devMode, mockMode, checkoutUrl,
|
|
691
|
+
(0, analytics_1.trackStartFailure)("validation_error", orderId, publicKey, devMode, mockMode, checkoutUrl, dependencyInfo);
|
|
545
692
|
setShowCheckout(false);
|
|
546
693
|
return false;
|
|
547
694
|
}
|
|
@@ -584,7 +731,7 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
584
731
|
(0, validation_1.safeCallback)(onSdkError, [errors], "onSdkError", devMode);
|
|
585
732
|
// Tracking start() failure
|
|
586
733
|
(0, analytics_1.trackSdkError)(errors, orderId, publicKey, devMode, mockMode, checkoutUrl);
|
|
587
|
-
(0, analytics_1.trackStartFailure)("validation_error", orderId, publicKey, devMode, mockMode, checkoutUrl,
|
|
734
|
+
(0, analytics_1.trackStartFailure)("validation_error", orderId, publicKey, devMode, mockMode, checkoutUrl, dependencyInfo);
|
|
588
735
|
setShowCheckout(false);
|
|
589
736
|
return false;
|
|
590
737
|
}
|
|
@@ -593,7 +740,7 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
593
740
|
console.log(`[Glomo-RN-SDK LRS] Cannot start checkout. Current status: ${status}. Payment already successful.`);
|
|
594
741
|
}
|
|
595
742
|
// Tracking start() failure
|
|
596
|
-
(0, analytics_1.trackStartFailure)("payment_successful", orderId, publicKey, devMode, mockMode, checkoutUrl,
|
|
743
|
+
(0, analytics_1.trackStartFailure)("payment_successful", orderId, publicKey, devMode, mockMode, checkoutUrl, dependencyInfo);
|
|
597
744
|
setShowCheckout(false);
|
|
598
745
|
return false;
|
|
599
746
|
}
|
|
@@ -607,7 +754,7 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
607
754
|
console.log(`[Glomo-RN-SDK LRS] Cannot start checkout. Unknown status: ${status}.`);
|
|
608
755
|
}
|
|
609
756
|
// Tracking start() failure
|
|
610
|
-
(0, analytics_1.trackStartFailure)("invalid_status", orderId, publicKey, devMode, mockMode, checkoutUrl,
|
|
757
|
+
(0, analytics_1.trackStartFailure)("invalid_status", orderId, publicKey, devMode, mockMode, checkoutUrl, dependencyInfo);
|
|
611
758
|
setShowCheckout(false);
|
|
612
759
|
return false;
|
|
613
760
|
}
|
|
@@ -616,7 +763,7 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
616
763
|
console.error("[Glomo-RN-SDK LRS] Cannot start checkout. Invalid checkout URL.");
|
|
617
764
|
}
|
|
618
765
|
// Tracking start() failure
|
|
619
|
-
(0, analytics_1.trackStartFailure)("invalid_url", orderId, publicKey, devMode, mockMode, checkoutUrl,
|
|
766
|
+
(0, analytics_1.trackStartFailure)("invalid_url", orderId, publicKey, devMode, mockMode, checkoutUrl, dependencyInfo);
|
|
620
767
|
setShowCheckout(false);
|
|
621
768
|
return false;
|
|
622
769
|
}
|
|
@@ -628,7 +775,7 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
628
775
|
setEducationCarouselState("pending");
|
|
629
776
|
setStatus("payment_in_progress");
|
|
630
777
|
// Tracking successful start
|
|
631
|
-
(0, analytics_1.trackStartSuccess)(orderId, publicKey, devMode, mockMode, checkoutUrl,
|
|
778
|
+
(0, analytics_1.trackStartSuccess)(orderId, publicKey, devMode, mockMode, checkoutUrl, dependencyInfo);
|
|
632
779
|
setShowCheckout(true);
|
|
633
780
|
return true;
|
|
634
781
|
}, [devMode, status, publicKey, orderId, baseCheckoutUrl, checkoutUrl, mockMode, onSdkError, server]);
|
|
@@ -663,6 +810,13 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
663
810
|
setEducationCarouselState("pending");
|
|
664
811
|
};
|
|
665
812
|
}, []);
|
|
813
|
+
/**
|
|
814
|
+
* Scripts injected into each WebView, carrying what this build can advertise.
|
|
815
|
+
*
|
|
816
|
+
* Resolved once per mount rather than at module load, so a merchant who never opens a
|
|
817
|
+
* checkout never pays for the dependency probe.
|
|
818
|
+
*/
|
|
819
|
+
const injectionScripts = (0, react_1.useMemo)(() => (0, index_1.buildInjectionScripts)((0, index_2.resolveCapabilities)()), []);
|
|
666
820
|
return {
|
|
667
821
|
start,
|
|
668
822
|
status,
|
|
@@ -683,8 +837,13 @@ function useLrsCheckout({ server, publicKey, orderId, onPaymentSuccess, onPaymen
|
|
|
683
837
|
handleNavigationStateChange,
|
|
684
838
|
handleModalBackButton,
|
|
685
839
|
handleFlowBack,
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
840
|
+
handlePermissionRequest,
|
|
841
|
+
injectedMain: __DEV__ && (internalOptions === null || internalOptions === void 0 ? void 0 : internalOptions._testInjectionScript)
|
|
842
|
+
? injectionScripts.main + internalOptions._testInjectionScript
|
|
843
|
+
: injectionScripts.main,
|
|
844
|
+
injectedFlow: injectionScripts.flow,
|
|
845
|
+
injectedEducationCarousel: __DEV__ && (internalOptions === null || internalOptions === void 0 ? void 0 : internalOptions._testCarouselInjectionScript)
|
|
846
|
+
? injectionScripts.educationCarousel + internalOptions._testCarouselInjectionScript
|
|
847
|
+
: injectionScripts.educationCarousel,
|
|
689
848
|
};
|
|
690
849
|
}
|