Completed
Push — master ( 272f75...c928b7 )
by Roy
02:12
created

assets/js/stripe.js   F

Complexity

Total Complexity 172
Complexity/F 3.91

Size

Lines of Code 840
Function Count 44

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 0
nc 0
dl 0
loc 840
rs 2.1818
c 1
b 0
f 0
wmc 172
mnd 4
bc 139
fnc 44
bpm 3.1589
cpm 3.909
noi 19

How to fix   Complexity   

Complexity

Complex classes like assets/js/stripe.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/* global wc_stripe_params */
2
3
jQuery( function( $ ) {
4
	'use strict';
5
6
	var stripe = Stripe( wc_stripe_params.key );
7
8
	if ( 'yes' === wc_stripe_params.use_elements ) {
9
		var elements = stripe.elements(),
10
			stripe_card,
11
			stripe_exp,
12
			stripe_cvc;
13
	}
14
15
	/**
16
	 * Object to handle Stripe elements payment form.
17
	 */
18
	var wc_stripe_form = {
19
		/**
20
		 * Get WC AJAX endpoint URL.
21
		 *
22
		 * @param  {String} endpoint Endpoint.
23
		 * @return {String}
24
		 */
25
		getAjaxURL: function( endpoint ) {
26
			return wc_stripe_params.ajaxurl
27
				.toString()
28
				.replace( '%%endpoint%%', 'wc_stripe_' + endpoint );
29
		},
30
31
		/**
32
		 * Initialize event handlers and UI state.
33
		 */
34
		init: function() {
35
			// Initialize tokenization script if on change payment method page and pay for order page.
36
			if ( 'yes' === wc_stripe_params.is_change_payment_page ) {
37
				$( document.body ).trigger( 'wc-credit-card-form-init' );
38
			}
39
40
			// Stripe Checkout.
41
			this.stripe_checkout_submit = false;
42
43
			// checkout page
44
			if ( $( 'form.woocommerce-checkout' ).length ) {
45
				this.form = $( 'form.woocommerce-checkout' );
46
			}
47
48
			$( 'form.woocommerce-checkout' )
49
				.on(
50
					'checkout_place_order_stripe checkout_place_order_stripe_bancontact checkout_place_order_stripe_sofort checkout_place_order_stripe_giropay checkout_place_order_stripe_ideal checkout_place_order_stripe_alipay checkout_place_order_stripe_sepa checkout_place_order_stripe_bitcoin',
51
					this.onSubmit
52
				);
53
54
			// pay order page
55
			if ( $( 'form#order_review' ).length ) {
56
				this.form = $( 'form#order_review' );
57
			}
58
59
			$( 'form#order_review' )
60
				.on(
61
					'submit',
62
					this.onSubmit
63
				);
64
65
			// add payment method page
66
			if ( $( 'form#add_payment_method' ).length ) {
67
				this.form = $( 'form#add_payment_method' );
68
			}
69
70
			$( 'form#add_payment_method' )
71
				.on(
72
					'submit',
73
					this.onSubmit
74
				);
75
76
			$( 'form.woocommerce-checkout' )
77
				.on(
78
					'change',
79
					'#stripe-bank-country',
80
					this.reset
81
				);
82
83
			$( document )
84
				.on(
85
					'stripeError',
86
					this.onError
87
				)
88
				.on(
89
					'checkout_error',
90
					this.reset
91
				);
92
93
			var elementStyles = {
94
				base: {
95
					iconColor: '#666EE8',
96
					color: '#31325F',
97
					fontSize: '15px',
98
					'::placeholder': {
99
				  		color: '#CFD7E0',
100
					}
101
				}
102
			};
103
104
			var elementClasses = {
105
				focus: 'focused',
106
				empty: 'empty',
107
				invalid: 'invalid',
108
			};
109
110
			if ( 'yes' === wc_stripe_params.use_elements && $( '#stripe-card-element' ).length ) {
111
				elementStyles  = wc_stripe_params.elements_styling ? wc_stripe_params.elements_styling : elementStyles;
112
				elementClasses = wc_stripe_params.elements_classes ? wc_stripe_params.elements_classes : elementClasses;
113
114
				if ( 'yes' === wc_stripe_params.inline_cc_form ) {
115
					stripe_card = elements.create( 'card', { style: elementStyles, hidePostalCode: true } );
0 ignored issues
show
Bug introduced by
The variable elements does not seem to be initialized in case "yes" === wc_stripe_params.use_elements on line 8 is false. Are you sure this can never be the case?
Loading history...
116
117
					stripe_card.addEventListener( 'change', function( event ) {
118
						wc_stripe_form.onCCFormChange();
119
120
						if ( event.error ) {
121
							$( document.body ).trigger( 'stripeError', event );
122
						}
123
					} );
124
				} else {
125
					stripe_card = elements.create( 'cardNumber', { style: elementStyles, classes: elementClasses } );
0 ignored issues
show
Bug introduced by
The variable elements does not seem to be initialized in case "yes" === wc_stripe_params.use_elements on line 8 is false. Are you sure this can never be the case?
Loading history...
126
					stripe_exp  = elements.create( 'cardExpiry', { style: elementStyles, classes: elementClasses } );
127
					stripe_cvc  = elements.create( 'cardCvc', { style: elementStyles, classes: elementClasses } );
128
129
					stripe_card.addEventListener( 'change', function( event ) {
130
						wc_stripe_form.onCCFormChange();
131
132
						if ( event.error ) {
133
							$( document.body ).trigger( 'stripeError', event );
134
						}
135
					} );
136
137
					stripe_exp.addEventListener( 'change', function( event ) {
138
						wc_stripe_form.onCCFormChange();
139
140
						if ( event.error ) {
141
							$( document.body ).trigger( 'stripeError', event );
142
						}
143
					} );
144
145
					stripe_cvc.addEventListener( 'change', function( event ) {
146
						wc_stripe_form.onCCFormChange();
147
148
						if ( event.error ) {
149
							$( document.body ).trigger( 'stripeError', event );
150
						}
151
					} );
152
				}
153
154
				/**
155
				 * Only in checkout page we need to delay the mounting of the
156
				 * card as some AJAX process needs to happen before we do.
157
				 */
158
				if ( wc_stripe_params.is_checkout ) {
159
					$( document.body ).on( 'updated_checkout', function() {
160
						// Don't mount elements a second time.
161
						if ( stripe_card ) {
162
							if ( 'yes' === wc_stripe_params.inline_cc_form ) {
163
								stripe_card.unmount( '#stripe-card-element' );
164
							} else {
165
								stripe_card.unmount( '#stripe-card-element' );
166
								stripe_exp.unmount( '#stripe-exp-element' );
0 ignored issues
show
Bug introduced by
The variable stripe_exp seems to not be initialized for all possible execution paths.
Loading history...
167
								stripe_cvc.unmount( '#stripe-cvc-element' );
0 ignored issues
show
Bug introduced by
The variable stripe_cvc seems to not be initialized for all possible execution paths.
Loading history...
168
							}
169
						}
170
171
						if ( 'yes' === wc_stripe_params.inline_cc_form ) {
172
							stripe_card.mount( '#stripe-card-element' );
173
						} else {
174
							stripe_card.mount( '#stripe-card-element' );
175
							stripe_exp.mount( '#stripe-exp-element' );
176
							stripe_cvc.mount( '#stripe-cvc-element' );
177
						}
178
					});
179
				} else if ( $( 'form#add_payment_method' ).length || $( 'form#order_review' ).length ) {
180
					if ( 'yes' === wc_stripe_params.inline_cc_form ) {
181
						stripe_card.mount( '#stripe-card-element' );
182
					} else {
183
						stripe_card.mount( '#stripe-card-element' );
184
						stripe_exp.mount( '#stripe-exp-element' );
185
						stripe_cvc.mount( '#stripe-cvc-element' );
186
					}
187
				}
188
			}
189
		},
190
191
		// Check to see if Stripe in general is being used for checkout.
192
		isStripeChosen: function() {
193
			return $( '#payment_method_stripe, #payment_method_stripe_bancontact, #payment_method_stripe_sofort, #payment_method_stripe_giropay, #payment_method_stripe_ideal, #payment_method_stripe_alipay, #payment_method_stripe_sepa, #payment_method_stripe_bitcoin' ).is( ':checked' ) || ( $( '#payment_method_stripe' ).is( ':checked' ) && 'new' === $( 'input[name="wc-stripe-payment-token"]:checked' ).val() ) || ( $( '#payment_method_stripe_sepa' ).is( ':checked' ) && 'new' === $( 'input[name="wc-stripe-payment-token"]:checked' ).val() );
194
		},
195
196
		// Currently only support saved cards via credit cards and SEPA. No other payment method.
197
		isStripeSaveCardChosen: function() {
198
			return ( $( '#payment_method_stripe' ).is( ':checked' ) && ( $( 'input[name="wc-stripe-payment-token"]' ).is( ':checked' ) && 'new' !== $( 'input[name="wc-stripe-payment-token"]:checked' ).val() ) ) ||
199
				( $( '#payment_method_stripe_sepa' ).is( ':checked' ) && ( $( 'input[name="wc-stripe_sepa-payment-token"]' ).is( ':checked' ) && 'new' !== $( 'input[name="wc-stripe_sepa-payment-token"]:checked' ).val() ) );
200
		},
201
202
		// Stripe credit card used.
203
		isStripeCardChosen: function() {
204
			return $( '#payment_method_stripe' ).is( ':checked' );
205
		},
206
207
		isBancontactChosen: function() {
208
			return $( '#payment_method_stripe_bancontact' ).is( ':checked' );
209
		},
210
211
		isGiropayChosen: function() {
212
			return $( '#payment_method_stripe_giropay' ).is( ':checked' );
213
		},
214
215
		isIdealChosen: function() {
216
			return $( '#payment_method_stripe_ideal' ).is( ':checked' );
217
		},
218
219
		isSofortChosen: function() {
220
			return $( '#payment_method_stripe_sofort' ).is( ':checked' );
221
		},
222
223
		isAlipayChosen: function() {
224
			return $( '#payment_method_stripe_alipay' ).is( ':checked' );
225
		},
226
227
		isSepaChosen: function() {
228
			return $( '#payment_method_stripe_sepa' ).is( ':checked' );
229
		},
230
231
		isBitcoinChosen: function() {
232
			return $( '#payment_method_stripe_bitcoin' ).is( ':checked' );
233
		},
234
235
		isP24Chosen: function() {
236
			return $( '#payment_method_stripe_p24' ).is( ':checked' );
237
		},
238
239
		hasSource: function() {
240
			return 0 < $( 'input.stripe-source' ).length;
241
		},
242
243
		// Legacy
244
		hasToken: function() {
245
			return 0 < $( 'input.stripe_token' ).length;
246
		},
247
248
		isMobile: function() {
249
			if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
0 ignored issues
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
250
				return true;
251
			}
252
253
			return false;
254
		},
255
256
		isStripeModalNeeded: function( e ) {
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
257
			var token = wc_stripe_form.form.find( 'input.stripe_token' ),
258
				$required_inputs;
0 ignored issues
show
Unused Code introduced by
The variable $required_inputs seems to be never used. Consider removing it.
Loading history...
259
260
			// If this is a stripe submission (after modal) and token exists, allow submit.
261
			if ( wc_stripe_form.stripe_submit && token ) {
262
				return false;
263
			}
264
265
			// Don't affect submission if modal is not needed.
266
			if ( ! wc_stripe_form.isStripeChosen() ) {
267
				return false;
268
			}
269
270
			return true;
271
		},
272
273
		block: function() {
274
			if ( wc_stripe_form.isMobile() ) {
275
				$.blockUI({
276
					message: null,
277
					overlayCSS: {
278
						background: '#fff',
279
						opacity: 0.6
280
					}
281
				});
282
			} else {
283
				wc_stripe_form.form.block({
284
					message: null,
285
					overlayCSS: {
286
						background: '#fff',
287
						opacity: 0.6
288
					}
289
				});
290
			}
291
		},
292
293
		unblock: function() {
294
			if ( wc_stripe_form.isMobile() ) {
295
				$.unblockUI();
296
			} else {
297
				wc_stripe_form.form.unblock();
298
			}
299
		},
300
301
		getSelectedPaymentElement: function() {
302
			return $( '.payment_methods input[name="payment_method"]:checked' );
303
		},
304
305
		// Stripe Checkout.
306
		openModal: function() {
307
			// Capture submittal and open stripecheckout
308
			var $form = wc_stripe_form.form,
309
				$data = $( '#stripe-payment-data' );
310
311
			wc_stripe_form.reset();
312
313
			var token_action = function( res ) {
314
				$form.find( 'input.stripe_source' ).remove();
315
316
				/* Since source was introduced in 4.0. We need to
317
				 * convert the token into a source.
318
				 */
319
				if ( 'token' === res.object ) {
320
					stripe.createSource( {
321
						type: 'card',
322
						token: res.id,
323
					} ).then( wc_stripe_form.sourceResponse );
324
				} else if ( 'source' === res.object ) {
325
					var response = { source: res };
326
					wc_stripe_form.sourceResponse( response );
327
				}
328
			};
329
330
			StripeCheckout.open({
0 ignored issues
show
Bug introduced by
The variable StripeCheckout seems to be never declared. If this is a global, consider adding a /** global: StripeCheckout */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
331
				key               : wc_stripe_params.key,
332
				billingAddress    : 'yes' === wc_stripe_params.stripe_checkout_require_billing_address,
333
				amount            : $data.data( 'amount' ),
334
				name              : $data.data( 'name' ),
335
				description       : $data.data( 'description' ),
336
				currency          : $data.data( 'currency' ),
337
				image             : $data.data( 'image' ),
338
				bitcoin           : $data.data( 'bitcoin' ),
339
				locale            : $data.data( 'locale' ),
340
				email             : $( '#billing_email' ).val() || $data.data( 'email' ),
341
				panelLabel        : $data.data( 'panel-label' ),
342
				allowRememberMe   : $data.data( 'allow-remember-me' ),
343
				token             : token_action,
344
				closed            : wc_stripe_form.onClose()
345
			});
346
		},
347
348
		// Stripe Checkout.
349
		resetModal: function() {
350
			wc_stripe_form.reset();
351
			wc_stripe_form.stripe_checkout_submit = false;
352
		},
353
354
		// Stripe Checkout.
355
		onClose: function() {
356
			wc_stripe_form.unblock();
357
		},
358
359
		onError: function( e, result ) {
360
			var message = result.error.message,
361
				errorContainer = wc_stripe_form.getSelectedPaymentElement().parents( 'li' ).eq(0).find( '.stripe-source-errors' );
362
363
			/*
364
			 * Customers do not need to know the specifics of the below type of errors
365
			 * therefore return a generic localizable error message.
366
			 */
367
			if (
368
				'invalid_request_error' === result.error.type ||
369
				'api_connection_error'  === result.error.type ||
370
				'api_error'             === result.error.type ||
371
				'authentication_error'  === result.error.type ||
372
				'rate_limit_error'      === result.error.type
373
			) {
374
				message = wc_stripe_params.invalid_request_error;
375
			}
376
377
			if ( 'card_error' === result.error.type && wc_stripe_params.hasOwnProperty( result.error.code ) ) {
378
				message = wc_stripe_params[ result.error.code ];
379
			}
380
381
			if ( 'validation_error' === result.error.type && wc_stripe_params.hasOwnProperty( result.error.code ) ) {
382
				message = wc_stripe_params[ result.error.code ];
383
			}
384
385
			wc_stripe_form.reset();
386
			$( '.woocommerce-NoticeGroup-checkout' ).remove();
387
			console.log( result.error.message ); // Leave for troubleshooting.
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
388
			$( errorContainer ).html( '<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li>' + message + '</li></ul>' );
389
390
			if ( $( '.wc-stripe-error' ).length ) {
391
				$( 'html, body' ).animate({
392
					scrollTop: ( $( '.wc-stripe-error' ).offset().top - 200 )
393
				}, 200 );
394
			}
395
			wc_stripe_form.unblock();
396
		},
397
398
		getOwnerDetails: function() {
399
			var first_name = $( '#billing_first_name' ).length ? $( '#billing_first_name' ).val() : wc_stripe_params.billing_first_name,
400
				last_name  = $( '#billing_last_name' ).length ? $( '#billing_last_name' ).val() : wc_stripe_params.billing_last_name,
401
				extra_details = { owner: { name: '', address: {}, email: '', phone: '' } };
402
403
			extra_details.owner.name = first_name;
404
405
			if ( first_name && last_name ) {
406
				extra_details.owner.name = first_name + ' ' + last_name;
407
			}
408
409
			extra_details.owner.email = $( '#billing_email' ).val();
410
			extra_details.owner.phone = $( '#billing_phone' ).val();
411
412
			/* Stripe does not like empty string values so
413
			 * we need to remove the parameter if we're not
414
			 * passing any value.
415
			 */
416
			if ( typeof extra_details.owner.phone !== 'undefined' && 0 >= extra_details.owner.phone.length ) {
417
				delete extra_details.owner.phone;
418
			}
419
420
			if ( typeof extra_details.owner.email !== 'undefined' && 0 >= extra_details.owner.email.length ) {
421
				delete extra_details.owner.email;
422
			}
423
424
			if ( $( '#billing_address_1' ).length > 0 ) {
425
				extra_details.owner.address.line1       = $( '#billing_address_1' ).val();
426
				extra_details.owner.address.line2       = $( '#billing_address_2' ).val();
427
				extra_details.owner.address.state       = $( '#billing_state' ).val();
428
				extra_details.owner.address.city        = $( '#billing_city' ).val();
429
				extra_details.owner.address.postal_code = $( '#billing_postcode' ).val();
430
				extra_details.owner.address.country     = $( '#billing_country' ).val();
431
			} else if ( wc_stripe_params.billing_address_1 ) {
432
				extra_details.owner.address.line1       = wc_stripe_params.billing_address_1;
433
				extra_details.owner.address.line2       = wc_stripe_params.billing_address_2;
434
				extra_details.owner.address.state       = wc_stripe_params.billing_state;
435
				extra_details.owner.address.city        = wc_stripe_params.billing_city;
436
				extra_details.owner.address.postal_code = wc_stripe_params.billing_postcode;
437
				extra_details.owner.address.country     = wc_stripe_params.billing_country;
438
			}
439
440
			return extra_details;
441
		},
442
443
		createSource: function() {
444
			var extra_details = wc_stripe_form.getOwnerDetails(),
445
				source_type   = 'card';
446
447
			if ( wc_stripe_form.isBancontactChosen() ) {
448
				source_type = 'bancontact';
449
			}
450
451
			if ( wc_stripe_form.isSepaChosen() ) {
452
				source_type = 'sepa_debit';
453
			}
454
455
			if ( wc_stripe_form.isIdealChosen() ) {
456
				source_type = 'ideal';
457
			}
458
459
			if ( wc_stripe_form.isSofortChosen() ) {
460
				source_type = 'sofort';
461
			}
462
463
			if ( wc_stripe_form.isBitcoinChosen() ) {
464
				source_type = 'bitcoin';
465
			}
466
467
			if ( wc_stripe_form.isGiropayChosen() ) {
468
				source_type = 'giropay';
469
			}
470
471
			if ( wc_stripe_form.isAlipayChosen() ) {
472
				source_type = 'alipay';
473
			}
474
475
			if ( 'card' === source_type ) {
476
				stripe.createSource( stripe_card, extra_details ).then( wc_stripe_form.sourceResponse );
477
			} else {
478
				switch ( source_type ) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
479
					case 'bancontact':
480
					case 'giropay':
481
					case 'ideal':
482
					case 'sofort':
483
					case 'alipay':
484
						// These redirect flow payment methods need this information to be set at source creation.
485
						extra_details.amount   = $( '#stripe-' + source_type + '-payment-data' ).data( 'amount' );
486
						extra_details.currency = $( '#stripe-' + source_type + '-payment-data' ).data( 'currency' );
487
						extra_details.redirect = { return_url: wc_stripe_params.return_url };
488
489
						if ( wc_stripe_params.statement_descriptor ) {
490
							extra_details.statement_descriptor = wc_stripe_params.statement_descriptor;
491
						}
492
493
						break;
494
				}
495
496
				// Handle special inputs that are unique to a payment method.
497
				switch ( source_type ) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
498
					case 'sepa_debit':
499
						var owner = $( '#stripe-payment-data' );
500
						extra_details.currency    = $( '#stripe-' + source_type + '-payment-data' ).data( 'currency' );
501
						extra_details.owner.name  = $( '#stripe-sepa-owner' ).val();
502
						extra_details.owner.email = owner.data( 'email' );
503
						extra_details.sepa_debit  = { iban: $( '#stripe-sepa-iban' ).val() };
504
						extra_details.mandate     = { notification_method: wc_stripe_params.sepa_mandate_notification };
505
						break;
506
					case 'ideal':
507
						extra_details.ideal = { bank: $( '#stripe-ideal-bank' ).val() };
508
						break;
509
					case 'bitcoin':
510
					case 'alipay':
511
						extra_details.currency = $( '#stripe-' + source_type + '-payment-data' ).data( 'currency' );
512
						extra_details.amount = $( '#stripe-' + source_type + '-payment-data' ).data( 'amount' );
513
						break;
514
					case 'sofort':
515
						extra_details.sofort = { country: $( '#billing_country' ).val() };
516
						break;
517
				}
518
519
				extra_details.type = source_type;
520
521
				stripe.createSource( extra_details ).then( wc_stripe_form.sourceResponse );
522
			}
523
		},
