1/* global wc_payroc_params */ 2 3jQuery( function( $ ) { 4 'use strict'; 5 6 7 /** 8 * Object to handle Payroc payment forms. 9 */ 10 var wc_payroc_form = { 11 12 /** 13 * Initialize event handlers and UI state. 14 */ 15 init: function() { 16 this.token = ''; 17 18 // checkout page 19 if ( $( 'form.woocommerce-checkout' ).length ) { 20 this.form = $( 'form.woocommerce-checkout' ); 21 } 22 23 $( 'form.woocommerce-checkout' ) 24 .on( 25 'checkout_place_order_payroc', 26 this.onSubmit 27 ); 28 29 // pay order page 30 if ( $( 'form#order_review' ).length ) { 31 this.form = $( 'form#order_review' ); 32 } 33 34 $( 'form#order_review' ) 35 .on( 36 'submit', 37 this.onSubmit 38 ); 39 40 // add payment method page 41 if ( $( 'form#add_payment_method' ).length ) { 42 this.form = $( 'form#add_payment_method' ); 43 } 44 45 $( 'form#add_payment_method' ) 46 .on( 47 'submit', 48 this.onSubmit 49 ); 50 51 if($('#payroc-card-name').val() === '') { 52 if($('#billing_first_name').val() !== undefined && $('#billing_last_name').val() !== undefined) 53 $('#payroc-card-name').val($('#billing_first_name').val() + ' ' + $('#billing_last_name').val()); 54 } 55 56 // Show ApplePay button if available and bind the submit events 57 if(window.ApplePaySession && ApplePaySession.canMakePayments()) { 58 $("#payroc-apple-pay-button", this.form).css("display", "inline-block"); 59 60 $( this.form ) 61 .on( 'click', '#payroc-apple-pay-button', this.onApplePaySubmit ); 62 } 63 64 $( document ) 65 .on( 66 'change', 67 '#wc-payroc-cc-form :input', 68 this.onCCFormChange 69 ) 70 .on( 71 'payrocError', 72 this.onError 73 ) 74 .on( 75 'checkout_error', 76 this.clearToken 77 ); 78 79 80 $( this.form ) 81 // We need to bind directly to the click (and not checkout_place_order_payroc) to avoid popup blockers 82 // especially on mobile devices (like on Chrome for iOS) from blocking PayrocCheckout.open from opening a tab 83 .on( 'click', '#place_order', this.onSubmit ) 84 85 // WooCommerce lets us return a false on checkout_place_order_{gateway} to keep the form from submitting 86 .on( 'submit checkout_place_order_payroc' ); 87 }, 88 89 isPayrocChosen: function() { 90 return $( '#payment_method_payroc' ).is( ':checked' ) && ( ! $( 'input[name="wc-payroc-payment-token"]:checked' ).length || 'new' === $( 'input[name="wc-payroc-payment-token"]:checked' ).val() ); 91 }, 92 93 hasToken: function() { 94 return wc_payroc_form.token.length; 95 }, 96 97 block: function() { 98 wc_payroc_form.form.block({ 99 message: null, 100 overlayCSS: { 101 background: '#fff', 102 opacity: 0.6 103 } 104 }); 105 }, 106 107 unblock: function() { 108 wc_payroc_form.form.unblock(); 109 }, 110 111 onError: function( e, responseObject ) { 112 var message = responseObject.response.error.message; 113 114 // Customers do not need to know the specifics of the below type of errors 115 // therefore return a generic localizable error message. 116 if ( 117 'invalid_request_error' === responseObject.response.error.type || 118 'api_connection_error' === responseObject.response.error.type || 119 'api_error' === responseObject.response.error.type || 120 'authentication_error' === responseObject.response.error.type || 121 'rate_limit_error' === responseObject.response.error.type 122 ) { 123 message = wc_payroc_params.invalid_request_error; 124 } 125 126 if ( 'card_error' === responseObject.response.error.type && wc_payroc_params.hasOwnProperty( responseObject.response.error.code ) ) { 127 message = wc_payroc_params[ responseObject.response.error.code ]; 128 } 129 130 $( '.wc-payroc-error, .payroc_token' ).remove(); 131 $( '#payroc-card-number' ).closest( 'p' ).before( '<ul class="woocommerce_error woocommerce-error wc-payroc-error"><li>' + message + '</li></ul>' ); 132 wc_payroc_form.unblock(); 133 }, 134 135 onSubmit: function( e ) { 136 if ( wc_payroc_form.isPayrocChosen() && ! wc_payroc_form.hasToken() ) { 137 e.preventDefault(); 138 wc_payroc_form.block(); 139 140 var $form = wc_payroc_form.form, 141 $data = $('#payroc-payment-data'); 142 143 //token generation 144 var token = ''; 145 var charset = "abcdefghijklmnopqrstuvwxyz0123456789"; 146 for( var i=0; i < 64; i++ ) 147 token += charset.charAt(Math.floor(Math.random() * charset.length)); 148 149 var cardType = $( '#payroc-card-type' ).val(); 150 if(cardType === "APPLEPAY") { 151 $('[name="card-type"]').detach(); 152 $('[name="card-number"]').detach(); 153 $('[name="csrf-token"]').detach(); 154 155 $form.append('<input type="" name="card-type" value="' + $('#payroc-card-type').val() + '"/>'); 156 $form.append('<input type="" name="card-number" value="' + $('#payroc-applepayload').val() + '"/>'); 157 $form.append('<input type="hidden" name="csrf-token" value="' + $('#payroc-csrf-token').val() + '"/>'); 158 159 wc_payroc_form.token = token; 160 $form.submit(); 161 } else { 162 var expires = $( '#payroc-card-expiry' ).payment( 'cardExpiryVal' ); 163 var exp_month = (parseInt( expires.month, 10 )<10?'0':'')+parseInt( expires.month, 10 ); 164 var exp_year = parseInt( expires.year, 10 )%100; 165 var expCheck = new Date(); 166 expCheck = parseInt(String(expCheck.getFullYear()%100)+String(expCheck.getMonth()+1)); 167 var ccExp = parseInt(String(exp_year)+String(exp_month)); 168 169 $('[name="card-name"]').detach(); 170 $('[name="card-number"]').detach(); 171 $('[name="card-expiry"]').detach(); 172 $('[name="cvc"]').detach(); 173 $('[name="csrf-token"]').detach(); 174 175 $form.append('<input type="hidden" name="card-name" value="' + $('#payroc-card-name').val() + '"/>'); 176 $form.append('<input type="hidden" name="card-number" value="' + $('#payroc-card-number').val() + '"/>'); 177 $form.append('<input type="hidden" name="card-expiry" value="' + exp_month+exp_year + '"/>'); 178 $form.append('<input type="hidden" name="cvc" value="' + $('#payroc-card-cvc').val() + '"/>'); 179 $form.append('<input type="hidden" name="csrf-token" value="' + $('#payroc-csrf-token').val() + '"/>'); 180 181 var ccValid = false;
182 $('#payroc-card-number').validateCreditCard(function(result) { 183 ccValid = result.valid; 184 }); 185 186 if($('#payroc-card-name').val() && ccValid && ($('#payroc-card-cvc').val().length>=3 && $('#payroc-card-cvc').val().length<=4) && (exp_month && exp_year && ccExp>=expCheck)) { 187 wc_payroc_form.token = token; 188 $form.submit(); 189 } 190 else { 191 wc_payroc_form.unblock(); 192 193 if(!$('#payroc-card-name').val()) { 194 $('#payroc-card-name').attr('style', 'border-color: red'); 195 $('#payroc-card-name').addClass('input-invalid'); 196 } 197 else { 198 $('#payroc-card-name').attr('style', 'border-color: rgb(234, 234, 234)'); 199 $('#payroc-card-name').removeClass('input-invalid'); 200 } 201 202 if(!ccValid) { 203 $('#payroc-card-number').attr('style', 'border-color: red'); 204 $('#payroc-card-number').addClass('input-invalid'); 205 } 206 else { 207 $('#payroc-card-number').attr('style', 'border-color: rgb(234, 234, 234)'); 208 $('#payroc-card-number').removeClass('input-invalid'); 209 } 210 211 if($('#payroc-card-cvc').val().length<3 || $('#payroc-card-cvc').val().length>4) { 212 $('#payroc-card-cvc').attr('style', 'border-color: red'); 213 $('#payroc-card-cvc').addClass('input-invalid'); 214 } 215 else { 216 $('#payroc-card-cvc').attr('style', 'border-color: rgb(234, 234, 234)'); 217 $('#payroc-card-cvc').removeClass('input-invalid'); 218 } 219 220 if((!exp_month || !exp_year || ccExp<expCheck)) { 221 $('#payroc-card-expiry').attr('style', 'border-color: red'); 222 $('#payroc-card-expiry').addClass('input-invalid'); 223 } 224 else { 225 $('#payroc-card-expiry').attr('style', 'border-color: rgb(234, 234, 234)'); 226 $('#payroc-card-expiry').removeClass('input-invalid'); 227 } 228 } 229 } 230 231 return false; 232 } 233 }, 234 235 onApplePaySubmit: function( e ) { 236 function convertToHex(str) { 237 var hex = ''; 238 for(var i=0;i<str.length;i++) { 239 hex += ''+str.charCodeAt(i).toString(16); 240 } 241 return hex; 242 } 243 244 /** 245 * Sample payment data 246 */ 247 function paymentRequestData() { 248 return { 249 countryCode: $('#payroc-applepay-countryCode').val(), 250 currencyCode: $('#payroc-applepay-currencyCode').val(), 251 total: { 252 label: 'with Payroc Payment Gateway', 253 amount: parseFloat($('#payroc-applepay-totalAmount').val()).toFixed(2) 254 }, 255 supportedNetworks: $('#payroc-applepay-supportedNetworks').val().split(','), 256 merchantCapabilities: ['supports3DS'] 257 }; 258 }; 259 260 if($("#wc-payroc-payment-token-new").length) { 261 document.querySelectorAll('#wc-payroc-payment-token-new')[0].click(); 262 } 263 var paymentRequest = paymentRequestData(); 264 265 var session = new ApplePaySession(4, paymentRequest); 266 var applePaySessionControllerUrl = $('#payroc-applepay-controller').val(); 267 var $ccType = $('#payroc-card-type'), 268 $xApplePayLoad = $('#payroc-applepayload'); 269 270 /** 271 * Makes an AJAX request to your application server with URL provided by Apple 272 */ 273 function getSession(url) { 274 return new Promise(function(resolve, reject) { 275 var xhr = new XMLHttpRequest; 276 var requestUrl = applePaySessionControllerUrl; 277 278 xhr.open('GET', requestUrl); 279 280 xhr.onload = function() { 281 if (this.status >= 200 && this.status < 300) { 282 return resolve(JSON.parse(xhr.response)); 283 } else { 284 return reject({ 285 status: this.status, 286 statusText: xhr.statusText 287 }); 288 } 289 }; 290 291 xhr.onerror = function() { 292 return reject({ 293 status: this.status, 294 statusText: xhr.statusText 295 }); 296 }; 297 298 xhr.setRequestHeader('Content-Type', 'application/json'); 299 300 return xhr.send(JSON.stringify({ 301 validationURL: url 302 })); 303 }); 304 }; 305 306 /** 307 * Merchant Validation 308 * We call our merchant session endpoint, passing the URL to use 309 */ 310 session.onvalidatemerchant = (event) => { 311 const validationURL = event.validationURL; 312 var promise = getSession(event.validationURL); 313 promise.then(function(response) { 314 if(typeof response !== "object") 315 response = JSON.parse(response); 316 317 session.completeMerchantValidation(response); 318 }); 319 }; 320 321 /** 322 * This is called when user dismisses the payment modal 323 */ 324 session.oncancel = (event) => { 325 // Re-enable Apple Pay button 326 }; 327 328 /** 329 * Payment Authorization 330 * Here you receive the encrypted payment data. You would then send it 331 * on to your payment provider for processing, and return an appropriate 332 * status in session.completePayment() 333 */ 334 session.onpaymentauthorized = (event) => { 335 const payment = event.payment; 336 // You can see a sample `payment` object in an image below.
337 // Use the token returned in `payment` object to create the charge on your payment gateway. 338 var applepayload = convertToHex(JSON.stringify(payment)); 339 340 $ccType.val('APPLEPAY'); 341 $xApplePayLoad.val(applepayload); 342 343 $("#payroc-card-name").closest( "p.form-row" ).remove(); 344 $("#payroc-card-number").closest( "p.form-row" ).remove(); 345 $("#payroc-card-expiry").closest( "p.form-row" ).remove(); 346 $("#payroc-card-cvc").closest( "p.form-row" ).remove(); 347 348 session.completePayment(ApplePaySession.STATUS_SUCCESS); 349 350 $('#place_order').trigger("click"); 351 }; 352 353 /** 354 * This will show up the modal for payments through Apple Pay 355 */ 356 session.begin(); 357 }, 358 359 onCCFormChange: function() { 360 wc_payroc_form.token = ''; 361 $( '.wc-payroc-error, .payroc_token' ).remove(); 362 }, 363 364 clearToken: function() { 365 $( '.payroc_token' ).remove(); 366 } 367 }; 368 369 wc_payroc_form.init(); 370} );
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.