PageSourceSearch

https://www.businessqualifications.com/wp-content/plugins/woocomme…/js/stripe-payment-request.js?ver=6.3.3

js businessqualifications.com collected 2026-10-08 04:31:23 UTC 28,924 bytes, 825 lines download raw bytes

1/* global wc_stripe_payment_request_params, Stripe */
2jQuery( function( $ ) {
3	'use strict';
4
5	var stripe = Stripe( wc_stripe_payment_request_params.stripe.key, {
6		locale: wc_stripe_payment_request_params.stripe.locale
7	} ),
8		paymentRequestType;
9
10	/**
11	 * Object to handle Stripe payment forms.
12	 */
13	var wc_stripe_payment_request = {
14		/**
15		 * Get WC AJAX endpoint URL.
16		 *
17		 * @param  {String} endpoint Endpoint.
18		 * @return {String}
19		 */
20		getAjaxURL: function( endpoint ) {
21			return wc_stripe_payment_request_params.ajax_url
22				.toString()
23				.replace( '%%endpoint%%', 'wc_stripe_' + endpoint );
24		},
25
26		getCartDetails: function() {
27			var data = {
28				security: wc_stripe_payment_request_params.nonce.payment
29			};
30
31			$.ajax( {
32				type:    'POST',
33				data:    data,
34				url:     wc_stripe_payment_request.getAjaxURL( 'get_cart_details' ),
35				success: function( response ) {
36					wc_stripe_payment_request.startPaymentRequest( response );
37				}
38			} );
39		},
40
41		getAttributes: function() {
42			var select = $( '.variations_form' ).find( '.variations select' ),
43				data   = {},
44				count  = 0,
45				chosen = 0;
46
47			select.each( function() {
48				var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
49				var value          = $( this ).val() || '';
50
51				if ( value.length > 0 ) {
52					chosen ++;
53				}
54
55				count ++;
56				data[ attribute_name ] = value;
57			});
58
59			return {
60				'count'      : count,
61				'chosenCount': chosen,
62				'data'       : data
63			};
64		},
65
66		processSource: function( source, paymentRequestType ) {
67			var data = wc_stripe_payment_request.getOrderData( source, paymentRequestType );
68
69			return $.ajax( {
70				type:    'POST',
71				data:    data,
72				dataType: 'json',
73				url:     wc_stripe_payment_request.getAjaxURL( 'create_order' )
74			} );
75		},
76
77		/**
78		 * Get order data.
79		 *
80		 * @since 3.1.0
81		 * @version 4.0.0
82		 * @param {PaymentResponse} source Payment Response instance.
83		 *
84		 * @return {Object}
85		 */
86		getOrderData: function( evt, paymentRequestType ) {
87			var source   = evt.source;
88			var email    = source.owner.email;
89			var phone    = source.owner.phone;
90			var billing  = source.owner.address;
91			var name     = source.owner.name;
92			var shipping = evt.shippingAddress;
93			var data     = {
94				_wpnonce:                  wc_stripe_payment_request_params.nonce.checkout,
95				billing_first_name:        null !== name ? name.split( ' ' ).slice( 0, 1 ).join( ' ' ) : '',
96				billing_last_name:         null !== name ? name.split( ' ' ).slice( 1 ).join( ' ' ) : '',
97				billing_company:           '',
98				billing_email:             null !== email   ? email : evt.payerEmail,
99				billing_phone:             null !== phone   ? phone : evt.payerPhone && evt.payerPhone.replace( '/[() -]/g', '' ),
100				billing_country:           null !== billing ? billing.country : '',
101				billing_address_1:         null !== billing ? billing.line1 : '',
102				billing_address_2:         null !== billing ? billing.line2 : '',
103				billing_city:              null !== billing ? billing.city : '',
104				billing_state:             null !== billing ? billing.state : '',
105				billing_postcode:          null !== billing ? billing.postal_code : '',
106				shipping_first_name:       '',
107				shipping_last_name:        '',
108				shipping_company:          '',
109				shipping_country:          '',
110				shipping_address_1:        '',
111				shipping_address_2:        '',
112				shipping_city:             '',
113				shipping_state:            '',
114				shipping_postcode:         '',
115				shipping_method:           [ null === evt.shippingOption ? null : evt.shippingOption.id ],
116				order_comments:            '',
117				payment_method:            'stripe',
118				ship_to_different_address: 1,
119				terms:                     1,
120				stripe_source:             source.id,
121				payment_request_type:      paymentRequestType
122			};
123
124			if ( shipping ) {
125				data.shipping_first_name = shipping.recipient.split( ' ' ).slice( 0, 1 ).join( ' ' );
126				data.shipping_last_name  = shipping.recipient.split( ' ' ).slice( 1 ).join( ' ' );
127				data.shipping_company    = shipping.organization;
128				data.shipping_country    = shipping.country;
129				data.shipping_address_1  = typeof shipping.addressLine[0] === 'undefined' ? '' : shipping.addressLine[0];
130				data.shipping_address_2  = typeof shipping.addressLine[1] === 'undefined' ? '' : shipping.addressLine[1];
131				data.shipping_city       = shipping.city;
132				data.shipping_state      = shipping.region;
133				data.shipping_postcode   = shipping.postalCode;
134			}
135
136			return data;
137		},
138
139		/**
140		 * Generate error message HTML.
141		 *
142		 * @since 3.1.0
143		 * @version 4.0.0
144		 * @param  {String} message Error message.
145		 * @return {Object}
146		 */
147		getErrorMessageHTML: function( message ) {
148			return $( '<div class="woocommerce-error" />' ).text( message );
149		},
150
151		/**
152		 * Display error messages.
153		 *
154		 * @since 4.8.0
155		 * @param {Object} message DOM object with error message to display.
156		 */
157		displayErrorMessage: function( message ) {
158			$( '.woocommerce-error' ).remove();
159
160			if ( wc_stripe_payment_request_params.is_product_page ) {
161				var element = $( '.product' ).first();
162				element.before( message );
163
164				$( 'html, body' ).animate({
165					scrollTop: element.prev( '.woocommerce-error' ).offset().top
166				}, 600 );
167			} else {
168				var $form = $( '.shop_table.cart' ).closest( 'form' );
169				$form.before( message );
170				$( 'html, body' ).animate({
171					scrollTop: $form.prev( '.woocommerce-error' ).offset().top
172				}, 600 );
173			}
174		},
175
176		/**
177		 * Abort payment and display error messages.
178		 *
179		 * @since 3.1.0
180		 * @version 4.8.0
181		 * @param {PaymentResponse} payment Payment response instance.
182		 * @param {Object}          message DOM object with error message to display.
183		 */
184		abortPayment: function( payment, message ) {
185			payment.complete( 'fail' );
186			wc_stripe_payment_request.displayErrorMessage( message );
187		},
188
189		/**
190		 * Complete payment.
191		 *
192		 * @since 3.1.0
193		 * @version 4.0.0
194		 * @param {PaymentResponse} payment Payment response instance.
195		 * @param {String}          url     Order thank you page URL.
196		 */
197		completePayment: function( payment, url ) {
198			wc_stripe_payment_request.block();
199
200			payment.complete( 'success' );
201
202			// Success, then redirect to the Thank You page.
203			window.location = url;
204		},
205
206		block: function() {
207			$.blockUI( {
208				message: null,
209				overlayCSS: {
210					background: '#fff',
211					opacity: 0.6
212				}
213			} );
214		},
215
216		/**
217		 * Update shipping options.
218		 *
219		 * @param {Object}         details Payment details.
220		 * @param {PaymentAddress} address Shipping address.
221		 */
222		updateShippingOptions: function( details, address ) {
223			var data = {
224				security:  wc_stripe_payment_request_params.nonce.shipping,
225				country:   address.country,
226				state:     address.region,
227				postcode:  address.postalCode,
228				city:      address.city,
229				address:   typeof address.addressLine[0] === 'undefined' ? '' : address.addressLine[0],
230				address_2: typeof address.addressLine[1] === 'undefined' ? '' : address.addressLine[1],
231				payment_request_type: paymentRequestType,
232				is_product_page: wc_stripe_payment_request_params.is_product_page,
233			};
234
235			return $.ajax( {
236				type:    'POST',
237				data:    data,
238				url:     wc_stripe_payment_request.getAjaxURL( 'get_shipping_options' )
239			} );
240		},
241
242		/**
243		 * Updates the shipping price and the total based on the shipping option.
244		 *
245		 * @param {Object}   details        The line items and shipping options.
246		 * @param {String}   shippingOption User's preferred shipping option to use for shipping price calculations.
247		 */
248		updateShippingDetails: function( details, shippingOption ) {
249			var data = {
250				security: wc_stripe_payment_request_params.nonce.update_shipping,
251				shipping_method: [ shippingOption.id ],
252				payment_request_type: paymentRequestType,
253				is_product_page: wc_stripe_payment_request_params.is_product_page,
254			};
255
256			return $.ajax( {
257				type: 'POST',
258				data: data,
259				url:  wc_stripe_payment_request.getAjaxURL( 'update_shipping_method' )
260			} );
261		},
262
263		/**
264		 * Adds the item to the cart and return cart details.
265		 *
266		 */
267		addToCart: function() {
268			var product_id = $( '.single_add_to_cart_button' ).val();
269
270			// Check if product is a variable product.
271			if ( $( '.single_variation_wrap' ).length ) {
272				product_id = $( '.single_variation_wrap' ).find( 'input[name="product_id"]' ).val();
273			}
274
275			var data = {
276				security: wc_stripe_payment_request_params.nonce.add_to_cart,
277				product_id: product_id,
278				qty: $( '.quantity .qty' ).val(),
279				attributes: $( '.variations_form' ).length ? wc_stripe_payment_request.getAttributes().data : []
280			};
281
282			// add addons data to the POST body
283			var formData = $( 'form.cart' ).serializeArray();
284			$.each( formData, function( i, field ) {
285				if ( /^addon-/.test( field.name ) ) {
286					if ( /\[\]$/.test( field.name ) ) {
287						var fieldName = field.name.substring( 0, field.name.length - 2);
288						if ( data[ fieldName ] ) {
289							data[ fieldName ].push( field.value );
290						} else {
291							data[ fieldName ] = [ field.value ];
292						}
293					} else {
294						data[ field.name ] = field.value;
295					}
296				}
297			} );
298
299			return $.ajax( {
300				type: 'POST',
301				data: data,
302				url:  wc_stripe_payment_request.getAjaxURL( 'add_to_cart' )
303			} );
304		},
305
306		clearCart: function() {
307			var data = {
308					'security': wc_stripe_payment_request_params.nonce.clear_cart
309				};
310
311			return $.ajax( {
312				type:    'POST',
313				data:    data,
314				url:     wc_stripe_payment_request.getAjaxURL( 'clear_cart' ),
315				success: function( response ) {}
316			} );
317		},
318
319		getRequestOptionsFromLocal: function() {
320			return {
321				total: wc_stripe_payment_request_params.product.total,
322				currency: wc_stripe_payment_request_params.checkout.currency_code,
323				country: wc_stripe_payment_request_params.checkout.country_code,
324				requestPayerName: true,
325				requestPayerEmail: true,
326				requestPayerPhone: wc_stripe_payment_request_params.checkout.needs_payer_phone,
327				requestShipping: wc_stripe_payment_request_params.product.requestShipping,
328				displayItems: wc_stripe_payment_request_params.product.displayItems
329			};
330		},
331
332		/**
333		 * Starts the payment request
334		 *
335		 * @since 4.0.0
336		 * @version 4.8.0
337		 */
338		startPaymentRequest: function( cart ) {
339			var paymentDetails,
340				options;
341
342			if ( wc_stripe_payment_request_params.is_product_page ) {
343				options = wc_stripe_payment_request.getRequestOptionsFromLocal();
344
345				paymentDetails = options;
346			} else {
347				options = {
348					total: cart.order_data.total,
349					currency: cart.order_data.currency,
350					country: cart.order_data.country_code,
351					requestPayerName: true,
352					requestPayerEmail: true,
353					requestPayerPhone: wc_stripe_payment_request_params.checkout.needs_payer_phone,
354					requestShipping: cart.shipping_required ? true : false,
355					displayItems: cart.order_data.displayItems
356				};
357
358				paymentDetails = cart.order_data;
359			}
360
361			// Puerto Rico (PR) is the only US territory/possession that's supported by Stripe.
362			// Since it's considered a US state by Stripe, we need to do some special mapping.
363			if ( 'PR' === options.country ) {
364				options.country = 'US';
365			}
366
367			// Handle errors thrown by Stripe, so we don't break the product page
368			try {
369				var paymentRequest = stripe.paymentRequest( options );
370
371				var elements = stripe.elements( { locale: wc_stripe_payment_request_params.button.locale } );
372				var prButton = wc_stripe_payment_request.createPaymentRequestButton( elements, paymentRequest );
373
374				// Check the availability of the Payment Request API first.
375				paymentRequest.canMakePayment().then( function( result ) {
376					if ( ! result ) {
377						return;
378					}
379					if ( result.applePay ) {
380						paymentRequestType = 'apple_pay';
381					} else if ( result.googlePay ) {
382						paymentRequestType = 'google_pay';
383					} else {
384						paymentRequestType = 'payment_request_api';
385					}
386
387					wc_stripe_payment_request.attachPaymentRequestButtonEventListeners( prButton, paymentRequest );
388					wc_stripe_payment_request.showPaymentRequestButton( prButton );
389				} );
390
391				// Possible statuses success, fail, invalid_payer_name, invalid_payer_email, invalid_payer_phone, invalid_shipping_address.
392				paymentRequest.on( 'shippingaddresschange', function( evt ) {
393					$.when( wc_stripe_payment_request.updateShippingOptions( paymentDetails, evt.shippingAddress ) ).then( function( response ) {
394						evt.updateWith( { status: response.result, shippingOptions: response.shipping_options, total: response.total, displayItems: response.displayItems } );
395					} );
396				} );
397
398				paymentRequest.on( 'shippingoptionchange', function( evt ) {
399					$.when( wc_stripe_payment_request.updateShippingDetails( paymentDetails, evt.shippingOption ) ).then( function( response ) {
400						if ( 'success' === response.result ) {
401							evt.updateWith( { status: 'success', total: response.total, displayItems: response.displayItems } );
402						}
403
404						if ( 'fail' === response.result ) {
405							evt.updateWith( { status: 'fail' } );
406						}
407					} );
408				} );
409
410				paymentRequest.on( 'source', function( evt ) {
411					// Check if we allow prepaid cards.
412					if ( 'no' === wc_stripe_payment_request_params.stripe.allow_prepaid_card && 'prepaid' === evt.source.card.funding ) {
413						wc_stripe_payment_request.abortPayment( evt, wc_stripe_payment_request.getErrorMessageHTML( wc_stripe_payment_request_params.i18n.no_prepaid_card ) );
414					} else {
415						$.when( wc_stripe_payment_request.processSource( evt, paymentRequestType ) ).then( function( response ) {
416							if ( 'success' === response.result ) {
417								wc_stripe_payment_request.completePayment( evt, response.redirect );
418							} else {
419								wc_stripe_payment_request.abortPayment( evt, response.messages );
420							}
421						} );
422					}
423				} );
424			} catch( e ) {
425				// Leave for troubleshooting
426				console.error( e );
427			}
428		},
429
430		getSelectedProductData: function() {
431			var product_id = $( '.single_add_to_cart_button' ).val();
432
433			// Check if product is a variable product.
434			if ( $( '.single_variation_wrap' ).length ) {
435				product_id = $( '.single_variation_wrap' ).find( 'input[name="product_id"]' ).val();
436			}
437
438			var addons = $( '#product-addons-total' ).data('price_data') || [];
439			var addon_value = addons.reduce( function ( sum, addon ) { return sum + addon.cost; }, 0 );
440
441			var data = {
442				security: wc_stripe_payment_request_params.nonce.get_selected_product_data,
443				product_id: product_id,
444				qty: $( '.quantity .qty' ).val(),
445				attributes: $( '.variations_form' ).length ? wc_stripe_payment_request.getAttributes().data : [],
446				addon_value: addon_value,
447			};
448
449			return $.ajax( {
450				type: 'POST',
451				data: data,
452				url:  wc_stripe_payment_request.getAjaxURL( 'get_selected_product_data' )
453			} );
454		},
455
456		/**
457		 * Creates a wrapper around a function that ensures a function can not
458		 * called in rappid succesion. The function can only be executed once and then agin after
459		 * the wait time has expired.  Even if the wrapper is called multiple times, the wrapped
460		 * function only excecutes once and then blocks until the wait time expires.
461		 *
462		 * @param {int} wait       Milliseconds wait for the next time a function can be executed.
463		 * @param {function} func       The function to be wrapped.
464		 * @param {bool} immediate Overriding the wait time, will force the function to fire everytime.
465		 *
466		 * @return {function} A wrapped function with execution limited by the wait time.
467		 */
468		debounce: function( wait, func, immediate ) {
469			var timeout;
470			return function() {
471				var context = this, args = arguments;
472				var later = function() {
473					timeout = null;
474					if (!immediate) func.apply(context, args);
475				};
476				var callNow = immediate && !timeout;
477				clearTimeout(timeout);
478				timeout = setTimeout(later, wait);
479				if (callNow) func.apply(context, args);
480			};
481		},
482
483		/**
484		 * Creates stripe paymentRequest element or connects to custom button
485		 *
486		 * @param {object} elements       Stripe elements instance.
487		 * @param {object} paymentRequest Stripe paymentRequest object.
488		 *
489		 * @return {object} Stripe paymentRequest element or custom button jQuery element.
490		 */
491		createPaymentRequestButton: function( elements, paymentRequest ) {
492			var button;
493			if ( wc_stripe_payment_request_params.button.is_custom ) {
494				button = $( wc_stripe_payment_request_params.button.css_selector );
495				if ( button.length ) {
496					// We fallback to default paymentRequest button if no custom button is found in the UI.
497					// Add flag to be sure that created button is custom button rather than fallback element.
498					button.data( 'isCustom', true );
499					return button;
500				}
501			}
502
503			if ( wc_stripe_payment_request_params.button.is_branded ) {
504				if ( wc_stripe_payment_request.shouldUseGooglePayBrand() ) {
505					button = wc_stripe_payment_request.createGooglePayButton();
506					// Add flag to be sure that created button is branded rather than fallback element.
507					button.data( 'isBranded', true );
508					return button;
509				} else {
510					// Not implemented branded buttons default to Stripe's button
511					// Apple Pay buttons can also fall back to Stripe's button, as it's already branded
512					// Set button type to default or buy, depending on branded type, to avoid issues with Stripe
513					wc_stripe_payment_request_params.button.type = 'long' === wc_stripe_payment_request_params.button.branded_type ? 'buy' : 'default';
514				}
515			}
516
517			return elements.create( 'paymentRequestButton', {
518				paymentRequest: paymentRequest,
519				style: {
520					paymentRequestButton: {
521						type: wc_stripe_payment_request_params.button.type,
522						theme: wc_stripe_payment_request_params.button.theme,
523						height: wc_stripe_payment_request_params.button.height + 'px',
524					},
525				},
526			} );
527		},
528
529		/**
530		 * Checks if button is custom payment request button.
531		 *
532		 * @param {object} prButton Stripe paymentRequest element or custom jQuery element.
533		 *
534		 * @return {boolean} True when prButton is custom button jQuery element.
535		 */
536		isCustomPaymentRequestButton: function ( prButton ) {
537			return prButton && 'function' === typeof prButton.data && prButton.data( 'isCustom' );
538		},
539
540		isBrandedPaymentRequestButton: function ( prButton ) {
541			return prButton && 'function' === typeof prButton.data && prButton.data( 'isBranded' );
542		},
543
544		shouldUseGooglePayBrand: function () {
545			var ua = window.navigator.userAgent.toLowerCase();
546			var isChrome = /chrome/.test( ua ) && ! /edge|edg|opr|brave\//.test( ua ) && 'Google Inc.' === window.navigator.vendor;
547			// newer versions of Brave do not have the userAgent string
548			var isBrave = isChrome && window.navigator.brave;
549			return isChrome && ! isBrave;
550		},
551
552		createGooglePayButton: function () {
553			var allowedThemes = [ 'dark', 'light', 'light-outline' ];
554			var allowedTypes = [ 'short', 'long' ];
555
556			var theme  = wc_stripe_payment_request_params.button.theme;
557			var type   = wc_stripe_payment_request_params.button.branded_type;
558			var locale = wc_stripe_payment_request_params.button.locale;
559			var height = wc_stripe_payment_request_params.button.height;
560			theme = allowedThemes.includes( theme ) ? theme : 'light';
561			var gpaySvgTheme = 'dark' === theme ? 'dark' : 'light';
562			type = allowedTypes.includes( type ) ? type : 'long';
563
564			var button = $( '<button type="button" id="wc-stripe-branded-button" aria-label="Google Pay" class="gpay-button"></button>' );
565			button.css( 'height', height + 'px' );
566			button.addClass( theme + ' ' + type );
567			if ( 'long' === type ) {
568				var url = 'https://www.gstatic.com/instantbuy/svg/' + gpaySvgTheme + '/' + locale + '.svg';
569				var fallbackUrl = 'https://www.gstatic.com/instantbuy/svg/' + gpaySvgTheme + '/en.svg';
570				// Check if locale GPay button exists, default to en if not
571				setBackgroundImageWithFallback( button, url, fallbackUrl );
572			}
573
574			return button;
575		},
576
577		attachPaymentRequestButtonEventListeners: function( prButton, paymentRequest ) {
578			// First, mark the body so we know a payment request button was used.
579			// This way error handling can any display errors in the most appropriate place.
580			prButton.on( 'click', function ( evt ) {
581				$( 'body' ).addClass( 'woocommerce-stripe-prb-clicked' );
582			});
583
584			// Then, attach specific handling for selected pages and button types
585			if ( wc_stripe_payment_request_params.is_product_page ) {
586				wc_stripe_payment_request.attachProductPageEventListeners( prButton, paymentRequest );
587			} else {
588				wc_stripe_payment_request.attachCartPageEventListeners( prButton, paymentRequest );
589			}
590		},
591
592		attachProductPageEventListeners: function( prButton, paymentRequest ) {
593			var paymentRequestError = [];
594			var addToCartButton = $( '.single_add_to_cart_button' );
595
596			prButton.on( 'click', function ( evt ) {
597				// If login is required for checkout, display redirect confirmation dialog.
598				if ( wc_stripe_payment_request_params.login_confirmation ) {
599					evt.preventDefault();
600					displayLoginConfirmation( paymentRequestType );
601					return;
602				}
603
604				// First check if product can be added to cart.
605				if ( addToCartButton.is( '.disabled' ) ) {
606					evt.preventDefault(); // Prevent showing payment request modal.
607					if ( addToCartButton.is( '.wc-variation-is-unavailable' ) ) {
608						window.alert( wc_add_to_cart_variation_params.i18n_unavailable_text );
609					} else if ( addToCartButton.is( '.wc-variation-selection-needed' ) ) {
610						window.alert( wc_add_to_cart_variation_params.i18n_make_a_selection_text );
611					}
612					return;
613				}
614
615				if ( 0 < paymentRequestError.length ) {
616					evt.preventDefault();
617					window.alert( paymentRequestError );
618					return;
619				}
620
621				wc_stripe_payment_request.addToCart();
622
623				if ( wc_stripe_payment_request.isCustomPaymentRequestButton( prButton ) || wc_stripe_payment_request.isBrandedPaymentRequestButton( prButton ) ) {
624					evt.preventDefault();
625					paymentRequest.show();
626				}
627			});
628
629			$( document.body ).on( 'wc_stripe_unblock_payment_request_button wc_stripe_enable_payment_request_button', function () {
630				wc_stripe_payment_request.unblockPaymentRequestButton();
631			} );
632
633			$( document.body ).on( 'wc_stripe_block_payment_request_button', function () {
634				wc_stripe_payment_request.blockPaymentRequestButton( 'wc_request_button_is_blocked' );
635			} );
636
637			$( document.body ).on( 'wc_stripe_disable_payment_request_button', function () {
638				wc_stripe_payment_request.blockPaymentRequestButton( 'wc_request_button_is_disabled' );
639			} );
640
641			$( document.body ).on( 'woocommerce_variation_has_changed', function () {
642				$( document.body ).trigger( 'wc_stripe_block_payment_request_button' );
643
644				$.when( wc_stripe_payment_request.getSelectedProductData() ).then( function ( response ) {
645					$.when(
646						paymentRequest.update( {
647							total: response.total,
648							displayItems: response.displayItems,
649						} )
650					).then( function () {
651						$( document.body ).trigger( 'wc_stripe_unblock_payment_request_button' );
652					} );
653				});
654			} );
655
656			// Block the payment request button as soon as an "input" event is fired, to avoid sync issues
657			// when the customer clicks on the button before the debounced event is processed.
658			$( '.quantity' ).on( 'input', '.qty', function() {
659				$( document.body ).trigger( 'wc_stripe_block_payment_request_button' );
660			} );
661
662			$( '.quantity' ).on( 'input', '.qty', wc_stripe_payment_request.debounce( 250, function() {
663				$( document.body ).trigger( 'wc_stripe_block_payment_request_button' );
664				paymentRequestError = [];
665
666				$.when( wc_stripe_payment_request.getSelectedProductData() ).then( function ( response ) {
667					if ( response.error ) {
668						paymentRequestError = [ response.error ];
669						$( document.body ).trigger( 'wc_stripe_unblock_payment_request_button' );
670					} else {
671						$.when(
672							paymentRequest.update( {
673								total: response.total,
674								displayItems: response.displayItems,
675							} )
676						).then( function () {
677							$( document.body ).trigger( 'wc_stripe_unblock_payment_request_button' );
678						});
679					}
680				} );
681			}));
682
683			if ( $('.variations_form').length ) {
684				$( '.variations_form' ).on( 'found_variation.wc-variation-form', function ( evt, variation ) {
685					if ( variation.is_in_stock ) {
686						wc_stripe_payment_request.unhidePaymentRequestButton();
687					} else {
688						wc_stripe_payment_request.hidePaymentRequestButton();
689					}
690				} );
691			}
692		},
693
694		attachCartPageEventListeners: function ( prButton, paymentRequest ) {
695			prButton.on( 'click', function ( evt ) {
696				// If login is required for checkout, display redirect confirmation dialog.
697				if ( wc_stripe_payment_request_params.login_confirmation ) {
698					evt.preventDefault();
699					displayLoginConfirmation( paymentRequestType );
700					return;
701				}
702
703				if (
704					wc_stripe_payment_request.isCustomPaymentRequestButton(
705						prButton
706					) ||
707					wc_stripe_payment_request.isBrandedPaymentRequestButton(
708						prButton
709					)
710				) {
711					evt.preventDefault();
712					paymentRequest.show();
713				}
714			} );
715		},
716
717		showPaymentRequestButton: function( prButton ) {
718			if ( wc_stripe_payment_request.isCustomPaymentRequestButton( prButton ) ) {
719				prButton.addClass( 'is-active' );
720				$( '#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator' ).show();
721			} else if ( wc_stripe_payment_request.isBrandedPaymentRequestButton( prButton ) ) {
722				$( '#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator' ).show();
723				$( '#wc-stripe-payment-request-button' ).html( prButton );
724			} else if ( $( '#wc-stripe-payment-request-button' ).length ) {
725				$( '#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator' ).show();
726				prButton.mount( '#wc-stripe-payment-request-button' );
727			}
728		},
729
730		hidePaymentRequestButton: function () {
731			$( '#wc-stripe-payment-request-wrapper, #wc-stripe-payment-request-button-separator' ).hide();
732		},
733
734		unhidePaymentRequestButton: function () {
735			const stripe_wrapper = $( '#wc-stripe-payment-request-wrapper' );
736			const stripe_separator = $( '#wc-stripe-payment-request-button-separator' );
737			// If either element is hidden, ensure both show.
738			if ( stripe_wrapper.is(':hidden') || stripe_separator.is(':hidden') ) {
739				stripe_wrapper.show();
740				stripe_separator.show();
741			}
742		},
743
744		blockPaymentRequestButton: function( cssClassname ) {
745			// check if element isn't already blocked before calling block() to avoid blinking overlay issues
746			// blockUI.isBlocked is either undefined or 0 when element is not blocked
747			if ( $( '#wc-stripe-payment-request-button' ).data( 'blockUI.isBlocked' ) ) {
748				return;
749			}
750
751			$( '#wc-stripe-payment-request-button' )
752				.addClass( cssClassname )
753				.block( { message: null } );
754		},
755
756		unblockPaymentRequestButton: function() {
757			$( '#wc-stripe-payment-request-button' )
758				.removeClass( ['wc_request_button_is_blocked', 'wc_request_button_is_disabled'] )
759				.unblock();
760		},
761
762		/**
763		 * Initialize event handlers and UI state
764		 *
765		 * @since 4.0.0
766		 * @version 4.0.0
767		 */
768		init: function() {
769			if ( wc_stripe_payment_request_params.is_product_page ) {
770				wc_stripe_payment_request.startPaymentRequest( '' );
771			} else {
772				wc_stripe_payment_request.getCartDetails();
773			}
774
775		},
776	};
777
778	wc_stripe_payment_request.init();
779
780	// We need to refresh payment request data when total is updated.
781	$( document.body ).on( 'updated_cart_totals', function() {
782		wc_stripe_payment_request.init();
783	} );
784
785	// We need to refresh payment request data when total is updated.
786	$( document.body ).on( 'updated_checkout', function() {
787		wc_stripe_payment_request.init();
788	} );
789
790	function setBackgroundImageWithFallback( element, background, fallback ) {
791		element.css( 'background-image', 'url(' + background + ')' );
792		// Need to use an img element to avoid CORS issues
793		var testImg = document.createElement("img");
794		testImg.onerror = function () {
795			element.css( 'background-image', 'url(' + fallback + ')' );
796		}
797		testImg.src = background;
798	}
799
800	// TODO: Replace this by `client/blocks/payment-request/login-confirmation.js`
801	// when we start using webpack to build this file.
802	function displayLoginConfirmation( paymentRequestType ) {
803		if ( ! wc_stripe_payment_request_params.login_confirmation ) {
804			return;
805		}
806
807		var message = wc_stripe_payment_request_params.login_confirmation.message;
808
809		// Replace dialog text with specific payment request type "Apple Pay" or "Google Pay".
810		if ( 'payment_request_api' !== paymentRequestType ) {
811			message = message.replace(
812				/\*\*.*?\*\*/,
813				'apple_pay' === paymentRequestType ? 'Apple Pay' : 'Google Pay'
814			);
815		}
816
817		// Remove asterisks from string.
818		message = message.replace( /\*\*/g, '' );
819
820		if ( confirm( message ) ) {
821			// Redirect to my account page.
822			window.location.href = wc_stripe_payment_request_params.login_confirmation.redirect_url;
823		}
824	}
825} );

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.