524
525
		sourceResponse: function( response ) {
526
			if ( response.error ) {
527
				$( document.body ).trigger( 'stripeError', response );
528
			} else if ( 'no' === wc_stripe_params.allow_prepaid_card && 'card' === response.source.type && 'prepaid' === response.source.card.funding ) {
529
				response.error = { message: wc_stripe_params.no_prepaid_card_msg };
530
531
				if ( wc_stripe_params.is_stripe_checkout ) {
532
					wc_stripe_form.submitError( '<ul class="woocommerce-error"><li>' + wc_stripe_params.no_prepaid_card_msg + '</li></ul>' );
533
				} else {
534
					$( document.body ).trigger( 'stripeError', response );
535
				}
536
			} else {
537
				wc_stripe_form.processStripeResponse( response.source );
538
			}
539
		},
540
541
		processStripeResponse: function( source ) {
542
			wc_stripe_form.reset();
543
544
			// Insert the Source into the form so it gets submitted to the server.
545
			wc_stripe_form.form.append( "<input type='hidden' class='stripe-source' name='stripe_source' value='" + source.id + "'/>" );
546
547
			if ( $( 'form#add_payment_method' ).length ) {
548
				$( wc_stripe_form.form ).off( 'submit', wc_stripe_form.form.onSubmit );
549
			}
550
551
			wc_stripe_form.form.submit();
552
		},
