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
  }
516
- }
 
517
 
518
- // Use an existing token, and then process the payment
519
- elseif ( isset( $_POST['wc-stripe-payment-token'] ) && 'new' !== $_POST['wc-stripe-payment-token'] ) {
520
  $token_id = wc_clean( $_POST['wc-stripe-payment-token'] );
521
  $token = WC_Payment_Tokens::get( $token_id );
522
 
@@ -552,10 +687,13 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
552
  $token_id = false;
553
 
554
  if ( $order ) {
555
- if ( $meta_value = get_post_meta( $order->id, '_stripe_customer_id', true ) ) {
 
 
556
  $stripe_customer->set_id( $meta_value );
557
  }
558
- if ( $meta_value = get_post_meta( $order->id, '_stripe_card_id', true ) ) {
 
559
  $stripe_source = $meta_value;
560
  }
561
  }
@@ -594,11 +732,12 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
594
 
595
  // Handle payment.
596
  if ( $order->get_total() > 0 ) {
 
597
  if ( $order->get_total() * 100 < WC_Stripe::get_minimum_amount() ) {
598
  throw new Exception( 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 ) ) );
599
  }
600
 
601
- WC_Stripe::log( "Info: Begin processing payment for order $order_id for the amount of {$order->get_total()}" );
602
 
603
  // Make the request.
604
  $response = WC_Stripe_API::request( $this->generate_payment_request( $order, $source ) );
@@ -612,11 +751,18 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
612
  } elseif ( 'source' === $response->get_error_code() && $source->token_id ) {
613
  $token = WC_Payment_Tokens::get( $source->token_id );
614
  $token->delete();
615
- throw new Exception( __( 'This card is no longer available and has been removed.', 'woocommerce-gateway-stripe' ) );
 
 
616
  }
 
617
  $localized_messages = $this->get_localized_messages();
618
 
619
- throw new Exception( ( isset( $localized_messages[ $response->get_error_code() ] ) ? $localized_messages[ $response->get_error_code() ] : $response->get_error_message() ) );
 
 
 
 
620
  }
621
 
622
  // Process valid response.
@@ -633,12 +779,12 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
633
  // Return thank you page redirect.
634
  return array(
635
  'result' => 'success',
636
- 'redirect' => $this->get_return_url( $order )
637
  );
638
 
639
  } catch ( Exception $e ) {
640
  wc_add_notice( $e->getMessage(), 'error' );
641
- WC_Stripe::log( sprintf( __( 'Error: %s', 'woocommerce-gateway-stripe' ), $e->getMessage() ) );
642
 
643
  if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
644
  $this->send_failed_order_email( $order_id );
@@ -648,7 +794,7 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
648
 
649
  return array(
650
  'result' => 'fail',
651
- 'redirect' => ''
652
  );
653
  }
654
  }
@@ -660,12 +806,14 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
660
  * @param stdClass $source Source information.
661
  */
662
  protected function save_source( $order, $source ) {
 
 
663
  // Store source in the order.
664
  if ( $source->customer ) {
665
- update_post_meta( $order->id, '_stripe_customer_id', $source->customer );
666
  }
667
  if ( $source->source ) {
668
- update_post_meta( $order->id, '_stripe_card_id', $source->source );
669
  }
670
  }
671
 
@@ -673,20 +821,22 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
673
  * Store extra meta data for an order from a Stripe Response.
674
  */
675
  public function process_response( $response, $order ) {
676
- WC_Stripe::log( "Processing response: " . print_r( $response, true ) );
 
 
677
 
678
  // Store charge data
679
- update_post_meta( $order->id, '_stripe_charge_id', $response->id );
680
- update_post_meta( $order->id, '_stripe_charge_captured', $response->captured ? 'yes' : 'no' );
681
 
682
  // Store other data such as fees
683
  if ( isset( $response->balance_transaction ) && isset( $response->balance_transaction->fee ) ) {
684
  // Fees and Net needs to both come from Stripe to be accurate as the returned
685
  // values are in the local currency of the Stripe account, not from WC.
686
- $fee = ! empty( $response->balance_transaction->fee ) ? number_format( $response->balance_transaction->fee / 100, 2, '.', '' ) : 0;
687
- $net = ! empty( $response->balance_transaction->net ) ? number_format( $response->balance_transaction->net / 100, 2, '.', '' ) : 0;
688
- update_post_meta( $order->id, 'Stripe Fee', $fee );
689
- update_post_meta( $order->id, 'Net Revenue From Stripe', $net );
690
  }
691
 
692
  if ( $response->captured ) {
@@ -694,17 +844,17 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
694
 
695
  $message = sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $response->id );
696
  $order->add_order_note( $message );
697
- WC_Stripe::log( 'Success: ' . $message );
698
 
699
  } else {
700
- add_post_meta( $order->id, '_transaction_id', $response->id, true );
701
 
702
  if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
703
- $order->reduce_order_stock();
704
  }
705
 
706
  $order->update_status( 'on-hold', sprintf( __( 'Stripe charge authorized (Charge ID: %s). Process order to take payment, or cancel to remove the pre-authorization.', 'woocommerce-gateway-stripe' ), $response->id ) );
707
- WC_Stripe::log( "Successful auth: $response->id" );
708
  }
709
 
710
  return $response;
@@ -770,17 +920,17 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
770
  );
771
  }
772
 
773
- WC_Stripe::log( "Info: Beginning refund for order $order_id for the amount of {$amount}" );
774
 
775
  $response = WC_Stripe_API::request( $body, 'charges/' . $order->get_transaction_id() . '/refunds' );
776
 
777
  if ( is_wp_error( $response ) ) {
778
- WC_Stripe::log( "Error: " . $response->get_error_message() );
779
  return $response;
780
  } elseif ( ! empty( $response->id ) ) {
781
- $refund_message = sprintf( __( 'Refunded %s - Refund ID: %s - Reason: %s', 'woocommerce-gateway-stripe' ), wc_price( $response->amount / 100 ), $response->id, $reason );
782
  $order->add_order_note( $refund_message );
783
- WC_Stripe::log( "Success: " . html_entity_decode( strip_tags( $refund_message ) ) );
784
  return true;
785
  }
786
  }
@@ -799,4 +949,18 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
799
  $emails['WC_Email_Failed_Order']->trigger( $order_id );
800
  }
801
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
802
  }
17
  */
18
  public $capture;
19
 
20
+ /**
21
+ * Alternate credit card statement name
22
+ *
23
+ * @var bool
24
+ */
25
+ public $statement_descriptor;
26
+
27
  /**
28
  * Checkout enabled
29
  *
80
  */
81
  public $allow_remember_me;
82
 
83
+ /**
84
+ * Do we accept Apple Pay?
85
+ *
86
+ * @var bool
87
+ */
88
+ public $apple_pay;
89
+
90
+ /**
91
+ * Apple Pay Domain Set.
92
+ *
93
+ * @var bool
94
+ */
95
+ public $apple_pay_domain_set;
96
+
97
+ /**
98
+ * Apple Pay button style.
99
+ *
100
+ * @var bool
101
+ */
102
+ public $apple_pay_button;
103
+
104
  /**
105
  * Is test mode active?
106
  *
139
  'multiple_subscriptions',
140
  'pre-orders',
141
  'tokenization',
142
+ 'add_payment_method',
143
  );
144
 
145
  // Load the form fields.
154
  $this->enabled = $this->get_option( 'enabled' );
155
  $this->testmode = 'yes' === $this->get_option( 'testmode' );
156
  $this->capture = 'yes' === $this->get_option( 'capture', 'yes' );
157
+ $this->statement_descriptor = $this->get_option( 'statement_descriptor', wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ) );
158
  $this->stripe_checkout = 'yes' === $this->get_option( 'stripe_checkout' );
159
  $this->stripe_checkout_locale = $this->get_option( 'stripe_checkout_locale' );
160
  $this->stripe_checkout_image = $this->get_option( 'stripe_checkout_image', '' );
162
  $this->secret_key = $this->testmode ? $this->get_option( 'test_secret_key' ) : $this->get_option( 'secret_key' );
163
  $this->publishable_key = $this->testmode ? $this->get_option( 'test_publishable_key' ) : $this->get_option( 'publishable_key' );
164
  $this->bitcoin = 'USD' === strtoupper( get_woocommerce_currency() ) && 'yes' === $this->get_option( 'stripe_bitcoin' );
165
+ $this->apple_pay = 'yes' === $this->get_option( 'apple_pay', 'yes' );
166
+ $this->apple_pay_domain_set = 'yes' === $this->get_option( 'apple_pay_domain_set', 'no' );
167
+ $this->apple_pay_button = $this->get_option( 'apple_pay_button', 'black' );
168
  $this->logging = 'yes' === $this->get_option( 'logging' );
169
  $this->allow_remember_me = 'yes' === $this->get_option( 'allow_remember_me', 'no' );
170
 
179
 
180
  WC_Stripe_API::set_secret_key( $this->secret_key );
181
 
182
+ $this->init_apple_pay();
183
+
184
  // Hooks.
185
  add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
186
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
187
  add_action( 'admin_notices', array( $this, 'admin_notices' ) );
188
  add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
189
  }
253
  return $total;
254
  }
255
 
256
+ /**
257
+ * Initializes Apple Pay process on settings page.
258
+ *
259
+ * @since 3.1.0
260
+ * @version 3.1.0
261
+ */
262
+ public function init_apple_pay() {
263
+ if (
264
+ is_admin() &&
265
+ isset( $_GET['page'] ) && 'wc-settings' === $_GET['page'] &&
266
+ isset( $_GET['tab'] ) && 'checkout' === $_GET['tab'] &&
267
+ isset( $_GET['section'] ) && 'stripe' === $_GET['section']
268
+ ) {
269
+ $this->process_apple_pay_verification();
270
+ }
271
+ }
272
+
273
+ /**
274
+ * Registers the domain with Stripe/Apple Pay
275
+ *
276
+ * @since 3.1.0
277
+ * @version 3.1.0
278
+ * @param string $secret_key
279
+ */
280
+ private function _register_apple_pay_domain( $secret_key = '' ) {
281
+ if ( empty( $secret_key ) ) {
282
+ throw new Exception( __( 'Unable to verify domain - missing secret key.', 'woocommerce-gateway-stripe' ) );
283
+ }
284
+
285
+ $endpoint = 'https://api.stripe.com/v1/apple_pay/domains';
286
+
287
+ $data = array(
288
+ 'domain_name' => $_SERVER['HTTP_HOST'],
289
+ );
290
+
291
+ $headers = array(
292
+ 'User-Agent' => 'WooCommerce Stripe Apple Pay',
293
+ 'Authorization' => 'Bearer ' . $secret_key,
294
+ );
295
+
296
+ $response = wp_remote_post( $endpoint, array(
297
+ 'headers' => $headers,
298
+ 'body' => http_build_query( $data ),
299
+ ) );
300
+
301
+ if ( 200 !== $response['response']['code'] ) {
302
+ throw new Exception( sprintf( __( 'Unable to verify domain - %s', 'woocommerce-gateway-stripe' ), $response['response']['message'] ) );
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Processes the Apple Pay domain verification.
308
+ *
309
+ * @since 3.1.0
310
+ * @version 3.1.0
311
+ */
312
+ public function process_apple_pay_verification() {
313
+ $gateway_settings = get_option( 'woocommerce_stripe_settings', '' );
314
+
315
+ try {
316
+ $path = untrailingslashit( preg_replace( "!${_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME'] ) );
317
+ $dir = '.well-known';
318
+ $file = 'apple-developer-merchantid-domain-association';
319
+ $fullpath = $path . '/' . $dir . '/' . $file;
320
+
321
+ if ( 'yes' === $gateway_settings['apple_pay_domain_set'] && file_exists( $fullpath ) ) {
322
+ return;
323
+ }
324
+
325
+ if ( ! file_exists( $path . '/' . $dir ) || ! file_exists( $fullpath ) ) {
326
+ if ( ! mkdir( $path . '/' . $dir, 0755 ) ) {
327
+ throw new Exception( __( 'Unable to create domain association folder to domain root.', 'woocommerce-gateway-stripe' ) );
328
+ }
329
+
330
+ if ( ! file_exists( $path . '/' . $dir . '/' . 'apple-developer-merchantid-domain-association' ) ) {
331
+ if ( ! copy( WC_STRIPE_PLUGIN_PATH . '/' . $file, $fullpath ) ) {
332
+ throw new Exception( __( 'Unable to copy domain association file to domain root.', 'woocommerce-gateway-stripe' ) );
333
+ }
334
+ }
335
+ }
336
+
337
+ // At this point then the domain association folder and file should be available.
338
+ // Proceed to verify/and or verify again.
339
+ $this->_register_apple_pay_domain( $this->secret_key );
340
+
341
+ // No errors to this point, verification success!
342
+ $gateway_settings['apple_pay_domain_set'] = 'yes';
343
+ $this->apple_pay_domain_set = true;
344
+
345
+ update_option( 'woocommerce_stripe_settings', $gateway_settings );
346
+
347
+ $this->log( __( 'Your domain has been verified with Apple Pay!', 'woocommerce-gateway-stripe' ) );
348
+
349
+ } catch ( Exception $e ) {
350
+ $gateway_settings['apple_pay_domain_set'] = 'no';
351
+
352
+ update_option( 'woocommerce_stripe_settings', $gateway_settings );
353
+
354
+ $this->log( sprintf( __( 'Error: %s', 'woocommerce-gateway-stripe' ), $e->getMessage() ) );
355
+ }
356
+ }
357
+
358
  /**
359
  * Check if SSL is enabled and notify the user
360
  */
363
  return;
364
  }
365
 
366
+ /**
367
+ * Apple pay is enabled by default and domain verification initializes
368
+ * when setting screen is displayed. So if domain verification is not set,
369
+ * something went wrong so lets notify user.
370
+ */
371
+ if ( ! empty( $this->secret_key ) && $this->apple_pay && ! $this->apple_pay_domain_set ) {
372
+ echo '<div class="error stripe-apple-pay-message"><p>' . sprintf( __( 'Apple Pay domain verification failed. Please check the %1$slog%2$s to see the issue.', 'woocommerce-gateway-stripe' ), '<a href="' . admin_url( 'page=wc-status&tab=logs' ) . '">', '</a>' ) . '</p></div>';
373
+ }
374
+
375
  // Show message if enabled and FORCE SSL is disabled and WordpressHTTPS plugin is not detected.
376
  if ( ( function_exists( 'wc_site_is_https' ) && ! wc_site_is_https() ) && ( 'no' === get_option( 'woocommerce_force_ssl_checkout' ) && ! class_exists( 'WordPressHTTPS' ) ) ) {
377
  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>';
399
  */
400
  public function init_form_fields() {
401
  $this->form_fields = include( 'settings-stripe.php' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
  }
403
 
404
  /**
434
  data-description=""
435
  data-email="' . esc_attr( $user_email ) . '"
436
  data-amount="' . esc_attr( $this->get_stripe_amount( $total ) ) . '"
437
+ data-name="' . esc_attr( $this->statement_descriptor ) . '"
438
  data-currency="' . esc_attr( strtolower( get_woocommerce_currency() ) ) . '"
439
  data-image="' . esc_attr( $this->stripe_checkout_image ) . '"
440
  data-bitcoin="' . esc_attr( $this->bitcoin ? 'true' : 'false' ) . '"
452
 
453
  if ( ! $this->stripe_checkout ) {
454
  $this->form();
455
+
456
  if ( $display_tokenization ) {
457
  $this->save_payment_method_checkbox();
458
  }
482
  'missing' => __( 'There is no card on a customer that is being charged.', 'woocommerce-gateway-stripe' ),
483
  'processing_error' => __( 'An error occurred while processing the card.', 'woocommerce-gateway-stripe' ),
484
  'invalid_request_error' => __( 'Could not find payment information.', 'woocommerce-gateway-stripe' ),
485
+ ) );
486
+ }
487
+
488
+ /**
489
+ * Load admin scripts.
490
+ *
491
+ * @since 3.1.0
492
+ * @version 3.1.0
493
+ */
494
+ public function admin_scripts() {
495
+ if ( 'woocommerce_page_wc-settings' !== get_current_screen()->id ) {
496
+ return;
497
+ }
498
+
499
+ $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
500
+
501
+ wp_enqueue_script( 'woocommerce_stripe_admin', plugins_url( 'assets/js/stripe-admin' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array(), WC_STRIPE_VERSION, true );
502
+
503
+ $stripe_admin_params = array(
504
+ 'localized_messages' => array(
505
+ 'not_valid_live_key_msg' => __( 'This is not a valid live key. Live keys start with "sk_live_" and "pk_live_".', 'woocommerce-gateway-stripe' ),
506
+ 'not_valid_test_key_msg' => __( 'This is not a valid test key. Test keys start with "sk_test_" and "pk_test_".', 'woocommerce-gateway-stripe' ),
507
+ 're_verify_button_text' => __( 'Re-verify Domain', 'woocommerce-gateway-stripe' ),
508
+ 'missing_secret_key' => __( 'Missing Secret Key. Please set the secret key field above and re-try.', 'woocommerce-gateway-stripe' ),
509
+ ),
510
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
511
+ 'nonce' => array(
512
+ 'apple_pay_domain_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_domain_nonce' ),
513
+ ),
514
+ );
515
+
516
+ wp_localize_script( 'woocommerce_stripe_admin', 'wc_stripe_admin_params', apply_filters( 'wc_stripe_admin_params', $stripe_admin_params ) );
517
  }
518
 
519
  /**
524
  * @access public
525
  */
526
  public function payment_scripts() {
527
+ if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) ) {
528
+ return;
529
+ }
530
+
531
  $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
532
+
533
  if ( $this->stripe_checkout ) {
534
+ wp_enqueue_script( 'stripe_checkout', 'https://checkout.stripe.com/v2/checkout.js', '', '2.0', true );
535
+ wp_enqueue_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe-checkout' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'stripe' ), WC_STRIPE_VERSION, true );
536
  } else {
537
  wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
538
  wp_enqueue_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'jquery-payment', 'stripe' ), WC_STRIPE_VERSION, true );
549
  $order_id = wc_get_order_id_by_order_key( urldecode( $_GET['key'] ) );
550
  $order = wc_get_order( $order_id );
551
 
552
+ $stripe_params['billing_first_name'] = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_first_name : $order->get_billing_first_name();
553
+ $stripe_params['billing_last_name'] = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_last_name : $order->get_billing_last_name();
554
+ $stripe_params['billing_address_1'] = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_address_1 : $order->get_billing_address_1();
555
+ $stripe_params['billing_address_2'] = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_address_2 : $order->get_billing_address_2();
556
+ $stripe_params['billing_state'] = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_state : $order->get_billing_state();
557
+ $stripe_params['billing_city'] = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_city : $order->get_billing_city();
558
+ $stripe_params['billing_postcode'] = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_postcode : $order->get_billing_postcode();
559
+ $stripe_params['billing_country'] = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_country : $order->get_billing_country();
560
  }
561
 
562
  $stripe_params['no_prepaid_card_msg'] = __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' );
577
  */
578
  protected function generate_payment_request( $order, $source ) {
579
  $post_data = array();
580
+ $post_data['currency'] = strtolower( version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->get_order_currency() : $order->get_currency() );
581
  $post_data['amount'] = $this->get_stripe_amount( $order->get_total(), $post_data['currency'] );
582
+ $post_data['description'] = sprintf( __( '%1$s - Order %2$s', 'woocommerce-gateway-stripe' ), $this->statement_descriptor, $order->get_order_number() );
583
  $post_data['capture'] = $this->capture ? 'true' : 'false';
584
 
585
+ $billing_email = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_email : $order->get_billing_email();
586
+ $billing_first_name = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_first_name : $order->get_billing_first_name();
587
+ $billing_last_name = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_last_name : $order->get_billing_last_name();
588
+
589
+ if ( ! empty( $billing_email ) && apply_filters( 'wc_stripe_send_stripe_receipt', false ) ) {
590
+ $post_data['receipt_email'] = $billing_email;
591
  }
592
 
593
  $post_data['expand[]'] = 'balance_transaction';
594
 
595
+ $metadata = array(
596
+ __( 'Customer Name', 'woocommerce-gateway-stripe' ) => sanitize_text_field( $billing_first_name ) . ' ' . sanitize_text_field( $billing_last_name ),
597
+ __( 'Customer Email', 'woocommerce-gateway-stripe' ) => sanitize_email( $billing_email ),
598
+ );
599
+
600
+ $post_data['metadata'] = apply_filters( 'wc_stripe_payment_metadata', $metadata, $order, $source );
601
+
602
  if ( $source->customer ) {
603
  $post_data['customer'] = $source->customer;
604
  }
606
  if ( $source->source ) {
607
  $post_data['source'] = $source->source;
608
  }
609
+
610
  /**
611
  * Filter the return value of the WC_Payment_Gateway_CC::generate_payment_request.
612
  *
644
  if ( is_wp_error( $stripe_source ) ) {
645
  throw new Exception( $stripe_source->get_error_message() );
646
  }
 
647
  } else {
648
  // Not saving token, so don't define customer either.
649
  $stripe_source = $stripe_token;
650
  $stripe_customer = false;
651
  }
652
+ } elseif ( isset( $_POST['wc-stripe-payment-token'] ) && 'new' !== $_POST['wc-stripe-payment-token'] ) {
653
+ // Use an existing token, and then process the payment
654
 
 
 
655
  $token_id = wc_clean( $_POST['wc-stripe-payment-token'] );
656
  $token = WC_Payment_Tokens::get( $token_id );
657
 
687
  $token_id = false;
688
 
689
  if ( $order ) {
690
+ $order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
691
+
692
+ if ( $meta_value = get_post_meta( $order_id, '_stripe_customer_id', true ) ) {
693
  $stripe_customer->set_id( $meta_value );
694
  }
695
+
696
+ if ( $meta_value = get_post_meta( $order_id, '_stripe_card_id', true ) ) {
697
  $stripe_source = $meta_value;
698
  }
699
  }
732
 
733
  // Handle payment.
734
  if ( $order->get_total() > 0 ) {
735
+
736
  if ( $order->get_total() * 100 < WC_Stripe::get_minimum_amount() ) {
737
  throw new Exception( 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 ) ) );
738
  }
739
 
740
+ $this->log( "Info: Begin processing payment for order $order_id for the amount of {$order->get_total()}" );
741
 
742
  // Make the request.
743
  $response = WC_Stripe_API::request( $this->generate_payment_request( $order, $source ) );
751
  } elseif ( 'source' === $response->get_error_code() && $source->token_id ) {
752
  $token = WC_Payment_Tokens::get( $source->token_id );
753
  $token->delete();
754
+ $message = __( 'This card is no longer available and has been removed.', 'woocommerce-gateway-stripe' );
755
+ $order->add_order_note( $message );
756
+ throw new Exception( $message );
757
  }
758
+
759
  $localized_messages = $this->get_localized_messages();
760
 
761
+ $message = isset( $localized_messages[ $response->get_error_code() ] ) ? $localized_messages[ $response->get_error_code() ] : $response->get_error_message();
762
+
763
+ $order->add_order_note( $message );
764
+
765
+ throw new Exception( $message );
766
  }
767
 
768
  // Process valid response.
779
  // Return thank you page redirect.
780
  return array(
781
  'result' => 'success',
782
+ 'redirect' => $this->get_return_url( $order ),
783
  );
784
 
785
  } catch ( Exception $e ) {
786
  wc_add_notice( $e->getMessage(), 'error' );
787
+ $this->log( sprintf( __( 'Error: %s', 'woocommerce-gateway-stripe' ), $e->getMessage() ) );
788
 
789
  if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
790
  $this->send_failed_order_email( $order_id );
794
 
795
  return array(
796
  'result' => 'fail',
797
+ 'redirect' => '',
798
  );
799
  }
800
  }
806
  * @param stdClass $source Source information.
807
  */
808
  protected function save_source( $order, $source ) {
809
+ $order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
810
+
811
  // Store source in the order.
812
  if ( $source->customer ) {
813
+ update_post_meta( $order_id, '_stripe_customer_id', $source->customer );
814
  }
815
  if ( $source->source ) {
816
+ update_post_meta( $order_id, '_stripe_card_id', $source->source );
817
  }
818
  }
819
 
821
  * Store extra meta data for an order from a Stripe Response.
822
  */
823
  public function process_response( $response, $order ) {
824
+ $this->log( 'Processing response: ' . print_r( $response, true ) );
825
+
826
+ $order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
827
 
828
  // Store charge data
829
+ update_post_meta( $order_id, '_stripe_charge_id', $response->id );
830
+ update_post_meta( $order_id, '_stripe_charge_captured', $response->captured ? 'yes' : 'no' );
831
 
832
  // Store other data such as fees
833
  if ( isset( $response->balance_transaction ) && isset( $response->balance_transaction->fee ) ) {
834
  // Fees and Net needs to both come from Stripe to be accurate as the returned
835
  // values are in the local currency of the Stripe account, not from WC.
836
+ $fee = ! empty( $response->balance_transaction->fee ) ? WC_Stripe::format_number( $response->balance_transaction, 'fee' ) : 0;
837
+ $net = ! empty( $response->balance_transaction->net ) ? WC_Stripe::format_number( $response->balance_transaction, 'net' ) : 0;
838
+ update_post_meta( $order_id, 'Stripe Fee', $fee );
839
+ update_post_meta( $order_id, 'Net Revenue From Stripe', $net );
840
  }
841
 
842
  if ( $response->captured ) {
844
 
845
  $message = sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $response->id );
846
  $order->add_order_note( $message );
847
+ $this->log( 'Success: ' . $message );
848
 
849
  } else {
850
+ add_post_meta( $order_id, '_transaction_id', $response->id, true );
851
 
852
  if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
853
+ version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->reduce_order_stock() : wc_reduce_stock_levels( $order_id );
854
  }
855
 
856
  $order->update_status( 'on-hold', sprintf( __( 'Stripe charge authorized (Charge ID: %s). Process order to take payment, or cancel to remove the pre-authorization.', 'woocommerce-gateway-stripe' ), $response->id ) );
857
+ $this->log( "Successful auth: $response->id" );
858
  }
859
 
860
  return $response;
920
  );
921
  }
