WooCommerce Stripe Payment Gateway - Version 3.1.0

Version Description

  • New - Apple Pay Support.
  • New - Add Google Payment Request API.
Download this release

Release Info

Developer royho
Plugin Icon 128x128 WooCommerce Stripe Payment Gateway
Version 3.1.0
Comparing to
See all releases

Code changes from version 3.0.7 to 3.1.0

assets/css/stripe-apple-pay.css ADDED
@@ -0,0 +1 @@
 
1
+ .apple-pay-button,.apple-pay-button-checkout-separator,.apple-pay-button-wrapper{display:none}@supports (-webkit-appearance:-apple-pay-button){.apple-pay-button-wrapper{display:block;margin-bottom:20px}.apple-pay-button{background-size:100% 100%;background-origin:content-box;background-repeat:no-repeat;width:100%;height:44px;padding:10px 0;border-radius:10px}.apple-pay-button-checkout-separator{text-transform:uppercase;text-align:center;font-size:1.2rem}.woocommerce-checkout .apple-pay-button-wrapper{text-align:center}.woocommerce-checkout .apple-pay-button{height:50px;margin:0 auto}.woocommerce-checkout .apple-pay-button-checkout-separator{border-bottom:1px solid #EBEBEB;padding-bottom:20px}.single-product div.product form.cart .apple-pay-button,.single-product div.product form.cart .quantity,.single-product div.product form.cart .quantity~.button{margin-bottom:10px}.single-product div.product form.cart .quantity{width:100%;margin-right:0}.single-product div.product form.cart .quantity input,.single-product div.product form.cart .quantity~.button{width:100%}.single-product div.product form.cart .apple-pay-button-wrapper{display:inline;margin-bottom:0}@media (min-width:768px){.woocommerce-checkout .apple-pay-button{width:30%}.single-product div.product form.cart .apple-pay-button,.single-product div.product form.cart .quantity,.single-product div.product form.cart .quantity~.button{margin-bottom:0}.single-product div.product form.cart .quantity{width:auto;margin-right:10px}.single-product div.product form.cart .quantity input{width:70px}.single-product div.product form.cart .quantity~.button{float:none;width:auto}.single-product div.product form.cart .apple-pay-button{float:left;max-width:20%;margin-right:10px}}}
assets/css/stripe-apple-pay.less ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .apple-pay-button-wrapper,
2
+ .apple-pay-button,
3
+ .apple-pay-button-checkout-separator {
4
+ display: none;
5
+ }
6
+
7
+ @supports (-webkit-appearance: -apple-pay-button) {
8
+ .apple-pay-button-wrapper {
9
+ display: block;
10
+ margin-bottom: 20px;
11
+ }
12
+
13
+ .apple-pay-button {
14
+ background-size: 100% 100%;
15
+ background-origin: content-box;
16
+ background-repeat: no-repeat;
17
+ width: 100%;
18
+ height: 44px;
19
+ padding: 10px 0;
20
+ border-radius: 10px;
21
+ }
22
+
23
+ .apple-pay-button-checkout-separator {
24
+ text-transform: uppercase;
25
+ text-align: center;
26
+ font-size: 1.2rem;
27
+ }
28
+
29
+ .woocommerce-checkout {
30
+ .apple-pay-button-wrapper {
31
+ text-align: center;
32
+ }
33
+
34
+ .apple-pay-button {
35
+ height: 50px;
36
+ margin: 0 auto;
37
+ }
38
+
39
+ .apple-pay-button-checkout-separator {
40
+ border-bottom: 1px solid #EBEBEB;
41
+ padding-bottom: 20px;
42
+ }
43
+ }
44
+
45
+ .single-product {
46
+ div.product {
47
+ form.cart {
48
+ .quantity,
49
+ .quantity ~ .button,
50
+ .apple-pay-button {
51
+ margin-bottom: 10px;
52
+ }
53
+
54
+ .quantity {
55
+ width: 100%;
56
+ margin-right: 0;
57
+
58
+ input {
59
+ width: 100%;
60
+ }
61
+ }
62
+
63
+ .quantity ~ .button {
64
+ width: 100%;
65
+ }
66
+
67
+ .apple-pay-button-wrapper {
68
+ display: inline;
69
+ margin-bottom: 0;
70
+ }
71
+ }
72
+ }
73
+ }
74
+
75
+ @media ( min-width: 768px ) {
76
+ .woocommerce-checkout {
77
+ .apple-pay-button {
78
+ width: 30%;
79
+ }
80
+ }
81
+
82
+ .single-product {
83
+ div.product {
84
+ form.cart {
85
+ .quantity,
86
+ .quantity ~ .button,
87
+ .apple-pay-button {
88
+ margin-bottom: 0;
89
+ }
90
+
91
+ .quantity {
92
+ width: auto;
93
+ margin-right: 10px;
94
+
95
+ input {
96
+ width: 70px;
97
+ }
98
+ }
99
+
100
+ .quantity ~ .button {
101
+ float: none;
102
+ width: auto;
103
+ }
104
+
105
+ .apple-pay-button {
106
+ float: left;
107
+ max-width: 20%;
108
+ margin-right: 10px;
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
assets/js/payment-request.js ADDED
@@ -0,0 +1,387 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*global jQuery, wcStripePaymentRequestParams, PaymentRequest, Stripe, Promise */
2
+ /*jshint es3: false */
3
+ /*jshint devel: true */
4
+ (function( $ ) {
5
+
6
+ /**
7
+ * WooCommerce Stripe PaymentRequest class.
8
+ *
9
+ * @type {Object}
10
+ */
11
+ var wcStripePaymentRequest = {
12
+
13
+ /**
14
+ * Initialize class events.
15
+ */
16
+ init: function() {
17
+ var self = this;
18
+
19
+ if ( self.hasPaymentRequestSupport() ) {
20
+ $( document.body )
21
+ .on( 'click', '.cart_totals a.checkout-button', self.initPaymentRequest );
22
+ }
23
+ },
24
+
25
+ /**
26
+ * Check if browser support PaymentRequest class and if is under HTTPS.
27
+ *
28
+ * @return {Bool}
29
+ */
30
+ hasPaymentRequestSupport: function() {
31
+ return window.PaymentRequest && 'https:' === window.location.protocol;
32
+ },
33
+
34
+ /**
35
+ * Get Stripe supported methods.
36
+ *
37
+ * @return {Array}
38
+ */
39
+ getSupportedMethods: function() {
40
+ return [
41
+ 'amex',
42
+ 'diners',
43
+ 'discover',
44
+ 'jcb',
45
+ 'mastercard',
46
+ 'visa'
47
+ ];
48
+ },
49
+
50
+ /**
51
+ * Get WC AJAX endpoint URL.
52
+ *
53
+ * @param {String} endpoint Endpoint.
54
+ * @return {String}
55
+ */
56
+ getAjaxURL: function( endpoint ) {
57
+ return wcStripePaymentRequestParams.ajax_url
58
+ .toString()
59
+ .replace( '%%endpoint%%', 'wc_stripe_' + endpoint );
60
+ },
61
+
62
+ /**
63
+ * Initialize the PaymentRequest.
64
+ *
65
+ * @param {Object} evt DOM events.
66
+ */
67
+ initPaymentRequest: function( evt ) {
68
+ evt.preventDefault();
69
+ var self = wcStripePaymentRequest;
70
+ var data = {
71
+ security: wcStripePaymentRequestParams.nonce.payment
72
+ };
73
+
74
+ $.ajax({
75
+ type: 'POST',
76
+ data: data,
77
+ url: self.getAjaxURL( 'get_cart_details' ),
78
+ success: function( response ) {
79
+ self.openPaymentRequest( response );
80
+ }
81
+ });
82
+ },
83
+
84
+ /**
85
+ * Open Payment Request modal.
86
+ *
87
+ * @param {Object} details Payment request details.
88
+ */
89
+ openPaymentRequest: function( details ) {
90
+ var self = this;
91
+
92
+ // PaymentRequest options.
93
+ var supportedInstruments = [{
94
+ supportedMethods: self.getSupportedMethods()
95
+ }];
96
+ var options = {
97
+ requestPayerPhone: true,
98
+ requestPayerEmail: true
99
+ };
100
+ if ( details.shipping_required ) {
101
+ options.requestShipping = true;
102
+ }
103
+ var paymentDetails = details.order_data;
104
+
105
+ // Init PaymentRequest.
106
+ var request = new PaymentRequest( supportedInstruments, paymentDetails, options );
107
+
108
+ // Set up shipping.
109
+ request.addEventListener( 'shippingaddresschange', function( evt ) {
110
+ evt.updateWith( new Promise( function( resolve, reject ) {
111
+ self.updateShippingOptions( paymentDetails, request.shippingAddress, resolve, reject );
112
+ }));
113
+ });
114
+ request.addEventListener( 'shippingoptionchange', function( evt ) {
115
+ evt.updateWith( new Promise( function( resolve, reject ) {
116
+ self.updateShippingDetails( paymentDetails, request.shippingOption, resolve, reject );
117
+ }));
118
+ });
119
+
120
+ // Open Payment Request UI.
121
+ request.show().then( function( payment ) {
122
+ self.processPayment( payment );
123
+ })
124
+ .catch( function( err ) {
125
+ console.error( err );
126
+ });
127
+ },
128
+
129
+ /**
130
+ * Update shipping options.
131
+ *
132
+ * @param {Object} details Payment details.
133
+ * @param {PaymentAddress} address Shipping address.
134
+ * @param {Function} resolve The callback to invoke with updated line items and shipping options.
135
+ * @param {Function} reject The callback to invoke in case of failure.
136
+ */
137
+ updateShippingOptions: function( details, address, resolve, reject ) {
138
+ var self = this;
139
+ var data = {
140
+ security: wcStripePaymentRequestParams.nonce.shipping,
141
+ country: address.country,
142
+ state: address.region,
143
+ postcode: address.postalCode,
144
+ city: address.city,
145
+ address: typeof address.addressLine[0] === 'undefined' ? '' : address.addressLine[0],
146
+ address_2: typeof address.addressLine[1] === 'undefined' ? '' : address.addressLine[1]
147
+ };
148
+
149
+ $.ajax({
150
+ type: 'POST',
151
+ data: data,
152
+ url: self.getAjaxURL( 'get_shipping_options' ),
153
+ success: function( response ) {
154
+ details.shippingOptions = response;
155
+ if ( details.shippingOptions.length == 1 ) {
156
+ // The sole shipping option was auto-selected. Update the details
157
+ // (including the total).
158
+ self.updateShippingDetails(
159
+ details, details.shippingOptions[0].id, resolve, reject );
160
+ } else {
161
+ resolve( details );
162
+ }
163
+ }
164
+ });
165
+ },
166
+
167
+ /**
168
+ * Updates the shipping price and the total based on the shipping option.
169
+ *
170
+ * @param {Object} details The line items and shipping options.
171
+ * @param {String} shippingOption User's preferred shipping option to use for shipping price calculations.
172
+ * @param {Function} resolve The callback to invoke with updated line items and shipping options.
173
+ * @param {Function} reject The callback to invoke in case of failure.
174
+ */
175
+ updateShippingDetails: function( details, shippingOption, resolve, reject ) {
176
+ var self = this;
177
+ var selected = null;
178
+ var data = {
179
+ security: wcStripePaymentRequestParams.nonce.update_shipping,
180
+ shipping_method: [
181
+ shippingOption
182
+ ]
183
+ };
184
+
185
+ $.ajax({
186
+ type: 'POST',
187
+ data: data,
188
+ url: self.getAjaxURL( 'update_shipping_method' ),
189
+ success: function( response ) {
190
+ details.shippingOptions.forEach( function( value, index ) {
191
+ if ( value.id === shippingOption ) {
192
+ selected = index;
193
+ value.selected = true;
194
+ details.total.amount.value = parseFloat( response.total );
195
+
196
+ if ( response.items ) {
197
+ details.displayItems = response.items;
198
+ }
199
+ } else {
200
+ value.selected = false;
201
+ }
202
+ });
203
+
204
+ if ( null === selected ) {
205
+ reject( wcStripePaymentRequestParams.i18n.unknown_shipping.toString().replace( '[option]', shippingOption ) );
206
+ }
207
+
208
+ resolve( details );
209
+ }
210
+ });
211
+ },
212
+
213
+ /**
214
+ * Get order data.
215
+ *
216
+ * @param {PaymentResponse} payment Payment Response instance.
217
+ *
218
+ * @return {Object}
219
+ */
220
+ getOrderData: function( payment ) {
221
+ var billing = payment.details.billingAddress;
222
+ var shipping = payment.shippingAddress;
223
+ var data = {
224
+ _wpnonce: wcStripePaymentRequestParams.nonce.checkout,
225
+ billing_first_name: billing.recipient.split( ' ' ).slice( 0, 1 ).join( ' ' ),
226
+ billing_last_name: billing.recipient.split( ' ' ).slice( 1 ).join( ' ' ),
227
+ billing_company: billing.organization,
228
+ billing_email: payment.payerEmail,
229
+ billing_phone: payment.payerPhone,
230
+ billing_country: billing.country,
231
+ billing_address_1: typeof billing.addressLine[0] === 'undefined' ? '' : billing.addressLine[0],
232
+ billing_address_2: typeof billing.addressLine[1] === 'undefined' ? '' : billing.addressLine[1],
233
+ billing_city: billing.city,
234
+ billing_state: billing.region,
235
+ billing_postcode: billing.postalCode,
236
+ shipping_first_name: '',
237
+ shipping_last_name: '',
238
+ shipping_company: '',
239
+ shipping_country: '',
240
+ shipping_address_1: '',
241
+ shipping_address_2: '',
242
+ shipping_city: '',
243
+ shipping_state: '',
244
+ shipping_postcode: '',
245
+ shipping_method: [ payment.shippingOption ],
246
+ order_comments: '',
247
+ payment_method: 'stripe',
248
+ // 'wc-stripe-payment-token': 'new',
249
+ stripe_token: '',
250
+ };
251
+
252
+ if ( shipping ) {
253
+ data.shipping_first_name = shipping.recipient.split( ' ' ).slice( 0, 1 ).join( ' ' );
254
+ data.shipping_last_name = shipping.recipient.split( ' ' ).slice( 1 ).join( ' ' );
255
+ data.shipping_company = shipping.organization;
256
+ data.shipping_country = shipping.country;
257
+ data.shipping_address_1 = typeof shipping.addressLine[0] === 'undefined' ? '' : shipping.addressLine[0];
258
+ data.shipping_address_2 = typeof shipping.addressLine[1] === 'undefined' ? '' : shipping.addressLine[1];
259
+ data.shipping_city = shipping.city;
260
+ data.shipping_state = shipping.region;
261
+ data.shipping_postcode = shipping.postalCode;
262
+ }
263
+
264
+ return data;
265
+ },
266
+
267
+ /**
268
+ * Get credit card data.
269
+ *
270
+ * @param {PaymentResponse} payment Payment Response instance.
271
+ *
272
+ * @return {Object}
273
+ */
274
+ getCardData: function( payment ) {
275
+ var billing = payment.details.billingAddress;
276
+ var data = {
277
+ number: payment.details.cardNumber,
278
+ cvc: payment.details.cardSecurityCode,
279
+ exp_month: parseInt( payment.details.expiryMonth, 10 ) || 0,
280
+ exp_year: parseInt( payment.details.expiryYear, 10 ) || 0,
281
+ name: billing.recipient,
282
+ address_line1: typeof billing.addressLine[0] === 'undefined' ? '' : billing.addressLine[0],
283
+ address_line2: typeof billing.addressLine[1] === 'undefined' ? '' : billing.addressLine[1],
284
+ address_state: billing.region,
285
+ address_city: billing.city,
286
+ address_zip: billing.postalCode,
287
+ address_country: billing.country
288
+ };
289
+
290
+ return data;
291
+ },
292
+
293
+ /**
294
+ * Generate error message HTML.
295
+ *
296
+ * @param {String} message Error message.
297
+ * @return {Object}
298
+ */
299
+ getErrorMessageHTML: function( message ) {
300
+ return $( '<div class="woocommerce-error" />' ).text( message );
301
+ },
302
+
303
+ /**
304
+ * Abort payment and display error messages.
305
+ *
306
+ * @param {PaymentResponse} payment Payment response instance.
307
+ * @param {String} message Error message to display.
308
+ */
309
+ abortPayment: function( payment, message ) {
310
+ payment.complete( 'fail' ).then( function() {
311
+ var $form = $( '.shop_table.cart' ).closest( 'form' );
312
+ $( '.woocommerce-error' ).remove();
313
+ $form.before( message );
314
+ $( 'html, body' ).animate({
315
+ scrollTop: $form.prev( '.woocommerce-error' ).offset().top
316
+ }, 600 );
317
+ })
318
+ .catch( function( err ) {
319
+ console.error( err );
320
+ });
321
+ },
322
+
323
+ /**
324
+ * Complete payment.
325
+ *
326
+ * @param {PaymentResponse} payment Payment response instance.
327
+ * @param {String} url Order thank you page URL.
328
+ */
329
+ completePayment: function( payment, url ) {
330
+ payment.complete( 'success' ).then( function() {
331
+ // Success, then redirect to the Thank You page.
332
+ window.location = url;
333
+ })
334
+ .catch( function( err ) {
335
+ console.error( err );
336
+ });
337
+ },
338
+
339
+ /**
340
+ * Process payment.
341
+ *
342
+ * @param {PaymentResponse} payment Payment response instance.
343
+ */
344
+ processPayment: function( payment ) {
345
+ var self = this;
346
+ var orderData = self.getOrderData( payment );
347
+ var cardData = self.getCardData( payment );
348
+
349
+ Stripe.setPublishableKey( wcStripePaymentRequestParams.stripe.key );
350
+ Stripe.createToken( cardData, function( status, response ) {
351
+ if ( response.error ) {
352
+ self.abortPayment( payment, self.getErrorMessageHTML( response.error.message ) );
353
+ } else {
354
+ // Check if we allow prepaid cards.
355
+ if ( 'no' === wcStripePaymentRequestParams.stripe.allow_prepaid_card && 'prepaid' === response.card.funding ) {
356
+ self.abortPayment( payment, self.getErrorMessageHTML( wcStripePaymentRequestParams.i18n.no_prepaid_card ) );
357
+ } else {
358
+ // Token contains id, last4, and card type.
359
+ orderData.stripe_token = response.id;
360
+
361
+ $.ajax({
362
+ type: 'POST',
363
+ data: orderData,
364
+ dataType: 'json',
365
+ url: self.getAjaxURL( 'create_order' ),
366
+ success: function( response ) {
367
+ if ( 'success' === response.result ) {
368
+ self.completePayment( payment, response.redirect );
369
+ } else {
370
+ self.abortPayment( payment, response.messages );
371
+ }
372
+ },
373
+ complete: function( jqXHR, textStatus ) {
374
+ if ( 'success' !== textStatus ) {
375
+ console.error( jqXHR );
376
+ }
377
+ }
378
+ });
379
+ }
380
+ }
381
+ });
382
+ }
383
+ };
384
+
385
+ wcStripePaymentRequest.init();
386
+
387
+ })( jQuery );
assets/js/payment-request.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(a){var b={init:function(){var b=this;b.hasPaymentRequestSupport()&&a(document.body).on("click",".cart_totals a.checkout-button",b.initPaymentRequest)},hasPaymentRequestSupport:function(){return window.PaymentRequest&&"https:"===window.location.protocol},getSupportedMethods:function(){return["amex","diners","discover","jcb","mastercard","visa"]},getAjaxURL:function(a){return wcStripePaymentRequestParams.ajax_url.toString().replace("%%endpoint%%","wc_stripe_"+a)},initPaymentRequest:function(c){c.preventDefault();var d=b,e={security:wcStripePaymentRequestParams.nonce.payment};a.ajax({type:"POST",data:e,url:d.getAjaxURL("get_cart_details"),success:function(a){d.openPaymentRequest(a)}})},openPaymentRequest:function(a){var b=this,c=[{supportedMethods:b.getSupportedMethods()}],d={requestPayerPhone:!0,requestPayerEmail:!0};a.shipping_required&&(d.requestShipping=!0);var e=a.order_data,f=new PaymentRequest(c,e,d);f.addEventListener("shippingaddresschange",function(a){a.updateWith(new Promise(function(a,c){b.updateShippingOptions(e,f.shippingAddress,a,c)}))}),f.addEventListener("shippingoptionchange",function(a){a.updateWith(new Promise(function(a,c){b.updateShippingDetails(e,f.shippingOption,a,c)}))}),f.show().then(function(a){b.processPayment(a)})["catch"](function(a){console.error(a)})},updateShippingOptions:function(b,c,d,e){var f=this,g={security:wcStripePaymentRequestParams.nonce.shipping,country:c.country,state:c.region,postcode:c.postalCode,city:c.city,address:"undefined"==typeof c.addressLine[0]?"":c.addressLine[0],address_2:"undefined"==typeof c.addressLine[1]?"":c.addressLine[1]};a.ajax({type:"POST",data:g,url:f.getAjaxURL("get_shipping_options"),success:function(a){b.shippingOptions=a,1==b.shippingOptions.length?f.updateShippingDetails(b,b.shippingOptions[0].id,d,e):d(b)}})},updateShippingDetails:function(b,c,d,e){var f=this,g=null,h={security:wcStripePaymentRequestParams.nonce.update_shipping,shipping_method:[c]};a.ajax({type:"POST",data:h,url:f.getAjaxURL("update_shipping_method"),success:function(a){b.shippingOptions.forEach(function(d,e){d.id===c?(g=e,d.selected=!0,b.total.amount.value=parseFloat(a.total),a.items&&(b.displayItems=a.items)):d.selected=!1}),null===g&&e(wcStripePaymentRequestParams.i18n.unknown_shipping.toString().replace("[option]",c)),d(b)}})},getOrderData:function(a){var b=a.details.billingAddress,c=a.shippingAddress,d={_wpnonce:wcStripePaymentRequestParams.nonce.checkout,billing_first_name:b.recipient.split(" ").slice(0,1).join(" "),billing_last_name:b.recipient.split(" ").slice(1).join(" "),billing_company:b.organization,billing_email:a.payerEmail,billing_phone:a.payerPhone,billing_country:b.country,billing_address_1:"undefined"==typeof b.addressLine[0]?"":b.addressLine[0],billing_address_2:"undefined"==typeof b.addressLine[1]?"":b.addressLine[1],billing_city:b.city,billing_state:b.region,billing_postcode:b.postalCode,shipping_first_name:"",shipping_last_name:"",shipping_company:"",shipping_country:"",shipping_address_1:"",shipping_address_2:"",shipping_city:"",shipping_state:"",shipping_postcode:"",shipping_method:[a.shippingOption],order_comments:"",payment_method:"stripe",stripe_token:""};return c&&(d.shipping_first_name=c.recipient.split(" ").slice(0,1).join(" "),d.shipping_last_name=c.recipient.split(" ").slice(1).join(" "),d.shipping_company=c.organization,d.shipping_country=c.country,d.shipping_address_1="undefined"==typeof c.addressLine[0]?"":c.addressLine[0],d.shipping_address_2="undefined"==typeof c.addressLine[1]?"":c.addressLine[1],d.shipping_city=c.city,d.shipping_state=c.region,d.shipping_postcode=c.postalCode),d},getCardData:function(a){var b=a.details.billingAddress,c={number:a.details.cardNumber,cvc:a.details.cardSecurityCode,exp_month:parseInt(a.details.expiryMonth,10)||0,exp_year:parseInt(a.details.expiryYear,10)||0,name:b.recipient,address_line1:"undefined"==typeof b.addressLine[0]?"":b.addressLine[0],address_line2:"undefined"==typeof b.addressLine[1]?"":b.addressLine[1],address_state:b.region,address_city:b.city,address_zip:b.postalCode,address_country:b.country};return c},getErrorMessageHTML:function(b){return a('<div class="woocommerce-error" />').text(b)},abortPayment:function(b,c){b.complete("fail").then(function(){var b=a(".shop_table.cart").closest("form");a(".woocommerce-error").remove(),b.before(c),a("html, body").animate({scrollTop:b.prev(".woocommerce-error").offset().top},600)})["catch"](function(a){console.error(a)})},completePayment:function(a,b){a.complete("success").then(function(){window.location=b})["catch"](function(a){console.error(a)})},processPayment:function(b){var c=this,d=c.getOrderData(b),e=c.getCardData(b);Stripe.setPublishableKey(wcStripePaymentRequestParams.stripe.key),Stripe.createToken(e,function(e,f){f.error?c.abortPayment(b,c.getErrorMessageHTML(f.error.message)):"no"===wcStripePaymentRequestParams.stripe.allow_prepaid_card&&"prepaid"===f.card.funding?c.abortPayment(b,c.getErrorMessageHTML(wcStripePaymentRequestParams.i18n.no_prepaid_card)):(d.stripe_token=f.id,a.ajax({type:"POST",data:d,dataType:"json",url:c.getAjaxURL("create_order"),success:function(a){"success"===a.result?c.completePayment(b,a.redirect):c.abortPayment(b,a.messages)},complete:function(a,b){"success"!==b&&console.error(a)}}))})}};b.init()}(jQuery);
assets/js/stripe-admin.js ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function( $ ) {
2
+ 'use strict';
3
+
4
+ /**
5
+ * Object to handle Stripe admin functions.
6
+ */
7
+ var wc_stripe_admin = {
8
+ isTestMode: function() {
9
+ return $( '#woocommerce_stripe_testmode' ).is( ':checked' );
10
+ },
11
+
12
+ getSecretKey: function() {
13
+ if ( wc_stripe_admin.isTestMode() ) {
14
+ return $( '#woocommerce_stripe_test_secret_key' ).val();
15
+ } else {
16
+ return $( '#woocommerce_stripe_secret_key' ).val();
17
+ }
18
+ },
19
+
20
+ /**
21
+ * Initialize.
22
+ */
23
+ init: function() {
24
+ $( document.body ).on( 'change', '#woocommerce_stripe_testmode', function() {
25
+ var test_secret_key = $( '#woocommerce_stripe_test_secret_key' ).parents( 'tr' ).eq( 0 ),
26
+ test_publishable_key = $( '#woocommerce_stripe_test_publishable_key' ).parents( 'tr' ).eq( 0 ),
27
+ live_secret_key = $( '#woocommerce_stripe_secret_key' ).parents( 'tr' ).eq( 0 ),
28
+ live_publishable_key = $( '#woocommerce_stripe_publishable_key' ).parents( 'tr' ).eq( 0 );
29
+
30
+ if ( $( this ).is( ':checked' ) ) {
31
+ test_secret_key.show();
32
+ test_publishable_key.show();
33
+ live_secret_key.hide();
34
+ live_publishable_key.hide();
35
+ } else {
36
+ test_secret_key.hide();
37
+ test_publishable_key.hide();
38
+ live_secret_key.show();
39
+ live_publishable_key.show();
40
+ }
41
+ } );
42
+
43
+ $( '#woocommerce_stripe_testmode' ).change();
44
+
45
+ // Toggle Stripe Checkout settings.
46
+ $( '#woocommerce_stripe_stripe_checkout' ).change( function() {
47
+ if ( $( this ).is( ':checked' ) ) {
48
+ $( '#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image, #woocommerce_stripe_allow_remember_me' ).closest( 'tr' ).show();
49
+ $( '#woocommerce_stripe_request_payment_api' ).closest( 'tr' ).hide();
50
+ } else {
51
+ $( '#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image, #woocommerce_stripe_allow_remember_me' ).closest( 'tr' ).hide();
52
+ $( '#woocommerce_stripe_request_payment_api' ).closest( 'tr' ).show();
53
+ }
54
+ }).change();
55
+
56
+ // Toggle Apple Pay settings.
57
+ $( '#woocommerce_stripe_apple_pay' ).change( function() {
58
+ if ( $( this ).is( ':checked' ) ) {
59
+ $( '#woocommerce_stripe_apple_pay_button, #woocommerce_stripe_apple_pay_button_lang' ).closest( 'tr' ).show();
60
+ } else {
61
+ $( '#woocommerce_stripe_apple_pay_button, #woocommerce_stripe_apple_pay_button_lang' ).closest( 'tr' ).hide();
62
+ }
63
+ }).change();
64
+
65
+ // Validate the keys to make sure it is matching test with test field.
66
+ $( '#woocommerce_stripe_secret_key, #woocommerce_stripe_publishable_key' ).on( 'input', function() {
67
+ var value = $( this ).val();
68
+
69
+ if ( value.indexOf( '_test_' ) >= 0 ) {
70
+ $( this ).css( 'border-color', 'red' ).after( '<span class="description stripe-error-description" style="color:red; display:block;">' + wc_stripe_admin_params.localized_messages.not_valid_live_key_msg + '</span>' );
71
+ } else {
72
+ $( this ).css( 'border-color', '' );
73
+ $( '.stripe-error-description', $( this ).parent() ).remove();
74
+ }
75
+ }).trigger( 'input' );
76
+
77
+ // Validate the keys to make sure it is matching live with live field.
78
+ $( '#woocommerce_stripe_test_secret_key, #woocommerce_stripe_test_publishable_key' ).on( 'input', function() {
79
+ var value = $( this ).val();
80
+
81
+ if ( value.indexOf( '_live_' ) >= 0 ) {
82
+ $( this ).css( 'border-color', 'red' ).after( '<span class="description stripe-error-description" style="color:red; display:block;">' + wc_stripe_admin_params.localized_messages.not_valid_test_key_msg + '</span>' );
83
+ } else {
84
+ $( this ).css( 'border-color', '' );
85
+ $( '.stripe-error-description', $( this ).parent() ).remove();
86
+ }
87
+ }).trigger( 'input' );
88
+ }
89
+ };
90
+
91
+ wc_stripe_admin.init();
92
+ });
assets/js/stripe-admin.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(function(a){"use strict";var b={isTestMode:function(){return a("#woocommerce_stripe_testmode").is(":checked")},getSecretKey:function(){return b.isTestMode()?a("#woocommerce_stripe_test_secret_key").val():a("#woocommerce_stripe_secret_key").val()},init:function(){a(document.body).on("change","#woocommerce_stripe_testmode",function(){var b=a("#woocommerce_stripe_test_secret_key").parents("tr").eq(0),c=a("#woocommerce_stripe_test_publishable_key").parents("tr").eq(0),d=a("#woocommerce_stripe_secret_key").parents("tr").eq(0),e=a("#woocommerce_stripe_publishable_key").parents("tr").eq(0);a(this).is(":checked")?(b.show(),c.show(),d.hide(),e.hide()):(b.hide(),c.hide(),d.show(),e.show())}),a("#woocommerce_stripe_testmode").change(),a("#woocommerce_stripe_stripe_checkout").change(function(){a(this).is(":checked")?(a("#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image, #woocommerce_stripe_allow_remember_me").closest("tr").show(),a("#woocommerce_stripe_request_payment_api").closest("tr").hide()):(a("#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image, #woocommerce_stripe_allow_remember_me").closest("tr").hide(),a("#woocommerce_stripe_request_payment_api").closest("tr").show())}).change(),a("#woocommerce_stripe_apple_pay").change(function(){a(this).is(":checked")?a("#woocommerce_stripe_apple_pay_button, #woocommerce_stripe_apple_pay_button_lang").closest("tr").show():a("#woocommerce_stripe_apple_pay_button, #woocommerce_stripe_apple_pay_button_lang").closest("tr").hide()}).change(),a("#woocommerce_stripe_secret_key, #woocommerce_stripe_publishable_key").on("input",function(){var b=a(this).val();b.indexOf("_test_")>=0?a(this).css("border-color","red").after('<span class="description stripe-error-description" style="color:red; display:block;">'+wc_stripe_admin_params.localized_messages.not_valid_live_key_msg+"</span>"):(a(this).css("border-color",""),a(".stripe-error-description",a(this).parent()).remove())}).trigger("input"),a("#woocommerce_stripe_test_secret_key, #woocommerce_stripe_test_publishable_key").on("input",function(){var b=a(this).val();b.indexOf("_live_")>=0?a(this).css("border-color","red").after('<span class="description stripe-error-description" style="color:red; display:block;">'+wc_stripe_admin_params.localized_messages.not_valid_test_key_msg+"</span>"):(a(this).css("border-color",""),a(".stripe-error-description",a(this).parent()).remove())}).trigger("input")}};b.init()});
assets/js/stripe-apple-pay-single.js ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global wc_stripe_apple_pay_single_params, Stripe */
2
+ Stripe.setPublishableKey( wc_stripe_apple_pay_single_params.key );
3
+
4
+ jQuery( function( $ ) {
5
+ 'use strict';
6
+
7
+ /**
8
+ * Object to handle Stripe payment forms.
9
+ */
10
+ var wc_stripe_apple_pay_single = {
11
+ /**
12
+ * Get WC AJAX endpoint URL.
13
+ *
14
+ * @param {String} endpoint Endpoint.
15
+ * @return {String}
16
+ */
17
+ getAjaxURL: function( endpoint ) {
18
+ return wc_stripe_apple_pay_single_params.ajaxurl
19
+ .toString()
20
+ .replace( '%%endpoint%%', 'wc_stripe_' + endpoint );
21
+ },
22
+
23
+ /**
24
+ * Initialize event handlers and UI state.
25
+ */
26
+ init: function() {
27
+ Stripe.applePay.checkAvailability( function( available ) {
28
+ if ( available ) {
29
+ $( document.body ).on( 'woocommerce_variation_has_changed', function() {
30
+ wc_stripe_apple_pay_single.generate_cart();
31
+ })
32
+
33
+ .on( 'change', '.quantity .qty', function() {
34
+ wc_stripe_apple_pay_single.generate_cart();
35
+ });
36
+
37
+ wc_stripe_apple_pay_single.generate_cart();
38
+
39
+ $( '.apple-pay-button' ).show();
40
+ }
41
+ });
42
+
43
+ $( document.body ).on( 'click', '.apple-pay-button', function( e ) {
44
+ e.preventDefault();
45
+
46
+ var addToCartButton = $( '.single_add_to_cart_button' );
47
+
48
+ // First check if product can be added to cart.
49
+ if ( addToCartButton.is( '.disabled' ) ) {
50
+ if ( addToCartButton.is( '.wc-variation-is-unavailable' ) ) {
51
+ window.alert( wc_add_to_cart_variation_params.i18n_unavailable_text );
52
+ } else if ( addToCartButton.is( '.wc-variation-selection-needed' ) ) {
53
+ window.alert( wc_add_to_cart_variation_params.i18n_make_a_selection_text );
54
+ }
55
+
56
+ return;
57
+ }
58
+
59
+ var paymentRequest = {
60
+ countryCode: wc_stripe_apple_pay_single_params.country_code,
61
+ currencyCode: wc_stripe_apple_pay_single_params.currency_code,
62
+ total: {
63
+ label: wc_stripe_apple_pay_single_params.label,
64
+ amount: wc_stripe_apple_pay_single_params.total
65
+ },
66
+ lineItems: wc_stripe_apple_pay_single_params.line_items,
67
+ requiredBillingContactFields: ['postalAddress'],
68
+ requiredShippingContactFields: 'yes' === wc_stripe_apple_pay_single_params.needs_shipping ? ['postalAddress', 'phone', 'email', 'name'] : ['phone', 'email', 'name']
69
+ };
70
+
71
+ var applePaySession = Stripe.applePay.buildSession( paymentRequest, function( result, completion ) {
72
+ var data = {
73
+ 'nonce': wc_stripe_apple_pay_single_params.stripe_apple_pay_nonce,
74
+ 'result': result
75
+ };
76
+
77
+ $.ajax({
78
+ type: 'POST',
79
+ data: data,
80
+ url: wc_stripe_apple_pay_single.getAjaxURL( 'apple_pay' ),
81
+ success: function( response ) {
82
+ if ( 'true' === response.success ) {
83
+ completion( ApplePaySession.STATUS_SUCCESS );
84
+ window.location.href = response.redirect;
85
+ }
86
+
87
+ if ( 'false' === response.success ) {
88
+ completion( ApplePaySession.STATUS_FAILURE );
89
+
90
+ $( '.apple-pay-button' ).before( '<p class="woocommerce-error wc-stripe-apple-pay-error">' + response.msg + '</p>' );
91
+
92
+ // Scroll to error so user can see it.
93
+ $( document.body ).animate({ scrollTop: $( '.wc-stripe-apple-pay-error' ).offset().top }, 500 );
94
+ }
95
+ }
96
+ });
97
+ });
98
+
99
+ // If shipping is needed -- get shipping methods.
100
+ if ( 'yes' === wc_stripe_apple_pay_single_params.needs_shipping ) {
101
+ // After the shipping contact/address has been selected
102
+ applePaySession.onshippingcontactselected = function( shipping ) {
103
+ var data = {
104
+ 'nonce': wc_stripe_apple_pay_single_params.stripe_apple_pay_get_shipping_methods_nonce,
105
+ 'address': shipping.shippingContact
106
+ };
107
+
108
+ $.ajax({
109
+ type: 'POST',
110
+ data: data,
111
+ url: wc_stripe_apple_pay_single.getAjaxURL( 'apple_pay_get_shipping_methods' ),
112
+ success: function( response ) {
113
+ var total = {
114
+ 'label': wc_stripe_apple_pay_single_params.label,
115
+ 'amount': response.total
116
+ };
117
+
118
+ if ( 'true' === response.success ) {
119
+ applePaySession.completeShippingContactSelection( ApplePaySession.STATUS_SUCCESS, response.shipping_methods, total, response.line_items );
120
+ }
121
+
122
+ if ( 'false' === response.success ) {
123
+ applePaySession.completeShippingContactSelection( ApplePaySession.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS, response.shipping_methods, total, response.line_items );
124
+ }
125
+ }
126
+ });
127
+ };
128
+
129
+ // After the shipping method has been selected
130
+ applePaySession.onshippingmethodselected = function( event ) {
131
+ var data = {
132
+ 'nonce': wc_stripe_apple_pay_single_params.stripe_apple_pay_update_shipping_method_nonce,
133
+ 'selected_shipping_method': event.shippingMethod
134
+ };
135
+
136
+ $.ajax({
137
+ type: 'POST',
138
+ data: data,
139
+ url: wc_stripe_apple_pay_single.getAjaxURL( 'apple_pay_update_shipping_method' ),
140
+ success: function( response ) {
141
+ var newTotal = {
142
+ 'label': wc_stripe_apple_pay_single_params.label,
143
+ 'amount': parseFloat( response.total ).toFixed(2)
144
+ };
145
+
146
+ if ( 'true' === response.success ) {
147
+ applePaySession.completeShippingMethodSelection( ApplePaySession.STATUS_SUCCESS, newTotal, response.line_items );
148
+ }
149
+
150
+ if ( 'false' === response.success ) {
151
+ applePaySession.completeShippingMethodSelection( ApplePaySession.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS, newTotal, response.line_items );
152
+ }
153
+ }
154
+ });
155
+ };
156
+ }
157
+
158
+ applePaySession.begin();
159
+ });
160
+ },
161
+
162
+ get_attributes: function() {
163
+ var select = $( '.variations_form' ).find( '.variations select' ),
164
+ data = {},
165
+ count = 0,
166
+ chosen = 0;
167
+
168
+ select.each( function() {
169
+ var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
170
+ var value = $( this ).val() || '';
171
+
172
+ if ( value.length > 0 ) {
173
+ chosen ++;
174
+ }
175
+
176
+ count ++;
177
+ data[ attribute_name ] = value;
178
+ });
179
+
180
+ return {
181
+ 'count' : count,
182
+ 'chosenCount': chosen,
183
+ 'data' : data
184
+ };
185
+ },
186
+
187
+ generate_cart: function() {
188
+ var data = {
189
+ 'nonce': wc_stripe_apple_pay_single_params.stripe_apple_pay_cart_nonce,
190
+ 'qty': $( '.quantity .qty' ).val(),
191
+ 'attributes': $( '.variations_form' ).length ? wc_stripe_apple_pay_single.get_attributes().data : []
192
+ };
193
+
194
+ return $.ajax({
195
+ type: 'POST',
196
+ data: data,
197
+ url: wc_stripe_apple_pay_single.getAjaxURL( 'generate_apple_pay_single' ),
198
+ success: function( response ) {
199
+ wc_stripe_apple_pay_single_params.total = response.total;
200
+ wc_stripe_apple_pay_single_params.line_items = response.line_items;
201
+ }
202
+ });
203
+ }
204
+ };
205
+
206
+ wc_stripe_apple_pay_single.init();
207
+ });
assets/js/stripe-apple-pay-single.min.js ADDED
@@ -0,0 +1 @@
 
1
+ Stripe.setPublishableKey(wc_stripe_apple_pay_single_params.key),jQuery(function(a){"use strict";var b={getAjaxURL:function(a){return wc_stripe_apple_pay_single_params.ajaxurl.toString().replace("%%endpoint%%","wc_stripe_"+a)},init:function(){Stripe.applePay.checkAvailability(function(c){c&&(a(document.body).on("woocommerce_variation_has_changed",function(){b.generate_cart()}).on("change",".quantity .qty",function(){b.generate_cart()}),b.generate_cart(),a(".apple-pay-button").show())}),a(document.body).on("click",".apple-pay-button",function(c){c.preventDefault();var d=a(".single_add_to_cart_button");if(d.is(".disabled"))return void(d.is(".wc-variation-is-unavailable")?window.alert(wc_add_to_cart_variation_params.i18n_unavailable_text):d.is(".wc-variation-selection-needed")&&window.alert(wc_add_to_cart_variation_params.i18n_make_a_selection_text));var e={countryCode:wc_stripe_apple_pay_single_params.country_code,currencyCode:wc_stripe_apple_pay_single_params.currency_code,total:{label:wc_stripe_apple_pay_single_params.label,amount:wc_stripe_apple_pay_single_params.total},lineItems:wc_stripe_apple_pay_single_params.line_items,requiredBillingContactFields:["postalAddress"],requiredShippingContactFields:"yes"===wc_stripe_apple_pay_single_params.needs_shipping?["postalAddress","phone","email","name"]:["phone","email","name"]},f=Stripe.applePay.buildSession(e,function(c,d){var e={nonce:wc_stripe_apple_pay_single_params.stripe_apple_pay_nonce,result:c};a.ajax({type:"POST",data:e,url:b.getAjaxURL("apple_pay"),success:function(b){"true"===b.success&&(d(ApplePaySession.STATUS_SUCCESS),window.location.href=b.redirect),"false"===b.success&&(d(ApplePaySession.STATUS_FAILURE),a(".apple-pay-button").before('<p class="woocommerce-error wc-stripe-apple-pay-error">'+b.msg+"</p>"),a(document.body).animate({scrollTop:a(".wc-stripe-apple-pay-error").offset().top},500))}})});"yes"===wc_stripe_apple_pay_single_params.needs_shipping&&(f.onshippingcontactselected=function(c){var d={nonce:wc_stripe_apple_pay_single_params.stripe_apple_pay_get_shipping_methods_nonce,address:c.shippingContact};a.ajax({type:"POST",data:d,url:b.getAjaxURL("apple_pay_get_shipping_methods"),success:function(a){var b={label:wc_stripe_apple_pay_single_params.label,amount:a.total};"true"===a.success&&f.completeShippingContactSelection(ApplePaySession.STATUS_SUCCESS,a.shipping_methods,b,a.line_items),"false"===a.success&&f.completeShippingContactSelection(ApplePaySession.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,a.shipping_methods,b,a.line_items)}})},f.onshippingmethodselected=function(c){var d={nonce:wc_stripe_apple_pay_single_params.stripe_apple_pay_update_shipping_method_nonce,selected_shipping_method:c.shippingMethod};a.ajax({type:"POST",data:d,url:b.getAjaxURL("apple_pay_update_shipping_method"),success:function(a){var b={label:wc_stripe_apple_pay_single_params.label,amount:parseFloat(a.total).toFixed(2)};"true"===a.success&&f.completeShippingMethodSelection(ApplePaySession.STATUS_SUCCESS,b,a.line_items),"false"===a.success&&f.completeShippingMethodSelection(ApplePaySession.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,b,a.line_items)}})}),f.begin()})},get_attributes:function(){var b=a(".variations_form").find(".variations select"),c={},d=0,e=0;return b.each(function(){var b=a(this).data("attribute_name")||a(this).attr("name"),f=a(this).val()||"";f.length>0&&e++,d++,c[b]=f}),{count:d,chosenCount:e,data:c}},generate_cart:function(){var c={nonce:wc_stripe_apple_pay_single_params.stripe_apple_pay_cart_nonce,qty:a(".quantity .qty").val(),attributes:a(".variations_form").length?b.get_attributes().data:[]};return a.ajax({type:"POST",data:c,url:b.getAjaxURL("generate_apple_pay_single"),success:function(a){wc_stripe_apple_pay_single_params.total=a.total,wc_stripe_apple_pay_single_params.line_items=a.line_items}})}};b.init()});
assets/js/stripe-apple-pay.js ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global wc_stripe_apple_pay_params, Stripe */
2
+ Stripe.setPublishableKey( wc_stripe_apple_pay_params.key );
3
+
4
+ jQuery( function( $ ) {
5
+ 'use strict';
6
+
7
+ /**
8
+ * Object to handle Stripe payment forms.
9
+ */
10
+ var wc_stripe_apple_pay = {
11
+ /**
12
+ * Get WC AJAX endpoint URL.
13
+ *
14
+ * @param {String} endpoint Endpoint.
15
+ * @return {String}
16
+ */
17
+ getAjaxURL: function( endpoint ) {
18
+ return wc_stripe_apple_pay_params.ajaxurl
19
+ .toString()
20
+ .replace( '%%endpoint%%', 'wc_stripe_' + endpoint );
21
+ },
22
+
23
+ /**
24
+ * Initialize event handlers and UI state.
25
+ */
26
+ init: function() {
27
+ Stripe.applePay.checkAvailability( function( available ) {
28
+ if ( available ) {
29
+ $( '.apple-pay-button' ).show();
30
+ // This is so it is centered on the checkout page.
31
+ $( '.woocommerce-checkout .apple-pay-button' ).css( 'visibility', 'visible' );
32
+ $( '.apple-pay-button-checkout-separator' ).show();
33
+
34
+ wc_stripe_apple_pay.generate_cart();
35
+ }
36
+ });
37
+
38
+ $( document.body ).on( 'click', '.apple-pay-button', function( e ) {
39
+ e.preventDefault();
40
+
41
+ var paymentRequest = {
42
+ countryCode: wc_stripe_apple_pay_params.country_code,
43
+ currencyCode: wc_stripe_apple_pay_params.currency_code,
44
+ total: {
45
+ label: wc_stripe_apple_pay_params.label,
46
+ amount: wc_stripe_apple_pay_params.total
47
+ },
48
+ lineItems: wc_stripe_apple_pay_params.line_items,
49
+ requiredBillingContactFields: ['postalAddress'],
50
+ requiredShippingContactFields: 'yes' === wc_stripe_apple_pay_params.needs_shipping ? ['postalAddress', 'phone', 'email', 'name'] : ['phone', 'email', 'name']
51
+ };
52
+
53
+ var applePaySession = Stripe.applePay.buildSession( paymentRequest, function( result, completion ) {
54
+ var data = {
55
+ 'nonce': wc_stripe_apple_pay_params.stripe_apple_pay_nonce,
56
+ 'result': result
57
+ };
58
+
59
+ $.ajax({
60
+ type: 'POST',
61
+ data: data,
62
+ url: wc_stripe_apple_pay.getAjaxURL( 'apple_pay' ),
63
+ success: function( response ) {
64
+ if ( 'true' === response.success ) {
65
+ completion( ApplePaySession.STATUS_SUCCESS );
66
+ window.location.href = response.redirect;
67
+ }
68
+
69
+ if ( 'false' === response.success ) {
70
+ completion( ApplePaySession.STATUS_FAILURE );
71
+
72
+ $( '.apple-pay-button' ).before( '<p class="woocommerce-error wc-stripe-apple-pay-error">' + response.msg + '</p>' );
73
+
74
+ // Scroll to error so user can see it.
75
+ $( document.body ).animate({ scrollTop: $( '.wc-stripe-apple-pay-error' ).offset().top }, 500 );
76
+ }
77
+ }
78
+ });
79
+ });
80
+
81
+ // If shipping is needed -- get shipping methods.
82
+ if ( 'yes' === wc_stripe_apple_pay_params.needs_shipping ) {
83
+ // After the shipping contact/address has been selected
84
+ applePaySession.onshippingcontactselected = function( shipping ) {
85
+ var data = {
86
+ 'nonce': wc_stripe_apple_pay_params.stripe_apple_pay_get_shipping_methods_nonce,
87
+ 'address': shipping.shippingContact
88
+ };
89
+
90
+ $.ajax({
91
+ type: 'POST',
92
+ data: data,
93
+ url: wc_stripe_apple_pay.getAjaxURL( 'apple_pay_get_shipping_methods' ),
94
+ success: function( response ) {
95
+ var total = {
96
+ 'label': wc_stripe_apple_pay_params.label,
97
+ 'amount': response.total
98
+ };
99
+
100
+ if ( 'true' === response.success ) {
101
+ applePaySession.completeShippingContactSelection( ApplePaySession.STATUS_SUCCESS, response.shipping_methods, total, response.line_items );
102
+ }
103
+
104
+ if ( 'false' === response.success ) {
105
+ applePaySession.completeShippingContactSelection( ApplePaySession.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS, response.shipping_methods, total, response.line_items );
106
+ }
107
+ }
108
+ });
109
+ };
110
+
111
+ // After the shipping method has been selected
112
+ applePaySession.onshippingmethodselected = function( event ) {
113
+ var data = {
114
+ 'nonce': wc_stripe_apple_pay_params.stripe_apple_pay_update_shipping_method_nonce,
115
+ 'selected_shipping_method': event.shippingMethod
116
+ };
117
+
118
+ $.ajax({
119
+ type: 'POST',
120
+ data: data,
121
+ url: wc_stripe_apple_pay.getAjaxURL( 'apple_pay_update_shipping_method' ),
122
+ success: function( response ) {
123
+ var newTotal = {
124
+ 'label': wc_stripe_apple_pay_params.label,
125
+ 'amount': parseFloat( response.total ).toFixed(2)
126
+ };
127
+
128
+ if ( 'true' === response.success ) {
129
+ applePaySession.completeShippingMethodSelection( ApplePaySession.STATUS_SUCCESS, newTotal, response.line_items );
130
+ }
131
+
132
+ if ( 'false' === response.success ) {
133
+ applePaySession.completeShippingMethodSelection( ApplePaySession.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS, newTotal, response.line_items );
134
+ }
135
+ }
136
+ });
137
+ };
138
+ }
139
+
140
+ applePaySession.begin();
141
+ });
142
+ },
143
+
144
+ generate_cart: function() {
145
+ var data = {
146
+ 'nonce': wc_stripe_apple_pay_params.stripe_apple_pay_cart_nonce
147
+ };
148
+
149
+ $.ajax({
150
+ type: 'POST',
151
+ data: data,
152
+ url: wc_stripe_apple_pay.getAjaxURL( 'generate_apple_pay_cart' ),
153
+ success: function( response ) {
154
+ wc_stripe_apple_pay_params.total = response.total;
155
+ wc_stripe_apple_pay_params.line_items = response.line_items;
156
+ }
157
+ });
158
+ }
159
+ };
160
+
161
+ wc_stripe_apple_pay.init();
162
+
163
+ // We need to refresh Apple Pay data when total is updated.
164
+ $( document.body ).on( 'updated_cart_totals', function() {
165
+ wc_stripe_apple_pay.init();
166
+ });
167
+
168
+ // We need to refresh Apple Pay data when total is updated.
169
+ $( document.body ).on( 'updated_checkout', function() {
170
+ wc_stripe_apple_pay.init();
171
+ });
172
+ });
assets/js/stripe-apple-pay.min.js ADDED
@@ -0,0 +1 @@
 
1
+ Stripe.setPublishableKey(wc_stripe_apple_pay_params.key),jQuery(function(a){"use strict";var b={getAjaxURL:function(a){return wc_stripe_apple_pay_params.ajaxurl.toString().replace("%%endpoint%%","wc_stripe_"+a)},init:function(){Stripe.applePay.checkAvailability(function(c){c&&(a(".apple-pay-button").show(),a(".woocommerce-checkout .apple-pay-button").css("visibility","visible"),a(".apple-pay-button-checkout-separator").show(),b.generate_cart())}),a(document.body).on("click",".apple-pay-button",function(c){c.preventDefault();var d={countryCode:wc_stripe_apple_pay_params.country_code,currencyCode:wc_stripe_apple_pay_params.currency_code,total:{label:wc_stripe_apple_pay_params.label,amount:wc_stripe_apple_pay_params.total},lineItems:wc_stripe_apple_pay_params.line_items,requiredBillingContactFields:["postalAddress"],requiredShippingContactFields:"yes"===wc_stripe_apple_pay_params.needs_shipping?["postalAddress","phone","email","name"]:["phone","email","name"]},e=Stripe.applePay.buildSession(d,function(c,d){var e={nonce:wc_stripe_apple_pay_params.stripe_apple_pay_nonce,result:c};a.ajax({type:"POST",data:e,url:b.getAjaxURL("apple_pay"),success:function(b){"true"===b.success&&(d(ApplePaySession.STATUS_SUCCESS),window.location.href=b.redirect),"false"===b.success&&(d(ApplePaySession.STATUS_FAILURE),a(".apple-pay-button").before('<p class="woocommerce-error wc-stripe-apple-pay-error">'+b.msg+"</p>"),a(document.body).animate({scrollTop:a(".wc-stripe-apple-pay-error").offset().top},500))}})});"yes"===wc_stripe_apple_pay_params.needs_shipping&&(e.onshippingcontactselected=function(c){var d={nonce:wc_stripe_apple_pay_params.stripe_apple_pay_get_shipping_methods_nonce,address:c.shippingContact};a.ajax({type:"POST",data:d,url:b.getAjaxURL("apple_pay_get_shipping_methods"),success:function(a){var b={label:wc_stripe_apple_pay_params.label,amount:a.total};"true"===a.success&&e.completeShippingContactSelection(ApplePaySession.STATUS_SUCCESS,a.shipping_methods,b,a.line_items),"false"===a.success&&e.completeShippingContactSelection(ApplePaySession.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,a.shipping_methods,b,a.line_items)}})},e.onshippingmethodselected=function(c){var d={nonce:wc_stripe_apple_pay_params.stripe_apple_pay_update_shipping_method_nonce,selected_shipping_method:c.shippingMethod};a.ajax({type:"POST",data:d,url:b.getAjaxURL("apple_pay_update_shipping_method"),success:function(a){var b={label:wc_stripe_apple_pay_params.label,amount:parseFloat(a.total).toFixed(2)};"true"===a.success&&e.completeShippingMethodSelection(ApplePaySession.STATUS_SUCCESS,b,a.line_items),"false"===a.success&&e.completeShippingMethodSelection(ApplePaySession.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,b,a.line_items)}})}),e.begin()})},generate_cart:function(){var c={nonce:wc_stripe_apple_pay_params.stripe_apple_pay_cart_nonce};a.ajax({type:"POST",data:c,url:b.getAjaxURL("generate_apple_pay_cart"),success:function(a){wc_stripe_apple_pay_params.total=a.total,wc_stripe_apple_pay_params.line_items=a.line_items}})}};b.init(),a(document.body).on("updated_cart_totals",function(){b.init()}),a(document.body).on("updated_checkout",function(){b.init()})});
assets/js/{stripe_checkout.js → stripe-checkout.js} RENAMED
File without changes
assets/js/{stripe_checkout.min.js → stripe-checkout.min.js} RENAMED
File without changes
assets/js/stripe.js CHANGED
@@ -3,7 +3,7 @@ Stripe.setPublishableKey( wc_stripe_params.key );
3
 
4
  jQuery( function( $ ) {
5
  'use strict';
6
-
7
  /* Open and close for legacy class */
8
  $( 'form.checkout, form#order_review' ).on( 'change', 'input[name="wc-stripe-payment-token"]', function() {
9
  if ( 'new' === $( '.stripe-legacy-payment-fields input[name="wc-stripe-payment-token"]:checked' ).val() ) {
@@ -112,8 +112,8 @@ jQuery( function( $ ) {
112
  message = wc_stripe_params[ responseObject.response.error.code ];
113
  }
114
 
115
- $( '.woocommerce-error, .stripe_token' ).remove();
116
- $( '#stripe-card-number' ).closest( 'p' ).before( '<ul class="woocommerce_error woocommerce-error"><li>' + message + '</li></ul>' );
117
  wc_stripe_form.unblock();
118
  },
119
 
@@ -162,7 +162,7 @@ jQuery( function( $ ) {
162
  },
163
 
164
  onCCFormChange: function() {
165
- $( '.woocommerce-error, .stripe_token' ).remove();
166
  },
167
 
168
  onStripeResponse: function( status, response ) {
3
 
4
  jQuery( function( $ ) {
5
  'use strict';
6
+
7
  /* Open and close for legacy class */
8
  $( 'form.checkout, form#order_review' ).on( 'change', 'input[name="wc-stripe-payment-token"]', function() {
9
  if ( 'new' === $( '.stripe-legacy-payment-fields input[name="wc-stripe-payment-token"]:checked' ).val() ) {
112
  message = wc_stripe_params[ responseObject.response.error.code ];
113
  }
114
 
115
+ $( '.wc-stripe-error, .stripe_token' ).remove();
116
+ $( '#stripe-card-number' ).closest( 'p' ).before( '<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li>' + message + '</li></ul>' );
117
  wc_stripe_form.unblock();
118
  },
119
 
162
  },
163
 
164
  onCCFormChange: function() {
165
+ $( '.wc-stripe-error, .stripe_token' ).remove();
166
  },
167
 
168
  onStripeResponse: function( status, response ) {
assets/js/stripe.min.js CHANGED
@@ -1 +1 @@
1
- Stripe.setPublishableKey(wc_stripe_params.key),jQuery(function(a){"use strict";a("form.checkout, form#order_review").on("change",'input[name="wc-stripe-payment-token"]',function(){"new"===a('.stripe-legacy-payment-fields input[name="wc-stripe-payment-token"]:checked').val()?a(".stripe-legacy-payment-fields #stripe-payment-data").slideDown(200):a(".stripe-legacy-payment-fields #stripe-payment-data").slideUp(200)});var b={init:function(){a("form.woocommerce-checkout").length&&(this.form=a("form.woocommerce-checkout")),a("form.woocommerce-checkout").on("checkout_place_order_stripe",this.onSubmit),a("form#order_review").length&&(this.form=a("form#order_review")),a("form#order_review").on("submit",this.onSubmit),a("form#add_payment_method").length&&(this.form=a("form#add_payment_method")),a("form#add_payment_method").on("submit",this.onSubmit),a(document).on("change","#wc-stripe-cc-form :input",this.onCCFormChange).on("stripeError",this.onError).on("checkout_error",this.clearToken)},isStripeChosen:function(){return a("#payment_method_stripe").is(":checked")&&(!a('input[name="wc-stripe-payment-token"]:checked').length||"new"===a('input[name="wc-stripe-payment-token"]:checked').val())},hasToken:function(){return 0<a("input.stripe_token").length},block:function(){b.form.block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){b.form.unblock()},onError:function(c,d){var e=d.response.error.message;("invalid_request_error"===d.response.error.type||"api_connection_error"===d.response.error.type||"api_error"===d.response.error.type||"authentication_error"===d.response.error.type||"rate_limit_error"===d.response.error.type)&&(e=wc_stripe_params.invalid_request_error),"card_error"===d.response.error.type&&wc_stripe_params.hasOwnProperty(d.response.error.code)&&(e=wc_stripe_params[d.response.error.code]),a(".woocommerce-error, .stripe_token").remove(),a("#stripe-card-number").closest("p").before('<ul class="woocommerce_error woocommerce-error"><li>'+e+"</li></ul>"),b.unblock()},onSubmit:function(c){if(b.isStripeChosen()&&!b.hasToken()){c.preventDefault(),b.block();var d=a("#stripe-card-number").val(),e=a("#stripe-card-cvc").val(),f=a("#stripe-card-expiry").payment("cardExpiryVal"),g=a("#billing_first_name").length?a("#billing_first_name").val():wc_stripe_params.billing_first_name,h=a("#billing_last_name").length?a("#billing_last_name").val():wc_stripe_params.billing_last_name,i={number:d,cvc:e,exp_month:parseInt(f.month,10)||0,exp_year:parseInt(f.year,10)||0};return g&&h&&(i.name=g+" "+h),a("#billing_address_1").length>0?(i.address_line1=a("#billing_address_1").val(),i.address_line2=a("#billing_address_2").val(),i.address_state=a("#billing_state").val(),i.address_city=a("#billing_city").val(),i.address_zip=a("#billing_postcode").val(),i.address_country=a("#billing_country").val()):wc_stripe_params.billing_address_1&&(i.address_line1=wc_stripe_params.billing_address_1,i.address_line2=wc_stripe_params.billing_address_2,i.address_state=wc_stripe_params.billing_state,i.address_city=wc_stripe_params.billing_city,i.address_zip=wc_stripe_params.billing_postcode,i.address_country=wc_stripe_params.billing_country),Stripe.createToken(i,b.onStripeResponse),!1}},onCCFormChange:function(){a(".woocommerce-error, .stripe_token").remove()},onStripeResponse:function(c,d){if(d.error)a(document).trigger("stripeError",{response:d});else{if("no"===wc_stripe_params.allow_prepaid_card&&"prepaid"===d.card.funding)return d.error={message:wc_stripe_params.no_prepaid_card_msg},a(document).trigger("stripeError",{response:d}),!1;var e=d.id;b.form.append("<input type='hidden' class='stripe_token' name='stripe_token' value='"+e+"'/>"),b.form.submit()}},clearToken:function(){a(".stripe_token").remove()}};b.init()});
1
+ Stripe.setPublishableKey(wc_stripe_params.key),jQuery(function(a){"use strict";a("form.checkout, form#order_review").on("change",'input[name="wc-stripe-payment-token"]',function(){"new"===a('.stripe-legacy-payment-fields input[name="wc-stripe-payment-token"]:checked').val()?a(".stripe-legacy-payment-fields #stripe-payment-data").slideDown(200):a(".stripe-legacy-payment-fields #stripe-payment-data").slideUp(200)});var b={init:function(){a("form.woocommerce-checkout").length&&(this.form=a("form.woocommerce-checkout")),a("form.woocommerce-checkout").on("checkout_place_order_stripe",this.onSubmit),a("form#order_review").length&&(this.form=a("form#order_review")),a("form#order_review").on("submit",this.onSubmit),a("form#add_payment_method").length&&(this.form=a("form#add_payment_method")),a("form#add_payment_method").on("submit",this.onSubmit),a(document).on("change","#wc-stripe-cc-form :input",this.onCCFormChange).on("stripeError",this.onError).on("checkout_error",this.clearToken)},isStripeChosen:function(){return a("#payment_method_stripe").is(":checked")&&(!a('input[name="wc-stripe-payment-token"]:checked').length||"new"===a('input[name="wc-stripe-payment-token"]:checked').val())},hasToken:function(){return 0<a("input.stripe_token").length},block:function(){b.form.block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){b.form.unblock()},onError:function(c,d){var e=d.response.error.message;("invalid_request_error"===d.response.error.type||"api_connection_error"===d.response.error.type||"api_error"===d.response.error.type||"authentication_error"===d.response.error.type||"rate_limit_error"===d.response.error.type)&&(e=wc_stripe_params.invalid_request_error),"card_error"===d.response.error.type&&wc_stripe_params.hasOwnProperty(d.response.error.code)&&(e=wc_stripe_params[d.response.error.code]),a(".wc-stripe-error, .stripe_token").remove(),a("#stripe-card-number").closest("p").before('<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li>'+e+"</li></ul>"),b.unblock()},onSubmit:function(c){if(b.isStripeChosen()&&!b.hasToken()){c.preventDefault(),b.block();var d=a("#stripe-card-number").val(),e=a("#stripe-card-cvc").val(),f=a("#stripe-card-expiry").payment("cardExpiryVal"),g=a("#billing_first_name").length?a("#billing_first_name").val():wc_stripe_params.billing_first_name,h=a("#billing_last_name").length?a("#billing_last_name").val():wc_stripe_params.billing_last_name,i={number:d,cvc:e,exp_month:parseInt(f.month,10)||0,exp_year:parseInt(f.year,10)||0};return g&&h&&(i.name=g+" "+h),a("#billing_address_1").length>0?(i.address_line1=a("#billing_address_1").val(),i.address_line2=a("#billing_address_2").val(),i.address_state=a("#billing_state").val(),i.address_city=a("#billing_city").val(),i.address_zip=a("#billing_postcode").val(),i.address_country=a("#billing_country").val()):wc_stripe_params.billing_address_1&&(i.address_line1=wc_stripe_params.billing_address_1,i.address_line2=wc_stripe_params.billing_address_2,i.address_state=wc_stripe_params.billing_state,i.address_city=wc_stripe_params.billing_city,i.address_zip=wc_stripe_params.billing_postcode,i.address_country=wc_stripe_params.billing_country),Stripe.createToken(i,b.onStripeResponse),!1}},onCCFormChange:function(){a(".wc-stripe-error, .stripe_token").remove()},onStripeResponse:function(c,d){if(d.error)a(document).trigger("stripeError",{response:d});else{if("no"===wc_stripe_params.allow_prepaid_card&&"prepaid"===d.card.funding)return d.error={message:wc_stripe_params.no_prepaid_card_msg},a(document).trigger("stripeError",{response:d}),!1;var e=d.id;b.form.append("<input type='hidden' class='stripe_token' name='stripe_token' value='"+e+"'/>"),b.form.submit()}},clearToken:function(){a(".stripe_token").remove()}};b.init()});
includes/class-wc-gateway-stripe-addons.php CHANGED
@@ -77,16 +77,18 @@ class WC_Gateway_Stripe_Addons extends WC_Gateway_Stripe {
77
  protected function save_source( $order, $source ) {
78
  parent::save_source( $order, $source );
79
 
 
 
80
  // Also store it on the subscriptions being purchased or paid for in the order
81
- if ( function_exists( 'wcs_order_contains_subscription' ) && wcs_order_contains_subscription( $order->id ) ) {
82
- $subscriptions = wcs_get_subscriptions_for_order( $order->id );
83
- } elseif ( function_exists( 'wcs_order_contains_renewal' ) && wcs_order_contains_renewal( $order->id ) ) {
84
- $subscriptions = wcs_get_subscriptions_for_renewal_order( $order->id );
85
  } else {
86
  $subscriptions = array();
87
  }
88
 
89
- foreach( $subscriptions as $subscription ) {
90
  update_post_meta( $subscription->id, '_stripe_customer_id', $source->customer );
91
  update_post_meta( $subscription->id, '_stripe_card_id', $source->source );
92
  }
@@ -99,7 +101,7 @@ class WC_Gateway_Stripe_Addons extends WC_Gateway_Stripe {
99
  * @param string $stripe_token (default: '')
100
  * @param bool initial_payment
101
  */
102
- public function process_subscription_payment( $order = '', $amount = 0 ) {
103
  if ( $amount * 100 < WC_Stripe::get_minimum_amount() ) {
104
  return new WP_Error( 'stripe_error', sprintf( __( 'Sorry, the minimum allowed order total is %1$s to use this payment method.', 'woocommerce-gateway-stripe' ), wc_price( WC_Stripe::get_minimum_amount() / 100 ) ) );
105
  }
@@ -117,14 +119,15 @@ class WC_Gateway_Stripe_Addons extends WC_Gateway_Stripe {
117
  return new WP_Error( 'stripe_error', __( 'Customer not found', 'woocommerce-gateway-stripe' ) );
118
  }
119
 
120
- WC_Stripe::log( "Info: Begin processing subscription payment for order {$order->id} for the amount of {$amount}" );
 
121
 
122
  // Make the request
123
  $request = $this->generate_payment_request( $order, $source );
124
  $request['capture'] = 'true';
125
  $request['amount'] = $this->get_stripe_amount( $amount, $request['currency'] );
126
  $request['metadata'] = array(
127
- 'payment_type' => 'recurring'
128
  );
129
  $response = WC_Stripe_API::request( $request );
130
 
@@ -169,7 +172,7 @@ class WC_Gateway_Stripe_Addons extends WC_Gateway_Stripe {
169
  // Return thank you page redirect
170
  return array(
171
  'result' => 'success',
172
- 'redirect' => $this->get_return_url( $order )
173
  );
174
  } catch ( Exception $e ) {
175
  wc_add_notice( $e->getMessage(), 'error' );
@@ -210,7 +213,6 @@ class WC_Gateway_Stripe_Addons extends WC_Gateway_Stripe {
210
  break;
211
  }
212
  }
213
-
214
  } catch ( Exception $e ) {
215
  $order_note = sprintf( __( 'Stripe Transaction Failed (%s)', 'woocommerce-gateway-stripe' ), $e->getMessage() );
216
 
@@ -264,7 +266,8 @@ class WC_Gateway_Stripe_Addons extends WC_Gateway_Stripe {
264
  * @param object $order
265
  */
266
  public function remove_order_source_before_retry( $order ) {
267
- delete_post_meta( $order->id, '_stripe_card_id' );
 
268
  }
269
 
270
  /**
@@ -272,7 +275,8 @@ class WC_Gateway_Stripe_Addons extends WC_Gateway_Stripe {
272
  * @param object $order
273
  */
274
  public function remove_order_customer_before_retry( $order ) {
275
- delete_post_meta( $order->id, '_stripe_customer_id' );
 
276
  }
277
 
278
  /**
@@ -377,15 +381,31 @@ class WC_Gateway_Stripe_Addons extends WC_Gateway_Stripe {
377
  foreach ( $cards as $card ) {
378
  if ( $card->id === $stripe_card_id ) {
379
  $found_card = true;
380
- $payment_method_to_display = sprintf( __( 'Via %s card ending in %s', 'woocommerce-gateway-stripe' ), ( isset( $card->type ) ? $card->type : $card->brand ), $card->last4 );
381
  break;
382
  }
383
  }
384
  if ( ! $found_card ) {
385
- $payment_method_to_display = sprintf( __( 'Via %s card ending in %s', 'woocommerce-gateway-stripe' ), ( isset( $cards[0]->type ) ? $cards[0]->type : $cards[0]->brand ), $cards[0]->last4 );
386
  }
387
  }
388
 
389
  return $payment_method_to_display;
390
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  }
77
  protected function save_source( $order, $source ) {
78
  parent::save_source( $order, $source );
79
 
80
+ $order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
81
+
82
  // Also store it on the subscriptions being purchased or paid for in the order
83
+ if ( function_exists( 'wcs_order_contains_subscription' ) && wcs_order_contains_subscription( $order_id ) ) {
84
+ $subscriptions = wcs_get_subscriptions_for_order( $order_id );
85
+ } elseif ( function_exists( 'wcs_order_contains_renewal' ) && wcs_order_contains_renewal( $order_id ) ) {
86
+ $subscriptions = wcs_get_subscriptions_for_renewal_order( $order_id );
87
  } else {
88
  $subscriptions = array();
89
  }
90
 
91
+ foreach ( $subscriptions as $subscription ) {
92
  update_post_meta( $subscription->id, '_stripe_customer_id', $source->customer );
93
  update_post_meta( $subscription->id, '_stripe_card_id', $source->source );
94
  }
101
  * @param string $stripe_token (default: '')
102
  * @param bool initial_payment
103
  */
104
+ public function process_subscription_payment( $order = '', $amount = 0 ) {
105
  if ( $amount * 100 < WC_Stripe::get_minimum_amount() ) {
106
  return new WP_Error( 'stripe_error', sprintf( __( 'Sorry, the minimum allowed order total is %1$s to use this payment method.', 'woocommerce-gateway-stripe' ), wc_price( WC_Stripe::get_minimum_amount() / 100 ) ) );
107
  }
119
  return new WP_Error( 'stripe_error', __( 'Customer not found', 'woocommerce-gateway-stripe' ) );
120
  }
121
 
122
+ $order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
123
+ $this->log( "Info: Begin processing subscription payment for order {$order_id} for the amount of {$amount}" );
124
 
125
  // Make the request
126
  $request = $this->generate_payment_request( $order, $source );
127
  $request['capture'] = 'true';
128
  $request['amount'] = $this->get_stripe_amount( $amount, $request['currency'] );
129
  $request['metadata'] = array(
130
+ 'payment_type' => 'recurring',
131
  );
132
  $response = WC_Stripe_API::request( $request );
133
 
172
  // Return thank you page redirect
173
  return array(
174
  'result' => 'success',
175
+ 'redirect' => $this->get_return_url( $order ),
176
  );
177
  } catch ( Exception $e ) {
178
  wc_add_notice( $e->getMessage(), 'error' );
213
  break;
214
  }
215
  }
 
216
  } catch ( Exception $e ) {
217
  $order_note = sprintf( __( 'Stripe Transaction Failed (%s)', 'woocommerce-gateway-stripe' ), $e->getMessage() );
218
 
266
  * @param object $order
267
  */
268
  public function remove_order_source_before_retry( $order ) {
269
+ $order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
270
+ delete_post_meta( $order_id, '_stripe_card_id' );
271
  }
272
 
273
  /**
275
  * @param object $order
276
  */
277
  public function remove_order_customer_before_retry( $order ) {
278
+ $order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
279
+ delete_post_meta( $order_id, '_stripe_customer_id' );
280
  }
281
 
282
  /**
381
  foreach ( $cards as $card ) {
382
  if ( $card->id === $stripe_card_id ) {
383
  $found_card = true;
384
+ $payment_method_to_display = sprintf( __( 'Via %1$s card ending in %2$s', 'woocommerce-gateway-stripe' ), ( isset( $card->type ) ? $card->type : $card->brand ), $card->last4 );
385
  break;
386
  }
387
  }
388
  if ( ! $found_card ) {
389
+ $payment_method_to_display = sprintf( __( 'Via %1$s card ending in %2$s', 'woocommerce-gateway-stripe' ), ( isset( $cards[0]->type ) ? $cards[0]->type : $cards[0]->brand ), $cards[0]->last4 );
390
  }
391
  }
392
 
393
  return $payment_method_to_display;
394
  }
395
+
396
+ /**
397
+ * Logs
398
+ *
399
+ * @since 3.1.0
400
+ * @version 3.1.0
401
+ *
402
+ * @param string $message
403
+ */
404
+ public function log( $message ) {
405
+ $options = get_option( 'woocommerce_stripe_settings' );
406
+
407
+ if ( 'yes' === $options['logging'] ) {
408
+ WC_Stripe::log( $message );
409
+ }
410
+ }
411
  }
includes/class-wc-gateway-stripe.php CHANGED
@@ -17,6 +17,13 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
17
  */
18
  public $capture;
19
 
 
 
 
 
 
 
 
20
  /**
21
  * Checkout enabled
22
  *
@@ -73,6 +80,27 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
73
  */
74
  public $allow_remember_me;
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  /**
77
  * Is test mode active?
78
  *
@@ -111,7 +139,7 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
111
  'multiple_subscriptions',
112
  'pre-orders',
113
  'tokenization',
114
- 'add_payment_method'
115
  );
116
 
117
  // Load the form fields.
@@ -126,6 +154,7 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
126
  $this->enabled = $this->get_option( 'enabled' );
127
  $this->testmode = 'yes' === $this->get_option( 'testmode' );
128
  $this->capture = 'yes' === $this->get_option( 'capture', 'yes' );
 
129
  $this->stripe_checkout = 'yes' === $this->get_option( 'stripe_checkout' );
130
  $this->stripe_checkout_locale = $this->get_option( 'stripe_checkout_locale' );
131
  $this->stripe_checkout_image = $this->get_option( 'stripe_checkout_image', '' );
@@ -133,6 +162,9 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
133
  $this->secret_key = $this->testmode ? $this->get_option( 'test_secret_key' ) : $this->get_option( 'secret_key' );
134
  $this->publishable_key = $this->testmode ? $this->get_option( 'test_publishable_key' ) : $this->get_option( 'publishable_key' );
135
  $this->bitcoin = 'USD' === strtoupper( get_woocommerce_currency() ) && 'yes' === $this->get_option( 'stripe_bitcoin' );
 
 
 
136
  $this->logging = 'yes' === $this->get_option( 'logging' );
137
  $this->allow_remember_me = 'yes' === $this->get_option( 'allow_remember_me', 'no' );
138
 
@@ -147,8 +179,11 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
147
 
148
  WC_Stripe_API::set_secret_key( $this->secret_key );
149
 
 
 
150
  // Hooks.
151
  add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
 
152
  add_action( 'admin_notices', array( $this, 'admin_notices' ) );
153
  add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
154
  }
@@ -218,6 +253,108 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
218
  return $total;
219
  }
220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  /**
222
  * Check if SSL is enabled and notify the user
223
  */
@@ -226,6 +363,15 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
226
  return;
227
  }
228
 
 
 
 
 
 
 
 
 
 
229
  // Show message if enabled and FORCE SSL is disabled and WordpressHTTPS plugin is not detected.
230
  if ( ( function_exists( 'wc_site_is_https' ) && ! wc_site_is_https() ) && ( 'no' === get_option( 'woocommerce_force_ssl_checkout' ) && ! class_exists( 'WordPressHTTPS' ) ) ) {
231
  echo '<div class="error stripe-ssl-message"><p>' . sprintf( __( 'Stripe is enabled, but the <a href="%s">force SSL option</a> is disabled; your checkout may not be secure! Please enable SSL and ensure your server has a valid SSL certificate - Stripe will only work in test mode.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout' ) ) . '</p></div>';
@@ -253,61 +399,6 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
253
  */
254
  public function init_form_fields() {
255
  $this->form_fields = include( 'settings-stripe.php' );
256
-
257
- wc_enqueue_js( "
258
- jQuery( function( $ ) {
259
- $( document.body ).on( 'change', '#woocommerce_stripe_testmode', function() {
260
- var test_secret_key = $( '#woocommerce_stripe_test_secret_key' ).parents( 'tr' ).eq( 0 ),
261
- test_publishable_key = $( '#woocommerce_stripe_test_publishable_key' ).parents( 'tr' ).eq( 0 ),
262
- live_secret_key = $( '#woocommerce_stripe_secret_key' ).parents( 'tr' ).eq( 0 ),
263
- live_publishable_key = $( '#woocommerce_stripe_publishable_key' ).parents( 'tr' ).eq( 0 );
264
-
265
- if ( $( this ).is( ':checked' ) ) {
266
- test_secret_key.show();
267
- test_publishable_key.show();
268
- live_secret_key.hide();
269
- live_publishable_key.hide();
270
- } else {
271
- test_secret_key.hide();
272
- test_publishable_key.hide();
273
- live_secret_key.show();
274
- live_publishable_key.show();
275
- }
276
- } );
277
-
278
- $( '#woocommerce_stripe_testmode' ).change();
279
-
280
- $( '#woocommerce_stripe_stripe_checkout' ).change( function() {
281
- if ( $( this ).is( ':checked' ) ) {
282
- $( '#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image, #woocommerce_stripe_allow_remember_me' ).closest( 'tr' ).show();
283
- } else {
284
- $( '#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image, #woocommerce_stripe_allow_remember_me' ).closest( 'tr' ).hide();
285
- }
286
- }).change();
287
-
288
- $( '#woocommerce_stripe_secret_key, #woocommerce_stripe_publishable_key' ).change(function(){
289
- var value = $( this ).val();
290
-
291
- if ( value.indexOf( '_test_' ) >= 0 ) {
292
- $( this ).css( 'border-color', 'red' ).after( '<span class=\"description stripe-error-description\" style=\"color:red; display:block;\">" . __( 'This is not a valid live key. Live keys start with "sk_live_" and "pk_live_".', 'woocommerce-gateway-stripe' ) . "</span>' );
293
- } else {
294
- $( this ).css( 'border-color', '' );
295
- $( '.stripe-error-description', $( this ).parent() ).remove();
296
- }
297
- }).change();
298
-
299
- $( '#woocommerce_stripe_test_secret_key, #woocommerce_stripe_test_publishable_key' ).change(function(){
300
- var value = $( this ).val();
301
-
302
- if ( value.indexOf( '_live_' ) >= 0 ) {
303
- $( this ).css( 'border-color', 'red' ).after( '<span class=\"description stripe-error-description\" style=\"color:red; display:block;\">" . __( 'This is not a valid test key. Test keys start with "sk_test_" and "pk_test_".', 'woocommerce-gateway-stripe' ) . "</span>' );
304
- } else {
305
- $( this ).css( 'border-color', '' );
306
- $( '.stripe-error-description', $( this ).parent() ).remove();
307
- }
308
- }).change();
309
- });
310
- " );
311
  }
312
 
313
  /**
@@ -343,7 +434,7 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
343
  data-description=""
344
  data-email="' . esc_attr( $user_email ) . '"
345
  data-amount="' . esc_attr( $this->get_stripe_amount( $total ) ) . '"
346
- data-name="' . esc_attr( get_bloginfo( 'name', 'display' ) ) . '"
347
  data-currency="' . esc_attr( strtolower( get_woocommerce_currency() ) ) . '"
348
  data-image="' . esc_attr( $this->stripe_checkout_image ) . '"
349
  data-bitcoin="' . esc_attr( $this->bitcoin ? 'true' : 'false' ) . '"
@@ -361,7 +452,7 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
361
 
362
  if ( ! $this->stripe_checkout ) {
363
  $this->form();
364
-
365
  if ( $display_tokenization ) {
366
  $this->save_payment_method_checkbox();
367
  }
@@ -391,7 +482,38 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
391
  'missing' => __( 'There is no card on a customer that is being charged.', 'woocommerce-gateway-stripe' ),
392
  'processing_error' => __( 'An error occurred while processing the card.', 'woocommerce-gateway-stripe' ),
393
  'invalid_request_error' => __( 'Could not find payment information.', 'woocommerce-gateway-stripe' ),
394
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  }
396
 
397
  /**
@@ -402,11 +524,15 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
402
  * @access public
403
  */
404
  public function payment_scripts() {
 
 
 
 
405
  $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
406
-
407
  if ( $this->stripe_checkout ) {
408
- wp_enqueue_script( 'stripe', 'https://checkout.stripe.com/v2/checkout.js', '', '2.0', true );
409
- wp_enqueue_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe_checkout' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'stripe' ), WC_STRIPE_VERSION, true );
410
  } else {
411
  wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
412
  wp_enqueue_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'jquery-payment', 'stripe' ), WC_STRIPE_VERSION, true );
@@ -423,14 +549,14 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
423
  $order_id = wc_get_order_id_by_order_key( urldecode( $_GET['key'] ) );
424
  $order = wc_get_order( $order_id );
425
 
426
- $stripe_params['billing_first_name'] = $order->billing_first_name;
427
- $stripe_params['billing_last_name'] = $order->billing_last_name;
428
- $stripe_params['billing_address_1'] = $order->billing_address_1;
429
- $stripe_params['billing_address_2'] = $order->billing_address_2;
430
- $stripe_params['billing_state'] = $order->billing_state;
431
- $stripe_params['billing_city'] = $order->billing_city;
432
- $stripe_params['billing_postcode'] = $order->billing_postcode;
433
- $stripe_params['billing_country'] = $order->billing_country;
434
  }
435
 
436
  $stripe_params['no_prepaid_card_msg'] = __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' );
@@ -451,17 +577,28 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
451
  */
452
  protected function generate_payment_request( $order, $source ) {
453
  $post_data = array();
454
- $post_data['currency'] = strtolower( $order->get_order_currency() ? $order->get_order_currency() : get_woocommerce_currency() );
455
  $post_data['amount'] = $this->get_stripe_amount( $order->get_total(), $post_data['currency'] );
456
- $post_data['description'] = sprintf( __( '%s - Order %s', 'woocommerce-gateway-stripe' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), $order->get_order_number() );
457
  $post_data['capture'] = $this->capture ? 'true' : 'false';
458
 
459
- if ( ! empty( $order->billing_email ) && apply_filters( 'wc_stripe_send_stripe_receipt', false ) ) {
460
- $post_data['receipt_email'] = $order->billing_email;
 
 
 
 
461
  }
462
 
463
  $post_data['expand[]'] = 'balance_transaction';
464
 
 
 
 
 
 
 
 
465
  if ( $source->customer ) {
466
  $post_data['customer'] = $source->customer;
467
  }
@@ -469,7 +606,7 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
469
  if ( $source->source ) {
470
  $post_data['source'] = $source->source;
471
  }
472
-
473
  /**
474
  * Filter the return value of the WC_Payment_Gateway_CC::generate_payment_request.
475
  *
@@ -507,16 +644,14 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
507
  if ( is_wp_error( $stripe_source ) ) {
508
  throw new Exception( $stripe_source->get_error_message() );
509
  }
510
-
511
  } else {
512
  // Not saving token, so don't define customer either.
513
  $stripe_source = $stripe_token;
514
  $stripe_customer = false;
515
  }