553
554
		// Legacy
555
		createToken: function() {
556
			var card       = $( '#stripe-card-number' ).val(),
557
				cvc        = $( '#stripe-card-cvc' ).val(),
558
				expires    = $( '#stripe-card-expiry' ).payment( 'cardExpiryVal' ),
559
				first_name = $( '#billing_first_name' ).length ? $( '#billing_first_name' ).val() : wc_stripe_params.billing_first_name,
560
				last_name  = $( '#billing_last_name' ).length ? $( '#billing_last_name' ).val() : wc_stripe_params.billing_last_name,
561
				data       = {
562
					number   : card,
563
					cvc      : cvc,
564
					exp_month: parseInt( expires.month, 10 ) || 0,
565
					exp_year : parseInt( expires.year, 10 ) || 0
566
				};
567
568
			if ( first_name && last_name ) {
569
				data.name = first_name + ' ' + last_name;
570
			}
571
572
			if ( $( '#billing_address_1' ).length > 0 ) {
573
				data.address_line1   = $( '#billing_address_1' ).val();
574
				data.address_line2   = $( '#billing_address_2' ).val();
575
				data.address_state   = $( '#billing_state' ).val();
576
				data.address_city    = $( '#billing_city' ).val();
577
				data.address_zip     = $( '#billing_postcode' ).val();
578
				data.address_country = $( '#billing_country' ).val();
579
			} else if ( wc_stripe_params.billing_address_1 ) {
580
				data.address_line1   = wc_stripe_params.billing_address_1;
581
				data.address_line2   = wc_stripe_params.billing_address_2;
582
				data.address_state   = wc_stripe_params.billing_state;
583
				data.address_city    = wc_stripe_params.billing_city;
584
				data.address_zip     = wc_stripe_params.billing_postcode;
585
				data.address_country = wc_stripe_params.billing_country;
586
			}
587
			Stripe.setPublishableKey( wc_stripe_params.key );
0 ignored issues
show
Bug introduced by
The variable Stripe seems to be never declared. If this is a global, consider adding a /** global: Stripe */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
588
			Stripe.createToken( data, wc_stripe_form.onStripeTokenResponse );
589
		},