922
 
923
+ $this->log( "Info: Beginning refund for order $order_id for the amount of {$amount}" );
924
 
925
  $response = WC_Stripe_API::request( $body, 'charges/' . $order->get_transaction_id() . '/refunds' );
926
 
927
  if ( is_wp_error( $response ) ) {
928
+ $this->log( 'Error: ' . $response->get_error_message() );
929
  return $response;
930
  } elseif ( ! empty( $response->id ) ) {
931
+ $refund_message = sprintf( __( 'Refunded %1$s - Refund ID: %2$s - Reason: %3$s', 'woocommerce-gateway-stripe' ), wc_price( $response->amount / 100 ), $response->id, $reason );
932
  $order->add_order_note( $refund_message );
933
+ $this->log( 'Success: ' . html_entity_decode( strip_tags( $refund_message ) ) );
934
  return true;
935
  }
936
  }
949
  $emails['WC_Email_Failed_Order']->trigger( $order_id );
950
  }
951
  }
952
+
953
+ /**
954
+ * Logs
955
+ *
956
+ * @since 3.1.0
957
+ * @version 3.1.0
958
+ *
959
+ * @param string $message
960
+ */
961
+ public function log( $message ) {
962
+ if ( $this->logging ) {
963
+ WC_Stripe::log( $message );
964
+ }
965
+ }
966
  }
includes/class-wc-stripe-api.php CHANGED
@@ -52,24 +52,24 @@ class WC_Stripe_API {
52
  * @return array|WP_Error
53
  */
54
  public static function request( $request, $api = 'charges', $method = 'POST' ) {
55
- WC_Stripe::log( "{$api} request: " . print_r( $request, true ) );
56
 
57
  $response = wp_safe_remote_post(
58
  self::ENDPOINT . $api,
59
  array(
60
  'method' => $method,
61
  'headers' => array(
62
- 'Authorization' => 'Basic ' . base64_encode( self::get_secret_key(). ':' ),
63
- 'Stripe-Version' => '2016-03-07'
64
  ),
65
  'body' => apply_filters( 'woocommerce_stripe_request_body', $request, $api ),
66
  'timeout' => 70,
67
- 'user-agent' => 'WooCommerce ' . WC()->version
68
  )
69
  );
70
 
71
  if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
72
- WC_Stripe::log( "Error Response: " . print_r( $response, true ) );
73
  return new WP_Error( 'stripe_error', __( 'There was a problem connecting to the payment gateway.', 'woocommerce-gateway-stripe' ) );
74
  }
75
 
@@ -88,4 +88,20 @@ class WC_Stripe_API {
88
  return $parsed_response;
89
  }
90
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  }
52
  * @return array|WP_Error
53
  */
54
  public static function request( $request, $api = 'charges', $method = 'POST' ) {
55
+ self::log( "{$api} request: " . print_r( $request, true ) );
56
 
57
  $response = wp_safe_remote_post(
58
  self::ENDPOINT . $api,
59
  array(
60
  'method' => $method,
61
  'headers' => array(
62
+ 'Authorization' => 'Basic ' . base64_encode( self::get_secret_key() . ':' ),
63
+ 'Stripe-Version' => '2016-03-07',
64
  ),
65
  'body' => apply_filters( 'woocommerce_stripe_request_body', $request, $api ),
66
  'timeout' => 70,
67
+ 'user-agent' => 'WooCommerce ' . WC()->version,
68
  )
69
  );
70
 
71
  if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
72
+ self::log( 'Error Response: ' . print_r( $response, true ) );
73
  return new WP_Error( 'stripe_error', __( 'There was a problem connecting to the payment gateway.', 'woocommerce-gateway-stripe' ) );
74
  }
75
 
88
  return $parsed_response;
89
  }
90
  }
91
+
92
+ /**
93
+ * Logs
94
+ *
95
+ * @since 3.1.0
96
+ * @version 3.1.0
97
+ *
98
+ * @param string $message
99
+ */
100
+ public static function log( $message ) {
101
+ $options = get_option( 'woocommerce_stripe_settings' );
102
+
103
+ if ( 'yes' === $options['logging'] ) {
104
+ WC_Stripe::log( $message );
105
+ }
106
+ }
107
  }
