@salla.sa/applepay 2.14.570 → 2.14.571
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/index.js +109 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salla.sa/applepay",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.571",
|
|
4
4
|
"description": "Salla Apple Pay light",
|
|
5
5
|
"main": "dist/app.js",
|
|
6
6
|
"scripts": {
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"axios": "^1.10.0"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "6ca1f94b0197d7a671c7412e27162e01aa2186b7"
|
|
30
30
|
}
|
package/src/index.js
CHANGED
|
@@ -156,6 +156,18 @@ const SallaApplePay = typeof window !== 'undefined' ? {
|
|
|
156
156
|
// Fresh transaction → clear any cancel flag from a previous attempt.
|
|
157
157
|
SallaApplePay.canceled = false;
|
|
158
158
|
|
|
159
|
+
// Analytics latches — one Submitted and one Succeeded per attempt, and
|
|
160
|
+
// at most one Failed, however many callbacks fire.
|
|
161
|
+
SallaApplePay._submittedTracked = false;
|
|
162
|
+
SallaApplePay._failureTracked = false;
|
|
163
|
+
SallaApplePay._succeededTracked = false;
|
|
164
|
+
|
|
165
|
+
// The cart belongs to the attempt, not to the singleton. The mini embed
|
|
166
|
+
// supplies one up front; on the PDP it stays null until checkout/mini
|
|
167
|
+
// answers during merchant validation. Without this a second attempt
|
|
168
|
+
// reports — and submits to — the previous attempt's cart.
|
|
169
|
+
SallaApplePay.id = SallaApplePay.detail?.cartId || null;
|
|
170
|
+
|
|
159
171
|
salla.log('🍏 Pay: payments::apple-pay.start-transaction', SallaApplePay.detail);
|
|
160
172
|
|
|
161
173
|
SallaApplePay.initDefault();
|
|
@@ -220,8 +232,17 @@ const SallaApplePay = typeof window !== 'undefined' ? {
|
|
|
220
232
|
skipBegin = SallaApplePay.detail.onStartedSession(SallaApplePay.session);
|
|
221
233
|
}
|
|
222
234
|
if (!skipBegin) {
|
|
223
|
-
|
|
235
|
+
try {
|
|
236
|
+
SallaApplePay.session.begin();
|
|
237
|
+
} catch (error) {
|
|
238
|
+
salla.logger.error('🍏 Pay: session.begin() failed', error);
|
|
239
|
+
SallaApplePay.trackPaymentFailed('client', 'APPLE_PAY_PRESENTATION_FAILED', error?.message || '');
|
|
240
|
+
SallaApplePay.detail.onError(salla.lang.get('pages.checkout.payment_failed'));
|
|
241
|
+
Salla.event.createAndDispatch('payments::apple-pay.canceled', {});
|
|
242
|
+
}
|
|
224
243
|
}
|
|
244
|
+
// skipBegin path: the caller begins later — onValidateMerchant fires
|
|
245
|
+
// once the sheet actually opens and emits the (latched) Submitted.
|
|
225
246
|
},
|
|
226
247
|
onPaymentMethodSelected: async (event) => {
|
|
227
248
|
salla.logger.log('🍏 Pay: onPaymentMethodSelected', event);
|
|
@@ -306,6 +327,10 @@ const SallaApplePay = typeof window !== 'undefined' ? {
|
|
|
306
327
|
|
|
307
328
|
onCancel: (event = {}, message = null) => {
|
|
308
329
|
SallaApplePay.canceled = true;
|
|
330
|
+
// Sheet opened (Payment Submitted already fired) but the attempt ended
|
|
331
|
+
// without authorization — dismissal, abort, or validation failure.
|
|
332
|
+
// Latched: a server rejection tracked earlier absorbs this call.
|
|
333
|
+
SallaApplePay.trackPaymentFailed('client', 'APPLE_PAY_SESSION_CANCELED', message || '');
|
|
309
334
|
SallaApplePay.detail.onError(message || salla.lang.get('pages.checkout.payment_failed'));
|
|
310
335
|
Salla.event.createAndDispatch('payments::apple-pay.canceled', event);
|
|
311
336
|
},
|
|
@@ -367,11 +392,15 @@ const SallaApplePay = typeof window !== 'undefined' ? {
|
|
|
367
392
|
}
|
|
368
393
|
|
|
369
394
|
Salla.event.dispatch('payments::apple-pay.authorized.init', event);
|
|
395
|
+
// The shopper has authorised with Face ID / Touch ID and the token is
|
|
396
|
+
// about to go to the gateway — this is the submission, not the tap.
|
|
397
|
+
SallaApplePay.trackPaymentSubmitted();
|
|
370
398
|
http.post(SallaApplePay.detail.authorized.url.replace('{id}', SallaApplePay.id), {
|
|
371
399
|
payment_method: 'apple_pay',
|
|
372
400
|
applepay_token: JSON.stringify(event.payment)
|
|
373
401
|
}, ({ data }) => {
|
|
374
402
|
Salla.event.dispatch('payments::apple-pay.authorized.success', data);
|
|
403
|
+
SallaApplePay.trackPaymentSucceeded(data);
|
|
375
404
|
|
|
376
405
|
if (typeof SallaApplePay.detail.authorized.onSuccess === 'function') {
|
|
377
406
|
SallaApplePay.detail.authorized.onSuccess(data);
|
|
@@ -383,6 +412,11 @@ const SallaApplePay = typeof window !== 'undefined' ? {
|
|
|
383
412
|
let response = error?.response;
|
|
384
413
|
|
|
385
414
|
Salla.event.dispatch('payments::apple-pay.authorized.failed', response);
|
|
415
|
+
// Backend rejected the token — latch set so the cancel callback
|
|
416
|
+
// following the failure UI can't emit a second Failed.
|
|
417
|
+
SallaApplePay.trackPaymentFailed('server',
|
|
418
|
+
response?.data?.error?.code || 'APPLE_PAY_FAILED',
|
|
419
|
+
response?.data?.error?.message || '');
|
|
386
420
|
|
|
387
421
|
if (typeof SallaApplePay.detail.authorized.onFailed === 'function') {
|
|
388
422
|
SallaApplePay.detail.authorized.onFailed(response);
|
|
@@ -849,6 +883,72 @@ const SallaApplePay = typeof window !== 'undefined' ? {
|
|
|
849
883
|
};
|
|
850
884
|
},
|
|
851
885
|
|
|
886
|
+
track: function (event, extra = {}) {
|
|
887
|
+
const id = SallaApplePay.id ? String(SallaApplePay.id) : null;
|
|
888
|
+
try {
|
|
889
|
+
salla.analytics?.track(event, {
|
|
890
|
+
payment_method: 'apple_pay',
|
|
891
|
+
gateway: 'apple_pay',
|
|
892
|
+
cart_id: id,
|
|
893
|
+
checkout_id: id,
|
|
894
|
+
session_id: salla.config?.get?.('jitsu.session_id') || null,
|
|
895
|
+
...extra,
|
|
896
|
+
// The host knows the surface — PDP quick-buy vs the mini-checkout
|
|
897
|
+
// embed both render salla-quick-buy and share this package.
|
|
898
|
+
checkout_type: extra.checkout_type
|
|
899
|
+
|| SallaApplePay.detail?.checkout_type
|
|
900
|
+
|| 'applepay_checkout',
|
|
901
|
+
});
|
|
902
|
+
} catch (error) {
|
|
903
|
+
salla.logger.error('🍏 Pay: failed to track ' + event, error);
|
|
904
|
+
}
|
|
905
|
+
},
|
|
906
|
+
|
|
907
|
+
trackPaymentSubmitted: function () {
|
|
908
|
+
if (SallaApplePay._submittedTracked) {
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
SallaApplePay._submittedTracked = true;
|
|
912
|
+
// Checkout Started belongs to the host: the mini-checkout embed already
|
|
913
|
+
// emits its own on open, and on the PDP the cart does not exist until
|
|
914
|
+
// checkout/mini answers, so salla-quick-buy fires it there with a real id.
|
|
915
|
+
SallaApplePay.track('Payment Submitted', {});
|
|
916
|
+
},
|
|
917
|
+
|
|
918
|
+
trackPaymentFailed: function (errorType, errorCode, message = '') {
|
|
919
|
+
// Payment Failed answers a Payment Submitted, and Submitted is emitted at
|
|
920
|
+
// authorization. Anything that ends the attempt before that — a dismissed
|
|
921
|
+
// sheet, a refused presentation, merchant validation — is abandonment or a
|
|
922
|
+
// setup error, not a failed payment, and counting it here would make
|
|
923
|
+
// Failed exceed Submitted. Those paths still log, still call
|
|
924
|
+
// detail.onError and still dispatch payments::apple-pay.canceled, so
|
|
925
|
+
// hosts and error reporting are unaffected; only the funnel is.
|
|
926
|
+
if (!SallaApplePay._submittedTracked || SallaApplePay._failureTracked) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
SallaApplePay._failureTracked = true;
|
|
930
|
+
SallaApplePay.track('Payment Failed', {
|
|
931
|
+
error_type: errorType,
|
|
932
|
+
error_code: errorCode,
|
|
933
|
+
error_message: message || '',
|
|
934
|
+
});
|
|
935
|
+
},
|
|
936
|
+
|
|
937
|
+
trackPaymentSucceeded: function (data) {
|
|
938
|
+
if (SallaApplePay._succeededTracked) {
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
SallaApplePay._succeededTracked = true;
|
|
942
|
+
const payload = data?.data || data || {};
|
|
943
|
+
SallaApplePay.track('Payment Succeeded', {
|
|
944
|
+
order_id: payload.order_id || null,
|
|
945
|
+
cart_total: payload.total || SallaApplePay.detail?.amount || null,
|
|
946
|
+
response_status: 'success',
|
|
947
|
+
has_redirect: false,
|
|
948
|
+
redirect_url: null,
|
|
949
|
+
});
|
|
950
|
+
},
|
|
951
|
+
|
|
852
952
|
/** Authorize + submit the payment, then close the sheet. */
|
|
853
953
|
prPaymentAuthorized: async function (response) {
|
|
854
954
|
// Guest checkout → persist the payer contact before submitting.
|
|
@@ -886,6 +986,8 @@ const SallaApplePay = typeof window !== 'undefined' ? {
|
|
|
886
986
|
}
|
|
887
987
|
|
|
888
988
|
Salla.event.dispatch('payments::apple-pay.authorized.init', response);
|
|
989
|
+
// Authorised on the paired device; the token is about to be submitted.
|
|
990
|
+
SallaApplePay.trackPaymentSubmitted();
|
|
889
991
|
|
|
890
992
|
let authorizedData;
|
|
891
993
|
try {
|
|
@@ -896,10 +998,16 @@ const SallaApplePay = typeof window !== 'undefined' ? {
|
|
|
896
998
|
|
|
897
999
|
authorizedData = data;
|
|
898
1000
|
Salla.event.dispatch('payments::apple-pay.authorized.success', data);
|
|
1001
|
+
SallaApplePay.trackPaymentSucceeded(data);
|
|
899
1002
|
await response.complete('success');
|
|
900
1003
|
} catch (error) {
|
|
901
1004
|
const errorResponse = error?.response;
|
|
902
1005
|
Salla.event.dispatch('payments::apple-pay.authorized.failed', errorResponse);
|
|
1006
|
+
// Backend rejected the token — latch set so the sheet-close /
|
|
1007
|
+
// cancel that follows can't emit a second Failed.
|
|
1008
|
+
SallaApplePay.trackPaymentFailed('server',
|
|
1009
|
+
errorResponse?.data?.error?.code || 'APPLE_PAY_FAILED',
|
|
1010
|
+
errorResponse?.data?.error?.message || '');
|
|
903
1011
|
await response.complete('fail');
|
|
904
1012
|
if (typeof SallaApplePay.detail.authorized.onFailed === 'function') {
|
|
905
1013
|
SallaApplePay.detail.authorized.onFailed(errorResponse);
|