1(function($) { 2 'use strict'; 3 4 var firstLoadFlag = false; 5 var isEventTriggered = false; 6 var add_payment_method_token; 7 var disableLoader = false; 8 var isExpressPaySubmission = false; 9 10 // Flex microform variables for saved card CVV. 11 var flexInstances = {}; 12 var flexFieldsValid = {}; 13 // Collect and send browser data for 3DS device information. 14 function collectBrowserData() { 15 if (typeof visa_acceptance_ajaxUCObj === 'undefined') { 16 return; 17 } 18 19 var browserData = { 20 action: 'store_browser_data', 21 nonce: visa_acceptance_ajaxUCObj.store_browser_data_nonce || '', 22 gateway_id: visa_acceptance_ajaxUCObj.gateway_id || '', 23 screen_height: window.screen.height, 24 screen_width: window.screen.width, 25 color_depth: window.screen.colorDepth, 26 tz_offset: new Date().getTimezoneOffset(), 27 java_enabled: navigator.javaEnabled ? navigator.javaEnabled() : false, 28 js_enabled: true 29 }; 30 31 $.ajax({ 32 url: visa_acceptance_ajaxUCObj.ajax_url, 33 type: 'POST', 34 data: browserData, 35 async: false 36 }); 37 } 38 39 // Collect browser data on page load. 40 $(document).ready(function() { 41 collectBrowserData(); 42 }); 43 44 jQuery(document).on('wc_checkout_form_error', function() { 45 window.flexSubmissionInProgress = false; 46 jQuery('form.checkout').off('submit', handleFormSubmission).on('submit', handleFormSubmission); 47 // Show payment form back when there's a validation error after express pay click. 48 hideExpressPayLoader(); 49 jQuery('.woocommerce-checkout-payment').show(); 50 }); 51 52 jQuery(document.body).on('checkout_error', function() { 53 var isNewCard = ( 54 jQuery("input[name$='payment_method'][value$='" + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id'] + "']").is(':checked') && 55 ( 56 jQuery('#wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] + '-use-new-payment-method').is(':checked') || 57 jQuery('#wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] + '-use-new-payment-method').length === 0 58 ) 59 ); 60 if (isNewCard) { 61 location.reload(); 62 } 63 }); 64 65 setInterval(checkDisableLoader, 1000); 66 67 function checkDisableLoader() { 68 if (disableLoader) { 69 jQuery('.blockUI.blockOverlay').hide(); 70 disableLoader = false;
71 location.reload(); 72 } 73 } 74 75 //Building Error Message. 76 const errorMessagePara = document.createElement("p"); 77 errorMessagePara.setAttribute('style','color:red') 78 const errorMessageText = document.createTextNode(visa_acceptance_ajaxUCObj['form_load_error']); 79 errorMessagePara.appendChild(errorMessageText); 80 81 var paymentMethodRow = $('tr.payment-method'); 82 var defaultPaymentMethodRow = $('tr.default-payment-method'); 83 var paymentMethodRowText = paymentMethodRow.find('td.woocommerce-PaymentMethod.woocommerce-PaymentMethod--default.payment-method-default').text(); 84 var defaultPaymentMethodRowText = defaultPaymentMethodRow.find('td.woocommerce-PaymentMethod.woocommerce-PaymentMethod--default.payment-method-default').text(); 85 86 jQuery('.woocommerce-MyAccount-paymentMethods').on('click', '.woocommerce-PaymentMethod--actions .button.delete', function(e) { 87 if (!confirm(visa_acceptance_ajaxUCObj['delete_card_text'])) { 88 e.preventDefault(); 89 location.reload(); 90 } 91 if (!navigator.onLine) { 92 alert(visa_acceptance_ajaxUCObj['offline_text']); 93 e.preventDefault(); 94 } 95 }); 96 97 // Named function for form submission handling. 98 async function handleFormSubmission(e) { 99 // Express pay bypasses all form validation (terms, CVV, etc.). 100 if (isExpressPaySubmission) { 101 isExpressPaySubmission = false; 102 return true; 103 } 104 if ($("input[name$='payment_method'][value$='" + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id'] +"']").is(':checked')) { 105 var valueForTkn = jQuery('input[name=wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] + '-payment-token]:checked').val(); 106 107 // If no token is selected, allow normal processing (new card). 108 if (!valueForTkn) { 109 document.getElementById("errorMessage").value = "no"; 110 return true; // Allow form submission. 111 } 112 113 // Check if token is eCheck - skip CVV validation for eCheck. 114 var isEcheck = visa_acceptance_ajaxUCObj['token_type'] && visa_acceptance_ajaxUCObj['token_type'][valueForTkn] === 'eCheck'; 115 116 if (!visa_acceptance_ajaxUCObj['saved_card_cvv'] || isEcheck) { 117 document.getElementById("errorMessage").value = "no"; 118 return true; 119 } 120 121 // CVV is required - check if Flex is being used for this token. 122 if (valueForTkn && flexInstances[valueForTkn]) { 123 if (!flexFieldsValid[valueForTkn]) { 124 // Show error if Flex CVV field is not valid. 125 jQuery('#error-' + encodeURI(valueForTkn)).show(); 126 document.getElementById("errorMessage").value = "yes"; 127 e.preventDefault(); 128 e.stopImmediatePropagation(); 129 return false; 130 } 131 try { 132 e.preventDefault(); 133 e.stopImmediatePropagation(); 134 135 var flexTokenResponse = await flexInstances[valueForTkn].createToken(); 136 137 if (flexTokenResponse && flexTokenResponse.token) { 138 // Add the flex token to a hidden field. 139 var flexTokenField = jQuery('input[name="flex_cvv_token"]'); 140 if (flexTokenField.length === 0) { 141 jQuery('form.checkout').append('<input type="hidden" name="flex_cvv_token" value="' + flexTokenResponse.token + '">'); 142 } else { 143 flexTokenField.val(flexTokenResponse.token); 144 } 145 document.getElementById("errorMessage").value = "no"; 146 147 if (!window.flexSubmissionInProgress) { 148 window.flexSubmissionInProgress = true; 149 var form = jQuery('form.checkout'); 150 form.off('submit', handleFormSubmission); 151 form.removeClass('processing'); 152 form.submit(); 153 } 154 return false;
155 } else { 156 jQuery('#error-' + encodeURI(valueForTkn)).show(); 157 document.getElementById("errorMessage").value = "yes"; 158 return false; 159 } 160 } catch (error) { 161 jQuery('#error-' + encodeURI(valueForTkn)).show(); 162 document.getElementById("errorMessage").value = "yes"; 163 e.preventDefault(); 164 e.stopImmediatePropagation(); 165 return false; 166 } 167 } else { 168 // Flex is NOT being used - validate regular input field. 169 let security_code = jQuery('input[name=csc-saved-card-' + encodeURI(valueForTkn) + ']').val(); 170 if (security_code && (security_code.length < 3 || security_code.length > 4)) { 171 jQuery('#error-' + encodeURI(valueForTkn)).show(); 172 document.getElementById("errorMessage").value = "yes"; 173 //To stop loading checkout page after entering invaid CVV. 174 e.preventDefault(); 175 e.stopImmediatePropagation(); 176 return false; 177 } 178 document.getElementById("errorMessage").value = "no"; 179 } 180 } 181 } 182 183 // Attach the named function to the form submit event. 184 jQuery('form.checkout').on("submit", handleFormSubmission); 185 186 if (paymentMethodRow.length && defaultPaymentMethodRow.length && paymentMethodRowText != defaultPaymentMethodRowText) { 187 defaultPaymentMethodRow.find('.woocommerce-PaymentMethod--actions .delete').hide(); 188 } 189 190 function createButton(id, text) { 191 return $('<button>', { 192 type: 'button', 193 id: id, 194 class: 'btn btn-lg btn-block btn-primary', 195 disabled: 'disabled', 196 text: text, 197 style: 'display: none;' 198 }); 199 } 200 201 function addLoader() { 202 var loaderHtml = '<div id="loader" style="display:none;">' + 203 '</div>'; 204 jQuery('body').append(loaderHtml); 205 } 206 207 function showExpressPayLoader() { 208 addLoader(); 209 const blockUIElement = document.querySelector('.blockUI.blockOverlay'); 210 if (blockUIElement) { 211 var computedStyle = getComputedStyle(blockUIElement); 212 var display = computedStyle.getPropertyValue('display'); 213 var visibility = computedStyle.getPropertyValue('visibility') 214 if (display == 'none' || visibility == 'hidden') { 215 var loader = document.getElementById("loader"); 216 loader.style.display = "block"; 217 const topWindow = window.top; 218 topWindow.document.body.appendChild(loader); 219 } 220 } else { 221 222 var loader = document.getElementById("loader"); 223 loader.style.display = "block"; 224 const topWindow = window.top; 225 topWindow.document.body.appendChild(loader); 226 } 227 } 228 229 function hideExpressPayLoader() { 230 document.getElementById("loader").style.display = "none"; 231 } 232 233 function populateCheckoutFieldsFromTransientToken(transientToken, isExpressPay) { 234 return new Promise((resolve) => { 235 var expressOnly = !!isExpressPay; 236 var isLoggedIn = (typeof visa_acceptance_ajaxUCObj !== 'undefined' && visa_acceptance_ajaxUCObj.is_user_logged_in); 237 238 if (!expressOnly || isLoggedIn) { 239 resolve(); 240 return; 241 } 242 243 if (!transientToken) { 244 resolve(); 245 return; 246 } 247 248 jQuery.ajax({ 249 type: "POST", 250 url: visa_acceptance_ajaxUCObj["ajax_url"], 251 data: { 252 action: 'get_addresses_from_transient_token', 253 transientToken: transientToken 254 }, 255 success: function (response) { 256 if (response && response.success && response.data) { 257 const billing = response.data.billing || {}; 258 const shipping = response.data.shipping || {}; 259 260 const billingMap = { 261 first_name: 'billing_first_name', 262 last_name: 'billing_last_name', 263 company: 'billing_company', 264 address_1: 'billing_address_1', 265 address_2: 'billing_address_2', 266 city: 'billing_city', 267 state: 'billing_state', 268 postcode: 'billing_postcode', 269 country: 'billing_country', 270 email: 'billing_email', 271 phone: 'billing_phone' 272 }; 273
274 Object.keys(billingMap).forEach(function (key) { 275 if (billing[key] !== undefined && billing[key] !== null) { 276 const fieldName = billingMap[key]; 277 const $field = jQuery('[name="' + fieldName + '"]'); 278 if ($field.length) { 279 $field.val(billing[key]).trigger('change'); 280 } 281 } 282 }); 283 284 const shipDiffCheckbox = jQuery('#ship-to-different-address-checkbox'); 285 const shouldSetShipping = shipDiffCheckbox.length ? shipDiffCheckbox.is(':checked') : true; 286 287 if (shouldSetShipping) { 288 const shippingMap = { 289 first_name: 'shipping_first_name', 290 last_name: 'shipping_last_name', 291 company: 'shipping_company', 292 address_1: 'shipping_address_1', 293 address_2: 'shipping_address_2', 294 city: 'shipping_city', 295 state: 'shipping_state', 296 postcode: 'shipping_postcode', 297 country: 'shipping_country', 298 phone: 'shipping_phone' 299 }; 300 301 Object.keys(shippingMap).forEach(function (key) { 302 if (shipping[key] !== undefined && shipping[key] !== null) { 303 const fieldName = shippingMap[key]; 304 const $field = jQuery('[name="' + fieldName + '"]'); 305 if ($field.length) { 306 $field.val(shipping[key]).trigger('change'); 307 } 308 } 309 }); 310 } 311 312 jQuery(document.body).trigger('update_checkout'); 313 } 314 resolve(); 315 }, 316 error: function () { 317 resolve(); 318 } 319 }); 320 }); 321 } 322 323 // Initialize Flex microform for saved card CVV validation. 324 function initFlexForToken(tokenId) { 325 326 // Check if Flex is available and we have required settings. 327 var flexCaptureContext = document.getElementById("flex_cvv_token_data").value; 328 if (typeof Flex !== 'undefined' && tokenId && visa_acceptance_ajaxUCObj['saved_card_cvv'] && flexCaptureContext) { 329 330 331 if (flexCaptureContext && typeof flexCaptureContext === 'string') { 332 var jwtParts = flexCaptureContext.split('.'); 333 if (jwtParts.length === 3) { 334 335 try { 336 var flex = new Flex(flexCaptureContext); 337 338 var microform = flex.microform('card', { 339 styles: { 340 'input': { 341 'font-size': '14px', 342 'font-family': 'inherit', 343 'color': '#333', 344 'padding': '8px' 345 } 346 }, 347 }); 348 349 var cardType = ''; 350 if (visa_acceptance_ajaxUCObj['token_type'] && tokenId) { 351 cardType = visa_acceptance_ajaxUCObj['token_type'][tokenId] || ''; 352 } 353 var max_length = ('AMEX' == cardType) ? 4 : 3; 354 var securityCode = microform.createField('securityCode', { 355 placeholder: 'â¢â¢â¢', 356 maxLength: max_length 357 }); 358 359 // Wait for DOM to be ready and load CVV field. 360 setTimeout(() => { 361 var containerElement = document.getElementById('flex-cvv-' + encodeURI(tokenId)); 362 363 if (!containerElement) { 364 return; 365 } 366 367 try { 368 securityCode.load(containerElement); 369 flexInstances[tokenId] = { 370 microform: microform, 371 securityCode: securityCode, 372 tokenId: tokenId, 373 374 createToken: function() { 375 return new Promise((resolve, reject) => { 376 try { 377 const options = {}; 378 379 microform.createToken(options, (err, flexjwtToken) => { 380 if (err) { 381 console.error('An error occurred while generating the Microform token:', err); 382 reject(err); 383 } else { 384 resolve({ token: flexjwtToken }); 385 } 386 }); 387 } catch (error) { 388 console.error('An unexpected error occurred during Microform token creation:', error); 389 reject(error); 390 } 391 }); 392 } 393 }; 394 395 flexFieldsValid[tokenId] = false;
396 397 // Handle CVV field events. 398 securityCode.on('change', function(data) { 399 flexFieldsValid[tokenId] = data.valid; 400 if (data.valid) { 401 jQuery('#error-' + encodeURI(tokenId)).hide(); 402 } 403 }); 404 405 // Hide the regular input field. 406 jQuery('input[name="csc-saved-card-' + encodeURI(tokenId) + '"]').hide(); 407 408 // Show the parent container and Flex container only on success. 409 jQuery('#token-' + encodeURI(tokenId)).show(); 410 jQuery('#flex-cvv-' + encodeURI(tokenId)).show(); 411 412 } catch (fieldError) { 413 jQuery('#token-' + encodeURI(tokenId)).hide(); 414 } 415 }, 100); 416 417 } catch (error) { 418 jQuery('#token-' + encodeURI(tokenId)).hide(); 419 } 420 } else { 421 jQuery('#token-' + encodeURI(tokenId)).hide(); 422 } 423 } else { 424 jQuery('#token-' + encodeURI(tokenId)).hide(); 425 } 426 } else { 427 if (tokenId) { 428 jQuery('#token-' + encodeURI(tokenId)).hide(); 429 } 430 } 431 } 432 433 function initExpressCheckout() { 434 435 var transientToken = document.getElementById("transientToken"); 436 var captureContext = document.getElementById("ep_jwt_updated") ? (document.getElementById("ep_jwt_updated")?.value || null) : (document.getElementById("ep_jwt")?.value || null); 437 438 var showArgs = { 439 containers: { 440 paymentSelection: "#expressPaymentListContainer" 441 } 442 }; 443 444 if (typeof Accept !== 'undefined' && captureContext) { 445 jQuery('#wc-error-failure').hide(); 446 447 Accept(captureContext) 448 .then(function(accept) { 449 return accept.unifiedPayments(); 450 }) 451 .then(function(up) { 452 return up.show(showArgs); 453 }) 454 .then(function(tt) { 455 456 // Force Visa Unified Checkout as active method after checkout updates. 457 const paymentMethodRadioId = "input[name='payment_method'][value='" + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id'] + "']"; 458 if( ! jQuery(paymentMethodRadioId).is(':checked') ) { 459 jQuery(paymentMethodRadioId).prop('checked', true).trigger('click'); 460 } 461 const gatewayRadioId = '#wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-use-new-payment-method'; 462 jQuery(gatewayRadioId).prop('checked', true).trigger('click'); 463 464 // hide default payment method box. 465 jQuery('.woocommerce-checkout-payment').hide(); 466 467 // show loader while processing. 468 showExpressPayLoader(); 469 470 transientToken.value = tt; 471 populateCheckoutFieldsFromTransientToken(tt, true).then(function () { 472 if (jQuery('form#order_review').length > 0) { 473 jQuery('form#order_review').submit(); 474 } 475 else { 476 // Auto-accept terms & conditions for express pay so that 477 // WooCommerce's terms checkbox validation does not block 478 // the express pay flow (registered/admin users included). 479 var $termsCheckbox = jQuery('input[name="terms"]'); 480 if ($termsCheckbox.length && !$termsCheckbox.is(':checked')) { 481 $termsCheckbox.prop('checked', true); 482 } 483 isExpressPaySubmission = true; 484 setTimeout(() => { 485 jQuery('form.checkout').removeClass('processing'); 486 jQuery('form.checkout').submit(); 487 }, 200); 488 hideExpressPayLoader(); 489 } 490 }); 491 }) 492 .catch(function(error) { 493 jQuery('#wc-error-failure').show(); 494 jQuery('#expressPaymentListContainer').hide(); 495 // Show payment form back if express pay fails. 496 hideExpressPayLoader(); 497 jQuery('.woocommerce-checkout-payment').show(); 498 }); 499 } else if (!captureContext) { 500 jQuery('#express_payment_form_load_error').show(); 501 } else { 502 jQuery('#wc-error-failure').show(); 503 } 504 505 if( jQuery("#wc-express-checkout-section").is(':hidden') ) { 506 jQuery('.checkout #wc-error-failure #wc-failure-error').hide(); 507 } 508 } 509 // Listen for checkout validation errors and show payment form back. 510 jQuery(document.body).on('checkout_error', function() { 511 hideExpressPayLoader(); 512 jQuery('.woocommerce-checkout-payment').show(); 513 }); 514 // Run on checkout load.
515 if(visa_acceptance_ajaxUCObj['enabled_payment_methods'].length !== 0){ 516 jQuery(document.body).on('updated_checkout', initExpressCheckout); 517 } 518 // Run Express Checkout initialization only on Pay for Order page. 519 if ((window.location.href.indexOf('order-pay=') !== -1 || window.location.pathname.indexOf('/order-pay/') !== -1) && visa_acceptance_ajaxUCObj['enabled_payment_methods'].length !== 0 ) { 520 initExpressCheckout(); 521 } 522 523 function handlePaymentSelection(event) { 524 // Remove the tag when calling the handle function. 525 jQuery('#buttonPaymentListContainer').remove(); 526 var buttonPaymentListContainer = $('<div>', { 527 id: 'buttonPaymentListContainer' 528 }); 529 var checkoutEmbeddedButton = createButton('checkoutEmbedded', 'Loading...'); 530 var checkoutSidebarButton = createButton('checkoutSidebar', 'Loading...'); 531 532 buttonPaymentListContainer.append(checkoutEmbeddedButton, checkoutSidebarButton); 533 534 async function deriveAESKeyFromString(stringVal) { 535 const encoder = new TextEncoder(); 536 const valIdData = encoder.encode(stringVal); 537 538 // Hash the valId using SHA-256 and take the initial 32 bytes for AES-256. 539 const hashBuffer = await crypto.subtle.digest('SHA-256', valIdData); 540 return new Uint8Array(hashBuffer).slice(0, 32); 541 } 542 543 async function encryptData(data, stringVal) { 544 const extId = crypto.getRandomValues(new Uint8Array(12));//iv:extId 545 const encoder = new TextEncoder();
546 const encodedData = encoder.encode(data); 547 548 try { 549 const valId = await deriveAESKeyFromString(stringVal);//key:valId 550 const cryptoKey = await crypto.subtle.importKey( 551 'raw', 552 valId, 553 { name: 'AES-GCM' }, 554 false, 555 [visa_acceptance_ajaxUCObj['encrypt_const']] 556 ); 557 558 const encryptedBuffer = await crypto.subtle.encrypt( 559 { name: 'AES-GCM', iv: extId }, 560 cryptoKey, 561 encodedData 562 ); 563 564 const encryptedArray = new Uint8Array(encryptedBuffer); 565 const refIdLength = 16; 566 const ciphertext = encryptedArray.slice(0, encryptedArray.length - refIdLength); 567 const refId = encryptedArray.slice(encryptedArray.length - refIdLength);//tag:refId 568 569 // Return base64 encoded values. 570 return { 571 encrypted: btoa(String.fromCharCode(...ciphertext)), 572 extId: btoa(String.fromCharCode(...extId)), 573 refId: btoa(String.fromCharCode(...refId)) 574 }; 575 } catch (error) { 576 return null; 577 } 578 } 579 580 var tokencnt = visa_acceptance_ajaxUCObj['token_cnt']; 581 if ( visa_acceptance_ajaxUCObj['tokenization'] === 'no' ) { 582 // Force "use new card" option to be selected by default. 583 jQuery('#wc-credit-card-use-new-payment-method-div').show(); 584 if (jQuery('#wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-use-new-payment-method').length > 0) { 585 jQuery('#wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-use-new-payment-method').prop('checked', true); 586 } 587 jQuery('#buttonPaymentListContainer').show(); 588 jQuery('#place_order').hide(); 589 } else { 590 if (tokencnt != "0") { 591 if (jQuery('#wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-use-new-payment-method').is(':checked')) { 592 jQuery('#buttonPaymentListContainer').show(); 593 jQuery('#place_order').hide(); 594 } else { 595 jQuery('#buttonPaymentListContainer').hide(); 596 jQuery('.wc-payment-gateway-payment-form-manage-payment-methods').show(); 597 jQuery('#wc-credit-card-use-new-payment-method-div').show(); 598 jQuery('#place_order').show(); 599 jQuery('#wc-unified-checkout-normal-save-token-div').hide(); 600 }; 601 } 602 } 603 var tknval = jQuery('input[name=wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-payment-token]:checked').val(); 604 605 // Hide CVV containers for ALL eCheck tokens on page load. 606 if (visa_acceptance_ajaxUCObj['token_type']) { 607 jQuery.each(visa_acceptance_ajaxUCObj['token_type'], function(tokenId, tokenType) { 608 if (tokenType === 'eCheck') { 609 jQuery('#token-' + tokenId).hide(); 610 } 611 }); 612 } 613 614 // Check if currently selected token is eCheck - don't initialize CVV for eCheck tokens. 615 var isEcheck = visa_acceptance_ajaxUCObj['token_type'] && visa_acceptance_ajaxUCObj['token_type'][tknval] === 'eCheck'; 616 617 if (tknval && visa_acceptance_ajaxUCObj['saved_card_cvv'] && !isEcheck) { 618 setTimeout(() => { 619 initFlexForToken(tknval); 620 }, 100); 621 } 622 jQuery(`input[name="csc-saved-card-${encodeURI(tknval)}"]`).on('input', async function () { 623 let rawValue = jQuery(this).val().replace(/\D/g, ''); 624 let valId = visa_acceptance_ajaxUCObj['token_key']; 625 jQuery(this).val(rawValue); 626 627 if ((rawValue.length === 3 || rawValue.length === 4)) { 628 const encryptedData = await encryptData(rawValue, valId); 629 630 if (encryptedData) { 631 632 // Ensure hidden fields for extId, and refId are created if needed. 633 if ($(`input[name="extId-${encodeURI(tknval)}"]`).length === 0) { 634 jQuery(this).after(` 635 <input type="hidden" name="csc-saved-card-${encodeURI(tknval)}" value="${encryptedData.encrypted}"> 636 <input type="hidden" name="extId-${encodeURI(tknval)}" value="${encryptedData.extId}"> 637 <input type="hidden" name="refId-${encodeURI(tknval)}" value="${encryptedData.refId}"> 638 `); 639 } else { 640 $(`input[name="csc-saved-card-${encodeURI(tknval)}"]`).val(encryptedData.encrypted); 641 $(`input[name="extId-${encodeURI(tknval)}"]`).val(encryptedData.extId); 642 $(`input[name="refId-${encodeURI(tknval)}"]`).val(encryptedData.refId); 643 } 644 jQuery(this).val(rawValue); 645 } 646 } 647 }); 648 //Fetch token selected 649 var tknval = jQuery('input[name=wc-' + visa_acceptance_aja
649xUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-payment-token]:checked').val(); 650 jQuery('input[name=wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-payment-token]').click(function() { 651 jQuery('#wc-unified-checkout-tokenize-payment-method').prop('checked', false); 652 jQuery('.cvv-div').hide(); 653 jQuery('.wc-unified-checkout-saved-card #wc-unified-checkout-saved-card-cvn').val(''); 654 655 //Fetch token selected. 656 var tknval = jQuery(this).val(); 657 658 jQuery('[id^="flex-cvv-"]').hide(); 659 jQuery('input[name^="csc-saved-card-"]').hide(); 660 jQuery('[id^="token-"]').hide(); 661 662 // Initialize Flex for the newly selected token (it will show the div if successful). 663 // Check if token is eCheck - don't initialize CVV for eCheck tokens. 664 var isEcheckToken = visa_acceptance_ajaxUCObj['token_type'] && visa_acceptance_ajaxUCObj['token_type'][tknval] === 'eCheck'; 665 if (tknval && visa_acceptance_ajaxUCObj['saved_card_cvv'] && !isEcheckToken) { 666 setTimeout(() => { 667 initFlexForToken(tknval); 668 }, 100); 669 } 670 jQuery(`input[name="csc-saved-card-${encodeURI(tknval)}"]`).on('input', async function () { 671 let rawValue = jQuery(this).val().replace(/\D/g, ''); 672 let valId = visa_acceptance_ajaxUCObj['token_key']; 673 jQuery(this).val(rawValue); 674 675 if ((rawValue.length === 3 || rawValue.length === 4)) { 676 const encryptedData = await encryptData(rawValue, valId); 677 678 if (encryptedData) { 679 680 // Ensure hidden fields for extId, and refId are created if needed. 681 if ($(`input[name="extId-${encodeURI(tknval)}"]`).length === 0) { 682 jQuery(this).after(` 683 <input type="hidden" name="csc-saved-card-${encodeURI(tknval)}" value="${encryptedData.encrypted}"> 684 <input type="hidden" name="extId-${encodeURI(tknval)}" value="${encryptedData.extId}"> 685 <input type="hidden" name="refId-${encodeURI(tknval)}" value="${encryptedData.refId}"> 686 `); 687 } else { 688 $(`input[name="csc-saved-card-${encodeURI(tknval)}"]`).val(encryptedData.encrypted); 689 $(`input[name="extId-${encodeURI(tknval)}"]`).val(encryptedData.extId); 690 $(`input[name="refId-${encodeURI(tknval)}"]`).val(encryptedData.refId); 691 } 692 jQuery(this).val(rawValue); 693 } 694 } 695 }); 696 jQuery('input[name=wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-payment-token]').not(':checked').each(function() { 697 var tknval = jQuery(this).val(); 698 jQuery("#token-" + encodeURI(tknval)).hide(); 699 }); 700 if (jQuery('#wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-use-new-payment-method').is(':checked')) { 701 //Add at Checkout page below Use a new card. 702 if(!jQuery('#buttonPaymentListContainer').length){ 703 $('#wc-credit-card-use-new-payment-method-div').append(buttonPaymentListContainer); 704 } 705 var transientToken = document.getElementById("transientToken"); 706 var captureContext = document.getElementById("jwt_updated")? document.getElementById("jwt_updated").value : (document.getElementById("jwt") ? document.getElementById("jwt").value : null); 707 var showArgs = { 708 containers: { 709 //checkout with card Payment box. 710 paymentSelection: "#buttonPaymentListContainer" 711 } 712 }; 713 714 if (typeof Accept !== 'undefined') { 715 jQuery('#wc-error-failure').hide(); 716 Accept(captureContext) 717 .then(function(accept) { 718 return accept.unifiedPayments(); 719 }) 720 .then(function(up) { 721 return up.show(showArgs); 722 }) 723 .then(function(tt) { 724 transientToken.value = tt; 725 jQuery("body").css({"overflow": "auto"}); 726 populateCheckoutFieldsFromTransientToken(tt, false).then(function () { 727 if (jQuery('form#order_review').length > 0) { 728 jQuery('form#order_review').submit(); 729 } else if (jQuery('form#add_payment_method').length > 0) { 730 add_payment_method_token = tt; 731 jQuery("form#add_payment_method").submit(); 732 } else { 733 $('form.checkout').removeClass('processing'); 734 $('form.checkout').submit(); 735 } 736 }); 737 738 }).catch(function(error) { 739 jQuery('#wc-error-failure').show(); 740 jQuery('#buttonPaymentListContainer').hide(); 741 }); 742 } else { 743 buttonPaymentListContainer.append(errorMessagePara); 744 } 745 746 jQuery('#buttonPaymentListContainer').show(); 747 jQuery('#place_order').hide(); 748 jQuery('#wc-unified-checkout-normal-save-token-div').show(); 749 } else { 750 jQuery('#place_order').show(); 751 jQuery('#buttonPaymentListContainer').hide(); 752 jQuery('#wc-unified-checkout-normal-save-token-div').hide(); 753 }; 754 }); 755 756 if ($("input[name$='payment_method'][value$='" + visa_acceptance_aja
756xUCObj['visa_acceptance_solutions_uc_id'] +"']").is(':checked')) { 757 if (jQuery('#wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-use-new-payment-method').length == 0 || jQuery('#wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-use-new-payment-method').is(':checked')) { 758 $("#place_order").hide(); 759 if (event.type == 'init_add_payment_method') { 760 // At My account -> Add Payment page. 761 if(!jQuery('#buttonPaymentListContainer').length){ 762 jQuery('.woocommerce-PaymentBox.woocommerce-PaymentBox--' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id'] + '.payment_box.payment_method_' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id']).append(buttonPaymentListContainer); 763 } 764 } 765 //checkout page - no saved payment method. 766 var save_token_checkbox_div = $('#wc-unified-checkout-normal-save-token-div'); 767 if(save_token_checkbox_div.length){ 768 //save card enabled, insert before checkbox div 769 buttonPaymentListContainer.insertBefore(save_token_checkbox_div); 770 }else{ 771 //If save card option not enabled, append directly to parent div 772 if(!jQuery('#buttonPaymentListContainer').length){ 773 $('.payment_box.payment_method_' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id']).append(buttonPaymentListContainer); 774 } 775 } 776 var transientToken = document.getElementById("transientToken"); 777 var captureContext = document.getElementById("jwt_updated")? document.getElementById("jwt_updated").value : (document.getElementById("jwt") ? document.getElementById("jwt").value : null); 778 var showArgs = { 779 containers: { 780 paymentSelection: "#buttonPaymentListContainer" 781 } 782 }; 783 if (typeof Accept !== 'undefined') { 784 jQuery('#wc-error-failure').hide(); 785 Accept(captureContext) 786 .then(function(accept) { 787 return accept.unifiedPayments(); 788 }) 789 .then(function(up) { 790 return up.show(showArgs); 791 }) 792 .then(function(tt) { 793 transientToken.value = tt; 794 // Adding to make the overflow auto. 795 jQuery("body").css({"overflow": "auto"}); 796 populateCheckoutFieldsFromTransientToken(tt, false).then(function () { 797 if (jQuery('form#order_review').length > 0) { 798 jQuery('form#order_review').submit(); 799 } else if (jQuery('form#add_payment_method').length > 0) { 800 add_payment_method_token = tt; 801 jQuery("form#add_payment_method").submit(); 802 } else { 803 $('form.checkout').removeClass('processing'); 804 $('form.checkout').submit(); 805 } 806 }); 807 808 }).catch(function(error) { 809 jQuery('#wc-error-failure').show(); 810 jQuery('#buttonPaymentListContainer').hide(); 811 }); 812 } else { 813 buttonPaymentListContainer.append(errorMessagePara); 814 } 815 816 } else { 817 buttonPaymentListContainer.append(errorMessagePara); 818 } 819 820 } else { 821 $("#place_order").show(); 822 $('.wc_payment_method.payment_method_' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id']).find('#buttonPaymentListContainer').empty(); 823 } 824 if (event.type == 'init_add_payment_method') { 825 firstLoadFlag = true; 826 827 function checkAndTrigger() { 828 if ($("input[name$='payment_method'][value$='"+ visa_acceptance_aja
828xUCObj['visa_acceptance_solutions_uc_id'] +"']").is(':checked') && !isEventTriggered) { 829 $(document.body).trigger('init_add_payment_method'); 830 isEventTriggered = true; // Set the flag to true once the event is triggered. 831 } else if (!$("input[name$='payment_method'][value$='"+ visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id']+"']").is(':checked')) { 832 isEventTriggered = false; // Reset the flag if the checkbox is unchecked. 833 } 834 } 835 836 function checkAndRemove() { 837 if (!$("input[name$='payment_method'][value$='"+ visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id']+"']").is(':checked')) { 838 $("#place_order").show(); 839 $('li.payment_method_' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id']).find('#buttonPaymentListContainer').empty(); 840 } 841 } 842 843 setInterval(checkAndTrigger, 1000); 844 setInterval(checkAndRemove, 1000); 845 } 846 } 847 848 $('body').on('payment_method_selected', handlePaymentSelection); 849 // Whenever there is an error it will call the function. 850 $('body').on('updated_checkout', handlePaymentSelection); 851 $('body').on('init_add_payment_method', function(event) { 852 handlePaymentSelection(event); 853 }); 854 855 856 //Code for Special case of pay-order page 857 //This extracts order_id to pass it to custom getOrderIDPayPage 858 var hrefUrl = window.location.href; 859 var url = new URL(hrefUrl); 860 var orderPayValue = url.searchParams.get("order-pay"); 861 var startIndex = hrefUrl.indexOf("/order-pay/") + "/order-pay/".length; 862 var endIndex = hrefUrl.indexOf("/", startIndex); 863 var extractedNumber; 864 if (startIndex !== -1 && endIndex !== -1 && hrefUrl.indexOf("/order-pay/") !== -1) { 865 extractedNumber = hrefUrl.substring(startIndex, endIndex); 866 } else if (orderPayValue !== null) { 867 extractedNumber = orderPayValue; 868 } 869 870 var repeatFlag = false; 871 872 jQuery('form#order_review').on('submit', async function(e) { 873 if ($("input[name$='payment_method'][value$='" + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id'] +"']").is(':checked')) { 874 var valTkn = jQuery('input[name=wc-' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id_hyphen'] +'-payment-token]:checked').val(); 875 var trans_token = document.getElementById("transientToken").value; 876 var solution_id = ''; 877 if (trans_token) { 878 const parts = trans_token.split('.'); 879 const decodedPayload = atob(parts[1]); 880 881 const payload = JSON.parse(decodedPayload); 882 883 if (payload?.content?.processingInformation?.paymentSolution?.value !== undefined) { 884 solution_id = payload.content.processingInformation.paymentSolution.value; 885 } 886 887 888 } 889 890 // Check if token is eCheck - skip CVV validation for eCheck. 891 var isEcheckPayOrder = visa_acceptance_ajaxUCObj['token_type'] && visa_acceptance_ajaxUCObj['token_type'][valTkn] === 'eCheck'; 892 893 // Check if using saved card with CVV required. 894 if (valTkn && visa_acceptance_ajaxUCObj['saved_card_cvv'] && !isEcheckPayOrder) { 895 // Check if Flex is being used for this token 896 if (flexInstances[valTkn]) { 897 if (!flexFieldsValid[valTkn]) { 898 jQuery('#error-' + encodeURI(valTkn)).show(); 899 e.preventDefault(); 900 e.stopImmediatePropagation(); 901 return false; 902 } 903 904 try { 905 e.preventDefault(); 906 e.stopImmediatePropagation(); 907 908 var flexTokenResponse = await flexInstances[valTkn].createToken(); 909 910 if (flexTokenResponse && flexTokenResponse.token) { 911 // Add the flex token to a hidden field 912 var flexTokenField = jQuery('input[name="flex_cvv_token"]'); 913 if (flexTokenField.length === 0) { 914 jQuery('form#order_review').append('<input type="hidden" name="flex_cvv_token" value="' + flexTokenResponse.token + '">'); 915 } else { 916 flexTokenField.val(flexTokenResponse.token); 917 } 918 if (!window.orderReviewFlexSubmission) { 919 window.orderReviewFlexSubmission = true; 920 // Check if payer authentication flow should handle submission 921 var isPayerAuthFlow = typeof visa_acceptance_uc_payer_auth_param !== 'undefined' 922 && visa_acceptance_uc_payer_auth_param['payment_method'] == 'unified_checkout' 923 && solution_id != '001' 924 && solution_id != '027'; 925 if (!isPayerAuthFlow) { 926 var form = jQuery('form#order_review'); 927 form.off('submit'); 928 form.submit(); 929 return false;
930 } 931 } 932 } else { 933 jQuery('#error-' + encodeURI(valTkn)).show(); 934 return false; 935 } 936 } catch (error) { 937 jQuery('#error-' + encodeURI(valTkn)).show(); 938 return false; 939 } 940 } else { 941 var security_code = jQuery('input[name=csc-saved-card-' + encodeURI(valTkn) + ']').val(); 942 if (( !(typeof security_code == 'undefined') && (security_code == '' || security_code.length > 4 || security_code.length < 3))) { 943 jQuery('#error-' + encodeURI(valTkn)).show(); 944 e.preventDefault(); 945 e.stopImmediatePropagation(); 946 return false; 947 } 948 } 949 } 950 951 if (typeof visa_acceptance_uc_payer_auth_param !== 'undefined' && solution_id != '001' && solution_id != '027') { 952 e.preventDefault(); 953 } 954 if (typeof payer_auth_param == 'undefined') { 955 if (!repeatFlag) { 956 repeatFlag = true; 957 958 if ((jQuery('#payment_method_' + visa_acceptance_ajaxUCObj['visa_acceptance_solutions_uc_id']).is(':checked'))) { 959 if (typeof visa_acceptance_uc_payer_auth_param !== 'undefined' && visa_acceptance_uc_payer_auth_param['payment_method'] == 'unified_checkout' && solution_id != '001' && solution_id != '027') { 960 addLoader(); 961 showLoader(); 962 getOrderIDPayPage(extractedNumber); 963 } else { 964 return true; 965 } 966 967 } 968 } 969 } 970 } 971 }); 972 973 974 // Function to move Visa Acceptance payment method after terms and conditions 975 function movePaymentMethodAfterTerms() { 976 var $termsWrapper = $('.woocommerce-terms-and-conditions-wrapper'); 977 var $visaPaymentMethod = $('.payment_box.payment_method_visa_acceptance_solutions_unified_checkout'); 978 var $paymentMethods = $('.wc_payment_methods.payment_methods.methods'); 979 980 // Check if both elements exist 981 if ($termsWrapper.length && $visaPaymentMethod.length) { 982 // Check if it's not already moved 983 if (!$visaPaymentMethod.hasClass('moved-after-terms') && $paymentMethods.length) { 984 // Add a class to track that it's been moved 985 $visaPaymentMethod.addClass('moved-after-terms'); 986 987 // Move the actual payment method element after terms and conditions 988 $visaPaymentMethod.detach().insertAfter($termsWrapper); 989 var $form = $('form.checkout'); 990 $visaPaymentMethod.find( 991 '#transientToken, #errorMessage, #jwt, #jwt_updated, #ep_jwt, #ep_jwt_updated, #payer_auth_enabled, #flex_cvv_token_data' 992 ).each(function() { 993 $form.append($(this).detach()); 994 }); 995 996 // Setup radio button synchronization 997 setupPaymentMethodRadioSync(); 998 } 999 } 1000 } 1001 1002 // Function to ensure only one payment method radio is selected at a time 1003 function setupPaymentMethodRadioSync() { 1004 // Handle clicks on the moved Visa Acceptance radio button 1005 $(document).on('change', '.payment_box.payment_method_visa_acceptance_solutions_unified_checkout.moved-after-terms > input[type="radio"][name="payment_method"]', function() { 1006 if ($(this).is(':checked')) { 1007 // Uncheck all other payment method radios in the original list 1008 $('.wc_payment_methods.payment_methods.methods input[type="radio"][name="payment_method"]').prop('checked', false); 1009 1010 // Show the payment box 1011 $('.payment_box.payment_method_visa_acceptance_solutions_unified_checkout.moved-after-terms .payment_box').slideDown(); 1012 1013 // Trigger WooCommerce payment method selected event 1014 $(document.body).trigger('payment_method_selected'); 1015 } 1016 }); 1017 1018 // Handle clicks on other payment method radios in the main payment methods list 1019 $(document).on('change', '.wc_payment_methods.payment_methods.methods input[type="radio"][name="payment_method"]', function() { 1020 if ($(this).is(':checked')) { 1021 // Uncheck the moved Visa Acceptance main radio button 1022 $('.payment_box.payment_method_visa_acceptance_solutions_unified_checkout.moved-after-terms > input[type="radio"][name="payment_method"]').prop('checked', false); 1023 1024 // Uncheck all nested token selection radios (saved cards and "use new card") 1025 $('.payment_box.payment_method_visa_acceptance_solutions_unified_checkout.moved-after-terms input[type="radio"]').not('[name="payment_method"]').prop('checked', false); 1026 1027 // Hide the payment box 1028 $('.payment_box.payment_method_visa_acceptance_solutions_unified_checkout.moved-after-terms .payment_box').slide
1028Up(); 1029 } 1030 }); 1031 } 1032 1033 // Run after WooCommerce updates checkout 1034 $(document.body).on('updated_checkout', function() { 1035 movePaymentMethodAfterTerms(); 1036 }); 1037 1038 })(jQuery);
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.