includes/class-wc-stripe-apple-pay.php ADDED
@@ -0,0 +1,884 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
+ /**
7
+ * WC_Stripe_Apple_Pay class.
8
+ *
9
+ * @extends WC_Gateway_Stripe
10
+ */
11
+ class WC_Stripe_Apple_Pay extends WC_Gateway_Stripe {
12
+ /**
13
+ * This Instance.
14
+ *
15
+ * @var
16
+ */
17
+ private static $_this;
18
+
19
+ /**
20
+ * Gateway.
21
+ *
22
+ * @var
23
+ */
24
+ private $_gateway;
25
+
26
+ /**
27
+ * Statement Description
28
+ *
29
+ * @var
30
+ */
31
+ public $statement_descriptor;
32
+
33
+ /**
34
+ * Gateway settings.
35
+ *
36
+ * @var
37
+ */
38
+ private $_gateway_settings;
39
+
40
+ /**
41
+ * Constructor.
42
+ *
43
+ * @access public
44
+ * @since 3.1.0
45
+ * @version 3.1.0
46
+ */
47
+ public function __construct() {
48
+ self::$_this = $this;
49
+
50
+ $this->_gateway_settings = get_option( 'woocommerce_stripe_settings', '' );
51
+
52
+ $this->statement_descriptor = ! empty( $this->_gateway_settings['statement_descriptor'] ) ? $this->_gateway_settings['statement_descriptor'] : wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
53
+
54
+ $this->init();
55
+ }
56
+
57
+ public function instance() {
58
+ return self::$_this;
59
+ }
60
+
61
+ /**
62
+ * Initialize.
63
+ *
64
+ * @access public
65
+ * @since 3.1.0
66
+ * @version 3.1.0
67
+ */
68
+ public function init() {
69
+ add_action( 'wp_enqueue_scripts', array( $this, 'cart_scripts' ) );
70
+ add_action( 'wp_enqueue_scripts', array( $this, 'single_scripts' ) );
71
+
72
+ /**
73
+ * In order to display the Apple Pay button in the correct position,
74
+ * a new hook was added to WooCommerce 2.7. In older versions of WooCommerce,
75
+ * CSS is used to position the button.
76
+ */
77
+ if ( version_compare( WC_VERSION, '3.0.0', '<' ) ) {
78
+ add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'display_apple_pay_button' ), 1 );
79
+ add_filter( 'body_class', array( $this, 'body_class' ) );
80
+ } else {
81
+ add_action( 'woocommerce_after_add_to_cart_quantity', array( $this, 'display_apple_pay_button' ), 1 );
82
+ }
83
+
84
+ add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_apple_pay_button' ), 1 );
85
+ add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_apple_pay_separator_html' ), 2 );
86
+ add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_apple_pay_button' ), 1 );
87
+ add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_apple_pay_separator_html' ), 2 );
88
+ add_action( 'wc_ajax_wc_stripe_apple_pay', array( $this, 'process_apple_pay' ) );
89
+ add_action( 'wc_ajax_wc_stripe_generate_apple_pay_cart', array( $this, 'generate_apple_pay_cart' ) );
90
+ add_action( 'wc_ajax_wc_stripe_generate_apple_pay_single', array( $this, 'generate_apple_pay_single' ) );
91
+ add_action( 'wc_ajax_wc_stripe_apple_pay_get_shipping_methods', array( $this, 'get_shipping_methods' ) );
92
+ add_action( 'wc_ajax_wc_stripe_apple_pay_update_shipping_method', array( $this, 'update_shipping_method' ) );
93
+ add_filter( 'woocommerce_gateway_title', array( $this, 'filter_gateway_title' ), 10, 2 );
94
+ }
95
+
96
+ /**
97
+ * Filters the gateway title to reflect Apple Pay.
98
+ *
99
+ */
100
+ public function filter_gateway_title( $title, $id ) {
101
+ global $post;
102
+
103
+ if ( ! is_object( $post ) ) {
104
+ return $title;
105
+ }
106
+
107
+ $method_title = get_post_meta( $post->ID, '_payment_method_title', true );
108
+
109
+ if ( 'stripe' === $id && ! empty( $method_title ) ) {
110
+ return $method_title;
111
+ }
112
+
113
+ return $title;
114
+ }
115
+
116
+ /**
117
+ * Enqueue JS scripts and styles for single product page.
118
+ *
119
+ * @since 3.1.0
120
+ * @version 3.1.0
121
+ */
122
+ public function single_scripts() {
123
+ if ( ! is_single() ) {
124
+ return;
125
+ }
126
+
127
+ global $post;
128
+
129
+ $product = wc_get_product( $post->ID );
130
+
131
+ if ( ! in_array( ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
132
+ return;
133
+ }
134
+
135
+ $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
136
+
137
+ wp_enqueue_style( 'stripe_apple_pay', plugins_url( 'assets/css/stripe-apple-pay.css', WC_STRIPE_MAIN_FILE ), array(), WC_STRIPE_VERSION );
138
+
139
+ wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
140
+ wp_enqueue_script( 'woocommerce_stripe_apple_pay_single', plugins_url( 'assets/js/stripe-apple-pay-single' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'stripe' ), WC_STRIPE_VERSION, true );
141
+
142
+ $publishable_key = 'yes' === $this->_gateway_settings['testmode'] ? $this->_gateway_settings['test_publishable_key'] : $this->_gateway_settings['publishable_key'];
143
+
144
+ $stripe_params = array(
145
+ 'key' => $publishable_key,
146
+ 'currency_code' => get_woocommerce_currency(),
147
+ 'country_code' => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
148
+ 'label' => $this->statement_descriptor,
149
+ 'ajaxurl' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
150
+ 'stripe_apple_pay_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_nonce' ),
151
+ 'stripe_apple_pay_cart_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_cart_nonce' ),
152
+ 'stripe_apple_pay_get_shipping_methods_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_get_shipping_methods_nonce' ),
153
+ 'stripe_apple_pay_update_shipping_method_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_update_shipping_method_nonce' ),
154
+ 'needs_shipping' => WC()->cart->needs_shipping() ? 'yes' : 'no',
155
+ );
156
+
157
+ wp_localize_script( 'woocommerce_stripe_apple_pay_single', 'wc_stripe_apple_pay_single_params', apply_filters( 'wc_stripe_apple_pay_single_params', $stripe_params ) );
158
+ }
159
+
160
+ /**
161
+ * Enqueue JS scripts and styles for the cart/checkout.
162
+ *
163
+ * @since 3.1.0
164
+ * @version 3.1.0
165
+ */
166
+ public function cart_scripts() {
167
+ if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) ) {
168
+ return;
169
+ }
170
+
171
+ $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
172
+
173
+ wp_enqueue_style( 'stripe_apple_pay', plugins_url( 'assets/css/stripe-apple-pay.css', WC_STRIPE_MAIN_FILE ), array(), WC_STRIPE_VERSION );
174
+
175
+ wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
176
+ wp_enqueue_script( 'woocommerce_stripe_apple_pay', plugins_url( 'assets/js/stripe-apple-pay' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'stripe' ), WC_STRIPE_VERSION, true );
177
+
178
+ $publishable_key = 'yes' === $this->_gateway_settings['testmode'] ? $this->_gateway_settings['test_publishable_key'] : $this->_gateway_settings['publishable_key'];
179
+
180
+ $stripe_params = array(
181
+ 'key' => $publishable_key,
182
+ 'currency_code' => get_woocommerce_currency(),
183
+ 'country_code' => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
184
+ 'label' => $this->statement_descriptor,
185
+ 'ajaxurl' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
186
+ 'stripe_apple_pay_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_nonce' ),
187
+ 'stripe_apple_pay_cart_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_cart_nonce' ),
188
+ 'stripe_apple_pay_get_shipping_methods_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_get_shipping_methods_nonce' ),
189
+ 'stripe_apple_pay_update_shipping_method_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_update_shipping_method_nonce' ),
190
+ 'needs_shipping' => WC()->cart->needs_shipping() ? 'yes' : 'no',
191
+ 'is_cart_page' => is_cart() ? 'yes' : 'no',
192
+ );
193
+
194
+ wp_localize_script( 'woocommerce_stripe_apple_pay', 'wc_stripe_apple_pay_params', apply_filters( 'wc_stripe_apple_pay_params', $stripe_params ) );
195
+ }
196
+
197
+ /**
198
+ * Checks to make sure product type is supported by Apple Pay.
199
+ *
200
+ */
201
+ public function supported_product_types() {
202
+ return array(
203
+ 'simple',
204
+ 'variable',
205
+ );
206
+ }
207
+
208
+ /**
209
+ * Display Apple Pay button on the cart page
210
+ *
211
+ * @since 3.1.0
212
+ * @version 3.1.0
213
+ */
214
+ public function display_apple_pay_button() {
215
+ $gateways = WC()->payment_gateways->get_available_payment_gateways();
216
+
217
+ /**
218
+ * In order for the Apple Pay button to show on cart page,
219
+ * Apple Pay must be enabled and Stripe gateway must be enabled.
220
+ */
221
+ if (
222
+ 'yes' !== $this->_gateway_settings['apple_pay']
223
+ || ! isset( $gateways['stripe'] )
224
+ ) {
225
+ return;
226
+ }
227
+
228
+ if ( is_single() ) {
229
+ global $post;
230
+
231
+ $product = wc_get_product( $post->ID );
232
+
233
+ if ( ! in_array( ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
234
+ return;
235
+ }
236
+ }
237
+
238
+ $apple_pay_button = ! empty( $this->_gateway_settings['apple_pay_button'] ) ? $this->_gateway_settings['apple_pay_button'] : 'black';
239
+ $button_lang = ! empty( $this->_gateway_settings['apple_pay_button_lang'] ) ? strtolower( $this->_gateway_settings['apple_pay_button_lang'] ) : 'en';
240
+ ?>
241
+ <div class="apple-pay-button-wrapper">
242
+ <button class="apple-pay-button" lang="<?php echo esc_attr( $button_lang ); ?>" style="-webkit-appearance: -apple-pay-button; -apple-pay-button-type: buy; -apple-pay-button-style: <?php echo esc_attr( $apple_pay_button ); ?>;"></button>
243
+ </div>
244
+ <?php
245
+ }
246
+
247
+ /**
248
+ * Display Apple Pay button on the cart page
249
+ *
250
+ * @since 3.1.0
251
+ * @version 3.1.0
252
+ */
253
+ public function display_apple_pay_separator_html() {
254
+ $gateways = WC()->payment_gateways->get_available_payment_gateways();
255
+
256
+ /**
257
+ * In order for the Apple Pay button to show on cart page,
258
+ * Apple Pay must be enabled and Stripe gateway must be enabled.
259
+ */
260
+ if (
261
+ 'yes' !== $this->_gateway_settings['apple_pay']
262
+ || ! isset( $gateways['stripe'] )
263
+ ) {
264
+ return;
265
+ }
266
+
267
+ if ( is_single() ) {
268
+ global $post;
269
+
270
+ $product = wc_get_product( $post->ID );
271
+
272
+ if ( ! in_array( ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
273
+ return;
274
+ }
275
+ }
276
+ ?>
277
+ <p class="apple-pay-button-checkout-separator">- <?php esc_html_e( 'Or', 'woocommerce-gateway-stripe' ); ?> -</p>
278
+ <?php
279
+ }
280
+
281
+ /**
282
+ * Add legacy WooCommerce body class.
283
+ *
284
+ * @since 3.1.0
285
+ * @version 3.1.0
286
+ * @param array $classes
287
+ * @return array $classes
288
+ */
289
+ public function body_class( $classes ) {
290
+ if ( 'yes' === $this->_gateway_settings['apple_pay'] && isset( $gateways['stripe'] ) ) {
291
+ $classes[] = 'wc-stripe-legacy';
292
+ }
293
+ return $classes;
294
+ }
295
+
296
+ /**
297
+ * Generates the Apple Pay single cart.
298
+ *
299
+ * @since 3.1.0
300
+ * @version 3.1.0
301
+ */
302
+ public function generate_apple_pay_single() {
303
+ if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_cart_nonce' ) ) {
304
+ wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
305
+ }
306
+
307
+ if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
308
+ define( 'WOOCOMMERCE_CART', true );
309
+ }
310
+
311
+ WC()->shipping->reset_shipping();
312
+
313
+ global $post;
314
+
315
+ $product = wc_get_product( $post->ID );
316
+ $qty = absint( $_POST['qty'] );
317
+
318
+ /**
319
+ * If this page is single product page, we need to simulate
320
+ * adding the product to the cart taken account if it is a
321
+ * simple or variable product.
322
+ */
323
+ if ( is_single() ) {
324
+ // First empty the cart to prevent wrong calculation.
325
+ WC()->cart->empty_cart();
326
+
327
+ if ( 'variable' === ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $product->product_type : $product->get_type() ) && isset( $_POST['attributes'] ) ) {
328
+ $attributes = array_map( 'wc_clean', $_POST['attributes'] );
329
+
330
+ $variation_id = $product->get_matching_variation( $attributes );
331
+
332
+ WC()->cart->add_to_cart( $product->get_id(), $qty, $variation_id, $attributes );
333
+ }
334
+
335
+ if ( 'simple' === ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $product->product_type : $product->get_type() ) ) {
336
+ WC()->cart->add_to_cart( $product->get_id(), $qty );
337
+ }
338
+ }
339
+
340
+ WC()->cart->calculate_totals();
341
+
342
+ wp_send_json( array( 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total ) );
343
+ }
344
+
345
+ /**
346
+ * Generates the Apple Pay cart.
347
+ *
348
+ * @since 3.1.0
349
+ * @version 3.1.0
350
+ */
351
+ public function generate_apple_pay_cart() {
352
+ if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_cart_nonce' ) ) {
353
+ wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
354
+ }
355
+
356
+ wp_send_json( array( 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total ) );
357
+ }
358
+
359
+ /**
360
+ * Calculate and set shipping method.
361
+ *
362
+ * @since 3.1.0
363
+ * @version 3.1.0
364
+ * @param array $address
365
+ */
366
+ public function calculate_shipping( $address = array() ) {
367
+ $country = strtoupper( $address['countryCode'] );
368
+ $state = strtoupper( $address['administrativeArea'] );
369
+ $postcode = $address['postalCode'];
370
+ $city = $address['locality'];
371
+
372
+ WC()->shipping->reset_shipping();
373
+
374
+ if ( $postcode && ! WC_Validation::is_postcode( $postcode, $country ) ) {
375
+ throw new Exception( __( 'Please enter a valid postcode/ZIP.', 'woocommerce-gateway-stripe' ) );
376
+ } elseif ( $postcode ) {
377
+ $postcode = wc_format_postcode( $postcode, $country );
378
+ }
379
+
380
+ if ( $country ) {
381
+ WC()->customer->set_location( $country, $state, $postcode, $city );
382
+ WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
383
+ } else {
384
+ WC()->customer->set_to_base();
385
+ WC()->customer->set_shipping_to_base();
386
+ }
387
+
388
+ WC()->customer->calculated_shipping( true );
389
+
390
+ /**
391
+ * Set the shipping package.
392
+ *
393
+ * Note that address lines are not provided at this point
394
+ * because Apple Pay does not supply that until after
395
+ * authentication via passcode or Touch ID. We will need to
396
+ * capture this information when we process the payment.
397
+ */
398
+
399
+ $packages = array();
400
+
401
+ $packages[0]['contents'] = WC()->cart->get_cart();
402
+ $packages[0]['contents_cost'] = 0;
403
+ $packages[0]['applied_coupons'] = WC()->cart->applied_coupons;
404
+ $packages[0]['user']['ID'] = get_current_user_id();
405
+ $packages[0]['destination']['country'] = $country;
406
+ $packages[0]['destination']['state'] = $state;
407
+ $packages[0]['destination']['postcode'] = $postcode;
408
+ $packages[0]['destination']['city'] = $city;
409
+
410
+ foreach ( WC()->cart->get_cart() as $item ) {
411
+ if ( $item['data']->needs_shipping() ) {
412
+ if ( isset( $item['line_total'] ) ) {
413
+ $packages[0]['contents_cost'] += $item['line_total'];
414
+ }
415
+ }
416
+ }
417
+
418
+ $packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages );
419
+
420
+ WC()->shipping->calculate_shipping( $packages );
421
+ }
422
+
423
+ /**
424
+ * Gets shipping for Apple Pay Payment sheet.
425
+ *
426
+ * @since 3.1.0
427
+ * @version 3.1.0
428
+ */
429
+ public function get_shipping_methods() {
430
+ if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_get_shipping_methods_nonce' ) ) {
431
+ wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
432
+ }
433
+
434
+ if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
435
+ define( 'WOOCOMMERCE_CART', true );
436
+ }
437
+
438
+ try {
439
+ $address = array_map( 'wc_clean', $_POST['address'] );
440
+
441
+ $this->calculate_shipping( $address );
442
+
443
+ // Set the shipping options.
444
+ $currency = get_woocommerce_currency();
445
+ $data = array();
446
+
447
+ $packages = WC()->shipping->get_packages();
448
+
449
+ if ( ! empty( $packages ) && WC()->customer->has_calculated_shipping() ) {
450
+ foreach ( $packages as $package_key => $package ) {
451
+ if ( empty( $package['rates'] ) ) {
452
+ throw new Exception( __( 'Unable to find shipping method for address.', 'woocommerce-gateway-stripe' ) );
453
+ }
454
+
455
+ foreach ( $package['rates'] as $key => $rate ) {
456
+ $data[] = array(
457
+ 'id' => $rate->id,
458
+ 'label' => $rate->label,
459
+ 'amount' => array(
460
+ 'currency' => $currency,
461
+ 'value' => $rate->cost,
462
+ ),
463
+ 'selected' => false,
464
+ );
465
+ }
466
+ }
467
+
468
+ // Auto select the first shipping method.
469
+ WC()->session->set( 'chosen_shipping_methods', array( $data[0]['id'] ) );
470
+
471
+ WC()->cart->calculate_totals();
472
+
473
+ wp_send_json( array( 'success' => 'true', 'shipping_methods' => $this->build_shipping_methods( $data ), 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total ) );
474
+ } else {
475
+ throw new Exception( __( 'Unable to find shipping method for address.', 'woocommerce-gateway-stripe' ) );
476
+ }
477
+ } catch ( Exception $e ) {
478
+ wp_send_json( array( 'success' => 'false', 'shipping_methods' => array(), 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total ) );
479
+ }
480
+ }
481
+
482
+ /**
483
+ * Updates shipping method on cart session.
484
+ *
485
+ * @since 3.1.0
486
+ * @version 3.1.0
487
+ */
488
+ public function update_shipping_method() {
489
+ if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
490
+ define( 'WOOCOMMERCE_CART', true );
491
+ }
492
+
493
+ if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_update_shipping_method_nonce' ) ) {
494
+ wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
495
+ }
496
+
497
+ $selected_shipping_method = array_map( 'wc_clean', $_POST['selected_shipping_method'] );
498
+
499
+ WC()->session->set( 'chosen_shipping_methods', array( $selected_shipping_method['identifier'] ) );
500
+
501
+ WC()->cart->calculate_totals();
502
+
503
+ // Send back the new cart total.
504
+ $currency = get_woocommerce_currency();
505
+ $tax_total = max( 0, round( WC()->cart->tax_total + WC()->cart->shipping_tax_total, WC()->cart->dp ) );
506
+ $data = array(
507
+ 'total' => WC()->cart->total,
508
+ );
509
+
510
+ // Include fees and taxes as displayItems.
511
+ foreach ( WC()->cart->fees as $key => $fee ) {
512
+ $data['items'][] = array(
513
+ 'label' => $fee->name,
514
+ 'amount' => array(
515
+ 'currency' => $currency,
516
+ 'value' => $fee->amount,
517
+ ),
518
+ );
519
+ }
520
+ if ( 0 < $tax_total ) {
521
+ $data['items'][] = array(
522
+ 'label' => __( 'Tax', 'woocommerce-gateway-stripe' ),
523
+ 'amount' => array(
524
+ 'currency' => $currency,
525
+ 'value' => $tax_total,
526
+ ),
527
+ );
528
+ }
529
+
530
+ wp_send_json( array( 'success' => 'true', 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total ) );
531
+ }
532
+
533
+ /**
534
+ * Handles the Apple Pay processing via AJAX
535
+ *
536
+ * @access public
537
+ * @since 3.1.0
538
+ * @version 3.1.0
539
+ */
540
+ public function process_apple_pay() {
541
+ if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_nonce' ) ) {
542
+ wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
543
+ }
544
+
545
+ try {
546
+ $result = array_map( 'wc_clean', $_POST['result'] );
547
+
548
+ $order = $this->create_order( $result );
549
+
550
+ $order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
551
+
552
+ // Handle payment.
553
+ if ( $order->get_total() > 0 ) {
554
+
555
+ if ( $order->get_total() * 100 < WC_Stripe::get_minimum_amount() ) {
556
+ 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 ) ) );
557
+ }
558
+
559
+ WC_Stripe::log( "Info: Begin processing payment for order {$order_id} for the amount of {$order->get_total()}" );
560
+
561
+ // Make the request.
562
+ $response = WC_Stripe_API::request( $this->generate_payment_request( $order, $result['token']['id'] ) );
563
+
564
+ if ( is_wp_error( $response ) ) {
565
+ $localized_messages = $this->get_localized_messages();
566
+
567
+ throw new Exception( ( isset( $localized_messages[ $response->get_error_code() ] ) ? $localized_messages[ $response->get_error_code() ] : $response->get_error_message() ) );
568
+ }
569
+
570
+ // Process valid response.
571
+ $this->process_response( $response, $order );
572
+ } else {
573
+ $order->payment_complete();
574
+ }
575
+
576
+ // Remove cart.
577
+ WC()->cart->empty_cart();
578
+
579
+ update_post_meta( $order_id, '_customer_user', get_current_user_id() );
580
+ update_post_meta( $order_id, '_payment_method_title', __( 'Apple Pay (Stripe)', 'woocommerce-gateway-stripe' ) );
581
+
582
+ // Return thank you page redirect.
583
+ wp_send_json( array(
584
+ 'success' => 'true',
585
+ 'redirect' => $this->get_return_url( $order ),
586
+ ) );
587
+
588
+ } catch ( Exception $e ) {
589
+ WC()->session->set( 'refresh_totals', true );
590
+ WC_Stripe::log( sprintf( __( 'Error: %s', 'woocommerce-gateway-stripe' ), $e->getMessage() ) );
591
+
592
+ if ( is_object( $order ) && isset( $order_id ) && $order->has_status( array( 'pending', 'failed' ) ) ) {
593
+ $this->send_failed_order_email( $order_id );
594
+ }
595
+
596
+ wp_send_json( array( 'success' => 'false', 'msg' => $e->getMessage() ) );
597
+ }
598
+ }
599
+
600
+ /**
601
+ * Generate the request for the payment.
602
+ * @param WC_Order $order
603
+ * @param string $source token
604
+ * @return array()
605
+ */
606
+ protected function generate_payment_request( $order, $source ) {
607
+ $post_data = array();
608
+ $post_data['currency'] = strtolower( version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->get_order_currency() : $order->get_currency() );
609
+ $post_data['amount'] = $this->get_stripe_amount( $order->get_total(), $post_data['currency'] );
610
+ $post_data['description'] = sprintf( __( '%1$s - Order %2$s', 'woocommerce-gateway-stripe' ), $this->statement_descriptor, $order->get_order_number() );
611
+ $post_data['capture'] = 'yes' === $this->_gateway_settings['capture'] ? 'true' : 'false';
612
+
613
+ $billing_email = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_email : $order->get_billing_email();
614
+
615
+ if ( ! empty( $billing_email ) && apply_filters( 'wc_stripe_send_stripe_receipt', false ) ) {
616
+ $post_data['receipt_email'] = $billing_email;
617
+ }
618
+
619
+ $post_data['expand[]'] = 'balance_transaction';
620
+ $post_data['source'] = $source;
621
+
622
+ /**
623
+ * Filter the return value of the WC_Payment_Gateway_CC::generate_payment_request.
624
+ *
625
+ * @since 3.1.0
626
+ * @param array $post_data
627
+ * @param WC_Order $order
628
+ * @param object $source
629
+ */
630
+ return apply_filters( 'wc_stripe_generate_payment_request', $post_data, $order );
631
+ }
632
+
633
+ /**
634
+ * Builds the shippings methods to pass to Apple Pay.
635
+ *
636
+ * @since 3.1.0
637
+ * @version 3.1.0
638
+ */
639
+ public function build_shipping_methods( $shipping_methods ) {
640
+ if ( empty( $shipping_methods ) ) {
641
+ return array();
642
+ }
643
+
644
+ $shipping = array();
645
+
646
+ foreach ( $shipping_methods as $method ) {
647
+ $shipping[] = array(
648
+ 'label' => $method['label'],
649
+ 'detail' => '',
650
+ 'amount' => $method['amount']['value'],
651
+ 'identifier' => $method['id'],
652
+ );
653
+ }
654
+
655
+ return $shipping;
656
+ }
657
+
658
+ /**
659
+ * Builds the line items to pass to Apple Pay.
660
+ *
661
+ * @since 3.1.0
662
+ * @version 3.1.0
663
+ */
664
+ public function build_line_items() {
665
+ if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
666
+ define( 'WOOCOMMERCE_CART', true );
667
+ }
668
+
669
+ $decimals = apply_filters( 'wc_stripe_apple_pay_decimals', 2 );
670
+
671
+ $items = array();
672
+ $subtotal = 0;
673
+
674
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
675
+ $amount = wc_format_decimal( $values['line_subtotal'], $decimals );
676
+ $subtotal += $values['line_subtotal'];
677
+ $quantity_label = 1 < $values['quantity'] ? ' (x' . $values['quantity'] . ')' : '';
678
+
679
+ $item = array(
680
+ 'type' => 'final',
681
+ 'label' => $values['data']->post->post_title . $quantity_label,
682
+ 'amount' => wc_format_decimal( $amount, $decimals ),
683
+ );
684
+
685
+ $items[] = $item;
686
+ }
687
+
688
+ // Default show only subtotal instead of itemization.
689
+ if ( apply_filters( 'wc_stripe_apple_pay_disable_itemization', true ) ) {
690
+ $items = array();
691
+ $items[] = array(
692
+ 'type' => 'final',
693
+ 'label' => __( 'Sub-Total', 'woocommerce-gateway-stripe' ),
694
+ 'amount' => wc_format_decimal( $subtotal, $decimals ),
695
+ );
696
+ }
697
+
698
+ $discounts = wc_format_decimal( WC()->cart->get_cart_discount_total(), $decimals );
699
+ $tax = wc_format_decimal( WC()->cart->tax_total + WC()->cart->shipping_tax_total, $decimals );
700
+ $shipping = wc_format_decimal( WC()->cart->shipping_total, $decimals );
701
+ $item_total = wc_format_decimal( WC()->cart->cart_contents_total, $decimals ) + $discounts;
702
+ $order_total = wc_format_decimal( $item_total + $tax + $shipping, $decimals );
703
+
704
+ if ( wc_tax_enabled() ) {
705
+ $items[] = array(
706
+ 'type' => 'final',
707
+ 'label' => __( 'Tax', 'woocommerce-gateway-stripe' ),
708
+ 'amount' => $tax,
709
+ );
710
+ }
711
+
712
+ if ( WC()->cart->needs_shipping() ) {
713
+ $items[] = array(
714
+ 'type' => 'final',
715
+ 'label' => __( 'Shipping', 'woocommerce-gateway-stripe' ),
716
+ 'amount' => $shipping,
717
+ );
718
+ }
719
+
720
+ if ( WC()->cart->has_discount() ) {
721
+ $items[] = array(
722
+ 'type' => 'final',
723
+ 'label' => __( 'Discount', 'woocommerce-gateway-stripe' ),
724
+ 'amount' => '-' . $discounts,
725
+ );
726
+ }
727
+
728
+ return $items;
729
+ }
730
+
731
+ /**
732
+ * Create order programatically.
733
+ *
734
+ * @since 3.1.0
735
+ * @version 3.1.0
736
+ * @param array $data
737
+ * @return object $order
738
+ */
739
+ public function create_order( $data = array() ) {
740
+ if ( empty( $data ) ) {
741
+ throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 520 ) );
742
+ }
743
+
744
+ $order = wc_create_order();
745
+ $order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
746
+
747
+ if ( is_wp_error( $order ) ) {
748
+ throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 520 ) );
749
+ } elseif ( false === $order ) {
750
+ throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 521 ) );
751
+ } else {
752
+ do_action( 'woocommerce_new_order', $order_id );
753
+ }
754
+
755
+ // Store the line items to the new/resumed order
756
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
757
+ $item_id = $order->add_product(
758
+ $values['data'],
759
+ $values['quantity'],
760
+ array(
761
+ 'variation' => $values['variation'],
762
+ 'totals' => array(
763
+ 'subtotal' => $values['line_subtotal'],
764
+ 'subtotal_tax' => $values['line_subtotal_tax'],
765
+ 'total' => $values['line_total'],
766
+ 'tax' => $values['line_tax'],
767
+ 'tax_data' => $values['line_tax_data'], // Since 2.2
768
+ ),
769
+ )
770
+ );
771
+
772
+ if ( ! $item_id ) {
773
+ throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 525 ) );
774
+ }
775
+
776
+ // Allow plugins to add order item meta
777
+ do_action( 'woocommerce_add_order_item_meta', $item_id, $values, $cart_item_key );
778
+ }
779
+
780
+ // Store fees
781
+ foreach ( WC()->cart->get_fees() as $fee_key => $fee ) {
782
+ $item_id = $order->add_fee( $fee );
783
+
784
+ if ( ! $item_id ) {
785
+ throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 526 ) );
786
+ }
787
+
788
+ // Allow plugins to add order item meta to fees
789
+ do_action( 'woocommerce_add_order_fee_meta', $order_id, $item_id, $fee, $fee_key );
790
+ }
791
+
792
+ // Store tax rows
793
+ foreach ( array_keys( WC()->cart->taxes + WC()->cart->shipping_taxes ) as $tax_rate_id ) {
794
+ if ( $tax_rate_id && ! $order->add_tax( $tax_rate_id, WC()->cart->get_tax_amount( $tax_rate_id ), WC()->cart->get_shipping_tax_amount( $tax_rate_id ) ) && apply_filters( 'woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated' ) !== $tax_rate_id ) {
795
+ throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 528 ) );
796
+ }
797
+ }
798
+
799
+ // Store coupons
800
+ foreach ( WC()->cart->get_coupons() as $code => $coupon ) {
801
+ if ( ! $order->add_coupon( $code, WC()->cart->get_coupon_discount_amount( $code ), WC()->cart->get_coupon_discount_tax_amount( $code ) ) ) {
802
+ throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 529 ) );
803
+ }
804
+ }
805
+
806
+ // Billing address
807
+ $billing_address = array();
808
+ if ( ! empty( $data['token']['card'] ) ) {
809
+ // Name from Stripe is a full name string.
810
+ $name = explode( ' ', $data['token']['card']['name'] );
811
+ $lastname = array_pop( $name );
812
+ $firstname = implode( ' ', $name );
813
+ $billing_address['first_name'] = $firstname;
814
+ $billing_address['last_name'] = $lastname;
815
+ $billing_address['email'] = $data['shippingContact']['emailAddress'];
816
+ $billing_address['phone'] = $data['shippingContact']['phoneNumber'];
817
+ $billing_address['country'] = $data['token']['card']['country'];
818
+ $billing_address['address_1'] = $data['token']['card']['address_line1'];
819
+ $billing_address['address_2'] = $data['token']['card']['address_line2'];
820
+ $billing_address['city'] = $data['token']['card']['address_city'];
821
+ $billing_address['state'] = $data['token']['card']['address_state'];
822
+ $billing_address['postcode'] = $data['token']['card']['address_zip'];
823
+ }
824
+
825
+ // Shipping address.
826
+ $shipping_address = array();
827
+ if ( WC()->cart->needs_shipping() && ! empty( $data['shippingContact'] ) ) {
828
+ $shipping_address['first_name'] = $data['shippingContact']['givenName'];
829
+ $shipping_address['last_name'] = $data['shippingContact']['familyName'];
830
+ $shipping_address['email'] = $data['shippingContact']['emailAddress'];
831
+ $shipping_address['phone'] = $data['shippingContact']['phoneNumber'];
832
+ $shipping_address['country'] = $data['shippingContact']['countryCode'];
833
+ $shipping_address['address_1'] = $data['shippingContact']['addressLines'][0];
834
+ $shipping_address['address_2'] = $data['shippingContact']['addressLines'][1];
835
+ $shipping_address['city'] = $data['shippingContact']['locality'];
836
+ $shipping_address['state'] = $data['shippingContact']['administrativeArea'];
837
+ $shipping_address['postcode'] = $data['shippingContact']['postalCode'];
838
+ } elseif ( ! empty( $data['shippingContact'] ) ) {
839
+ $shipping_address['first_name'] = $firstname;
840
+ $shipping_address['last_name'] = $lastname;
841
+ $shipping_address['email'] = $data['shippingContact']['emailAddress'];
842
+ $shipping_address['phone'] = $data['shippingContact']['phoneNumber'];
843
+ $shipping_address['country'] = $data['token']['card']['country'];
844
+ $shipping_address['address_1'] = $data['token']['card']['address_line1'];
845
+ $shipping_address['address_2'] = $data['token']['card']['address_line2'];
846
+ $shipping_address['city'] = $data['token']['card']['address_city'];
847
+ $shipping_address['state'] = $data['token']['card']['address_state'];
848
+ $shipping_address['postcode'] = $data['token']['card']['address_zip'];
849
+ }
850
+
851
+ $order->set_address( $billing_address, 'billing' );
852
+ $order->set_address( $shipping_address, 'shipping' );
853
+
854
+ WC()->shipping->calculate_shipping( WC()->cart->get_shipping_packages() );
855
+
856
+ // Get the rate object selected by user.
857
+ foreach ( WC()->shipping->get_packages() as $package_key => $package ) {
858
+ foreach ( $package['rates'] as $key => $rate ) {
859
+ // Loop through user chosen shipping methods.
860
+ foreach ( WC()->session->get( 'chosen_shipping_methods' ) as $method ) {
861
+ if ( $method === $key ) {
862
+ $order->add_shipping( $rate );
863
+ }
864
+ }
865
+ }
866
+ }
867
+
868
+ $available_gateways = WC()->payment_gateways->get_available_payment_gateways();
869
+ $order->set_payment_method( $available_gateways['stripe'] );
870
+ $order->set_total( WC()->cart->shipping_total, 'shipping' );
871
+ $order->set_total( WC()->cart->get_cart_discount_total(), 'cart_discount' );
872
+ $order->set_total( WC()->cart->get_cart_discount_tax_total(), 'cart_discount_tax' );
873
+ $order->set_total( WC()->cart->tax_total, 'tax' );
874
+ $order->set_total( WC()->cart->shipping_tax_total, 'shipping_tax' );
875
+ $order->set_total( WC()->cart->total );
876
+
877
+ // If we got here, the order was created without problems!
878
+ wc_transaction_query( 'commit' );
879
+
880
+ return $order;
881
+ }
882
+ }
883
+
884
+ new WC_Stripe_Apple_Pay();
includes/class-wc-stripe-customer.php CHANGED
@@ -137,6 +137,10 @@ class WC_Stripe_Customer {
137
  );
138
  }
139
 
 
 
 
 
140
  $args = wp_parse_args( $args, $defaults );
141
  $response = WC_Stripe_API::request( $args, 'customers' );
142
 
@@ -173,7 +177,7 @@ class WC_Stripe_Customer {
173
  }
174
 
175
  $response = WC_Stripe_API::request( array(
176
- 'source' => $token
177
  ), 'customers/' . $this->get_id() . '/sources' );
178
 
