1(function () { 2 'use strict'; 3 4 // An approved PayPal order cannot be repriced. Cancel the stale local 5 // checkout session and reload so the SDK creates a new order from the 6 // current cart instead of leaving the customer at a terminal error. 7 if (!window.fetch || !window.ps_checkoutValidateUrl || !window.ps_checkoutCancelUrl) { 8 return; 9 } 10 11 var nativeFetch = window.fetch.bind(window); 12 var recoveryStarted = false; 13 var recoveryStorageKey = 'ps_checkout_amount_mismatch_recovery'; 14 var recoveryWindow = 5 * 60 * 1000; 15 16 function isSameUrl(first, second) { 17 try { 18 return new URL(first, window.location.href).href === new URL(second, window.location.href).href; 19 } catch (e) { 20 return first === second; 21 } 22 } 23 24 function clearRecoveryAttempt() { 25 try { 26 window.sessionStorage.removeItem(recoveryStorageKey); 27 } catch (e) { 28 // Checkout still works when session storage is unavailable. 29 } 30 } 31 32 function reserveRecoveryAttempt() { 33 try { 34 var previousAttempt = parseInt(window.sessionStorage.getItem(recoveryStorageKey), 10); 35 var now = Date.now(); 36 37 if (previousAttempt && now - previousAttempt < recoveryWindow) { 38 return false; 39 } 40 41 window.sessionStorage.setItem(recoveryStorageKey, String(now)); 42 } catch (e) { 43 // In private/restricted contexts, the in-page guard still prevents 44 // duplicate recovery requests. 45 } 46 47 return true; 48 } 49 50 window.fetch = function (input, init) { 51 var requestUrl = typeof input === 'string' ? input : input && input.url; 52 var requestBody = init && init.body; 53 54 return nativeFetch(input, init).then(function (response) { 55 if (!isSameUrl(requestUrl, window.ps_checkoutValidateUrl)) { 56 return response; 57 } 58 59 if (response.ok) { 60 clearRecoveryAttempt(); 61 return response; 62 } 63 64 if (!response.clone) { 65 return response; 66 } 67 68 response.clone().json().then(function (payload) { 69 var error = payload && payload.body && payload.body.error; 70 71 if (!error || String(error.code) !== '43' || !requestBody || recoveryStarted) { 72 return; 73 } 74 75 var checkoutData; 76 try { 77 checkoutData = JSON.parse(requestBody); 78 } catch (e) { 79 return; 80 } 81 82 if (!checkoutData.orderID) { 83 return; 84 } 85 86 if (!reserveRecoveryAttempt()) { 87 return; 88 } 89 90 recoveryStarted = true; 91 checkoutData.reason = 'amount_mismatch_recovery'; 92 checkoutData.orderStatus = 'CANCELED'; 93 94 var reloadStarted = false; 95 var reloadCheckout = function () { 96 if (reloadStarted) { 97 return; 98 } 99 100 reloadStarted = true; 101 window.location.reload(); 102 }; 103 104 nativeFetch(window.ps_checkoutCancelUrl, { 105 method: 'post', 106 credentials: 'same-origin', 107 headers: { 108 'Content-Type': 'application/json', 109 Accept: 'application/json' 110 }, 111 body: JSON.stringify(checkoutData) 112 }).then(reloadCheckout, reloadCheckout); 113 114 window.setTimeout(reloadCheckout, 1500); 115 }); 116 117 return response; 118 }); 119 }; 120}());
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.