1/* global wc_ppec_context */ 2;( function ( $, window, document ) { 3 'use strict'; 4 5 // Use global 'paypal' object or namespaced 'paypal_sdk' as PayPal API (depends on legacy/SDK mode). 6 var paypal = wc_ppec_context.use_checkout_js ? window.paypal : window.paypal_sdk; 7 8 // Show error notice at top of checkout form, or else within button container 9 var showError = function( errorMessage, selector ) { 10 var $container = $( '.woocommerce-notices-wrapper, form.checkout' ); 11 12 if ( ! $container || ! $container.length ) { 13 $( selector ).prepend( errorMessage ); 14 return; 15 } else { 16 $container = $container.first(); 17 } 18 19 // Adapted from https://github.com/woocommerce/woocommerce/blob/ea9aa8cd59c9fa735460abf0ebcb97fa18f80d03/assets/js/frontend/checkout.js#L514-L529 20 $( '.woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message' ).remove(); 21 $container.prepend( '<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">' + errorMessage + '</div>' ); 22 $container.find( '.input-text, select, input:checkbox' ).trigger( 'validate' ).trigger( 'blur' ); 23 24 var scrollElement = $( '.woocommerce-NoticeGroup-checkout' ); 25 if ( ! scrollElement.length ) { 26 scrollElement = $container; 27 } 28 29 if ( $.scroll_to_notices ) { 30 $.scroll_to_notices( scrollElement ); 31 } else { 32 // Compatibility with WC <3.3 33 $( 'html, body' ).animate( { 34 scrollTop: ( $container.offset().top - 100 ) 35 }, 1000 ); 36 } 37 38 $( document.body ).trigger( 'checkout_error' ); 39 } 40
41 // Map funding method settings to enumerated options provided by PayPal (checkout.js). 42 var getFundingMethods = function( methods ) { 43 if ( ! methods ) { 44 return undefined; 45 } 46 47 var paypal_funding_methods = []; 48 49 $.each( methods, function( index, method_name ) { 50 var method = paypal.FUNDING[ method_name.toUpperCase() ]; 51 if ( method ) { 52 paypal_funding_methods.push( method ); 53 } 54 } ); 55 56 return paypal_funding_methods; 57 } 58 59 var renderCreditMessaging = function( buttonSelector ) { 60 if ( 'undefined' === typeof wc_ppec_context.credit_messaging || ! wc_ppec_context.credit_messaging || 'undefined' === typeof paypal.Messages ) { 61 return; 62 } 63 64 if ( 'undefined' != typeof paypal.isFundingEligible && ! paypal.isFundingEligible( paypal.FUNDING.CREDIT ) && ! paypal.isFundingEligible( paypal.FUNDING.PAYLATER ) ) { 65 return; 66 } 67 68 if ( 0 === $( buttonSelector ).length ) { 69 return; 70 } 71 72 // Add an element for messaging. 73 var messagingWrapper = $( '<div id="woo-ppec-credit-messaging"></div>' ).prependTo( buttonSelector ).get( 0 ); 74 paypal.Messages( wc_ppec_context.credit_messaging ).render( messagingWrapper ); 75 } 76 77 var render = function( isMiniCart ) { 78 var prefix = isMiniCart ? 'mini_cart_' : ''; 79 var button_size = wc_ppec_context[ prefix + 'button_size' ]; 80 var button_layout = wc_ppec_context[ prefix + 'button_layout' ]; 81 var button_label = ( 'undefined' !== wc_ppec_context[ prefix + 'button_label' ] ) ? wc_ppec_context[ prefix + 'button_label' ] : wc_ppec_context['button_label']; 82 var allowed = wc_ppec_context[ prefix + 'allowed_methods' ]; 83 var disallowed = wc_ppec_context[ prefix + 'disallowed_methods' ]; 84 85 var selector = isMiniCart ? '#woo_pp_ec_button_mini_cart' : '#woo_pp_ec_button_' + wc_ppec_context.page; 86 var fromCheckout = 'checkout' === wc_ppec_context.page && ! isMiniCart; 87 const return_url = wc_ppec_context['return_url']; 88 const cancel_url = wc_ppec_context['cancel_url']; 89 90 // Don't render if selector doesn't exist or is already rendered in DOM. 91 if ( ! $( selector ).length || $( selector ).children().length ) { 92 return; 93 } 94 95 var button_args = { 96 env: wc_ppec_context.environment, 97 locale: wc_ppec_context.locale, 98 commit: fromCheckout, 99 100 funding: { 101 allowed: getFundingMethods( allowed ), 102 disallowed: getFundingMethods( disallowed ), 103 }, 104 105 style: { 106 color: wc_ppec_context.button_color, 107 shape: wc_ppec_context.button_shape, 108 label: button_label, 109 layout: button_layout, 110 size: button_size, 111 branding: true, 112 tagline: false, 113 }, 114 115 validate: function( actions ) { 116 // Only enable on variable product page if purchasable variation selected. 117 $( '#woo_pp_ec_button_product' ).off( '.legacy' ) 118 .on( 'enable', actions.enable ) 119 .on( 'disable', actions.disable ); 120 }, 121 122 payment: function() { 123 // Clear any errors from previous attempt. 124 $( '.woocommerce-error', selector ).remove(); 125 126 return new Promise( function( resolve, reject ) { 127 // First, generate cart if triggered from single product. 128 if ( 'product' === wc_ppec_context.page && ! isMiniCart ) { 129 window.wc_ppec_generate_cart( resolve ); 130 } else { 131 resolve(); 132 } 133 } ).then( function() { 134 // Make PayPal Checkout initialization request. 135 var data = $( selector ).closest( 'form' ) 136 .add( $( '<input type="hidden" name="nonce" /> ' ) 137 .attr( 'value', wc_ppec_context.start_checkout_nonce ) 138 ) 139 .add( $( '<input type="hidden" name="from_checkout" /> ' ) 140 .attr( 'value', fromCheckout ? 'yes' : 'no' ) 141 ) 142 .serialize(); 143 144 var request_callback = function( response ) { 145 if ( ! response.success ) { 146 // Error messages may be preformatted in which case response structure will differ 147 var messages = response.data ? response.data.messages : response.messages; 148 if ( 'string' === typeof messages ) { 149 showError( messages ); 150 } else { 151 var messageItems = messages.map( function( message ) { 152 return '<li>' + message + '</li>'; 153 } ).join( '' ); 154 showError( '<ul class="woocommerce-error" role="alert">
154' + messageItems + '</ul>', selector ); 155 } 156 return null; 157 } 158 return response.data.token; 159 }; 160 161 if ( ! wc_ppec_context.use_checkout_js ) { 162 return fetch( wc_ppec_context.start_checkout_url, { 163 method: 'post', 164 cache: 'no-cache', 165 credentials: 'same-origin', 166 headers: { 167 'Content-Type': 'application/x-www-form-urlencoded', 168 }, 169 body: data 170 } ).then( function ( response ) { 171 return response.json(); 172 } ).then( request_callback ); 173 } else { 174 return paypal.request( { 175 method: 'post', 176 url: wc_ppec_context.start_checkout_url, 177 body: data, 178 } ).then( request_callback ); 179 } 180 } ); 181 }, 182 183 onAuthorize: function( data, actions ) { 184 if ( fromCheckout ) { 185 // Pass data necessary for authorizing payment to back-end. 186 $( 'form.checkout' ) 187 .append( $( '<input type="hidden" name="paymentToken" /> ' ).attr( 'value', ! wc_ppec_context.use_checkout_js ? data.orderID : data.paymentToken ) ) 188 .append( $( '<input type="hidden" name="payerID" /> ' ).attr( 'value', data.payerID ) ) 189 .trigger( 'submit' ); 190 } else { 191 // Navigate to order confirmation URL specified in original request to PayPal from back-end. 192 if ( ! wc_ppec_context.use_checkout_js ) { 193 const query_args = '?woo-paypal-return=true&token=' + data.orderID + '&PayerID=' + data.payerID; 194 return actions.redirect( return_url + query_args ); 195 } 196 197 return actions.redirect(); 198 } 199 }, 200 201 onCancel: function( data, actions ) { 202 if ( cancel_url && 'orderID' in data ) { 203 const query_args = '?woo-paypal-cancel=true&token=' + data.orderID; 204 return actions.redirect( cancel_url + query_args ); 205 } 206 }, 207 208 onError: function() { 209 jQuery( selector ).empty(); 210 render(); 211 }, 212 }; 213 214 if ( ! wc_ppec_context.use_checkout_js ) { 215 if ( ! isMiniCart ) { 216 renderCreditMessaging( selector ); 217 } 218 219 // 'payment()' and 'onAuthorize()' callbacks from checkout.js are now 'createOrder()' and 'onApprove()'. 220 Object.defineProperty( button_args, 'createOrder', Object.getOwnPropertyDescriptor( button_args, 'payment' ) ); 221 Object.defineProperty( button_args, 'onApprove', Object.getOwnPropertyDescriptor( button_args, 'onAuthorize' ) ); 222 223 // 'style.size' is no longer supported in the JS SDK. See https://developer.paypal.com/docs/checkout/integration-features/customize-button/#size. 224 delete button_args['style']['size']; 225 226 // Add a class selector so the buttons can be styled via css. 227 $( selector ).addClass( 'wc_ppec_' + button_size + '_payment_buttons' ); 228 229 // Drop other args no longer needed in the JS SDK. 230 var args_to_remove = [ 'env', 'locale', 'commit', 'funding', 'payment', 'onAuthorize' ]; 231 args_to_remove.forEach( function( arg ) { 232 delete button_args[ arg ] 233 }); 234 235 var disabledFundingSources = getFundingMethods( disallowed ); 236 if ( 'undefined' === typeof( disabledFundingSources ) || ! disabledFundingSources || 0 === disabledFundingSources.length ) { 237 paypal.Buttons( button_args ).render( selector ); 238 } else { 239 // Render context specific buttons. 240 paypal.getFundingSources().forEach( function( fundingSource ) { 241 if ( -1 !== disabledFundingSources.indexOf( fundingSource ) ) { 242 return; 243 } 244 245 var buttonSettings = { 246 createOrder: button_args.createOrder, 247 onApprove: button_args.onApprove, 248 onError: button_args.onError, 249 onCancel: button_args.onCancel, 250 fundingSource: fundingSource, 251 style: ( paypal.FUNDING.PAYPAL === fundingSource ) ? button_args.style : { layout: button_args.style.layout, shape: button_args.style.shape } 252 }; 253 254 var button = paypal.Buttons( buttonSettings ); 255 256 if ( button.isEligible() ) { 257 button.render( selector ); 258 } 259 } ); 260 } 261 } else { 262 paypal.Button.render( button_args, selector ); 263 } 264 }; 265 266 // Render cart, single product, or checkout buttons. 267 if ( wc_ppec_context.page ) { 268 if ( 'checkout' !== wc_ppec_context.page ) { 269 render(); 270 } 271 272 $( document.body ).on( 'updated_cart_totals updated_checkout', render.bind( this, false ) ); 273 } 274 275 // Render buttons in mini-cart if present. 276 $( document.body ).on( 'wc_fragments_loaded wc_fragments_refreshed', function() { 277 var $button = $( '.widget_shopping_cart #woo_pp_ec_button_mini_cart' ); 278 if ( $button.length ) { 279 // Clear any existing button in container, and render. 280 $button.empty(); 281 render( true ); 282 } 283 } ); 284} )( jQuery, window, document );
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.