590
591
		// Legacy
592
		onStripeTokenResponse: function( status, response ) {
593
			if ( response.error ) {
594
				$( document ).trigger( 'stripeError', response );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
595
			} else {
596
				// check if we allow prepaid cards
597
				if ( 'no' === wc_stripe_params.allow_prepaid_card && 'prepaid' === response.card.funding ) {
598
					response.error = { message: wc_stripe_params.no_prepaid_card_msg };
599
600
					$( document ).trigger( 'stripeError', { response: response } );
601
602
					return false;
603
				}
604
605
				// token contains id, last4, and card type
606
				var token = response.id;
607
608
				// insert the token into the form so it gets submitted to the server
609
				wc_stripe_form.form.append( "<input type='hidden' class='stripe_token' name='stripe_token' value='" + token + "'/>" );
610
611
				if ( $( 'form#add_payment_method' ).length ) {
612
					$( wc_stripe_form.form ).off( 'submit', wc_stripe_form.form.onSubmit );
613
				}
614
615
				wc_stripe_form.form.submit();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
616
			}
617
		},
618
619
		onSubmit: function( e ) {
620
			if ( wc_stripe_form.isStripeChosen() && ! wc_stripe_form.isStripeSaveCardChosen() && ! wc_stripe_form.hasSource() && ! wc_stripe_form.hasToken() ) {
621
				e.preventDefault();
622
623
				// Stripe Checkout.
624
				if ( 'yes' === wc_stripe_params.is_stripe_checkout && wc_stripe_form.isStripeModalNeeded() && wc_stripe_form.isStripeCardChosen() ) {
625
					// Since in mobile actions cannot be deferred, no dynamic validation applied.
626
					if ( wc_stripe_form.isMobile() ) {
627
						wc_stripe_form.openModal();
628
					} else {
629
						wc_stripe_form.validateCheckout( 'modal' );
630
					}
631
632
					return false;
633
				}
634
635
				wc_stripe_form.block();
636
637
				// Process legacy card token.
638
				if ( wc_stripe_form.isStripeCardChosen() && 'no' === wc_stripe_params.use_elements ) {
639
					wc_stripe_form.createToken();
640
					return false;
641
				}
642
643
				if ( wc_stripe_form.isSepaChosen() ) {
644
					// Check if SEPA owner is filled before proceed.
645
					if ( '' === $( '#stripe-sepa-owner' ).val() ) {
646
						$( document.body ).trigger( 'stripeError', { error: { message: wc_stripe_params.no_sepa_owner_msg } } );
647
						return false;
648
					}
649
650
					// Check if SEPA IBAN is filled before proceed.
651
					if ( '' === $( '#stripe-sepa-iban' ).val() ) {
652
						$( document.body ).trigger( 'stripeError', { error: { message: wc_stripe_params.no_sepa_iban_msg } } );
653
						return false;
654
					}
655
				}
656
657
				/*
658
				 * For methods that needs redirect, we will create the
659
				 * source server side so we can obtain the order ID.
660
				 */
661
				if (
662
					wc_stripe_form.isBancontactChosen() ||
663
					wc_stripe_form.isGiropayChosen() ||
664
					wc_stripe_form.isIdealChosen() ||
665
					wc_stripe_form.isAlipayChosen() ||
666
					wc_stripe_form.isSofortChosen() ||
667
					wc_stripe_form.isP24Chosen()
668
				) {
669
					if ( $( 'form#order_review' ).length ) {
670
						$( 'form#order_review' )
671
							.off(
672
								'submit',
673
								this.onSubmit
674
							);
675
676
						if ( wc_stripe_form.isMobile() ) {
677
							wc_stripe_form.unblock();
678
						}
679
680
						return true;
681
					}
682
683
					if ( $( 'form.woocommerce-checkout' ).length ) {
684
						$( 'form.woocommerce-checkout' )
685
							.off(
686
								'submit',
687
								this.onSubmit
688
							);
689
690
						if ( wc_stripe_form.isMobile() ) {
691
							wc_stripe_form.unblock();
692
						}
693
694
						return true;
695
					}
696
697
					if ( $( 'form#add_payment_method' ).length ) {
698
						$( 'form#add_payment_method' )
699
							.off(
700
								'submit',
701
								this.onSubmit
702
							);
703
704
						if ( wc_stripe_form.isMobile() ) {
705
							wc_stripe_form.unblock();
706
						}
707
708
						return true;
709
					}
710
				}
711
712
				// We don't need to run validate on non checkout pages.
713
				if ( wc_stripe_params.is_checkout ) {
714
					wc_stripe_form.validateCheckout();
715
				} else {
716
					wc_stripe_form.createSource();
717
				}
718
719
				// Prevent form submitting
720
				return false;
721
			} else if ( $( 'form#add_payment_method' ).length ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if $("form#add_payment_method").length is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
722
				e.preventDefault();
723
724
				// Stripe Checkout.
725
				if ( 'yes' === wc_stripe_params.is_stripe_checkout && wc_stripe_form.isStripeModalNeeded() && wc_stripe_form.isStripeCardChosen() ) {
726
					wc_stripe_form.openModal();
727
728
					return false;
729
				}
730
731
				wc_stripe_form.block();
732
733
				// Process legacy card token.
734
				if ( wc_stripe_form.isStripeCardChosen() && 'no' === wc_stripe_params.use_elements ) {
735
					wc_stripe_form.createToken();
736
					return false;
737
				}
738
739
				wc_stripe_form.createSource();
740
				return false;
741
			}
742
		},
