Version Description
- First public WordPress.org release.
- Refactor for WC 2.6 and above. Legacy support for 2.5.
- Improved saved card handling using tokenization API in WooCommerce.
See changelog for all versions.
Download this release
Release Info
Developer | mikejolley |
Plugin | WooCommerce Stripe Payment Gateway |
Version | 3.0.0 |
Comparing to | |
See all releases |
Version 3.0.0
- .github/CONTRIBUTING.md +14 -0
- .github/ISSUE_TEMPLATE.md +28 -0
- .github/PULL_REQUEST_TEMPLATE.md +9 -0
- DEVELOPER.md +46 -0
- assets/images/bitcoin.png +0 -0
- assets/images/bitcoin.svg +7 -0
- assets/images/diners.png +0 -0
- assets/js/stripe.js +136 -0
- assets/js/stripe_checkout.js +135 -0
- changelog.txt +309 -0
- includes/class-wc-gateway-stripe-addons.php +411 -0
- includes/class-wc-gateway-stripe.php +570 -0
- includes/class-wc-stripe-api.php +91 -0
- includes/class-wc-stripe-customer.php +281 -0
- includes/legacy/class-wc-gateway-stripe-saved-cards.php +83 -0
- includes/legacy/class-wc-gateway-stripe.php +596 -0
- includes/legacy/templates/saved-cards.php +41 -0
- includes/settings-stripe.php +132 -0
- languages/index.html +0 -0
- languages/woocommerce-gateway-stripe.pot +508 -0
- readme.txt +95 -0
- woocommerce-gateway-stripe.php +436 -0
- wordpress_org_assets/banner-1544x500.png +0 -0
- wordpress_org_assets/banner-772x250.png +0 -0
- wordpress_org_assets/icon-128x128.png +0 -0
- wordpress_org_assets/icon-256x256.png +0 -0
- wordpress_org_assets/screenshot-1.png +0 -0
- wordpress_org_assets/screenshot-2.png +0 -0
- wordpress_org_assets/screenshot-3.png +0 -0
- wordpress_org_assets/screenshot-4.png +0 -0
- wordpress_org_assets/screenshot-5.png +0 -0
- wordpress_org_assets/wc-stripe.sketch +0 -0
.github/CONTRIBUTING.md
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
### Create Bug Reports
|
2 |
+
|
3 |
+
If you find a bug or suggest enhancement, let us know by [opening a new issue](https://github.com/woothemes/woocommerce-gateway-stripe/issues/new).
|
4 |
+
|
5 |
+
### Write and submit a patch
|
6 |
+
|
7 |
+
If you'd like to fix a bug, you can submit a Pull Request. If possible, raises an issue first and link the issue in your [commit message](https://help.github.com/articles/closing-issues-via-commit-messages/) or [PR's body](https://github.com/blog/1506-closing-issues-via-pull-requests).
|
8 |
+
|
9 |
+
When creating Pull Requests, remember:
|
10 |
+
|
11 |
+
- [Check In Early, Check In Often](http://blog.codinghorror.com/check-in-early-check-in-often/).
|
12 |
+
- Write [good commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
13 |
+
- Respect the [Best practices for WordPress development](http://jetpack.com/contribute/#practices).
|
14 |
+
|
.github/ISSUE_TEMPLATE.md
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!-- Thanks for contributing to this extension! Pick a clear title ("Order: Unable to refund") and proceed. -->
|
2 |
+
|
3 |
+
#### What I expected
|
4 |
+
|
5 |
+
<!-- What you expected when performing the steps -->
|
6 |
+
|
7 |
+
#### What happened instead
|
8 |
+
|
9 |
+
<!-- What actual results you got -->
|
10 |
+
|
11 |
+
#### Steps to reproduce the issue
|
12 |
+
|
13 |
+
<!-- Please add detailed steps to reproduce the issue. Make sure it's reproducible locally. Other extensions should be deactivated and standard theme is used when reproducing the issue locally -->
|
14 |
+
|
15 |
+
<!--
|
16 |
+
PLEASE NOTE
|
17 |
+
- These comments won't show up when you submit the issue.
|
18 |
+
- Everything is optional, but try to add as many details as possible.
|
19 |
+
- Screenshot worth a thousand words, use screenshots if possible.
|
20 |
+
- If requesting a new feature, explain why you'd like to see it added.
|
21 |
+
- Please apply appropriate labels on the issue
|
22 |
+
-->
|
23 |
+
|
24 |
+
|
25 |
+
-------------------
|
26 |
+
|
27 |
+
- [ ] Issue assigned to next milestone.
|
28 |
+
- [ ] Issue assigned a priority (will be assessed by maintainers).
|
.github/PULL_REQUEST_TEMPLATE.md
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Fixes # .
|
2 |
+
|
3 |
+
#### Changes proposed in this Pull Request:
|
4 |
+
-
|
5 |
+
|
6 |
+
-------------------
|
7 |
+
- [ ] Make sure your changes respect [WordPress' coding standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/).
|
8 |
+
- [ ] Did you make changes, or create a **new .js file**? If **Gruntfile.js** exists in the repo, make sure to run `grunt`.
|
9 |
+
|
DEVELOPER.md
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# DEVELOPER.md
|
2 |
+
|
3 |
+
## Testing
|
4 |
+
|
5 |
+
* In wp-admin > WooCommerce > Settings > Checkout > Stripe, Enable Stripe, Enable Test Mode, Enable Stripe Checkout and Enable Payment via Saved Cards
|
6 |
+
* In wp-admin > WooCommerce > Settings > Checkout > Stripe, enter a Test Secret Key and a Test Publishable Key
|
7 |
+
* Enable at least one other payment gateway (e.g. Cheques)
|
8 |
+
|
9 |
+
* On the front side, place an item in your cart and proceed to Checkout
|
10 |
+
* Fill in all required fields in the Billing Details area
|
11 |
+
* Select Credit Card (Stripe) and "Use a new credit card"
|
12 |
+
* Click on Continue to payment
|
13 |
+
* Verify you get the stripe modal requesting card number, expiration and CVC
|
14 |
+
* Enter 4242 4242 4242 4242, 12/17, 123
|
15 |
+
* Leave Remember Me unchecked
|
16 |
+
* Click Confirm and Pay
|
17 |
+
* Verify the modal closes, the page dims for a bit, and then you are redirected to Order Received
|
18 |
+
|
19 |
+
* Repeat the above steps, but this time instead of "Use a new credit card" use a stored card
|
20 |
+
* Click on Continue to payment
|
21 |
+
* Verify the page dims for a bit and then you are redirected to Order Received
|
22 |
+
|
23 |
+
* Repeat the above steps, but this time clear the Billing Details (e.g. Name, etc)
|
24 |
+
* Choose a stored card in Stripe
|
25 |
+
* Click on Continue to payment
|
26 |
+
* Verify you get prompted to fill in required fields.
|
27 |
+
* Fill in the required fields
|
28 |
+
* Click on Continue to payment
|
29 |
+
* Verify the page dims for a bit and then you are redirected to Order Received
|
30 |
+
|
31 |
+
* Repeat the above steps, but this time choose the "Cheque Payment" gateway
|
32 |
+
* Click on Place Order
|
33 |
+
* Verify the page dims for a bit and then you are redirected to Order Received
|
34 |
+
|
35 |
+
* Repeat at least the "Use a new credit card" case on Chrome on an iPhone or iPad
|
36 |
+
|
37 |
+
* In wp-admin > WooCommerce > Settings > Checkout > Stripe, uncheck Enable Payment via Saved Cards
|
38 |
+
* On the front side, place an item in your cart and proceed to Checkout
|
39 |
+
* Fill in all required fields in the Billing Details area
|
40 |
+
* Select Credit Card (Stripe)
|
41 |
+
* Click on Continue to payment
|
42 |
+
* Verify you get the stripe modal requesting card number, expiration and CVC
|
43 |
+
* Enter 4242 4242 4242 4242, 12/17, 123
|
44 |
+
* Leave Remember Me unchecked
|
45 |
+
* Click Confirm and Pay
|
46 |
+
* Verify the modal closes, the page dims for a bit, and then you are redirected to Order Received
|
assets/images/bitcoin.png
ADDED
Binary file
|
assets/images/bitcoin.svg
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
2 |
+
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="64" width="64" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
3 |
+
<g transform="translate(0.00630876,-0.00301984)">
|
4 |
+
<path fill="#f7931a" d="m63.033,39.744c-4.274,17.143-21.637,27.576-38.782,23.301-17.138-4.274-27.571-21.638-23.295-38.78,4.272-17.145,21.635-27.579,38.775-23.305,17.144,4.274,27.576,21.64,23.302,38.784z"/>
|
5 |
+
<path fill="#FFF" d="m46.103,27.444c0.637-4.258-2.605-6.547-7.038-8.074l1.438-5.768-3.511-0.875-1.4,5.616c-0.923-0.23-1.871-0.447-2.813-0.662l1.41-5.653-3.509-0.875-1.439,5.766c-0.764-0.174-1.514-0.346-2.242-0.527l0.004-0.018-4.842-1.209-0.934,3.75s2.605,0.597,2.55,0.634c1.422,0.355,1.679,1.296,1.636,2.042l-1.638,6.571c0.098,0.025,0.225,0.061,0.365,0.117-0.117-0.029-0.242-0.061-0.371-0.092l-2.296,9.205c-0.174,0.432-0.615,1.08-1.609,0.834,0.035,0.051-2.552-0.637-2.552-0.637l-1.743,4.019,4.569,1.139c0.85,0.213,1.683,0.436,2.503,0.646l-1.453,5.834,3.507,0.875,1.439-5.772c0.958,0.26,1.888,0.5,2.798,0.726l-1.434,5.745,3.511,0.875,1.453-5.823c5.987,1.133,10.489,0.676,12.384-4.739,1.527-4.36-0.076-6.875-3.226-8.515,2.294-0.529,4.022-2.038,4.483-5.155zm-8.022,11.249c-1.085,4.36-8.426,2.003-10.806,1.412l1.928-7.729c2.38,0.594,10.012,1.77,8.878,6.317zm1.086-11.312c-0.99,3.966-7.1,1.951-9.082,1.457l1.748-7.01c1.982,0.494,8.365,1.416,7.334,5.553z"/>
|
6 |
+
</g>
|
7 |
+
</svg>
|
assets/images/diners.png
ADDED
Binary file
|
assets/js/stripe.js
ADDED
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* global wc_stripe_params */
|
2 |
+
Stripe.setPublishableKey( wc_stripe_params.key );
|
3 |
+
|
4 |
+
jQuery( function( $ ) {
|
5 |
+
|
6 |
+
/* Open and close for legacy class */
|
7 |
+
jQuery( "form.checkout, form#order_review" ).on('change', 'input[name="wc-stripe-payment-token"]', function() {
|
8 |
+
if ( jQuery( '.stripe-legacy-payment-fields input[name="wc-stripe-payment-token"]:checked' ).val() == 'new' ) {
|
9 |
+
jQuery( '.stripe-legacy-payment-fields #stripe-payment-data' ).slideDown( 200 );
|
10 |
+
} else {
|
11 |
+
jQuery( '.stripe-legacy-payment-fields #stripe-payment-data' ).slideUp( 200 );
|
12 |
+
}
|
13 |
+
} );
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Object to handle Stripe payment forms.
|
17 |
+
*/
|
18 |
+
var wc_stripe_form = {
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Initialize event handlers and UI state.
|
22 |
+
*/
|
23 |
+
init: function( form ) {
|
24 |
+
this.form = form;
|
25 |
+
|
26 |
+
$( this.form )
|
27 |
+
.on(
|
28 |
+
'submit checkout_place_order_stripe',
|
29 |
+
this.onSubmit
|
30 |
+
);
|
31 |
+
|
32 |
+
$( document )
|
33 |
+
.on(
|
34 |
+
'change',
|
35 |
+
'#wc-stripe-cc-form :input',
|
36 |
+
this.onCCFormChange
|
37 |
+
)
|
38 |
+
.on(
|
39 |
+
'stripeError',
|
40 |
+
this.onError
|
41 |
+
);
|
42 |
+
},
|
43 |
+
|
44 |
+
isStripeChosen: function() {
|
45 |
+
return $( '#payment_method_stripe' ).is( ':checked' ) && ( ! $( 'input[name="wc-stripe-payment-token"]:checked' ).length || 'new' === $( 'input[name="wc-stripe-payment-token"]:checked' ).val() );
|
46 |
+
},
|
47 |
+
|
48 |
+
hasToken: function() {
|
49 |
+
return 0 < $( 'input.stripe_token' ).length;
|
50 |
+
},
|
51 |
+
|
52 |
+
block: function() {
|
53 |
+
wc_stripe_form.form.block({
|
54 |
+
message: null,
|
55 |
+
overlayCSS: {
|
56 |
+
background: '#fff',
|
57 |
+
opacity: 0.6
|
58 |
+
}
|
59 |
+
});
|
60 |
+
},
|
61 |
+
|
62 |
+
unblock: function() {
|
63 |
+
wc_stripe_form.form.unblock();
|
64 |
+
},
|
65 |
+
|
66 |
+
onError: function( e, responseObject ) {
|
67 |
+
$( '.woocommerce-error, .stripe_token' ).remove();
|
68 |
+
$( '#stripe-card-number' ).closest( 'p' ).before( '<ul class="woocommerce_error woocommerce-error"><li>' + responseObject.response.error.message + '</li></ul>' );
|
69 |
+
wc_stripe_form.unblock();
|
70 |
+
},
|
71 |
+
|
72 |
+
onSubmit: function( e ) {
|
73 |
+
if ( wc_stripe_form.isStripeChosen() && ! wc_stripe_form.hasToken() ) {
|
74 |
+
e.preventDefault();
|
75 |
+
wc_stripe_form.block();
|
76 |
+
|
77 |
+
var card = $( '#stripe-card-number' ).val(),
|
78 |
+
cvc = $( '#stripe-card-cvc' ).val(),
|
79 |
+
expires = $( '#stripe-card-expiry' ).payment( 'cardExpiryVal' ),
|
80 |
+
first_name = $( '#billing_first_name' ).length ? $( '#billing_first_name' ).val() : wc_stripe_params.billing_first_name,
|
81 |
+
last_name = $( '#billing_last_name' ).length ? $( '#billing_last_name' ).val() : wc_stripe_params.billing_last_name,
|
82 |
+
address = {
|
83 |
+
|
84 |
+
},
|
85 |
+
data = {
|
86 |
+
number : card,
|
87 |
+
cvc : cvc,
|
88 |
+
exp_month: parseInt( expires['month'] ) || 0,
|
89 |
+
exp_year : parseInt( expires['year'] ) || 0,
|
90 |
+
name : first_name + ' ' + last_name
|
91 |
+
|
92 |
+
};
|
93 |
+
|
94 |
+
if ( jQuery('#billing_address_1').length > 0 ) {
|
95 |
+
data.address_line1 = $( '#billing_address_1' ).val();
|
96 |
+
data.address_line2 = $( '#billing_address_2' ).val();
|
97 |
+
data.address_state = $( '#billing_state' ).val();
|
98 |
+
data.address_city = $( '#billing_city' ).val();
|
99 |
+
data.address_zip = $( '#billing_postcode' ).val();
|
100 |
+
data.address_country = $( '#billing_country' ).val();
|
101 |
+
} else if ( data.address_line1 ) {
|
102 |
+
data.address_line1 = wc_stripe_params.billing_address_1;
|
103 |
+
data.address_line2 = wc_stripe_params.billing_address_2;
|
104 |
+
data.address_state = wc_stripe_params.billing_state;
|
105 |
+
data.address_city = wc_stripe_params.billing_city;
|
106 |
+
data.address_zip = wc_stripe_params.billing_postcode;
|
107 |
+
data.address_country = wc_stripe_params.billing_country;
|
108 |
+
}
|
109 |
+
|
110 |
+
Stripe.createToken( data, wc_stripe_form.onStripeReponse );
|
111 |
+
|
112 |
+
// Prevent form submitting
|
113 |
+
return false;
|
114 |
+
}
|
115 |
+
},
|
116 |
+
|
117 |
+
onCCFormChange: function() {
|
118 |
+
$( '.woocommerce-error, .stripe_token' ).remove();
|
119 |
+
},
|
120 |
+
|
121 |
+
onStripeReponse: function( status, response ) {
|
122 |
+
if ( response.error ) {
|
123 |
+
$( document ).trigger( 'stripeError', { response: response } );
|
124 |
+
} else {
|
125 |
+
// token contains id, last4, and card type
|
126 |
+
var token = response['id'];
|
127 |
+
|
128 |
+
// insert the token into the form so it gets submitted to the server
|
129 |
+
wc_stripe_form.form.append( "<input type='hidden' class='stripe_token' name='stripe_token' value='" + token + "'/>" );
|
130 |
+
wc_stripe_form.form.submit();
|
131 |
+
}
|
132 |
+
}
|
133 |
+
};
|
134 |
+
|
135 |
+
wc_stripe_form.init( $( "form.checkout, form#order_review, form#add_payment_method" ) );
|
136 |
+
} );
|
assets/js/stripe_checkout.js
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery( function( $ ) {
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Object to handle Stripe payment forms.
|
5 |
+
*/
|
6 |
+
var wc_stripe_form = {
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Initialize e handlers and UI state.
|
10 |
+
*/
|
11 |
+
init: function( form ) {
|
12 |
+
this.form = form;
|
13 |
+
this.stripe_submit = false;
|
14 |
+
|
15 |
+
$( this.form )
|
16 |
+
// We need to bind directly to the click (and not checkout_place_order_stripe) to avoid popup blockers
|
17 |
+
// especially on mobile devices (like on Chrome for iOS) from blocking StripeCheckout.open from opening a tab
|
18 |
+
.on( 'click', '#place_order', this.onSubmit )
|
19 |
+
|
20 |
+
// WooCommerce lets us return a false on checkout_place_order_{gateway} to keep the form from submitting
|
21 |
+
.on( 'submit checkout_place_order_stripe' );
|
22 |
+
},
|
23 |
+
|
24 |
+
isStripeChosen: function() {
|
25 |
+
return $( '#payment_method_stripe' ).is( ':checked' ) && ( ! $( 'input[name="wc-stripe-payment-token"]:checked' ).length || 'new' === $( 'input[name="wc-stripe-payment-token"]:checked' ).val() );
|
26 |
+
},
|
27 |
+
|
28 |
+
isStripeModalNeeded: function( e ) {
|
29 |
+
var token = wc_stripe_form.form.find( 'input.stripe_token' );
|
30 |
+
|
31 |
+
// If this is a stripe submission (after modal) and token exists, allow submit.
|
32 |
+
if ( wc_stripe_form.stripe_submit && token ) {
|
33 |
+
return false;
|
34 |
+
}
|
35 |
+
|
36 |
+
// Don't affect submission if modal is not needed.
|
37 |
+
if ( ! wc_stripe_form.isStripeChosen() ) {
|
38 |
+
return false;
|
39 |
+
}
|
40 |
+
|
41 |
+
// Don't open modal if required fields are not complete
|
42 |
+
if ( $( 'input#terms' ).length === 1 && $( 'input#terms:checked' ).length === 0 ) {
|
43 |
+
return false;
|
44 |
+
}
|
45 |
+
|
46 |
+
if ( $( '#createaccount' ).is( ':checked' ) && $( '#account_password' ).length && $( '#account_password' ).val() === '' ) {
|
47 |
+
return false;
|
48 |
+
}
|
49 |
+
|
50 |
+
// check to see if we need to validate shipping address
|
51 |
+
if ( $( '#ship-to-different-address-checkbox' ).is( ':checked' ) ) {
|
52 |
+
$required_inputs = $( '.woocommerce-billing-fields .validate-required, .woocommerce-shipping-fields .validate-required' );
|
53 |
+
} else {
|
54 |
+
$required_inputs = $( '.woocommerce-billing-fields .validate-required' );
|
55 |
+
}
|
56 |
+
|
57 |
+
if ( $required_inputs.length ) {
|
58 |
+
var required_error = false;
|
59 |
+
|
60 |
+
$required_inputs.each( function() {
|
61 |
+
if ( $( this ).find( 'input.input-text, select' ).not( $( '#account_password, #account_username' ) ).val() === '' ) {
|
62 |
+
required_error = true;
|
63 |
+
}
|
64 |
+
});
|
65 |
+
|
66 |
+
if ( required_error ) {
|
67 |
+
return false;
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
return true;
|
72 |
+
},
|
73 |
+
|
74 |
+
block: function() {
|
75 |
+
wc_stripe_form.form.block({
|
76 |
+
message: null,
|
77 |
+
overlayCSS: {
|
78 |
+
background: '#fff',
|
79 |
+
opacity: 0.6
|
80 |
+
}
|
81 |
+
});
|
82 |
+
},
|
83 |
+
|
84 |
+
unblock: function() {
|
85 |
+
wc_stripe_form.form.unblock();
|
86 |
+
},
|
87 |
+
|
88 |
+
onClose: function() {
|
89 |
+
wc_stripe_form.unblock();
|
90 |
+
},
|
91 |
+
|
92 |
+
onSubmit: function( e ) {
|
93 |
+
if ( wc_stripe_form.isStripeModalNeeded() ) {
|
94 |
+
e.preventDefault();
|
95 |
+
|
96 |
+
// Capture submittal and open stripecheckout
|
97 |
+
var $form = wc_stripe_form.form,
|
98 |
+
$data = $( '#stripe-payment-data' ),
|
99 |
+
token = $form.find( 'input.stripe_token' );
|
100 |
+
|
101 |
+
token.val( '' );
|
102 |
+
|
103 |
+
var token_action = function( res ) {
|
104 |
+
$form.find( 'input.stripe_token' ).remove();
|
105 |
+
$form.append( '<input type="hidden" class="stripe_token" name="stripe_token" value="' + res.id + '"/>' );
|
106 |
+
wc_stripe_form.stripe_submit = true;
|
107 |
+
$form.submit();
|
108 |
+
};
|
109 |
+
|
110 |
+
StripeCheckout.open({
|
111 |
+
key : wc_stripe_params.key,
|
112 |
+
address : false,
|
113 |
+
amount : $data.data( 'amount' ),
|
114 |
+
name : $data.data( 'name' ),
|
115 |
+
description : $data.data( 'description' ),
|
116 |
+
currency : $data.data( 'currency' ),
|
117 |
+
image : $data.data( 'image' ),
|
118 |
+
bitcoin : $data.data( 'bitcoin' ),
|
119 |
+
locale : $data.data( 'locale' ),
|
120 |
+
refund_mispayments: true, // for bitcoin payments let Stripe handle refunds if too little is paid
|
121 |
+
email : $( '#billing_email' ).val() || $data.data( 'email' ),
|
122 |
+
"panel-label" : $data.data( 'panel-label' ),
|
123 |
+
token : token_action,
|
124 |
+
closed : wc_stripe_form.onClose()
|
125 |
+
});
|
126 |
+
|
127 |
+
return false;
|
128 |
+
}
|
129 |
+
|
130 |
+
return true;
|
131 |
+
}
|
132 |
+
};
|
133 |
+
|
134 |
+
wc_stripe_form.init( $( "form.checkout, form#order_review, form#add_payment_method" ) );
|
135 |
+
} );
|
changelog.txt
ADDED
@@ -0,0 +1,309 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*** Changelog ***
|
2 |
+
|
3 |
+
= 3.0.0 =
|
4 |
+
* First public WordPress.org release.
|
5 |
+
* Refactor for WC 2.6 and above. Legacy support for 2.5.
|
6 |
+
* Improved saved card handling using tokenization API in WooCommerce.
|
7 |
+
|
8 |
+
= 2.6.12 - 2016.04.13 =
|
9 |
+
* Fix - When saved cards option is enabled with no cards on file, CC field was hidden.
|
10 |
+
|
11 |
+
= 2.6.11 - 2016.04.11 =
|
12 |
+
* Add - Option to set a default card in manage card section and detect previous card paid by subscription.
|
13 |
+
* Fix - Admin notice link when key is not added and when addons are present.
|
14 |
+
|
15 |
+
= 2.6.10 - 2016.03.16 =
|
16 |
+
* Tweak - Add logging mechanism. New 'Logging' option is added in Stripe gateway setting to enable logging.
|
17 |
+
* Fix - Allow language files to be located outside of plugin directory
|
18 |
+
|
19 |
+
= 2.6.9 - 2016.02.29 =
|
20 |
+
* Tweak - Allow mechanism to override Stripe JS error handler. See https://gist.github.com/gedex/240492f479c7443e4780
|
21 |
+
for an example to override error handler with simple alert.
|
22 |
+
|
23 |
+
= 2.6.8 - 2016.02.11 =
|
24 |
+
* Tweak - Include card brand in saved cards radio label class
|
25 |
+
* Tweak - Add action when deleting card
|
26 |
+
* Tweak - Add actions for add_card and add_customer
|
27 |
+
* Tweak - Add support for automatic localisation in Stripe Checkout modal
|
28 |
+
* Fix - Check for Stripe error code emptiness before returning the WP_Error
|
29 |
+
|
30 |
+
= 2.6.7 - 2015.12.17 =
|
31 |
+
* Fix is_available SSL check to also work properly on hosts that always serve HTTPS
|
32 |
+
|
33 |
+
= 2.6.6 - 2015.12.03 =
|
34 |
+
* Fix a JavaScript bug introduced in 2.6.4 that caused checkout with a saved card to fail
|
35 |
+
|
36 |
+
= 2.6.5 - 2015.12.02 =
|
37 |
+
* Do not require a card id when updating a subscription payment method
|
38 |
+
|
39 |
+
= 2.6.4 - 2015.11.20 =
|
40 |
+
* Fix a JavaScript bug that caused the Stripe Checkout popup to be blocked on Chrome for iOS
|
41 |
+
|
42 |
+
= 2.6.3 - 2015.11.12 =
|
43 |
+
* Add metadata to subscription payments in stripe dashboard to indicate whether it is the initial or a recurring payment
|
44 |
+
|
45 |
+
= 2.6.2 - 2015.11.06 =
|
46 |
+
* Fix bug that would cause multiple subscriptions to not be supported under certain circumstances
|
47 |
+
|
48 |
+
= 2.6.1 - 2015.09.15 =
|
49 |
+
* Unset source if not set during pre-order release payments.
|
50 |
+
* Store customer ID if not logged in for pre-order payments.
|
51 |
+
|
52 |
+
= 2.6.0 - 2015.09.02 =
|
53 |
+
* Subscriptions 2.0 support.
|
54 |
+
|
55 |
+
= 2.5.4 - 2015.08.11 =
|
56 |
+
* Tweak - Terms and conditions error styling when required
|
57 |
+
* Tweak - Account password error styling when required
|
58 |
+
|
59 |
+
= 2.5.3 - 2015.7.28 =
|
60 |
+
* Added - Filter to prevent Stripe from sending its own receipts "wc_stripe_send_stripe_receipt"
|
61 |
+
|
62 |
+
= 2.5.2 - 2015.07.19 =
|
63 |
+
* Fix - Removed deprecated add_error function
|
64 |
+
* Tweak - Improve error message when Stripe checkout function is used
|
65 |
+
|
66 |
+
= 2.5.1 - 2015.07.01 =
|
67 |
+
* Fix - Only send receipt_email when set.
|
68 |
+
|
69 |
+
= 2.5.0 - 2015.05.11 =
|
70 |
+
* Update to API version 2015-04-07
|
71 |
+
* Feature - Support authorize on subscriptions first payment.
|
72 |
+
* Tweak - Option labels.
|
73 |
+
* Tweak - Safe remote GET.
|
74 |
+
* Tweak - SSLVerify true.
|
75 |
+
* Tweak - Update card icons.
|
76 |
+
* Tweak - Pass receipt email.
|
77 |
+
|
78 |
+
= 2.4.3 - 2015.05.11 =
|
79 |
+
* Fix - fixed validation issue when account creation is not checked
|
80 |
+
* Update - Stripe checkout JS API v2
|
81 |
+
|
82 |
+
= 2.4.2 - 2015.03.23 =
|
83 |
+
* Fix - Create account password field was not being validated
|
84 |
+
|
85 |
+
= 2.4.1 - 2015.03.20 =
|
86 |
+
* Fix - Undefined JS error due to deprecated ajax_loader_url
|
87 |
+
* Fix - When using Stripe checkout JS, some form required fields were not validating
|
88 |
+
|
89 |
+
= 2.4.0 - 2015.02.20 =
|
90 |
+
* Added support for bitcoin currency
|
91 |
+
|
92 |
+
= 2.3.0 - 2015.01.31 =
|
93 |
+
* Added 'wc_stripe_description' filter to allow filtering of payment description.
|
94 |
+
* Added order_review handling for stripe checkout.
|
95 |
+
* Mark order as failed is Stripe API call fails
|
96 |
+
* Allow valid HTML in Stripe Description
|
97 |
+
* Fix settings link
|
98 |
+
* use get_order_currency() when generating payment args, rather than always using store currency.
|
99 |
+
* Fix fees where not logged correctly when using authorized first capture later
|
100 |
+
* Retry payment if customer_id is invalid.
|
101 |
+
|
102 |
+
= 2.2.8 - 2014.11.21 =
|
103 |
+
* Save card/customer id for regular orders.
|
104 |
+
|
105 |
+
= 2.2.7 - 2014.11.20 =
|
106 |
+
* Fixed all instances where order IDs were used instead of user IDs.
|
107 |
+
* Update orignal order card/customer ids for renewals.
|
108 |
+
* Add reasons to refunds.
|
109 |
+
|
110 |
+
= 2.2.6 - 2014.11.18 =
|
111 |
+
* Stripe card ID should be taken from the order, not the user.
|
112 |
+
* Fix order_meta_query.
|
113 |
+
|
114 |
+
= 2.2.5 - 2014.11.06 =
|
115 |
+
* Round totals to 2 decimals so when we multiply by 100 we're sure we've got an integer.
|
116 |
+
|
117 |
+
= 2.2.4 - 2014.10.01 =
|
118 |
+
* Fix card display for subscriptions.
|
119 |
+
|
120 |
+
= 2.2.3 - 2014.10.01 =
|
121 |
+
* Fixed textdomain name
|
122 |
+
|
123 |
+
= 2.2.2 - 2014.09.23 =
|
124 |
+
* Set API version to 2014-09-08.
|
125 |
+
* Fixed card display (type->brand).
|
126 |
+
|
127 |
+
= 2.2.1 - 2014.09.15 =
|
128 |
+
* Fix strict standards warning.
|
129 |
+
|
130 |
+
= 2.2.0 - 2014.09.01 =
|
131 |
+
* Replaced woocommerce_get_template (deprecated) with wc_get_template.
|
132 |
+
* Tweak refund support.
|
133 |
+
* Support for pre-orders.
|
134 |
+
* Fixed typo.
|
135 |
+
|
136 |
+
= 2.1.0 - 2014.08.06 =
|
137 |
+
* Associate stripe customers with wp users.
|
138 |
+
* Refactored saved card code.
|
139 |
+
* Use Stripe API to get and delete saved cards.
|
140 |
+
* Updated subscriptions integration for saved cards.
|
141 |
+
* WC 2.2 - Store transaction ID.
|
142 |
+
* WC 2.2 - Refund support.
|
143 |
+
|
144 |
+
= 2.0.4 - 2014.07.31 =
|
145 |
+
* Tweaked the stripe checkout submission method.
|
146 |
+
|
147 |
+
= 2.0.3 - 2014.07.25 =
|
148 |
+
* wc_stripe_manage_saved_cards_url filter.
|
149 |
+
* Zero decimal currency handling.
|
150 |
+
* Only open stripe model when required fields are completed.
|
151 |
+
|
152 |
+
= 2.0.2 - 2014.06.06 =
|
153 |
+
* Fix use of saved cards on subscriptions.
|
154 |
+
|
155 |
+
= 2.0.1 - 2014.05.29 =
|
156 |
+
* Fix ajax loading gif.
|
157 |
+
* Fix notices.
|
158 |
+
* Fix stray comma in stripe.js.
|
159 |
+
* Prompt user to accept terms before showing stripe checkout modal.
|
160 |
+
|
161 |
+
= 2.0.0 - 2014.05.21 =
|
162 |
+
* Added the WC credit_card_form - this extension now requires WC 2.1+
|
163 |
+
* Option to disable saved cards
|
164 |
+
* Refactored code base
|
165 |
+
* Fix jquery notices
|
166 |
+
* Fix settings page links
|
167 |
+
* woocommerce_stripe_request_body filter
|
168 |
+
* Store fees for subscriptions
|
169 |
+
|
170 |
+
= 1.8.6 - 2014.05.20 =
|
171 |
+
* correct SSl message
|
172 |
+
* decode get_bloginfo( 'name' ) for plain text display
|
173 |
+
|
174 |
+
= 1.8.5 - 2014.05.10 =
|
175 |
+
* Updated textdomains
|
176 |
+
* date_i18n
|
177 |
+
* Improve stripe checkout flow - pop up on the checkout button click
|
178 |
+
|
179 |
+
= 1.8.4 - 2014.04.01 =
|
180 |
+
* Fix updating credit card used for future subscription payments when paying for a failed subscription renewal order with a new credit card.
|
181 |
+
|
182 |
+
= 1.8.3 - 2014.02.13 =
|
183 |
+
* Fix fatal error for subscription payments of deleted products.
|
184 |
+
|
185 |
+
= 1.8.2 - 2014.02.06 =
|
186 |
+
* Fix notice on card delete
|
187 |
+
|
188 |
+
= 1.8.1 - 2014.01.28 =
|
189 |
+
* set default for $checked
|
190 |
+
|
191 |
+
= 1.8.0 - 2014.01.08 =
|
192 |
+
* Checked compatibility with 2013-12-03 API
|
193 |
+
* 2.1 compatibility
|
194 |
+
* Pre-filled email address when using stripe checkout
|
195 |
+
|
196 |
+
= 1.7.6 - 2013.12.02 =
|
197 |
+
* Fix card display
|
198 |
+
|
199 |
+
= 1.7.5 - 2013.11.27 =
|
200 |
+
* Show payment method for subscriptions on account page
|
201 |
+
|
202 |
+
= 1.7.4 - 2013.11.20 =
|
203 |
+
* Expand/close when using saved cards.
|
204 |
+
* Use balance_transaction to get and store fees
|
205 |
+
|
206 |
+
= 1.7.3 - 2013.11.01 =
|
207 |
+
* Default to saved card
|
208 |
+
|
209 |
+
= 1.7.2 - 2013.11.01 =
|
210 |
+
* Added missing global in update_failing_payment_method
|
211 |
+
|
212 |
+
= 1.7.1 - 2013.09.28 =
|
213 |
+
* Remove non-existant (yet) function
|
214 |
+
|
215 |
+
= 1.7.0 - 2013.09.25 =
|
216 |
+
* Different credit card image for US than for other countries + a filter.
|
217 |
+
* Support for upcoming version of subscriptions.
|
218 |
+
* Add new woocommerce_stripe_month_display filter
|
219 |
+
|
220 |
+
= 1.6.0 - 2013.09.02 =
|
221 |
+
* Option to define a Stripe Checkout Image
|
222 |
+
* Removed currency check due to beta rollout
|
223 |
+
|
224 |
+
= 1.5.14 - 2013.08.12 =
|
225 |
+
* New cards format for subscriptions class.
|
226 |
+
|
227 |
+
= 1.5.13 - 2013.07.24 =
|
228 |
+
* Updated customer response object handler to work with new cards format.
|
229 |
+
* Fixed delete card button
|
230 |
+
|
231 |
+
= 1.5.12 - 2013.07.24 =
|
232 |
+
* EUR support for Stripe Beta
|
233 |
+
|
234 |
+
= 1.5.11 - 2013.07.17 =
|
235 |
+
* Workaround for stripe error messages.
|
236 |
+
|
237 |
+
= 1.5.10 - 2013.06.28 =
|
238 |
+
* Store charge ID, fee in meta
|
239 |
+
|
240 |
+
= 1.5.9 - 2013.06.28 =
|
241 |
+
* Capture true default
|
242 |
+
|
243 |
+
= 1.5.8 - 2013.06.18 =
|
244 |
+
* Add currency to stripe checkout js
|
245 |
+
* Authorize-only mode. Captures payment when order is made processing.
|
246 |
+
|
247 |
+
= 1.5.7 - 2013.06.15 =
|
248 |
+
* Added 'capture' option should you wish to authorize only. Authorized orders are on-hold. Processed orders capture the charge automatically.
|
249 |
+
|
250 |
+
= 1.5.6 - 2013.06.03 =
|
251 |
+
* added data-currency to stripe-checkout
|
252 |
+
|
253 |
+
= 1.5.5 - 2013.04.26 =
|
254 |
+
* Allow card re-entry in stripe checkout after errors.
|
255 |
+
|
256 |
+
= 1.5.4 - 2013.04.19 =
|
257 |
+
* GBP fix
|
258 |
+
|
259 |
+
= 1.5.3 - 2013.04.15 =
|
260 |
+
* Support GBP currency code (For UK Beta)
|
261 |
+
|
262 |
+
= 1.5.2 - 2013.04.09 =
|
263 |
+
* Send billing city to stripe
|
264 |
+
|
265 |
+
= 1.5.1 - 2013.01.24 =
|
266 |
+
* Add support for changing a subscription's recurring amount
|
267 |
+
|
268 |
+
= 1.5.0 - 2013.01.18 =
|
269 |
+
* Supports Stripe Checkout https://stripe.com/docs/checkout
|
270 |
+
|
271 |
+
= 1.4.0 - 2013.01.18 =
|
272 |
+
* WC 2.0 Compat
|
273 |
+
|
274 |
+
= 1.3.5 - 2012.12.05 =
|
275 |
+
* Pass address fields to stripe.js on pay page.
|
276 |
+
|
277 |
+
= 1.3.4 - 2012.12.05 =
|
278 |
+
* Updater
|
279 |
+
|
280 |
+
= 1.3.3 - 2012.10.22 =
|
281 |
+
* Fix CAD check
|
282 |
+
|
283 |
+
= 1.3.2 - 2012.10.15 =
|
284 |
+
* Fixed bug causing settings to not show when using CAD
|
285 |
+
|
286 |
+
= 1.3.1 - 2012.10.11 =
|
287 |
+
* Add support for changing subscription next payment date
|
288 |
+
* Remove order meta from subscription renewal orders
|
289 |
+
|
290 |
+
= 1.3 - 2012.09.20 =
|
291 |
+
* Allowed canadian dollars - Stripe is beta testing support for Canada
|
292 |
+
|
293 |
+
= 1.2.1 - 2012.09.11 =
|
294 |
+
* Fix text mode SSL logic
|
295 |
+
|
296 |
+
= 1.2 - 2012.09.01 =
|
297 |
+
* SSL not required in TEST MODE
|
298 |
+
* Saved cards - store customer tokens and let users pay again using the same card
|
299 |
+
* Subscriptions use a single customer, rather than per-order
|
300 |
+
* Only load JS on checkout
|
301 |
+
|
302 |
+
= 1.1 - 2012.06.19 =
|
303 |
+
* Update woo updater
|
304 |
+
* Class name update
|
305 |
+
* Stripe JS for added security - you will need to re-enter keys and ensure you are using WooCommerce 1.5.8
|
306 |
+
* Subscriptions support (requires WC Subscriptions addon)
|
307 |
+
|
308 |
+
= 1.0 - 2011.12.08 =
|
309 |
+
* First Release
|
includes/class-wc-gateway-stripe-addons.php
ADDED
@@ -0,0 +1,411 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit;
|
4 |
+
}
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WC_Gateway_Stripe_Addons class.
|
8 |
+
*
|
9 |
+
* @extends WC_Gateway_Stripe
|
10 |
+
*/
|
11 |
+
class WC_Gateway_Stripe_Addons extends WC_Gateway_Stripe {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Constructor
|
15 |
+
*/
|
16 |
+
public function __construct() {
|
17 |
+
parent::__construct();
|
18 |
+
|
19 |
+
if ( class_exists( 'WC_Subscriptions_Order' ) ) {
|
20 |
+
add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, array( $this, 'scheduled_subscription_payment' ), 10, 2 );
|
21 |
+
add_action( 'wcs_resubscribe_order_created', array( $this, 'delete_resubscribe_meta' ), 10 );
|
22 |
+
add_action( 'wcs_renewal_order_created', array( $this, 'delete_renewal_meta' ), 10 );
|
23 |
+
add_action( 'woocommerce_subscription_failing_payment_method_updated_stripe', array( $this, 'update_failing_payment_method' ), 10, 2 );
|
24 |
+
|
25 |
+
// display the credit card used for a subscription in the "My Subscriptions" table
|
26 |
+
add_filter( 'woocommerce_my_subscriptions_payment_method', array( $this, 'maybe_render_subscription_payment_method' ), 10, 2 );
|
27 |
+
|
28 |
+
// allow store managers to manually set Stripe as the payment method on a subscription
|
29 |
+
add_filter( 'woocommerce_subscription_payment_meta', array( $this, 'add_subscription_payment_meta' ), 10, 2 );
|
30 |
+
add_filter( 'woocommerce_subscription_validate_payment_meta', array( $this, 'validate_subscription_payment_meta' ), 10, 2 );
|
31 |
+
}
|
32 |
+
|
33 |
+
if ( class_exists( 'WC_Pre_Orders_Order' ) ) {
|
34 |
+
add_action( 'wc_pre_orders_process_pre_order_completion_payment_' . $this->id, array( $this, 'process_pre_order_release_payment' ) );
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Is $order_id a subscription?
|
40 |
+
* @param int $order_id
|
41 |
+
* @return boolean
|
42 |
+
*/
|
43 |
+
protected function is_subscription( $order_id ) {
|
44 |
+
return ( function_exists( 'wcs_order_contains_subscription' ) && ( wcs_order_contains_subscription( $order_id ) || wcs_is_subscription( $order_id ) || wcs_order_contains_renewal( $order_id ) ) );
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Is $order_id a pre-order?
|
49 |
+
* @param int $order_id
|
50 |
+
* @return boolean
|
51 |
+
*/
|
52 |
+
protected function is_pre_order( $order_id ) {
|
53 |
+
return ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Order::order_contains_pre_order( $order_id ) );
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Process the payment based on type.
|
58 |
+
* @param int $order_id
|
59 |
+
* @return array
|
60 |
+
*/
|
61 |
+
public function process_payment( $order_id, $retry = true, $force_customer = false ) {
|
62 |
+
if ( $this->is_subscription( $order_id ) ) {
|
63 |
+
// Regular payment with force customer enabled
|
64 |
+
return parent::process_payment( $order_id, true, true );
|
65 |
+
|
66 |
+
} elseif ( $this->is_pre_order( $order_id ) ) {
|
67 |
+
return $this->process_pre_order( $order_id, $retry, $force_customer );
|
68 |
+
|
69 |
+
} else {
|
70 |
+
return parent::process_payment( $order_id, $retry, $force_customer );
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Updates other subscription sources.
|
76 |
+
*/
|
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 ( wcs_order_contains_subscription( $order->id ) ) {
|
82 |
+
$subscriptions = wcs_get_subscriptions_for_order( $order->id );
|
83 |
+
} elseif ( 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 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* process_subscription_payment function.
|
97 |
+
* @param mixed $order
|
98 |
+
* @param int $amount (default: 0)
|
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 < 50 ) {
|
104 |
+
return new WP_Error( 'stripe_error', __( 'Sorry, the minimum allowed order total is 0.50 to use this payment method.', 'woocommerce-gateway-stripe' ) );
|
105 |
+
}
|
106 |
+
|
107 |
+
// Get source from order
|
108 |
+
$source = $this->get_order_source( $order );
|
109 |
+
|
110 |
+
// If no order source was defined, use user source instead.
|
111 |
+
if ( ! $source->customer ) {
|
112 |
+
$source = $this->get_source( $order->customer_user );
|
113 |
+
}
|
114 |
+
|
115 |
+
// Or fail :(
|
116 |
+
if ( ! $source->customer ) {
|
117 |
+
return new WP_Error( 'stripe_error', __( 'Customer not found', 'woocommerce-gateway-stripe' ) );
|
118 |
+
}
|
119 |
+
|
120 |
+
WC_Stripe::log( "Info: Begin processing subscriotion 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 |
+
|
131 |
+
// Process valid response
|
132 |
+
if ( ! is_wp_error( $response ) ) {
|
133 |
+
$this->process_response( $response, $order );
|
134 |
+
}
|
135 |
+
|
136 |
+
return $response;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Process the pre-order
|
141 |
+
* @param int $order_id
|
142 |
+
* @return array
|
143 |
+
*/
|
144 |
+
public function process_pre_order( $order_id, $retry, $force_customer ) {
|
145 |
+
if ( WC_Pre_Orders_Order::order_requires_payment_tokenization( $order_id ) ) {
|
146 |
+
try {
|
147 |
+
$order = wc_get_order( $order_id );
|
148 |
+
|
149 |
+
if ( $order->get_total() * 100 < 50 ) {
|
150 |
+
throw new Exception( __( 'Sorry, the minimum allowed order total is 0.50 to use this payment method.', 'woocommerce-gateway-stripe' ) );
|
151 |
+
}
|
152 |
+
|
153 |
+
$source = $this->get_source( get_current_user_id(), true );
|
154 |
+
|
155 |
+
// We need a source on file to continue.
|
156 |
+
if ( empty( $source->customer ) || empty( $source->source ) ) {
|
157 |
+
throw new Exception( __( 'Unable to store payment details. Please try again.', 'woocommerce-gateway-stripe' ) );
|
158 |
+
}
|
159 |
+
|
160 |
+
// Store source to order meta
|
161 |
+
$this->save_source( $order, $source );
|
162 |
+
|
163 |
+
// Reduce stock levels
|
164 |
+
$order->reduce_order_stock();
|
165 |
+
|
166 |
+
// Remove cart
|
167 |
+
WC()->cart->empty_cart();
|
168 |
+
|
169 |
+
// Is pre ordered!
|
170 |
+
WC_Pre_Orders_Order::mark_order_as_pre_ordered( $order );
|
171 |
+
|
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' );
|
179 |
+
return;
|
180 |
+
}
|
181 |
+
} else {
|
182 |
+
return parent::process_payment( $order_id, $retry, $force_customer );
|
183 |
+
}
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Process a pre-order payment when the pre-order is released
|
188 |
+
* @param WC_Order $order
|
189 |
+
* @return void
|
190 |
+
*/
|
191 |
+
public function process_pre_order_release_payment( $order ) {
|
192 |
+
try {
|
193 |
+
// Define some callbacks if the first attempt fails.
|
194 |
+
$retry_callbacks = array(
|
195 |
+
'remove_order_source_before_retry',
|
196 |
+
'remove_order_customer_before_retry',
|
197 |
+
);
|
198 |
+
|
199 |
+
while ( 1 ) {
|
200 |
+
$source = $this->get_order_source( $order );
|
201 |
+
$response = WC_Stripe_API::request( $this->generate_payment_request( $order, $source ) );
|
202 |
+
|
203 |
+
if ( is_wp_error( $response ) ) {
|
204 |
+
if ( 0 === sizeof( $retry_callbacks ) ) {
|
205 |
+
throw new Exception( $response->get_error_message() );
|
206 |
+
} else {
|
207 |
+
$retry_callback = array_shift( $retry_callbacks );
|
208 |
+
call_user_func( array( $this, $retry_callback ), $order );
|
209 |
+
}
|
210 |
+
} else {
|
211 |
+
// Successful
|
212 |
+
$this->process_response( $response, $order );
|
213 |
+
break;
|
214 |
+
}
|
215 |
+
}
|
216 |
+
|
217 |
+
} catch ( Exception $e ) {
|
218 |
+
$order_note = sprintf( __( 'Stripe Transaction Failed (%s)', 'woocommerce-gateway-stripe' ), $e->getMessage() );
|
219 |
+
|
220 |
+
// Mark order as failed if not already set,
|
221 |
+
// otherwise, make sure we add the order note so we can detect when someone fails to check out multiple times
|
222 |
+
if ( ! $order->has_status( 'failed' ) ) {
|
223 |
+
$order->update_status( 'failed', $order_note );
|
224 |
+
} else {
|
225 |
+
$order->add_order_note( $order_note );
|
226 |
+
}
|
227 |
+
}
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Don't transfer Stripe customer/token meta to resubscribe orders.
|
232 |
+
* @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
|
233 |
+
*/
|
234 |
+
public function delete_resubscribe_meta( $resubscribe_order ) {
|
235 |
+
delete_post_meta( $resubscribe_order->id, '_stripe_customer_id' );
|
236 |
+
delete_post_meta( $resubscribe_order->id, '_stripe_card_id' );
|
237 |
+
$this->delete_renewal_meta( $resubscribe_order );
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Don't transfer Stripe fee/ID meta to renewal orders.
|
242 |
+
* @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
|
243 |
+
*/
|
244 |
+
public function delete_renewal_meta( $renewal_order ) {
|
245 |
+
delete_post_meta( $renewal_order->id, 'Stripe Fee' );
|
246 |
+
delete_post_meta( $renewal_order->id, 'Net Revenue From Stripe' );
|
247 |
+
delete_post_meta( $renewal_order->id, 'Stripe Payment ID' );
|
248 |
+
return $renewal_order;
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* scheduled_subscription_payment function.
|
253 |
+
*
|
254 |
+
* @param $amount_to_charge float The amount to charge.
|
255 |
+
* @param $renewal_order WC_Order A WC_Order object created to record the renewal payment.
|
256 |
+
*/
|
257 |
+
public function scheduled_subscription_payment( $amount_to_charge, $renewal_order ) {
|
258 |
+
// Define some callbacks if the first attempt fails.
|
259 |
+
$retry_callbacks = array(
|
260 |
+
'remove_order_source_before_retry',
|
261 |
+
'remove_order_customer_before_retry',
|
262 |
+
);
|
263 |
+
|
264 |
+
while ( 1 ) {
|
265 |
+
$response = $this->process_subscription_payment( $renewal_order, $amount_to_charge );
|
266 |
+
|
267 |
+
if ( is_wp_error( $response ) ) {
|
268 |
+
if ( 0 === sizeof( $retry_callbacks ) ) {
|
269 |
+
$renewal_order->update_status( 'failed', sprintf( __( 'Stripe Transaction Failed (%s)', 'woocommerce-gateway-stripe' ), $response->get_error_message() ) );
|
270 |
+
break;
|
271 |
+
} else {
|
272 |
+
$retry_callback = array_shift( $retry_callbacks );
|
273 |
+
call_user_func( array( $this, $retry_callback ), $renewal_order );
|
274 |
+
}
|
275 |
+
} else {
|
276 |
+
// Successful
|
277 |
+
break;
|
278 |
+
}
|
279 |
+
}
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Remove order meta
|
284 |
+
* @param object $order
|
285 |
+
*/
|
286 |
+
public function remove_order_source_before_retry( $order ) {
|
287 |
+
delete_post_meta( $order->id, '_stripe_card_id' );
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Remove order meta
|
292 |
+
* @param object $order
|
293 |
+
*/
|
294 |
+
public function remove_order_customer_before_retry( $order ) {
|
295 |
+
delete_post_meta( $order->id, '_stripe_customer_id' );
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Update the customer_id for a subscription after using Stripe to complete a payment to make up for
|
300 |
+
* an automatic renewal payment which previously failed.
|
301 |
+
*
|
302 |
+
* @access public
|
303 |
+
* @param WC_Subscription $subscription The subscription for which the failing payment method relates.
|
304 |
+
* @param WC_Order $renewal_order The order which recorded the successful payment (to make up for the failed automatic payment).
|
305 |
+
* @return void
|
306 |
+
*/
|
307 |
+
public function update_failing_payment_method( $subscription, $renewal_order ) {
|
308 |
+
update_post_meta( $subscription->id, '_stripe_customer_id', $renewal_order->stripe_customer_id );
|
309 |
+
update_post_meta( $subscription->id, '_stripe_card_id', $renewal_order->stripe_card_id );
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* Include the payment meta data required to process automatic recurring payments so that store managers can
|
314 |
+
* manually set up automatic recurring payments for a customer via the Edit Subscriptions screen in 2.0+.
|
315 |
+
*
|
316 |
+
* @since 2.5
|
317 |
+
* @param array $payment_meta associative array of meta data required for automatic payments
|
318 |
+
* @param WC_Subscription $subscription An instance of a subscription object
|
319 |
+
* @return array
|
320 |
+
*/
|
321 |
+
public function add_subscription_payment_meta( $payment_meta, $subscription ) {
|
322 |
+
$payment_meta[ $this->id ] = array(
|
323 |
+
'post_meta' => array(
|
324 |
+
'_stripe_customer_id' => array(
|
325 |
+
'value' => get_post_meta( $subscription->id, '_stripe_customer_id', true ),
|
326 |
+
'label' => 'Stripe Customer ID',
|
327 |
+
),
|
328 |
+
'_stripe_card_id' => array(
|
329 |
+
'value' => get_post_meta( $subscription->id, '_stripe_card_id', true ),
|
330 |
+
'label' => 'Stripe Card ID',
|
331 |
+
),
|
332 |
+
),
|
333 |
+
);
|
334 |
+
return $payment_meta;
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Validate the payment meta data required to process automatic recurring payments so that store managers can
|
339 |
+
* manually set up automatic recurring payments for a customer via the Edit Subscriptions screen in 2.0+.
|
340 |
+
*
|
341 |
+
* @since 2.5
|
342 |
+
* @param string $payment_method_id The ID of the payment method to validate
|
343 |
+
* @param array $payment_meta associative array of meta data required for automatic payments
|
344 |
+
* @return array
|
345 |
+
*/
|
346 |
+
public function validate_subscription_payment_meta( $payment_method_id, $payment_meta ) {
|
347 |
+
if ( $this->id === $payment_method_id ) {
|
348 |
+
|
349 |
+
if ( ! isset( $payment_meta['post_meta']['_stripe_customer_id']['value'] ) || empty( $payment_meta['post_meta']['_stripe_customer_id']['value'] ) ) {
|
350 |
+
throw new Exception( 'A "_stripe_customer_id" value is required.' );
|
351 |
+
} elseif ( 0 !== strpos( $payment_meta['post_meta']['_stripe_customer_id']['value'], 'cus_' ) ) {
|
352 |
+
throw new Exception( 'Invalid customer ID. A valid "_stripe_customer_id" must begin with "cus_".' );
|
353 |
+
}
|
354 |
+
|
355 |
+
if ( ! empty( $payment_meta['post_meta']['_stripe_card_id']['value'] ) && 0 !== strpos( $payment_meta['post_meta']['_stripe_card_id']['value'], 'card_' ) ) {
|
356 |
+
throw new Exception( 'Invalid card ID. A valid "_stripe_card_id" must begin with "card_".' );
|
357 |
+
}
|
358 |
+
}
|
359 |
+
}
|
360 |
+
|
361 |
+
/**
|
362 |
+
* Render the payment method used for a subscription in the "My Subscriptions" table
|
363 |
+
*
|
364 |
+
* @since 1.7.5
|
365 |
+
* @param string $payment_method_to_display the default payment method text to display
|
366 |
+
* @param WC_Subscription $subscription the subscription details
|
367 |
+
* @return string the subscription payment method
|
368 |
+
*/
|
369 |
+
public function maybe_render_subscription_payment_method( $payment_method_to_display, $subscription ) {
|
370 |
+
// bail for other payment methods
|
371 |
+
if ( $this->id !== $subscription->payment_method || ! $subscription->customer_user ) {
|
372 |
+
return $payment_method_to_display;
|
373 |
+
}
|
374 |
+
|
375 |
+
$stripe_customer = new WC_Stripe_Customer();
|
376 |
+
$stripe_customer_id = get_post_meta( $subscription->id, '_stripe_customer_id', true );
|
377 |
+
$stripe_card_id = get_post_meta( $subscription->id, '_stripe_card_id', true );
|
378 |
+
|
379 |
+
// If we couldn't find a Stripe customer linked to the subscription, fallback to the user meta data.
|
380 |
+
if ( ! $stripe_customer_id || ! is_string( $stripe_customer_id ) ) {
|
381 |
+
$user_id = $subscription->customer_user;
|
382 |
+
$stripe_customer_id = get_user_meta( $user_id, '_stripe_customer_id', true );
|
383 |
+
$stripe_card_id = get_user_meta( $user_id, '_stripe_card_id', true );
|
384 |
+
}
|
385 |
+
|
386 |
+
// If we couldn't find a Stripe customer linked to the account, fallback to the order meta data.
|
387 |
+
if ( ( ! $stripe_customer_id || ! is_string( $stripe_customer_id ) ) && false !== $subscription->order ) {
|
388 |
+
$stripe_customer_id = get_post_meta( $subscription->order->id, '_stripe_customer_id', true );
|
389 |
+
$stripe_card_id = get_post_meta( $subscription->order->id, '_stripe_card_id', true );
|
390 |
+
}
|
391 |
+
|
392 |
+
$stripe_customer->set_id( $stripe_customer_id );
|
393 |
+
$cards = $stripe_customer->get_cards();
|
394 |
+
|
395 |
+
if ( $cards ) {
|
396 |
+
$found_card = false;
|
397 |
+
foreach ( $cards as $card ) {
|
398 |
+
if ( $card->id === $stripe_card_id ) {
|
399 |
+
$found_card = true;
|
400 |
+
$payment_method_to_display = sprintf( __( 'Via %s card ending in %s', 'woocommerce-gateway-stripe' ), ( isset( $card->type ) ? $card->type : $card->brand ), $card->last4 );
|
401 |
+
break;
|
402 |
+
}
|
403 |
+
}
|
404 |
+
if ( ! $found_card ) {
|
405 |
+
$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 );
|
406 |
+
}
|
407 |
+
}
|
408 |
+
|
409 |
+
return $payment_method_to_display;
|
410 |
+
}
|
411 |
+
}
|
includes/class-wc-gateway-stripe.php
ADDED
@@ -0,0 +1,570 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit;
|
4 |
+
}
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WC_Gateway_Stripe class.
|
8 |
+
*
|
9 |
+
* @extends WC_Payment_Gateway
|
10 |
+
*/
|
11 |
+
class WC_Gateway_Stripe extends WC_Payment_Gateway_CC {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Constructor
|
15 |
+
*/
|
16 |
+
public function __construct() {
|
17 |
+
$this->id = 'stripe';
|
18 |
+
$this->method_title = __( 'Stripe', 'woocommerce-gateway-stripe' );
|
19 |
+
$this->method_description = __( 'Stripe works by adding credit card fields on the checkout and then sending the details to Stripe for verification.', 'woocommerce-gateway-stripe' );
|
20 |
+
$this->has_fields = true;
|
21 |
+
$this->view_transaction_url = 'https://dashboard.stripe.com/payments/%s';
|
22 |
+
$this->supports = array(
|
23 |
+
'subscriptions',
|
24 |
+
'products',
|
25 |
+
'refunds',
|
26 |
+
'subscription_cancellation',
|
27 |
+
'subscription_reactivation',
|
28 |
+
'subscription_suspension',
|
29 |
+
'subscription_amount_changes',
|
30 |
+
'subscription_payment_method_change', // Subs 1.n compatibility
|
31 |
+
'subscription_payment_method_change_customer',
|
32 |
+
'subscription_payment_method_change_admin',
|
33 |
+
'subscription_date_changes',
|
34 |
+
'multiple_subscriptions',
|
35 |
+
'pre-orders',
|
36 |
+
'tokenization',
|
37 |
+
);
|
38 |
+
|
39 |
+
// Load the form fields
|
40 |
+
$this->init_form_fields();
|
41 |
+
|
42 |
+
// Load the settings.
|
43 |
+
$this->init_settings();
|
44 |
+
|
45 |
+
// Get setting values.
|
46 |
+
$this->title = $this->get_option( 'title' );
|
47 |
+
$this->description = $this->get_option( 'description' );
|
48 |
+
$this->enabled = $this->get_option( 'enabled' );
|
49 |
+
$this->testmode = 'yes' === $this->get_option( 'testmode' );
|
50 |
+
$this->capture = 'yes' === $this->get_option( 'capture', 'yes' );
|
51 |
+
$this->stripe_checkout = 'yes' === $this->get_option( 'stripe_checkout' );
|
52 |
+
$this->stripe_checkout_locale = $this->get_option( 'stripe_checkout_locale' );
|
53 |
+
$this->stripe_checkout_image = $this->get_option( 'stripe_checkout_image', '' );
|
54 |
+
$this->saved_cards = 'yes' === $this->get_option( 'saved_cards' );
|
55 |
+
$this->secret_key = $this->testmode ? $this->get_option( 'test_secret_key' ) : $this->get_option( 'secret_key' );
|
56 |
+
$this->publishable_key = $this->testmode ? $this->get_option( 'test_publishable_key' ) : $this->get_option( 'publishable_key' );
|
57 |
+
$this->bitcoin = 'USD' === strtoupper( get_woocommerce_currency() ) && 'yes' === $this->get_option( 'stripe_bitcoin' );
|
58 |
+
$this->logging = 'yes' === $this->get_option( 'logging' );
|
59 |
+
|
60 |
+
if ( $this->stripe_checkout ) {
|
61 |
+
$this->order_button_text = __( 'Continue to payment', 'woocommerce-gateway-stripe' );
|
62 |
+
}
|
63 |
+
|
64 |
+
if ( $this->testmode ) {
|
65 |
+
$this->description .= ' ' . sprintf( __( 'TEST MODE ENABLED. In test mode, you can use the card number 4242424242424242 with any CVC and a valid expiration date or check the documentation "<a href="%s">Testing Stripe</a>" for more card numbers.', 'woocommerce-gateway-stripe' ), 'https://stripe.com/docs/testing' );
|
66 |
+
$this->description = trim( $this->description );
|
67 |
+
}
|
68 |
+
|
69 |
+
WC_Stripe_API::set_secret_key( $this->secret_key );
|
70 |
+
|
71 |
+
// Hooks
|
72 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
|
73 |
+
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
74 |
+
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* get_icon function.
|
79 |
+
*
|
80 |
+
* @access public
|
81 |
+
* @return string
|
82 |
+
*/
|
83 |
+
public function get_icon() {
|
84 |
+
$ext = version_compare( WC()->version, '2.6', '>=' ) ? '.svg' : '.png';
|
85 |
+
$style = version_compare( WC()->version, '2.6', '>=' ) ? 'style="margin-left: 0.3em"' : '';
|
86 |
+
|
87 |
+
$icon = '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/visa' . $ext ) . '" alt="Visa" width="32" ' . $style . ' />';
|
88 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/mastercard' . $ext ) . '" alt="Mastercard" width="32" ' . $style . ' />';
|
89 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/amex' . $ext ) . '" alt="Amex" width="32" ' . $style . ' />';
|
90 |
+
|
91 |
+
if ( 'USD' === get_woocommerce_currency() ) {
|
92 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/discover' . $ext ) . '" alt="Discover" width="32" ' . $style . ' />';
|
93 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/jcb' . $ext ) . '" alt="JCB" width="32" ' . $style . ' />';
|
94 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/diners' . $ext ) . '" alt="Diners" width="32" ' . $style . ' />';
|
95 |
+
}
|
96 |
+
|
97 |
+
if ( $this->bitcoin ) {
|
98 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( plugins_url( '/assets/images/bitcoin' . $ext, WC_STRIPE_MAIN_FILE ) ) . '" alt="Bitcoin" width="32" ' . $style . ' />';
|
99 |
+
}
|
100 |
+
|
101 |
+
return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Get Stripe amount to pay
|
106 |
+
* @return float
|
107 |
+
*/
|
108 |
+
public function get_stripe_amount( $total, $currency = '' ) {
|
109 |
+
if ( ! $currency ) {
|
110 |
+
$currency = get_woocommerce_currency();
|
111 |
+
}
|
112 |
+
switch ( strtoupper( $currency ) ) {
|
113 |
+
// Zero decimal currencies
|
114 |
+
case 'BIF' :
|
115 |
+
case 'CLP' :
|
116 |
+
case 'DJF' :
|
117 |
+
case 'GNF' :
|
118 |
+
case 'JPY' :
|
119 |
+
case 'KMF' :
|
120 |
+
case 'KRW' :
|
121 |
+
case 'MGA' :
|
122 |
+
case 'PYG' :
|
123 |
+
case 'RWF' :
|
124 |
+
case 'VND' :
|
125 |
+
case 'VUV' :
|
126 |
+
case 'XAF' :
|
127 |
+
case 'XOF' :
|
128 |
+
case 'XPF' :
|
129 |
+
$total = absint( $total );
|
130 |
+
break;
|
131 |
+
default :
|
132 |
+
$total = round( $total, 2 ) * 100; // In cents
|
133 |
+
break;
|
134 |
+
}
|
135 |
+
return $total;
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Check if SSL is enabled and notify the user
|
140 |
+
*/
|
141 |
+
public function admin_notices() {
|
142 |
+
if ( 'no' === $this->enabled ) {
|
143 |
+
return;
|
144 |
+
}
|
145 |
+
|
146 |
+
// Show message if enabled and FORCE SSL is disabled and WordpressHTTPS plugin is not detected
|
147 |
+
if ( ( function_exists( 'wc_site_is_https' ) && ! wc_site_is_https() ) && ( 'no' === get_option( 'woocommerce_force_ssl_checkout' ) && ! class_exists( 'WordPressHTTPS' ) ) ) {
|
148 |
+
echo '<div class="error"><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>';
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Check if this gateway is enabled
|
154 |
+
*/
|
155 |
+
public function is_available() {
|
156 |
+
if ( 'yes' === $this->enabled ) {
|
157 |
+
if ( ! $this->testmode && is_checkout() && ! is_ssl() ) {
|
158 |
+
return false;
|
159 |
+
}
|
160 |
+
if ( ! $this->secret_key || ! $this->publishable_key ) {
|
161 |
+
return false;
|
162 |
+
}
|
163 |
+
return true;
|
164 |
+
}
|
165 |
+
return false;
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Initialise Gateway Settings Form Fields
|
170 |
+
*/
|
171 |
+
public function init_form_fields() {
|
172 |
+
$this->form_fields = include( 'settings-stripe.php' );
|
173 |
+
|
174 |
+
wc_enqueue_js( "
|
175 |
+
jQuery( function( $ ) {
|
176 |
+
$( '#woocommerce_stripe_stripe_checkout' ).change(function(){
|
177 |
+
if ( $( this ).is( ':checked' ) ) {
|
178 |
+
$( '#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image' ).closest( 'tr' ).show();
|
179 |
+
} else {
|
180 |
+
$( '#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image' ).closest( 'tr' ).hide();
|
181 |
+
}
|
182 |
+
}).change();
|
183 |
+
});
|
184 |
+
" );
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Payment form on checkout page
|
189 |
+
*/
|
190 |
+
public function payment_fields() {
|
191 |
+
$user = wp_get_current_user();
|
192 |
+
$display_tokenization = $this->supports( 'tokenization' ) && is_checkout() && $this->saved_cards && $user->ID;
|
193 |
+
|
194 |
+
if ( $user->ID ) {
|
195 |
+
$user_email = get_user_meta( $user->ID, 'billing_email', true );
|
196 |
+
$user_email = $user_email ? $user_email : $user->user_email;
|
197 |
+
} else {
|
198 |
+
$user_email = '';
|
199 |
+
}
|
200 |
+
|
201 |
+
if ( is_add_payment_method_page() ) {
|
202 |
+
$pay_button_text = __( 'Add Card', 'woocommerce-gateway-stripe' );
|
203 |
+
} else {
|
204 |
+
$pay_button_text = '';
|
205 |
+
}
|
206 |
+
|
207 |
+
echo '<div
|
208 |
+
id="stripe-payment-data"
|
209 |
+
data-panel-label="' . esc_attr( $pay_button_text ) . '"
|
210 |
+
data-description=""
|
211 |
+
data-email="' . esc_attr( $user_email ) . '"
|
212 |
+
data-amount="' . esc_attr( $this->get_stripe_amount( WC()->cart->total ) ) . '"
|
213 |
+
data-name="' . esc_attr( sprintf( __( '%s', 'woocommerce-gateway-stripe' ), get_bloginfo( 'name', 'display' ) ) ) . '"
|
214 |
+
data-currency="' . esc_attr( strtolower( get_woocommerce_currency() ) ) . '"
|
215 |
+
data-image="' . esc_attr( $this->stripe_checkout_image ) . '"
|
216 |
+
data-bitcoin="' . esc_attr( $this->bitcoin ? 'true' : 'false' ) . '"
|
217 |
+
data-locale="' . esc_attr( $this->stripe_checkout_locale ? $this->stripe_checkout_locale : 'en' ) . '">';
|
218 |
+
|
219 |
+
if ( $this->description ) {
|
220 |
+
echo apply_filters( 'wc_stripe_description', wpautop( wp_kses_post( $this->description ) ) );
|
221 |
+
}
|
222 |
+
|
223 |
+
if ( $display_tokenization ) {
|
224 |
+
$this->tokenization_script();
|
225 |
+
$this->saved_payment_methods();
|
226 |
+
}
|
227 |
+
|
228 |
+
if ( ! $this->stripe_checkout ) {
|
229 |
+
$this->form();
|
230 |
+
|
231 |
+
if ( $display_tokenization ) {
|
232 |
+
$this->save_payment_method_checkbox();
|
233 |
+
}
|
234 |
+
}
|
235 |
+
|
236 |
+
echo '</div>';
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* payment_scripts function.
|
241 |
+
*
|
242 |
+
* Outputs scripts used for stripe payment
|
243 |
+
*
|
244 |
+
* @access public
|
245 |
+
*/
|
246 |
+
public function payment_scripts() {
|
247 |
+
if ( $this->stripe_checkout ) {
|
248 |
+
wp_enqueue_script( 'stripe', 'https://checkout.stripe.com/v2/checkout.js', '', '2.0', true );
|
249 |
+
wp_enqueue_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe_checkout.js', WC_STRIPE_MAIN_FILE ), array( 'stripe' ), WC_STRIPE_VERSION, true );
|
250 |
+
} else {
|
251 |
+
wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
|
252 |
+
wp_enqueue_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe.js', WC_STRIPE_MAIN_FILE ), array( 'jquery-payment', 'stripe' ), WC_STRIPE_VERSION, true );
|
253 |
+
}
|
254 |
+
|
255 |
+
$stripe_params = array(
|
256 |
+
'key' => $this->publishable_key,
|
257 |
+
'i18n_terms' => __( 'Please accept the terms and conditions first', 'woocommerce-gateway-stripe' ),
|
258 |
+
'i18n_required_fields' => __( 'Please fill in required checkout fields first', 'woocommerce-gateway-stripe' ),
|
259 |
+
);
|
260 |
+
|
261 |
+
// If we're on the pay page we need to pass stripe.js the address of the order.
|
262 |
+
if ( is_checkout_pay_page() && isset( $_GET['order'] ) && isset( $_GET['order_id'] ) ) {
|
263 |
+
$order_key = urldecode( $_GET['order'] );
|
264 |
+
$order_id = absint( $_GET['order_id'] );
|
265 |
+
$order = wc_get_order( $order_id );
|
266 |
+
|
267 |
+
if ( $order->id === $order_id && $order->order_key === $order_key ) {
|
268 |
+
$stripe_params['billing_first_name'] = $order->billing_first_name;
|
269 |
+
$stripe_params['billing_last_name'] = $order->billing_last_name;
|
270 |
+
$stripe_params['billing_address_1'] = $order->billing_address_1;
|
271 |
+
$stripe_params['billing_address_2'] = $order->billing_address_2;
|
272 |
+
$stripe_params['billing_state'] = $order->billing_state;
|
273 |
+
$stripe_params['billing_city'] = $order->billing_city;
|
274 |
+
$stripe_params['billing_postcode'] = $order->billing_postcode;
|
275 |
+
$stripe_params['billing_country'] = $order->billing_country;
|
276 |
+
}
|
277 |
+
}
|
278 |
+
|
279 |
+
wp_localize_script( 'woocommerce_stripe', 'wc_stripe_params', apply_filters( 'wc_stripe_params', $stripe_params ) );
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Generate the request for the payment.
|
284 |
+
* @param WC_Order $order
|
285 |
+
* @param object $source
|
286 |
+
* @return array()
|
287 |
+
*/
|
288 |
+
protected function generate_payment_request( $order, $source ) {
|
289 |
+
$post_data = array();
|
290 |
+
$post_data['currency'] = strtolower( $order->get_order_currency() ? $order->get_order_currency() : get_woocommerce_currency() );
|
291 |
+
$post_data['amount'] = $this->get_stripe_amount( $order->get_total(), $post_data['currency'] );
|
292 |
+
$post_data['description'] = sprintf( __( '%s - Order %s', 'woocommerce-gateway-stripe' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), $order->get_order_number() );
|
293 |
+
$post_data['capture'] = $this->capture ? 'true' : 'false';
|
294 |
+
|
295 |
+
if ( ! empty( $order->billing_email ) && apply_filters( 'wc_stripe_send_stripe_receipt', false ) ) {
|
296 |
+
$post_data['receipt_email'] = $order->billing_email;
|
297 |
+
}
|
298 |
+
|
299 |
+
$post_data['expand[]'] = 'balance_transaction';
|
300 |
+
|
301 |
+
if ( $source->customer ) {
|
302 |
+
$post_data['customer'] = $source->customer;
|
303 |
+
}
|
304 |
+
|
305 |
+
if ( $source->source ) {
|
306 |
+
$post_data['source'] = $source->source;
|
307 |
+
}
|
308 |
+
|
309 |
+
return $post_data;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* Get payment source. This can be a new token or existing card.
|
314 |
+
* @param bool $force_customer Should we force customer creation?
|
315 |
+
* @return object
|
316 |
+
*/
|
317 |
+
protected function get_source( $user_id, $force_customer = false ) {
|
318 |
+
$stripe_customer = new WC_Stripe_Customer( $user_id );
|
319 |
+
$stripe_source = false;
|
320 |
+
$token_id = false;
|
321 |
+
|
322 |
+
// New CC info was entered and we have a new token to process
|
323 |
+
if ( isset( $_POST['stripe_token'] ) ) {
|
324 |
+
$stripe_token = wc_clean( $_POST['stripe_token'] );
|
325 |
+
$maybe_saved_card = ! isset( $_POST['wc-stripe-new-payment-method'] ) || ! empty( $_POST['wc-stripe-new-payment-method'] );
|
326 |
+
|
327 |
+
// This is true if the user wants to store the card to their account.
|
328 |
+
if ( ( $user_id && $this->saved_cards && $maybe_saved_card ) || $force_customer ) {
|
329 |
+
$stripe_source = $stripe_customer->add_card( $stripe_token );
|
330 |
+
|
331 |
+
if ( is_wp_error( $stripe_source ) ) {
|
332 |
+
throw new Exception( $stripe_source->get_error_message() );
|
333 |
+
}
|
334 |
+
|
335 |
+
} else {
|
336 |
+
// Not saving token, so don't define customer either.
|
337 |
+
$stripe_source = $stripe_token;
|
338 |
+
$stripe_customer = false;
|
339 |
+
}
|
340 |
+
}
|
341 |
+
|
342 |
+
// Use an existing token, and then process the payment
|
343 |
+
elseif ( isset( $_POST['wc-stripe-payment-token'] ) && 'new' !== $_POST['wc-stripe-payment-token'] ) {
|
344 |
+
$token_id = wc_clean( $_POST['wc-stripe-payment-token'] );
|
345 |
+
$token = WC_Payment_Tokens::get( $token_id );
|
346 |
+
|
347 |
+
if ( ! $token || $token->get_user_id() !== get_current_user_id() ) {
|
348 |
+
WC()->session->set( 'refresh_totals', true );
|
349 |
+
throw new Exception( __( 'Invalid payment method. Please input a new card number.', 'woocommerce-gateway-stripe' ) );
|
350 |
+
}
|
351 |
+
|
352 |
+
$stripe_source = $token->get_token();
|
353 |
+
}
|
354 |
+
|
355 |
+
return (object) array(
|
356 |
+
'token_id' => $token_id,
|
357 |
+
'customer' => $stripe_customer ? $stripe_customer->get_id() : false,
|
358 |
+
'source' => $stripe_source,
|
359 |
+
);
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Get payment source from an order. This could be used in the future for
|
364 |
+
* a subscription as an example, therefore using the current user ID would
|
365 |
+
* not work - the customer won't be logged in :)
|
366 |
+
*
|
367 |
+
* Not using 2.6 tokens for this part since we need a customer AND a card
|
368 |
+
* token, and not just one.
|
369 |
+
*
|
370 |
+
* @param object $order
|
371 |
+
* @return object
|
372 |
+
*/
|
373 |
+
protected function get_order_source( $order = null ) {
|
374 |
+
$stripe_customer = new WC_Stripe_Customer();
|
375 |
+
$stripe_source = false;
|
376 |
+
$token_id = false;
|
377 |
+
|
378 |
+
if ( $order ) {
|
379 |
+
if ( $meta_value = get_post_meta( $order->id, '_stripe_customer_id', true ) ) {
|
380 |
+
$stripe_customer->set_id( $meta_value );
|
381 |
+
}
|
382 |
+
if ( $meta_value = get_post_meta( $order->id, '_stripe_card_id', true ) ) {
|
383 |
+
$stripe_source = $meta_value;
|
384 |
+
}
|
385 |
+
}
|
386 |
+
|
387 |
+
return (object) array(
|
388 |
+
'token_id' => $token_id,
|
389 |
+
'customer' => $stripe_customer ? $stripe_customer->get_id() : false,
|
390 |
+
'source' => $stripe_source,
|
391 |
+
);
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* Process the payment
|
396 |
+
*/
|
397 |
+
public function process_payment( $order_id, $retry = true, $force_customer = false ) {
|
398 |
+
try {
|
399 |
+
$order = wc_get_order( $order_id );
|
400 |
+
$source = $this->get_source( get_current_user_id(), $force_customer );
|
401 |
+
|
402 |
+
if ( empty( $source->source ) && empty( $source->customer ) ) {
|
403 |
+
$error_msg = __( 'Please enter your card details to make a payment.', 'woocommerce-gateway-stripe' );
|
404 |
+
$error_msg .= ' ' . __( 'Developers: Please make sure that you are including jQuery and there are no JavaScript errors on the page.', 'woocommerce-gateway-stripe' );
|
405 |
+
throw new Exception( $error_msg );
|
406 |
+
}
|
407 |
+
|
408 |
+
// Store source to order meta
|
409 |
+
$this->save_source( $order, $source );
|
410 |
+
|
411 |
+
// Handle payment
|
412 |
+
if ( $order->get_total() > 0 ) {
|
413 |
+
|
414 |
+
if ( $order->get_total() * 100 < 50 ) {
|
415 |
+
throw new Exception( __( 'Sorry, the minimum allowed order total is 0.50 to use this payment method.', 'woocommerce-gateway-stripe' ) );
|
416 |
+
}
|
417 |
+
|
418 |
+
WC_Stripe::log( "Info: Begin processing payment for order $order_id for the amount of {$order->get_total()}" );
|
419 |
+
|
420 |
+
// Make the request
|
421 |
+
$response = WC_Stripe_API::request( $this->generate_payment_request( $order, $source ) );
|
422 |
+
|
423 |
+
if ( is_wp_error( $response ) ) {
|
424 |
+
// Customer param wrong? The user may have been deleted on stripe's end. Remove customer_id. Can be retried without.
|
425 |
+
if ( 'customer' === $response->get_error_code() && $retry ) {
|
426 |
+
delete_user_meta( get_current_user_id(), '_stripe_customer_id' );
|
427 |
+
return $this->process_payment( $order_id, false, $force_customer );
|
428 |
+
// Source param wrong? The CARD may have been deleted on stripe's end. Remove token and show message.
|
429 |
+
} elseif ( 'source' === $response->get_error_code() && $source->token_id ) {
|
430 |
+
$token = WC_Payment_Tokens::get( $source->token_id );
|
431 |
+
$token->delete();
|
432 |
+
throw new Exception( __( 'This card is no longer available and has been removed.', 'woocommerce-gateway-stripe' ) );
|
433 |
+
}
|
434 |
+
throw new Exception( $response->get_error_code() . ': ' . $response->get_error_message() );
|
435 |
+
}
|
436 |
+
|
437 |
+
// Process valid response
|
438 |
+
$this->process_response( $response, $order );
|
439 |
+
} else {
|
440 |
+
$order->payment_complete();
|
441 |
+
}
|
442 |
+
|
443 |
+
// Remove cart
|
444 |
+
WC()->cart->empty_cart();
|
445 |
+
|
446 |
+
// Return thank you page redirect
|
447 |
+
return array(
|
448 |
+
'result' => 'success',
|
449 |
+
'redirect' => $this->get_return_url( $order )
|
450 |
+
);
|
451 |
+
|
452 |
+
} catch ( Exception $e ) {
|
453 |
+
wc_add_notice( $e->getMessage(), 'error' );
|
454 |
+
WC()->session->set( 'refresh_totals', true );
|
455 |
+
WC_Stripe::log( sprintf( __( 'Error: %s', 'woocommerce-gateway-stripe' ), $e->getMessage() ) );
|
456 |
+
return;
|
457 |
+
}
|
458 |
+
}
|
459 |
+
|
460 |
+
/**
|
461 |
+
* Save source to order.
|
462 |
+
*/
|
463 |
+
protected function save_source( $order, $source ) {
|
464 |
+
// Store source in the order
|
465 |
+
if ( $source->customer ) {
|
466 |
+
update_post_meta( $order->id, '_stripe_customer_id', $source->customer );
|
467 |
+
}
|
468 |
+
if ( $source->source ) {
|
469 |
+
update_post_meta( $order->id, '_stripe_card_id', $source->source );
|
470 |
+
}
|
471 |
+
}
|
472 |
+
|
473 |
+
/**
|
474 |
+
* Store extra meta data for an order from a Stripe Response.
|
475 |
+
*/
|
476 |
+
public function process_response( $response, $order ) {
|
477 |
+
WC_Stripe::log( "Processing response: " . print_r( $response, true ) );
|
478 |
+
|
479 |
+
// Store charge data
|
480 |
+
update_post_meta( $order->id, '_stripe_charge_id', $response->id );
|
481 |
+
update_post_meta( $order->id, '_stripe_charge_captured', $response->captured ? 'yes' : 'no' );
|
482 |
+
|
483 |
+
// Store other data such as fees
|
484 |
+
if ( isset( $response->balance_transaction ) && isset( $response->balance_transaction->fee ) ) {
|
485 |
+
$fee = number_format( $response->balance_transaction->fee / 100, 2, '.', '' );
|
486 |
+
update_post_meta( $order->id, 'Stripe Fee', $fee );
|
487 |
+
update_post_meta( $order->id, 'Net Revenue From Stripe', $order->get_total() - $fee );
|
488 |
+
}
|
489 |
+
|
490 |
+
if ( $response->captured ) {
|
491 |
+
$order->payment_complete( $response->id );
|
492 |
+
WC_Stripe::log( "Successful charge: $response->id" );
|
493 |
+
} else {
|
494 |
+
add_post_meta( $order->id, '_transaction_id', $response->id, true );
|
495 |
+
|
496 |
+
if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
|
497 |
+
$order->reduce_order_stock();
|
498 |
+
}
|
499 |
+
|
500 |
+
$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 ) );
|
501 |
+
WC_Stripe::log( "Successful auth: $response->id" );
|
502 |
+
}
|
503 |
+
|
504 |
+
return $response;
|
505 |
+
}
|
506 |
+
|
507 |
+
/**
|
508 |
+
* Add payment method via account screen.
|
509 |
+
* We don't store the token locally, but to the Stripe API.
|
510 |
+
* @since 3.0.0
|
511 |
+
*/
|
512 |
+
public function add_payment_method() {
|
513 |
+
if ( empty( $_POST['stripe_token'] ) || ! is_user_logged_in() ) {
|
514 |
+
wc_add_notice( __( 'There was a problem adding the card.', 'woocommerce-gateway-stripe' ), 'error' );
|
515 |
+
return;
|
516 |
+
}
|
517 |
+
|
518 |
+
$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
|
519 |
+
$card = $stripe_customer->add_card( wc_clean( $_POST['stripe_token'] ) );
|
520 |
+
|
521 |
+
if ( is_wp_error( $card ) ) {
|
522 |
+
throw new Exception( $card->get_error_message() );
|
523 |
+
}
|
524 |
+
|
525 |
+
return array(
|
526 |
+
'result' => 'success',
|
527 |
+
'redirect' => wc_get_endpoint_url( 'payment-methods' ),
|
528 |
+
);
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Refund a charge
|
533 |
+
* @param int $order_id
|
534 |
+
* @param float $amount
|
535 |
+
* @return bool
|
536 |
+
*/
|
537 |
+
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
538 |
+
$order = wc_get_order( $order_id );
|
539 |
+
|
540 |
+
if ( ! $order || ! $order->get_transaction_id() ) {
|
541 |
+
return false;
|
542 |
+
}
|
543 |
+
|
544 |
+
$body = array();
|
545 |
+
|
546 |
+
if ( ! is_null( $amount ) ) {
|
547 |
+
$body['amount'] = $this->get_stripe_amount( $amount );
|
548 |
+
}
|
549 |
+
|
550 |
+
if ( $reason ) {
|
551 |
+
$body['metadata'] = array(
|
552 |
+
'reason' => $reason,
|
553 |
+
);
|
554 |
+
}
|
555 |
+
|
556 |
+
WC_Stripe::log( "Info: Beginning refund for order $order_id for the amount of {$amount}" );
|
557 |
+
|
558 |
+
$response = WC_Stripe_API::request( $body, 'charges/' . $order->get_transaction_id() . '/refunds' );
|
559 |
+
|
560 |
+
if ( is_wp_error( $response ) ) {
|
561 |
+
WC_Stripe::log( "Error: " . $response->get_error_message() );
|
562 |
+
return $response;
|
563 |
+
} elseif ( ! empty( $response->id ) ) {
|
564 |
+
$refund_message = sprintf( __( 'Refunded %s - Refund ID: %s - Reason: %s', 'woocommerce-gateway-stripe' ), wc_price( $response->amount / 100 ), $response->id, $reason );
|
565 |
+
$order->add_order_note( $refund_message );
|
566 |
+
WC_Stripe::log( "Success: " . html_entity_decode( strip_tags( $refund_message ) ) );
|
567 |
+
return true;
|
568 |
+
}
|
569 |
+
}
|
570 |
+
}
|
includes/class-wc-stripe-api.php
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit;
|
4 |
+
}
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WC_Stripe_API class.
|
8 |
+
*
|
9 |
+
* Communicates with Stripe API.
|
10 |
+
*/
|
11 |
+
class WC_Stripe_API {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Stripe API Endpoint
|
15 |
+
*/
|
16 |
+
const ENDPOINT = 'https://api.stripe.com/v1/';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Secret API Key.
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
private static $secret_key = '';
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Set secret API Key.
|
26 |
+
* @param string $key
|
27 |
+
*/
|
28 |
+
public static function set_secret_key( $secret_key ) {
|
29 |
+
self::$secret_key = $secret_key;
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Get secret key.
|
34 |
+
* @return string
|
35 |
+
*/
|
36 |
+
public static function get_secret_key() {
|
37 |
+
if ( ! self::$secret_key ) {
|
38 |
+
$options = get_option( 'woocommerce_stripe_settings' );
|
39 |
+
|
40 |
+
if ( isset( $options['testmode'], $options['secret_key'], $options['test_secret_key'] ) ) {
|
41 |
+
self::set_secret_key( 'yes' === $options['testmode'] ? $options['test_secret_key'] : $options['secret_key'] );
|
42 |
+
}
|
43 |
+
}
|
44 |
+
return self::$secret_key;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Send the request to Stripe's API
|
49 |
+
*
|
50 |
+
* @param array $request
|
51 |
+
* @param string $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 |
+
|
76 |
+
$parsed_response = json_decode( $response['body'] );
|
77 |
+
// Handle response
|
78 |
+
if ( ! empty( $parsed_response->error ) ) {
|
79 |
+
if ( ! empty( $parsed_response->error->param ) ) {
|
80 |
+
$code = $parsed_response->error->param;
|
81 |
+
} elseif ( ! empty( $parsed_response->error->code ) ) {
|
82 |
+
$code = $parsed_response->error->code;
|
83 |
+
} else {
|
84 |
+
$code = 'stripe_error';
|
85 |
+
}
|
86 |
+
return new WP_Error( $code, $parsed_response->error->message );
|
87 |
+
} else {
|
88 |
+
return $parsed_response;
|
89 |
+
}
|
90 |
+
}
|
91 |
+
}
|
includes/class-wc-stripe-customer.php
ADDED
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit;
|
4 |
+
}
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WC_Stripe_Customer class.
|
8 |
+
*
|
9 |
+
* Represents a Stripe Customer.
|
10 |
+
*/
|
11 |
+
class WC_Stripe_Customer {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Stripe customer ID
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
private $id = '';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* WP User ID
|
21 |
+
* @var integer
|
22 |
+
*/
|
23 |
+
private $user_id = 0;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Data from API
|
27 |
+
* @var array
|
28 |
+
*/
|
29 |
+
private $customer_data = array();
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Constructor
|
33 |
+
* @param integer $user_id
|
34 |
+
*/
|
35 |
+
public function __construct( $user_id = 0 ) {
|
36 |
+
if ( $user_id ) {
|
37 |
+
$this->set_user_id( $user_id );
|
38 |
+
$this->set_id( get_user_meta( $user_id, '_stripe_customer_id', true ) );
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Get Stripe customer ID.
|
44 |
+
* @return string
|
45 |
+
*/
|
46 |
+
public function get_id() {
|
47 |
+
return $this->id;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Set Stripe customer ID.
|
52 |
+
* @param [type] $id [description]
|
53 |
+
*/
|
54 |
+
public function set_id( $id ) {
|
55 |
+
$this->id = wc_clean( $id );
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* User ID in WordPress.
|
60 |
+
* @return int
|
61 |
+
*/
|
62 |
+
public function get_user_id() {
|
63 |
+
return absint( $this->user_id );
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Set User ID used by WordPress.
|
68 |
+
* @param int $user_id
|
69 |
+
*/
|
70 |
+
public function set_user_id( $user_id ) {
|
71 |
+
$this->user_id = absint( $user_id );
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Get user object.
|
76 |
+
* @return WP_User
|
77 |
+
*/
|
78 |
+
protected function get_user() {
|
79 |
+
return $this->get_user_id() ? get_user_by( 'id', $this->get_user_id() ) : false;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Store data from the Stripe API about this customer
|
84 |
+
*/
|
85 |
+
public function set_customer_data( $data ) {
|
86 |
+
$this->customer_data = $data;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Get data from the Stripe API about this customer
|
91 |
+
*/
|
92 |
+
public function get_customer_data() {
|
93 |
+
if ( empty( $this->customer_data ) && $this->get_id() && false === ( $this->customer_data = get_transient( 'stripe_customer_' . $this->get_id() ) ) ) {
|
94 |
+
$response = WC_Stripe_API::request( array(), 'customers/' . $this->get_id() );
|
95 |
+
|
96 |
+
if ( ! is_wp_error( $response ) ) {
|
97 |
+
$this->set_customer_data( $response );
|
98 |
+
set_transient( 'stripe_customer_' . $this->get_id(), $response, HOUR_IN_SECONDS * 48 );
|
99 |
+
}
|
100 |
+
}
|
101 |
+
return $this->customer_data;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Get default card/source
|
106 |
+
* @return string
|
107 |
+
*/
|
108 |
+
public function get_default_card() {
|
109 |
+
$data = $this->get_customer_data();
|
110 |
+
$source = '';
|
111 |
+
|
112 |
+
if ( $data ) {
|
113 |
+
$source = $data->default_source;
|
114 |
+
}
|
115 |
+
|
116 |
+
return $source;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Create a customer via API.
|
121 |
+
* @param array $args
|
122 |
+
* @return WP_Error|int
|
123 |
+
*/
|
124 |
+
public function create_customer( $args ) {
|
125 |
+
if ( $user = $this->get_user() ) {
|
126 |
+
$defaults = array(
|
127 |
+
'email' => $user->user_email,
|
128 |
+
'description' => $user->display_name,
|
129 |
+
);
|
130 |
+
} else {
|
131 |
+
$defaults = array(
|
132 |
+
'email' => '',
|
133 |
+
'description' => '',
|
134 |
+
);
|
135 |
+
}
|
136 |
+
|
137 |
+
$args = wp_parse_args( $args, $defaults );
|
138 |
+
$response = WC_Stripe_API::request( $args, 'customers' );
|
139 |
+
|
140 |
+
if ( is_wp_error( $response ) ) {
|
141 |
+
return $response;
|
142 |
+
} elseif ( empty( $response->id ) ) {
|
143 |
+
return new WP_Error( 'stripe_error', __( 'Could not create Stripe customer.', 'woocommerce-gateway-stripe' ) );
|
144 |
+
}
|
145 |
+
|
146 |
+
$this->set_id( $response->id );
|
147 |
+
$this->clear_cache();
|
148 |
+
$this->set_customer_data( $response );
|
149 |
+
|
150 |
+
if ( $this->get_user_id() ) {
|
151 |
+
update_user_meta( $this->get_user_id(), '_stripe_customer_id', $response->id );
|
152 |
+
}
|
153 |
+
|
154 |
+
do_action( 'woocommerce_stripe_add_customer', $args, $response );
|
155 |
+
|
156 |
+
return $response->id;
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Add a card for this stripe customer.
|
161 |
+
* @param string $token
|
162 |
+
* @param bool $retry
|
163 |
+
* @return WP_Error|int
|
164 |
+
*/
|
165 |
+
public function add_card( $token, $retry = true ) {
|
166 |
+
if ( ! $this->get_id() ) {
|
167 |
+
if ( ( $response = $this->create_customer() ) && is_wp_error( $response ) ) {
|
168 |
+
return $response;
|
169 |
+
}
|
170 |
+
}
|
171 |
+
|
172 |
+
$response = WC_Stripe_API::request( array(
|
173 |
+
'source' => $token
|
174 |
+
), 'customers/' . $this->get_id() . '/sources' );
|
175 |
+
|
176 |
+
if ( is_wp_error( $response ) ) {
|
177 |
+
if ( 'customer' === $response->get_error_code() && $retry ) {
|
178 |
+
$this->create_customer();
|
179 |
+
return $this->add_card( $token, false );
|
180 |
+
} else {
|
181 |
+
return $response;
|
182 |
+
}
|
183 |
+
} elseif ( empty( $response->id ) ) {
|
184 |
+
return new WP_Error( 'error', __( 'Unable to add card', 'woocommerce-gateway-stripe' ) );
|
185 |
+
}
|
186 |
+
|
187 |
+
// Add token to WooCommerce
|
188 |
+
if ( $this->get_user_id() ) {
|
189 |
+
$token = new WC_Payment_Token_CC();
|
190 |
+
$token->set_token( $response->id );
|
191 |
+
$token->set_gateway_id( 'stripe' );
|
192 |
+
$token->set_card_type( strtolower( $response->brand ) );
|
193 |
+
$token->set_last4( $response->last4 );
|
194 |
+
$token->set_expiry_month( $response->exp_month );
|
195 |
+
$token->set_expiry_year( $response->exp_year );
|
196 |
+
$token->set_user_id( $this->get_user_id() );
|
197 |
+
$token->save();
|
198 |
+
}
|
199 |
+
|
200 |
+
$this->clear_cache();
|
201 |
+
|
202 |
+
do_action( 'woocommerce_stripe_add_card', $this->get_id(), $token, $response );
|
203 |
+
|
204 |
+
return $response->id;
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Get a customers saved cards using their Stripe ID. Cached.
|
209 |
+
*
|
210 |
+
* @param string $customer_id
|
211 |
+
* @return array
|
212 |
+
*/
|
213 |
+
public function get_cards() {
|
214 |
+
$cards = array();
|
215 |
+
|
216 |
+
if ( $this->get_id() && false === ( $cards = get_transient( 'stripe_cards_' . $this->get_id() ) ) ) {
|
217 |
+
$response = WC_Stripe_API::request( array(
|
218 |
+
'limit' => 100
|
219 |
+
), 'customers/' . $this->get_id() . '/sources', 'GET' );
|
220 |
+
|
221 |
+
if ( is_wp_error( $response ) ) {
|
222 |
+
return array();
|
223 |
+
}
|
224 |
+
|
225 |
+
if ( is_array( $response->data ) ) {
|
226 |
+
$cards = $response->data;
|
227 |
+
}
|
228 |
+
|
229 |
+
set_transient( 'stripe_cards_' . $this->get_id(), $cards, HOUR_IN_SECONDS * 48 );
|
230 |
+
}
|
231 |
+
|
232 |
+
return $cards;
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Delete a card from stripe.
|
237 |
+
* @param string $card_id
|
238 |
+
*/
|
239 |
+
public function delete_card( $card_id ) {
|
240 |
+
$response = WC_Stripe_API::request( array(), 'customers/' . $this->get_id() . '/sources/' . sanitize_text_field( $card_id ), 'DELETE' );
|
241 |
+
|
242 |
+
$this->clear_cache();
|
243 |
+
|
244 |
+
if ( ! is_wp_error( $response ) ) {
|
245 |
+
do_action( 'wc_stripe_delete_card', $this->get_id(), $response );
|
246 |
+
|
247 |
+
return true;
|
248 |
+
}
|
249 |
+
|
250 |
+
return false;
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Set default card in Stripe
|
255 |
+
* @param string $card_id
|
256 |
+
*/
|
257 |
+
public function set_default_card( $card_id ) {
|
258 |
+
$response = WC_Stripe_API::request( array(
|
259 |
+
'default_source' => sanitize_text_field( $card_id ),
|
260 |
+
), 'customers/' . $this->get_id(), 'POST' );
|
261 |
+
|
262 |
+
$this->clear_cache();
|
263 |
+
|
264 |
+
if ( ! is_wp_error( $response ) ) {
|
265 |
+
do_action( 'wc_stripe_set_default_card', $this->get_id(), $response );
|
266 |
+
|
267 |
+
return true;
|
268 |
+
}
|
269 |
+
|
270 |
+
return false;
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Deletes caches for this users cards.
|
275 |
+
*/
|
276 |
+
public function clear_cache() {
|
277 |
+
delete_transient( 'stripe_cards_' . $this->get_id() );
|
278 |
+
delete_transient( 'stripe_customer_' . $this->get_id() );
|
279 |
+
$this->customer_data = array();
|
280 |
+
}
|
281 |
+
}
|
includes/legacy/class-wc-gateway-stripe-saved-cards.php
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit;
|
4 |
+
}
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WC_Gateway_Stripe_Saved_Cards class.
|
8 |
+
*/
|
9 |
+
class WC_Gateway_Stripe_Saved_Cards {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Constructor
|
13 |
+
*/
|
14 |
+
public function __construct() {
|
15 |
+
add_action( 'wp', array( $this, 'delete_card' ) );
|
16 |
+
add_action( 'woocommerce_after_my_account', array( $this, 'output' ) );
|
17 |
+
add_action( 'wp', array( $this, 'default_card' ) );
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Display saved cards
|
22 |
+
*/
|
23 |
+
public function output() {
|
24 |
+
if ( ! is_user_logged_in() ) {
|
25 |
+
return;
|
26 |
+
}
|
27 |
+
|
28 |
+
$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
|
29 |
+
$stripe_cards = $stripe_customer->get_cards();
|
30 |
+
$default_card = $stripe_customer->get_default_card();
|
31 |
+
|
32 |
+
if ( $stripe_cards ) {
|
33 |
+
wc_get_template( 'saved-cards.php', array( 'cards' => $stripe_cards, 'default_card' => $default_card ), 'woocommerce-gateway-stripe/', untrailingslashit( plugin_dir_path( WC_STRIPE_MAIN_FILE ) ) . '/includes/legacy/templates/' );
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Delete a card
|
39 |
+
*/
|
40 |
+
public function delete_card() {
|
41 |
+
if ( ! isset( $_POST['stripe_delete_card'] ) || ! is_account_page() ) {
|
42 |
+
return;
|
43 |
+
}
|
44 |
+
|
45 |
+
$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
|
46 |
+
$stripe_customer_id = $stripe_customer->get_id();
|
47 |
+
$delete_card = sanitize_text_field( $_POST['stripe_delete_card'] );
|
48 |
+
|
49 |
+
if ( ! is_user_logged_in() || ! $stripe_customer_id || ! wp_verify_nonce( $_POST['_wpnonce'], "stripe_del_card" ) ) {
|
50 |
+
wp_die( __( 'Unable to make default card, please try again', 'woocommerce-gateway-stripe' ) );
|
51 |
+
}
|
52 |
+
|
53 |
+
if ( ! $stripe_customer->delete_card( $delete_card ) ) {
|
54 |
+
wc_add_notice( __( 'Unable to delete card.', 'woocommerce-gateway-stripe' ), 'error' );
|
55 |
+
} else {
|
56 |
+
wc_add_notice( __( 'Card deleted.', 'woocommerce-gateway-stripe' ), 'success' );
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Make a card as default method
|
62 |
+
*/
|
63 |
+
public function default_card() {
|
64 |
+
if ( ! isset( $_POST['stripe_default_card'] ) || ! is_account_page() ) {
|
65 |
+
return;
|
66 |
+
}
|
67 |
+
|
68 |
+
$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
|
69 |
+
$stripe_customer_id = $stripe_customer->get_id();
|
70 |
+
$default_source = sanitize_text_field( $_POST['stripe_default_card'] );
|
71 |
+
|
72 |
+
if ( ! is_user_logged_in() || ! $stripe_customer_id || ! wp_verify_nonce( $_POST['_wpnonce'], "stripe_default_card" ) ) {
|
73 |
+
wp_die( __( 'Unable to make default card, please try again', 'woocommerce-gateway-stripe' ) );
|
74 |
+
}
|
75 |
+
|
76 |
+
if ( ! $stripe_customer->set_default_card( $default_source ) ) {
|
77 |
+
wc_add_notice( __( 'Unable to update default card.', 'woocommerce-gateway-stripe' ), 'error' );
|
78 |
+
} else {
|
79 |
+
wc_add_notice( __( 'Default card updated.', 'woocommerce-gateway-stripe' ), 'success' );
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
new WC_Gateway_Stripe_Saved_Cards();
|
includes/legacy/class-wc-gateway-stripe.php
ADDED
@@ -0,0 +1,596 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit;
|
4 |
+
}
|
5 |
+
|
6 |
+
/**
|
7 |
+
* WC_Gateway_Stripe class.
|
8 |
+
*
|
9 |
+
* @extends WC_Payment_Gateway
|
10 |
+
*/
|
11 |
+
class WC_Gateway_Stripe extends WC_Payment_Gateway {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Constructor
|
15 |
+
*/
|
16 |
+
public function __construct() {
|
17 |
+
$this->id = 'stripe';
|
18 |
+
$this->method_title = __( 'Stripe', 'woocommerce-gateway-stripe' );
|
19 |
+
$this->method_description = __( 'Stripe works by adding credit card fields on the checkout and then sending the details to Stripe for verification.', 'woocommerce-gateway-stripe' );
|
20 |
+
$this->has_fields = true;
|
21 |
+
$this->view_transaction_url = 'https://dashboard.stripe.com/payments/%s';
|
22 |
+
$this->supports = array(
|
23 |
+
'subscriptions',
|
24 |
+
'products',
|
25 |
+
'refunds',
|
26 |
+
'subscription_cancellation',
|
27 |
+
'subscription_reactivation',
|
28 |
+
'subscription_suspension',
|
29 |
+
'subscription_amount_changes',
|
30 |
+
'subscription_payment_method_change', // Subs 1.n compatibility
|
31 |
+
'subscription_payment_method_change_customer',
|
32 |
+
'subscription_payment_method_change_admin',
|
33 |
+
'subscription_date_changes',
|
34 |
+
'multiple_subscriptions',
|
35 |
+
'pre-orders',
|
36 |
+
);
|
37 |
+
|
38 |
+
// Load the form fields
|
39 |
+
$this->init_form_fields();
|
40 |
+
|
41 |
+
// Load the settings.
|
42 |
+
$this->init_settings();
|
43 |
+
|
44 |
+
// Get setting values.
|
45 |
+
$this->title = $this->get_option( 'title' );
|
46 |
+
$this->description = $this->get_option( 'description' );
|
47 |
+
$this->enabled = $this->get_option( 'enabled' );
|
48 |
+
$this->testmode = 'yes' === $this->get_option( 'testmode' );
|
49 |
+
$this->capture = 'yes' === $this->get_option( 'capture', 'yes' );
|
50 |
+
$this->stripe_checkout = 'yes' === $this->get_option( 'stripe_checkout' );
|
51 |
+
$this->stripe_checkout_locale = $this->get_option( 'stripe_checkout_locale' );
|
52 |
+
$this->stripe_checkout_image = $this->get_option( 'stripe_checkout_image', '' );
|
53 |
+
$this->saved_cards = 'yes' === $this->get_option( 'saved_cards' );
|
54 |
+
$this->secret_key = $this->testmode ? $this->get_option( 'test_secret_key' ) : $this->get_option( 'secret_key' );
|
55 |
+
$this->publishable_key = $this->testmode ? $this->get_option( 'test_publishable_key' ) : $this->get_option( 'publishable_key' );
|
56 |
+
$this->bitcoin = 'USD' === strtoupper( get_woocommerce_currency() ) && 'yes' === $this->get_option( 'stripe_bitcoin' );
|
57 |
+
$this->logging = 'yes' === $this->get_option( 'logging' );
|
58 |
+
|
59 |
+
if ( $this->stripe_checkout ) {
|
60 |
+
$this->order_button_text = __( 'Continue to payment', 'woocommerce-gateway-stripe' );
|
61 |
+
}
|
62 |
+
|
63 |
+
if ( $this->testmode ) {
|
64 |
+
$this->description .= ' ' . sprintf( __( 'TEST MODE ENABLED. In test mode, you can use the card number 4242424242424242 with any CVC and a valid expiration date or check the documentation "<a href="%s">Testing Stripe</a>" for more card numbers.', 'woocommerce-gateway-stripe' ), 'https://stripe.com/docs/testing' );
|
65 |
+
$this->description = trim( $this->description );
|
66 |
+
}
|
67 |
+
|
68 |
+
WC_Stripe_API::set_secret_key( $this->secret_key );
|
69 |
+
|
70 |
+
// Hooks
|
71 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
|
72 |
+
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
73 |
+
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* get_icon function.
|
78 |
+
*
|
79 |
+
* @access public
|
80 |
+
* @return string
|
81 |
+
*/
|
82 |
+
public function get_icon() {
|
83 |
+
$ext = version_compare( WC()->version, '2.6', '>=' ) ? '.svg' : '.png';
|
84 |
+
$style = version_compare( WC()->version, '2.6', '>=' ) ? 'style="margin-left: 0.3em"' : '';
|
85 |
+
|
86 |
+
$icon = '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/visa' . $ext ) . '" alt="Visa" width="32" ' . $style . ' />';
|
87 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/mastercard' . $ext ) . '" alt="Mastercard" width="32" ' . $style . ' />';
|
88 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/amex' . $ext ) . '" alt="Amex" width="32" ' . $style . ' />';
|
89 |
+
|
90 |
+
if ( 'USD' === get_woocommerce_currency() ) {
|
91 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/discover' . $ext ) . '" alt="Discover" width="32" ' . $style . ' />';
|
92 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/jcb' . $ext ) . '" alt="JCB" width="32" ' . $style . ' />';
|
93 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( WC()->plugin_url() . '/assets/images/icons/credit-cards/diners' . $ext ) . '" alt="Diners" width="32" ' . $style . ' />';
|
94 |
+
}
|
95 |
+
|
96 |
+
if ( $this->bitcoin ) {
|
97 |
+
$icon .= '<img src="' . WC_HTTPS::force_https_url( plugins_url( '/assets/images/bitcoin' . $ext, WC_STRIPE_MAIN_FILE ) ) . '" alt="Bitcoin" width="32" ' . $style . ' />';
|
98 |
+
}
|
99 |
+
|
100 |
+
return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Get Stripe amount to pay
|
105 |
+
* @return float
|
106 |
+
*/
|
107 |
+
public function get_stripe_amount( $total, $currency = '' ) {
|
108 |
+
if ( ! $currency ) {
|
109 |
+
$currency = get_woocommerce_currency();
|
110 |
+
}
|
111 |
+
switch ( strtoupper( $currency ) ) {
|
112 |
+
// Zero decimal currencies
|
113 |
+
case 'BIF' :
|
114 |
+
case 'CLP' :
|
115 |
+
case 'DJF' :
|
116 |
+
case 'GNF' :
|
117 |
+
case 'JPY' :
|
118 |
+
case 'KMF' :
|
119 |
+
case 'KRW' :
|
120 |
+
case 'MGA' :
|
121 |
+
case 'PYG' :
|
122 |
+
case 'RWF' :
|
123 |
+
case 'VND' :
|
124 |
+
case 'VUV' :
|
125 |
+
case 'XAF' :
|
126 |
+
case 'XOF' :
|
127 |
+
case 'XPF' :
|
128 |
+
$total = absint( $total );
|
129 |
+
break;
|
130 |
+
default :
|
131 |
+
$total = round( $total, 2 ) * 100; // In cents
|
132 |
+
break;
|
133 |
+
}
|
134 |
+
return $total;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Check if SSL is enabled and notify the user
|
139 |
+
*/
|
140 |
+
public function admin_notices() {
|
141 |
+
if ( $this->enabled == 'no' ) {
|
142 |
+
return;
|
143 |
+
}
|
144 |
+
|
145 |
+
$addons = ( class_exists( 'WC_Subscriptions_Order' ) || class_exists( 'WC_Pre_Orders_Order' ) ) ? '_addons' : '';
|
146 |
+
|
147 |
+
// Check required fields
|
148 |
+
if ( ! $this->secret_key ) {
|
149 |
+
echo '<div class="error"><p>' . sprintf( __( 'Stripe error: Please enter your secret key <a href="%s">here</a>', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=wc_gateway_stripe' . $addons ) ) . '</p></div>';
|
150 |
+
return;
|
151 |
+
|
152 |
+
} elseif ( ! $this->publishable_key ) {
|
153 |
+
echo '<div class="error"><p>' . sprintf( __( 'Stripe error: Please enter your publishable key <a href="%s">here</a>', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=wc_gateway_stripe' . $addons ) ) . '</p></div>';
|
154 |
+
return;
|
155 |
+
}
|
156 |
+
|
157 |
+
// Simple check for duplicate keys
|
158 |
+
if ( $this->secret_key == $this->publishable_key ) {
|
159 |
+
echo '<div class="error"><p>' . sprintf( __( 'Stripe error: Your secret and publishable keys match. Please check and re-enter.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=wc_gateway_stripe' . $addons ) ) . '</p></div>';
|
160 |
+
return;
|
161 |
+
}
|
162 |
+
|
163 |
+
// Show message if enabled and FORCE SSL is disabled and WordpressHTTPS plugin is not detected
|
164 |
+
if ( ( function_exists( 'wc_site_is_https' ) && ! wc_site_is_https() ) && ( 'no' === get_option( 'woocommerce_force_ssl_checkout' ) && ! class_exists( 'WordPressHTTPS' ) ) ) {
|
165 |
+
echo '<div class="error"><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>';
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Check if this gateway is enabled
|
171 |
+
*/
|
172 |
+
public function is_available() {
|
173 |
+
if ( 'yes' === $this->enabled ) {
|
174 |
+
if ( ! $this->testmode && is_checkout() && ! is_ssl() ) {
|
175 |
+
return false;
|
176 |
+
}
|
177 |
+
if ( ! $this->secret_key || ! $this->publishable_key ) {
|
178 |
+
return false;
|
179 |
+
}
|
180 |
+
return true;
|
181 |
+
}
|
182 |
+
return false;
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Initialise Gateway Settings Form Fields
|
187 |
+
*/
|
188 |
+
public function init_form_fields() {
|
189 |
+
$this->form_fields = include( untrailingslashit( plugin_dir_path( WC_STRIPE_MAIN_FILE ) ) . '/includes/settings-stripe.php' );
|
190 |
+
|
191 |
+
wc_enqueue_js( "
|
192 |
+
jQuery( function( $ ) {
|
193 |
+
$( '#woocommerce_stripe_stripe_checkout' ).change(function(){
|
194 |
+
if ( $( this ).is( ':checked' ) ) {
|
195 |
+
$( '#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image' ).closest( 'tr' ).show();
|
196 |
+
} else {
|
197 |
+
$( '#woocommerce_stripe_stripe_checkout_locale, #woocommerce_stripe_stripe_bitcoin, #woocommerce_stripe_stripe_checkout_image' ).closest( 'tr' ).hide();
|
198 |
+
}
|
199 |
+
}).change();
|
200 |
+
});
|
201 |
+
" );
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Payment form on checkout page
|
206 |
+
*/
|
207 |
+
public function payment_fields() {
|
208 |
+
?>
|
209 |
+
<fieldset class="stripe-legacy-payment-fields">
|
210 |
+
<?php
|
211 |
+
if ( $this->description ) {
|
212 |
+
echo apply_filters( 'wc_stripe_description', wpautop( wp_kses_post( $this->description ) ) );
|
213 |
+
}
|
214 |
+
if ( $this->saved_cards && is_user_logged_in() ) {
|
215 |
+
$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
|
216 |
+
?>
|
217 |
+
<p class="form-row form-row-wide">
|
218 |
+
<a class="<?php echo apply_filters( 'wc_stripe_manage_saved_cards_class', 'button' ); ?>" style="float:right;" href="<?php echo apply_filters( 'wc_stripe_manage_saved_cards_url', get_permalink( get_option( 'woocommerce_myaccount_page_id' ) ) ); ?>#saved-cards"><?php esc_html_e( 'Manage cards', 'woocommerce-gateway-stripe' ); ?></a>
|
219 |
+
<?php
|
220 |
+
if ( $cards = $stripe_customer->get_cards() ) {
|
221 |
+
$default_card = $cards[0]->id;
|
222 |
+
foreach ( (array) $cards as $card ) {
|
223 |
+
if ( 'card' !== $card->object ) {
|
224 |
+
continue;
|
225 |
+
}
|
226 |
+
?>
|
227 |
+
<label for="stripe_card_<?php echo $card->id; ?>" class="brand-<?php echo esc_attr( strtolower( $card->brand ) ); ?>">
|
228 |
+
<input type="radio" id="stripe_card_<?php echo $card->id; ?>" name="wc-stripe-payment-token" value="<?php echo $card->id; ?>" <?php checked( $default_card, $card->id ) ?> />
|
229 |
+
<?php printf( __( '%s card ending in %s (Expires %s/%s)', 'woocommerce-gateway-stripe' ), $card->brand, $card->last4, $card->exp_month, $card->exp_year ); ?>
|
230 |
+
</label>
|
231 |
+
<?php
|
232 |
+
}
|
233 |
+
}
|
234 |
+
?>
|
235 |
+
<label for="new">
|
236 |
+
<input type="radio" id="new" name="wc-stripe-payment-token" value="new" />
|
237 |
+
<?php _e( 'Use a new credit card', 'woocommerce-gateway-stripe' ); ?>
|
238 |
+
</label>
|
239 |
+
</p>
|
240 |
+
<?php
|
241 |
+
}
|
242 |
+
|
243 |
+
$user = wp_get_current_user();
|
244 |
+
|
245 |
+
if ( $user ) {
|
246 |
+
$user_email = get_user_meta( $user->ID, 'billing_email', true );
|
247 |
+
$user_email = $user_email ? $user_email : $user->user_email;
|
248 |
+
} else {
|
249 |
+
$user_email = '';
|
250 |
+
}
|
251 |
+
|
252 |
+
$display = '';
|
253 |
+
|
254 |
+
if ( $this->stripe_checkout || $this->saved_cards && ! empty( $cards ) ) {
|
255 |
+
$display = 'style="display:none;"';
|
256 |
+
}
|
257 |
+
|
258 |
+
echo '<div ' . $display . ' id="stripe-payment-data"
|
259 |
+
data-description=""
|
260 |
+
data-email="' . esc_attr( $user_email ) . '"
|
261 |
+
data-amount="' . esc_attr( $this->get_stripe_amount( WC()->cart->total ) ) . '"
|
262 |
+
data-name="' . esc_attr( sprintf( __( '%s', 'woocommerce-gateway-stripe' ), get_bloginfo( 'name', 'display' ) ) ) . '"
|
263 |
+
data-currency="' . esc_attr( strtolower( get_woocommerce_currency() ) ) . '"
|
264 |
+
data-image="' . esc_attr( $this->stripe_checkout_image ) . '"
|
265 |
+
data-bitcoin="' . esc_attr( $this->bitcoin ? 'true' : 'false' ) . '"
|
266 |
+
data-locale="' . esc_attr( $this->stripe_checkout_locale ? $this->stripe_checkout_locale : 'en' ) . '">';
|
267 |
+
|
268 |
+
if ( ! $this->stripe_checkout ) {
|
269 |
+
$this->credit_card_form( array( 'fields_have_names' => false ) );
|
270 |
+
}
|
271 |
+
|
272 |
+
echo '</div>';
|
273 |
+
?>
|
274 |
+
</fieldset>
|
275 |
+
<?php
|
276 |
+
}
|
277 |
+
|
278 |
+
/**
|
279 |
+
* payment_scripts function.
|
280 |
+
*
|
281 |
+
* Outputs scripts used for stripe payment
|
282 |
+
*
|
283 |
+
* @access public
|
284 |
+
*/
|
285 |
+
public function payment_scripts() {
|
286 |
+
if ( $this->stripe_checkout ) {
|
287 |
+
wp_enqueue_script( 'stripe', 'https://checkout.stripe.com/v2/checkout.js', '', '2.0', true );
|
288 |
+
wp_enqueue_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe_checkout.js', WC_STRIPE_MAIN_FILE ), array( 'stripe' ), WC_STRIPE_VERSION, true );
|
289 |
+
} else {
|
290 |
+
wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
|
291 |
+
wp_enqueue_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe.js', WC_STRIPE_MAIN_FILE ), array( 'jquery-payment', 'stripe' ), WC_STRIPE_VERSION, true );
|
292 |
+
}
|
293 |
+
|
294 |
+
$stripe_params = array(
|
295 |
+
'key' => $this->publishable_key,
|
296 |
+
'i18n_terms' => __( 'Please accept the terms and conditions first', 'woocommerce-gateway-stripe' ),
|
297 |
+
'i18n_required_fields' => __( 'Please fill in required checkout fields first', 'woocommerce-gateway-stripe' ),
|
298 |
+
);
|
299 |
+
|
300 |
+
// If we're on the pay page we need to pass stripe.js the address of the order.
|
301 |
+
if ( is_checkout_pay_page() && isset( $_GET['order'] ) && isset( $_GET['order_id'] ) ) {
|
302 |
+
$order_key = urldecode( $_GET['order'] );
|
303 |
+
$order_id = absint( $_GET['order_id'] );
|
304 |
+
$order = wc_get_order( $order_id );
|
305 |
+
|
306 |
+
if ( $order->id === $order_id && $order->order_key === $order_key ) {
|
307 |
+
$stripe_params['billing_first_name'] = $order->billing_first_name;
|
308 |
+
$stripe_params['billing_last_name'] = $order->billing_last_name;
|
309 |
+
$stripe_params['billing_address_1'] = $order->billing_address_1;
|
310 |
+
$stripe_params['billing_address_2'] = $order->billing_address_2;
|
311 |
+
$stripe_params['billing_state'] = $order->billing_state;
|
312 |
+
$stripe_params['billing_city'] = $order->billing_city;
|
313 |
+
$stripe_params['billing_postcode'] = $order->billing_postcode;
|
314 |
+
$stripe_params['billing_country'] = $order->billing_country;
|
315 |
+
}
|
316 |
+
}
|
317 |
+
|
318 |
+
wp_localize_script( 'woocommerce_stripe', 'wc_stripe_params', apply_filters( 'wc_stripe_params', $stripe_params ) );
|
319 |
+
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* Generate the request for the payment.
|
323 |
+
* @param WC_Order $order
|
324 |
+
* @param object $source
|
325 |
+
* @return array()
|
326 |
+
*/
|
327 |
+
protected function generate_payment_request( $order, $source ) {
|
328 |
+
$post_data = array();
|
329 |
+
$post_data['currency'] = strtolower( $order->get_order_currency() ? $order->get_order_currency() : get_woocommerce_currency() );
|
330 |
+
$post_data['amount'] = $this->get_stripe_amount( $order->get_total(), $post_data['currency'] );
|
331 |
+
$post_data['description'] = sprintf( __( '%s - Order %s', 'woocommerce-gateway-stripe' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), $order->get_order_number() );
|
332 |
+
$post_data['capture'] = $this->capture ? 'true' : 'false';
|
333 |
+
|
334 |
+
if ( ! empty( $order->billing_email ) && apply_filters( 'wc_stripe_send_stripe_receipt', false ) ) {
|
335 |
+
$post_data['receipt_email'] = $order->billing_email;
|
336 |
+
}
|
337 |
+
|
338 |
+
$post_data['expand[]'] = 'balance_transaction';
|
339 |
+
|
340 |
+
if ( $source->customer ) {
|
341 |
+
$post_data['customer'] = $source->customer;
|
342 |
+
}
|
343 |
+
|
344 |
+
if ( $source->source ) {
|
345 |
+
$post_data['source'] = $source->source;
|
346 |
+
}
|
347 |
+
|
348 |
+
return $post_data;
|
349 |
+
}
|
350 |
+
|
351 |
+
/**
|
352 |
+
* Get payment source. This can be a new token or existing card.
|
353 |
+
* @param bool $force_customer Should we force customer creation?
|
354 |
+
* @return object
|
355 |
+
*/
|
356 |
+
protected function get_source( $user_id, $force_customer = false ) {
|
357 |
+
$stripe_customer = new WC_Stripe_Customer( $user_id );
|
358 |
+
$stripe_source = false;
|
359 |
+
$token_id = false;
|
360 |
+
|
361 |
+
// New CC info was entered and we have a new token to process
|
362 |
+
if ( isset( $_POST['stripe_token'] ) ) {
|
363 |
+
$stripe_token = wc_clean( $_POST['stripe_token'] );
|
364 |
+
$maybe_saved_card = ! isset( $_POST['wc-stripe-new-payment-method'] ) || ! empty( $_POST['wc-stripe-new-payment-method'] );
|
365 |
+
|
366 |
+
// This is true if the user wants to store the card to their account.
|
367 |
+
if ( ( $user_id && $this->saved_cards && $maybe_saved_card ) || $force_customer ) {
|
368 |
+
$stripe_source = $stripe_customer->add_card( $stripe_token );
|
369 |
+
|
370 |
+
if ( is_wp_error( $stripe_source ) ) {
|
371 |
+
throw new Exception( $stripe_source->get_error_message() );
|
372 |
+
}
|
373 |
+
|
374 |
+
} else {
|
375 |
+
// Not saving token, so don't define customer either.
|
376 |
+
$stripe_source = $stripe_token;
|
377 |
+
$stripe_customer = false;
|
378 |
+
}
|
379 |
+
}
|
380 |
+
|
381 |
+
// Use an existing token, and then process the payment
|
382 |
+
elseif ( isset( $_POST['wc-stripe-payment-token'] ) && 'new' !== $_POST['wc-stripe-payment-token'] ) {
|
383 |
+
$stripe_source = wc_clean( $_POST['wc-stripe-payment-token'] );
|
384 |
+
}
|
385 |
+
|
386 |
+
return (object) array(
|
387 |
+
'token_id' => $token_id,
|
388 |
+
'customer' => $stripe_customer ? $stripe_customer->get_id() : false,
|
389 |
+
'source' => $stripe_source,
|
390 |
+
);
|
391 |
+
}
|
392 |
+
|
393 |
+
/**
|
394 |
+
* Get payment source from an order. This could be used in the future for
|
395 |
+
* a subscription as an example, therefore using the current user ID would
|
396 |
+
* not work - the customer won't be logged in :)
|
397 |
+
*
|
398 |
+
* Not using 2.6 tokens for this part since we need a customer AND a card
|
399 |
+
* token, and not just one.
|
400 |
+
*
|
401 |
+
* @param object $order
|
402 |
+
* @return object
|
403 |
+
*/
|
404 |
+
protected function get_order_source( $order = null ) {
|
405 |
+
$stripe_customer = new WC_Stripe_Customer();
|
406 |
+
$stripe_source = false;
|
407 |
+
$token_id = false;
|
408 |
+
|
409 |
+
if ( $order ) {
|
410 |
+
if ( $meta_value = get_post_meta( $order->id, '_stripe_customer_id', true ) ) {
|
411 |
+
$stripe_customer->set_id( $meta_value );
|
412 |
+
}
|
413 |
+
if ( $meta_value = get_post_meta( $order->id, '_stripe_card_id', true ) ) {
|
414 |
+
$stripe_source = $meta_value;
|
415 |
+
}
|
416 |
+
}
|
417 |
+
|
418 |
+
return (object) array(
|
419 |
+
'token_id' => $token_id,
|
420 |
+
'customer' => $stripe_customer ? $stripe_customer->get_id() : false,
|
421 |
+
'source' => $stripe_source,
|
422 |
+
);
|
423 |
+
}
|
424 |
+
|
425 |
+
/**
|
426 |
+
* Process the payment
|
427 |
+
*/
|
428 |
+
public function process_payment( $order_id, $retry = true, $force_customer = false ) {
|
429 |
+
try {
|
430 |
+
$order = wc_get_order( $order_id );
|
431 |
+
$source = $this->get_source( get_current_user_id(), $force_customer );
|
432 |
+
|
433 |
+
if ( empty( $source->source ) && empty( $source->customer ) ) {
|
434 |
+
$error_msg = __( 'Please enter your card details to make a payment.', 'woocommerce-gateway-stripe' );
|
435 |
+
$error_msg .= ' ' . __( 'Developers: Please make sure that you are including jQuery and there are no JavaScript errors on the page.', 'woocommerce-gateway-stripe' );
|
436 |
+
throw new Exception( $error_msg );
|
437 |
+
}
|
438 |
+
|
439 |
+
// Store source to order meta
|
440 |
+
$this->save_source( $order, $source );
|
441 |
+
|
442 |
+
// Handle payment
|
443 |
+
if ( $order->get_total() > 0 ) {
|
444 |
+
|
445 |
+
if ( $order->get_total() * 100 < 50 ) {
|
446 |
+
throw new Exception( __( 'Sorry, the minimum allowed order total is 0.50 to use this payment method.', 'woocommerce-gateway-stripe' ) );
|
447 |
+
}
|
448 |
+
|
449 |
+
WC_Stripe::log( "Info: Begin processing payment for order $order_id for the amount of {$order->get_total()}" );
|
450 |
+
|
451 |
+
// Make the request
|
452 |
+
$response = WC_Stripe_API::request( $this->generate_payment_request( $order, $source ) );
|
453 |
+
|
454 |
+
if ( is_wp_error( $response ) ) {
|
455 |
+
// Customer param wrong? The user may have been deleted on stripe's end. Remove customer_id. Can be retried without.
|
456 |
+
if ( 'customer' === $response->get_error_code() && $retry ) {
|
457 |
+
delete_user_meta( get_current_user_id(), '_stripe_customer_id' );
|
458 |
+
return $this->process_payment( $order_id, false, $force_customer );
|
459 |
+
}
|
460 |
+
throw new Exception( $response->get_error_code() . ': ' . $response->get_error_message() );
|
461 |
+
}
|
462 |
+
|
463 |
+
// Process valid response
|
464 |
+
$this->process_response( $response, $order );
|
465 |
+
} else {
|
466 |
+
$order->payment_complete();
|
467 |
+
}
|
468 |
+
|
469 |
+
// Remove cart
|
470 |
+
WC()->cart->empty_cart();
|
471 |
+
|
472 |
+
// Return thank you page redirect
|
473 |
+
return array(
|
474 |
+
'result' => 'success',
|
475 |
+
'redirect' => $this->get_return_url( $order )
|
476 |
+
);
|
477 |
+
|
478 |
+
} catch ( Exception $e ) {
|
479 |
+
wc_add_notice( $e->getMessage(), 'error' );
|
480 |
+
WC()->session->set( 'refresh_totals', true );
|
481 |
+
WC_Stripe::log( sprintf( __( 'Error: %s', 'woocommerce-gateway-stripe' ), $e->getMessage() ) );
|
482 |
+
return;
|
483 |
+
}
|
484 |
+
}
|
485 |
+
|
486 |
+
/**
|
487 |
+
* Save source to order.
|
488 |
+
*/
|
489 |
+
protected function save_source( $order, $source ) {
|
490 |
+
// Store source in the order
|
491 |
+
if ( $source->customer ) {
|
492 |
+
update_post_meta( $order->id, '_stripe_customer_id', $source->customer );
|
493 |
+
}
|
494 |
+
if ( $source->source ) {
|
495 |
+
update_post_meta( $order->id, '_stripe_card_id', $source->source->id );
|
496 |
+
}
|
497 |
+
}
|
498 |
+
|
499 |
+
/**
|
500 |
+
* Store extra meta data for an order from a Stripe Response.
|
501 |
+
*/
|
502 |
+
public function process_response( $response, $order ) {
|
503 |
+
WC_Stripe::log( "Processing response: " . print_r( $response, true ) );
|
504 |
+
|
505 |
+
// Store charge data
|
506 |
+
update_post_meta( $order->id, '_stripe_charge_id', $response->id );
|
507 |
+
update_post_meta( $order->id, '_stripe_charge_captured', $response->captured ? 'yes' : 'no' );
|
508 |
+
|
509 |
+
// Store other data such as fees
|
510 |
+
if ( isset( $response->balance_transaction ) && isset( $response->balance_transaction->fee ) ) {
|
511 |
+
$fee = number_format( $response->balance_transaction->fee / 100, 2, '.', '' );
|
512 |
+
update_post_meta( $order->id, 'Stripe Fee', $fee );
|
513 |
+
update_post_meta( $order->id, 'Net Revenue From Stripe', $order->get_total() - $fee );
|
514 |
+
}
|
515 |
+
|
516 |
+
if ( $response->captured ) {
|
517 |
+
$order->payment_complete( $response->id );
|
518 |
+
WC_Stripe::log( "Successful charge: $response->id" );
|
519 |
+
} else {
|
520 |
+
add_post_meta( $order->id, '_transaction_id', $response->id, true );
|
521 |
+
|
522 |
+
if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
|
523 |
+
$order->reduce_order_stock();
|
524 |
+
}
|
525 |
+
|
526 |
+
$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 ) );
|
527 |
+
WC_Stripe::log( "Successful auth: $response->id" );
|
528 |
+
}
|
529 |
+
|
530 |
+
return $response;
|
531 |
+
}
|
532 |
+
|
533 |
+
/**
|
534 |
+
* Add payment method via account screen.
|
535 |
+
* We don't store the token locally, but to the Stripe API.
|
536 |
+
* @since 3.0.0
|
537 |
+
*/
|
538 |
+
public function add_payment_method() {
|
539 |
+
if ( empty( $_POST['stripe_token'] ) || ! is_user_logged_in() ) {
|
540 |
+
wc_add_notice( __( 'There was a problem adding the card.', 'woocommerce-gateway-stripe' ), 'error' );
|
541 |
+
return;
|
542 |
+
}
|
543 |
+
|
544 |
+
$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
|
545 |
+
$result = $stripe_customer->add_card( wc_clean( $_POST['stripe_token'] ) );
|
546 |
+
|
547 |
+
if ( is_wp_error( $result ) ) {
|
548 |
+
throw new Exception( $result->get_error_message() );
|
549 |
+
}
|
550 |
+
|
551 |
+
return array(
|
552 |
+
'result' => 'success',
|
553 |
+
'redirect' => wc_get_endpoint_url( 'payment-methods' ),
|
554 |
+
);
|
555 |
+
}
|
556 |
+
|
557 |
+
/**
|
558 |
+
* Refund a charge
|
559 |
+
* @param int $order_id
|
560 |
+
* @param float $amount
|
561 |
+
* @return bool
|
562 |
+
*/
|
563 |
+
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
564 |
+
$order = wc_get_order( $order_id );
|
565 |
+
|
566 |
+
if ( ! $order || ! $order->get_transaction_id() ) {
|
567 |
+
return false;
|
568 |
+
}
|
569 |
+
|
570 |
+
$body = array();
|
571 |
+
|
572 |
+
if ( ! is_null( $amount ) ) {
|
573 |
+
$body['amount'] = $this->get_stripe_amount( $amount );
|
574 |
+
}
|
575 |
+
|
576 |
+
if ( $reason ) {
|
577 |
+
$body['metadata'] = array(
|
578 |
+
'reason' => $reason,
|
579 |
+
);
|
580 |
+
}
|
581 |
+
|
582 |
+
WC_Stripe::log( "Info: Beginning refund for order $order_id for the amount of {$amount}" );
|
583 |
+
|
584 |
+
$response = WC_Stripe_API::request( $body, 'charges/' . $order->get_transaction_id() . '/refunds' );
|
585 |
+
|
586 |
+
if ( is_wp_error( $response ) ) {
|
587 |
+
WC_Stripe::log( "Error: " . $response->get_error_message() );
|
588 |
+
return $response;
|
589 |
+
} elseif ( ! empty( $response->id ) ) {
|
590 |
+
$refund_message = sprintf( __( 'Refunded %s - Refund ID: %s - Reason: %s', 'woocommerce-gateway-stripe' ), wc_price( $response->amount / 100 ), $response->id, $reason );
|
591 |
+
$order->add_order_note( $refund_message );
|
592 |
+
WC_Stripe::log( "Success: " . html_entity_decode( strip_tags( $refund_message ) ) );
|
593 |
+
return true;
|
594 |
+
}
|
595 |
+
}
|
596 |
+
}
|
includes/legacy/templates/saved-cards.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<h2 id="saved-cards" style="margin-top:40px;"><?php _e( 'Saved cards', 'woocommerce-gateway-stripe' ); ?></h2>
|
2 |
+
<table class="shop_table">
|
3 |
+
<thead>
|
4 |
+
<tr>
|
5 |
+
<th><?php esc_html_e( 'Card', 'woocommerce-gateway-stripe' ); ?></th>
|
6 |
+
<th><?php esc_html_e( 'Expires', 'woocommerce-gateway-stripe' ); ?></th>
|
7 |
+
<th></th>
|
8 |
+
</tr>
|
9 |
+
</thead>
|
10 |
+
<tbody>
|
11 |
+
<?php foreach ( $cards as $card ) :
|
12 |
+
if ( 'card' !== $card->object ) {
|
13 |
+
continue;
|
14 |
+
}
|
15 |
+
|
16 |
+
$is_default_card = $card->id === $default_card ? true : false;
|
17 |
+
?>
|
18 |
+
<tr>
|
19 |
+
<td><?php printf( __( '%s card ending in %s', 'woocommerce-gateway-stripe' ), $card->brand, $card->last4 ); ?>
|
20 |
+
<?php if ( $is_default_card ) echo '<br />' . __( '(Default)', 'woocommerce-gateway-stripe' ); ?>
|
21 |
+
</td>
|
22 |
+
<td><?php printf( __( 'Expires %s/%s', 'woocommerce-gateway-stripe' ), $card->exp_month, $card->exp_year ); ?></td>
|
23 |
+
<td>
|
24 |
+
<form action="" method="POST">
|
25 |
+
<?php wp_nonce_field ( 'stripe_del_card' ); ?>
|
26 |
+
<input type="hidden" name="stripe_delete_card" value="<?php echo esc_attr( $card->id ); ?>">
|
27 |
+
<input type="submit" class="button" value="<?php esc_attr_e( 'Delete card', 'woocommerce-gateway-stripe' ); ?>">
|
28 |
+
</form>
|
29 |
+
|
30 |
+
<?php if ( ! $is_default_card ) { ?>
|
31 |
+
<form action="" method="POST" style="margin-top:10px;">
|
32 |
+
<?php wp_nonce_field ( 'stripe_default_card' ); ?>
|
33 |
+
<input type="hidden" name="stripe_default_card" value="<?php echo esc_attr( $card->id ); ?>">
|
34 |
+
<input type="submit" class="button" value="<?php esc_attr_e( 'Make Default', 'woocommerce-gateway-stripe' ); ?>">
|
35 |
+
</form>
|
36 |
+
<?php } ?>
|
37 |
+
</td>
|
38 |
+
</tr>
|
39 |
+
<?php endforeach; ?>
|
40 |
+
</tbody>
|
41 |
+
</table>
|
includes/settings-stripe.php
ADDED
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit;
|
4 |
+
}
|
5 |
+
|
6 |
+
return apply_filters( 'wc_stripe_settings',
|
7 |
+
array(
|
8 |
+
'enabled' => array(
|
9 |
+
'title' => __( 'Enable/Disable', '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' ),
|
17 |
+
'type' => 'text',
|
18 |
+
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
|
19 |
+
'default' => __( 'Credit card (Stripe)', 'woocommerce-gateway-stripe' ),
|
20 |
+
'desc_tip' => true,
|
21 |
+
),
|
22 |
+
'description' => array(
|
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(
|
30 |
+
'title' => __( 'Test mode', 'woocommerce-gateway-stripe' ),
|
31 |
+
'label' => __( 'Enable Test Mode', 'woocommerce-gateway-stripe' ),
|
32 |
+
'type' => 'checkbox',
|
33 |
+
'description' => __( 'Place the payment gateway in test mode using test API keys.', 'woocommerce-gateway-stripe' ),
|
34 |
+
'default' => 'yes',
|
35 |
+
'desc_tip' => true,
|
36 |
+
),
|
37 |
+
'secret_key' => array(
|
38 |
+
'title' => __( 'Live Secret Key', 'woocommerce-gateway-stripe' ),
|
39 |
+
'type' => 'text',
|
40 |
+
'description' => __( 'Get your API keys from your stripe account.', 'woocommerce-gateway-stripe' ),
|
41 |
+
'default' => '',
|
42 |
+
'desc_tip' => true,
|
43 |
+
),
|
44 |
+
'publishable_key' => array(
|
45 |
+
'title' => __( 'Live Publishable Key', 'woocommerce-gateway-stripe' ),
|
46 |
+
'type' => 'text',
|
47 |
+
'description' => __( 'Get your API keys from your stripe account.', 'woocommerce-gateway-stripe' ),
|
48 |
+
'default' => '',
|
49 |
+
'desc_tip' => true,
|
50 |
+
),
|
51 |
+
'test_secret_key' => array(
|
52 |
+
'title' => __( 'Test Secret Key', 'woocommerce-gateway-stripe' ),
|
53 |
+
'type' => 'text',
|
54 |
+
'description' => __( 'Get your API keys from your stripe account.', 'woocommerce-gateway-stripe' ),
|
55 |
+
'default' => '',
|
56 |
+
'desc_tip' => true,
|
57 |
+
),
|
58 |
+
'test_publishable_key' => array(
|
59 |
+
'title' => __( 'Test Publishable Key', 'woocommerce-gateway-stripe' ),
|
60 |
+
'type' => 'text',
|
61 |
+
'description' => __( 'Get your API keys from your stripe account.', 'woocommerce-gateway-stripe' ),
|
62 |
+
'default' => '',
|
63 |
+
'desc_tip' => true,
|
64 |
+
),
|
65 |
+
'capture' => array(
|
66 |
+
'title' => __( 'Capture', 'woocommerce-gateway-stripe' ),
|
67 |
+
'label' => __( 'Capture charge immediately', 'woocommerce-gateway-stripe' ),
|
68 |
+
'type' => 'checkbox',
|
69 |
+
'description' => __( 'Whether or not to immediately capture the charge. When unchecked, the charge issues an authorization and will need to be captured later. Uncaptured charges expire in 7 days.', 'woocommerce-gateway-stripe' ),
|
70 |
+
'default' => 'yes',
|
71 |
+
'desc_tip' => true,
|
72 |
+
),
|
73 |
+
'stripe_checkout' => array(
|
74 |
+
'title' => __( 'Stripe Checkout', 'woocommerce-gateway-stripe' ),
|
75 |
+
'label' => __( 'Enable Stripe Checkout', 'woocommerce-gateway-stripe' ),
|
76 |
+
'type' => 'checkbox',
|
77 |
+
'description' => __( 'If enabled, this option shows a "pay" button and modal credit card form on the checkout, instead of credit card fields directly on the page.', 'woocommerce-gateway-stripe' ),
|
78 |
+
'default' => 'no',
|
79 |
+
'desc_tip' => true,
|
80 |
+
),
|
81 |
+
'stripe_checkout_locale' => array(
|
82 |
+
'title' => __( 'Stripe Checkout locale', 'woocommerce-gateway-stripe' ),
|
83 |
+
'type' => 'select',
|
84 |
+
'class' => 'wc-enhanced-select',
|
85 |
+
'description' => __( 'Language to display in Stripe Checkout modal. Specify Auto to display Checkout in the user\'s preferred language, if available. English will be used by default.', 'woocommerce-gateway-stripe' ),
|
86 |
+
'default' => 'en',
|
87 |
+
'desc_tip' => true,
|
88 |
+
'options' => array(
|
89 |
+
'auto' => __( 'Auto', 'woocommerce-gateway-stripe' ),
|
90 |
+
'zh' => __( 'Simplified Chinese', 'woocommerce-gateway-stripe' ),
|
91 |
+
'nl' => __( 'Dutch', 'woocommerce-gateway-stripe' ),
|
92 |
+
'en' => __( 'English', 'woocommerce-gateway-stripe' ),
|
93 |
+
'fr' => __( 'French', 'woocommerce-gateway-stripe' ),
|
94 |
+
'de' => __( 'German', 'woocommerce-gateway-stripe' ),
|
95 |
+
'it' => __( 'Italian', 'woocommerce-gateway-stripe' ),
|
96 |
+
'ja' => __( 'Japanese', 'woocommerce-gateway-stripe' ),
|
97 |
+
'es' => __( 'Spanish', 'woocommerce-gateway-stripe' ),
|
98 |
+
),
|
99 |
+
),
|
100 |
+
'stripe_bitcoin' => array(
|
101 |
+
'title' => __( 'Bitcoin Currency', 'woocommerce-gateway-stripe' ),
|
102 |
+
'label' => __( 'Enable Bitcoin Currency', 'woocommerce-gateway-stripe' ),
|
103 |
+
'type' => 'checkbox',
|
104 |
+
'description' => __( 'If enabled, an option to accept bitcoin will show on the checkout modal. Note: Stripe Checkout needs to be enabled and store currency must be set to USD.', 'woocommerce-gateway-stripe' ),
|
105 |
+
'default' => 'no',
|
106 |
+
'desc_tip' => true,
|
107 |
+
),
|
108 |
+
'stripe_checkout_image' => array(
|
109 |
+
'title' => __( 'Stripe Checkout Image', 'woocommerce-gateway-stripe' ),
|
110 |
+
'description' => __( 'Optionally enter the URL to a 128x128px image of your brand or product. e.g. <code>https://yoursite.com/wp-content/uploads/2013/09/yourimage.jpg</code>', 'woocommerce-gateway-stripe' ),
|
111 |
+
'type' => 'text',
|
112 |
+
'default' => '',
|
113 |
+
'desc_tip' => true,
|
114 |
+
),
|
115 |
+
'saved_cards' => array(
|
116 |
+
'title' => __( 'Saved Cards', 'woocommerce-gateway-stripe' ),
|
117 |
+
'label' => __( 'Enable Payment via Saved Cards', 'woocommerce-gateway-stripe' ),
|
118 |
+
'type' => 'checkbox',
|
119 |
+
'description' => __( 'If enabled, users will be able to pay with a saved card during checkout. Card details are saved on Stripe servers, not on your store.', 'woocommerce-gateway-stripe' ),
|
120 |
+
'default' => 'no',
|
121 |
+
'desc_tip' => true,
|
122 |
+
),
|
123 |
+
'logging' => array(
|
124 |
+
'title' => __( 'Logging', 'woocommerce-gateway-stripe' ),
|
125 |
+
'label' => __( 'Log debug messages', 'woocommerce-gateway-stripe' ),
|
126 |
+
'type' => 'checkbox',
|
127 |
+
'description' => __( 'Save debug messages to the WooCommerce System Status log.', 'woocommerce-gateway-stripe' ),
|
128 |
+
'default' => 'no',
|
129 |
+
'desc_tip' => true,
|
130 |
+
),
|
131 |
+
)
|
132 |
+
);
|
languages/index.html
ADDED
File without changes
|
languages/woocommerce-gateway-stripe.pot
ADDED
@@ -0,0 +1,508 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (C) 2016 WooCommerce Stripe Gateway
|
2 |
+
# This file is distributed under the same license as the WooCommerce Stripe Gateway package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"Project-Id-Version: WooCommerce Stripe Gateway 3.0.0\n"
|
6 |
+
"Report-Msgid-Bugs-To: http://wordpress.org/tag/woocommerce-gateway-stripe\n"
|
7 |
+
"POT-Creation-Date: 2016-06-07 10:40:14+00:00\n"
|
8 |
+
"MIME-Version: 1.0\n"
|
9 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
+
"Content-Transfer-Encoding: 8bit\n"
|
11 |
+
"PO-Revision-Date: 2016-MO-DA HO:MI+ZONE\n"
|
12 |
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
+
|
15 |
+
#: includes/class-wc-gateway-stripe-addons.php:104
|
16 |
+
#: includes/class-wc-gateway-stripe-addons.php:150
|
17 |
+
#: includes/class-wc-gateway-stripe.php:415
|
18 |
+
#: includes/legacy/class-wc-gateway-stripe.php:446
|
19 |
+
msgid ""
|
20 |
+
"Sorry, the minimum allowed order total is 0.50 to use this payment method."
|
21 |
+
msgstr ""
|
22 |
+
|
23 |
+
#: includes/class-wc-gateway-stripe-addons.php:117
|
24 |
+
msgid "Customer not found"
|
25 |
+
msgstr ""
|
26 |
+
|
27 |
+
#: includes/class-wc-gateway-stripe-addons.php:157
|
28 |
+
msgid "Unable to store payment details. Please try again."
|
29 |
+
msgstr ""
|
30 |
+
|
31 |
+
#: includes/class-wc-gateway-stripe-addons.php:218
|
32 |
+
#: includes/class-wc-gateway-stripe-addons.php:269
|
33 |
+
msgid "Stripe Transaction Failed (%s)"
|
34 |
+
msgstr ""
|
35 |
+
|
36 |
+
#: includes/class-wc-gateway-stripe-addons.php:400
|
37 |
+
#: includes/class-wc-gateway-stripe-addons.php:405
|
38 |
+
msgid "Via %s card ending in %s"
|
39 |
+
msgstr ""
|
40 |
+
|
41 |
+
#: includes/class-wc-gateway-stripe.php:18
|
42 |
+
#: includes/legacy/class-wc-gateway-stripe.php:18
|
43 |
+
msgid "Stripe"
|
44 |
+
msgstr ""
|
45 |
+
|
46 |
+
#: includes/class-wc-gateway-stripe.php:19
|
47 |
+
#: includes/legacy/class-wc-gateway-stripe.php:19
|
48 |
+
msgid ""
|
49 |
+
"Stripe works by adding credit card fields on the checkout and then sending "
|
50 |
+
"the details to Stripe for verification."
|
51 |
+
msgstr ""
|
52 |
+
|
53 |
+
#: includes/class-wc-gateway-stripe.php:61
|
54 |
+
#: includes/legacy/class-wc-gateway-stripe.php:60
|
55 |
+
msgid "Continue to payment"
|
56 |
+
msgstr ""
|
57 |
+
|
58 |
+
#: includes/class-wc-gateway-stripe.php:65
|
59 |
+
#: includes/legacy/class-wc-gateway-stripe.php:64
|
60 |
+
msgid ""
|
61 |
+
"TEST MODE ENABLED. In test mode, you can use the card number "
|
62 |
+
"4242424242424242 with any CVC and a valid expiration date or check the "
|
63 |
+
"documentation \"<a href=\"%s\">Testing Stripe</a>\" for more card numbers."
|
64 |
+
msgstr ""
|
65 |
+
|
66 |
+
#: includes/class-wc-gateway-stripe.php:148
|
67 |
+
#: includes/legacy/class-wc-gateway-stripe.php:165
|
68 |
+
msgid ""
|
69 |
+
"Stripe is enabled, but the <a href=\"%s\">force SSL option</a> is disabled; "
|
70 |
+
"your checkout may not be secure! Please enable SSL and ensure your server "
|
71 |
+
"has a valid SSL certificate - Stripe will only work in test mode."
|
72 |
+
msgstr ""
|
73 |
+
|
74 |
+
#: includes/class-wc-gateway-stripe.php:202
|
75 |
+
msgid "Add Card"
|
76 |
+
msgstr ""
|
77 |
+
|
78 |
+
#: includes/class-wc-gateway-stripe.php:213
|
79 |
+
#: includes/legacy/class-wc-gateway-stripe.php:262
|
80 |
+
msgid "%s"
|
81 |
+
msgstr ""
|
82 |
+
|
83 |
+
#: includes/class-wc-gateway-stripe.php:257
|
84 |
+
#: includes/legacy/class-wc-gateway-stripe.php:296
|
85 |
+
msgid "Please accept the terms and conditions first"
|
86 |
+
msgstr ""
|
87 |
+
|
88 |
+
#: includes/class-wc-gateway-stripe.php:258
|
89 |
+
#: includes/legacy/class-wc-gateway-stripe.php:297
|
90 |
+
msgid "Please fill in required checkout fields first"
|
91 |
+
msgstr ""
|
92 |
+
|
93 |
+
#: includes/class-wc-gateway-stripe.php:292
|
94 |
+
#: includes/legacy/class-wc-gateway-stripe.php:331
|
95 |
+
msgid "%s - Order %s"
|
96 |
+
msgstr ""
|
97 |
+
|
98 |
+
#: includes/class-wc-gateway-stripe.php:349
|
99 |
+
msgid "Invalid payment method. Please input a new card number."
|
100 |
+
msgstr ""
|
101 |
+
|
102 |
+
#: includes/class-wc-gateway-stripe.php:403
|
103 |
+
#: includes/legacy/class-wc-gateway-stripe.php:434
|
104 |
+
msgid "Please enter your card details to make a payment."
|
105 |
+
msgstr ""
|
106 |
+
|
107 |
+
#: includes/class-wc-gateway-stripe.php:404
|
108 |
+
#: includes/legacy/class-wc-gateway-stripe.php:435
|
109 |
+
msgid ""
|
110 |
+
"Developers: Please make sure that you are including jQuery and there are no "
|
111 |
+
"JavaScript errors on the page."
|
112 |
+
msgstr ""
|
113 |
+
|
114 |
+
#: includes/class-wc-gateway-stripe.php:432
|
115 |
+
msgid "This card is no longer available and has been removed."
|
116 |
+
msgstr ""
|
117 |
+
|
118 |
+
#: includes/class-wc-gateway-stripe.php:455
|
119 |
+
#: includes/legacy/class-wc-gateway-stripe.php:481
|
120 |
+
msgid "Error: %s"
|
121 |
+
msgstr ""
|
122 |
+
|
123 |
+
#: includes/class-wc-gateway-stripe.php:500
|
124 |
+
#: includes/legacy/class-wc-gateway-stripe.php:526
|
125 |
+
msgid ""
|
126 |
+
"Stripe charge authorized (Charge ID: %s). Process order to take payment, or "
|
127 |
+
"cancel to remove the pre-authorization."
|
128 |
+
msgstr ""
|
129 |
+
|
130 |
+
#: includes/class-wc-gateway-stripe.php:514
|
131 |
+
#: includes/legacy/class-wc-gateway-stripe.php:540
|
132 |
+
msgid "There was a problem adding the card."
|
133 |
+
msgstr ""
|
134 |
+
|
135 |
+
#: includes/class-wc-gateway-stripe.php:564
|
136 |
+
#: includes/legacy/class-wc-gateway-stripe.php:590
|
137 |
+
msgid "Refunded %s - Refund ID: %s - Reason: %s"
|
138 |
+
msgstr ""
|
139 |
+
|
140 |
+
#: includes/class-wc-stripe-api.php:73
|
141 |
+
msgid "There was a problem connecting to the payment gateway."
|
142 |
+
msgstr ""
|
143 |
+
|
144 |
+
#: includes/class-wc-stripe-customer.php:143
|
145 |
+
msgid "Could not create Stripe customer."
|
146 |
+
msgstr ""
|
147 |
+
|
148 |
+
#: includes/class-wc-stripe-customer.php:184
|
149 |
+
msgid "Unable to add card"
|
150 |
+
msgstr ""
|
151 |
+
|
152 |
+
#: includes/legacy/class-wc-gateway-stripe-saved-cards.php:50
|
153 |
+
#: includes/legacy/class-wc-gateway-stripe-saved-cards.php:73
|
154 |
+
msgid "Unable to make default card, please try again"
|
155 |
+
msgstr ""
|
156 |
+
|
157 |
+
#: includes/legacy/class-wc-gateway-stripe-saved-cards.php:54
|
158 |
+
msgid "Unable to delete card."
|
159 |
+
msgstr ""
|
160 |
+
|
161 |
+
#: includes/legacy/class-wc-gateway-stripe-saved-cards.php:56
|
162 |
+
msgid "Card deleted."
|
163 |
+
msgstr ""
|
164 |
+
|
165 |
+
#: includes/legacy/class-wc-gateway-stripe-saved-cards.php:77
|
166 |
+
msgid "Unable to update default card."
|
167 |
+
msgstr ""
|
168 |
+
|
169 |
+
#: includes/legacy/class-wc-gateway-stripe-saved-cards.php:79
|
170 |
+
msgid "Default card updated."
|
171 |
+
msgstr ""
|
172 |
+
|
173 |
+
#: includes/legacy/class-wc-gateway-stripe.php:149
|
174 |
+
msgid "Stripe error: Please enter your secret key <a href=\"%s\">here</a>"
|
175 |
+
msgstr ""
|
176 |
+
|
177 |
+
#: includes/legacy/class-wc-gateway-stripe.php:153
|
178 |
+
msgid "Stripe error: Please enter your publishable key <a href=\"%s\">here</a>"
|
179 |
+
msgstr ""
|
180 |
+
|
181 |
+
#: includes/legacy/class-wc-gateway-stripe.php:159
|
182 |
+
msgid ""
|
183 |
+
"Stripe error: Your secret and publishable keys match. Please check and re-"
|
184 |
+
"enter."
|
185 |
+
msgstr ""
|
186 |
+
|
187 |
+
#: includes/legacy/class-wc-gateway-stripe.php:218
|
188 |
+
msgid "Manage cards"
|
189 |
+
msgstr ""
|
190 |
+
|
191 |
+
#: includes/legacy/class-wc-gateway-stripe.php:229
|
192 |
+
msgid "%s card ending in %s (Expires %s/%s)"
|
193 |
+
msgstr ""
|
194 |
+
|
195 |
+
#: includes/legacy/class-wc-gateway-stripe.php:237
|
196 |
+
msgid "Use a new credit card"
|
197 |
+
msgstr ""
|
198 |
+
|
199 |
+
#: includes/legacy/templates/saved-cards.php:1
|
200 |
+
msgid "Saved cards"
|
201 |
+
msgstr ""
|
202 |
+
|
203 |
+
#: includes/legacy/templates/saved-cards.php:5
|
204 |
+
msgid "Card"
|
205 |
+
msgstr ""
|
206 |
+
|
207 |
+
#: includes/legacy/templates/saved-cards.php:6
|
208 |
+
msgid "Expires"
|
209 |
+
msgstr ""
|
210 |
+
|
211 |
+
#: includes/legacy/templates/saved-cards.php:19
|
212 |
+
msgid "%s card ending in %s"
|
213 |
+
msgstr ""
|
214 |
+
|
215 |
+
#: includes/legacy/templates/saved-cards.php:20
|
216 |
+
msgid "(Default)"
|
217 |
+
msgstr ""
|
218 |
+
|
219 |
+
#: includes/legacy/templates/saved-cards.php:22
|
220 |
+
msgid "Expires %s/%s"
|
221 |
+
msgstr ""
|
222 |
+
|
223 |
+
#: includes/legacy/templates/saved-cards.php:27
|
224 |
+
msgid "Delete card"
|
225 |
+
msgstr ""
|
226 |
+
|
227 |
+
#: includes/legacy/templates/saved-cards.php:34
|
228 |
+
msgid "Make Default"
|
229 |
+
msgstr ""
|
230 |
+
|
231 |
+
#: includes/settings-stripe.php:9
|
232 |
+
msgid "Enable/Disable"
|
233 |
+
msgstr ""
|
234 |
+
|
235 |
+
#: includes/settings-stripe.php:10
|
236 |
+
msgid "Enable Stripe"
|
237 |
+
msgstr ""
|
238 |
+
|
239 |
+
#: includes/settings-stripe.php:16
|
240 |
+
msgid "Title"
|
241 |
+
msgstr ""
|
242 |
+
|
243 |
+
#: includes/settings-stripe.php:18
|
244 |
+
msgid "This controls the title which the user sees during checkout."
|
245 |
+
msgstr ""
|
246 |
+
|
247 |
+
#: includes/settings-stripe.php:19
|
248 |
+
msgid "Credit card (Stripe)"
|
249 |
+
msgstr ""
|
250 |
+
|
251 |
+
#: includes/settings-stripe.php:23
|
252 |
+
msgid "Description"
|
253 |
+
msgstr ""
|
254 |
+
|
255 |
+
#: includes/settings-stripe.php:25
|
256 |
+
msgid "This controls the description which the user sees during checkout."
|
257 |
+
msgstr ""
|
258 |
+
|
259 |
+
#: includes/settings-stripe.php:26
|
260 |
+
msgid "Pay with your credit card via Stripe."
|
261 |
+
msgstr ""
|
262 |
+
|
263 |
+
#: includes/settings-stripe.php:30
|
264 |
+
msgid "Test mode"
|
265 |
+
msgstr ""
|
266 |
+
|
267 |
+
#: includes/settings-stripe.php:31
|
268 |
+
msgid "Enable Test Mode"
|
269 |
+
msgstr ""
|
270 |
+
|
271 |
+
#: includes/settings-stripe.php:33
|
272 |
+
msgid "Place the payment gateway in test mode using test API keys."
|
273 |
+
msgstr ""
|
274 |
+
|
275 |
+
#: includes/settings-stripe.php:38
|
276 |
+
msgid "Live Secret Key"
|
277 |
+
msgstr ""
|
278 |
+
|
279 |
+
#: includes/settings-stripe.php:40 includes/settings-stripe.php:47
|
280 |
+
#: includes/settings-stripe.php:54 includes/settings-stripe.php:61
|
281 |
+
msgid "Get your API keys from your stripe account."
|
282 |
+
msgstr ""
|
283 |
+
|
284 |
+
#: includes/settings-stripe.php:45
|
285 |
+
msgid "Live Publishable Key"
|
286 |
+
msgstr ""
|
287 |
+
|
288 |
+
#: includes/settings-stripe.php:52
|
289 |
+
msgid "Test Secret Key"
|
290 |
+
msgstr ""
|
291 |
+
|
292 |
+
#: includes/settings-stripe.php:59
|
293 |
+
msgid "Test Publishable Key"
|
294 |
+
msgstr ""
|
295 |
+
|
296 |
+
#: includes/settings-stripe.php:66
|
297 |
+
msgid "Capture"
|
298 |
+
msgstr ""
|
299 |
+
|
300 |
+
#: includes/settings-stripe.php:67
|
301 |
+
msgid "Capture charge immediately"
|
302 |
+
msgstr ""
|
303 |
+
|
304 |
+
#: includes/settings-stripe.php:69
|
305 |
+
msgid ""
|
306 |
+
"Whether or not to immediately capture the charge. When unchecked, the charge "
|
307 |
+
"issues an authorization and will need to be captured later. Uncaptured "
|
308 |
+
"charges expire in 7 days."
|
309 |
+
msgstr ""
|
310 |
+
|
311 |
+
#: includes/settings-stripe.php:74
|
312 |
+
msgid "Stripe Checkout"
|
313 |
+
msgstr ""
|
314 |
+
|
315 |
+
#: includes/settings-stripe.php:75
|
316 |
+
msgid "Enable Stripe Checkout"
|
317 |
+
msgstr ""
|
318 |
+
|
319 |
+
#: includes/settings-stripe.php:77
|
320 |
+
msgid ""
|
321 |
+
"If enabled, this option shows a \"pay\" button and modal credit card form on "
|
322 |
+
"the checkout, instead of credit card fields directly on the page."
|
323 |
+
msgstr ""
|
324 |
+
|
325 |
+
#: includes/settings-stripe.php:82
|
326 |
+
msgid "Stripe Checkout locale"
|
327 |
+
msgstr ""
|
328 |
+
|
329 |
+
#: includes/settings-stripe.php:85
|
330 |
+
msgid ""
|
331 |
+
"Language to display in Stripe Checkout modal. Specify Auto to display "
|
332 |
+
"Checkout in the user's preferred language, if available. English will be "
|
333 |
+
"used by default."
|
334 |
+
msgstr ""
|
335 |
+
|
336 |
+
#: includes/settings-stripe.php:89
|
337 |
+
msgid "Auto"
|
338 |
+
msgstr ""
|
339 |
+
|
340 |
+
#: includes/settings-stripe.php:90
|
341 |
+
msgid "Simplified Chinese"
|
342 |
+
msgstr ""
|
343 |
+
|
344 |
+
#: includes/settings-stripe.php:91
|
345 |
+
msgid "Dutch"
|
346 |
+
msgstr ""
|
347 |
+
|
348 |
+
#: includes/settings-stripe.php:92
|
349 |
+
msgid "English"
|
350 |
+
msgstr ""
|
351 |
+
|
352 |
+
#: includes/settings-stripe.php:93
|
353 |
+
msgid "French"
|
354 |
+
msgstr ""
|
355 |
+
|
356 |
+
#: includes/settings-stripe.php:94
|
357 |
+
msgid "German"
|
358 |
+
msgstr ""
|
359 |
+
|
360 |
+
#: includes/settings-stripe.php:95
|
361 |
+
msgid "Italian"
|
362 |
+
msgstr ""
|
363 |
+
|
364 |
+
#: includes/settings-stripe.php:96
|
365 |
+
msgid "Japanese"
|
366 |
+
msgstr ""
|
367 |
+
|
368 |
+
#: includes/settings-stripe.php:97
|
369 |
+
msgid "Spanish"
|
370 |
+
msgstr ""
|
371 |
+
|
372 |
+
#: includes/settings-stripe.php:101
|
373 |
+
msgid "Bitcoin Currency"
|
374 |
+
msgstr ""
|
375 |
+
|
376 |
+
#: includes/settings-stripe.php:102
|
377 |
+
msgid "Enable Bitcoin Currency"
|
378 |
+
msgstr ""
|
379 |
+
|
380 |
+
#: includes/settings-stripe.php:104
|
381 |
+
msgid ""
|
382 |
+
"If enabled, an option to accept bitcoin will show on the checkout modal. "
|
383 |
+
"Note: Stripe Checkout needs to be enabled and store currency must be set to "
|
384 |
+
"USD."
|
385 |
+
msgstr ""
|
386 |
+
|
387 |
+
#: includes/settings-stripe.php:109
|
388 |
+
msgid "Stripe Checkout Image"
|
389 |
+
msgstr ""
|
390 |
+
|
391 |
+
#: includes/settings-stripe.php:110
|
392 |
+
msgid ""
|
393 |
+
"Optionally enter the URL to a 128x128px image of your brand or product. e.g. "
|
394 |
+
"<code>https://yoursite.com/wp-content/uploads/2013/09/yourimage.jpg</code>"
|
395 |
+
msgstr ""
|
396 |
+
|
397 |
+
#: includes/settings-stripe.php:116
|
398 |
+
msgid "Saved Cards"
|
399 |
+
msgstr ""
|
400 |
+
|
401 |
+
#: includes/settings-stripe.php:117
|
402 |
+
msgid "Enable Payment via Saved Cards"
|
403 |
+
msgstr ""
|
404 |
+
|
405 |
+
#: includes/settings-stripe.php:119
|
406 |
+
msgid ""
|
407 |
+
"If enabled, users will be able to pay with a saved card during checkout. "
|
408 |
+
"Card details are saved on Stripe servers, not on your store."
|
409 |
+
msgstr ""
|
410 |
+
|
411 |
+
#: includes/settings-stripe.php:124
|
412 |
+
msgid "Logging"
|
413 |
+
msgstr ""
|
414 |
+
|
415 |
+
#: includes/settings-stripe.php:125
|
416 |
+
msgid "Log debug messages"
|
417 |
+
msgstr ""
|
418 |
+
|
419 |
+
#: includes/settings-stripe.php:127
|
420 |
+
msgid "Save debug messages to the WooCommerce System Status log."
|
421 |
+
msgstr ""
|
422 |
+
|
423 |
+
#: woocommerce-gateway-stripe.php:173
|
424 |
+
msgid ""
|
425 |
+
"Stripe is almost ready. To get started, <a href=\"%s\">set your Stripe "
|
426 |
+
"account keys</a>."
|
427 |
+
msgstr ""
|
428 |
+
|
429 |
+
#: woocommerce-gateway-stripe.php:184
|
430 |
+
msgid ""
|
431 |
+
"The plugin could not be activated. The minimum PHP version required for this "
|
432 |
+
"plugin is %1$s. You are running %2$s."
|
433 |
+
msgstr ""
|
434 |
+
|
435 |
+
#: woocommerce-gateway-stripe.php:186
|
436 |
+
msgid ""
|
437 |
+
"The WooCommerce Stripe plugin has been deactivated. The minimum PHP version "
|
438 |
+
"required for this plugin is %1$s. You are running %2$s."
|
439 |
+
msgstr ""
|
440 |
+
|
441 |
+
#: woocommerce-gateway-stripe.php:193
|
442 |
+
msgid ""
|
443 |
+
"The plugin could not be activated. The minimum WooCommerce version required "
|
444 |
+
"for this plugin is %1$s. You are running %2$s."
|
445 |
+
msgstr ""
|
446 |
+
|
447 |
+
#: woocommerce-gateway-stripe.php:195
|
448 |
+
msgid ""
|
449 |
+
"The WooCommerce Stripe plugin has been deactivated. The minimum WooCommerce "
|
450 |
+
"version required for this plugin is %1$s. You are running %2$s."
|
451 |
+
msgstr ""
|
452 |
+
|
453 |
+
#: woocommerce-gateway-stripe.php:202
|
454 |
+
msgid "The plugin could not be activated. cURL is not installed."
|
455 |
+
msgstr ""
|
456 |
+
|
457 |
+
#: woocommerce-gateway-stripe.php:204
|
458 |
+
msgid ""
|
459 |
+
"The WooCommerce Stripe plugin has been deactivated. cURL is not installed."
|
460 |
+
msgstr ""
|
461 |
+
|
462 |
+
#: woocommerce-gateway-stripe.php:219
|
463 |
+
msgid "Settings"
|
464 |
+
msgstr ""
|
465 |
+
|
466 |
+
#: woocommerce-gateway-stripe.php:220
|
467 |
+
msgid "Docs"
|
468 |
+
msgstr ""
|
469 |
+
|
470 |
+
#: woocommerce-gateway-stripe.php:221
|
471 |
+
msgid "Support"
|
472 |
+
msgstr ""
|
473 |
+
|
474 |
+
#: woocommerce-gateway-stripe.php:314
|
475 |
+
msgid "Unable to capture charge!"
|
476 |
+
msgstr ""
|
477 |
+
|
478 |
+
#: woocommerce-gateway-stripe.php:316
|
479 |
+
msgid "Stripe charge complete (Charge ID: %s)"
|
480 |
+
msgstr ""
|
481 |
+
|
482 |
+
#: woocommerce-gateway-stripe.php:348
|
483 |
+
msgid "Unable to refund charge!"
|
484 |
+
msgstr ""
|
485 |
+
|
486 |
+
#: woocommerce-gateway-stripe.php:350
|
487 |
+
msgid "Stripe charge refunded (Charge ID: %s)"
|
488 |
+
msgstr ""
|
489 |
+
|
490 |
+
#. Plugin Name of the plugin/theme
|
491 |
+
msgid "WooCommerce Stripe Gateway"
|
492 |
+
msgstr ""
|
493 |
+
|
494 |
+
#. Plugin URI of the plugin/theme
|
495 |
+
msgid "https://wordpress.org/plugins/woocommerce-gateway-stripe/"
|
496 |
+
msgstr ""
|
497 |
+
|
498 |
+
#. Description of the plugin/theme
|
499 |
+
msgid "Take credit card payments on your store using Stripe."
|
500 |
+
msgstr ""
|
501 |
+
|
502 |
+
#. Author of the plugin/theme
|
503 |
+
msgid "Automattic"
|
504 |
+
msgstr ""
|
505 |
+
|
506 |
+
#. Author URI of the plugin/theme
|
507 |
+
msgid "http://woothemes.com/"
|
508 |
+
msgstr ""
|
readme.txt
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== WooCommerce Stripe Payment Gateway ===
|
2 |
+
Contributors: automattic, woothemes, mikejolley, akeda, royho
|
3 |
+
Tags: credit card, stripe, woocommerce
|
4 |
+
Requires at least: 4.4
|
5 |
+
Tested up to: 4.5
|
6 |
+
Stable tag: 3.0.0
|
7 |
+
License: GPLv3
|
8 |
+
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
9 |
+
|
10 |
+
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 |
+
|
18 |
+
The Stripe plugin extends WooCommerce allowing you to take payments directly on your store via Stripe’s API.
|
19 |
+
|
20 |
+
Stripe is available in:
|
21 |
+
|
22 |
+
* United States
|
23 |
+
* Canada
|
24 |
+
* UK
|
25 |
+
* Australia
|
26 |
+
* Belgium
|
27 |
+
* France
|
28 |
+
* Germany
|
29 |
+
* Ireland
|
30 |
+
* The Netherlands
|
31 |
+
* [and more](https://support.stripe.com/questions/what-countries-does-stripe-support)
|
32 |
+
|
33 |
+
Stripe is a simple way to accept payments online. With Stripe you can accept Visa, MasterCard, American Express, Discover, JCB, and Diners Club cards, even Bitcoin, directly on your store.
|
34 |
+
|
35 |
+
= Why choose Stripe? =
|
36 |
+
|
37 |
+
Stripe has no setup fees, no monthly fees, no hidden costs: you only get charged when you earn money! Earnings are transferred to your bank account on a 7-day rolling basis.
|
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.
|
44 |
+
|
45 |
+
You can download an [older version of this gateway for older versions of WooCommerce from here](https://wordpress.org/plugins/woocommerce-gateway-stripe/developers/).
|
46 |
+
|
47 |
+
= Automatic installation =
|
48 |
+
|
49 |
+
Automatic installation is the easiest option as WordPress handles the file transfers itself and you don’t need to leave your web browser. To
|
50 |
+
do an automatic install of, log in to your WordPress dashboard, navigate to the Plugins menu and click Add New.
|
51 |
+
|
52 |
+
In the search field type “WooCommerce Stripe Payment Gateway” and click Search Plugins. Once you’ve found our plugin you can view details about it such as the point release, rating and description. Most importantly of course, you can install it by simply clicking "Install Now".
|
53 |
+
|
54 |
+
= Manual installation =
|
55 |
+
|
56 |
+
The manual installation method involves downloading our plugin and uploading it to your web server via your favorite FTP application. The WordPress codex contains [instructions on how to do this here](http://codex.wordpress.org/Managing_Plugins#Manual_Plugin_Installation).
|
57 |
+
|
58 |
+
= Updating =
|
59 |
+
|
60 |
+
Automatic updates should work like a charm; as always though, ensure you backup your site just in case.
|
61 |
+
|
62 |
+
== Frequently Asked Questions ==
|
63 |
+
|
64 |
+
= Does this support recurring payments, like for subscriptions? =
|
65 |
+
|
66 |
+
Yes!
|
67 |
+
|
68 |
+
= Does this support both production mode and sandbox mode for testing? =
|
69 |
+
|
70 |
+
Yes it does - production and sandbox mode is driven by the API keys you use.
|
71 |
+
|
72 |
+
= Where can I find documentation? =
|
73 |
+
|
74 |
+
For help setting up and configuring, please refer to our [user guide](https://docs.woothemes.com/document/stripe/)
|
75 |
+
|
76 |
+
= Where can I get support or talk to other users? =
|
77 |
+
|
78 |
+
If you get stuck, you can ask for help in the Plugin Forum.
|
79 |
+
|
80 |
+
== Screenshots ==
|
81 |
+
|
82 |
+
1. The settings panel used to configure the gateway.
|
83 |
+
2. Normal checkout with Stripe.
|
84 |
+
3. Option to save a card to your account.
|
85 |
+
4. Checking out with a saved card.
|
86 |
+
5. Using the Stripe checkout modal.
|
87 |
+
|
88 |
+
== Changelog ==
|
89 |
+
|
90 |
+
= 3.0.0 =
|
91 |
+
* First public WordPress.org release.
|
92 |
+
* Refactor for WC 2.6 and above. Legacy support for 2.5.
|
93 |
+
* Improved saved card handling using tokenization API in WooCommerce.
|
94 |
+
|
95 |
+
[See changelog for all versions](https://raw.githubusercontent.com/woothemes/woocommerce-gateway-stripe/master/CHANGELOG.txt).
|
woocommerce-gateway-stripe.php
ADDED
@@ -0,0 +1,436 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Plugin Name: WooCommerce Stripe Gateway
|
4 |
+
* Plugin URI: https://wordpress.org/plugins/woocommerce-gateway-stripe/
|
5 |
+
* Description: Take credit card payments on your store using Stripe.
|
6 |
+
* Author: Automattic
|
7 |
+
* Author URI: http://woothemes.com/
|
8 |
+
* Version: 3.0.0
|
9 |
+
*
|
10 |
+
* Copyright (c) 2016 Automattic
|
11 |
+
*
|
12 |
+
* This program is free software: you can redistribute it and/or modify
|
13 |
+
* it under the terms of the GNU General Public License as published by
|
14 |
+
* the Free Software Foundation, either version 3 of the License, or
|
15 |
+
* (at your option) any later version.
|
16 |
+
*
|
17 |
+
* This program is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
* GNU General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU General Public License
|
23 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
+
*/
|
25 |
+
|
26 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
27 |
+
exit;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Required minimums and constants
|
32 |
+
*/
|
33 |
+
define( 'WC_STRIPE_VERSION', '3.0.0' );
|
34 |
+
define( 'WC_STRIPE_MIN_PHP_VER', '5.3.0' );
|
35 |
+
define( 'WC_STRIPE_MIN_WC_VER', '2.5.0' );
|
36 |
+
define( 'WC_STRIPE_MAIN_FILE', __FILE__ );
|
37 |
+
define( 'WC_STRIPE_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
|
38 |
+
|
39 |
+
if ( ! class_exists( 'WC_Stripe' ) ) {
|
40 |
+
|
41 |
+
class WC_Stripe {
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @var Singleton The reference the *Singleton* instance of this class
|
45 |
+
*/
|
46 |
+
private static $instance;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @var Reference to logging class.
|
50 |
+
*/
|
51 |
+
private static $log;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Returns the *Singleton* instance of this class.
|
55 |
+
*
|
56 |
+
* @return Singleton The *Singleton* instance.
|
57 |
+
*/
|
58 |
+
public static function get_instance() {
|
59 |
+
if ( null === self::$instance ) {
|
60 |
+
self::$instance = new self();
|
61 |
+
}
|
62 |
+
return self::$instance;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Private clone method to prevent cloning of the instance of the
|
67 |
+
* *Singleton* instance.
|
68 |
+
*
|
69 |
+
* @return void
|
70 |
+
*/
|
71 |
+
private function __clone() {}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Private unserialize method to prevent unserializing of the *Singleton*
|
75 |
+
* instance.
|
76 |
+
*
|
77 |
+
* @return void
|
78 |
+
*/
|
79 |
+
private function __wakeup() {}
|
80 |
+
|
81 |
+
/** @var whether or not we need to load code for / support subscriptions */
|
82 |
+
private $subscription_support_enabled = false;
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Notices (array)
|
86 |
+
* @var array
|
87 |
+
*/
|
88 |
+
public $notices = array();
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Protected constructor to prevent creating a new instance of the
|
92 |
+
* *Singleton* via the `new` operator from outside of this class.
|
93 |
+
*/
|
94 |
+
protected function __construct() {
|
95 |
+
add_action( 'admin_init', array( $this, 'check_environment' ) );
|
96 |
+
add_action( 'admin_notices', array( $this, 'admin_notices' ), 15 );
|
97 |
+
add_action( 'plugins_loaded', array( $this, 'init' ) );
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Init the plugin after plugins_loaded so environment variables are set.
|
102 |
+
*/
|
103 |
+
public function init() {
|
104 |
+
// Don't hook anything else in the plugin if we're in an incompatible environment
|
105 |
+
if ( self::get_environment_warning() ) {
|
106 |
+
return;
|
107 |
+
}
|
108 |
+
|
109 |
+
include_once( plugin_basename( 'includes/class-wc-stripe-api.php' ) );
|
110 |
+
include_once( plugin_basename( 'includes/class-wc-stripe-customer.php' ) );
|
111 |
+
|
112 |
+
// Init the gateway itself
|
113 |
+
$this->init_gateways();
|
114 |
+
|
115 |
+
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
|
116 |
+
add_action( 'woocommerce_order_status_on-hold_to_processing', array( $this, 'capture_payment' ) );
|
117 |
+
add_action( 'woocommerce_order_status_on-hold_to_completed', array( $this, 'capture_payment' ) );
|
118 |
+
add_action( 'woocommerce_order_status_on-hold_to_cancelled', array( $this, 'cancel_payment' ) );
|
119 |
+
add_action( 'woocommerce_order_status_on-hold_to_refunded', array( $this, 'cancel_payment' ) );
|
120 |
+
add_filter( 'woocommerce_get_customer_payment_tokens', array( $this, 'woocommerce_get_customer_payment_tokens' ), 10, 3 );
|
121 |
+
add_action( 'woocommerce_payment_token_deleted', array( $this, 'woocommerce_payment_token_deleted' ), 10, 2 );
|
122 |
+
add_action( 'woocommerce_payment_token_set_default', array( $this, 'woocommerce_payment_token_set_default' ) );
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Allow this class and other classes to add slug keyed notices (to avoid duplication)
|
127 |
+
*/
|
128 |
+
public function add_admin_notice( $slug, $class, $message ) {
|
129 |
+
$this->notices[ $slug ] = array(
|
130 |
+
'class' => $class,
|
131 |
+
'message' => $message
|
132 |
+
);
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* The primary sanity check, automatically disable the plugin on activation if it doesn't
|
137 |
+
* meet minimum requirements.
|
138 |
+
*
|
139 |
+
* Based on http://wptavern.com/how-to-prevent-wordpress-plugins-from-activating-on-sites-with-incompatible-hosting-environments
|
140 |
+
*/
|
141 |
+
public static function activation_check() {
|
142 |
+
$environment_warning = self::get_environment_warning( true );
|
143 |
+
if ( $environment_warning ) {
|
144 |
+
deactivate_plugins( plugin_basename( __FILE__ ) );
|
145 |
+
wp_die( $environment_warning );
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* The backup sanity check, in case the plugin is activated in a weird way,
|
151 |
+
* or the environment changes after activation.
|
152 |
+
*/
|
153 |
+
public function check_environment() {
|
154 |
+
$environment_warning = self::get_environment_warning();
|
155 |
+
if ( $environment_warning && is_plugin_active( plugin_basename( __FILE__ ) ) ) {
|
156 |
+
deactivate_plugins( plugin_basename( __FILE__ ) );
|
157 |
+
$this->add_admin_notice( 'bad_environment', 'error', $environment_warning );
|
158 |
+
if ( isset( $_GET['activate'] ) ) {
|
159 |
+
unset( $_GET['activate'] );
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
// Check if secret key present. Otherwise prompt, via notice, to go to
|
164 |
+
// setting.
|
165 |
+
if ( ! class_exists( 'WC_Stripe_API' ) ) {
|
166 |
+
include_once( plugin_basename( 'includes/class-wc-stripe-api.php' ) );
|
167 |
+
}
|
168 |
+
|
169 |
+
$secret = WC_Stripe_API::get_secret_key();
|
170 |
+
|
171 |
+
if ( empty( $secret ) && ! ( isset( $_GET['page'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'stripe' === $_GET['section'] ) ) {
|
172 |
+
$setting_link = $this->get_setting_link();
|
173 |
+
$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>.', 'wwoocommerce-gateway-stripe' ), $setting_link ) );
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Checks the environment for compatibility problems. Returns a string with the first incompatibility
|
179 |
+
* found or false if the environment has no problems.
|
180 |
+
*/
|
181 |
+
static function get_environment_warning( $during_activation = false ) {
|
182 |
+
if ( version_compare( phpversion(), WC_STRIPE_MIN_PHP_VER, '<' ) ) {
|
183 |
+
if ( $during_activation ) {
|
184 |
+
$message = __( 'The plugin could not be activated. The minimum PHP version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe', 'woocommerce-gateway-stripe' );
|
185 |
+
} else {
|
186 |
+
$message = __( 'The WooCommerce Stripe plugin has been deactivated. The minimum PHP version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
|
187 |
+
}
|
188 |
+
return sprintf( $message, WC_STRIPE_MIN_PHP_VER, phpversion() );
|
189 |
+
}
|
190 |
+
|
191 |
+
if ( version_compare( WC_VERSION, WC_STRIPE_MIN_WC_VER, '<' ) ) {
|
192 |
+
if ( $during_activation ) {
|
193 |
+
$message = __( 'The plugin could not be activated. The minimum WooCommerce version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe', 'woocommerce-gateway-stripe' );
|
194 |
+
} else {
|
195 |
+
$message = __( 'The WooCommerce Stripe plugin has been deactivated. The minimum WooCommerce version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
|
196 |
+
}
|
197 |
+
return sprintf( $message, WC_STRIPE_MIN_WC_VER, WC_VERSION );
|
198 |
+
}
|
199 |
+
|
200 |
+
if ( ! function_exists( 'curl_init' ) ) {
|
201 |
+
if ( $during_activation ) {
|
202 |
+
return __( 'The plugin could not be activated. cURL is not installed.', 'woocommerce-gateway-stripe' );
|
203 |
+
}
|
204 |
+
return __( 'The WooCommerce Stripe plugin has been deactivated. cURL is not installed.', 'woocommerce-gateway-stripe' );
|
205 |
+
}
|
206 |
+
|
207 |
+
return false;
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Adds plugin action links
|
212 |
+
*
|
213 |
+
* @since 1.0.0
|
214 |
+
*/
|
215 |
+
public function plugin_action_links( $links ) {
|
216 |
+
$setting_link = $this->get_setting_link();
|
217 |
+
|
218 |
+
$plugin_links = array(
|
219 |
+
'<a href="' . $setting_link . '">' . __( 'Settings', 'woocommerce-gateway-stripe' ) . '</a>',
|
220 |
+
'<a href="https://docs.woothemes.com/document/stripe/">' . __( 'Docs', 'woocommerce-gateway-stripe' ) . '</a>',
|
221 |
+
'<a href="http://support.woothemes.com/">' . __( 'Support', 'woocommerce-gateway-stripe' ) . '</a>',
|
222 |
+
);
|
223 |
+
return array_merge( $plugin_links, $links );
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* Get setting link.
|
228 |
+
*
|
229 |
+
* @since 1.0.0
|
230 |
+
*
|
231 |
+
* @return string Setting link
|
232 |
+
*/
|
233 |
+
public function get_setting_link() {
|
234 |
+
$use_id_as_section = version_compare( WC()->version, '2.6', '>=' );
|
235 |
+
|
236 |
+
$section_slug = $use_id_as_section ? 'stripe' : strtolower( 'WC_Gateway_Stripe' );
|
237 |
+
|
238 |
+
return admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=' . $section_slug );
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Display any notices we've collected thus far (e.g. for connection, disconnection)
|
243 |
+
*/
|
244 |
+
public function admin_notices() {
|
245 |
+
foreach ( (array) $this->notices as $notice_key => $notice ) {
|
246 |
+
echo "<div class='" . esc_attr( $notice['class'] ) . "'><p>";
|
247 |
+
echo wp_kses( $notice['message'], array( 'a' => array( 'href' => array() ) ) );
|
248 |
+
echo "</p></div>";
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Initialize the gateway. Called very early - in the context of the plugins_loaded action
|
254 |
+
*
|
255 |
+
* @since 1.0.0
|
256 |
+
*/
|
257 |
+
public function init_gateways() {
|
258 |
+
if ( class_exists( 'WC_Subscriptions_Order' ) && function_exists( 'wcs_create_renewal_order' ) ) {
|
259 |
+
$this->subscription_support_enabled = true;
|
260 |
+
}
|
261 |
+
|
262 |
+
if ( ! class_exists( 'WC_Payment_Gateway' ) ) {
|
263 |
+
return;
|
264 |
+
}
|
265 |
+
|
266 |
+
if ( class_exists( 'WC_Payment_Gateway_CC' ) ) {
|
267 |
+
include_once( plugin_basename( 'includes/class-wc-gateway-stripe.php' ) );
|
268 |
+
} else {
|
269 |
+
include_once( plugin_basename( 'includes/legacy/class-wc-gateway-stripe.php' ) );
|
270 |
+
include_once( plugin_basename( 'includes/legacy/class-wc-gateway-stripe-saved-cards.php' ) );
|
271 |
+
}
|
272 |
+
|
273 |
+
load_plugin_textdomain( 'woocommerce-gateway-stripe', false, trailingslashit( dirname( plugin_basename( __FILE__ ) ) ) );
|
274 |
+
add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateways' ) );
|
275 |
+
|
276 |
+
if ( $this->subscription_support_enabled ) {
|
277 |
+
require_once( plugin_basename( 'includes/class-wc-gateway-stripe-addons.php' ) );
|
278 |
+
}
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Add the gateways to WooCommerce
|
283 |
+
*
|
284 |
+
* @since 1.0.0
|
285 |
+
*/
|
286 |
+
public function add_gateways( $methods ) {
|
287 |
+
if ( $this->subscription_support_enabled ) {
|
288 |
+
$methods[] = 'WC_Gateway_Stripe_Addons';
|
289 |
+
} else {
|
290 |
+
$methods[] = 'WC_Gateway_Stripe';
|
291 |
+
}
|
292 |
+
return $methods;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Capture payment when the order is changed from on-hold to complete or processing
|
297 |
+
*
|
298 |
+
* @param int $order_id
|
299 |
+
*/
|
300 |
+
public function capture_payment( $order_id ) {
|
301 |
+
$order = wc_get_order( $order_id );
|
302 |
+
|
303 |
+
if ( 'stripe' === $order->payment_method ) {
|
304 |
+
$charge = get_post_meta( $order_id, '_stripe_charge_id', true );
|
305 |
+
$captured = get_post_meta( $order_id, '_stripe_charge_captured', true );
|
306 |
+
|
307 |
+
if ( $charge && 'no' === $captured ) {
|
308 |
+
$result = WC_Stripe_API::request( array(
|
309 |
+
'amount' => $order->get_total() * 100,
|
310 |
+
'expand[]' => 'balance_transaction'
|
311 |
+
), 'charges/' . $charge . '/capture' );
|
312 |
+
|
313 |
+
if ( is_wp_error( $result ) ) {
|
314 |
+
$order->add_order_note( __( 'Unable to capture charge!', 'woocommerce-gateway-stripe' ) . ' ' . $result->get_error_message() );
|
315 |
+
} else {
|
316 |
+
$order->add_order_note( sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $result->id ) );
|
317 |
+
update_post_meta( $order->id, '_stripe_charge_captured', 'yes' );
|
318 |
+
|
319 |
+
// Store other data such as fees
|
320 |
+
update_post_meta( $order->id, 'Stripe Payment ID', $result->id );
|
321 |
+
|
322 |
+
if ( isset( $result->balance_transaction ) && isset( $result->balance_transaction->fee ) ) {
|
323 |
+
update_post_meta( $order->id, 'Stripe Fee', number_format( $result->balance_transaction->fee / 100, 2, '.', '' ) );
|
324 |
+
update_post_meta( $order->id, 'Net Revenue From Stripe', ( $order->order_total - number_format( $result->balance_transaction->fee / 100, 2, '.', '' ) ) );
|
325 |
+
}
|
326 |
+
}
|
327 |
+
}
|
328 |
+
}
|
329 |
+
}
|
330 |
+
|
331 |
+
/**
|
332 |
+
* Cancel pre-auth on refund/cancellation
|
333 |
+
*
|
334 |
+
* @param int $order_id
|
335 |
+
*/
|
336 |
+
public function cancel_payment( $order_id ) {
|
337 |
+
$order = wc_get_order( $order_id );
|
338 |
+
|
339 |
+
if ( 'stripe' === $order->payment_method ) {
|
340 |
+
$charge = get_post_meta( $order_id, '_stripe_charge_id', true );
|
341 |
+
|
342 |
+
if ( $charge ) {
|
343 |
+
$result = WC_Stripe_API::request( array(
|
344 |
+
'amount' => $order->get_total() * 100,
|
345 |
+
), 'charges/' . $charge . '/refund' );
|
346 |
+
|
347 |
+
if ( is_wp_error( $result ) ) {
|
348 |
+
$order->add_order_note( __( 'Unable to refund charge!', 'woocommerce-gateway-stripe' ) . ' ' . $result->get_error_message() );
|
349 |
+
} else {
|
350 |
+
$order->add_order_note( sprintf( __( 'Stripe charge refunded (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $result->id ) );
|
351 |
+
delete_post_meta( $order->id, '_stripe_charge_captured' );
|
352 |
+
delete_post_meta( $order->id, '_stripe_charge_id' );
|
353 |
+
}
|
354 |
+
}
|
355 |
+
}
|
356 |
+
}
|
357 |
+
|
358 |
+
/**
|
359 |
+
* Gets saved tokens from API if they don't already exist in WooCommerce.
|
360 |
+
* @param array $tokens
|
361 |
+
* @return array
|
362 |
+
*/
|
363 |
+
public function woocommerce_get_customer_payment_tokens( $tokens, $customer_id, $gateway_id ) {
|
364 |
+
if ( is_user_logged_in() && 'stripe' === $gateway_id ) {
|
365 |
+
$stripe_customer = new WC_Stripe_Customer( $customer_id );
|
366 |
+
$stripe_cards = $stripe_customer->get_cards();
|
367 |
+
$stored_tokens = array();
|
368 |
+
|
369 |
+
foreach ( $tokens as $token ) {
|
370 |
+
$stored_tokens[] = $token->get_token();
|
371 |
+
}
|
372 |
+
|
373 |
+
foreach ( $stripe_cards as $card ) {
|
374 |
+
if ( ! in_array( $card->id, $stored_tokens ) ) {
|
375 |
+
$token = new WC_Payment_Token_CC();
|
376 |
+
$token->set_token( $card->id );
|
377 |
+
$token->set_gateway_id( 'stripe' );
|
378 |
+
$token->set_card_type( strtolower( $card->brand ) );
|
379 |
+
$token->set_last4( $card->last4 );
|
380 |
+
$token->set_expiry_month( $card->exp_month );
|
381 |
+
$token->set_expiry_year( $card->exp_year );
|
382 |
+
$token->set_user_id( $customer_id );
|
383 |
+
$token->save();
|
384 |
+
$tokens[ $token->get_id() ] = $token;
|
385 |
+
}
|
386 |
+
}
|
387 |
+
}
|
388 |
+
return $tokens;
|
389 |
+
}
|
390 |
+
|
391 |
+
/**
|
392 |
+
* Delete token from Stripe
|
393 |
+
*/
|
394 |
+
public function woocommerce_payment_token_deleted( $token_id, $token ) {
|
395 |
+
if ( 'stripe' === $token->get_gateway_id() ) {
|
396 |
+
$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
|
397 |
+
$stripe_customer->delete_card( $token->get_token() );
|
398 |
+
}
|
399 |
+
}
|
400 |
+
|
401 |
+
/**
|
402 |
+
* Set as default in Stripe
|
403 |
+
*/
|
404 |
+
public function woocommerce_payment_token_set_default( $token_id ) {
|
405 |
+
$token = WC_Payment_Tokens::get( $token_id );
|
406 |
+
if ( 'stripe' === $token->get_gateway_id() ) {
|
407 |
+
$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
|
408 |
+
$stripe_customer->set_default_card( $token->get_token() );
|
409 |
+
}
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* What rolls down stairs
|
414 |
+
* alone or in pairs,
|
415 |
+
* and over your neighbor's dog?
|
416 |
+
* What's great for a snack,
|
417 |
+
* And fits on your back?
|
418 |
+
* It's log, log, log
|
419 |
+
*/
|
420 |
+
public static function log( $message ) {
|
421 |
+
if ( empty( self::$log ) ) {
|
422 |
+
self::$log = new WC_Logger();
|
423 |
+
}
|
424 |
+
|
425 |
+
self::$log->add( 'woocommerce-gateway-stripe', $message );
|
426 |
+
|
427 |
+
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
428 |
+
error_log( $message );
|
429 |
+
}
|
430 |
+
}
|
431 |
+
}
|
432 |
+
|
433 |
+
$GLOBALS['wc_stripe'] = WC_Stripe::get_instance();
|
434 |
+
register_activation_hook( __FILE__, array( 'WC_Stripe', 'activation_check' ) );
|
435 |
+
|
436 |
+
}
|
wordpress_org_assets/banner-1544x500.png
ADDED
Binary file
|
wordpress_org_assets/banner-772x250.png
ADDED
Binary file
|
wordpress_org_assets/icon-128x128.png
ADDED
Binary file
|
wordpress_org_assets/icon-256x256.png
ADDED
Binary file
|
wordpress_org_assets/screenshot-1.png
ADDED
Binary file
|
wordpress_org_assets/screenshot-2.png
ADDED
Binary file
|
wordpress_org_assets/screenshot-3.png
ADDED
Binary file
|
wordpress_org_assets/screenshot-4.png
ADDED
Binary file
|
wordpress_org_assets/screenshot-5.png
ADDED
Binary file
|
wordpress_org_assets/wc-stripe.sketch
ADDED
Binary file
|