179
  if ( is_wp_error( $response ) ) {
@@ -194,7 +198,7 @@ class WC_Stripe_Customer {
194
  $token->set_gateway_id( 'stripe' );
195
  $token->set_card_type( strtolower( $response->brand ) );
196
  $token->set_last4( $response->last4 );
197
- $token->set_expiry_month( $response->exp_month );
198
  $token->set_expiry_year( $response->exp_year );
199
  $token->set_user_id( $this->get_user_id() );
200
  $token->save();
@@ -218,7 +222,7 @@ class WC_Stripe_Customer {
218
 
219
  if ( $this->get_id() && false === ( $cards = get_transient( 'stripe_cards_' . $this->get_id() ) ) ) {
220
  $response = WC_Stripe_API::request( array(
221
- 'limit' => 100
222
  ), 'customers/' . $this->get_id() . '/sources', 'GET' );
223
 
224
  if ( is_wp_error( $response ) ) {
137
  );
138
  }
139
 
140
+ $metadata = array();
141
+
142
+ $defaults['metadata'] = apply_filters( 'wc_stripe_customer_metadata', $metadata, $user );
143
+
144
  $args = wp_parse_args( $args, $defaults );
145
  $response = WC_Stripe_API::request( $args, 'customers' );
146
 
177
  }
178
 
179
  $response = WC_Stripe_API::request( array(
180
+ 'source' => $token,
181
  ), 'customers/' . $this->get_id() . '/sources' );
182
 
183
  if ( is_wp_error( $response ) ) {
198
  $token->set_gateway_id( 'stripe' );
199
  $token->set_card_type( strtolower( $response->brand ) );
200
  $token->set_last4( $response->last4 );
201
+ $token->set_expiry_month( $response->exp_month );
202
  $token->set_expiry_year( $response->exp_year );
203
  $token->set_user_id( $this->get_user_id() );
204
  $token->save();
222
 
223
  if ( $this->get_id() && false === ( $cards = get_transient( 'stripe_cards_' . $this->get_id() ) ) ) {
224
  $response = WC_Stripe_API::request( array(
225
+ 'limit' => 100,
226
  ), 'customers/' . $this->get_id() . '/sources', 'GET' );
227
 
228
  if ( is_wp_error( $response ) ) {
includes/class-wc-stripe-payment-request.php ADDED
@@ -0,0 +1,359 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stripe Payment Request API
4
+ *
5
+ * @package WooCommerce_Stripe/Classes/Payment_Request
6
+ * @since 3.1.0
7
+ * @version 3.1.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * WC_Stripe_Payment_Request class.
16
+ */
17
+ class WC_Stripe_Payment_Request {
18
+
19
+ /**
20
+ * Initialize class actions.
21
+ */
22
+ public function __construct() {
23
+ add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
24
+
25
+ add_action( 'wc_ajax_wc_stripe_get_cart_details', array( $this, 'ajax_get_cart_details' ) );
26
+ add_action( 'wc_ajax_wc_stripe_get_shipping_options', array( $this, 'ajax_get_shipping_options' ) );
27
+ add_action( 'wc_ajax_wc_stripe_update_shipping_method', array( $this, 'ajax_update_shipping_method' ) );
28
+ add_action( 'wc_ajax_wc_stripe_create_order', array( $this, 'ajax_create_order' ) );
29
+ }
30
+
31
+ /**
32
+ * Check if Stripe gateway is enabled.
33
+ *
34
+ * @return bool
35
+ */
36
+ protected function is_activated() {
37
+ $options = get_option( 'woocommerce_stripe_settings', array() );
38
+ $enabled = isset( $options['enabled'] ) && 'yes' === $options['enabled'];
39
+ $stripe_checkout = isset( $options['stripe_checkout'] ) && 'yes' !== $options['stripe_checkout'];
40
+ $request_payment_api = isset( $options['request_payment_api'] ) && 'yes' === $options['request_payment_api'];
41
+
42
+ return $enabled && $stripe_checkout && $request_payment_api && is_ssl();
43
+ }
44
+
45
+ /**
46
+ * Get publishable key.
47
+ *
48
+ * @return string
49
+ */
50
+ protected function get_publishable_key() {
51
+ $options = get_option( 'woocommerce_stripe_settings', array() );
52
+
53
+ if ( empty( $options ) ) {
54
+ return '';
55
+ }
56
+
57
+ return 'yes' === $options['testmode'] ? $options['test_publishable_key'] : $options['publishable_key'];
58
+ }
59
+
60
+ /**
61
+ * Load public scripts.
62
+ */
63
+ public function scripts() {
64
+ // Load PaymentRequest only on cart for now.
65
+ if ( ! is_cart() ) {
66
+ return;
67
+ }
68
+
69
+ if ( ! $this->is_activated() ) {
70
+ return;
71
+ }
72
+
73
+ $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
74
+
75
+ wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
76
+ wp_enqueue_script( 'google-payment-request-shim', 'https://storage.googleapis.com/prshim/v1/payment-shim.js', '', '1.0', false );
77
+ wp_enqueue_script( 'wc-stripe-payment-request', plugins_url( 'assets/js/payment-request' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'jquery', 'stripe' ), WC_STRIPE_VERSION, true );
78
+
79
+ wp_localize_script(
80
+ 'wc-stripe-payment-request',
81
+ 'wcStripePaymentRequestParams',
82
+ array(
83
+ 'ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
84
+ 'stripe' => array(
85
+ 'key' => $this->get_publishable_key(),
86
+ 'allow_prepaid_card' => apply_filters( 'wc_stripe_allow_prepaid_card', true ) ? 'yes' : 'no',
87
+ ),
88
+ 'nonce' => array(
89
+ 'payment' => wp_create_nonce( 'wc-stripe-payment-request' ),
90
+ 'shipping' => wp_create_nonce( 'wc-stripe-payment-request-shipping' ),
91
+ 'update_shipping' => wp_create_nonce( 'wc-stripe-update-shipping-method' ),
92
+ 'checkout' => wp_create_nonce( 'woocommerce-process_checkout' ),
93
+ ),
94
+ 'i18n' => array(
95
+ 'no_prepaid_card' => __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' ),
96
+ /* translators: Do not translate the [option] placeholder */
97
+ 'unknown_shipping' => __( 'Unknown shipping option "[option]".', 'woocommerce-gateway-stripe' ),
98
+ ),
99
+ )
100
+ );
101
+ }
102
+
103
+ /**
104
+ * Get cart details.
105
+ */
106
+ public function ajax_get_cart_details() {
107
+ check_ajax_referer( 'wc-stripe-payment-request', 'security' );
108
+
109
+ if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
110
+ define( 'WOOCOMMERCE_CART', true );
111
+ }
112
+
113
+ WC()->cart->calculate_totals();
114
+
115
+ $currency = get_woocommerce_currency();
116
+
117
+ // Set mandatory payment details.
118
+ $data = array(
119
+ 'shipping_required' => WC()->cart->needs_shipping(),
120
+ 'order_data' => array(
121
+ 'total' => array(
122
+ 'label' => __( 'Total', 'woocommerce-gateway-stripe' ),
123
+ 'amount' => array(
124
+ 'value' => max( 0, apply_filters( 'woocommerce_calculated_total', round( WC()->cart->cart_contents_total + WC()->cart->fee_total + WC()->cart->tax_total, WC()->cart->dp ), WC()->cart ) ),
125
+ 'currency' => $currency,
126
+ ),
127
+ ),
128
+ // Include line items such as subtotal, fees and taxes. No shipping option is provided here because it is not chosen yet.
129
+ 'displayItems' => $this->compute_display_items( null ),
130
+ ),
131
+ );
132
+
133
+ wp_send_json( $data );
134
+ }
135
+
136
+ /**
137
+ * Calculate and set shipping method.
138
+ *
139
+ * @since 3.1.0
140
+ * @version 3.1.0
141
+ * @param array $address
142
+ */
143
+ public function calculate_shipping( $address = array() ) {
144
+ $country = $address['country'];
145
+ $state = $address['state'];
146
+ $postcode = $address['postcode'];
147
+ $city = $address['city'];
148
+ $address_1 = $address['address'];
149
+ $address_2 = $address['address_2'];
150
+
151
+ WC()->shipping->reset_shipping();
152
+
153
+ if ( $postcode && WC_Validation::is_postcode( $postcode, $country ) ) {
154
+ $postcode = wc_format_postcode( $postcode, $country );
155
+ }
156
+
157
+ if ( $country ) {
158
+ WC()->customer->set_location( $country, $state, $postcode, $city );
159
+ WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
160
+ } else {
161
+ WC()->customer->set_to_base();
162
+ WC()->customer->set_shipping_to_base();
163
+ }
164
+
165
+ WC()->customer->calculated_shipping( true );
166
+
167
+ $packages = array();
168
+
169
+ $packages[0]['contents'] = WC()->cart->get_cart();
170
+ $packages[0]['contents_cost'] = 0;
171
+ $packages[0]['applied_coupons'] = WC()->cart->applied_coupons;
172
+ $packages[0]['user']['ID'] = get_current_user_id();
173
+ $packages[0]['destination']['country'] = $country;
174
+ $packages[0]['destination']['state'] = $state;
175
+ $packages[0]['destination']['postcode'] = $postcode;
176
+ $packages[0]['destination']['city'] = $city;
177
+ $packages[0]['destination']['address'] = $address_1;
178
+ $packages[0]['destination']['address_2'] = $address_2;
179
+
180
+ foreach ( WC()->cart->get_cart() as $item ) {
181
+ if ( $item['data']->needs_shipping() ) {
182
+ if ( isset( $item['line_total'] ) ) {
183
+ $packages[0]['contents_cost'] += $item['line_total'];
184
+ }
185
+ }
186
+ }
187
+
188
+ $packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages );
189
+
190
+ WC()->shipping->calculate_shipping( $packages );
191
+ }
192
+
193
+ /**
194
+ * Get shipping options.
195
+ *
196
+ * @see WC_Cart::get_shipping_packages().
197
+ * @see WC_Shipping::calculate_shipping().
198
+ * @see WC_Shipping::get_packages().
199
+ */
200
+ public function ajax_get_shipping_options() {
201
+ check_ajax_referer( 'wc-stripe-payment-request-shipping', 'security' );
202
+
203
+ // Set the shipping package.
204
+ $posted = filter_input_array( INPUT_POST, array(
205
+ 'country' => FILTER_SANITIZE_STRING,
206
+ 'state' => FILTER_SANITIZE_STRING,
207
+ 'postcode' => FILTER_SANITIZE_STRING,
208
+ 'city' => FILTER_SANITIZE_STRING,
209
+ 'address' => FILTER_SANITIZE_STRING,
210
+ 'address_2' => FILTER_SANITIZE_STRING,
211
+ ) );
212
+
213
+ $this->calculate_shipping( $posted );
214
+
215
+ // Set the shipping options.
216
+ $currency = get_woocommerce_currency();
217
+ $data = array();
218
+
219
+ $packages = WC()->shipping->get_packages();
220
+
221
+ if ( ! empty( $packages ) && WC()->customer->has_calculated_shipping() ) {
222
+ foreach ( $packages as $package_key => $package ) {
223
+ if ( empty( $package['rates'] ) ) {
224
+ break;
225
+ }
226
+
227
+ foreach ( $package['rates'] as $key => $rate ) {
228
+ $data[] = array(
229
+ 'id' => $rate->id,
230
+ 'label' => $rate->label,
231
+ 'amount' => array(
232
+ 'currency' => $currency,
233
+ 'value' => $rate->cost,
234
+ ),
235
+ 'selected' => false,
236
+ );
237
+ }
238
+ }
239
+ }
240
+
241
+ // Auto select when have only one shipping method available.
242
+ if ( 1 === count( $data ) ) {
243
+ $data[0]['selected'] = true;
244
+ }
245
+
246
+ wp_send_json( $data );
247
+ }
248
+
249
+ /**
250
+ * Update shipping method.
251
+ */
252
+ public function ajax_update_shipping_method() {
253
+ check_ajax_referer( 'wc-stripe-update-shipping-method', 'security' );
254
+
255
+ if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
256
+ define( 'WOOCOMMERCE_CART', true );
257
+ }
258
+
259
+ $chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
260
+ $shipping_method = filter_input( INPUT_POST, 'shipping_method', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
261
+
262
+ if ( is_array( $shipping_method ) ) {
263
+ foreach ( $shipping_method as $i => $value ) {
264
+ $chosen_shipping_methods[ $i ] = wc_clean( $value );
265
+ }
266
+ }
267
+
268
+ WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
269
+
270
+ WC()->cart->calculate_totals();
271
+
272
+ // Send back the new cart total and line items to be displayed, such as subtotal, shipping rate(s), fees and taxes.
273
+ $data = array(
274
+ 'total' => WC()->cart->total,
275
+ 'items' => $this->compute_display_items( $shipping_method[0] ),
276
+ );
277
+
278
+ wp_send_json( $data );
279
+ }
280
+
281
+ /**
282
+ * Create order.
283
+ */
284
+ public function ajax_create_order() {
285
+ if ( WC()->cart->is_empty() ) {
286
+ wp_send_json_error( __( 'Empty cart', 'woocommerce-gateway-stripe' ) );
287
+ }
288
+
289
+ if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
290
+ define( 'WOOCOMMERCE_CHECKOUT', true );
291
+ }
292
+
293
+ WC()->checkout()->process_checkout();
294
+
295
+ die( 0 );
296
+ }
297
+
298
+ /**
299
+ * Compute display items to be included in the 'displayItems' key of the PaymentDetails.
300
+ *
301
+ * @param string shipping_method_id If shipping method ID is provided, will include display items about shipping.
302
+ */
303
+ protected function compute_display_items( $shipping_method_id ) {
304
+ $currency = get_woocommerce_currency();
305
+ $items = array(
306
+ // Subtotal excluding tax, because taxes is a separate item, below.
307
+ array(
308
+ 'label' => __( 'Subtotal', 'woocommerce-gateway-stripe' ),
309
+ 'amount' => array(
310
+ 'value' => max( 0, round( WC()->cart->subtotal_ex_tax, WC()->cart->dp ) ),
311
+ 'currency' => $currency,
312
+ ),
313
+ ),
314
+ );
315
+ // If a chosen shipping option was provided, add line item(s) for it and include the shipping tax.
316
+ $tax_total = max( 0, round( WC()->cart->tax_total, WC()->cart->dp ) );
317
+ if ( $shipping_method_id ) {
318
+ $tax_total = max( 0, round( WC()->cart->tax_total + WC()->cart->shipping_tax_total, WC()->cart->dp ) );
319
+ // Look through the package rates for $shipping_method_id, and when found, add a line item.
320
+ foreach ( WC()->shipping->get_packages() as $package_key => $package ) {
321
+ foreach ( $package['rates'] as $key => $rate ) {
322
+ if ( $rate->id == $shipping_method_id ) {
323
+ $items[] = array(
324
+ 'label' => $rate->label,
325
+ 'amount' => array(
326
+ 'value' => $rate->cost,
327
+ 'currency' => $currency,
328
+ ),
329
+ );
330
+ break;
331
+ }
332
+ }
333
+ }
334
+ }
335
+ // Include fees and taxes as display items.
336
+ foreach ( WC()->cart->fees as $key => $fee ) {
337
+ $items[] = array(
338
+ 'label' => $fee->name,
339
+ 'amount' => array(
340
+ 'currency' => $currency,
341
+ 'value' => $fee->amount,
342
+ ),
343
+ );
344
+ }
345
+ // The tax total may include the shipping taxes if a shipping option is provided.
346
+ if ( 0 < $tax_total ) {
347
+ $items[] = array(
348
+ 'label' => __( 'Tax', 'woocommerce-gateway-stripe' ),
349
+ 'amount' => array(
350
+ 'currency' => $currency,
351
+ 'value' => $tax_total,
352
+ ),
353
+ );
354
+ }
355
+ return $items;
356
+ }
357
+ }
358
+
359
+ new WC_Stripe_Payment_Request();
includes/legacy/class-wc-gateway-stripe.php CHANGED
@@ -441,6 +441,7 @@ class WC_Gateway_Stripe extends WC_Payment_Gateway {
441
 
442
  // Handle payment
443
  if ( $order->get_total() > 0 ) {
 
444
  if ( $order->get_total() * 100 < WC_Stripe::get_minimum_amount() ) {
445
  throw new Exception( 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 ) ) );
446
  }
441
 
442
  // Handle payment
443
  if ( $order->get_total() > 0 ) {
444
+
445
  if ( $order->get_total() * 100 < WC_Stripe::get_minimum_amount() ) {
446
  throw new Exception( 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 ) ) );
447
  }
includes/settings-stripe.php CHANGED
@@ -10,7 +10,7 @@ return apply_filters( 'wc_stripe_settings',
10
  'label' => __( 'Enable Stripe', 'woocommerce-gateway-stripe' ),
11
  'type' => 'checkbox',
12
  'description' => '',
13
- 'default' => 'no'
14
  ),
15
  'title' => array(
16
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
@@ -23,7 +23,7 @@ return apply_filters( 'wc_stripe_settings',
23
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
24
  'type' => 'text',
25
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
26
- 'default' => __( 'Pay with your credit card via Stripe.', 'woocommerce-gateway-stripe'),
27
  'desc_tip' => true,
28
  ),
29
  'testmode' => array(
@@ -62,6 +62,13 @@ return apply_filters( 'wc_stripe_settings',
62
  'default' => '',
63
  'desc_tip' => true,
64
  ),
 
 
 
 
 
 
 
65
  'capture' => array(
66
  'title' => __( 'Capture', 'woocommerce-gateway-stripe' ),
67
  'label' => __( 'Capture charge immediately', 'woocommerce-gateway-stripe' ),
@@ -124,6 +131,41 @@ return apply_filters( 'wc_stripe_settings',
124
  'default' => '',
125
  'desc_tip' => true,
126
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  'saved_cards' => array(
128
  'title' => __( 'Saved Cards', 'woocommerce-gateway-stripe' ),
129
  'label' => __( 'Enable Payment via Saved Cards', 'woocommerce-gateway-stripe' ),
10
  'label' => __( 'Enable Stripe', 'woocommerce-gateway-stripe' ),
11
  'type' => 'checkbox',
12
  'description' => '',
13
+ 'default' => 'no',
14
  ),
15
  'title' => array(
16
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
23
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
24
  'type' => 'text',
25
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
26
+ 'default' => __( 'Pay with your credit card via Stripe.', 'woocommerce-gateway-stripe' ),
27
  'desc_tip' => true,
28
  ),
29
  'testmode' => array(
62
  'default' => '',
63
  'desc_tip' => true,
64
  ),
65
+ 'statement_descriptor' => array(
66
+ 'title' => __( 'Statement Descriptor', 'woocommerce-gateway-stripe' ),
67
+ 'type' => 'text',
68
+ 'description' => __( 'Extra information about a charge. This will appear on your customer’s credit card statement.', 'woocommerce-gateway-stripe' ),
69
+ 'default' => '',
70
+ 'desc_tip' => true,
71
+ ),
72
  'capture' => array(
73
  'title' => __( 'Capture', 'woocommerce-gateway-stripe' ),
74
  'label' => __( 'Capture charge immediately', 'woocommerce-gateway-stripe' ),
131
  'default' => '',
132
  'desc_tip' => true,
133
  ),
134
+ 'request_payment_api' => array(
135
+ 'title' => __( 'Payment Request API', 'woocommerce-gateway-stripe' ),
136
+ 'label' => __( 'Enable Payment Request API', 'woocommerce-gateway-stripe' ),
137
+ 'type' => 'checkbox',
138
+ 'description' => __( 'If enabled, users will be able to pay using the Payment Request API if supported by the browser.', 'woocommerce-gateway-stripe' ),
139
+ 'default' => 'no',
140
+ 'desc_tip' => true,
141
+ ),
142
+ 'apple_pay' => array(
143
+ 'title' => __( 'Apple Pay', 'woocommerce-gateway-stripe' ),
144
+ 'label' => sprintf( __( 'Enable Apple Pay. %1$sBy using Apple Pay, you agree to %2$s and %3$s\'s terms of service.', 'woocommerce-gateway-stripe' ), '<br />', '<a href="https://stripe.com/apple-pay/legal" target="_blank">Stripe</a>', '<a href="https://developer.apple.com/apple-pay/acceptable-use-guidelines-for-websites/" target="_blank">Apple</a>' ),
145
+ 'type' => 'checkbox',
146
+ 'description' => __( 'If enabled, users will be able to pay with Apple Pay.', 'woocommerce-gateway-stripe' ),
147
+ 'default' => 'yes',
148
+ 'desc_tip' => true,
149
+ ),
150
+ 'apple_pay_button' => array(
151
+ 'title' => __( 'Apple Pay Button Style', 'woocommerce-gateway-stripe' ),
152
+ 'label' => __( 'Button Style', 'woocommerce-gateway-stripe' ),
153
+ 'type' => 'select',
154
+ 'description' => __( 'Select the button style you would like to show.', 'woocommerce-gateway-stripe' ),
155
+ 'default' => 'black',
156
+ 'desc_tip' => true,
157
+ 'options' => array(
158
+ 'black' => __( 'Black', 'woocommerce-gateway-stripe' ),
159
+ 'white' => __( 'White', 'woocommerce-gateway-stripe' ),
160
+ ),
161
+ ),
162
+ 'apple_pay_button_lang' => array(
163
+ 'title' => __( 'Apple Pay Button Language', 'woocommerce-gateway-stripe' ),
164
+ 'description' => __( 'Enter the 2 letter ISO code for the language you would like your Apple Pay Button to display in. Reference available ISO codes here <code>http://www.w3schools.com/tags/ref_language_codes.asp</code>', 'woocommerce-gateway-stripe' ),
165
+ 'type' => 'text',
166
+ 'default' => 'en',
167
+ 'desc_tip' => false,
168
+ ),
169
  'saved_cards' => array(
170
  'title' => __( 'Saved Cards', 'woocommerce-gateway-stripe' ),
171
  'label' => __( 'Enable Payment via Saved Cards', 'woocommerce-gateway-stripe' ),
languages/index.html DELETED
File without changes
languages/woocommerce-gateway-stripe.pot CHANGED
@@ -1,8 +1,8 @@
1
  msgid ""
2
  msgstr ""
3
  "Project-Id-Version: WooCommerce Stripe Gateway\n"
4
- "POT-Creation-Date: 2016-09-24 08:19-0800\n"
5
- "PO-Revision-Date: 2016-09-24 08:19-0800\n"
6
  "Last-Translator: \n"
7
  "Language-Team: \n"
8
  "Language: en_US\n"
@@ -19,52 +19,54 @@ msgstr ""
19
  "X-Poedit-SearchPath-0: .\n"
20
  "X-Poedit-SearchPathExcluded-0: *.js\n"
21
 
22
- #: includes/class-wc-gateway-stripe-addons.php:104
23
- #: includes/class-wc-gateway-stripe-addons.php:150
24
- #: includes/class-wc-gateway-stripe.php:548
 
25
  #: includes/legacy/class-wc-gateway-stripe.php:446
 
26
  msgid ""
27
- "Sorry, the minimum allowed order total is 0.50 to use this payment method."
28
  msgstr ""
29
 
30
- #: includes/class-wc-gateway-stripe-addons.php:117
31
  msgid "Customer not found"
32
  msgstr ""
33
 
34
- #: includes/class-wc-gateway-stripe-addons.php:157
35
  msgid "Unable to store payment details. Please try again."
36
  msgstr ""
37
 
38
- #: includes/class-wc-gateway-stripe-addons.php:218
39
- #: includes/class-wc-gateway-stripe-addons.php:261
40
  #, php-format
41
  msgid "Stripe Transaction Failed (%s)"
42
  msgstr ""
43
 
44
- #: includes/class-wc-gateway-stripe-addons.php:383
45
- #: includes/class-wc-gateway-stripe-addons.php:388
46
  #, php-format
47
- msgid "Via %s card ending in %s"
48
  msgstr ""
49
 
50
- #: includes/class-wc-gateway-stripe.php:88
51
  #: includes/legacy/class-wc-gateway-stripe.php:18
52
  msgid "Stripe"
53
  msgstr ""
54
 
55
- #: includes/class-wc-gateway-stripe.php:89
56
  #: includes/legacy/class-wc-gateway-stripe.php:19
57
  msgid ""
58
  "Stripe works by adding credit card fields on the checkout and then sending "
59
  "the details to Stripe for verification."
60
  msgstr ""
61
 
62
- #: includes/class-wc-gateway-stripe.php:131
63
  #: includes/legacy/class-wc-gateway-stripe.php:60
64
  msgid "Continue to payment"
65
  msgstr ""
66
 
67
- #: includes/class-wc-gateway-stripe.php:135
68
  #: includes/legacy/class-wc-gateway-stripe.php:64
69
  #, php-format
70
  msgid ""
@@ -73,137 +75,178 @@ msgid ""
73
  "documentation \"<a href=\"%s\">Testing Stripe</a>\" for more card numbers."
74
  msgstr ""
75
 
76
- #: includes/class-wc-gateway-stripe.php:222
77
- #: includes/legacy/class-wc-gateway-stripe.php:165
 
 
 
78
  #, php-format
79
- msgid ""
80
- "Stripe is enabled, but the <a href=\"%s\">force SSL option</a> is disabled; "
81
- "your checkout may not be secure! Please enable SSL and ensure your server "
82
- "has a valid SSL certificate - Stripe will only work in test mode."
83
  msgstr ""
84
 
85
- #: includes/class-wc-gateway-stripe.php:262
86
- msgid ""
87
- "This is not a valid live key. Live keys start with \"sk_live_\" and "
88
- "\"pk_live_\"."
89
  msgstr ""
90
 
91
- #: includes/class-wc-gateway-stripe.php:273
92
- msgid ""
93
- "This is not a valid test key. Test keys start with \"sk_test_\" and "
94
- "\"pk_test_\"."
95
  msgstr ""
96
 
97
- #: includes/class-wc-gateway-stripe.php:298
98
- msgid "Add Card"
99
  msgstr ""
100
 
101
- #: includes/class-wc-gateway-stripe.php:309
102
- #: includes/legacy/class-wc-gateway-stripe.php:262
 
 
103
  #, php-format
104
- msgid "%s"
105
  msgstr ""
106
 
107
- #: includes/class-wc-gateway-stripe.php:353
108
- #: includes/legacy/class-wc-gateway-stripe.php:296
109
- msgid "Please accept the terms and conditions first"
 
 
110
  msgstr ""
111
 
112
- #: includes/class-wc-gateway-stripe.php:354
113
- #: includes/legacy/class-wc-gateway-stripe.php:297
114
- msgid "Please fill in required checkout fields first"
 
 
 
 
115
  msgstr ""
116
 
117
- #: includes/class-wc-gateway-stripe.php:375
118
- msgid "Sorry, we're not accepting prepaid cards at this time."
119
  msgstr ""
120
 
121
- #: includes/class-wc-gateway-stripe.php:379
122
  msgid "The card number is not a valid credit card number."
123
  msgstr ""
124
 
125
- #: includes/class-wc-gateway-stripe.php:380
126
  msgid "The card's expiration month is invalid."
127
  msgstr ""
128
 
129
- #: includes/class-wc-gateway-stripe.php:381
130
  msgid "The card's expiration year is invalid."
131
  msgstr ""
132
 
133
- #: includes/class-wc-gateway-stripe.php:382
134
  msgid "The card's security code is invalid."
135
  msgstr ""
136
 
137
- #: includes/class-wc-gateway-stripe.php:383
138
  msgid "The card number is incorrect."
139
  msgstr ""
140
 
141
- #: includes/class-wc-gateway-stripe.php:384
142
  msgid "The card has expired."
143
  msgstr ""
144
 
145
- #: includes/class-wc-gateway-stripe.php:385
146
  msgid "The card's security code is incorrect."
147
  msgstr ""
148
 
149
- #: includes/class-wc-gateway-stripe.php:386
150
  msgid "The card's zip code failed validation."
151
  msgstr ""
152
 
153
- #: includes/class-wc-gateway-stripe.php:387
154
  msgid "The card was declined."
155
  msgstr ""
156
 
157
- #: includes/class-wc-gateway-stripe.php:388
158
  msgid "There is no card on a customer that is being charged."
159
  msgstr ""
160
 
161
- #: includes/class-wc-gateway-stripe.php:389
162
  msgid "An error occurred while processing the card."
163
  msgstr ""
164
 
165
- #: includes/class-wc-gateway-stripe.php:390
166
  msgid "Could not find payment information."
167
  msgstr ""
168
 
169
- #: includes/class-wc-gateway-stripe.php:405
170
- #: includes/legacy/class-wc-gateway-stripe.php:331
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  #, php-format
172
- msgid "%s - Order %s"
173
  msgstr ""
174
 
175
- #: includes/class-wc-gateway-stripe.php:474
 
 
 
 
 
 
 
 
176
  msgid "Invalid payment method. Please input a new card number."
177
  msgstr ""
178
 
179
- #: includes/class-wc-gateway-stripe.php:536
180
  #: includes/legacy/class-wc-gateway-stripe.php:434
181
  msgid "Please enter your card details to make a payment."
182
  msgstr ""
183
 
184
- #: includes/class-wc-gateway-stripe.php:537
185
  #: includes/legacy/class-wc-gateway-stripe.php:435
186
  msgid ""
187
  "Developers: Please make sure that you are including jQuery and there are no "
188
  "JavaScript errors on the page."
189
  msgstr ""
190
 
191
- #: includes/class-wc-gateway-stripe.php:565
192
  msgid "This card is no longer available and has been removed."
193
  msgstr ""
194
 
195
- #: includes/class-wc-gateway-stripe.php:588
196
- #: includes/legacy/class-wc-gateway-stripe.php:481
197
- #, php-format
198
- msgid "Error: %s"
199
- msgstr ""
200
-
201
- #: includes/class-wc-gateway-stripe.php:634 woocommerce-gateway-stripe.php:345
202
  #, php-format
203
  msgid "Stripe charge complete (Charge ID: %s)"
204
  msgstr ""
205
 
206
- #: includes/class-wc-gateway-stripe.php:645
207
  #: includes/legacy/class-wc-gateway-stripe.php:526
208
  #, php-format
209
  msgid ""
@@ -211,29 +254,100 @@ msgid ""
211
  "cancel to remove the pre-authorization."
212
  msgstr ""
213
 
214
- #: includes/class-wc-gateway-stripe.php:659
 
215
  #: includes/legacy/class-wc-gateway-stripe.php:540
216
  msgid "There was a problem adding the card."
217
  msgstr ""
218
 
219
- #: includes/class-wc-gateway-stripe.php:709
220
- #: includes/legacy/class-wc-gateway-stripe.php:590
221
  #, php-format
222
- msgid "Refunded %s - Refund ID: %s - Reason: %s"
223
  msgstr ""
224
 
225
  #: includes/class-wc-stripe-api.php:73
226
  msgid "There was a problem connecting to the payment gateway."
227
  msgstr ""
228
 
229
- #: includes/class-wc-stripe-customer.php:143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  msgid "Could not create Stripe customer."
231
  msgstr ""
232
 
233
- #: includes/class-wc-stripe-customer.php:184
234
  msgid "Unable to add card"
235
  msgstr ""
236
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  #: includes/legacy/class-wc-gateway-stripe-saved-cards.php:50
238
  #: includes/legacy/class-wc-gateway-stripe-saved-cards.php:73
239
  msgid "Unable to make default card, please try again"
@@ -284,6 +398,16 @@ msgstr ""
284
  msgid "Use a new credit card"
285
  msgstr ""
286
 
 
 
 
 
 
 
 
 
 
 
287
  #: includes/legacy/templates/saved-cards.php:1
288
  msgid "Saved cards"
289
  msgstr ""
@@ -363,7 +487,7 @@ msgid "Place the payment gateway in test mode using test API keys."
363
  msgstr ""
364
 
365
  #: includes/settings-stripe.php:38
366
- msgid "Live Secret Key"
367
  msgstr ""
368
 
369
  #: includes/settings-stripe.php:40 includes/settings-stripe.php:47
@@ -372,213 +496,478 @@ msgid "Get your API keys from your stripe account."
372
  msgstr ""
373
 
374
  #: includes/settings-stripe.php:45
375
- msgid "Live Publishable Key"
376
  msgstr ""
377
 
378
  #: includes/settings-stripe.php:52
379
- msgid "Test Secret Key"
380
  msgstr ""
381
 
382
  #: includes/settings-stripe.php:59
383
- msgid "Test Publishable Key"
384
  msgstr ""
385
 
386
  #: includes/settings-stripe.php:66
 
 
 
 
 
 
 
 
 
 
387
  msgid "Capture"
388
  msgstr ""
389
 
390
- #: includes/settings-stripe.php:67
391
  msgid "Capture charge immediately"
392
  msgstr ""
393
 
394
- #: includes/settings-stripe.php:69
395
  msgid ""
396
  "Whether or not to immediately capture the charge. When unchecked, the charge "
397
  "issues an authorization and will need to be captured later. Uncaptured "
398
  "charges expire in 7 days."
399
  msgstr ""
400
 
401
- #: includes/settings-stripe.php:74
402
  msgid "Stripe Checkout"
403
  msgstr ""
404
 
405
- #: includes/settings-stripe.php:75
406
  msgid "Enable Stripe Checkout"
407
  msgstr ""
408
 
409
- #: includes/settings-stripe.php:77
410
  msgid ""
411
  "If enabled, this option shows a \"pay\" button and modal credit card form on "
412
  "the checkout, instead of credit card fields directly on the page."
413
  msgstr ""
414
 
415
- #: includes/settings-stripe.php:82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  msgid "Stripe Checkout locale"
417
  msgstr ""
418
 
419
- #: includes/settings-stripe.php:85
420
  msgid ""
421
  "Language to display in Stripe Checkout modal. Specify Auto to display "
422
  "Checkout in the user's preferred language, if available. English will be "
423
  "used by default."
424
  msgstr ""
425
 
426
- #: includes/settings-stripe.php:89
427
  msgid "Auto"
428
  msgstr ""
429
 
430
- #: includes/settings-stripe.php:90
431
  msgid "Simplified Chinese"
432
  msgstr ""
433
 
434
- #: includes/settings-stripe.php:91
 
 
 
 
435
  msgid "Dutch"
436
  msgstr ""
437
 
438
- #: includes/settings-stripe.php:92
439
  msgid "English"
440
  msgstr ""
441
 
442
- #: includes/settings-stripe.php:93
 
 
 
 
443
  msgid "French"
444
  msgstr ""
445
 
446
- #: includes/settings-stripe.php:94
447
  msgid "German"
448
  msgstr ""
449
 
450
- #: includes/settings-stripe.php:95
451
  msgid "Italian"
452
  msgstr ""
453
 
454
- #: includes/settings-stripe.php:96
455
  msgid "Japanese"
456
  msgstr ""
457
 
458
- #: includes/settings-stripe.php:97
 
 
 
 
459
  msgid "Spanish"
460
  msgstr ""
461
 
462
- #: includes/settings-stripe.php:101
 
 
 
 
463
  msgid "Bitcoin Currency"
464
  msgstr ""
465
 
466
- #: includes/settings-stripe.php:102
467
  msgid "Enable Bitcoin Currency"
468
  msgstr ""
469
 
470
- #: includes/settings-stripe.php:104
471
  msgid ""
472
  "If enabled, an option to accept bitcoin will show on the checkout modal. "
473
  "Note: Stripe Checkout needs to be enabled and store currency must be set to "
474
  "USD."
475
  msgstr ""
476
 
477
- #: includes/settings-stripe.php:109
478
  msgid "Stripe Checkout Image"
479
  msgstr ""
480
 
481
- #: includes/settings-stripe.php:110
482
  msgid ""
483
  "Optionally enter the URL to a 128x128px image of your brand or product. e.g. "
484
  "<code>https://yoursite.com/wp-content/uploads/2013/09/yourimage.jpg</code>"
485
  msgstr ""
486
 
487
- #: includes/settings-stripe.php:116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488
  msgid "Saved Cards"
489
  msgstr ""
490
 
491
- #: includes/settings-stripe.php:117
492
  msgid "Enable Payment via Saved Cards"
493
  msgstr ""
494
 
495
- #: includes/settings-stripe.php:119
496
  msgid ""
497
  "If enabled, users will be able to pay with a saved card during checkout. "
498
  "Card details are saved on Stripe servers, not on your store."
499
  msgstr ""
500
 
501
- #: includes/settings-stripe.php:124
502
  msgid "Logging"
503
  msgstr ""
504
 
505
- #: includes/settings-stripe.php:125
506
  msgid "Log debug messages"
507
  msgstr ""
508
 
509
- #: includes/settings-stripe.php:127
510
  msgid "Save debug messages to the WooCommerce System Status log."
511
  msgstr ""
512
 
513
- #: woocommerce-gateway-stripe.php:188
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
514
  #, php-format
515
- msgid ""
516
- "Stripe is almost ready. To get started, <a href=\"%s\">set your Stripe "
517
- "account keys</a>."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518
  msgstr ""
519
 
520
- #: woocommerce-gateway-stripe.php:199
521
- #, php-format
522
- msgid ""
523
- "The plugin could not be activated. The minimum PHP version required for this "
524
- "plugin is %1$s. You are running %2$s."
525
  msgstr ""
526
 
527
- #: woocommerce-gateway-stripe.php:201
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
528
  #, php-format
529
- msgid ""
530
- "The WooCommerce Stripe plugin has been deactivated. The minimum PHP version "
531
- "required for this plugin is %1$s. You are running %2$s."
 
 
 
 
 
532
  msgstr ""
533
 
534
- #: woocommerce-gateway-stripe.php:207
535
- msgid "The plugin could not be activated. WooCommerce is not activated."
 
 
 
 
 
536
  msgstr ""
537
 
538
- #: woocommerce-gateway-stripe.php:212
539
  #, php-format
540
  msgid ""
541
- "The plugin could not be activated. The minimum WooCommerce version required "
542
- "for this plugin is %1$s. You are running %2$s."
543
  msgstr ""
544
 
545
- #: woocommerce-gateway-stripe.php:214
546
  #, php-format
547
  msgid ""
548
- "The WooCommerce Stripe plugin has been deactivated. The minimum WooCommerce "
549
- "version required for this plugin is %1$s. You are running %2$s."
550
  msgstr ""
551
 
552
- #: woocommerce-gateway-stripe.php:221
553
- msgid "The plugin could not be activated. cURL is not installed."
554
  msgstr ""
555
 
556
- #: woocommerce-gateway-stripe.php:223
 
557
  msgid ""
558
- "The WooCommerce Stripe plugin has been deactivated. cURL is not installed."
 
559
  msgstr ""
560
 
561
- #: woocommerce-gateway-stripe.php:238
 
 
 
 
562
  msgid "Settings"
563
  msgstr ""
564
 
565
- #: woocommerce-gateway-stripe.php:239
566
  msgid "Docs"
567
  msgstr ""
568
 
569
- #: woocommerce-gateway-stripe.php:240
570
  msgid "Support"
571
  msgstr ""
572
 
573
- #: woocommerce-gateway-stripe.php:343
 
 
 
 
 
 
 
 
 
 
 
 
 
574
  msgid "Unable to capture charge!"
575
  msgstr ""
576
 
577
- #: woocommerce-gateway-stripe.php:377
578
  msgid "Unable to refund charge!"
579
  msgstr ""
580
 
581
- #: woocommerce-gateway-stripe.php:379
582
  #, php-format
583
  msgid "Stripe charge refunded (Charge ID: %s)"
584
  msgstr ""
1
  msgid ""
2
  msgstr ""
3
  "Project-Id-Version: WooCommerce Stripe Gateway\n"
4
+ "POT-Creation-Date: 2017-03-13 07:42-0800\n"
5
+ "PO-Revision-Date: 2017-03-13 07:42-0800\n"
6
  "Last-Translator: \n"
7
  "Language-Team: \n"
8
  "Language: en_US\n"
19
  "X-Poedit-SearchPath-0: .\n"
20
  "X-Poedit-SearchPathExcluded-0: *.js\n"
21
 
22
+ #: includes/class-wc-gateway-stripe-addons.php:106
23
+ #: includes/class-wc-gateway-stripe-addons.php:153
24
+ #: includes/class-wc-gateway-stripe.php:737
25
+ #: includes/class-wc-stripe-apple-pay.php:556
26
  #: includes/legacy/class-wc-gateway-stripe.php:446
27
+ #, php-format
28
  msgid ""
29
+ "Sorry, the minimum allowed order total is %1$s to use this payment method."
30
  msgstr ""
31
 
32
+ #: includes/class-wc-gateway-stripe-addons.php:119
33
  msgid "Customer not found"
34
  msgstr ""
35
 
36
+ #: includes/class-wc-gateway-stripe-addons.php:160
37
  msgid "Unable to store payment details. Please try again."
38
  msgstr ""
39
 
40
+ #: includes/class-wc-gateway-stripe-addons.php:217
41
+ #: includes/class-wc-gateway-stripe-addons.php:260
42
  #, php-format
43
  msgid "Stripe Transaction Failed (%s)"
44
  msgstr ""
45
 
46
+ #: includes/class-wc-gateway-stripe-addons.php:384
47
+ #: includes/class-wc-gateway-stripe-addons.php:389
48
  #, php-format
49
+ msgid "Via %1$s card ending in %2$s"
50
  msgstr ""
51
 
52
+ #: includes/class-wc-gateway-stripe.php:123
53
  #: includes/legacy/class-wc-gateway-stripe.php:18
54
  msgid "Stripe"
55
  msgstr ""
56
 
57
+ #: includes/class-wc-gateway-stripe.php:124
58
  #: includes/legacy/class-wc-gateway-stripe.php:19
59
  msgid ""
60
  "Stripe works by adding credit card fields on the checkout and then sending "
61
  "the details to Stripe for verification."
62
  msgstr ""
63
 
64
+ #: includes/class-wc-gateway-stripe.php:172
65
  #: includes/legacy/class-wc-gateway-stripe.php:60
66
  msgid "Continue to payment"
67
  msgstr ""
68
 
69
+ #: includes/class-wc-gateway-stripe.php:176
70
  #: includes/legacy/class-wc-gateway-stripe.php:64
71
  #, php-format
72
  msgid ""
75
  "documentation \"<a href=\"%s\">Testing Stripe</a>\" for more card numbers."
76
  msgstr ""
77
 
78
+ #: includes/class-wc-gateway-stripe.php:282
79
+ msgid "Unable to verify domain - missing secret key."
80
+ msgstr ""
81
+
82
+ #: includes/class-wc-gateway-stripe.php:302
83
  #, php-format
84
+ msgid "Unable to verify domain - %s"
 
 
 
85
  msgstr ""
86
 
87
+ #: includes/class-wc-gateway-stripe.php:327
88
+ msgid "Unable to create domain association folder to domain root."
 
 
89
  msgstr ""
90
 
91
+ #: includes/class-wc-gateway-stripe.php:332
92
+ msgid "Unable to copy domain association file to domain root."
 
 
93
  msgstr ""
94
 
95
+ #: includes/class-wc-gateway-stripe.php:347
96
+ msgid "Your domain has been verified with Apple Pay!"
97
  msgstr ""
98
 
99
+ #: includes/class-wc-gateway-stripe.php:354
100
+ #: includes/class-wc-gateway-stripe.php:787
101
+ #: includes/class-wc-stripe-apple-pay.php:590
102
+ #: includes/legacy/class-wc-gateway-stripe.php:481
103
  #, php-format
104
+ msgid "Error: %s"
105
  msgstr ""
106
 
107
+ #: includes/class-wc-gateway-stripe.php:372
108
+ #, php-format
109
+ msgid ""
110
+ "Apple Pay domain verification failed. Please check the %1$slog%2$s to see "
111
+ "the issue."
112
  msgstr ""
113
 
114
+ #: includes/class-wc-gateway-stripe.php:377
115
+ #: includes/legacy/class-wc-gateway-stripe.php:165
116
+ #, php-format
117
+ msgid ""
118
+ "Stripe is enabled, but the <a href=\"%s\">force SSL option</a> is disabled; "
119
+ "your checkout may not be secure! Please enable SSL and ensure your server "
120
+ "has a valid SSL certificate - Stripe will only work in test mode."
121
  msgstr ""
122
 
123
+ #: includes/class-wc-gateway-stripe.php:426
124
+ msgid "Add Card"
125
  msgstr ""
126
 
127
+ #: includes/class-wc-gateway-stripe.php:473
128
  msgid "The card number is not a valid credit card number."
129
  msgstr ""
130
 
131
+ #: includes/class-wc-gateway-stripe.php:474
132
  msgid "The card's expiration month is invalid."
133
  msgstr ""
134
 
135
+ #: includes/class-wc-gateway-stripe.php:475
136
  msgid "The card's expiration year is invalid."
137
  msgstr ""
138
 
139
+ #: includes/class-wc-gateway-stripe.php:476
140
  msgid "The card's security code is invalid."
141
  msgstr ""
142
 
143
+ #: includes/class-wc-gateway-stripe.php:477
144
  msgid "The card number is incorrect."
145
  msgstr ""
146
 
147
+ #: includes/class-wc-gateway-stripe.php:478
148
  msgid "The card has expired."
149
  msgstr ""
150
 
151
+ #: includes/class-wc-gateway-stripe.php:479
152
  msgid "The card's security code is incorrect."
153
  msgstr ""
154
 
155
+ #: includes/class-wc-gateway-stripe.php:480
156
  msgid "The card's zip code failed validation."
157
  msgstr ""
158
 
159
+ #: includes/class-wc-gateway-stripe.php:481
160
  msgid "The card was declined."
161
  msgstr ""
162
 
163
+ #: includes/class-wc-gateway-stripe.php:482
164
  msgid "There is no card on a customer that is being charged."
165
  msgstr ""
166
 
167
+ #: includes/class-wc-gateway-stripe.php:483
168
  msgid "An error occurred while processing the card."
169
  msgstr ""
170
 
171
+ #: includes/class-wc-gateway-stripe.php:484
172
  msgid "Could not find payment information."
173
  msgstr ""
174
 
175
+ #: includes/class-wc-gateway-stripe.php:505
176
+ msgid ""
177
+ "This is not a valid live key. Live keys start with \"sk_live_\" and "
178
+ "\"pk_live_\"."
179
+ msgstr ""
180
+
181
+ #: includes/class-wc-gateway-stripe.php:506
182
+ msgid ""
183
+ "This is not a valid test key. Test keys start with \"sk_test_\" and "
184
+ "\"pk_test_\"."
185
+ msgstr ""
186
+
187
+ #: includes/class-wc-gateway-stripe.php:507
188
+ msgid "Re-verify Domain"
189
+ msgstr ""
190
+
191
+ #: includes/class-wc-gateway-stripe.php:508
192
+ msgid "Missing Secret Key. Please set the secret key field above and re-try."
193
+ msgstr ""
194
+
195
+ #: includes/class-wc-gateway-stripe.php:543
196
+ #: includes/legacy/class-wc-gateway-stripe.php:296
197
+ msgid "Please accept the terms and conditions first"
198
+ msgstr ""
199
+
200
+ #: includes/class-wc-gateway-stripe.php:544
201
+ #: includes/legacy/class-wc-gateway-stripe.php:297
202
+ msgid "Please fill in required checkout fields first"
203
+ msgstr ""
204
+
205
+ #: includes/class-wc-gateway-stripe.php:562
206
+ #: includes/class-wc-stripe-payment-request.php:95
207
+ msgid "Sorry, we're not accepting prepaid cards at this time."
208
+ msgstr ""
209
+
210
+ #: includes/class-wc-gateway-stripe.php:582
211
+ #: includes/class-wc-stripe-apple-pay.php:610
212
  #, php-format
213
+ msgid "%1$s - Order %2$s"
214
  msgstr ""
215
 
216
+ #: includes/class-wc-gateway-stripe.php:596
217
+ msgid "Customer Name"
218
+ msgstr ""
219
+
220
+ #: includes/class-wc-gateway-stripe.php:597
221
+ msgid "Customer Email"
222
+ msgstr ""
223
+
224
+ #: includes/class-wc-gateway-stripe.php:660
225
  msgid "Invalid payment method. Please input a new card number."
226
  msgstr ""
227
 
228
+ #: includes/class-wc-gateway-stripe.php:725
229
  #: includes/legacy/class-wc-gateway-stripe.php:434
230
  msgid "Please enter your card details to make a payment."
231
  msgstr ""
232
 
233
+ #: includes/class-wc-gateway-stripe.php:726
234
  #: includes/legacy/class-wc-gateway-stripe.php:435
235
  msgid ""
236
  "Developers: Please make sure that you are including jQuery and there are no "
237
  "JavaScript errors on the page."
238
  msgstr ""
239
 
240
+ #: includes/class-wc-gateway-stripe.php:754
241
  msgid "This card is no longer available and has been removed."
242
  msgstr ""
243
 
244
+ #: includes/class-wc-gateway-stripe.php:845 woocommerce-gateway-stripe.php:470
 
 
 
 
 
 
245
  #, php-format
246
  msgid "Stripe charge complete (Charge ID: %s)"
247
  msgstr ""
248
 
249
+ #: includes/class-wc-gateway-stripe.php:856
250
  #: includes/legacy/class-wc-gateway-stripe.php:526
251
  #, php-format
252
  msgid ""
254
  "cancel to remove the pre-authorization."
255
  msgstr ""
256
 
257
+ #: includes/class-wc-gateway-stripe.php:870
258
+ #: includes/class-wc-gateway-stripe.php:879
259
  #: includes/legacy/class-wc-gateway-stripe.php:540
260
  msgid "There was a problem adding the card."
261
  msgstr ""
262
 
263
+ #: includes/class-wc-gateway-stripe.php:931
 
264
  #, php-format
265
+ msgid "Refunded %1$s - Refund ID: %2$s - Reason: %3$s"
266
  msgstr ""
267
 
268
  #: includes/class-wc-stripe-api.php:73
269
  msgid "There was a problem connecting to the payment gateway."
270
  msgstr ""
271
 
272
+ #: includes/class-wc-stripe-apple-pay.php:277
273
+ msgid "Or"
274
+ msgstr ""
275
+
276
+ #: includes/class-wc-stripe-apple-pay.php:304
277
+ #: includes/class-wc-stripe-apple-pay.php:353
278
+ #: includes/class-wc-stripe-apple-pay.php:431
279
+ #: includes/class-wc-stripe-apple-pay.php:494
280
+ #: includes/class-wc-stripe-apple-pay.php:542
281
+ msgid "Cheatin&#8217; huh?"
282
+ msgstr ""
283
+
284
+ #: includes/class-wc-stripe-apple-pay.php:375
285
+ msgid "Please enter a valid postcode/ZIP."
286
+ msgstr ""
287
+
288
+ #: includes/class-wc-stripe-apple-pay.php:452
289
+ #: includes/class-wc-stripe-apple-pay.php:475
290
+ msgid "Unable to find shipping method for address."
291
+ msgstr ""
292
+
293
+ #: includes/class-wc-stripe-apple-pay.php:522
294
+ #: includes/class-wc-stripe-apple-pay.php:707
295
+ #: includes/class-wc-stripe-payment-request.php:348
296
+ msgid "Tax"
297
+ msgstr ""
298
+
299
+ #: includes/class-wc-stripe-apple-pay.php:580
300
+ msgid "Apple Pay (Stripe)"
301
+ msgstr ""
302
+
303
+ #: includes/class-wc-stripe-apple-pay.php:693
304
+ msgid "Sub-Total"
305
+ msgstr ""
306
+
307
+ #: includes/class-wc-stripe-apple-pay.php:715
308
+ msgid "Shipping"
309
+ msgstr ""
310
+
311
+ #: includes/class-wc-stripe-apple-pay.php:723
312
+ msgid "Discount"
313
+ msgstr ""
314
+
315
+ #: includes/class-wc-stripe-apple-pay.php:741
316
+ #: includes/class-wc-stripe-apple-pay.php:748
317
+ #: includes/class-wc-stripe-apple-pay.php:750
318
+ #: includes/class-wc-stripe-apple-pay.php:773
319
+ #: includes/class-wc-stripe-apple-pay.php:785
320
+ #: includes/class-wc-stripe-apple-pay.php:795
321
+ #: includes/class-wc-stripe-apple-pay.php:802
322
+ #, php-format
323
+ msgid "Error %d: Unable to create order. Please try again."
324
+ msgstr ""
325
+
326
+ #: includes/class-wc-stripe-customer.php:150
327
  msgid "Could not create Stripe customer."
328
  msgstr ""
329
 
330
+ #: includes/class-wc-stripe-customer.php:191
331
  msgid "Unable to add card"
332
  msgstr ""
333
 
334
+ #. translators: Do not translate the [option] placeholder
335
+ #: includes/class-wc-stripe-payment-request.php:97
336
+ msgid "Unknown shipping option \"[option]\"."
337
+ msgstr ""
338
+
339
+ #: includes/class-wc-stripe-payment-request.php:122
340
+ msgid "Total"
341
+ msgstr ""
342
+
343
+ #: includes/class-wc-stripe-payment-request.php:286
344
+ msgid "Empty cart"
345
+ msgstr ""
346
+
347
+ #: includes/class-wc-stripe-payment-request.php:308
348
+ msgid "Subtotal"
349
+ msgstr ""
350
+
351
  #: includes/legacy/class-wc-gateway-stripe-saved-cards.php:50
352
  #: includes/legacy/class-wc-gateway-stripe-saved-cards.php:73
353
  msgid "Unable to make default card, please try again"
398
  msgid "Use a new credit card"
399
  msgstr ""
400
 
401
+ #: includes/legacy/class-wc-gateway-stripe.php:331
402
+ #, php-format
403
+ msgid "%s - Order %s"
404
+ msgstr ""
405
+
406
+ #: includes/legacy/class-wc-gateway-stripe.php:590
407
+ #, php-format
408
+ msgid "Refunded %s - Refund ID: %s - Reason: %s"
409
+ msgstr ""
410
+
411
  #: includes/legacy/templates/saved-cards.php:1
412
  msgid "Saved cards"
413
  msgstr ""
487
  msgstr ""
488
 
489
  #: includes/settings-stripe.php:38
490
+ msgid "Test Secret Key"
491
  msgstr ""
492
 
493
  #: includes/settings-stripe.php:40 includes/settings-stripe.php:47
496
  msgstr ""
497
 
498
  #: includes/settings-stripe.php:45
499
+ msgid "Test Publishable Key"
500
  msgstr ""
501
 
502
  #: includes/settings-stripe.php:52
503
+ msgid "Live Secret Key"
504
  msgstr ""
505
 
506
  #: includes/settings-stripe.php:59
507
+ msgid "Live Publishable Key"
508
  msgstr ""
509
 
510
  #: includes/settings-stripe.php:66
511
+ msgid "Statement Descriptor"
512
+ msgstr ""
513
+
514
+ #: includes/settings-stripe.php:68
515
+ msgid ""
516
+ "Extra information about a charge. This will appear on your customer’s credit "
517
+ "card statement."
518
+ msgstr ""
519
+
520
+ #: includes/settings-stripe.php:73
521
  msgid "Capture"
522
  msgstr ""
523
 
524
+ #: includes/settings-stripe.php:74
525
  msgid "Capture charge immediately"
526
  msgstr ""
527
 
528
+ #: includes/settings-stripe.php:76
529
  msgid ""
530
  "Whether or not to immediately capture the charge. When unchecked, the charge "
531
  "issues an authorization and will need to be captured later. Uncaptured "
532
  "charges expire in 7 days."
533
  msgstr ""
534
 
535
+ #: includes/settings-stripe.php:81
536
  msgid "Stripe Checkout"
537
  msgstr ""
538
 
539
+ #: includes/settings-stripe.php:82
540
  msgid "Enable Stripe Checkout"
541
  msgstr ""
542
 
543
+ #: includes/settings-stripe.php:84
544
  msgid ""
545
  "If enabled, this option shows a \"pay\" button and modal credit card form on "
546
  "the checkout, instead of credit card fields directly on the page."
547
  msgstr ""
548
 
549
+ #: includes/settings-stripe.php:89
550
+ msgid "Allow Remember Me"
551
+ msgstr ""
552
+
553
+ #: includes/settings-stripe.php:90
554
+ msgid "Enable Remember Me"
555
+ msgstr ""
556
+
557
+ #: includes/settings-stripe.php:92
558
+ msgid ""
559
+ "If enabled, this option shows a \"Remember Me\" checkbox which when checked "
560
+ "by the customer will persist their details."
561
+ msgstr ""
562
+
563
+ #: includes/settings-stripe.php:97
564
  msgid "Stripe Checkout locale"
565
  msgstr ""
566
 
567
+ #: includes/settings-stripe.php:100
568
  msgid ""
569
  "Language to display in Stripe Checkout modal. Specify Auto to display "
570
  "Checkout in the user's preferred language, if available. English will be "
571
  "used by default."
572
  msgstr ""
573
 
574
+ #: includes/settings-stripe.php:104
575
  msgid "Auto"
576
  msgstr ""
577
 
578
+ #: includes/settings-stripe.php:105
579
  msgid "Simplified Chinese"
580
  msgstr ""
581
 
582
+ #: includes/settings-stripe.php:106
583
+ msgid "Danish"
584
+ msgstr ""
585
+
586
+ #: includes/settings-stripe.php:107
587
  msgid "Dutch"
588
  msgstr ""
589
 
590
+ #: includes/settings-stripe.php:108
591
  msgid "English"
592
  msgstr ""
593
 
594
+ #: includes/settings-stripe.php:109
595
+ msgid "Finnish"
596
+ msgstr ""
597
+
598
+ #: includes/settings-stripe.php:110
599
  msgid "French"
600
  msgstr ""
601
 
602
+ #: includes/settings-stripe.php:111
603
  msgid "German"
604
  msgstr ""
605
 
606
+ #: includes/settings-stripe.php:112
607
  msgid "Italian"
608
  msgstr ""
609
 
610
+ #: includes/settings-stripe.php:113
611
  msgid "Japanese"
612
  msgstr ""
613
 
614
+ #: includes/settings-stripe.php:114
615
+ msgid "Norwegian"
616
+ msgstr ""
617
+
618
+ #: includes/settings-stripe.php:115
619
  msgid "Spanish"
620
  msgstr ""
621
 
622
+ #: includes/settings-stripe.php:116
623
+ msgid "Swedish"
624
+ msgstr ""
625
+
626
+ #: includes/settings-stripe.php:120
627
  msgid "Bitcoin Currency"
628
  msgstr ""
629
 
630
+ #: includes/settings-stripe.php:121
631
  msgid "Enable Bitcoin Currency"
632
  msgstr ""
633
 
634
+ #: includes/settings-stripe.php:123
635
  msgid ""
636
  "If enabled, an option to accept bitcoin will show on the checkout modal. "
637
  "Note: Stripe Checkout needs to be enabled and store currency must be set to "
638
  "USD."
639
  msgstr ""
640
 
641
+ #: includes/settings-stripe.php:128
642
  msgid "Stripe Checkout Image"
643
  msgstr ""
644
 
645
+ #: includes/settings-stripe.php:129
646
  msgid ""
647
  "Optionally enter the URL to a 128x128px image of your brand or product. e.g. "
648
  "<code>https://yoursite.com/wp-content/uploads/2013/09/yourimage.jpg</code>"
649
  msgstr ""
650
 
651
+ #: includes/settings-stripe.php:135
652
+ msgid "Payment Request API"
653
+ msgstr ""
654
+
655
+ #: includes/settings-stripe.php:136
656
+ msgid "Enable Payment Request API"
657
+ msgstr ""
658
+
659
+ #: includes/settings-stripe.php:138
660
+ msgid ""
661
+ "If enabled, users will be able to pay using the Payment Request API if "
662
+ "supported by the browser."
663
+ msgstr ""
664
+
665
+ #: includes/settings-stripe.php:143
666
+ msgid "Apple Pay"
667
+ msgstr ""
668
+
669
+ #: includes/settings-stripe.php:144
670
+ #, php-format
671
+ msgid ""
672
+ "Enable Apple Pay. %1$sBy using Apple Pay, you agree to %2$s and %3$s's terms "
673
+ "of service."
674
+ msgstr ""
675
+
676
+ #: includes/settings-stripe.php:146
677
+ msgid "If enabled, users will be able to pay with Apple Pay."
678
+ msgstr ""
679
+
680
+ #: includes/settings-stripe.php:151
681
+ msgid "Apple Pay Button Style"
682
+ msgstr ""
683
+
684
+ #: includes/settings-stripe.php:152
685
+ msgid "Button Style"
686
+ msgstr ""
687
+
688
+ #: includes/settings-stripe.php:154
689
+ msgid "Select the button style you would like to show."
690
+ msgstr ""
691
+
692
+ #: includes/settings-stripe.php:158
693
+ msgid "Black"
694
+ msgstr ""
695
+
696
+ #: includes/settings-stripe.php:159
697
+ msgid "White"
698
+ msgstr ""
699
+
700
+ #: includes/settings-stripe.php:163
701
+ msgid "Apple Pay Button Language"
702
+ msgstr ""
703
+
704
+ #: includes/settings-stripe.php:164
705
+ msgid ""
706
+ "Enter the 2 letter ISO code for the language you would like your Apple Pay "
707
+ "Button to display in. Reference available ISO codes here <code>http://www."
708
+ "w3schools.com/tags/ref_language_codes.asp</code>"
709
+ msgstr ""
710
+
711
+ #: includes/settings-stripe.php:170
712
  msgid "Saved Cards"
713
  msgstr ""
714
 
715
+ #: includes/settings-stripe.php:171
716
  msgid "Enable Payment via Saved Cards"
717
  msgstr ""
718
 
719
+ #: includes/settings-stripe.php:173
720
  msgid ""
721
  "If enabled, users will be able to pay with a saved card during checkout. "
722
  "Card details are saved on Stripe servers, not on your store."
723
  msgstr ""
724
 
725
+ #: includes/settings-stripe.php:178
726
  msgid "Logging"
727
  msgstr ""
728
 
729
+ #: includes/settings-stripe.php:179
730
  msgid "Log debug messages"
731
  msgstr ""
732
 
733
+ #: includes/settings-stripe.php:181
734
  msgid "Save debug messages to the WooCommerce System Status log."
735
  msgstr ""
736
 
737
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:3
738
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:5
739
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:9
740
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:10
741
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:14
742
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:15
743
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:4
744
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:6
745
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:10
746
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:11
747
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:15
748
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:16
749
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:3
750
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:5
751
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:9
752
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:10
753
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:14
754
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:15
755
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:3
756
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:5
757
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:9
758
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:10
759
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:14
760
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:15
761
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:3
762
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:5
763
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:9
764
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:10
765
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:14
766
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:15
767
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:3
768
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:5
769
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:9
770
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:10
771
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:14
772
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:15
773
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:4
774
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:6
775
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:10
776
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:11
777
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:15
778
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:16
779
+ msgid "Hello World"
780
+ msgstr ""
781
+
782
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:4
783
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:6
784
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:11
785
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:16
786
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:5
787
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:7
788
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:12
789
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:17
790
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:4
791
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:6
792
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:11
793
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:16
794
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:4
795
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:6
796
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:11
797
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:16
798
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:4
799
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:6
800
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:11
801
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:16
802
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:4
803
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:6
804
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:11
805
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:16
806
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:5
807
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:7
808
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:12
809
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:17
810
+ msgctxt "verb"
811
+ msgid "Post"
812
+ msgstr ""
813
+
814
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:20
815
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:24
816
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:21
817
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:25
818
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:20
819
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:24
820
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:20
821
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:24
822
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:20
823
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:24
824
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:20
825
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:24
826
+ #: node_modules/grunt-checktextdomain/test/fixtures/plurals.php:3
827
+ #: node_modules/grunt-checktextdomain/test/fixtures/plurals.php:8
828
+ #: node_modules/grunt-checktextdomain/test/fixtures/plurals.php:15
829
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:21
830
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:25
831
  #, php-format
832
+ msgid "%d apple"
833
+ msgid_plural "%d apples"
834
+ msgstr[0] ""
835
+ msgstr[1] ""
836
+
837
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:21
838
+ #: node_modules/grunt-checktextdomain/test/expected/incorrect-domain-autocorrect.php:25
839
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:22
840
+ #: node_modules/grunt-checktextdomain/test/expected/variable-domain-autocorrect.php:26
841
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:21
842
+ #: node_modules/grunt-checktextdomain/test/fixtures/correct-domain.php:25
843
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:21
844
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain-autocorrect.php:25
845
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:21
846
+ #: node_modules/grunt-checktextdomain/test/fixtures/incorrect-domain.php:25
847
+ #: node_modules/grunt-checktextdomain/test/fixtures/missing-domain.php:25
848
+ #: node_modules/grunt-checktextdomain/test/fixtures/plurals.php:4
849
+ #: node_modules/grunt-checktextdomain/test/fixtures/plurals.php:9
850
+ #: node_modules/grunt-checktextdomain/test/fixtures/plurals.php:16
851
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:22
852
+ #: node_modules/grunt-checktextdomain/test/fixtures/variable-domain-autocorrect.php:26
853
+ #, php-format
854
+ msgctxt "noun, job positions"
855
+ msgid "%d post"
856
+ msgid_plural "%d posts"
857
+ msgstr[0] ""
858
+ msgstr[1] ""
859
+
860
+ #: node_modules/grunt-wp-i18n/test/fixtures/basic-theme/exclude/file.php:3
861
+ #: node_modules/grunt-wp-i18n/test/fixtures/plugin-include/plugin-include.php:6
862
+ msgid "Exclude"
863
  msgstr ""
864
 
865
+ #: node_modules/grunt-wp-i18n/test/fixtures/plugin-include/include/file.php:2
866
+ msgid "Include"
 
 
 
867
  msgstr ""
868
 
869
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/add-domain.php:2
870
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-all-domains.php:2
871
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-all-domains.php:3
872
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-all-domains.php:4
873
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-domains.php:2
874
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-domains.php:3
875
+ msgid "String"
876
+ msgstr ""
877
+
878
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-all-domains.php:6
879
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-all-domains.php:7
880
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-all-domains.php:8
881
+ msgctxt "a string"
882
+ msgid "String"
883
+ msgstr ""
884
+
885
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-all-domains.php:9
886
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-all-domains.php:10
887
+ #: node_modules/grunt-wp-i18n/test/fixtures/text-domains/update-all-domains.php:11
888
  #, php-format
889
+ msgid "1 Star"
890
+ msgid_plural "%s Stars"
891
+ msgstr[0] ""
892
+ msgstr[1] ""
893
+
894
+ #. translators: A single line translators comment.
895
+ #: node_modules/grunt-wp-i18n/test/fixtures/translator-comments/translator-comments.php:7
896
+ msgid "A"
897
  msgstr ""
898
 
899
+ #. translators: A
900
+ #. multiline
901
+ #. translators
902
+ #. comment.
903
+ #.
904
+ #: node_modules/grunt-wp-i18n/test/fixtures/translator-comments/translator-comments.php:15
905
+ msgid "B"
906
  msgstr ""
907
 
908
+ #: woocommerce-gateway-stripe.php:182
909
  #, php-format
910
  msgid ""
911
+ "Stripe is almost ready. To get started, <a href=\"%s\">set your Stripe "
912
+ "account keys</a>."
913
  msgstr ""
914
 
915
+ #: woocommerce-gateway-stripe.php:240
916
  #, php-format
917
  msgid ""
918
+ "WooCommerce Stripe - The minimum PHP version required for this plugin is "
919
+ "%1$s. You are running %2$s."
920
  msgstr ""
921
 
922
+ #: woocommerce-gateway-stripe.php:246
923
+ msgid "WooCommerce Stripe requires WooCommerce to be activated to work."
924
  msgstr ""
925
 
926
+ #: woocommerce-gateway-stripe.php:250
927
+ #, php-format
928
  msgid ""
929
+ "WooCommerce Stripe - The minimum WooCommerce version required for this "
930
+ "plugin is %1$s. You are running %2$s."
931
  msgstr ""
932
 
933
+ #: woocommerce-gateway-stripe.php:256
934
+ msgid "WooCommerce Stripe - cURL is not installed."
935
+ msgstr ""
936
+
937
+ #: woocommerce-gateway-stripe.php:271
938
  msgid "Settings"
939
  msgstr ""
940
 
941
+ #: woocommerce-gateway-stripe.php:272
942
  msgid "Docs"
943
  msgstr ""
944
 
945
+ #: woocommerce-gateway-stripe.php:273
946
  msgid "Support"
947
  msgstr ""
948
 
949
+ #: woocommerce-gateway-stripe.php:303
950
+ msgid ""
951
+ "New Feature! Stripe now supports Apple Pay. Your customers can now purchase "
952
+ "your products even faster. Apple Pay has been enabled by default."
953
+ msgstr ""
954
+
955
+ #: woocommerce-gateway-stripe.php:321
956
+ msgid ""
957
+ "New Feature! Stripe now supports Google Payment Request. Your customers can "
958
+ "now use mobile phones with supported browsers such as Chrome to make "
959
+ "purchases easier and faster."
960
+ msgstr ""
961
+
962
+ #: woocommerce-gateway-stripe.php:468
963
  msgid "Unable to capture charge!"
964
  msgstr ""
965
 
966
+ #: woocommerce-gateway-stripe.php:506
967
  msgid "Unable to refund charge!"
968
  msgstr ""
969
 
970
+ #: woocommerce-gateway-stripe.php:508
971
  #, php-format
972
  msgid "Stripe charge refunded (Charge ID: %s)"
973
  msgstr ""
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === WooCommerce Stripe Payment Gateway ===
2
- Contributors: automattic, woothemes, mikejolley, akeda, royho, slash1andy, woosteve, spraveenitpro, mikedmoore, fernashes, shellbeezy, danieldudzic, mikaey, dsmithweb, fullysupportedphil, corsonr
3
  Tags: credit card, stripe, woocommerce
4
  Requires at least: 4.4
5
- Tested up to: 4.7.1
6
- Stable tag: 3.0.7
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -11,7 +11,7 @@ Take credit card payments on your store using Stripe.
11
 
12
  == Description ==
13
 
14
- Accept Visa, MasterCard, American Express, Discover, JCB, Diners Club, and more cards directly on your store with the Stripe payment gateway for WooCommerce.
15
 
16
  = Take Credit card payments easily and directly on your store =
17
 
@@ -38,6 +38,14 @@ Stripe has no setup fees, no monthly fees, no hidden costs: you only get charged
38
 
39
  Stripe also supports the [Subscriptions extension](http://www.woothemes.com/extension/subscriptions/) and re-using cards. When a customer pays, they are set up in Stripe as a customer. If they create another order, they can check out using the same card. A massive timesaver for returning customers.
40
 
 
 
 
 
 
 
 
 
41
  == Installation ==
42
 
43
  Please note, v3 of this gateway requires WooCommerce 2.5 and above.
@@ -87,6 +95,10 @@ If you get stuck, you can ask for help in the Plugin Forum.
87
 
88
  == Changelog ==
89
 
 
 
 
 
90
  = 3.0.7 =
91
  * New - Option to allow/disallow remember me on Stripe checkout modal.
92
  * Fix - Paying for order incorrectly uses cart amount.
@@ -134,7 +146,6 @@ If you get stuck, you can ask for help in the Plugin Forum.
134
 
135
  == Upgrade Notice ==
136
 
137
- = 3.0.7 =
138
- * New - Option to allow/disallow remember me on Stripe checkout modal.
139
- * Fix - Paying for order incorrectly uses cart amount.
140
- * Fix - Using WC function before checking exists causes fatal error.
1
  === WooCommerce Stripe Payment Gateway ===
2
+ Contributors: automattic, woothemes, mikejolley, akeda, royho, mattyza, slash1andy, woosteve, spraveenitpro, mikedmoore, fernashes, shellbeezy, danieldudzic, mikaey, dsmithweb, fullysupportedphil, corsonr, deskroid, luminus, tiagonoronha
3
  Tags: credit card, stripe, woocommerce
4
  Requires at least: 4.4
5
+ Tested up to: 4.7.2
6
+ Stable tag: 3.1.0
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
11
 
12
  == Description ==
13
 
14
+ Accept Visa, MasterCard, American Express, Discover, JCB, Diners Club, and more cards directly on your store with the Stripe payment gateway for WooCommerce, including Apple Pay for mobile and desktop.
15
 
16
  = Take Credit card payments easily and directly on your store =
17
 
38
 
39
  Stripe also supports the [Subscriptions extension](http://www.woothemes.com/extension/subscriptions/) and re-using cards. When a customer pays, they are set up in Stripe as a customer. If they create another order, they can check out using the same card. A massive timesaver for returning customers.
40
 
41
+ = Apple Pay Support =
42
+
43
+ WooCommerce Stripe now includes [Apple Pay](https://stripe.com/apple-pay) support, which means customers can pay using payment details associated to their Apple ID. Checkout is now just a thumbprint away. on both mobile and desktop.
44
+
45
+ = Web Payments API Support =
46
+
47
+ WooCommerce Stripe now includes [Web Payments API](https://www.w3.org/TR/payment-request/) support, which means customers can pay using payment details associated to their mobile devices, in browsers supporting the Web Payments API (Chrome for Android, amongst others). Checkout is now just a few taps away. on mobile.
48
+
49
  == Installation ==
50
 
51
  Please note, v3 of this gateway requires WooCommerce 2.5 and above.
95
 
96
  == Changelog ==
97
 
98
+ = 3.1.0 =
99
+ * New - Apple Pay Support.
100
+ * New - Add Google Payment Request API.
101
+
102
  = 3.0.7 =
103
  * New - Option to allow/disallow remember me on Stripe checkout modal.
104
  * Fix - Paying for order incorrectly uses cart amount.
146
 
147
  == Upgrade Notice ==
148
 
149
+ = 3.1.0 =
150
+ * New - Apple Pay Support.
151
+ * New - Add Google Payment Request API.
 
woocommerce-gateway-stripe.php CHANGED
@@ -5,7 +5,7 @@
5
  * Description: Take credit card payments on your store using Stripe.
6
  * Author: WooCommerce
7
  * Author URI: https://woocommerce.com/
8
- * Version: 3.0.7
9
  * Text Domain: woocommerce-gateway-stripe
10
  * Domain Path: /languages
11
  *
@@ -32,454 +32,599 @@ if ( ! defined( 'ABSPATH' ) ) {
32
  /**
33
  * Required minimums and constants
34
  */
35
- define( 'WC_STRIPE_VERSION', '3.0.7' );
36
- define( 'WC_STRIPE_MIN_PHP_VER', '5.3.0' );
37
  define( 'WC_STRIPE_MIN_WC_VER', '2.5.0' );
38
  define( 'WC_STRIPE_MAIN_FILE', __FILE__ );
39
  define( 'WC_STRIPE_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
 
40
 
41
  if ( ! class_exists( 'WC_Stripe' ) ) :
42
 
43
- class WC_Stripe {
44
-
45
- /**
46
- * @var Singleton The reference the *Singleton* instance of this class
47
- */
48
- private static $instance;
49
-
50
- /**
51
- * @var Reference to logging class.
52
- */
53
- private static $log;
54
-
55
- /**
56
- * Returns the *Singleton* instance of this class.
57
- *
58
- * @return Singleton The *Singleton* instance.
59
- */
60
- public static function get_instance() {
61
- if ( null === self::$instance ) {
62
- self::$instance = new self();
 
 
63
  }
64
- return self::$instance;
65
- }
66
 
67
- /**
68
- * Private clone method to prevent cloning of the instance of the
69
- * *Singleton* instance.
70
- *
71
- * @return void
72
- */
73
- private function __clone() {}
74
-
75
- /**
76
- * Private unserialize method to prevent unserializing of the *Singleton*
77
- * instance.
78
- *
79
- * @return void
80
- */
81
- private function __wakeup() {}
82
-
83
- /**
84
- * Flag to indicate whether or not we need to load code for / support subscriptions.
85
- *
86
- * @var bool
87
- */
88
- private $subscription_support_enabled = false;
89
-
90
- /**
91
- * Flag to indicate whether or not we need to load support for pre-orders.
92
- *
93
- * @since 3.0.3
94
- *
95
- * @var bool
96
- */
97
- private $pre_order_enabled = false;
98
-
99
- /**
100
- * Notices (array)
101
- * @var array
102
- */
103
- public $notices = array();
104
-
105
- /**
106
- * Protected constructor to prevent creating a new instance of the
107
- * *Singleton* via the `new` operator from outside of this class.
108
- */
109
- protected function __construct() {
110
- add_action( 'admin_init', array( $this, 'check_environment' ) );
111
- add_action( 'admin_notices', array( $this, 'admin_notices' ), 15 );
112
- add_action( 'plugins_loaded', array( $this, 'init' ) );
113
- }
 
 
 
 
 
 
 
 
 
114
 
115
- /**
116
- * Init the plugin after plugins_loaded so environment variables are set.
117
- */
118
- public function init() {
119
- // Don't hook anything else in the plugin if we're in an incompatible environment
120
- if ( self::get_environment_warning() ) {
121
- return;
 
 
 
 
 
 
 
 
 
 
 
122
  }
123
 
124
- include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php' );
125
- include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-customer.php' );
 
 
 
 
 
 
 
126
 
127
- // Init the gateway itself
128
- $this->init_gateways();
 
 
 
 
 
129
 
130
- add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
131
- add_action( 'woocommerce_order_status_on-hold_to_processing', array( $this, 'capture_payment' ) );
132
- add_action( 'woocommerce_order_status_on-hold_to_completed', array( $this, 'capture_payment' ) );
133
- add_action( 'woocommerce_order_status_on-hold_to_cancelled', array( $this, 'cancel_payment' ) );
134
- add_action( 'woocommerce_order_status_on-hold_to_refunded', array( $this, 'cancel_payment' ) );
135
- add_filter( 'woocommerce_get_customer_payment_tokens', array( $this, 'woocommerce_get_customer_payment_tokens' ), 10, 3 );
136
- add_action( 'woocommerce_payment_token_deleted', array( $this, 'woocommerce_payment_token_deleted' ), 10, 2 );
137
- add_action( 'woocommerce_payment_token_set_default', array( $this, 'woocommerce_payment_token_set_default' ) );
138
- }
139
 
140
- /**
141
- * Allow this class and other classes to add slug keyed notices (to avoid duplication)
142
- */
143
- public function add_admin_notice( $slug, $class, $message ) {
144
- $this->notices[ $slug ] = array(
145
- 'class' => $class,
146
- 'message' => $message
147
- );
148
- }
 
 
149
 
150
- /**
151
- * The backup sanity check, in case the plugin is activated in a weird way,
152
- * or the environment changes after activation.
153
- */
154
- public function check_environment() {
155
- $environment_warning = self::get_environment_warning();
156
 
157
- if ( $environment_warning && is_plugin_active( plugin_basename( __FILE__ ) ) ) {
158
- $this->add_admin_notice( 'bad_environment', 'error', $environment_warning );
 
 
159
  }
160
 
161
- // Check if secret key present. Otherwise prompt, via notice, to go to
162
- // setting.
163
- if ( ! class_exists( 'WC_Stripe_API' ) ) {
164
- include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php' );
 
 
 
 
 
 
 
 
165
  }
166
 
167
- $secret = WC_Stripe_API::get_secret_key();
 
 
 
 
 
 
 
 
168
 
169
- if ( empty( $secret ) && ! ( isset( $_GET['page'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'stripe' === $_GET['section'] ) ) {
170
- $setting_link = $this->get_setting_link();
171
- $this->add_admin_notice( 'prompt_connect', 'notice notice-warning', sprintf( __( 'Stripe is almost ready. To get started, <a href="%s">set your Stripe account keys</a>.', 'woocommerce-gateway-stripe' ), $setting_link ) );
 
 
 
 
 
172
  }
173
- }
174
 
175
- /**
176
- * Checks the environment for compatibility problems. Returns a string with the first incompatibility
177
- * found or false if the environment has no problems.
178
- */
179
- static function get_environment_warning() {
180
- if ( version_compare( phpversion(), WC_STRIPE_MIN_PHP_VER, '<' ) ) {
181
- $message = __( 'WooCommerce Stripe - The minimum PHP version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe', 'woocommerce-gateway-stripe' );
 
 
 
182
 
183
- return sprintf( $message, WC_STRIPE_MIN_PHP_VER, phpversion() );
184
  }
185
-
186
- if ( ! defined( 'WC_VERSION' ) ) {
187
- return __( 'WooCommerce Stripe requires WooCommerce to be activated to work.', 'woocommerce-gateway-stripe' );
188
- }
189
 
190
- if ( version_compare( WC_VERSION, WC_STRIPE_MIN_WC_VER, '<' ) ) {
191
- $message = __( 'WooCommerce Stripe - The minimum WooCommerce version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe', 'woocommerce-gateway-stripe' );
 
 
 
 
 
192
 
193
- return sprintf( $message, WC_STRIPE_MIN_WC_VER, WC_VERSION );
194
- }
195
 
196
- if ( ! function_exists( 'curl_init' ) ) {
197
- return __( 'WooCommerce Stripe - cURL is not installed.', 'woocommerce-gateway-stripe' );
198
- }
199
 
200
- return false;
201
- }
202
 
203
- /**
204
- * Adds plugin action links
205
- *
206
- * @since 1.0.0
207
- */
208
- public function plugin_action_links( $links ) {
209
- $setting_link = $this->get_setting_link();
210
-
211
- $plugin_links = array(
212
- '<a href="' . $setting_link . '">' . __( 'Settings', 'woocommerce-gateway-stripe' ) . '</a>',
213
- '<a href="https://docs.woothemes.com/document/stripe/">' . __( 'Docs', 'woocommerce-gateway-stripe' ) . '</a>',
214
- '<a href="http://support.woothemes.com/">' . __( 'Support', 'woocommerce-gateway-stripe' ) . '</a>',
215
- );
216
- return array_merge( $plugin_links, $links );
217
- }
218
 
219
- /**
220
- * Get setting link.
221
- *
222
- * @since 1.0.0
223
- *
224
- * @return string Setting link
225
- */
226
- public function get_setting_link() {
227
- $use_id_as_section = function_exists( 'WC' ) ? version_compare( WC()->version, '2.6', '>=' ) : false;
228
 
229
- $section_slug = $use_id_as_section ? 'stripe' : strtolower( 'WC_Gateway_Stripe' );
 
230
 
231
- return admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . $section_slug );
232
- }
 
 
 
 
 
233
 
234
- /**
235
- * Display any notices we've collected thus far (e.g. for connection, disconnection)
236
- */
237
- public function admin_notices() {
238
- foreach ( (array) $this->notices as $notice_key => $notice ) {
239
- echo "<div class='" . esc_attr( $notice['class'] ) . "'><p>";
240
- echo wp_kses( $notice['message'], array( 'a' => array( 'href' => array() ) ) );
241
- echo "</p></div>";
242
  }
243
- }
244
 
245
- /**
246
- * Initialize the gateway. Called very early - in the context of the plugins_loaded action
247
- *
248
- * @since 1.0.0
249
- */
250
- public function init_gateways() {
251
- if ( class_exists( 'WC_Subscriptions_Order' ) && function_exists( 'wcs_create_renewal_order' ) ) {
252
- $this->subscription_support_enabled = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  }
254
 
255
- if ( class_exists( 'WC_Pre_Orders_Order' ) ) {
256
- $this->pre_order_enabled = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  }
258
 
259
- if ( ! class_exists( 'WC_Payment_Gateway' ) ) {
260
- return;
 
 
 
 
 
 
 
 
 
 
261
  }
262
 
263
- if ( class_exists( 'WC_Payment_Gateway_CC' ) ) {
264
- include_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-stripe.php' );
265
- } else {
266
- include_once( dirname( __FILE__ ) . '/includes/legacy/class-wc-gateway-stripe.php' );
267
- include_once( dirname( __FILE__ ) . '/includes/legacy/class-wc-gateway-stripe-saved-cards.php' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  }
269
 
270
- load_plugin_textdomain( 'woocommerce-gateway-stripe', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
271
- add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateways' ) );
 
 
 
 
 
 
 
 
 
272
 
273
- $load_addons = (
274
- $this->subscription_support_enabled
275
- ||
276
- $this->pre_order_enabled
277
- );
278
 
279
- if ( $load_addons ) {
280
- require_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-stripe-addons.php' );
281
- }
282
- }
 
 
283
 
284
- /**
285
- * Add the gateways to WooCommerce
286
- *
287
- * @since 1.0.0
288
- */
289
- public function add_gateways( $methods ) {
290
- if ( $this->subscription_support_enabled || $this->pre_order_enabled ) {
291
- $methods[] = 'WC_Gateway_Stripe_Addons';
292
- } else {
293
- $methods[] = 'WC_Gateway_Stripe';
294
  }
295
- return $methods;
296
- }
297
 
298
- /**
299
- * Capture payment when the order is changed from on-hold to complete or processing
300
- *
301
- * @param int $order_id
302
- */
303
- public function capture_payment( $order_id ) {
304
- $order = wc_get_order( $order_id );
305
-
306
- if ( 'stripe' === $order->payment_method ) {
307
- $charge = get_post_meta( $order_id, '_stripe_charge_id', true );
308
- $captured = get_post_meta( $order_id, '_stripe_charge_captured', true );
309
-
310
- if ( $charge && 'no' === $captured ) {
311
- $result = WC_Stripe_API::request( array(
312
- 'amount' => $order->get_total() * 100,
313
- 'expand[]' => 'balance_transaction'
314
- ), 'charges/' . $charge . '/capture' );
315
-
316
- if ( is_wp_error( $result ) ) {
317
- $order->add_order_note( __( 'Unable to capture charge!', 'woocommerce-gateway-stripe' ) . ' ' . $result->get_error_message() );
318
- } else {
319
- $order->add_order_note( sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $result->id ) );
320
- update_post_meta( $order->id, '_stripe_charge_captured', 'yes' );
321
-
322
- // Store other data such as fees
323
- update_post_meta( $order->id, 'Stripe Payment ID', $result->id );
324
-
325
- if ( isset( $result->balance_transaction ) && isset( $result->balance_transaction->fee ) ) {
326
- // Fees and Net needs to both come from Stripe to be accurate as the returned
327
- // values are in the local currency of the Stripe account, not from WC.
328
- $fee = ! empty( $result->balance_transaction->fee ) ? number_format( $result->balance_transaction->fee / 100, 2, '.', '' ) : 0;
329
- $net = ! empty( $result->balance_transaction->net ) ? number_format( $result->balance_transaction->net / 100, 2, '.', '' ) : 0;
330
- update_post_meta( $order->id, 'Stripe Fee', $fee );
331
- update_post_meta( $order->id, 'Net Revenue From Stripe', $net );
 
332
  }
333
  }
334
  }
335
  }
336
- }
337
 
338
- /**
339
- * Cancel pre-auth on refund/cancellation
340
- *
341
- * @param int $order_id
342
- */
343
- public function cancel_payment( $order_id ) {
344
- $order = wc_get_order( $order_id );
345
-
346
- if ( 'stripe' === $order->payment_method ) {
347
- $charge = get_post_meta( $order_id, '_stripe_charge_id', true );
348
-
349
- if ( $charge ) {
350
- $result = WC_Stripe_API::request( array(
351
- 'amount' => $order->get_total() * 100,
352
- ), 'charges/' . $charge . '/refund' );
353
-
354
- if ( is_wp_error( $result ) ) {
355
- $order->add_order_note( __( 'Unable to refund charge!', 'woocommerce-gateway-stripe' ) . ' ' . $result->get_error_message() );
356
- } else {
357
- $order->add_order_note( sprintf( __( 'Stripe charge refunded (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $result->id ) );
358
- delete_post_meta( $order->id, '_stripe_charge_captured' );
359
- delete_post_meta( $order->id, '_stripe_charge_id' );
 
360
  }
361
  }
362
  }
363
- }
364
 
365
- /**
366
- * Gets saved tokens from API if they don't already exist in WooCommerce.
367
- * @param array $tokens
368
- * @return array
369
- */
370
- public function woocommerce_get_customer_payment_tokens( $tokens, $customer_id, $gateway_id ) {
371
- if ( is_user_logged_in() && 'stripe' === $gateway_id && class_exists( 'WC_Payment_Token_CC' ) ) {
372
- $stripe_customer = new WC_Stripe_Customer( $customer_id );
373
- $stripe_cards = $stripe_customer->get_cards();
374
- $stored_tokens = array();
375
-
376
- foreach ( $tokens as $token ) {
377
- $stored_tokens[] = $token->get_token();
378
- }
379
 
380
- foreach ( $stripe_cards as $card ) {
381
- if ( ! in_array( $card->id, $stored_tokens ) ) {
382
- $token = new WC_Payment_Token_CC();
383
- $token->set_token( $card->id );
384
- $token->set_gateway_id( 'stripe' );
385
- $token->set_card_type( strtolower( $card->brand ) );
386
- $token->set_last4( $card->last4 );
387
- $token->set_expiry_month( $card->exp_month );
388
- $token->set_expiry_year( $card->exp_year );
389
- $token->set_user_id( $customer_id );
390
- $token->save();
391
- $tokens[ $token->get_id() ] = $token;
 
392
  }
393
  }
 
394
  }
395
- return $tokens;
396
- }
397
 
398
- /**
399
- * Delete token from Stripe
400
- */
401
- public function woocommerce_payment_token_deleted( $token_id, $token ) {
402
- if ( 'stripe' === $token->get_gateway_id() ) {
403
- $stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
404
- $stripe_customer->delete_card( $token->get_token() );
 
405
  }
406
- }
407
 
408
- /**
409
- * Set as default in Stripe
410
- */
411
- public function woocommerce_payment_token_set_default( $token_id ) {
412
- $token = WC_Payment_Tokens::get( $token_id );
413
- if ( 'stripe' === $token->get_gateway_id() ) {
414
- $stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
415
- $stripe_customer->set_default_card( $token->get_token() );
416
- }
417
- }
418
-
419
- /**
420
- * Checks Stripe minimum order value authorized per currency
421
- */
422
- public static function get_minimum_amount() {
423
-
424
- // Check order amount
425
- switch ( get_woocommerce_currency() ) {
426
- case 'USD':
427
- case 'CAD':
428
- case 'EUR':
429
- case 'CHF':
430
- case 'AUD':
431
- case 'SGD':
432
- $minimum_amount = 50;
433
- break;
434
- case 'GBP':
435
- $minimum_amount = 30;
436
- break;
437
- case 'DKK':
438
- $minimum_amount = 250;
439
- break;
440
- case 'NOK':
441
- case 'SEK':
442
- $minimum_amount = 300;
443
- break;
444
- case 'JPY':
445
- $minimum_amount = 5000;
446
- break;
447
- case 'MXN':
448
- $minimum_amount = 1000;
449
- break;
450
- case 'HKD':
451
- $minimum_amount = 400;
452
- break;
453
- default:
454
- $minimum_amount = 50;
455
- break;
456
  }
457
-
458
- return $minimum_amount;
459
-
460
- }
461
 
462
- /**
463
- * What rolls down stairs
464
- * alone or in pairs,
465
- * and over your neighbor's dog?
466
- * What's great for a snack,
467
- * And fits on your back?
468
- * It's log, log, log
469
- */
470
- public static function log( $message ) {
471
- if ( empty( self::$log ) ) {
472
- self::$log = new WC_Logger();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
  }
474
 
475
- self::$log->add( 'woocommerce-gateway-stripe', $message );
 
 
 
 
 
 
 
 
 
 
 
476
 
477
- if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
478
- error_log( $message );
479
  }
480
  }
481
- }
482
 
483
- $GLOBALS['wc_stripe'] = WC_Stripe::get_instance();
484
 
485
  endif;
5
  * Description: Take credit card payments on your store using Stripe.
6
  * Author: WooCommerce
7
  * Author URI: https://woocommerce.com/
8
+ * Version: 3.1.0
9
  * Text Domain: woocommerce-gateway-stripe
10
  * Domain Path: /languages
11
  *
32
  /**
33
  * Required minimums and constants
34
  */
35
+ define( 'WC_STRIPE_VERSION', '3.1.0' );
36
+ define( 'WC_STRIPE_MIN_PHP_VER', '5.6.0' );
37
  define( 'WC_STRIPE_MIN_WC_VER', '2.5.0' );
38
  define( 'WC_STRIPE_MAIN_FILE', __FILE__ );
39
  define( 'WC_STRIPE_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
40
+ define( 'WC_STRIPE_PLUGIN_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
41
 
42
  if ( ! class_exists( 'WC_Stripe' ) ) :
43
 
44
+ class WC_Stripe {
45
+
46
+ /**
47
+ * @var Singleton The reference the *Singleton* instance of this class
48
+ */
49
+ private static $instance;
50
+
51
+ /**
52
+ * @var Reference to logging class.
53
+ */
54
+ private static $log;
55
+
56
+ /**
57
+ * Returns the *Singleton* instance of this class.
58
+ *
59
+ * @return Singleton The *Singleton* instance.
60
+ */
61
+ public static function get_instance() {
62
+ if ( null === self::$instance ) {
63
+ self::$instance = new self();
64
+ }
65
+ return self::$instance;
66
  }
 
 
67
 
68
+ /**
69
+ * Private clone method to prevent cloning of the instance of the
70
+ * *Singleton* instance.
71
+ *
72
+ * @return void
73
+ */
74
+ private function __clone() {}
75
+
76
+ /**
77
+ * Private unserialize method to prevent unserializing of the *Singleton*
78
+ * instance.
79
+ *
80
+ * @return void
81
+ */
82
+ private function __wakeup() {}
83
+
84
+ /**
85
+ * Flag to indicate whether or not we need to load code for / support subscriptions.
86
+ *
87
+ * @var bool
88
+ */
89
+ private $subscription_support_enabled = false;
90
+
91
+ /**
92
+ * Flag to indicate whether or not we need to load support for pre-orders.
93
+ *
94
+ * @since 3.0.3
95
+ *
96
+ * @var bool
97
+ */
98
+ private $pre_order_enabled = false;
99
+
100
+ /**
101
+ * Notices (array)
102
+ * @var array
103
+ */
104
+ public $notices = array();
105
+
106
+ /**
107
+ * Protected constructor to prevent creating a new instance of the
108
+ * *Singleton* via the `new` operator from outside of this class.
109
+ */
110
+ protected function __construct() {
111
+ add_action( 'admin_init', array( $this, 'check_environment' ) );
112
+ add_action( 'admin_notices', array( $this, 'admin_notices' ), 15 );
113
+ add_action( 'plugins_loaded', array( $this, 'init' ) );
114
+ }
115
+
116
+ /**
117
+ * Init the plugin after plugins_loaded so environment variables are set.
118
+ */
119
+ public function init() {
120
+ // Don't hook anything else in the plugin if we're in an incompatible environment
121
+ if ( self::get_environment_warning() ) {
122
+ return;
123
+ }
124
 
125
+ include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php' );
126
+ include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-customer.php' );
127
+
128
+ // Init the gateway itself
129
+ $this->init_gateways();
130
+
131
+ add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
132
+ add_action( 'woocommerce_order_status_on-hold_to_processing', array( $this, 'capture_payment' ) );
133
+ add_action( 'woocommerce_order_status_on-hold_to_completed', array( $this, 'capture_payment' ) );
134
+ add_action( 'woocommerce_order_status_on-hold_to_cancelled', array( $this, 'cancel_payment' ) );
135
+ add_action( 'woocommerce_order_status_on-hold_to_refunded', array( $this, 'cancel_payment' ) );
136
+ add_filter( 'woocommerce_get_customer_payment_tokens', array( $this, 'woocommerce_get_customer_payment_tokens' ), 10, 3 );
137
+ add_action( 'woocommerce_payment_token_deleted', array( $this, 'woocommerce_payment_token_deleted' ), 10, 2 );
138
+ add_action( 'woocommerce_payment_token_set_default', array( $this, 'woocommerce_payment_token_set_default' ) );
139
+ add_action( 'wp_ajax_stripe_dismiss_request_api_notice', array( $this, 'dismiss_request_api_notice' ) );
140
+ add_action( 'wp_ajax_stripe_dismiss_apple_pay_notice', array( $this, 'dismiss_apple_pay_notice' ) );
141
+
142
+ include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-payment-request.php' );
143
  }
144
 
145
+ /**
146
+ * Allow this class and other classes to add slug keyed notices (to avoid duplication)
147
+ */
148
+ public function add_admin_notice( $slug, $class, $message ) {
149
+ $this->notices[ $slug ] = array(
150
+ 'class' => $class,
151
+ 'message' => $message,
152
+ );
153
+ }
154
 
155
+ /**
156
+ * The backup sanity check, in case the plugin is activated in a weird way,
157
+ * or the environment changes after activation. Also handles upgrade routines.
158
+ */
159
+ public function check_environment() {
160
+ if ( ! defined( 'IFRAME_REQUEST' ) && ( WC_STRIPE_VERSION !== get_option( 'woocommerce_stripe_version' ) ) ) {
161
+ $this->install();
162
 
163
+ do_action( 'woocommerce_stripe_updated' );
164
+ }
 
 
 
 
 
 
 
165
 
166
+ $environment_warning = self::get_environment_warning();
167
+
168
+ if ( $environment_warning && is_plugin_active( plugin_basename( __FILE__ ) ) ) {
169
+ $this->add_admin_notice( 'bad_environment', 'error', $environment_warning );
170
+ }
171
+
172
+ // Check if secret key present. Otherwise prompt, via notice, to go to
173
+ // setting.
174
+ if ( ! class_exists( 'WC_Stripe_API' ) ) {
175
+ include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php' );
176
+ }
177
 
178
+ $secret = WC_Stripe_API::get_secret_key();
 
 
 
 
 
179
 
180
+ if ( empty( $secret ) && ! ( isset( $_GET['page'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'stripe' === $_GET['section'] ) ) {
181
+ $setting_link = $this->get_setting_link();
182
+ $this->add_admin_notice( 'prompt_connect', 'notice notice-warning', sprintf( __( 'Stripe is almost ready. To get started, <a href="%s">set your Stripe account keys</a>.', 'woocommerce-gateway-stripe' ), $setting_link ) );
183
+ }
184
  }
185
 
186
+ /**
187
+ * Updates the plugin version in db
188
+ *
189
+ * @since 3.1.0
190
+ * @version 3.1.0
191
+ * @return bool
192
+ */
193
+ private static function _update_plugin_version() {
194
+ delete_option( 'wc_stripe_version' );
195
+ add_option( 'wc_stripe_version', WC_STRIPE_VERSION );
196
+
197
+ return true;
198
  }
199
 
200
+ /**
201
+ * Dismiss the Google Payment Request API Feature notice.
202
+ *
203
+ * @since 3.1.0
204
+ * @version 3.1.0
205
+ */
206
+ public function dismiss_request_api_notice() {
207
+ add_option( 'wc_stripe_show_request_api_notice', 'no' );
208
+ }
209
 
210
+ /**
211
+ * Dismiss the Apple Pay Feature notice.
212
+ *
213
+ * @since 3.1.0
214
+ * @version 3.1.0
215
+ */
216
+ public function dismiss_apple_pay_notice() {
217
+ add_option( 'wc_stripe_show_apple_pay_notice', 'no' );
218
  }
 
219
 
220
+ /**
221
+ * Handles upgrade routines.
222
+ *
223
+ * @since 3.1.0
224
+ * @version 3.1.0
225
+ */
226
+ public function install() {
227
+ if ( ! defined( 'WC_STRIPE_INSTALLING' ) ) {
228
+ define( 'WC_STRIPE_INSTALLING', true );
229
+ }
230
 
231
+ $this->_update_plugin_version();
232
  }
 
 
 
 
233
 
234
+ /**
235
+ * Checks the environment for compatibility problems. Returns a string with the first incompatibility
236
+ * found or false if the environment has no problems.
237
+ */
238
+ static function get_environment_warning() {
239
+ if ( version_compare( phpversion(), WC_STRIPE_MIN_PHP_VER, '<' ) ) {
240
+ $message = __( 'WooCommerce Stripe - The minimum PHP version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
241
 
242
+ return sprintf( $message, WC_STRIPE_MIN_PHP_VER, phpversion() );
243
+ }
244
 
245
+ if ( ! defined( 'WC_VERSION' ) ) {
246
+ return __( 'WooCommerce Stripe requires WooCommerce to be activated to work.', 'woocommerce-gateway-stripe' );
247
+ }
248
 
249
+ if ( version_compare( WC_VERSION, WC_STRIPE_MIN_WC_VER, '<' ) ) {
250
+ $message = __( 'WooCommerce Stripe - The minimum WooCommerce version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
251
 
252
+ return sprintf( $message, WC_STRIPE_MIN_WC_VER, WC_VERSION );
253
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
254
 
255
+ if ( ! function_exists( 'curl_init' ) ) {
256
+ return __( 'WooCommerce Stripe - cURL is not installed.', 'woocommerce-gateway-stripe' );
257
+ }
 
 
 
 
 
 
258
 
259
+ return false;
260
+ }
261
 
262
+ /**
263
+ * Adds plugin action links
264
+ *
265
+ * @since 1.0.0
266
+ */
267
+ public function plugin_action_links( $links ) {
268
+ $setting_link = $this->get_setting_link();
269
 
270
+ $plugin_links = array(
271
+ '<a href="' . $setting_link . '">' . __( 'Settings', 'woocommerce-gateway-stripe' ) . '</a>',
272
+ '<a href="https://docs.woothemes.com/document/stripe/">' . __( 'Docs', 'woocommerce-gateway-stripe' ) . '</a>',
273
+ '<a href="http://support.woothemes.com/">' . __( 'Support', 'woocommerce-gateway-stripe' ) . '</a>',
274
+ );
275
+ return array_merge( $plugin_links, $links );
 
 
276
  }
 
277
 
278
+ /**
279
+ * Get setting link.
280
+ *
281
+ * @since 1.0.0
282
+ *
283
+ * @return string Setting link
284
+ */
285
+ public function get_setting_link() {
286
+ $use_id_as_section = function_exists( 'WC' ) ? version_compare( WC()->version, '2.6', '>=' ) : false;
287
+
288
+ $section_slug = $use_id_as_section ? 'stripe' : strtolower( 'WC_Gateway_Stripe' );
289
+
290
+ return admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . $section_slug );
291
+ }
292
+
293
+ /**
294
+ * Display any notices we've collected thus far (e.g. for connection, disconnection)
295
+ */
296
+ public function admin_notices() {
297
+ $show_request_api_notice = get_option( 'wc_stripe_show_request_api_notice' );
298
+ $show_apple_pay_notice = get_option( 'wc_stripe_show_apple_pay_notice' );
299
+
300
+ if ( empty( $show_apple_pay_notice ) ) {
301
+ // @TODO remove this notice in the future.
302
+ ?>
303
+ <div class="notice notice-warning wc-stripe-apple-pay-notice is-dismissible"><p><?php esc_html_e( 'New Feature! Stripe now supports Apple Pay. Your customers can now purchase your products even faster. Apple Pay has been enabled by default.', 'woocommerce-gateway-stripe' ); ?></p></div>
304
+
305
+ <script type="application/javascript">
306
+ jQuery( '.wc-stripe-apple-pay-notice' ).on( 'click', '.notice-dismiss', function() {
307
+ var data = {
308
+ action: 'stripe_dismiss_apple_pay_notice'
309
+ };
310
+
311
+ jQuery.post( '<?php echo admin_url( 'admin-ajax.php' ); ?>', data );
312
+ });
313
+ </script>
314
+
315
+ <?php
316
+ }
317
+
318
+ if ( empty( $show_request_api_notice ) ) {
319
+ // @TODO remove this notice in the future.
320
+ ?>
321
+ <div class="notice notice-warning wc-stripe-request-api-notice is-dismissible"><p><?php esc_html_e( 'New Feature! Stripe now supports Google Payment Request. Your customers can now use mobile phones with supported browsers such as Chrome to make purchases easier and faster.', 'woocommerce-gateway-stripe' ); ?></p></div>
322
+
323
+ <script type="application/javascript">
324
+ jQuery( '.wc-stripe-request-api-notice' ).on( 'click', '.notice-dismiss', function() {
325
+ var data = {
326
+ action: 'stripe_dismiss_request_api_notice'
327
+ };
328
+
329
+ jQuery.post( '<?php echo admin_url( 'admin-ajax.php' ); ?>', data );
330
+ });
331
+ </script>
332
+
333
+ <?php
334
+ }
335
+
336
+ foreach ( (array) $this->notices as $notice_key => $notice ) {
337
+ echo "<div class='" . esc_attr( $notice['class'] ) . "'><p>";
338
+ echo wp_kses( $notice['message'], array( 'a' => array( 'href' => array() ) ) );
339
+ echo '</p></div>';
340
+ }
341
  }
342
 
343
+ /**
344
+ * Initialize the gateway. Called very early - in the context of the plugins_loaded action
345
+ *
346
+ * @since 1.0.0
347
+ */
348
+ public function init_gateways() {
349
+ if ( class_exists( 'WC_Subscriptions_Order' ) && function_exists( 'wcs_create_renewal_order' ) ) {
350
+ $this->subscription_support_enabled = true;
351
+ }
352
+
353
+ if ( class_exists( 'WC_Pre_Orders_Order' ) ) {
354
+ $this->pre_order_enabled = true;
355
+ }
356
+
357
+ if ( ! class_exists( 'WC_Payment_Gateway' ) ) {
358
+ return;
359
+ }
360
+
361
+ if ( class_exists( 'WC_Payment_Gateway_CC' ) ) {
362
+ include_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-stripe.php' );
363
+ include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-apple-pay.php' );
364
+ } else {
365
+ include_once( dirname( __FILE__ ) . '/includes/legacy/class-wc-gateway-stripe.php' );
366
+ include_once( dirname( __FILE__ ) . '/includes/legacy/class-wc-gateway-stripe-saved-cards.php' );
367
+ }
368
+
369
+ load_plugin_textdomain( 'woocommerce-gateway-stripe', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
370
+ add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateways' ) );
371
+
372
+ $load_addons = (
373
+ $this->subscription_support_enabled
374
+ ||
375
+ $this->pre_order_enabled
376
+ );
377
+
378
+ if ( $load_addons ) {
379
+ require_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-stripe-addons.php' );
380
+ }
381
  }
382
 
383
+ /**
384
+ * Add the gateways to WooCommerce
385
+ *
386
+ * @since 1.0.0
387
+ */
388
+ public function add_gateways( $methods ) {
389
+ if ( $this->subscription_support_enabled || $this->pre_order_enabled ) {
390
+ $methods[] = 'WC_Gateway_Stripe_Addons';
391
+ } else {
392
+ $methods[] = 'WC_Gateway_Stripe';
393
+ }
394
+ return $methods;
395
  }
396
 
397
+ /**
398
+ * List of currencies supported by Stripe that has no decimals.
399
+ *
400
+ * @return array $currencies
401
+ */
402
+ public static function no_decimal_currencies() {
403
+ return array(
404
+ 'bif', // Burundian Franc
405
+ 'djf', // Djiboutian Franc
406
+ 'jpy', // Japanese Yen
407
+ 'krw', // South Korean Won
408
+ 'pyg', // Paraguayan Guaraní
409
+ 'vnd', // Vietnamese Đồng
410
+ 'xaf', // Central African Cfa Franc
411
+ 'xpf', // Cfp Franc
412
+ 'clp', // Chilean Peso
413
+ 'gnf', // Guinean Franc
414
+ 'kmf', // Comorian Franc
415
+ 'mga', // Malagasy Ariary
416
+ 'rwf', // Rwandan Franc
417
+ 'vuv', // Vanuatu Vatu
418
+ 'xof', // West African Cfa Franc
419
+ );
420
  }
421
 
422
+ /**
423
+ * Stripe uses smallest denomination in currencies such as cents.
424
+ * We need to format the returned currency from Stripe into human readable form.
425
+ *
426
+ * @param object $balance_transaction
427
+ * @param string $type Type of number to format
428
+ */
429
+ public static function format_number( $balance_transaction, $type = 'fee' ) {
430
+ if ( ! is_object( $balance_transaction ) ) {
431
+ return;
432
+ }
433
 
434
+ if ( in_array( strtolower( $balance_transaction->currency ), self::no_decimal_currencies() ) ) {
435
+ if ( 'fee' === $type ) {
436
+ return $balance_transaction->fee;
437
+ }
 
438
 
439
+ return $balance_transaction->net;
440
+ }
441
+
442
+ if ( 'fee' === $type ) {
443
+ return number_format( $balance_transaction->fee / 100, 2, '.', '' );
444
+ }
445
 
446
+ return number_format( $balance_transaction->net / 100, 2, '.', '' );
 
 
 
 
 
 
 
 
 
447
  }
 
 
448
 
449
+ /**
450
+ * Capture payment when the order is changed from on-hold to complete or processing
451
+ *
452
+ * @param int $order_id
453
+ */
454
+ public function capture_payment( $order_id ) {
455
+ $order = wc_get_order( $order_id );
456
+
457
+ if ( 'stripe' === ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->payment_method : $order->get_payment_method() ) ) {
458
+ $charge = get_post_meta( $order_id, '_stripe_charge_id', true );
459
+ $captured = get_post_meta( $order_id, '_stripe_charge_captured', true );
460
+
461
+ if ( $charge && 'no' === $captured ) {
462
+ $result = WC_Stripe_API::request( array(
463
+ 'amount' => $order->get_total() * 100,
464
+ 'expand[]' => 'balance_transaction',
465
+ ), 'charges/' . $charge . '/capture' );
466
+
467
+ if ( is_wp_error( $result ) ) {
468
+ $order->add_order_note( __( 'Unable to capture charge!', 'woocommerce-gateway-stripe' ) . ' ' . $result->get_error_message() );
469
+ } else {
470
+ $order->add_order_note( sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $result->id ) );
471
+ update_post_meta( $order_id, '_stripe_charge_captured', 'yes' );
472
+
473
+ // Store other data such as fees
474
+ update_post_meta( $order_id, 'Stripe Payment ID', $result->id );
475
+
476
+ if ( isset( $result->balance_transaction ) && isset( $result->balance_transaction->fee ) ) {
477
+ // Fees and Net needs to both come from Stripe to be accurate as the returned
478
+ // values are in the local currency of the Stripe account, not from WC.
479
+ $fee = ! empty( $result->balance_transaction->fee ) ? self::format_number( $result->balance_transaction, 'fee' ) : 0;
480
+ $net = ! empty( $result->balance_transaction->net ) ? self::format_number( $result->balance_transaction, 'net' ) : 0;
481
+ update_post_meta( $order_id, 'Stripe Fee', $fee );
482
+ update_post_meta( $order_id, 'Net Revenue From Stripe', $net );
483
+ }
484
  }
485
  }
486
  }
487
  }
 
488
 
489
+ /**
490
+ * Cancel pre-auth on refund/cancellation
491
+ *
492
+ * @param int $order_id
493
+ */
494
+ public function cancel_payment( $order_id ) {
495
+ $order = wc_get_order( $order_id );
496
+
497
+ if ( 'stripe' === ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->payment_method : $order->get_payment_method() ) ) {
498
+ $charge = get_post_meta( $order_id, '_stripe_charge_id', true );
499
+
500
+ if ( $charge ) {
501
+ $result = WC_Stripe_API::request( array(
502
+ 'amount' => $order->get_total() * 100,
503
+ ), 'charges/' . $charge . '/refund' );
504
+
505
+ if ( is_wp_error( $result ) ) {
506
+ $order->add_order_note( __( 'Unable to refund charge!', 'woocommerce-gateway-stripe' ) . ' ' . $result->get_error_message() );
507
+ } else {
508
+ $order->add_order_note( sprintf( __( 'Stripe charge refunded (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $result->id ) );
509
+ delete_post_meta( $order_id, '_stripe_charge_captured' );
510
+ delete_post_meta( $order_id, '_stripe_charge_id' );
511
+ }
512
  }
513
  }
514
  }
 
515
 
516
+ /**
517
+ * Gets saved tokens from API if they don't already exist in WooCommerce.
518
+ * @param array $tokens
519
+ * @return array
520
+ */
521
+ public function woocommerce_get_customer_payment_tokens( $tokens, $customer_id, $gateway_id ) {
522
+ if ( is_user_logged_in() && 'stripe' === $gateway_id && class_exists( 'WC_Payment_Token_CC' ) ) {
523
+ $stripe_customer = new WC_Stripe_Customer( $customer_id );
524
+ $stripe_cards = $stripe_customer->get_cards();
525
+ $stored_tokens = array();
526
+
527
+ foreach ( $tokens as $token ) {
528
+ $stored_tokens[] = $token->get_token();
529
+ }
530
 
531
+ foreach ( $stripe_cards as $card ) {
532
+ if ( ! in_array( $card->id, $stored_tokens ) ) {
533
+ $token = new WC_Payment_Token_CC();
534
+ $token->set_token( $card->id );
535
+ $token->set_gateway_id( 'stripe' );
536
+ $token->set_card_type( strtolower( $card->brand ) );
537
+ $token->set_last4( $card->last4 );
538
+ $token->set_expiry_month( $card->exp_month );
539
+ $token->set_expiry_year( $card->exp_year );
540
+ $token->set_user_id( $customer_id );
541
+ $token->save();
542
+ $tokens[ $token->get_id() ] = $token;
543
+ }
544
  }
545
  }
546
+ return $tokens;
547
  }
 
 
548
 
549
+ /**
550
+ * Delete token from Stripe
551
+ */
552
+ public function woocommerce_payment_token_deleted( $token_id, $token ) {
553
+ if ( 'stripe' === $token->get_gateway_id() ) {
554
+ $stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
555
+ $stripe_customer->delete_card( $token->get_token() );
556
+ }
557
  }
 
558
 
559
+ /**
560
+ * Set as default in Stripe
561
+ */
562
+ public function woocommerce_payment_token_set_default( $token_id ) {
563
+ $token = WC_Payment_Tokens::get( $token_id );
564
+ if ( 'stripe' === $token->get_gateway_id() ) {
565
+ $stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
566
+ $stripe_customer->set_default_card( $token->get_token() );
567
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
  }
 
 
 
 
569
 
570
+ /**
571
+ * Checks Stripe minimum order value authorized per currency
572
+ */
573
+ public static function get_minimum_amount() {
574
+ // Check order amount
575
+ switch ( get_woocommerce_currency() ) {
576
+ case 'USD':
577
+ case 'CAD':
578
+ case 'EUR':
579
+ case 'CHF':
580
+ case 'AUD':
581
+ case 'SGD':
582
+ $minimum_amount = 50;
583
+ break;
584
+ case 'GBP':
585
+ $minimum_amount = 30;
586
+ break;
587
+ case 'DKK':
588
+ $minimum_amount = 250;
589
+ break;
590
+ case 'NOK':
591
+ case 'SEK':
592
+ $minimum_amount = 300;
593
+ break;
594
+ case 'JPY':
595
+ $minimum_amount = 5000;
596
+ break;
597
+ case 'MXN':
598
+ $minimum_amount = 1000;
599
+ break;
600
+ case 'HKD':
601
+ $minimum_amount = 400;
602
+ break;
603
+ default:
604
+ $minimum_amount = 50;
605
+ break;
606
+ }
607
+
608
+ return $minimum_amount;
609
  }
610
 
611
+ /**
612
+ * What rolls down stairs
613
+ * alone or in pairs,
614
+ * and over your neighbor's dog?
615
+ * What's great for a snack,
616
+ * And fits on your back?
617
+ * It's log, log, log
618
+ */
619
+ public static function log( $message ) {
620
+ if ( empty( self::$log ) ) {
621
+ self::$log = new WC_Logger();
622
+ }
623
 
624
+ self::$log->add( 'woocommerce-gateway-stripe', $message );
 
625
  }
626
  }
 
627
 
628
+ $GLOBALS['wc_stripe'] = WC_Stripe::get_instance();
629
 
630
  endif;