743
744
		onCCFormChange: function() {
745
			wc_stripe_form.reset();
746
		},
747
748
		reset: function() {
749
			$( '.wc-stripe-error, .stripe-source, .stripe_token, .stripe-checkout-object' ).remove();
750
751
			// Stripe Checkout.
752
			if ( 'yes' === wc_stripe_params.is_stripe_checkout ) {
753
				wc_stripe_form.stripe_submit = false;
754
			}
755
		},
756
757
		getRequiredFields: function() {
758
			return wc_stripe_form.form.find( '.form-row.validate-required > input, .form-row.validate-required > select, .form-row.validate-required > textarea' );
759
		},
760
761
		validateCheckout: function( type ) {
762
			if ( typeof type === 'undefined' ) {
763
				type = '';
764
			}
765
766
			var data = {
767
				'nonce': wc_stripe_params.stripe_nonce,
768
				'required_fields': wc_stripe_form.getRequiredFields().serialize(),
769
				'all_fields': wc_stripe_form.form.serialize(),
770
				'source_type': wc_stripe_form.getSelectedPaymentElement().val(),
771
				'is_add_payment_page': wc_stripe_params.is_add_payment_method_page
772
			};
773
774
			$.ajax({
775
				type:		'POST',
776
				url:		wc_stripe_form.getAjaxURL( 'validate_checkout' ),
777
				data:		data,
778
				dataType:   'json',
779
				success:	function( result ) {
780
					if ( 'success' === result ) {
781
						// Stripe Checkout.
782
						if ( 'modal' === type ) {
783
							wc_stripe_form.openModal();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
784
						} else {
785
							if ( wc_stripe_form.isSepaChosen() ) {
786
								// Check if SEPA owner is filled before proceed.
787
								if ( '' === $( '#stripe-sepa-owner' ).val() ) {
788
									$( document.body ).trigger( 'stripeError', { error: { message: wc_stripe_params.no_sepa_owner_msg } } );
789
									return false;
790
								}
791
792
								// Check if SEPA IBAN is filled before proceed.
793
								if ( '' === $( '#stripe-sepa-iban' ).val() ) {
794
									$( document.body ).trigger( 'stripeError', { error: { message: wc_stripe_params.no_sepa_iban_msg } } );
795
									return false;
796
								}
797
							}
798
799
							wc_stripe_form.createSource();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
800
						}
801
					} else if ( result.messages ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if result.messages is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
802
						wc_stripe_form.resetModal();
803
						wc_stripe_form.reset();
804
						wc_stripe_form.submitError( result.messages );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
805
					}
806
				}
807
			});
808
		},
809
810
		submitError: function( error_message ) {
811
			$( '.woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message' ).remove();
812
			wc_stripe_form.form.prepend( '<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">' + error_message + '</div>' );
813
			wc_stripe_form.form.removeClass( 'processing' ).unblock();
814
			wc_stripe_form.form.find( '.input-text, select, input:checkbox' ).blur();
815
			
816
			var selector = '';
817
818
			if ( $( '#add_payment_method' ).length ) {
819
				selector = $( '#add_payment_method' );
820
			}
821
822
			if ( $( '#order_review' ).length ) {
823
				selector = $( '#order_review' );
824
			}
825
826
			if ( $( 'form.checkout' ).length ) {
827
				selector = $( 'form.checkout' );
828
			}
829
830
			if ( selector.length ) {
831
				$( 'html, body' ).animate({
832
					scrollTop: ( selector.offset().top - 100 )
833
				}, 500 );
834
			}
835
836
			$( document.body ).trigger( 'checkout_error' );
837
			wc_stripe_form.unblock();
838
		}
839
	};
840
841
	wc_stripe_form.init();
842
} );
843