Version Description
2019-10-17 =
* Add - For WooCommerce Subscriptions optimize the payment flow for subsequent subscription payments when authentication may be required by using the setup_future_usage
parameter for the first subscription payment
* Add - Allow customer to authenticate payment even if they are not charged right away for WooCommerce Subscriptions and Pre-Orders, for example for a WooCommerce Subscription that has a free trial
* Add - When an off-session payment requires authentication, create a link for customers to come back to the store to authenticate the payment
* Add - Send an email to WooCommerce Subscription and Pre-Orders customers who need to authenticate a payment that was automatically tried on their behalf
* Add - When an off-session payment requires authentication, send an email to the admin
* Add - Admin notice about SCA-readiness
* Fix - Avoid idempotency key errors for Pre-Orders
* Fix - Use unique anchor for link about checkout styling changes
Release Info
Developer | woothemes |
Plugin | WooCommerce Stripe Payment Gateway |
Version | 4.3.0 |
Comparing to | |
See all releases |
Code changes from version 4.2.5 to 4.3.0
- assets/js/stripe.js +16 -11
- assets/js/stripe.min.js +1 -1
- changelog.txt +10 -0
- includes/abstracts/abstract-wc-stripe-payment-gateway.php +153 -29
- includes/admin/class-wc-stripe-admin-notices.php +30 -2
- includes/class-wc-gateway-stripe.php +116 -58
- includes/class-wc-stripe-api.php +1 -1
- includes/class-wc-stripe-customer.php +11 -5
- includes/class-wc-stripe-helper.php +19 -0
- includes/class-wc-stripe-intent-controller.php +1 -1
- includes/class-wc-stripe-webhook-handler.php +42 -1
- includes/compat/class-wc-stripe-email-failed-authentication-retry.php +132 -0
- includes/compat/class-wc-stripe-email-failed-authentication.php +126 -0
- includes/compat/class-wc-stripe-email-failed-preorder-authentication.php +104 -0
- includes/compat/class-wc-stripe-email-failed-renewal-authentication.php +113 -0
- includes/compat/class-wc-stripe-pre-orders-compat.php +58 -40
- includes/compat/class-wc-stripe-subs-compat.php +123 -67
- languages/woocommerce-gateway-stripe.pot +239 -109
- readme.txt +12 -13
- templates/emails/failed-preorder-authentication.php +63 -0
- templates/emails/failed-renewal-authentication-requested.php +57 -0
- templates/emails/failed-renewal-authentication.php +17 -0
- templates/emails/plain/failed-preorder-authentication.php +29 -0
- templates/emails/plain/failed-renewal-authentication-requested.php +49 -0
- templates/emails/plain/failed-renewal-authentication.php +17 -0
- woocommerce-gateway-stripe.php +27 -4
@@ -709,30 +709,32 @@ jQuery( function( $ ) {
|
|
709 |
},
|
710 |
|
711 |
/**
|
712 |
-
* Handles changes in the hash in order to show a modal for PaymentIntent confirmations.
|
713 |
*
|
714 |
* Listens for `hashchange` events and checks for a hash in the following format:
|
715 |
* #confirm-pi-<intentClientSecret>:<successRedirectURL>
|
716 |
*
|
717 |
* If such a hash appears, the partials will be used to call `stripe.handleCardPayment`
|
718 |
-
* in order to allow customers to confirm an 3DS/SCA authorization.
|
|
|
719 |
*
|
720 |
* Those redirects/hashes are generated in `WC_Gateway_Stripe::process_payment`.
|
721 |
*/
|
722 |
onHashChange: function() {
|
723 |
-
var partials = window.location.hash.match( /^#?confirm-pi-([^:]+):(.+)$/ );
|
724 |
|
725 |
-
if ( ! partials ||
|
726 |
return;
|
727 |
}
|
728 |
|
729 |
-
var
|
730 |
-
var
|
|
|
731 |
|
732 |
// Cleanup the URL
|
733 |
window.location.hash = '';
|
734 |
|
735 |
-
wc_stripe_form.openIntentModal( intentClientSecret, redirectURL );
|
736 |
},
|
737 |
|
738 |
maybeConfirmIntent: function() {
|
@@ -743,7 +745,7 @@ jQuery( function( $ ) {
|
|
743 |
var intentSecret = $( '#stripe-intent-id' ).val();
|
744 |
var returnURL = $( '#stripe-intent-return' ).val();
|
745 |
|
746 |
-
wc_stripe_form.openIntentModal( intentSecret, returnURL, true );
|
747 |
},
|
748 |
|
749 |
/**
|
@@ -753,15 +755,18 @@ jQuery( function( $ ) {
|
|
753 |
* @param {string} redirectURL The URL to ping on fail or redirect to on success.
|
754 |
* @param {boolean} alwaysRedirect If set to true, an immediate redirect will happen no matter the result.
|
755 |
* If not, an error will be displayed on failure.
|
|
|
|
|
756 |
*/
|
757 |
-
openIntentModal: function( intentClientSecret, redirectURL, alwaysRedirect ) {
|
758 |
-
stripe
|
759 |
.then( function( response ) {
|
760 |
if ( response.error ) {
|
761 |
throw response.error;
|
762 |
}
|
763 |
|
764 |
-
|
|
|
765 |
return;
|
766 |
}
|
767 |
|
709 |
},
|
710 |
|
711 |
/**
|
712 |
+
* Handles changes in the hash in order to show a modal for PaymentIntent/SetupIntent confirmations.
|
713 |
*
|
714 |
* Listens for `hashchange` events and checks for a hash in the following format:
|
715 |
* #confirm-pi-<intentClientSecret>:<successRedirectURL>
|
716 |
*
|
717 |
* If such a hash appears, the partials will be used to call `stripe.handleCardPayment`
|
718 |
+
* in order to allow customers to confirm an 3DS/SCA authorization, or stripe.handleCardSetup if
|
719 |
+
* what needs to be confirmed is a SetupIntent.
|
720 |
*
|
721 |
* Those redirects/hashes are generated in `WC_Gateway_Stripe::process_payment`.
|
722 |
*/
|
723 |
onHashChange: function() {
|
724 |
+
var partials = window.location.hash.match( /^#?confirm-(pi|si)-([^:]+):(.+)$/ );
|
725 |
|
726 |
+
if ( ! partials || 4 > partials.length ) {
|
727 |
return;
|
728 |
}
|
729 |
|
730 |
+
var type = partials[1];
|
731 |
+
var intentClientSecret = partials[2];
|
732 |
+
var redirectURL = decodeURIComponent( partials[3] );
|
733 |
|
734 |
// Cleanup the URL
|
735 |
window.location.hash = '';
|
736 |
|
737 |
+
wc_stripe_form.openIntentModal( intentClientSecret, redirectURL, false, 'si' === type );
|
738 |
},
|
739 |
|
740 |
maybeConfirmIntent: function() {
|
745 |
var intentSecret = $( '#stripe-intent-id' ).val();
|
746 |
var returnURL = $( '#stripe-intent-return' ).val();
|
747 |
|
748 |
+
wc_stripe_form.openIntentModal( intentSecret, returnURL, true, false );
|
749 |
},
|
750 |
|
751 |
/**
|
755 |
* @param {string} redirectURL The URL to ping on fail or redirect to on success.
|
756 |
* @param {boolean} alwaysRedirect If set to true, an immediate redirect will happen no matter the result.
|
757 |
* If not, an error will be displayed on failure.
|
758 |
+
* @param {boolean} isSetupIntent If set to true, ameans that the flow is handling a Setup Intent.
|
759 |
+
* If false, it's a Payment Intent.
|
760 |
*/
|
761 |
+
openIntentModal: function( intentClientSecret, redirectURL, alwaysRedirect, isSetupIntent ) {
|
762 |
+
stripe[ isSetupIntent ? 'handleCardSetup' : 'handleCardPayment' ]( intentClientSecret )
|
763 |
.then( function( response ) {
|
764 |
if ( response.error ) {
|
765 |
throw response.error;
|
766 |
}
|
767 |
|
768 |
+
var intent = response[ isSetupIntent ? 'setupIntent' : 'paymentIntent' ];
|
769 |
+
if ( 'requires_capture' !== intent.status && 'succeeded' !== intent.status ) {
|
770 |
return;
|
771 |
}
|
772 |
|
@@ -1 +1 @@
|
|
1 |
-
jQuery(function(c){"use strict";try{var n=Stripe(wc_stripe_params.key)}catch(e){return void console.log(e)}var t,o,i,e=Object.keys(wc_stripe_params.elements_options).length?wc_stripe_params.elements_options:{},r=Object.keys(wc_stripe_params.sepa_elements_options).length?wc_stripe_params.sepa_elements_options:{},s=n.elements(e),a=s.create("iban",r),m={getAjaxURL:function(e){return wc_stripe_params.ajaxurl.toString().replace("%%endpoint%%","wc_stripe_"+e)},unmountElements:function(){"yes"===wc_stripe_params.inline_cc_form?t.unmount("#stripe-card-element"):(t.unmount("#stripe-card-element"),o.unmount("#stripe-exp-element"),i.unmount("#stripe-cvc-element"))},mountElements:function(){if(c("#stripe-card-element").length){if("yes"===wc_stripe_params.inline_cc_form)return t.mount("#stripe-card-element");t.mount("#stripe-card-element"),o.mount("#stripe-exp-element"),i.mount("#stripe-cvc-element")}},createElements:function(){var e={base:{iconColor:"#666EE8",color:"#31325F",fontSize:"15px","::placeholder":{color:"#CFD7E0"}}},r={focus:"focused",empty:"empty",invalid:"invalid"};e=wc_stripe_params.elements_styling?wc_stripe_params.elements_styling:e,r=wc_stripe_params.elements_classes?wc_stripe_params.elements_classes:r,"yes"===wc_stripe_params.inline_cc_form?(t=s.create("card",{style:e,hidePostalCode:!0})).addEventListener("change",function(e){m.onCCFormChange(),e.error&&c(document.body).trigger("stripeError",e)}):(t=s.create("cardNumber",{style:e,classes:r}),o=s.create("cardExpiry",{style:e,classes:r}),i=s.create("cardCvc",{style:e,classes:r}),t.addEventListener("change",function(e){m.onCCFormChange(),m.updateCardBrand(e.brand),e.error&&c(document.body).trigger("stripeError",e)}),o.addEventListener("change",function(e){m.onCCFormChange(),e.error&&c(document.body).trigger("stripeError",e)}),i.addEventListener("change",function(e){m.onCCFormChange(),e.error&&c(document.body).trigger("stripeError",e)})),"yes"===wc_stripe_params.is_checkout?c(document.body).on("updated_checkout",function(){t&&m.unmountElements(),m.mountElements(),c("#stripe-iban-element").length&&a.mount("#stripe-iban-element")}):(c("form#add_payment_method").length||c("form#order_review").length)&&(m.mountElements(),c("#stripe-iban-element").length&&a.mount("#stripe-iban-element"))},updateCardBrand:function(e){var r={visa:"stripe-visa-brand",mastercard:"stripe-mastercard-brand",amex:"stripe-amex-brand",discover:"stripe-discover-brand",diners:"stripe-diners-brand",jcb:"stripe-jcb-brand",unknown:"stripe-credit-card-brand"},t=c(".stripe-card-brand"),n="stripe-credit-card-brand";e in r&&(n=r[e]),c.each(r,function(e,r){t.removeClass(r)}),t.addClass(n)},init:function(){"yes"!==wc_stripe_params.is_change_payment_page&&"yes"!==wc_stripe_params.is_pay_for_order_page||c(document.body).trigger("wc-credit-card-form-init"),c("form.woocommerce-checkout").length&&(this.form=c("form.woocommerce-checkout")),c("form.woocommerce-checkout").on("checkout_place_order_stripe checkout_place_order_stripe_bancontact checkout_place_order_stripe_sofort checkout_place_order_stripe_giropay checkout_place_order_stripe_ideal checkout_place_order_stripe_alipay checkout_place_order_stripe_sepa",this.onSubmit),c("form#order_review").length&&(this.form=c("form#order_review")),c("form#order_review, form#add_payment_method").on("submit",this.onSubmit),c("form#add_payment_method").length&&(this.form=c("form#add_payment_method")),c("form.woocommerce-checkout").on("change",this.reset),c(document).on("stripeError",this.onError).on("checkout_error",this.reset),a.on("change",this.onSepaError),m.createElements(),window.addEventListener("hashchange",m.onHashChange),m.maybeConfirmIntent()},isStripeChosen:function(){return c("#payment_method_stripe, #payment_method_stripe_bancontact, #payment_method_stripe_sofort, #payment_method_stripe_giropay, #payment_method_stripe_ideal, #payment_method_stripe_alipay, #payment_method_stripe_sepa, #payment_method_stripe_eps, #payment_method_stripe_multibanco").is(":checked")||c("#payment_method_stripe").is(":checked")&&"new"===c('input[name="wc-stripe-payment-token"]:checked').val()||c("#payment_method_stripe_sepa").is(":checked")&&"new"===c('input[name="wc-stripe-payment-token"]:checked').val()},isStripeSaveCardChosen:function(){return c("#payment_method_stripe").is(":checked")&&c('input[name="wc-stripe-payment-token"]').is(":checked")&&"new"!==c('input[name="wc-stripe-payment-token"]:checked').val()||c("#payment_method_stripe_sepa").is(":checked")&&c('input[name="wc-stripe_sepa-payment-token"]').is(":checked")&&"new"!==c('input[name="wc-stripe_sepa-payment-token"]:checked').val()},isStripeCardChosen:function(){return c("#payment_method_stripe").is(":checked")},isBancontactChosen:function(){return c("#payment_method_stripe_bancontact").is(":checked")},isGiropayChosen:function(){return c("#payment_method_stripe_giropay").is(":checked")},isIdealChosen:function(){return c("#payment_method_stripe_ideal").is(":checked")},isSofortChosen:function(){return c("#payment_method_stripe_sofort").is(":checked")},isAlipayChosen:function(){return c("#payment_method_stripe_alipay").is(":checked")},isSepaChosen:function(){return c("#payment_method_stripe_sepa").is(":checked")},isP24Chosen:function(){return c("#payment_method_stripe_p24").is(":checked")},isEpsChosen:function(){return c("#payment_method_stripe_eps").is(":checked")},isMultibancoChosen:function(){return c("#payment_method_stripe_multibanco").is(":checked")},hasSource:function(){return 0<c("input.stripe-source").length},isMobile:function(){return!!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},block:function(){m.isMobile()||m.form.block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){m.form&&m.form.unblock()},getSelectedPaymentElement:function(){return c('.payment_methods input[name="payment_method"]:checked')},getOwnerDetails:function(){var e=c("#billing_first_name").length?c("#billing_first_name").val():wc_stripe_params.billing_first_name,r=c("#billing_last_name").length?c("#billing_last_name").val():wc_stripe_params.billing_last_name,t={name:"",address:{},email:"",phone:""};return t.name=e,t.name=e&&r?e+" "+r:c("#stripe-payment-data").data("full-name"),t.email=c("#billing_email").val(),t.phone=c("#billing_phone").val(),(void 0===t.phone||t.phone.length<=0)&&delete t.phone,(void 0===t.email||t.email.length<=0)&&(c("#stripe-payment-data").data("email").length?t.email=c("#stripe-payment-data").data("email"):delete t.email),(void 0===t.name||t.name.length<=0)&&delete t.name,t.address.line1=c("#billing_address_1").val()||wc_stripe_params.billing_address_1,t.address.line2=c("#billing_address_2").val()||wc_stripe_params.billing_address_2,t.address.state=c("#billing_state").val()||wc_stripe_params.billing_state,t.address.city=c("#billing_city").val()||wc_stripe_params.billing_city,t.address.postal_code=c("#billing_postcode").val()||wc_stripe_params.billing_postcode,t.address.country=c("#billing_country").val()||wc_stripe_params.billing_country,{owner:t}},createSource:function(){var e=m.getOwnerDetails();return m.isSepaChosen()?(e.currency=c("#stripe-sepa_debit-payment-data").data("currency"),e.mandate={notification_method:wc_stripe_params.sepa_mandate_notification},e.type="sepa_debit",n.createSource(a,e).then(m.sourceResponse)):n.createSource(t,e).then(m.sourceResponse)},sourceResponse:function(e){if(e.error)return c(document.body).trigger("stripeError",e);m.reset(),m.form.append(c('<input type="hidden" />').addClass("stripe-source").attr("name","stripe_source").val(e.source.id)),c("form#add_payment_method").length&&c(m.form).off("submit",m.form.onSubmit),m.form.submit()},onSubmit:function(){return!m.isStripeChosen()||(!(!m.isStripeSaveCardChosen()&&!m.hasSource())||(!!(m.isBancontactChosen()||m.isGiropayChosen()||m.isIdealChosen()||m.isAlipayChosen()||m.isSofortChosen()||m.isP24Chosen()||m.isEpsChosen()||m.isMultibancoChosen())||(m.block(),m.createSource(),!1)))},onCCFormChange:function(){m.reset()},reset:function(){c(".wc-stripe-error, .stripe-source").remove()},onSepaError:function(e){var r=m.getSelectedPaymentElement().parents("li").eq(0).find(".stripe-source-errors");if(!e.error)return c(r).html("");console.log(e.error.message),c(r).html('<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li /></ul>'),c(r).find("li").text(e.error.message)},onError:function(e,r){var t,n=r.error.message,o=m.getSelectedPaymentElement().closest("li"),i=o.find(".woocommerce-SavedPaymentMethods-tokenInput");if(i.length){var s=i.filter(":checked");t=s.closest(".woocommerce-SavedPaymentMethods-new").length?c("#wc-stripe-cc-form .stripe-source-errors"):s.closest("li").find(".stripe-source-errors")}else t=o.find(".stripe-source-errors");if(m.isSepaChosen()&&"invalid_owner_name"===r.error.code&&wc_stripe_params.hasOwnProperty(r.error.code)){var a='<ul class="woocommerce-error"><li /></ul>';return a.find("li").text(wc_stripe_params[r.error.code]),m.submitError(a)}"email_invalid"===r.error.code?n=wc_stripe_params.email_invalid:"invalid_request_error"!==r.error.type&&"api_connection_error"!==r.error.type&&"api_error"!==r.error.type&&"authentication_error"!==r.error.type&&"rate_limit_error"!==r.error.type||(n=wc_stripe_params.invalid_request_error),"card_error"===r.error.type&&wc_stripe_params.hasOwnProperty(r.error.code)&&(n=wc_stripe_params[r.error.code]),"validation_error"===r.error.type&&wc_stripe_params.hasOwnProperty(r.error.code)&&(n=wc_stripe_params[r.error.code]),m.reset(),c(".woocommerce-NoticeGroup-checkout").remove(),console.log(r.error.message),c(t).html('<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li /></ul>'),c(t).find("li").text(n),c(".wc-stripe-error").length&&c("html, body").animate({scrollTop:c(".wc-stripe-error").offset().top-200},200),m.unblock(),c.unblockUI()},submitError:function(e){c(".woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message").remove(),m.form.prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">'+e+"</div>"),m.form.removeClass("processing").unblock(),m.form.find(".input-text, select, input:checkbox").blur();var r="";c("#add_payment_method").length&&(r=c("#add_payment_method")),c("#order_review").length&&(r=c("#order_review")),c("form.checkout").length&&(r=c("form.checkout")),r.length&&c("html, body").animate({scrollTop:r.offset().top-100},500),c(document.body).trigger("checkout_error"),m.unblock()},onHashChange:function(){var e=window.location.hash.match(/^#?confirm-pi-([^:]+):(.+)$/);if(e&&!(e.length<3)){var r=e[1],t=decodeURIComponent(e[2]);window.location.hash="",m.openIntentModal(r,t)}},maybeConfirmIntent:function(){if(c("#stripe-intent-id").length&&c("#stripe-intent-return").length){var e=c("#stripe-intent-id").val(),r=c("#stripe-intent-return").val();m.openIntentModal(e,r,!0)}},openIntentModal:function(e,r,t){n.handleCardPayment(e).then(function(e){if(e.error)throw e.error;"requires_capture"!==e.paymentIntent.status&&"succeeded"!==e.paymentIntent.status||(window.location=r)}).catch(function(e){if(t)return window.location=r;c(document.body).trigger("stripeError",{error:e}),m.form&&m.form.removeClass("processing"),c.get(r+"&is_ajax")})}};m.init()});
|
1 |
+
jQuery(function(c){"use strict";try{var o=Stripe(wc_stripe_params.key)}catch(e){return void console.log(e)}var t,n,i,e=Object.keys(wc_stripe_params.elements_options).length?wc_stripe_params.elements_options:{},r=Object.keys(wc_stripe_params.sepa_elements_options).length?wc_stripe_params.sepa_elements_options:{},s=o.elements(e),a=s.create("iban",r),m={getAjaxURL:function(e){return wc_stripe_params.ajaxurl.toString().replace("%%endpoint%%","wc_stripe_"+e)},unmountElements:function(){"yes"===wc_stripe_params.inline_cc_form?t.unmount("#stripe-card-element"):(t.unmount("#stripe-card-element"),n.unmount("#stripe-exp-element"),i.unmount("#stripe-cvc-element"))},mountElements:function(){if(c("#stripe-card-element").length){if("yes"===wc_stripe_params.inline_cc_form)return t.mount("#stripe-card-element");t.mount("#stripe-card-element"),n.mount("#stripe-exp-element"),i.mount("#stripe-cvc-element")}},createElements:function(){var e={base:{iconColor:"#666EE8",color:"#31325F",fontSize:"15px","::placeholder":{color:"#CFD7E0"}}},r={focus:"focused",empty:"empty",invalid:"invalid"};e=wc_stripe_params.elements_styling?wc_stripe_params.elements_styling:e,r=wc_stripe_params.elements_classes?wc_stripe_params.elements_classes:r,"yes"===wc_stripe_params.inline_cc_form?(t=s.create("card",{style:e,hidePostalCode:!0})).addEventListener("change",function(e){m.onCCFormChange(),e.error&&c(document.body).trigger("stripeError",e)}):(t=s.create("cardNumber",{style:e,classes:r}),n=s.create("cardExpiry",{style:e,classes:r}),i=s.create("cardCvc",{style:e,classes:r}),t.addEventListener("change",function(e){m.onCCFormChange(),m.updateCardBrand(e.brand),e.error&&c(document.body).trigger("stripeError",e)}),n.addEventListener("change",function(e){m.onCCFormChange(),e.error&&c(document.body).trigger("stripeError",e)}),i.addEventListener("change",function(e){m.onCCFormChange(),e.error&&c(document.body).trigger("stripeError",e)})),"yes"===wc_stripe_params.is_checkout?c(document.body).on("updated_checkout",function(){t&&m.unmountElements(),m.mountElements(),c("#stripe-iban-element").length&&a.mount("#stripe-iban-element")}):(c("form#add_payment_method").length||c("form#order_review").length)&&(m.mountElements(),c("#stripe-iban-element").length&&a.mount("#stripe-iban-element"))},updateCardBrand:function(e){var r={visa:"stripe-visa-brand",mastercard:"stripe-mastercard-brand",amex:"stripe-amex-brand",discover:"stripe-discover-brand",diners:"stripe-diners-brand",jcb:"stripe-jcb-brand",unknown:"stripe-credit-card-brand"},t=c(".stripe-card-brand"),n="stripe-credit-card-brand";e in r&&(n=r[e]),c.each(r,function(e,r){t.removeClass(r)}),t.addClass(n)},init:function(){"yes"!==wc_stripe_params.is_change_payment_page&&"yes"!==wc_stripe_params.is_pay_for_order_page||c(document.body).trigger("wc-credit-card-form-init"),c("form.woocommerce-checkout").length&&(this.form=c("form.woocommerce-checkout")),c("form.woocommerce-checkout").on("checkout_place_order_stripe checkout_place_order_stripe_bancontact checkout_place_order_stripe_sofort checkout_place_order_stripe_giropay checkout_place_order_stripe_ideal checkout_place_order_stripe_alipay checkout_place_order_stripe_sepa",this.onSubmit),c("form#order_review").length&&(this.form=c("form#order_review")),c("form#order_review, form#add_payment_method").on("submit",this.onSubmit),c("form#add_payment_method").length&&(this.form=c("form#add_payment_method")),c("form.woocommerce-checkout").on("change",this.reset),c(document).on("stripeError",this.onError).on("checkout_error",this.reset),a.on("change",this.onSepaError),m.createElements(),window.addEventListener("hashchange",m.onHashChange),m.maybeConfirmIntent()},isStripeChosen:function(){return c("#payment_method_stripe, #payment_method_stripe_bancontact, #payment_method_stripe_sofort, #payment_method_stripe_giropay, #payment_method_stripe_ideal, #payment_method_stripe_alipay, #payment_method_stripe_sepa, #payment_method_stripe_eps, #payment_method_stripe_multibanco").is(":checked")||c("#payment_method_stripe").is(":checked")&&"new"===c('input[name="wc-stripe-payment-token"]:checked').val()||c("#payment_method_stripe_sepa").is(":checked")&&"new"===c('input[name="wc-stripe-payment-token"]:checked').val()},isStripeSaveCardChosen:function(){return c("#payment_method_stripe").is(":checked")&&c('input[name="wc-stripe-payment-token"]').is(":checked")&&"new"!==c('input[name="wc-stripe-payment-token"]:checked').val()||c("#payment_method_stripe_sepa").is(":checked")&&c('input[name="wc-stripe_sepa-payment-token"]').is(":checked")&&"new"!==c('input[name="wc-stripe_sepa-payment-token"]:checked').val()},isStripeCardChosen:function(){return c("#payment_method_stripe").is(":checked")},isBancontactChosen:function(){return c("#payment_method_stripe_bancontact").is(":checked")},isGiropayChosen:function(){return c("#payment_method_stripe_giropay").is(":checked")},isIdealChosen:function(){return c("#payment_method_stripe_ideal").is(":checked")},isSofortChosen:function(){return c("#payment_method_stripe_sofort").is(":checked")},isAlipayChosen:function(){return c("#payment_method_stripe_alipay").is(":checked")},isSepaChosen:function(){return c("#payment_method_stripe_sepa").is(":checked")},isP24Chosen:function(){return c("#payment_method_stripe_p24").is(":checked")},isEpsChosen:function(){return c("#payment_method_stripe_eps").is(":checked")},isMultibancoChosen:function(){return c("#payment_method_stripe_multibanco").is(":checked")},hasSource:function(){return 0<c("input.stripe-source").length},isMobile:function(){return!!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},block:function(){m.isMobile()||m.form.block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){m.form&&m.form.unblock()},getSelectedPaymentElement:function(){return c('.payment_methods input[name="payment_method"]:checked')},getOwnerDetails:function(){var e=c("#billing_first_name").length?c("#billing_first_name").val():wc_stripe_params.billing_first_name,r=c("#billing_last_name").length?c("#billing_last_name").val():wc_stripe_params.billing_last_name,t={name:"",address:{},email:"",phone:""};return t.name=e,t.name=e&&r?e+" "+r:c("#stripe-payment-data").data("full-name"),t.email=c("#billing_email").val(),t.phone=c("#billing_phone").val(),(void 0===t.phone||t.phone.length<=0)&&delete t.phone,(void 0===t.email||t.email.length<=0)&&(c("#stripe-payment-data").data("email").length?t.email=c("#stripe-payment-data").data("email"):delete t.email),(void 0===t.name||t.name.length<=0)&&delete t.name,t.address.line1=c("#billing_address_1").val()||wc_stripe_params.billing_address_1,t.address.line2=c("#billing_address_2").val()||wc_stripe_params.billing_address_2,t.address.state=c("#billing_state").val()||wc_stripe_params.billing_state,t.address.city=c("#billing_city").val()||wc_stripe_params.billing_city,t.address.postal_code=c("#billing_postcode").val()||wc_stripe_params.billing_postcode,t.address.country=c("#billing_country").val()||wc_stripe_params.billing_country,{owner:t}},createSource:function(){var e=m.getOwnerDetails();return m.isSepaChosen()?(e.currency=c("#stripe-sepa_debit-payment-data").data("currency"),e.mandate={notification_method:wc_stripe_params.sepa_mandate_notification},e.type="sepa_debit",o.createSource(a,e).then(m.sourceResponse)):o.createSource(t,e).then(m.sourceResponse)},sourceResponse:function(e){if(e.error)return c(document.body).trigger("stripeError",e);m.reset(),m.form.append(c('<input type="hidden" />').addClass("stripe-source").attr("name","stripe_source").val(e.source.id)),c("form#add_payment_method").length&&c(m.form).off("submit",m.form.onSubmit),m.form.submit()},onSubmit:function(){return!m.isStripeChosen()||(!(!m.isStripeSaveCardChosen()&&!m.hasSource())||(!!(m.isBancontactChosen()||m.isGiropayChosen()||m.isIdealChosen()||m.isAlipayChosen()||m.isSofortChosen()||m.isP24Chosen()||m.isEpsChosen()||m.isMultibancoChosen())||(m.block(),m.createSource(),!1)))},onCCFormChange:function(){m.reset()},reset:function(){c(".wc-stripe-error, .stripe-source").remove()},onSepaError:function(e){var r=m.getSelectedPaymentElement().parents("li").eq(0).find(".stripe-source-errors");if(!e.error)return c(r).html("");console.log(e.error.message),c(r).html('<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li /></ul>'),c(r).find("li").text(e.error.message)},onError:function(e,r){var t,n=r.error.message,o=m.getSelectedPaymentElement().closest("li"),i=o.find(".woocommerce-SavedPaymentMethods-tokenInput");if(i.length){var s=i.filter(":checked");t=s.closest(".woocommerce-SavedPaymentMethods-new").length?c("#wc-stripe-cc-form .stripe-source-errors"):s.closest("li").find(".stripe-source-errors")}else t=o.find(".stripe-source-errors");if(m.isSepaChosen()&&"invalid_owner_name"===r.error.code&&wc_stripe_params.hasOwnProperty(r.error.code)){var a='<ul class="woocommerce-error"><li /></ul>';return a.find("li").text(wc_stripe_params[r.error.code]),m.submitError(a)}"email_invalid"===r.error.code?n=wc_stripe_params.email_invalid:"invalid_request_error"!==r.error.type&&"api_connection_error"!==r.error.type&&"api_error"!==r.error.type&&"authentication_error"!==r.error.type&&"rate_limit_error"!==r.error.type||(n=wc_stripe_params.invalid_request_error),"card_error"===r.error.type&&wc_stripe_params.hasOwnProperty(r.error.code)&&(n=wc_stripe_params[r.error.code]),"validation_error"===r.error.type&&wc_stripe_params.hasOwnProperty(r.error.code)&&(n=wc_stripe_params[r.error.code]),m.reset(),c(".woocommerce-NoticeGroup-checkout").remove(),console.log(r.error.message),c(t).html('<ul class="woocommerce_error woocommerce-error wc-stripe-error"><li /></ul>'),c(t).find("li").text(n),c(".wc-stripe-error").length&&c("html, body").animate({scrollTop:c(".wc-stripe-error").offset().top-200},200),m.unblock(),c.unblockUI()},submitError:function(e){c(".woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message").remove(),m.form.prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">'+e+"</div>"),m.form.removeClass("processing").unblock(),m.form.find(".input-text, select, input:checkbox").blur();var r="";c("#add_payment_method").length&&(r=c("#add_payment_method")),c("#order_review").length&&(r=c("#order_review")),c("form.checkout").length&&(r=c("form.checkout")),r.length&&c("html, body").animate({scrollTop:r.offset().top-100},500),c(document.body).trigger("checkout_error"),m.unblock()},onHashChange:function(){var e=window.location.hash.match(/^#?confirm-(pi|si)-([^:]+):(.+)$/);if(e&&!(e.length<4)){var r=e[1],t=e[2],n=decodeURIComponent(e[3]);window.location.hash="",m.openIntentModal(t,n,!1,"si"===r)}},maybeConfirmIntent:function(){if(c("#stripe-intent-id").length&&c("#stripe-intent-return").length){var e=c("#stripe-intent-id").val(),r=c("#stripe-intent-return").val();m.openIntentModal(e,r,!0,!1)}},openIntentModal:function(e,t,r,n){o[n?"handleCardSetup":"handleCardPayment"](e).then(function(e){if(e.error)throw e.error;var r=e[n?"setupIntent":"paymentIntent"];"requires_capture"!==r.status&&"succeeded"!==r.status||(window.location=t)}).catch(function(e){if(r)return window.location=t;c(document.body).trigger("stripeError",{error:e}),m.form&&m.form.removeClass("processing"),c.get(t+"&is_ajax")})}};m.init()});
|
@@ -1,5 +1,15 @@
|
|
1 |
*** Changelog ***
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
= 4.2.5 - 2019-10-02 =
|
4 |
* Fix - WooCommerce Subscriptions that use only the Stripe customer ID can again be renewed
|
5 |
|
1 |
*** Changelog ***
|
2 |
|
3 |
+
= 4.3.0 2019-10-17 =
|
4 |
+
* Add - For WooCommerce Subscriptions optimize the payment flow for subsequent subscription payments when authentication may be required by using the `setup_future_usage` parameter for the first subscription payment
|
5 |
+
* Add - Allow customer to authenticate payment even if they are not charged right away for WooCommerce Subscriptions and Pre-Orders, for example for a WooCommerce Subscription that has a free trial
|
6 |
+
* Add - When an off-session payment requires authentication, create a link for customers to come back to the store to authenticate the payment
|
7 |
+
* Add - Send an email to WooCommerce Subscription and Pre-Orders customers who need to authenticate a payment that was automatically tried on their behalf
|
8 |
+
* Add - When an off-session payment requires authentication, send an email to the admin
|
9 |
+
* Add - Admin notice about SCA-readiness
|
10 |
+
* Fix - Avoid idempotency key errors for Pre-Orders
|
11 |
+
* Fix - Use unique anchor for link about checkout styling changes
|
12 |
+
|
13 |
= 4.2.5 - 2019-10-02 =
|
14 |
* Fix - WooCommerce Subscriptions that use only the Stripe customer ID can again be renewed
|
15 |
|
@@ -72,21 +72,6 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
|
|
72 |
);
|
73 |
}
|
74 |
|
75 |
-
/**
|
76 |
-
* Checks to see if error is of invalid request
|
77 |
-
* error and source is already consumed.
|
78 |
-
*
|
79 |
-
* @since 4.1.0
|
80 |
-
* @param array $error
|
81 |
-
*/
|
82 |
-
public function is_source_already_consumed_error( $error ) {
|
83 |
-
return (
|
84 |
-
$error &&
|
85 |
-
'invalid_request_error' === $error->type &&
|
86 |
-
preg_match( '/The reusable source you provided is consumed because it was previously charged without being attached to a customer or was detached from a customer. To charge a reusable source multiple time you must attach it to a customer first./i', $error->message )
|
87 |
-
);
|
88 |
-
}
|
89 |
-
|
90 |
/**
|
91 |
* Checks to see if error is of invalid request
|
92 |
* error and it is no such customer.
|
@@ -548,7 +533,11 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
|
|
548 |
* @return bool
|
549 |
*/
|
550 |
public function is_prepaid_card( $source_object ) {
|
551 |
-
return (
|
|
|
|
|
|
|
|
|
552 |
}
|
553 |
|
554 |
/**
|
@@ -589,7 +578,6 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
|
|
589 |
*/
|
590 |
public function prepare_source( $user_id, $force_save_source = false ) {
|
591 |
$customer = new WC_Stripe_Customer( $user_id );
|
592 |
-
$set_customer = true;
|
593 |
$force_save_source = apply_filters( 'wc_stripe_force_save_source', $force_save_source, $customer );
|
594 |
$source_object = '';
|
595 |
$source_id = '';
|
@@ -644,16 +632,15 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
|
|
644 |
throw new WC_Stripe_Exception( print_r( $response, true ), $response->error->message );
|
645 |
}
|
646 |
} else {
|
647 |
-
$set_customer = false;
|
648 |
$source_id = $stripe_token;
|
649 |
$is_token = true;
|
650 |
}
|
651 |
}
|
652 |
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
$customer_id = $customer->get_id()
|
657 |
}
|
658 |
|
659 |
if ( empty( $source_object ) && ! $is_token ) {
|
@@ -1021,13 +1008,13 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
|
|
1021 |
}
|
1022 |
|
1023 |
/**
|
1024 |
-
*
|
1025 |
*
|
1026 |
* @param WC_Order $order The order that is being paid for.
|
1027 |
* @param object $prepared_source The source that is used for the payment.
|
1028 |
-
* @return
|
1029 |
*/
|
1030 |
-
public function
|
1031 |
// The request for a charge contains metadata for the intent.
|
1032 |
$full_request = $this->generate_payment_request( $order, $prepared_source );
|
1033 |
|
@@ -1037,7 +1024,6 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
|
|
1037 |
'currency' => strtolower( WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->get_order_currency() : $order->get_currency() ),
|
1038 |
'description' => $full_request['description'],
|
1039 |
'metadata' => $full_request['metadata'],
|
1040 |
-
'statement_descriptor' => $full_request['statement_descriptor'],
|
1041 |
'capture_method' => ( 'true' === $full_request['capture'] ) ? 'automatic' : 'manual',
|
1042 |
'payment_method_types' => array(
|
1043 |
'card',
|
@@ -1048,6 +1034,31 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
|
|
1048 |
$request['customer'] = $prepared_source->customer;
|
1049 |
}
|
1050 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1051 |
// Create an intent that awaits an action.
|
1052 |
$intent = WC_Stripe_API::request( $request, 'payment_intents' );
|
1053 |
if ( ! empty( $intent->error ) ) {
|
@@ -1167,11 +1178,22 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
|
|
1167 |
$intent_id = $order->get_meta( '_stripe_intent_id' );
|
1168 |
}
|
1169 |
|
1170 |
-
if (
|
1171 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1172 |
}
|
1173 |
|
1174 |
-
return
|
1175 |
}
|
1176 |
|
1177 |
/**
|
@@ -1208,4 +1230,106 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
|
|
1208 |
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->id : $order->get_id();
|
1209 |
delete_transient( 'wc_stripe_processing_intent_' . $order_id );
|
1210 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1211 |
}
|
72 |
);
|
73 |
}
|
74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
/**
|
76 |
* Checks to see if error is of invalid request
|
77 |
* error and it is no such customer.
|
533 |
* @return bool
|
534 |
*/
|
535 |
public function is_prepaid_card( $source_object ) {
|
536 |
+
return (
|
537 |
+
$source_object
|
538 |
+
&& ( 'token' === $source_object->object || 'source' === $source_object->object )
|
539 |
+
&& 'prepaid' === $source_object->card->funding
|
540 |
+
);
|
541 |
}
|
542 |
|
543 |
/**
|
578 |
*/
|
579 |
public function prepare_source( $user_id, $force_save_source = false ) {
|
580 |
$customer = new WC_Stripe_Customer( $user_id );
|
|
|
581 |
$force_save_source = apply_filters( 'wc_stripe_force_save_source', $force_save_source, $customer );
|
582 |
$source_object = '';
|
583 |
$source_id = '';
|
632 |
throw new WC_Stripe_Exception( print_r( $response, true ), $response->error->message );
|
633 |
}
|
634 |
} else {
|
|
|
635 |
$source_id = $stripe_token;
|
636 |
$is_token = true;
|
637 |
}
|
638 |
}
|
639 |
|
640 |
+
$customer_id = $customer->get_id();
|
641 |
+
if ( ! $customer_id ) {
|
642 |
+
$customer->set_id( $customer->create_customer() );
|
643 |
+
$customer_id = $customer->get_id();
|
644 |
}
|
645 |
|
646 |
if ( empty( $source_object ) && ! $is_token ) {
|
1008 |
}
|
1009 |
|
1010 |
/**
|
1011 |
+
* Generates the request when creating a new payment intent.
|
1012 |
*
|
1013 |
* @param WC_Order $order The order that is being paid for.
|
1014 |
* @param object $prepared_source The source that is used for the payment.
|
1015 |
+
* @return array The arguments for the request.
|
1016 |
*/
|
1017 |
+
public function generate_create_intent_request( $order, $prepared_source ) {
|
1018 |
// The request for a charge contains metadata for the intent.
|
1019 |
$full_request = $this->generate_payment_request( $order, $prepared_source );
|
1020 |
|
1024 |
'currency' => strtolower( WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->get_order_currency() : $order->get_currency() ),
|
1025 |
'description' => $full_request['description'],
|
1026 |
'metadata' => $full_request['metadata'],
|
|
|
1027 |
'capture_method' => ( 'true' === $full_request['capture'] ) ? 'automatic' : 'manual',
|
1028 |
'payment_method_types' => array(
|
1029 |
'card',
|
1034 |
$request['customer'] = $prepared_source->customer;
|
1035 |
}
|
1036 |
|
1037 |
+
if ( isset( $full_request['statement_descriptor'] ) ) {
|
1038 |
+
$request['statement_descriptor'] = $full_request['statement_descriptor'];
|
1039 |
+
}
|
1040 |
+
|
1041 |
+
/**
|
1042 |
+
* Filter the return value of the WC_Payment_Gateway_CC::generate_create_intent_request.
|
1043 |
+
*
|
1044 |
+
* @since 3.1.0
|
1045 |
+
* @param array $request
|
1046 |
+
* @param WC_Order $order
|
1047 |
+
* @param object $source
|
1048 |
+
*/
|
1049 |
+
return apply_filters( 'wc_stripe_generate_create_intent_request', $request, $order, $prepared_source );
|
1050 |
+
}
|
1051 |
+
|
1052 |
+
/**
|
1053 |
+
* Create a new PaymentIntent.
|
1054 |
+
*
|
1055 |
+
* @param WC_Order $order The order that is being paid for.
|
1056 |
+
* @param object $prepared_source The source that is used for the payment.
|
1057 |
+
* @return object An intent or an error.
|
1058 |
+
*/
|
1059 |
+
public function create_intent( $order, $prepared_source ) {
|
1060 |
+
$request = $this->generate_create_intent_request( $order, $prepared_source );
|
1061 |
+
|
1062 |
// Create an intent that awaits an action.
|
1063 |
$intent = WC_Stripe_API::request( $request, 'payment_intents' );
|
1064 |
if ( ! empty( $intent->error ) ) {
|
1178 |
$intent_id = $order->get_meta( '_stripe_intent_id' );
|
1179 |
}
|
1180 |
|
1181 |
+
if ( $intent_id ) {
|
1182 |
+
return WC_Stripe_API::request( array(), "payment_intents/$intent_id", 'GET' );
|
1183 |
+
}
|
1184 |
+
|
1185 |
+
// The order doesn't have a payment intent, but it may have a setup intent.
|
1186 |
+
if ( WC_Stripe_Helper::is_wc_lt( '3.0' ) ) {
|
1187 |
+
$intent_id = get_post_meta( $order_id, '_stripe_setup_intent', true );
|
1188 |
+
} else {
|
1189 |
+
$intent_id = $order->get_meta( '_stripe_setup_intent' );
|
1190 |
+
}
|
1191 |
+
|
1192 |
+
if ( $intent_id ) {
|
1193 |
+
return WC_Stripe_API::request( array(), "setup_intents/$intent_id", 'GET' );
|
1194 |
}
|
1195 |
|
1196 |
+
return false;
|
1197 |
}
|
1198 |
|
1199 |
/**
|
1230 |
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->id : $order->get_id();
|
1231 |
delete_transient( 'wc_stripe_processing_intent_' . $order_id );
|
1232 |
}
|
1233 |
+
|
1234 |
+
/**
|
1235 |
+
* Given a response from Stripe, check if it's a card error where authentication is required
|
1236 |
+
* to complete the payment.
|
1237 |
+
*
|
1238 |
+
* @param object $response The response from Stripe.
|
1239 |
+
* @return boolean Whether or not it's a 'authentication_required' error
|
1240 |
+
*/
|
1241 |
+
public function is_authentication_required_for_payment( $response ) {
|
1242 |
+
return ( ! empty( $response->error ) && 'authentication_required' === $response->error->code )
|
1243 |
+
|| ( ! empty( $response->last_payment_error ) && 'authentication_required' === $response->last_payment_error->code );
|
1244 |
+
}
|
1245 |
+
|
1246 |
+
/**
|
1247 |
+
* Creates a SetupIntent for future payments, and saves it to the order.
|
1248 |
+
*
|
1249 |
+
* @param WC_Order $order The ID of the (free/pre- order).
|
1250 |
+
* @param object $prepared_source The source, entered/chosen by the customer.
|
1251 |
+
* @return string The client secret of the intent, used for confirmation in JS.
|
1252 |
+
*/
|
1253 |
+
public function setup_intent( $order, $prepared_source ) {
|
1254 |
+
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->id : $order->get_id();
|
1255 |
+
$setup_intent = WC_Stripe_API::request( array(
|
1256 |
+
'payment_method' => $prepared_source->source,
|
1257 |
+
'customer' => $prepared_source->customer,
|
1258 |
+
'confirm' => 'true',
|
1259 |
+
), 'setup_intents' );
|
1260 |
+
|
1261 |
+
if ( is_wp_error( $setup_intent ) ) {
|
1262 |
+
WC_Stripe_Logger::log( "Unable to create SetupIntent for Order #$order_id: " . print_r( $setup_intent, true ) );
|
1263 |
+
} elseif ( 'requires_action' === $setup_intent->status ) {
|
1264 |
+
if ( WC_Stripe_Helper::is_wc_lt( '3.0' ) ) {
|
1265 |
+
update_post_meta( $order_id, '_stripe_setup_intent', $setup_intent->id );
|
1266 |
+
} else {
|
1267 |
+
$order->update_meta_data( '_stripe_setup_intent', $setup_intent->id );
|
1268 |
+
$order->save();
|
1269 |
+
}
|
1270 |
+
|
1271 |
+
return $setup_intent->client_secret;
|
1272 |
+
}
|
1273 |
+
}
|
1274 |
+
|
1275 |
+
/**
|
1276 |
+
* Create and confirm a new PaymentIntent.
|
1277 |
+
*
|
1278 |
+
* @param WC_Order $order The order that is being paid for.
|
1279 |
+
* @param object $prepared_source The source that is used for the payment.
|
1280 |
+
* @param float $amount The amount to charge. If not specified, it will be read from the order.
|
1281 |
+
* @return object An intent or an error.
|
1282 |
+
*/
|
1283 |
+
public function create_and_confirm_intent_for_off_session( $order, $prepared_source, $amount = NULL ) {
|
1284 |
+
// The request for a charge contains metadata for the intent.
|
1285 |
+
$full_request = $this->generate_payment_request( $order, $prepared_source );
|
1286 |
+
|
1287 |
+
$request = array(
|
1288 |
+
'amount' => $amount ? WC_Stripe_Helper::get_stripe_amount( $amount, $full_request['currency'] ) : $full_request['amount'],
|
1289 |
+
'currency' => $full_request['currency'],
|
1290 |
+
'description' => $full_request['description'],
|
1291 |
+
'metadata' => $full_request['metadata'],
|
1292 |
+
'payment_method_types' => array(
|
1293 |
+
'card',
|
1294 |
+
),
|
1295 |
+
'off_session' => 'true',
|
1296 |
+
'confirm' => 'true',
|
1297 |
+
'confirmation_method' => 'automatic',
|
1298 |
+
);
|
1299 |
+
|
1300 |
+
if ( isset( $full_request['statement_descriptor'] ) ) {
|
1301 |
+
$request['statement_descriptor'] = $full_request['statement_descriptor'];
|
1302 |
+
}
|
1303 |
+
|
1304 |
+
if ( isset( $full_request['customer'] ) ) {
|
1305 |
+
$request['customer'] = $full_request['customer'];
|
1306 |
+
}
|
1307 |
+
|
1308 |
+
if ( isset( $full_request['source'] ) ) {
|
1309 |
+
$request['source'] = $full_request['source'];
|
1310 |
+
}
|
1311 |
+
|
1312 |
+
$intent = WC_Stripe_API::request( $request, 'payment_intents' );
|
1313 |
+
$is_authentication_required = $this->is_authentication_required_for_payment( $intent );
|
1314 |
+
|
1315 |
+
if ( ! empty( $intent->error ) && ! $is_authentication_required ) {
|
1316 |
+
return $intent;
|
1317 |
+
}
|
1318 |
+
|
1319 |
+
$intent_id = ( ! empty( $intent->error )
|
1320 |
+
? $intent->error->payment_intent->id
|
1321 |
+
: $intent->id
|
1322 |
+
);
|
1323 |
+
$payment_intent = ( ! empty( $intent->error )
|
1324 |
+
? $intent->error->payment_intent
|
1325 |
+
: $intent
|
1326 |
+
);
|
1327 |
+
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->id : $order->get_id();
|
1328 |
+
WC_Stripe_Logger::log( "Stripe PaymentIntent $intent_id initiated for order $order_id" );
|
1329 |
+
|
1330 |
+
// Save the intent ID to the order.
|
1331 |
+
$this->save_intent_to_order( $order, $payment_intent );
|
1332 |
+
|
1333 |
+
return $intent;
|
1334 |
+
}
|
1335 |
}
|
@@ -23,6 +23,7 @@ class WC_Stripe_Admin_Notices {
|
|
23 |
public function __construct() {
|
24 |
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
25 |
add_action( 'wp_loaded', array( $this, 'hide_notices' ) );
|
|
|
26 |
}
|
27 |
|
28 |
/**
|
@@ -106,6 +107,7 @@ class WC_Stripe_Admin_Notices {
|
|
106 |
$show_phpver_notice = get_option( 'wc_stripe_show_phpver_notice' );
|
107 |
$show_wcver_notice = get_option( 'wc_stripe_show_wcver_notice' );
|
108 |
$show_curl_notice = get_option( 'wc_stripe_show_curl_notice' );
|
|
|
109 |
$options = get_option( 'woocommerce_stripe_settings' );
|
110 |
$testmode = ( isset( $options['testmode'] ) && 'yes' === $options['testmode'] ) ? true : false;
|
111 |
$test_pub_key = isset( $options['test_publishable_key'] ) ? $options['test_publishable_key'] : '';
|
@@ -126,9 +128,9 @@ class WC_Stripe_Admin_Notices {
|
|
126 |
|
127 |
if ( empty( $show_style_notice ) ) {
|
128 |
/* translators: 1) int version 2) int version */
|
129 |
-
$message = __( 'WooCommerce Stripe - We recently made changes to Stripe that may impact the appearance of your checkout. If your checkout has changed unexpectedly, please follow these <a href="https://docs.woocommerce.com/document/stripe/#
|
130 |
|
131 |
-
$this->add_admin_notice( 'style', '
|
132 |
|
133 |
return;
|
134 |
}
|
@@ -199,6 +201,10 @@ class WC_Stripe_Admin_Notices {
|
|
199 |
$this->add_admin_notice( 'ssl', 'notice notice-warning', sprintf( __( 'Stripe is enabled, but a SSL certificate is not detected. Your checkout may not be secure! Please ensure your server has a valid <a href="%1$s" target="_blank">SSL certificate</a>', 'woocommerce-gateway-stripe' ), 'https://en.wikipedia.org/wiki/Transport_Layer_Security' ), true );
|
200 |
}
|
201 |
}
|
|
|
|
|
|
|
|
|
202 |
}
|
203 |
}
|
204 |
|
@@ -292,6 +298,9 @@ class WC_Stripe_Admin_Notices {
|
|
292 |
case 'SOFORT':
|
293 |
update_option( 'wc_stripe_show_sofort_notice', 'no' );
|
294 |
break;
|
|
|
|
|
|
|
295 |
}
|
296 |
}
|
297 |
}
|
@@ -310,6 +319,25 @@ class WC_Stripe_Admin_Notices {
|
|
310 |
|
311 |
return admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=' . $section_slug );
|
312 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
313 |
}
|
314 |
|
315 |
new WC_Stripe_Admin_Notices();
|
23 |
public function __construct() {
|
24 |
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
25 |
add_action( 'wp_loaded', array( $this, 'hide_notices' ) );
|
26 |
+
add_action( 'woocommerce_stripe_updated', array( $this, 'stripe_updated' ) );
|
27 |
}
|
28 |
|
29 |
/**
|
107 |
$show_phpver_notice = get_option( 'wc_stripe_show_phpver_notice' );
|
108 |
$show_wcver_notice = get_option( 'wc_stripe_show_wcver_notice' );
|
109 |
$show_curl_notice = get_option( 'wc_stripe_show_curl_notice' );
|
110 |
+
$show_sca_notice = get_option( 'wc_stripe_show_sca_notice' );
|
111 |
$options = get_option( 'woocommerce_stripe_settings' );
|
112 |
$testmode = ( isset( $options['testmode'] ) && 'yes' === $options['testmode'] ) ? true : false;
|
113 |
$test_pub_key = isset( $options['test_publishable_key'] ) ? $options['test_publishable_key'] : '';
|
128 |
|
129 |
if ( empty( $show_style_notice ) ) {
|
130 |
/* translators: 1) int version 2) int version */
|
131 |
+
$message = __( 'WooCommerce Stripe - We recently made changes to Stripe that may impact the appearance of your checkout. If your checkout has changed unexpectedly, please follow these <a href="https://docs.woocommerce.com/document/stripe/#styling" target="_blank">instructions</a> to fix.', 'woocommerce-gateway-stripe' );
|
132 |
|
133 |
+
$this->add_admin_notice( 'style', 'notice notice-warning', $message, true );
|
134 |
|
135 |
return;
|
136 |
}
|
201 |
$this->add_admin_notice( 'ssl', 'notice notice-warning', sprintf( __( 'Stripe is enabled, but a SSL certificate is not detected. Your checkout may not be secure! Please ensure your server has a valid <a href="%1$s" target="_blank">SSL certificate</a>', 'woocommerce-gateway-stripe' ), 'https://en.wikipedia.org/wiki/Transport_Layer_Security' ), true );
|
202 |
}
|
203 |
}
|
204 |
+
|
205 |
+
if ( empty( $show_sca_notice ) ) {
|
206 |
+
$this->add_admin_notice( 'sca', 'notice notice-success', sprintf( __( 'Stripe is now ready for Strong Customer Authentication (SCA) and 3D Secure 2! <a href="%1$s" target="_blank">Read about SCA</a>', 'woocommerce-gateway-stripe' ), 'https://woocommerce.com/posts/introducing-strong-customer-authentication-sca/' ), true );
|
207 |
+
}
|
208 |
}
|
209 |
}
|
210 |
|
298 |
case 'SOFORT':
|
299 |
update_option( 'wc_stripe_show_sofort_notice', 'no' );
|
300 |
break;
|
301 |
+
case 'sca':
|
302 |
+
update_option( 'wc_stripe_show_sca_notice', 'no' );
|
303 |
+
break;
|
304 |
}
|
305 |
}
|
306 |
}
|
319 |
|
320 |
return admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=' . $section_slug );
|
321 |
}
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Saves options in order to hide notices based on the gateway's version.
|
325 |
+
*
|
326 |
+
* @since 4.3.0
|
327 |
+
*/
|
328 |
+
public function stripe_updated() {
|
329 |
+
$previous_version = get_option( 'wc_stripe_version' );
|
330 |
+
|
331 |
+
// Only show the style notice if the plugin was installed and older than 4.1.4.
|
332 |
+
if ( empty( $previous_version ) || version_compare( $previous_version, '4.1.4', 'ge' ) ) {
|
333 |
+
update_option( 'wc_stripe_show_style_notice', 'no' );
|
334 |
+
}
|
335 |
+
|
336 |
+
// Only show the SCA notice on pre-4.3.0 installs.
|
337 |
+
if ( empty( $previous_version ) || version_compare( $previous_version, '4.3.0', 'ge' ) ) {
|
338 |
+
update_option( 'wc_stripe_show_sca_notice', 'no' );
|
339 |
+
}
|
340 |
+
}
|
341 |
}
|
342 |
|
343 |
new WC_Stripe_Admin_Notices();
|
@@ -139,6 +139,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
139 |
add_action( 'woocommerce_account_view-order_endpoint', array( $this, 'check_intent_status_on_order_page' ), 1 );
|
140 |
add_filter( 'woocommerce_payment_successful_result', array( $this, 'modify_successful_payment_result' ), 99999, 2 );
|
141 |
add_action( 'set_logged_in_cookie', array( $this, 'set_cookie_on_current_request' ) );
|
|
|
142 |
|
143 |
if ( WC_Stripe_Helper::is_pre_orders_exists() ) {
|
144 |
$this->pre_orders = new WC_Stripe_Pre_Orders_Compat();
|
@@ -248,29 +249,17 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
248 |
}
|
249 |
|
250 |
if ( is_add_payment_method_page() ) {
|
251 |
-
$pay_button_text = __( 'Add Card', 'woocommerce-gateway-stripe' );
|
252 |
-
$total = '';
|
253 |
$firstname = $user->user_firstname;
|
254 |
$lastname = $user->user_lastname;
|
255 |
-
|
256 |
-
} elseif ( function_exists( 'wcs_order_contains_subscription' ) && isset( $_GET['change_payment_method'] ) ) { // wpcs: csrf ok.
|
257 |
-
$pay_button_text = __( 'Change Payment Method', 'woocommerce-gateway-stripe' );
|
258 |
-
$total = '';
|
259 |
-
} else {
|
260 |
-
$pay_button_text = '';
|
261 |
}
|
262 |
|
263 |
ob_start();
|
264 |
|
265 |
echo '<div
|
266 |
id="stripe-payment-data"
|
267 |
-
data-panel-label="' . esc_attr( $pay_button_text ) . '"
|
268 |
data-email="' . esc_attr( $user_email ) . '"
|
269 |
-
data-amount="' . esc_attr( WC_Stripe_Helper::get_stripe_amount( $total ) ) . '"
|
270 |
-
data-name="' . esc_attr( $this->statement_descriptor ) . '"
|
271 |
data-full-name="' . esc_attr( $firstname . ' ' . $lastname ) . '"
|
272 |
data-currency="' . esc_attr( strtolower( get_woocommerce_currency() ) ) . '"
|
273 |
-
data-allow-remember-me="' . esc_attr( apply_filters( 'wc_stripe_allow_remember_me', true ) ? 'true' : 'false' ) . '"
|
274 |
>';
|
275 |
|
276 |
if ( $this->testmode ) {
|
@@ -383,7 +372,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
383 |
* @version 4.0.0
|
384 |
*/
|
385 |
public function payment_scripts() {
|
386 |
-
if ( ! is_product() && ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() && ! isset( $_GET['change_payment_method'] ) ) { // wpcs: csrf ok.
|
387 |
return;
|
388 |
}
|
389 |
|
@@ -476,23 +465,6 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
476 |
wp_enqueue_script( 'woocommerce_stripe' );
|
477 |
}
|
478 |
|
479 |
-
/**
|
480 |
-
* Creates a new WC_Stripe_Customer if the visitor chooses to.
|
481 |
-
*
|
482 |
-
* @since 4.2.0
|
483 |
-
* @param WC_Order $order The order that is being created.
|
484 |
-
*/
|
485 |
-
public function maybe_create_customer( $order ) {
|
486 |
-
// This comes from the create account checkbox in the checkout page.
|
487 |
-
if ( empty( $_POST['createaccount'] ) ) { // wpcs: csrf ok.
|
488 |
-
return;
|
489 |
-
}
|
490 |
-
|
491 |
-
$new_customer_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->customer_user : $order->get_customer_id();
|
492 |
-
$new_stripe_customer = new WC_Stripe_Customer( $new_customer_id );
|
493 |
-
$new_stripe_customer->create_customer();
|
494 |
-
}
|
495 |
-
|
496 |
/**
|
497 |
* Checks if a source object represents a prepaid credit card and
|
498 |
* throws an exception if it is one, but that is not allowed.
|
@@ -554,20 +526,33 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
554 |
* Completes an order without a positive value.
|
555 |
*
|
556 |
* @since 4.2.0
|
557 |
-
* @param WC_Order $order
|
558 |
-
* @
|
|
|
|
|
559 |
*/
|
560 |
-
public function complete_free_order( $order ) {
|
561 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
562 |
|
563 |
// Remove cart.
|
564 |
WC()->cart->empty_cart();
|
565 |
|
|
|
|
|
566 |
// Return thank you page redirect.
|
567 |
-
return
|
568 |
-
'result' => 'success',
|
569 |
-
'redirect' => $this->get_return_url( $order ),
|
570 |
-
);
|
571 |
}
|
572 |
|
573 |
/**
|
@@ -593,8 +578,6 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
593 |
return $this->pre_orders->process_pre_order( $order_id );
|
594 |
}
|
595 |
|
596 |
-
$this->maybe_create_customer( $order );
|
597 |
-
|
598 |
$prepared_source = $this->prepare_source( get_current_user_id(), $force_save_source );
|
599 |
|
600 |
$this->maybe_disallow_prepaid_card( $prepared_source );
|
@@ -602,7 +585,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
602 |
$this->save_source_to_order( $order, $prepared_source );
|
603 |
|
604 |
if ( 0 >= $order->get_total() ) {
|
605 |
-
return $this->complete_free_order( $order );
|
606 |
}
|
607 |
|
608 |
// This will throw exception if not valid.
|
@@ -611,6 +594,10 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
611 |
WC_Stripe_Logger::log( "Info: Begin processing payment for order $order_id for the amount of {$order->get_total()}" );
|
612 |
|
613 |
$intent = $this->get_intent_from_order( $order );
|
|
|
|
|
|
|
|
|
614 |
if ( $intent ) {
|
615 |
$intent = $this->update_existing_intent( $intent, $order, $prepared_source );
|
616 |
} else {
|
@@ -658,9 +645,9 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
658 |
*/
|
659 |
|
660 |
return array(
|
661 |
-
'result'
|
662 |
-
'redirect'
|
663 |
-
'
|
664 |
);
|
665 |
}
|
666 |
}
|
@@ -670,7 +657,9 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
670 |
$this->process_response( $response, $order );
|
671 |
|
672 |
// Remove cart.
|
673 |
-
WC()->cart
|
|
|
|
|
674 |
|
675 |
// Unlock the order.
|
676 |
$this->unlock_order_payment( $order );
|
@@ -836,9 +825,16 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
836 |
return $gateways;
|
837 |
}
|
838 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
839 |
add_filter( 'woocommerce_checkout_show_terms', '__return_false' );
|
840 |
add_filter( 'woocommerce_pay_order_button_html', '__return_false' );
|
841 |
-
add_filter( 'woocommerce_available_payment_gateways',
|
842 |
add_filter( 'woocommerce_no_available_payment_methods_message', array( $this, 'change_no_available_methods_message' ) );
|
843 |
add_action( 'woocommerce_pay_order_after_submit', array( $this, 'render_payment_intent_inputs' ) );
|
844 |
|
@@ -856,14 +852,52 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
856 |
return wpautop( __( "Almost there!\n\nYour order has already been created, the only thing that still needs to be done is for you to authorize the payment with your bank.", 'woocommerce-gateway-stripe' ) );
|
857 |
}
|
858 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
859 |
/**
|
860 |
* Renders hidden inputs on the "Pay for Order" page in order to let Stripe handle PaymentIntents.
|
861 |
*
|
|
|
|
|
|
|
862 |
* @since 4.2
|
863 |
*/
|
864 |
-
public function render_payment_intent_inputs() {
|
865 |
-
|
866 |
-
|
|
|
|
|
|
|
|
|
867 |
|
868 |
$verification_url = add_query_arg(
|
869 |
array(
|
@@ -875,7 +909,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
875 |
WC_AJAX::get_endpoint( 'wc_stripe_verify_intent' )
|
876 |
);
|
877 |
|
878 |
-
echo '<input type="hidden" id="stripe-intent-id" value="' . esc_attr( $
|
879 |
echo '<input type="hidden" id="stripe-intent-return" value="' . esc_attr( $verification_url ) . '" />';
|
880 |
}
|
881 |
|
@@ -917,7 +951,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
917 |
/**
|
918 |
* Attached to `woocommerce_payment_successful_result` with a late priority,
|
919 |
* this method will combine the "naturally" generated redirect URL from
|
920 |
-
* WooCommerce and a payment intent secret into a hash, which contains both
|
921 |
* the secret, and a proper URL, which will confirm whether the intent succeeded.
|
922 |
*
|
923 |
* @since 4.2.0
|
@@ -926,8 +960,8 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
926 |
* @return array
|
927 |
*/
|
928 |
public function modify_successful_payment_result( $result, $order_id ) {
|
929 |
-
|
930 |
-
|
931 |
return $result;
|
932 |
}
|
933 |
|
@@ -941,8 +975,11 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
941 |
WC_AJAX::get_endpoint( 'wc_stripe_verify_intent' )
|
942 |
);
|
943 |
|
944 |
-
|
945 |
-
|
|
|
|
|
|
|
946 |
|
947 |
return array(
|
948 |
'result' => 'success',
|
@@ -990,7 +1027,14 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
990 |
return;
|
991 |
}
|
992 |
|
993 |
-
if ( '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
994 |
// Proceed with the payment completion.
|
995 |
$this->process_response( end( $intent->charges->data ), $order );
|
996 |
} else if ( 'requires_payment_method' === $intent->status ) {
|
@@ -1015,12 +1059,26 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
|
|
1015 |
}
|
1016 |
|
1017 |
// Load the right message and update the status.
|
1018 |
-
$status_message = ( $intent->last_payment_error )
|
1019 |
/* translators: 1) The error message that was received from Stripe. */
|
1020 |
? sprintf( __( 'Stripe SCA authentication failed. Reason: %s', 'woocommerce-gateway-stripe' ), $intent->last_payment_error->message )
|
1021 |
: __( 'Stripe SCA authentication failed.', 'woocommerce-gateway-stripe' );
|
1022 |
$order->update_status( 'failed', $status_message );
|
|
|
1023 |
|
1024 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1025 |
}
|
1026 |
}
|
139 |
add_action( 'woocommerce_account_view-order_endpoint', array( $this, 'check_intent_status_on_order_page' ), 1 );
|
140 |
add_filter( 'woocommerce_payment_successful_result', array( $this, 'modify_successful_payment_result' ), 99999, 2 );
|
141 |
add_action( 'set_logged_in_cookie', array( $this, 'set_cookie_on_current_request' ) );
|
142 |
+
add_filter( 'woocommerce_get_checkout_payment_url', array( $this, 'get_checkout_payment_url' ), 10, 2 );
|
143 |
|
144 |
if ( WC_Stripe_Helper::is_pre_orders_exists() ) {
|
145 |
$this->pre_orders = new WC_Stripe_Pre_Orders_Compat();
|
249 |
}
|
250 |
|
251 |
if ( is_add_payment_method_page() ) {
|
|
|
|
|
252 |
$firstname = $user->user_firstname;
|
253 |
$lastname = $user->user_lastname;
|
|
|
|
|
|
|
|
|
|
|
|
|
254 |
}
|
255 |
|
256 |
ob_start();
|
257 |
|
258 |
echo '<div
|
259 |
id="stripe-payment-data"
|
|
|
260 |
data-email="' . esc_attr( $user_email ) . '"
|
|
|
|
|
261 |
data-full-name="' . esc_attr( $firstname . ' ' . $lastname ) . '"
|
262 |
data-currency="' . esc_attr( strtolower( get_woocommerce_currency() ) ) . '"
|
|
|
263 |
>';
|
264 |
|
265 |
if ( $this->testmode ) {
|
372 |
* @version 4.0.0
|
373 |
*/
|
374 |
public function payment_scripts() {
|
375 |
+
if ( ! is_product() && ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() && ! isset( $_GET['change_payment_method'] ) || ( is_order_received_page() ) ) { // wpcs: csrf ok.
|
376 |
return;
|
377 |
}
|
378 |
|
465 |
wp_enqueue_script( 'woocommerce_stripe' );
|
466 |
}
|
467 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
468 |
/**
|
469 |
* Checks if a source object represents a prepaid credit card and
|
470 |
* throws an exception if it is one, but that is not allowed.
|
526 |
* Completes an order without a positive value.
|
527 |
*
|
528 |
* @since 4.2.0
|
529 |
+
* @param WC_Order $order The order to complete.
|
530 |
+
* @param WC_Order $prepared_source Payment source and customer data.
|
531 |
+
* @param boolean $force_save_source Whether the payment source must be saved, like when dealing with a Subscription setup.
|
532 |
+
* @return array Redirection data for `process_payment`.
|
533 |
*/
|
534 |
+
public function complete_free_order( $order, $prepared_source, $force_save_source ) {
|
535 |
+
$response = array(
|
536 |
+
'result' => 'success',
|
537 |
+
'redirect' => $this->get_return_url( $order ),
|
538 |
+
);
|
539 |
+
|
540 |
+
if ( $force_save_source ) {
|
541 |
+
$intent_secret = $this->setup_intent( $order, $prepared_source );
|
542 |
+
|
543 |
+
if ( ! empty( $intent_secret ) ) {
|
544 |
+
$response['setup_intent_secret'] = $intent_secret;
|
545 |
+
return $response;
|
546 |
+
}
|
547 |
+
}
|
548 |
|
549 |
// Remove cart.
|
550 |
WC()->cart->empty_cart();
|
551 |
|
552 |
+
$order->payment_complete();
|
553 |
+
|
554 |
// Return thank you page redirect.
|
555 |
+
return $response;
|
|
|
|
|
|
|
556 |
}
|
557 |
|
558 |
/**
|
578 |
return $this->pre_orders->process_pre_order( $order_id );
|
579 |
}
|
580 |
|
|
|
|
|
581 |
$prepared_source = $this->prepare_source( get_current_user_id(), $force_save_source );
|
582 |
|
583 |
$this->maybe_disallow_prepaid_card( $prepared_source );
|
585 |
$this->save_source_to_order( $order, $prepared_source );
|
586 |
|
587 |
if ( 0 >= $order->get_total() ) {
|
588 |
+
return $this->complete_free_order( $order, $prepared_source, $force_save_source );
|
589 |
}
|
590 |
|
591 |
// This will throw exception if not valid.
|
594 |
WC_Stripe_Logger::log( "Info: Begin processing payment for order $order_id for the amount of {$order->get_total()}" );
|
595 |
|
596 |
$intent = $this->get_intent_from_order( $order );
|
597 |
+
if ( isset( $intent->object ) && 'setup_intent' === $intent->object ) {
|
598 |
+
$intent = false; // This function can only deal with *payment* intents
|
599 |
+
}
|
600 |
+
|
601 |
if ( $intent ) {
|
602 |
$intent = $this->update_existing_intent( $intent, $order, $prepared_source );
|
603 |
} else {
|
645 |
*/
|
646 |
|
647 |
return array(
|
648 |
+
'result' => 'success',
|
649 |
+
'redirect' => $this->get_return_url( $order ),
|
650 |
+
'payment_intent_secret' => $intent->client_secret,
|
651 |
);
|
652 |
}
|
653 |
}
|
657 |
$this->process_response( $response, $order );
|
658 |
|
659 |
// Remove cart.
|
660 |
+
if ( isset( WC()->cart ) ) {
|
661 |
+
WC()->cart->empty_cart();
|
662 |
+
}
|
663 |
|
664 |
// Unlock the order.
|
665 |
$this->unlock_order_payment( $order );
|
825 |
return $gateways;
|
826 |
}
|
827 |
|
828 |
+
try {
|
829 |
+
$this->prepare_intent_for_order_pay_page();
|
830 |
+
} catch ( WC_Stripe_Exception $e ) {
|
831 |
+
// Just show the full order pay page if there was a problem preparing the Payment Intent
|
832 |
+
return $gateways;
|
833 |
+
}
|
834 |
+
|
835 |
add_filter( 'woocommerce_checkout_show_terms', '__return_false' );
|
836 |
add_filter( 'woocommerce_pay_order_button_html', '__return_false' );
|
837 |
+
add_filter( 'woocommerce_available_payment_gateways', '__return_empty_array' );
|
838 |
add_filter( 'woocommerce_no_available_payment_methods_message', array( $this, 'change_no_available_methods_message' ) );
|
839 |
add_action( 'woocommerce_pay_order_after_submit', array( $this, 'render_payment_intent_inputs' ) );
|
840 |
|
852 |
return wpautop( __( "Almost there!\n\nYour order has already been created, the only thing that still needs to be done is for you to authorize the payment with your bank.", 'woocommerce-gateway-stripe' ) );
|
853 |
}
|
854 |
|
855 |
+
/**
|
856 |
+
* Prepares the Payment Intent for it to be completed in the "Pay for Order" page.
|
857 |
+
*
|
858 |
+
* @param WC_Order|null $order Order object, or null to get the order from the "order-pay" URL parameter
|
859 |
+
*
|
860 |
+
* @throws WC_Stripe_Exception
|
861 |
+
* @since 4.3
|
862 |
+
*/
|
863 |
+
public function prepare_intent_for_order_pay_page( $order = null ) {
|
864 |
+
if ( ! isset( $order ) || empty( $order ) ) {
|
865 |
+
$order = wc_get_order( absint( get_query_var( 'order-pay' ) ) );
|
866 |
+
}
|
867 |
+
$intent = $this->get_intent_from_order( $order );
|
868 |
+
|
869 |
+
if ( ! $intent ) {
|
870 |
+
throw new WC_Stripe_Exception( 'Payment Intent not found', __( 'Payment Intent not found for order #' . $order->get_id(), 'woocommerce-gateway-stripe' ) );
|
871 |
+
}
|
872 |
+
|
873 |
+
if ( 'requires_payment_method' === $intent->status && isset( $intent->last_payment_error )
|
874 |
+
&& 'authentication_required' === $intent->last_payment_error->code ) {
|
875 |
+
$intent = WC_Stripe_API::request( array(
|
876 |
+
'payment_method' => $intent->last_payment_error->source->id,
|
877 |
+
), 'payment_intents/' . $intent->id . '/confirm' );
|
878 |
+
if ( isset( $intent->error ) ) {
|
879 |
+
throw new WC_Stripe_Exception( print_r( $intent, true ), $intent->error->message );
|
880 |
+
}
|
881 |
+
}
|
882 |
+
|
883 |
+
$this->order_pay_intent = $intent;
|
884 |
+
}
|
885 |
+
|
886 |
/**
|
887 |
* Renders hidden inputs on the "Pay for Order" page in order to let Stripe handle PaymentIntents.
|
888 |
*
|
889 |
+
* @param WC_Order|null $order Order object, or null to get the order from the "order-pay" URL parameter
|
890 |
+
*
|
891 |
+
* @throws WC_Stripe_Exception
|
892 |
* @since 4.2
|
893 |
*/
|
894 |
+
public function render_payment_intent_inputs( $order = null ) {
|
895 |
+
if ( ! isset( $order ) || empty( $order ) ) {
|
896 |
+
$order = wc_get_order( absint( get_query_var( 'order-pay' ) ) );
|
897 |
+
}
|
898 |
+
if ( ! isset( $this->order_pay_intent ) ) {
|
899 |
+
$this->prepare_intent_for_order_pay_page( $order );
|
900 |
+
}
|
901 |
|
902 |
$verification_url = add_query_arg(
|
903 |
array(
|
909 |
WC_AJAX::get_endpoint( 'wc_stripe_verify_intent' )
|
910 |
);
|
911 |
|
912 |
+
echo '<input type="hidden" id="stripe-intent-id" value="' . esc_attr( $this->order_pay_intent->client_secret ) . '" />';
|
913 |
echo '<input type="hidden" id="stripe-intent-return" value="' . esc_attr( $verification_url ) . '" />';
|
914 |
}
|
915 |
|
951 |
/**
|
952 |
* Attached to `woocommerce_payment_successful_result` with a late priority,
|
953 |
* this method will combine the "naturally" generated redirect URL from
|
954 |
+
* WooCommerce and a payment/setup intent secret into a hash, which contains both
|
955 |
* the secret, and a proper URL, which will confirm whether the intent succeeded.
|
956 |
*
|
957 |
* @since 4.2.0
|
960 |
* @return array
|
961 |
*/
|
962 |
public function modify_successful_payment_result( $result, $order_id ) {
|
963 |
+
if ( ! isset( $result['payment_intent_secret'] ) && ! isset( $result['setup_intent_secret'] ) ) {
|
964 |
+
// Only redirects with intents need to be modified.
|
965 |
return $result;
|
966 |
}
|
967 |
|
975 |
WC_AJAX::get_endpoint( 'wc_stripe_verify_intent' )
|
976 |
);
|
977 |
|
978 |
+
if ( isset( $result['payment_intent_secret'] ) ) {
|
979 |
+
$redirect = sprintf( '#confirm-pi-%s:%s', $result['payment_intent_secret'], rawurlencode( $verification_url ) );
|
980 |
+
} else if ( isset( $result['setup_intent_secret'] ) ) {
|
981 |
+
$redirect = sprintf( '#confirm-si-%s:%s', $result['setup_intent_secret'], rawurlencode( $verification_url ) );
|
982 |
+
}
|
983 |
|
984 |
return array(
|
985 |
'result' => 'success',
|
1027 |
return;
|
1028 |
}
|
1029 |
|
1030 |
+
if ( 'setup_intent' === $intent->object && 'succeeded' === $intent->status ) {
|
1031 |
+
WC()->cart->empty_cart();
|
1032 |
+
if ( WC_Stripe_Helper::is_pre_orders_exists() && WC_Pre_Orders_Order::order_contains_pre_order( $order ) ) {
|
1033 |
+
WC_Pre_Orders_Order::mark_order_as_pre_ordered( $order );
|
1034 |
+
} else {
|
1035 |
+
$order->payment_complete();
|
1036 |
+
}
|
1037 |
+
} else if ( 'succeeded' === $intent->status || 'requires_capture' === $intent->status ) {
|
1038 |
// Proceed with the payment completion.
|
1039 |
$this->process_response( end( $intent->charges->data ), $order );
|
1040 |
} else if ( 'requires_payment_method' === $intent->status ) {
|
1059 |
}
|
1060 |
|
1061 |
// Load the right message and update the status.
|
1062 |
+
$status_message = isset( $intent->last_payment_error )
|
1063 |
/* translators: 1) The error message that was received from Stripe. */
|
1064 |
? sprintf( __( 'Stripe SCA authentication failed. Reason: %s', 'woocommerce-gateway-stripe' ), $intent->last_payment_error->message )
|
1065 |
: __( 'Stripe SCA authentication failed.', 'woocommerce-gateway-stripe' );
|
1066 |
$order->update_status( 'failed', $status_message );
|
1067 |
+
}
|
1068 |
|
1069 |
+
/**
|
1070 |
+
* Preserves the "wc-stripe-confirmation" URL parameter so the user can complete the SCA authentication after logging in.
|
1071 |
+
*
|
1072 |
+
* @param string $pay_url Current computed checkout URL for the given order.
|
1073 |
+
* @param WC_Order $order Order object.
|
1074 |
+
*
|
1075 |
+
* @return string Checkout URL for the given order.
|
1076 |
+
*/
|
1077 |
+
public function get_checkout_payment_url( $pay_url, $order ) {
|
1078 |
+
global $wp;
|
1079 |
+
if ( isset( $_GET['wc-stripe-confirmation'] ) && isset( $wp->query_vars['order-pay'] ) && $wp->query_vars['order-pay'] == $order->get_id() ) {
|
1080 |
+
$pay_url = add_query_arg( 'wc-stripe-confirmation', 1, $pay_url );
|
1081 |
+
}
|
1082 |
+
return $pay_url;
|
1083 |
}
|
1084 |
}
|
@@ -14,7 +14,7 @@ class WC_Stripe_API {
|
|
14 |
* Stripe API Endpoint
|
15 |
*/
|
16 |
const ENDPOINT = 'https://api.stripe.com/v1/';
|
17 |
-
const STRIPE_API_VERSION = '2019-
|
18 |
|
19 |
/**
|
20 |
* Secret API Key.
|
14 |
* Stripe API Endpoint
|
15 |
*/
|
16 |
const ENDPOINT = 'https://api.stripe.com/v1/';
|
17 |
+
const STRIPE_API_VERSION = '2019-09-09';
|
18 |
|
19 |
/**
|
20 |
* Secret API Key.
|
@@ -116,16 +116,23 @@ class WC_Stripe_Customer {
|
|
116 |
$billing_last_name = get_user_meta( $user->ID, 'last_name', true );
|
117 |
}
|
118 |
|
119 |
-
|
|
|
120 |
|
121 |
$defaults = array(
|
122 |
'email' => $user->user_email,
|
123 |
'description' => $description,
|
124 |
);
|
125 |
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
$defaults = array(
|
127 |
'email' => $billing_email,
|
128 |
-
'description' =>
|
129 |
);
|
130 |
}
|
131 |
|
@@ -171,10 +178,9 @@ class WC_Stripe_Customer {
|
|
171 |
/**
|
172 |
* Add a source for this stripe customer.
|
173 |
* @param string $source_id
|
174 |
-
* @param bool $retry
|
175 |
* @return WP_Error|int
|
176 |
*/
|
177 |
-
public function add_source( $source_id
|
178 |
if ( ! $this->get_id() ) {
|
179 |
$this->set_id( $this->create_customer() );
|
180 |
}
|
@@ -195,7 +201,7 @@ class WC_Stripe_Customer {
|
|
195 |
if ( $this->is_no_such_customer_error( $response->error ) ) {
|
196 |
delete_user_meta( $this->get_user_id(), '_stripe_customer_id' );
|
197 |
$this->create_customer();
|
198 |
-
return $this->add_source( $source_id
|
199 |
} else {
|
200 |
return $response;
|
201 |
}
|
116 |
$billing_last_name = get_user_meta( $user->ID, 'last_name', true );
|
117 |
}
|
118 |
|
119 |
+
// translators: %1$s First name, %2$s Second name, %3$s Username.
|
120 |
+
$description = sprintf( __( 'Name: %1$s %2$s, Username: %s', 'woocommerce-gateway-stripe' ), $billing_first_name, $billing_last_name, $user->user_login );
|
121 |
|
122 |
$defaults = array(
|
123 |
'email' => $user->user_email,
|
124 |
'description' => $description,
|
125 |
);
|
126 |
} else {
|
127 |
+
$billing_first_name = isset( $_POST['billing_first_name'] ) ? filter_var( wp_unslash( $_POST['billing_first_name'] ), FILTER_SANITIZE_STRING ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
|
128 |
+
$billing_last_name = isset( $_POST['billing_last_name'] ) ? filter_var( wp_unslash( $_POST['billing_last_name'] ), FILTER_SANITIZE_STRING ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
|
129 |
+
|
130 |
+
// translators: %1$s First name, %2$s Second name.
|
131 |
+
$description = sprintf( __( 'Name: %1$s %2$s, Guest', 'woocommerce-gateway-stripe' ), $billing_first_name, $billing_last_name );
|
132 |
+
|
133 |
$defaults = array(
|
134 |
'email' => $billing_email,
|
135 |
+
'description' => $description,
|
136 |
);
|
137 |
}
|
138 |
|
178 |
/**
|
179 |
* Add a source for this stripe customer.
|
180 |
* @param string $source_id
|
|
|
181 |
* @return WP_Error|int
|
182 |
*/
|
183 |
+
public function add_source( $source_id ) {
|
184 |
if ( ! $this->get_id() ) {
|
185 |
$this->set_id( $this->create_customer() );
|
186 |
}
|
201 |
if ( $this->is_no_such_customer_error( $response->error ) ) {
|
202 |
delete_user_meta( $this->get_user_id(), '_stripe_customer_id' );
|
203 |
$this->create_customer();
|
204 |
+
return $this->add_source( $source_id );
|
205 |
} else {
|
206 |
return $response;
|
207 |
}
|
@@ -453,6 +453,25 @@ class WC_Stripe_Helper {
|
|
453 |
return false;
|
454 |
}
|
455 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
456 |
/**
|
457 |
* Sanitize statement descriptor text.
|
458 |
*
|
453 |
return false;
|
454 |
}
|
455 |
|
456 |
+
/**
|
457 |
+
* Gets the order by Stripe SetupIntent ID.
|
458 |
+
*
|
459 |
+
* @since 4.3
|
460 |
+
* @param string $intent_id The ID of the intent.
|
461 |
+
* @return WC_Order|bool Either an order or false when not found.
|
462 |
+
*/
|
463 |
+
public static function get_order_by_setup_intent_id( $intent_id ) {
|
464 |
+
global $wpdb;
|
465 |
+
|
466 |
+
$order_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT ID FROM $wpdb->posts as posts LEFT JOIN $wpdb->postmeta as meta ON posts.ID = meta.post_id WHERE meta.meta_value = %s AND meta.meta_key = %s", $intent_id, '_stripe_setup_intent' ) );
|
467 |
+
|
468 |
+
if ( ! empty( $order_id ) ) {
|
469 |
+
return wc_get_order( $order_id );
|
470 |
+
}
|
471 |
+
|
472 |
+
return false;
|
473 |
+
}
|
474 |
+
|
475 |
/**
|
476 |
* Sanitize statement descriptor text.
|
477 |
*
|
@@ -92,7 +92,7 @@ class WC_Stripe_Intent_Controller {
|
|
92 |
wc_add_notice( esc_html( $message ), 'error' );
|
93 |
|
94 |
$redirect_url = $woocommerce->cart->is_empty()
|
95 |
-
? get_permalink( woocommerce_get_page_id( 'shop' ) )
|
96 |
: wc_get_checkout_url();
|
97 |
|
98 |
$this->handle_error( $e, $redirect_url );
|
92 |
wc_add_notice( esc_html( $message ), 'error' );
|
93 |
|
94 |
$redirect_url = $woocommerce->cart->is_empty()
|
95 |
+
? get_permalink( WC_Stripe_Helper::is_wc_lt( '3.0' ) ? woocommerce_get_page_id( 'shop' ) : wc_get_page_id( 'shop' ) )
|
96 |
: wc_get_checkout_url();
|
97 |
|
98 |
$this->handle_error( $e, $redirect_url );
|
@@ -81,7 +81,6 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
|
|
81 |
*
|
82 |
* @since 4.0.0
|
83 |
* @version 4.0.0
|
84 |
-
* @todo Implement proper webhook signature validation. Ref https://stripe.com/docs/webhooks#signatures
|
85 |
* @param string $request_headers The request headers from Stripe.
|
86 |
* @param string $request_body The request body from Stripe.
|
87 |
* @return bool
|
@@ -693,6 +692,43 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
|
|
693 |
$this->unlock_order_payment( $order );
|
694 |
}
|
695 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
696 |
/**
|
697 |
* Processes the incoming webhook.
|
698 |
*
|
@@ -744,6 +780,11 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
|
|
744 |
case 'payment_intent.payment_failed':
|
745 |
case 'payment_intent.amount_capturable_updated':
|
746 |
$this->process_payment_intent_success( $notification );
|
|
|
|
|
|
|
|
|
|
|
747 |
|
748 |
}
|
749 |
}
|
81 |
*
|
82 |
* @since 4.0.0
|
83 |
* @version 4.0.0
|
|
|
84 |
* @param string $request_headers The request headers from Stripe.
|
85 |
* @param string $request_body The request body from Stripe.
|
86 |
* @return bool
|
692 |
$this->unlock_order_payment( $order );
|
693 |
}
|
694 |
|
695 |
+
public function process_setup_intent( $notification ) {
|
696 |
+
$intent = $notification->data->object;
|
697 |
+
$order = WC_Stripe_Helper::get_order_by_setup_intent_id( $intent->id );
|
698 |
+
|
699 |
+
if ( ! $order ) {
|
700 |
+
WC_Stripe_Logger::log( 'Could not find order via setup intent ID: ' . $intent->id );
|
701 |
+
return;
|
702 |
+
}
|
703 |
+
|
704 |
+
if ( 'pending' !== $order->get_status() && 'failed' !== $order->get_status() ) {
|
705 |
+
return;
|
706 |
+
}
|
707 |
+
|
708 |
+
if ( $this->lock_order_payment( $order, $intent ) ) {
|
709 |
+
return;
|
710 |
+
}
|
711 |
+
|
712 |
+
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->id : $order->get_id();
|
713 |
+
if ( 'setup_intent.succeeded' === $notification->type ) {
|
714 |
+
WC_Stripe_Logger::log( "Stripe SetupIntent $intent->id succeeded for order $order_id" );
|
715 |
+
if ( WC_Stripe_Helper::is_pre_orders_exists() && WC_Pre_Orders_Order::order_contains_pre_order( $order ) ) {
|
716 |
+
WC_Pre_Orders_Order::mark_order_as_pre_ordered( $order );
|
717 |
+
} else {
|
718 |
+
$order->payment_complete();
|
719 |
+
}
|
720 |
+
} else {
|
721 |
+
$error_message = $intent->last_setup_error ? $intent->last_setup_error->message : "";
|
722 |
+
|
723 |
+
/* translators: 1) The error message that was received from Stripe. */
|
724 |
+
$order->update_status( 'failed', sprintf( __( 'Stripe SCA authentication failed. Reason: %s', 'woocommerce-gateway-stripe' ), $error_message ) );
|
725 |
+
|
726 |
+
$this->send_failed_order_email( $order_id );
|
727 |
+
}
|
728 |
+
|
729 |
+
$this->unlock_order_payment( $order );
|
730 |
+
}
|
731 |
+
|
732 |
/**
|
733 |
* Processes the incoming webhook.
|
734 |
*
|
780 |
case 'payment_intent.payment_failed':
|
781 |
case 'payment_intent.amount_capturable_updated':
|
782 |
$this->process_payment_intent_success( $notification );
|
783 |
+
break;
|
784 |
+
|
785 |
+
case 'setup_intent.succeeded':
|
786 |
+
case 'setup_intent.setup_failed':
|
787 |
+
$this->process_setup_intent( $notification );
|
788 |
|
789 |
}
|
790 |
}
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Admin email about payment retry failed due to authentication
|
4 |
+
*
|
5 |
+
* Email sent to admins when an attempt to automatically process a subscription renewal payment has failed
|
6 |
+
* with the `authentication_needed` error, and a retry rule has been applied to retry the payment in the future.
|
7 |
+
*
|
8 |
+
* @version 4.3.0
|
9 |
+
* @package WooCommerce_Stripe/Classes/WC_Stripe_Email_Failed_Authentication_Retry
|
10 |
+
* @extends WC_Email_Failed_Order
|
11 |
+
*/
|
12 |
+
|
13 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
14 |
+
exit;
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* An email sent to the admin when payment fails to go through due to authentication_required error.
|
19 |
+
*
|
20 |
+
* @since 4.3.0
|
21 |
+
*/
|
22 |
+
class WC_Stripe_Email_Failed_Authentication_Retry extends WC_Email_Failed_Order {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Constructor
|
26 |
+
*/
|
27 |
+
public function __construct() {
|
28 |
+
$this->id = 'failed_authentication_requested';
|
29 |
+
$this->title = __( 'Payment Authentication Requested Email', 'woocommerce-gateway-stripe' );
|
30 |
+
$this->description = __( 'Payment authentication requested emails are sent to chosen recipient(s) when an attempt to automatically process a subscription renewal payment fails because the transaction requires an SCA verification, the customer is requested to authenticate the payment, and a retry rule has been applied to notify the customer again within a certain time period.', 'woocommerce-gateway-stripe' );
|
31 |
+
|
32 |
+
$this->heading = __( 'Automatic renewal payment failed due to authentication required', 'woocommerce-gateway-stripe' );
|
33 |
+
$this->subject = __( '[{site_title}] Automatic payment failed for {order_number}. Customer asked to authenticate payment and will be notified again {retry_time}', 'woocommerce-gateway-stripe' );
|
34 |
+
|
35 |
+
$this->template_html = 'emails/failed-renewal-authentication-requested.php';
|
36 |
+
$this->template_plain = 'emails/plain/failed-renewal-authentication-requested.php';
|
37 |
+
$this->template_base = plugin_dir_path( WC_STRIPE_MAIN_FILE ) . 'templates/';
|
38 |
+
|
39 |
+
$this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) );
|
40 |
+
|
41 |
+
// We want all the parent's methods, with none of its properties, so call its parent's constructor, rather than my parent constructor.
|
42 |
+
WC_Email::__construct();
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Get the default e-mail subject.
|
47 |
+
*
|
48 |
+
* @return string
|
49 |
+
*/
|
50 |
+
public function get_default_subject() {
|
51 |
+
return $this->subject;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Get the default e-mail heading.
|
56 |
+
*
|
57 |
+
* @return string
|
58 |
+
*/
|
59 |
+
public function get_default_heading() {
|
60 |
+
return $this->heading;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Trigger.
|
65 |
+
*
|
66 |
+
* @param int $order_id The order ID.
|
67 |
+
* @param WC_Order|null $order Order object.
|
68 |
+
*/
|
69 |
+
public function trigger( $order_id, $order = null ) {
|
70 |
+
$this->object = $order;
|
71 |
+
|
72 |
+
$this->find['retry-time'] = '{retry_time}';
|
73 |
+
if ( class_exists( 'WCS_Retry_Manager' ) && function_exists( 'wcs_get_human_time_diff' ) ) {
|
74 |
+
$this->retry = WCS_Retry_Manager::store()->get_last_retry_for_order( wcs_get_objects_property( $order, 'id' ) );
|
75 |
+
$this->replace['retry-time'] = wcs_get_human_time_diff( $this->retry->get_time() );
|
76 |
+
} else {
|
77 |
+
WC_Stripe_Logger::log( 'WCS_Retry_Manager class or does not exist. Not able to send admnin email about customer notification for authentication required for renewal payment.' );
|
78 |
+
return;
|
79 |
+
}
|
80 |
+
|
81 |
+
$this->find['order-number'] = '{order_number}';
|
82 |
+
$this->replace['order-number'] = $this->object->get_order_number();
|
83 |
+
|
84 |
+
if ( ! $this->is_enabled() || ! $this->get_recipient() ) {
|
85 |
+
return;
|
86 |
+
}
|
87 |
+
|
88 |
+
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Get content html.
|
93 |
+
*
|
94 |
+
* @return string
|
95 |
+
*/
|
96 |
+
public function get_content_html() {
|
97 |
+
return wc_get_template_html(
|
98 |
+
$this->template_html,
|
99 |
+
array(
|
100 |
+
'order' => $this->object,
|
101 |
+
'retry' => $this->retry,
|
102 |
+
'email_heading' => $this->get_heading(),
|
103 |
+
'sent_to_admin' => true,
|
104 |
+
'plain_text' => false,
|
105 |
+
'email' => $this,
|
106 |
+
),
|
107 |
+
'',
|
108 |
+
$this->template_base
|
109 |
+
);
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Get content plain.
|
114 |
+
*
|
115 |
+
* @return string
|
116 |
+
*/
|
117 |
+
public function get_content_plain() {
|
118 |
+
return wc_get_template_html(
|
119 |
+
$this->template_plain,
|
120 |
+
array(
|
121 |
+
'order' => $this->object,
|
122 |
+
'retry' => $this->retry,
|
123 |
+
'email_heading' => $this->get_heading(),
|
124 |
+
'sent_to_admin' => true,
|
125 |
+
'plain_text' => true,
|
126 |
+
'email' => $this,
|
127 |
+
),
|
128 |
+
'',
|
129 |
+
$this->template_base
|
130 |
+
);
|
131 |
+
}
|
132 |
+
}
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit; // Exit if accessed directly.
|
4 |
+
}
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Base for Failed Renewal/Pre-Order Authentication Notifications.
|
8 |
+
*
|
9 |
+
* @extends WC_Email
|
10 |
+
*/
|
11 |
+
abstract class WC_Stripe_Email_Failed_Authentication extends WC_Email {
|
12 |
+
/**
|
13 |
+
* An instance of the email, which would normally be sent after a failed payment.
|
14 |
+
*
|
15 |
+
* @var WC_Email
|
16 |
+
*/
|
17 |
+
public $original_email;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Generates the HTML for the email while keeping the `template_base` in mind.
|
21 |
+
*
|
22 |
+
* @return string
|
23 |
+
*/
|
24 |
+
public function get_content_html() {
|
25 |
+
ob_start();
|
26 |
+
wc_get_template(
|
27 |
+
$this->template_html,
|
28 |
+
array(
|
29 |
+
'order' => $this->object,
|
30 |
+
'email_heading' => $this->get_heading(),
|
31 |
+
'sent_to_admin' => false,
|
32 |
+
'plain_text' => false,
|
33 |
+
'authorization_url' => $this->get_authorization_url( $this->object ),
|
34 |
+
'email' => $this,
|
35 |
+
),
|
36 |
+
'',
|
37 |
+
$this->template_base
|
38 |
+
);
|
39 |
+
return ob_get_clean();
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Generates the plain text for the email while keeping the `template_base` in mind.
|
44 |
+
*
|
45 |
+
* @return string
|
46 |
+
*/
|
47 |
+
public function get_content_plain() {
|
48 |
+
ob_start();
|
49 |
+
wc_get_template(
|
50 |
+
$this->template_plain,
|
51 |
+
array(
|
52 |
+
'order' => $this->object,
|
53 |
+
'email_heading' => $this->get_heading(),
|
54 |
+
'sent_to_admin' => false,
|
55 |
+
'plain_text' => true,
|
56 |
+
'authorization_url' => $this->get_authorization_url( $this->object ),
|
57 |
+
'email' => $this,
|
58 |
+
),
|
59 |
+
'',
|
60 |
+
$this->template_base
|
61 |
+
);
|
62 |
+
return ob_get_clean();
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Generates the URL, which will be used to authenticate the payment.
|
67 |
+
*
|
68 |
+
* @param WC_Order $order The order whose payment needs authentication.
|
69 |
+
* @return string
|
70 |
+
*/
|
71 |
+
public function get_authorization_url( $order ) {
|
72 |
+
return add_query_arg( 'wc-stripe-confirmation', 1, $order->get_checkout_payment_url( false ) );
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Uses specific fields from `WC_Email_Customer_Invoice` for this email.
|
77 |
+
*/
|
78 |
+
public function init_form_fields() {
|
79 |
+
parent::init_form_fields();
|
80 |
+
$base_fields = $this->form_fields;
|
81 |
+
|
82 |
+
$this->form_fields = array(
|
83 |
+
'enabled' => array(
|
84 |
+
'title' => _x( 'Enable/Disable', 'an email notification', 'woocommerce-gateway-stripe' ),
|
85 |
+
'type' => 'checkbox',
|
86 |
+
'label' => __( 'Enable this email notification', 'woocommerce-gateway-stripe' ),
|
87 |
+
'default' => 'yes',
|
88 |
+
),
|
89 |
+
|
90 |
+
'subject' => $base_fields['subject'],
|
91 |
+
'heading' => $base_fields['heading'],
|
92 |
+
'email_type' => $base_fields['email_type'],
|
93 |
+
);
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Triggers the email.
|
98 |
+
*
|
99 |
+
* @param WC_Order $order The renewal order whose payment failed.
|
100 |
+
*/
|
101 |
+
public function trigger( $order ) {
|
102 |
+
if ( ! $this->is_enabled() ) {
|
103 |
+
return;
|
104 |
+
}
|
105 |
+
|
106 |
+
$this->object = $order;
|
107 |
+
|
108 |
+
if ( method_exists( $order, 'get_billing_email' ) ) {
|
109 |
+
$this->recipient = $order->get_billing_email();
|
110 |
+
} else {
|
111 |
+
$this->recipient = $order->billing_email;
|
112 |
+
}
|
113 |
+
|
114 |
+
$this->find['order_date'] = '{order_date}';
|
115 |
+
if ( function_exists( 'wc_format_datetime' ) ) { // WC 3.0+
|
116 |
+
$this->replace['order_date'] = wc_format_datetime( $order->get_date_created() );
|
117 |
+
} else { // WC < 3.0
|
118 |
+
$this->replace['order_date'] = $order->date_created->date_i18n( wc_date_format() );
|
119 |
+
}
|
120 |
+
|
121 |
+
$this->find['order_number'] = '{order_number}';
|
122 |
+
$this->replace['order_number'] = $order->get_order_number();
|
123 |
+
|
124 |
+
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
|
125 |
+
}
|
126 |
+
}
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit; // Exit if accessed directly.
|
4 |
+
}
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Failed Renewal/Pre-Order Authentication Notification
|
8 |
+
*
|
9 |
+
* @extends WC_Stripe_Email_Failed_Authentication
|
10 |
+
*/
|
11 |
+
class WC_Stripe_Email_Failed_Preorder_Authentication extends WC_Stripe_Email_Failed_Authentication {
|
12 |
+
/**
|
13 |
+
* Holds the message, which is entered by admins when sending the email.
|
14 |
+
*
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
protected $custom_message;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Constructor.
|
21 |
+
*
|
22 |
+
* @param WC_Email[] $email_classes All existing instances of WooCommerce emails.
|
23 |
+
*/
|
24 |
+
public function __construct( $email_classes = array() ) {
|
25 |
+
$this->id = 'failed_preorder_sca_authentication';
|
26 |
+
$this->title = __( 'Pre-order Payment Action Needed', 'woocommerce-gateway-stripe' );
|
27 |
+
$this->description = __( 'This is an order notification sent to the customer once a pre-order is complete, but additional payment steps are required.', 'woocommerce-gateway-stripe' );
|
28 |
+
$this->customer_email = true;
|
29 |
+
|
30 |
+
$this->template_html = 'emails/failed-preorder-authentication.php';
|
31 |
+
$this->template_plain = 'emails/plain/failed-preorder-authentication.php';
|
32 |
+
$this->template_base = plugin_dir_path( WC_STRIPE_MAIN_FILE ) . 'templates/';
|
33 |
+
|
34 |
+
// Use the "authentication required" hook to add the correct, later hook.
|
35 |
+
add_action( 'wc_gateway_stripe_process_payment_authentication_required', array( $this, 'trigger' ) );
|
36 |
+
|
37 |
+
if ( isset( $email_classes['WC_Pre_Orders_Email_Pre_Order_Available'] ) ) {
|
38 |
+
$this->original_email = $email_classes['WC_Pre_Orders_Email_Pre_Order_Available'];
|
39 |
+
}
|
40 |
+
|
41 |
+
// We want all the parent's methods, with none of its properties, so call its parent's constructor, rather than my parent constructor.
|
42 |
+
parent::__construct();
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* When autnentication is required, this adds another action to `wc_pre_orders_pre_order_completed`
|
47 |
+
* in order to send the authentication required email when the custom pre-orders message is available.
|
48 |
+
*
|
49 |
+
* @param WC_Order $order The order whose payment is failing.
|
50 |
+
*/
|
51 |
+
public function trigger( $order ) {
|
52 |
+
if ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Order::order_contains_pre_order( $order->get_id() ) ) {
|
53 |
+
if ( isset( $this->original_email ) ) {
|
54 |
+
remove_action( 'wc_pre_order_status_completed_notification', array( $this->original_email, 'trigger' ), 10, 2 );
|
55 |
+
}
|
56 |
+
|
57 |
+
add_action( 'wc_pre_orders_pre_order_completed', array( $this, 'send_email' ), 10, 2 );
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Triggers the email while also disconnecting the original Pre-Orders email.
|
63 |
+
*
|
64 |
+
* @param WC_Order $order The order that is being paid.
|
65 |
+
* @param string $message The message, which should be added to the email.
|
66 |
+
*/
|
67 |
+
public function send_email( $order, $message ) {
|
68 |
+
$this->custom_message = $message;
|
69 |
+
|
70 |
+
parent::trigger( $order );
|
71 |
+
|
72 |
+
// Restore the action of the original email for other bulk actions.
|
73 |
+
if ( isset( $this->original_email ) ) {
|
74 |
+
add_action( 'wc_pre_order_status_completed_notification', array( $this->original_email, 'trigger' ), 10, 2 );
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Returns the default subject of the email (modifyable in settings).
|
80 |
+
*
|
81 |
+
* @return string
|
82 |
+
*/
|
83 |
+
public function get_default_subject() {
|
84 |
+
return __( 'Payment authorization needed for pre-order {order_number}', 'woocommerce-gateway-stripe' );
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Returns the default heading of the email (modifyable in settings).
|
89 |
+
*
|
90 |
+
* @return string
|
91 |
+
*/
|
92 |
+
public function get_default_heading() {
|
93 |
+
return __( 'Payment authorization needed for pre-order {order_number}', 'woocommerce-gateway-stripe' );
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Returns the custom message, entered by the admin.
|
98 |
+
*
|
99 |
+
* @return string
|
100 |
+
*/
|
101 |
+
public function get_custom_message() {
|
102 |
+
return $this->custom_message;
|
103 |
+
}
|
104 |
+
}
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit; // Exit if accessed directly.
|
4 |
+
}
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Failed Renewal/Pre-Order Authentication Notification
|
8 |
+
*
|
9 |
+
* @extends WC_Email_Customer_Invoice
|
10 |
+
*/
|
11 |
+
class WC_Stripe_Email_Failed_Renewal_Authentication extends WC_Stripe_Email_Failed_Authentication {
|
12 |
+
/**
|
13 |
+
* Constructor.
|
14 |
+
*
|
15 |
+
* @param WC_Email[] $email_classes All existing instances of WooCommerce emails.
|
16 |
+
*/
|
17 |
+
public function __construct( $email_classes = array() ) {
|
18 |
+
$this->id = 'failed_renewal_authentication';
|
19 |
+
$this->title = __( 'Failed Subscription Renewal SCA Authentication', 'woocommerce-gateway-stripe' );
|
20 |
+
$this->description = __( 'Sent to a customer when a renewal fails because the transaction requires an SCA verification. The email contains renewal order information and payment links.', 'woocommerce-gateway-stripe' );
|
21 |
+
$this->customer_email = true;
|
22 |
+
|
23 |
+
$this->template_html = 'emails/failed-renewal-authentication.php';
|
24 |
+
$this->template_plain = 'emails/plain/failed-renewal-authentication.php';
|
25 |
+
$this->template_base = plugin_dir_path( WC_STRIPE_MAIN_FILE ) . 'templates/';
|
26 |
+
|
27 |
+
// Triggers the email at the correct hook.
|
28 |
+
add_action( 'wc_gateway_stripe_process_payment_authentication_required', array( $this, 'trigger' ) );
|
29 |
+
|
30 |
+
if ( isset( $email_classes['WCS_Email_Customer_Renewal_Invoice'] ) ) {
|
31 |
+
$this->original_email = $email_classes['WCS_Email_Customer_Renewal_Invoice'];
|
32 |
+
}
|
33 |
+
|
34 |
+
// We want all the parent's methods, with none of its properties, so call its parent's constructor, rather than my parent constructor.
|
35 |
+
parent::__construct();
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Triggers the email while also disconnecting the original Subscriptions email.
|
40 |
+
*
|
41 |
+
* @param WC_Order $order The order that is being paid.
|
42 |
+
*/
|
43 |
+
public function trigger( $order ) {
|
44 |
+
if ( function_exists( 'wcs_order_contains_subscription' ) && ( wcs_order_contains_subscription( $order->get_id() ) || wcs_is_subscription( $order->get_id() ) || wcs_order_contains_renewal( $order->get_id() ) ) ) {
|
45 |
+
parent::trigger( $order );
|
46 |
+
|
47 |
+
// Prevent the renewal email from WooCommerce Subscriptions from being sent.
|
48 |
+
if ( isset( $this->original_email ) ) {
|
49 |
+
remove_action( 'woocommerce_generated_manual_renewal_order_renewal_notification', array( $this->original_email, 'trigger' ) );
|
50 |
+
remove_action( 'woocommerce_order_status_failed_renewal_notification', array( $this->original_email, 'trigger' ) );
|
51 |
+
}
|
52 |
+
|
53 |
+
// Prevent the retry email from WooCommerce Subscriptions from being sent.
|
54 |
+
add_filter( 'wcs_get_retry_rule_raw', array( $this, 'prevent_retry_notification_email' ), 100, 3 );
|
55 |
+
|
56 |
+
// Send email to store owner indicating communication is happening with the customer to request authentication.
|
57 |
+
add_filter( 'wcs_get_retry_rule_raw', array( $this, 'set_store_owner_custom_email' ), 100, 3 );
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Returns the default subject of the email (modifyable in settings).
|
63 |
+
*
|
64 |
+
* @return string
|
65 |
+
*/
|
66 |
+
public function get_default_subject() {
|
67 |
+
return __( 'Payment authorization needed for renewal of {site_title} order {order_number}', 'woocommerce-gateway-stripe' );
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Returns the default heading of the email (modifyable in settings).
|
72 |
+
*
|
73 |
+
* @return string
|
74 |
+
*/
|
75 |
+
public function get_default_heading() {
|
76 |
+
return __( 'Payment authorization needed for renewal of order {order_number}', 'woocommerce-gateway-stripe' );
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Prevent all customer-facing retry notifications from being sent after this email.
|
81 |
+
*
|
82 |
+
* @param array $rule_array The raw details about the retry rule.
|
83 |
+
* @param int $retry_number The number of the retry.
|
84 |
+
* @param int $order_id The ID of the order that needs payment.
|
85 |
+
* @return array
|
86 |
+
*/
|
87 |
+
public function prevent_retry_notification_email( $rule_array, $retry_number, $order_id ) {
|
88 |
+
if ( wcs_get_objects_property( $this->object, 'id' ) === $order_id ) {
|
89 |
+
$rule_array['email_template_customer'] = '';
|
90 |
+
}
|
91 |
+
|
92 |
+
return $rule_array;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Send store owner a different email when the retry is related to an authentication required error.
|
97 |
+
*
|
98 |
+
* @param array $rule_array The raw details about the retry rule.
|
99 |
+
* @param int $retry_number The number of the retry.
|
100 |
+
* @param int $order_id The ID of the order that needs payment.
|
101 |
+
* @return array
|
102 |
+
*/
|
103 |
+
public function set_store_owner_custom_email( $rule_array, $retry_number, $order_id ) {
|
104 |
+
if (
|
105 |
+
wcs_get_objects_property( $this->object, 'id' ) === $order_id &&
|
106 |
+
'' !== $rule_array['email_template_admin'] // Only send our email if a retry admin email was already going to be sent.
|
107 |
+
) {
|
108 |
+
$rule_array['email_template_admin'] = 'WC_Stripe_Email_Failed_Authentication_Retry';
|
109 |
+
}
|
110 |
+
|
111 |
+
return $rule_array;
|
112 |
+
}
|
113 |
+
}
|
@@ -28,19 +28,15 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
|
|
28 |
* @param object $order
|
29 |
*/
|
30 |
public function remove_order_source_before_retry( $order ) {
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
*/
|
41 |
-
public function remove_order_customer_before_retry( $order ) {
|
42 |
-
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->id : $order->get_id();
|
43 |
-
delete_post_meta( $order_id, '_stripe_customer_id' );
|
44 |
}
|
45 |
|
46 |
/**
|
@@ -61,19 +57,29 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
|
|
61 |
throw new WC_Stripe_Exception( __( 'Unable to store payment details. Please try again.', 'woocommerce-gateway-stripe' ) );
|
62 |
}
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
$this->save_source_to_order( $order, $prepared_source );
|
65 |
|
66 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
WC()->cart->empty_cart();
|
68 |
|
69 |
// Is pre ordered!
|
70 |
WC_Pre_Orders_Order::mark_order_as_pre_ordered( $order );
|
71 |
|
72 |
// Return thank you page redirect
|
73 |
-
return
|
74 |
-
'result' => 'success',
|
75 |
-
'redirect' => $this->get_return_url( $order ),
|
76 |
-
);
|
77 |
} catch ( WC_Stripe_Exception $e ) {
|
78 |
wc_add_notice( $e->getLocalizedMessage(), 'error' );
|
79 |
WC_Stripe_Logger::log( 'Pre Orders Error: ' . $e->getMessage() );
|
@@ -87,37 +93,49 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
|
|
87 |
|
88 |
/**
|
89 |
* Process a pre-order payment when the pre-order is released.
|
|
|
90 |
* @param WC_Order $order
|
|
|
|
|
91 |
* @return void
|
92 |
*/
|
93 |
-
public function process_pre_order_release_payment( $order ) {
|
94 |
try {
|
95 |
-
|
96 |
-
$
|
97 |
-
|
98 |
-
|
99 |
-
);
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
if ( ! empty( $response->error ) ) {
|
106 |
-
if ( 0 === sizeof( $retry_callbacks ) ) {
|
107 |
-
throw new Exception( $response->error->message );
|
108 |
-
} else {
|
109 |
-
$retry_callback = array_shift( $retry_callbacks );
|
110 |
-
call_user_func( array( $this, $retry_callback ), $order );
|
111 |
-
}
|
112 |
-
} else {
|
113 |
-
// Successful
|
114 |
-
$this->process_response( $response, $order );
|
115 |
-
break;
|
116 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
}
|
118 |
} catch ( Exception $e ) {
|
|
|
119 |
/* translators: error message */
|
120 |
-
$order_note = sprintf( __( 'Stripe Transaction Failed (%s)', 'woocommerce-gateway-stripe' ), $
|
121 |
|
122 |
// Mark order as failed if not already set,
|
123 |
// otherwise, make sure we add the order note so we can detect when someone fails to check out multiple times
|
28 |
* @param object $order
|
29 |
*/
|
30 |
public function remove_order_source_before_retry( $order ) {
|
31 |
+
if ( WC_Stripe_Helper::is_wc_lt( '3.0' ) ) {
|
32 |
+
delete_post_meta( $order->id, '_stripe_source_id' );
|
33 |
+
// For BW compat will remove in the future.
|
34 |
+
delete_post_meta( $order->id, '_stripe_card_id' );
|
35 |
+
} else {
|
36 |
+
$order->delete_meta_data( '_stripe_source_id' );
|
37 |
+
$order->delete_meta_data( '_stripe_card_id' );
|
38 |
+
$order->save();
|
39 |
+
}
|
|
|
|
|
|
|
|
|
40 |
}
|
41 |
|
42 |
/**
|
57 |
throw new WC_Stripe_Exception( __( 'Unable to store payment details. Please try again.', 'woocommerce-gateway-stripe' ) );
|
58 |
}
|
59 |
|
60 |
+
// Setup the response early to allow later modifications.
|
61 |
+
$response = array(
|
62 |
+
'result' => 'success',
|
63 |
+
'redirect' => $this->get_return_url( $order ),
|
64 |
+
);
|
65 |
+
|
66 |
$this->save_source_to_order( $order, $prepared_source );
|
67 |
|
68 |
+
// Try setting up a payment intent.
|
69 |
+
$intent_secret = $this->setup_intent( $order, $prepared_source );
|
70 |
+
if ( ! empty( $intent_secret ) ) {
|
71 |
+
$response['setup_intent_secret'] = $intent_secret;
|
72 |
+
return $response;
|
73 |
+
}
|
74 |
+
|
75 |
+
// Remove cart.
|
76 |
WC()->cart->empty_cart();
|
77 |
|
78 |
// Is pre ordered!
|
79 |
WC_Pre_Orders_Order::mark_order_as_pre_ordered( $order );
|
80 |
|
81 |
// Return thank you page redirect
|
82 |
+
return $response;
|
|
|
|
|
|
|
83 |
} catch ( WC_Stripe_Exception $e ) {
|
84 |
wc_add_notice( $e->getLocalizedMessage(), 'error' );
|
85 |
WC_Stripe_Logger::log( 'Pre Orders Error: ' . $e->getMessage() );
|
93 |
|
94 |
/**
|
95 |
* Process a pre-order payment when the pre-order is released.
|
96 |
+
*
|
97 |
* @param WC_Order $order
|
98 |
+
* @param bool $retry
|
99 |
+
*
|
100 |
* @return void
|
101 |
*/
|
102 |
+
public function process_pre_order_release_payment( $order, $retry = true ) {
|
103 |
try {
|
104 |
+
$source = $this->prepare_order_source( $order );
|
105 |
+
$response = $this->create_and_confirm_intent_for_off_session( $order, $source );
|
106 |
+
|
107 |
+
$is_authentication_required = $this->is_authentication_required_for_payment( $response );
|
|
|
108 |
|
109 |
+
if ( ! empty( $response->error ) && ! $is_authentication_required ) {
|
110 |
+
if ( ! $retry ) {
|
111 |
+
throw new Exception( $response->error->message );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
}
|
113 |
+
$this->remove_order_source_before_retry( $order );
|
114 |
+
$this->process_pre_order_release_payment( $order, false );
|
115 |
+
} else if ( $is_authentication_required ) {
|
116 |
+
$charge = end( $response->error->payment_intent->charges->data );
|
117 |
+
$id = $charge->id;
|
118 |
+
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->id : $order->get_id();
|
119 |
+
|
120 |
+
WC_Stripe_Helper::is_wc_lt( '3.0' ) ? update_post_meta( $order_id, '_transaction_id', $id ) : $order->set_transaction_id( $id );
|
121 |
+
$order->update_status( 'failed', sprintf( __( 'Stripe charge awaiting authentication by user: %s.', 'woocommerce-gateway-stripe' ), $id ) );
|
122 |
+
if ( is_callable( array( $order, 'save' ) ) ) {
|
123 |
+
$order->save();
|
124 |
+
}
|
125 |
+
|
126 |
+
WC_Emails::instance();
|
127 |
+
|
128 |
+
do_action( 'wc_gateway_stripe_process_payment_authentication_required', $order );
|
129 |
+
|
130 |
+
throw new WC_Stripe_Exception( print_r( $response, true ), $response->error->message );
|
131 |
+
} else {
|
132 |
+
// Successful
|
133 |
+
$this->process_response( end( $response->charges->data ), $order );
|
134 |
}
|
135 |
} catch ( Exception $e ) {
|
136 |
+
$error_message = is_callable( array( $e, 'getLocalizedMessage' ) ) ? $e->getLocalizedMessage() : $e->getMessage();
|
137 |
/* translators: error message */
|
138 |
+
$order_note = sprintf( __( 'Stripe Transaction Failed (%s)', 'woocommerce-gateway-stripe' ), $error_message );
|
139 |
|
140 |
// Mark order as failed if not already set,
|
141 |
// otherwise, make sure we add the order note so we can detect when someone fails to check out multiple times
|
@@ -30,6 +30,15 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
|
|
30 |
add_filter( 'woocommerce_subscription_payment_meta', array( $this, 'add_subscription_payment_meta' ), 10, 2 );
|
31 |
add_filter( 'woocommerce_subscription_validate_payment_meta', array( $this, 'validate_subscription_payment_meta' ), 10, 2 );
|
32 |
add_filter( 'wc_stripe_display_save_payment_method_checkbox', array( $this, 'maybe_hide_save_checkbox' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
}
|
34 |
}
|
35 |
|
@@ -124,19 +133,9 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
|
|
124 |
try {
|
125 |
$subscription = wc_get_order( $order_id );
|
126 |
$prepared_source = $this->prepare_source( get_current_user_id(), true );
|
127 |
-
$source_object = $prepared_source->source_object;
|
128 |
-
|
129 |
-
// Check if we don't allow prepaid credit cards.
|
130 |
-
if ( ! apply_filters( 'wc_stripe_allow_prepaid_card', true ) && $this->is_prepaid_card( $source_object ) ) {
|
131 |
-
$localized_message = __( 'Sorry, we\'re not accepting prepaid cards at this time. Your credit card has not been charge. Please try with alternative payment method.', 'woocommerce-gateway-stripe' );
|
132 |
-
throw new WC_Stripe_Exception( print_r( $source_object, true ), $localized_message );
|
133 |
-
}
|
134 |
-
|
135 |
-
if ( empty( $prepared_source->source ) ) {
|
136 |
-
$localized_message = __( 'Payment processing failed. Please retry.', 'woocommerce-gateway-stripe' );
|
137 |
-
throw new WC_Stripe_Exception( print_r( $prepared_source, true ), $localized_message );
|
138 |
-
}
|
139 |
|
|
|
|
|
140 |
$this->save_source_to_order( $subscription, $prepared_source );
|
141 |
|
142 |
do_action( 'wc_stripe_change_subs_payment_method_success', $prepared_source->source, $prepared_source );
|
@@ -169,6 +168,28 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
|
|
169 |
}
|
170 |
}
|
171 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
/**
|
173 |
* Scheduled_subscription_payment function.
|
174 |
*
|
@@ -199,6 +220,11 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
|
|
199 |
|
200 |
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $renewal_order->id : $renewal_order->get_id();
|
201 |
|
|
|
|
|
|
|
|
|
|
|
202 |
// Get source from order
|
203 |
$prepared_source = $this->prepare_order_source( $renewal_order );
|
204 |
$source_object = $prepared_source->source_object;
|
@@ -221,9 +247,13 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
|
|
221 |
$prepared_source->source = '';
|
222 |
}
|
223 |
|
224 |
-
$response = $this->
|
|
|
|
|
225 |
|
226 |
-
if
|
|
|
|
|
227 |
// We want to retry.
|
228 |
if ( $this->is_retryable_error( $response->error ) ) {
|
229 |
if ( $retry ) {
|
@@ -257,10 +287,29 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
|
|
257 |
throw new WC_Stripe_Exception( print_r( $response, true ), $localized_message );
|
258 |
}
|
259 |
|
260 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
261 |
|
|
|
|
|
|
|
262 |
|
263 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
} catch ( WC_Stripe_Exception $e ) {
|
265 |
WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
|
266 |
|
@@ -271,57 +320,6 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
|
|
271 |
}
|
272 |
}
|
273 |
|
274 |
-
/**
|
275 |
-
* Create and confirm a new PaymentIntent.
|
276 |
-
*
|
277 |
-
* @param float $amount The amount to charge.
|
278 |
-
* @param WC_Order $order The order that is being paid for.
|
279 |
-
* @param object $prepared_source The source that is used for the payment.
|
280 |
-
* @return object An intent or an error.
|
281 |
-
*/
|
282 |
-
public function create_and_confirm_intent_for_renewal( $amount, $order, $prepared_source ) {
|
283 |
-
// The request for a charge contains metadata for the intent.
|
284 |
-
$full_request = $this->generate_payment_request( $order, $prepared_source );
|
285 |
-
|
286 |
-
$request = array(
|
287 |
-
'amount' => WC_Stripe_Helper::get_stripe_amount( $amount, $full_request['currency'] ),
|
288 |
-
'currency' => $full_request['currency'],
|
289 |
-
'description' => $full_request['description'],
|
290 |
-
'metadata' => $full_request['metadata'],
|
291 |
-
'payment_method_types' => array(
|
292 |
-
'card',
|
293 |
-
),
|
294 |
-
'off_session' => 'true',
|
295 |
-
'confirm' => 'true',
|
296 |
-
'confirmation_method' => 'automatic',
|
297 |
-
);
|
298 |
-
|
299 |
-
if ( isset( $full_request['statement_descriptor'] ) ) {
|
300 |
-
$request['statement_descriptor'] = $full_request['statement_descriptor'];
|
301 |
-
}
|
302 |
-
|
303 |
-
if ( isset( $full_request['customer'] ) ) {
|
304 |
-
$request['customer'] = $full_request['customer'];
|
305 |
-
}
|
306 |
-
|
307 |
-
if ( isset( $full_request['source'] ) ) {
|
308 |
-
$request['source'] = $full_request['source'];
|
309 |
-
}
|
310 |
-
|
311 |
-
$intent = WC_Stripe_API::request( $request, 'payment_intents' );
|
312 |
-
if ( ! empty( $intent->error ) ) {
|
313 |
-
return $intent;
|
314 |
-
}
|
315 |
-
|
316 |
-
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $order->id : $order->get_id();
|
317 |
-
WC_Stripe_Logger::log( "Stripe PaymentIntent $intent->id initiated for order $order_id" );
|
318 |
-
|
319 |
-
// Save the intent ID to the order.
|
320 |
-
$this->save_intent_to_order( $order, $intent );
|
321 |
-
|
322 |
-
return $intent;
|
323 |
-
}
|
324 |
-
|
325 |
/**
|
326 |
* Updates other subscription sources.
|
327 |
*
|
@@ -551,4 +549,62 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
|
|
551 |
|
552 |
return $payment_method_to_display;
|
553 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
554 |
}
|
30 |
add_filter( 'woocommerce_subscription_payment_meta', array( $this, 'add_subscription_payment_meta' ), 10, 2 );
|
31 |
add_filter( 'woocommerce_subscription_validate_payment_meta', array( $this, 'validate_subscription_payment_meta' ), 10, 2 );
|
32 |
add_filter( 'wc_stripe_display_save_payment_method_checkbox', array( $this, 'maybe_hide_save_checkbox' ) );
|
33 |
+
|
34 |
+
/*
|
35 |
+
* WC subscriptions hooks into the "template_redirect" hook with priority 100.
|
36 |
+
* If the screen is "Pay for order" and the order is a subscription renewal, it redirects to the plain checkout.
|
37 |
+
* See: https://github.com/woocommerce/woocommerce-subscriptions/blob/99a75687e109b64cbc07af6e5518458a6305f366/includes/class-wcs-cart-renewal.php#L165
|
38 |
+
* If we are in the "You just need to authorize SCA" flow, we don't want that redirection to happen.
|
39 |
+
*/
|
40 |
+
add_action( 'template_redirect', array( $this, 'remove_order_pay_var' ), 99 );
|
41 |
+
add_action( 'template_redirect', array( $this, 'restore_order_pay_var' ), 101 );
|
42 |
}
|
43 |
}
|
44 |
|
133 |
try {
|
134 |
$subscription = wc_get_order( $order_id );
|
135 |
$prepared_source = $this->prepare_source( get_current_user_id(), true );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
|
137 |
+
$this->maybe_disallow_prepaid_card( $prepared_source );
|
138 |
+
$this->check_source( $prepared_source );
|
139 |
$this->save_source_to_order( $subscription, $prepared_source );
|
140 |
|
141 |
do_action( 'wc_stripe_change_subs_payment_method_success', $prepared_source->source, $prepared_source );
|
168 |
}
|
169 |
}
|
170 |
|
171 |
+
/**
|
172 |
+
* Overloads WC_Stripe_Payment_Gateway::generate_create_intent_request() in order to
|
173 |
+
* include additional flags, used when setting payment intents up for off-session usage.
|
174 |
+
*
|
175 |
+
* @param WC_Order $order The order that is being paid for.
|
176 |
+
* @param object $prepared_source The source that is used for the payment.
|
177 |
+
* @return array The arguments for the request.
|
178 |
+
*/
|
179 |
+
public function generate_create_intent_request( $order, $prepared_source ) {
|
180 |
+
$request = parent::generate_create_intent_request( $order, $prepared_source );
|
181 |
+
|
182 |
+
// Non-subscription orders do not need any additional parameters.
|
183 |
+
if ( ! $this->has_subscription( $order ) ) {
|
184 |
+
return $request;
|
185 |
+
}
|
186 |
+
|
187 |
+
// Let Stripe know that the payment should be prepared for future usage.
|
188 |
+
$request['setup_future_usage'] = 'off_session';
|
189 |
+
|
190 |
+
return $request;
|
191 |
+
}
|
192 |
+
|
193 |
/**
|
194 |
* Scheduled_subscription_payment function.
|
195 |
*
|
220 |
|
221 |
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $renewal_order->id : $renewal_order->get_id();
|
222 |
|
223 |
+
// Check for an existing intent, which is associated with the order.
|
224 |
+
if ( $this->has_authentication_already_failed( $renewal_order ) ) {
|
225 |
+
return;
|
226 |
+
}
|
227 |
+
|
228 |
// Get source from order
|
229 |
$prepared_source = $this->prepare_order_source( $renewal_order );
|
230 |
$source_object = $prepared_source->source_object;
|
247 |
$prepared_source->source = '';
|
248 |
}
|
249 |
|
250 |
+
$response = $this->create_and_confirm_intent_for_off_session( $renewal_order, $prepared_source, $amount );
|
251 |
+
|
252 |
+
$is_authentication_required = $this->is_authentication_required_for_payment( $response );
|
253 |
|
254 |
+
// It's only a failed payment if it's an error and it's not of the type 'authentication_required'.
|
255 |
+
// If it's 'authentication_required', then we should email the user and ask them to authenticate.
|
256 |
+
if ( ! empty( $response->error ) && ! $is_authentication_required ) {
|
257 |
// We want to retry.
|
258 |
if ( $this->is_retryable_error( $response->error ) ) {
|
259 |
if ( $retry ) {
|
287 |
throw new WC_Stripe_Exception( print_r( $response, true ), $localized_message );
|
288 |
}
|
289 |
|
290 |
+
// Either the charge was successfully captured, or it requires further authentication.
|
291 |
+
|
292 |
+
if ( $is_authentication_required ) {
|
293 |
+
do_action( 'wc_gateway_stripe_process_payment_authentication_required', $renewal_order, $response );
|
294 |
+
|
295 |
+
$error_message = __( 'This transaction requires authentication.', 'woocommerce-gateway-stripe' );
|
296 |
+
$renewal_order->add_order_note( $error_message );
|
297 |
|
298 |
+
$charge = end( $response->error->payment_intent->charges->data );
|
299 |
+
$id = $charge->id;
|
300 |
+
$order_id = WC_Stripe_Helper::is_wc_lt( '3.0' ) ? $renewal_order->id : $renewal_order->get_id();
|
301 |
|
302 |
+
WC_Stripe_Helper::is_wc_lt( '3.0' ) ? update_post_meta( $order_id, '_transaction_id', $id ) : $renewal_order->set_transaction_id( $id );
|
303 |
+
$renewal_order->update_status( 'failed', sprintf( __( 'Stripe charge awaiting authentication by user: %s.', 'woocommerce-gateway-stripe' ), $id ) );
|
304 |
+
if ( is_callable( array( $renewal_order, 'save' ) ) ) {
|
305 |
+
$renewal_order->save();
|
306 |
+
}
|
307 |
+
} else {
|
308 |
+
// The charge was successfully captured
|
309 |
+
do_action( 'wc_gateway_stripe_process_payment', $response, $renewal_order );
|
310 |
+
|
311 |
+
$this->process_response( end( $response->charges->data ), $renewal_order );
|
312 |
+
}
|
313 |
} catch ( WC_Stripe_Exception $e ) {
|
314 |
WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
|
315 |
|
320 |
}
|
321 |
}
|
322 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
/**
|
324 |
* Updates other subscription sources.
|
325 |
*
|
549 |
|
550 |
return $payment_method_to_display;
|
551 |
}
|
552 |
+
|
553 |
+
/**
|
554 |
+
* If this is the "Pass the SCA challenge" flow, remove a variable that is checked by WC Subscriptions
|
555 |
+
* so WC Subscriptions doesn't redirect to the checkout
|
556 |
+
*/
|
557 |
+
public function remove_order_pay_var() {
|
558 |
+
global $wp;
|
559 |
+
if ( isset( $_GET['wc-stripe-confirmation'] ) ) {
|
560 |
+
$this->order_pay_var = $wp->query_vars['order-pay'];
|
561 |
+
$wp->query_vars['order-pay'] = null;
|
562 |
+
}
|
563 |
+
}
|
564 |
+
|
565 |
+
/**
|
566 |
+
* Restore the variable that was removed in remove_order_pay_var()
|
567 |
+
*/
|
568 |
+
public function restore_order_pay_var() {
|
569 |
+
global $wp;
|
570 |
+
if ( isset( $this->order_pay_var ) ) {
|
571 |
+
$wp->query_vars['order-pay'] = $this->order_pay_var;
|
572 |
+
}
|
573 |
+
}
|
574 |
+
|
575 |
+
/**
|
576 |
+
* Checks if a renewal already failed because a manual authentication is required.
|
577 |
+
*
|
578 |
+
* @param WC_Order $renewal_order The renewal order.
|
579 |
+
* @return boolean
|
580 |
+
*/
|
581 |
+
public function has_authentication_already_failed( $renewal_order ) {
|
582 |
+
$existing_intent = $this->get_intent_from_order( $renewal_order );
|
583 |
+
|
584 |
+
if (
|
585 |
+
! $existing_intent
|
586 |
+
|| 'requires_payment_method' !== $existing_intent->status
|
587 |
+
|| empty( $existing_intent->last_payment_error )
|
588 |
+
|| 'authentication_required' !== $existing_intent->last_payment_error->code
|
589 |
+
) {
|
590 |
+
return false;
|
591 |
+
}
|
592 |
+
|
593 |
+
// Make sure all emails are instantiated.
|
594 |
+
WC_Emails::instance();
|
595 |
+
|
596 |
+
/**
|
597 |
+
* A payment attempt failed because SCA authentication is required.
|
598 |
+
*
|
599 |
+
* @param WC_Order $renewal_order The order that is being renewed.
|
600 |
+
*/
|
601 |
+
do_action( 'wc_gateway_stripe_process_payment_authentication_required', $renewal_order );
|
602 |
+
|
603 |
+
// Fail the payment attempt (order would be currently pending because of retry rules).
|
604 |
+
$charge = end( $existing_intent->charges->data );
|
605 |
+
$charge_id = $charge->id;
|
606 |
+
$renewal_order->update_status( 'failed', sprintf( __( 'Stripe charge awaiting authentication by user: %s.', 'woocommerce-gateway-stripe' ), $charge_id ) );
|
607 |
+
|
608 |
+
return true;
|
609 |
+
}
|
610 |
}
|
@@ -2,10 +2,9 @@
|
|
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 4.
|
6 |
-
"Report-Msgid-Bugs-To: "
|
7 |
-
"
|
8 |
-
"POT-Creation-Date: 2019-10-02 17:24:17+00:00\n"
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=utf-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
@@ -28,72 +27,71 @@ msgstr ""
|
|
28 |
msgid "Save payment information to my account for future purchases."
|
29 |
msgstr ""
|
30 |
|
31 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
32 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:216
|
33 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
34 |
#. translators: 1) dollar amount
|
35 |
#. translators: minimum amount
|
36 |
msgid "Sorry, the minimum allowed order total is %1$s to use this payment method."
|
37 |
msgstr ""
|
38 |
|
39 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
40 |
#. translators: 1) blog name 2) order number
|
41 |
msgid "%1$s - Order %2$s"
|
42 |
msgstr ""
|
43 |
|
44 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
45 |
msgid "customer_name"
|
46 |
msgstr ""
|
47 |
|
48 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
49 |
msgid "customer_email"
|
50 |
msgstr ""
|
51 |
|
52 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
53 |
#. translators: transaction id
|
54 |
msgid "Stripe charge awaiting payment: %s."
|
55 |
msgstr ""
|
56 |
|
57 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
58 |
#: includes/class-wc-stripe-order-handler.php:296
|
59 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
60 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
61 |
#. translators: transaction id
|
62 |
msgid "Stripe charge complete (Charge ID: %s)"
|
63 |
msgstr ""
|
64 |
|
65 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
66 |
-
#: includes/class-wc-gateway-stripe.php:
|
67 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:173
|
68 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:136
|
69 |
msgid "Payment processing failed. Please retry."
|
70 |
msgstr ""
|
71 |
|
72 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
73 |
#. translators: transaction id
|
74 |
msgid ""
|
75 |
"Stripe charge authorized (Charge ID: %s). Process order to take payment, or "
|
76 |
"cancel to remove the pre-authorization."
|
77 |
msgstr ""
|
78 |
|
79 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
80 |
msgid "Invalid payment method. Please input a new card number."
|
81 |
msgstr ""
|
82 |
|
83 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
84 |
#. translators: 1) dollar amount 2) transaction id 3) refund message
|
85 |
msgid "Refunded %1$s - Refund ID: %2$s - Reason: %3$s"
|
86 |
msgstr ""
|
87 |
|
88 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
89 |
msgid "Pre-Authorization Released"
|
90 |
msgstr ""
|
91 |
|
92 |
-
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:
|
93 |
msgid "There was a problem adding the payment method."
|
94 |
msgstr ""
|
95 |
|
96 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
97 |
#. translators: 1) A URL that explains Stripe Radar.
|
98 |
msgid ""
|
99 |
"WooCommerce Stripe - We see that you had the \"Require 3D secure when "
|
@@ -102,42 +100,42 @@ msgid ""
|
|
102 |
"href=\"%s\" target=\"_blank\">here</a>."
|
103 |
msgstr ""
|
104 |
|
105 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
106 |
#. translators: 1) int version 2) int version
|
107 |
msgid ""
|
108 |
"WooCommerce Stripe - We recently made changes to Stripe that may impact the "
|
109 |
"appearance of your checkout. If your checkout has changed unexpectedly, "
|
110 |
"please follow these <a "
|
111 |
-
"href=\"https://docs.woocommerce.com/document/stripe/#
|
112 |
"target=\"_blank\">instructions</a> to fix."
|
113 |
msgstr ""
|
114 |
|
115 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
116 |
#. translators: 1) int version 2) int version
|
117 |
msgid ""
|
118 |
"WooCommerce Stripe - The minimum PHP version required for this plugin is "
|
119 |
"%1$s. You are running %2$s."
|
120 |
msgstr ""
|
121 |
|
122 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
123 |
#. translators: 1) int version 2) int version
|
124 |
msgid ""
|
125 |
"WooCommerce Stripe - The minimum WooCommerce version required for this "
|
126 |
"plugin is %1$s. You are running %2$s."
|
127 |
msgstr ""
|
128 |
|
129 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
130 |
msgid "WooCommerce Stripe - cURL is not installed."
|
131 |
msgstr ""
|
132 |
|
133 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
134 |
#. translators: 1) link
|
135 |
msgid ""
|
136 |
"Stripe is almost ready. To get started, <a href=\"%s\">set your Stripe "
|
137 |
"account keys</a>."
|
138 |
msgstr ""
|
139 |
|
140 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
141 |
#. translators: 1) link
|
142 |
msgid ""
|
143 |
"Stripe is in test mode however your test keys may not be valid. Test keys "
|
@@ -145,7 +143,7 @@ msgid ""
|
|
145 |
"<a href=\"%s\">set your Stripe account keys</a>."
|
146 |
msgstr ""
|
147 |
|
148 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
149 |
#. translators: 1) link
|
150 |
msgid ""
|
151 |
"Stripe is in live mode however your test keys may not be valid. Live keys "
|
@@ -153,7 +151,7 @@ msgid ""
|
|
153 |
"<a href=\"%s\">set your Stripe account keys</a>."
|
154 |
msgstr ""
|
155 |
|
156 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
157 |
#. translators: 1) link
|
158 |
msgid ""
|
159 |
"Stripe is enabled, but a SSL certificate is not detected. Your checkout may "
|
@@ -161,16 +159,22 @@ msgid ""
|
|
161 |
"target=\"_blank\">SSL certificate</a>"
|
162 |
msgstr ""
|
163 |
|
164 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
#. translators: %1$s Payment method, %2$s List of supported currencies
|
166 |
msgid "%1$s is enabled - it requires store currency to be set to %2$s"
|
167 |
msgstr ""
|
168 |
|
169 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
170 |
msgid "Action failed. Please refresh the page and retry."
|
171 |
msgstr ""
|
172 |
|
173 |
-
#: includes/admin/class-wc-stripe-admin-notices.php:
|
174 |
msgid "Cheatin’ huh?"
|
175 |
msgstr ""
|
176 |
|
@@ -206,8 +210,8 @@ msgstr ""
|
|
206 |
|
207 |
#: includes/admin/class-wc-stripe-privacy.php:41
|
208 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:463
|
209 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
210 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
211 |
msgid "N/A"
|
212 |
msgstr ""
|
213 |
|
@@ -761,22 +765,14 @@ msgid ""
|
|
761 |
"your Stripe account keys</a>."
|
762 |
msgstr ""
|
763 |
|
764 |
-
#: includes/class-wc-gateway-stripe.php:
|
765 |
#. translators: 1) Opening anchor tag 2) closing anchor tag
|
766 |
msgid ""
|
767 |
"If your billing address has been changed for saved payment methods, be sure "
|
768 |
"to remove any %1$ssaved payment methods%2$s on file and re-add them."
|
769 |
msgstr ""
|
770 |
|
771 |
-
#: includes/class-wc-gateway-stripe.php:
|
772 |
-
msgid "Add Card"
|
773 |
-
msgstr ""
|
774 |
-
|
775 |
-
#: includes/class-wc-gateway-stripe.php:257
|
776 |
-
msgid "Change Payment Method"
|
777 |
-
msgstr ""
|
778 |
-
|
779 |
-
#: includes/class-wc-gateway-stripe.php:278
|
780 |
#. translators: link to Stripe testing page
|
781 |
msgid ""
|
782 |
"TEST MODE ENABLED. In test mode, you can use the card number "
|
@@ -785,84 +781,84 @@ msgid ""
|
|
785 |
"card numbers."
|
786 |
msgstr ""
|
787 |
|
788 |
-
#: includes/class-wc-gateway-stripe.php:
|
789 |
msgid "Credit or debit card"
|
790 |
msgstr ""
|
791 |
|
792 |
-
#: includes/class-wc-gateway-stripe.php:
|
793 |
msgid "Card Number"
|
794 |
msgstr ""
|
795 |
|
796 |
-
#: includes/class-wc-gateway-stripe.php:
|
797 |
msgid "Expiry Date"
|
798 |
msgstr ""
|
799 |
|
800 |
-
#: includes/class-wc-gateway-stripe.php:
|
801 |
msgid "Card Code (CVC)"
|
802 |
msgstr ""
|
803 |
|
804 |
-
#: includes/class-wc-gateway-stripe.php:
|
805 |
msgid "Please accept the terms and conditions first"
|
806 |
msgstr ""
|
807 |
|
808 |
-
#: includes/class-wc-gateway-stripe.php:
|
809 |
msgid "Please fill in required checkout fields first"
|
810 |
msgstr ""
|
811 |
|
812 |
-
#: includes/class-wc-gateway-stripe.php:
|
813 |
-
#: includes/class-wc-gateway-stripe.php:
|
814 |
msgid ""
|
815 |
"Sorry, we're not accepting prepaid cards at this time. Your credit card has "
|
816 |
"not been charged. Please try with alternative payment method."
|
817 |
msgstr ""
|
818 |
|
819 |
-
#: includes/class-wc-gateway-stripe.php:
|
820 |
msgid "Please enter your IBAN account name."
|
821 |
msgstr ""
|
822 |
|
823 |
-
#: includes/class-wc-gateway-stripe.php:
|
824 |
msgid "Please enter your IBAN account number."
|
825 |
msgstr ""
|
826 |
|
827 |
-
#: includes/class-wc-gateway-stripe.php:
|
828 |
msgid "We couldn't initiate the payment. Please try again."
|
829 |
msgstr ""
|
830 |
|
831 |
-
#: includes/class-wc-gateway-stripe.php:
|
832 |
msgid "Billing First Name and Last Name are required."
|
833 |
msgstr ""
|
834 |
|
835 |
-
#: includes/class-wc-gateway-stripe.php:
|
836 |
#. translators: error message
|
837 |
msgid "This represents the fee Stripe collects for the transaction."
|
838 |
msgstr ""
|
839 |
|
840 |
-
#: includes/class-wc-gateway-stripe.php:
|
841 |
msgid "Stripe Fee:"
|
842 |
msgstr ""
|
843 |
|
844 |
-
#: includes/class-wc-gateway-stripe.php:
|
845 |
msgid ""
|
846 |
"This represents the net total that will be credited to your Stripe bank "
|
847 |
"account. This may be in the currency that is set in your Stripe account."
|
848 |
msgstr ""
|
849 |
|
850 |
-
#: includes/class-wc-gateway-stripe.php:
|
851 |
msgid "Stripe Payout:"
|
852 |
msgstr ""
|
853 |
|
854 |
-
#: includes/class-wc-gateway-stripe.php:
|
855 |
#: includes/class-wc-stripe-order-handler.php:162
|
856 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
857 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:263
|
858 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
859 |
#: includes/payment-methods/class-wc-gateway-stripe-sepa.php:373
|
860 |
msgid ""
|
861 |
"Sorry, we are unable to process your payment at this time. Please retry "
|
862 |
"later."
|
863 |
msgstr ""
|
864 |
|
865 |
-
#: includes/class-wc-gateway-stripe.php:
|
866 |
msgid ""
|
867 |
"Almost there!\n"
|
868 |
"\n"
|
@@ -870,13 +866,14 @@ msgid ""
|
|
870 |
"done is for you to authorize the payment with your bank."
|
871 |
msgstr ""
|
872 |
|
873 |
-
#: includes/class-wc-gateway-stripe.php:
|
874 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
|
|
875 |
#. translators: 1) The error message that was received from Stripe.
|
876 |
msgid "Stripe SCA authentication failed. Reason: %s"
|
877 |
msgstr ""
|
878 |
|
879 |
-
#: includes/class-wc-gateway-stripe.php:
|
880 |
msgid "Stripe SCA authentication failed."
|
881 |
msgstr ""
|
882 |
|
@@ -909,15 +906,17 @@ msgid ""
|
|
909 |
"the issue. (Logging must be enabled to see recorded logs)"
|
910 |
msgstr ""
|
911 |
|
912 |
-
#: includes/class-wc-stripe-customer.php:
|
913 |
-
|
|
|
914 |
msgstr ""
|
915 |
|
916 |
-
#: includes/class-wc-stripe-customer.php:
|
917 |
-
|
|
|
918 |
msgstr ""
|
919 |
|
920 |
-
#: includes/class-wc-stripe-customer.php:
|
921 |
msgid "Unable to add payment source."
|
922 |
msgstr ""
|
923 |
|
@@ -1008,7 +1007,7 @@ msgid "Payment verification error: %s"
|
|
1008 |
msgstr ""
|
1009 |
|
1010 |
#: includes/class-wc-stripe-order-handler.php:144
|
1011 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1012 |
#: includes/payment-methods/class-wc-gateway-stripe-sepa.php:353
|
1013 |
msgid "This card is no longer available and has been removed."
|
1014 |
msgstr ""
|
@@ -1035,7 +1034,7 @@ msgstr ""
|
|
1035 |
msgid "SEPA IBAN ending in %s"
|
1036 |
msgstr ""
|
1037 |
|
1038 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1039 |
#. translators: 1) The URL to the order.
|
1040 |
msgid ""
|
1041 |
"A dispute was created for this order. Response is needed. Please go to your "
|
@@ -1043,34 +1042,34 @@ msgid ""
|
|
1043 |
"Dashboard</a> to review this dispute."
|
1044 |
msgstr ""
|
1045 |
|
1046 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1047 |
#. translators: partial captured amount
|
1048 |
msgid "This charge was partially captured via Stripe Dashboard in the amount of: %s"
|
1049 |
msgstr ""
|
1050 |
|
1051 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1052 |
msgid "This payment failed to clear."
|
1053 |
msgstr ""
|
1054 |
|
1055 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1056 |
msgid "This payment has cancelled."
|
1057 |
msgstr ""
|
1058 |
|
1059 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1060 |
msgid "Refunded via Stripe Dashboard"
|
1061 |
msgstr ""
|
1062 |
|
1063 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1064 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1065 |
msgid "Pre-Authorization Released via Stripe Dashboard"
|
1066 |
msgstr ""
|
1067 |
|
1068 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1069 |
#. translators: 1) dollar amount 2) transaction id 3) refund message
|
1070 |
msgid "Refunded %1$s - Refund ID: %2$s - %3$s"
|
1071 |
msgstr ""
|
1072 |
|
1073 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1074 |
#. translators: 1) The URL to the order. 2) The reason type.
|
1075 |
msgid ""
|
1076 |
"A review has been opened for this order. Action is needed. Please go to "
|
@@ -1078,47 +1077,116 @@ msgid ""
|
|
1078 |
"Dashboard</a> to review the issue. Reason: (%2$s)"
|
1079 |
msgstr ""
|
1080 |
|
1081 |
-
#: includes/class-wc-stripe-webhook-handler.php:
|
1082 |
#. translators: 1) The reason type.
|
1083 |
msgid "The opened review for this order is now closed. Reason: (%s)"
|
1084 |
msgstr ""
|
1085 |
|
1086 |
-
#: includes/compat/class-wc-stripe-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1087 |
msgid "Unable to store payment details. Please try again."
|
1088 |
msgstr ""
|
1089 |
|
1090 |
-
#: includes/compat/class-wc-stripe-pre-orders-compat.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
1091 |
#. translators: error message
|
1092 |
msgid "Stripe Transaction Failed (%s)"
|
1093 |
msgstr ""
|
1094 |
|
1095 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:88
|
1096 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
1097 |
msgid ""
|
1098 |
"Update the Payment Method used for all of my active subscriptions "
|
1099 |
"(optional)."
|
1100 |
msgstr ""
|
1101 |
|
1102 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:226
|
1103 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
1104 |
msgid "Customer not found"
|
1105 |
msgstr ""
|
1106 |
|
1107 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:386
|
1108 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
1109 |
#. translators: error message
|
1110 |
msgid "A \"Stripe Customer ID\" value is required."
|
1111 |
msgstr ""
|
1112 |
|
1113 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:388
|
1114 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
1115 |
msgid ""
|
1116 |
"Invalid customer ID. A valid \"Stripe Customer ID\" must begin with "
|
1117 |
"\"cus_\"."
|
1118 |
msgstr ""
|
1119 |
|
1120 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:397
|
1121 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
1122 |
msgid ""
|
1123 |
"Invalid source ID. A valid source \"Stripe Source ID\" must begin with "
|
1124 |
"\"src_\" or \"card_\"."
|
@@ -1129,19 +1197,17 @@ msgstr ""
|
|
1129 |
msgid "Via SEPA Direct Debit ending in %1$s"
|
1130 |
msgstr ""
|
1131 |
|
1132 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
1133 |
-
msgid ""
|
1134 |
-
"Sorry, we're not accepting prepaid cards at this time. Your credit card has "
|
1135 |
-
"not been charge. Please try with alternative payment method."
|
1136 |
msgstr ""
|
1137 |
|
1138 |
-
#: includes/compat/class-wc-stripe-subs-compat.php:
|
1139 |
#. translators: 1) card brand 2) last 4 digits
|
1140 |
msgid "Via %1$s card ending in %2$s"
|
1141 |
msgstr ""
|
1142 |
|
1143 |
#: includes/payment-methods/class-wc-gateway-stripe-alipay.php:60
|
1144 |
-
#: woocommerce-gateway-stripe.php:
|
1145 |
msgid "Stripe Alipay"
|
1146 |
msgstr ""
|
1147 |
|
@@ -1170,27 +1236,27 @@ msgid "Add Payment"
|
|
1170 |
msgstr ""
|
1171 |
|
1172 |
#: includes/payment-methods/class-wc-gateway-stripe-bancontact.php:60
|
1173 |
-
#: woocommerce-gateway-stripe.php:
|
1174 |
msgid "Stripe Bancontact"
|
1175 |
msgstr ""
|
1176 |
|
1177 |
#: includes/payment-methods/class-wc-gateway-stripe-eps.php:60
|
1178 |
-
#: woocommerce-gateway-stripe.php:
|
1179 |
msgid "Stripe EPS"
|
1180 |
msgstr ""
|
1181 |
|
1182 |
#: includes/payment-methods/class-wc-gateway-stripe-giropay.php:60
|
1183 |
-
#: woocommerce-gateway-stripe.php:
|
1184 |
msgid "Stripe Giropay"
|
1185 |
msgstr ""
|
1186 |
|
1187 |
#: includes/payment-methods/class-wc-gateway-stripe-ideal.php:60
|
1188 |
-
#: woocommerce-gateway-stripe.php:
|
1189 |
msgid "Stripe iDeal"
|
1190 |
msgstr ""
|
1191 |
|
1192 |
#: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:60
|
1193 |
-
#: woocommerce-gateway-stripe.php:
|
1194 |
msgid "Stripe Multibanco"
|
1195 |
msgstr ""
|
1196 |
|
@@ -1219,12 +1285,12 @@ msgid "Awaiting Multibanco payment"
|
|
1219 |
msgstr ""
|
1220 |
|
1221 |
#: includes/payment-methods/class-wc-gateway-stripe-p24.php:60
|
1222 |
-
#: woocommerce-gateway-stripe.php:
|
1223 |
msgid "Stripe P24"
|
1224 |
msgstr ""
|
1225 |
|
1226 |
#: includes/payment-methods/class-wc-gateway-stripe-sepa.php:75
|
1227 |
-
#: woocommerce-gateway-stripe.php:
|
1228 |
msgid "Stripe SEPA Direct Debit"
|
1229 |
msgstr ""
|
1230 |
|
@@ -1251,7 +1317,7 @@ msgid ""
|
|
1251 |
msgstr ""
|
1252 |
|
1253 |
#: includes/payment-methods/class-wc-gateway-stripe-sofort.php:60
|
1254 |
-
#: woocommerce-gateway-stripe.php:
|
1255 |
msgid "Stripe SOFORT"
|
1256 |
msgstr ""
|
1257 |
|
@@ -1309,6 +1375,23 @@ msgstr ""
|
|
1309 |
msgid "Discount"
|
1310 |
msgstr ""
|
1311 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1312 |
#: woocommerce-gateway-stripe.php:32
|
1313 |
#. translators: 1. URL link.
|
1314 |
msgid ""
|
@@ -1316,15 +1399,15 @@ msgid ""
|
|
1316 |
"here."
|
1317 |
msgstr ""
|
1318 |
|
1319 |
-
#: woocommerce-gateway-stripe.php:
|
1320 |
msgid "Settings"
|
1321 |
msgstr ""
|
1322 |
|
1323 |
-
#: woocommerce-gateway-stripe.php:
|
1324 |
msgid "Docs"
|
1325 |
msgstr ""
|
1326 |
|
1327 |
-
#: woocommerce-gateway-stripe.php:
|
1328 |
msgid "Support"
|
1329 |
msgstr ""
|
1330 |
|
@@ -1346,4 +1429,51 @@ msgstr ""
|
|
1346 |
|
1347 |
#. Author URI of the plugin/theme
|
1348 |
msgid "https://woocommerce.com/"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1349 |
msgstr ""
|
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 4.3.0\n"
|
6 |
+
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/stripe-git\n"
|
7 |
+
"POT-Creation-Date: 2019-10-17 20:55:54+00:00\n"
|
|
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=utf-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
27 |
msgid "Save payment information to my account for future purchases."
|
28 |
msgstr ""
|
29 |
|
30 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:230
|
31 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:216
|
32 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:218
|
33 |
#. translators: 1) dollar amount
|
34 |
#. translators: minimum amount
|
35 |
msgid "Sorry, the minimum allowed order total is %1$s to use this payment method."
|
36 |
msgstr ""
|
37 |
|
38 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:326
|
39 |
#. translators: 1) blog name 2) order number
|
40 |
msgid "%1$s - Order %2$s"
|
41 |
msgstr ""
|
42 |
|
43 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:353
|
44 |
msgid "customer_name"
|
45 |
msgstr ""
|
46 |
|
47 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:354
|
48 |
msgid "customer_email"
|
49 |
msgstr ""
|
50 |
|
51 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:417
|
52 |
#. translators: transaction id
|
53 |
msgid "Stripe charge awaiting payment: %s."
|
54 |
msgstr ""
|
55 |
|
56 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:424
|
57 |
#: includes/class-wc-stripe-order-handler.php:296
|
58 |
+
#: includes/class-wc-stripe-webhook-handler.php:347
|
59 |
+
#: includes/class-wc-stripe-webhook-handler.php:399
|
60 |
#. translators: transaction id
|
61 |
msgid "Stripe charge complete (Charge ID: %s)"
|
62 |
msgstr ""
|
63 |
|
64 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:429
|
65 |
+
#: includes/class-wc-gateway-stripe.php:495
|
66 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:173
|
|
|
67 |
msgid "Payment processing failed. Please retry."
|
68 |
msgstr ""
|
69 |
|
70 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:441
|
71 |
#. translators: transaction id
|
72 |
msgid ""
|
73 |
"Stripe charge authorized (Charge ID: %s). Process order to take payment, or "
|
74 |
"cancel to remove the pre-authorization."
|
75 |
msgstr ""
|
76 |
|
77 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:615
|
78 |
msgid "Invalid payment method. Please input a new card number."
|
79 |
msgstr ""
|
80 |
|
81 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:895
|
82 |
#. translators: 1) dollar amount 2) transaction id 3) refund message
|
83 |
msgid "Refunded %1$s - Refund ID: %2$s - Reason: %3$s"
|
84 |
msgstr ""
|
85 |
|
86 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:895
|
87 |
msgid "Pre-Authorization Released"
|
88 |
msgstr ""
|
89 |
|
90 |
+
#: includes/abstracts/abstract-wc-stripe-payment-gateway.php:913
|
91 |
msgid "There was a problem adding the payment method."
|
92 |
msgstr ""
|
93 |
|
94 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:124
|
95 |
#. translators: 1) A URL that explains Stripe Radar.
|
96 |
msgid ""
|
97 |
"WooCommerce Stripe - We see that you had the \"Require 3D secure when "
|
100 |
"href=\"%s\" target=\"_blank\">here</a>."
|
101 |
msgstr ""
|
102 |
|
103 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:131
|
104 |
#. translators: 1) int version 2) int version
|
105 |
msgid ""
|
106 |
"WooCommerce Stripe - We recently made changes to Stripe that may impact the "
|
107 |
"appearance of your checkout. If your checkout has changed unexpectedly, "
|
108 |
"please follow these <a "
|
109 |
+
"href=\"https://docs.woocommerce.com/document/stripe/#styling\" "
|
110 |
"target=\"_blank\">instructions</a> to fix."
|
111 |
msgstr ""
|
112 |
|
113 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:141
|
114 |
#. translators: 1) int version 2) int version
|
115 |
msgid ""
|
116 |
"WooCommerce Stripe - The minimum PHP version required for this plugin is "
|
117 |
"%1$s. You are running %2$s."
|
118 |
msgstr ""
|
119 |
|
120 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:152
|
121 |
#. translators: 1) int version 2) int version
|
122 |
msgid ""
|
123 |
"WooCommerce Stripe - The minimum WooCommerce version required for this "
|
124 |
"plugin is %1$s. You are running %2$s."
|
125 |
msgstr ""
|
126 |
|
127 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:162
|
128 |
msgid "WooCommerce Stripe - cURL is not installed."
|
129 |
msgstr ""
|
130 |
|
131 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:172
|
132 |
#. translators: 1) link
|
133 |
msgid ""
|
134 |
"Stripe is almost ready. To get started, <a href=\"%s\">set your Stripe "
|
135 |
"account keys</a>."
|
136 |
msgstr ""
|
137 |
|
138 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:183
|
139 |
#. translators: 1) link
|
140 |
msgid ""
|
141 |
"Stripe is in test mode however your test keys may not be valid. Test keys "
|
143 |
"<a href=\"%s\">set your Stripe account keys</a>."
|
144 |
msgstr ""
|
145 |
|
146 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:192
|
147 |
#. translators: 1) link
|
148 |
msgid ""
|
149 |
"Stripe is in live mode however your test keys may not be valid. Live keys "
|
151 |
"<a href=\"%s\">set your Stripe account keys</a>."
|
152 |
msgstr ""
|
153 |
|
154 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:201
|
155 |
#. translators: 1) link
|
156 |
msgid ""
|
157 |
"Stripe is enabled, but a SSL certificate is not detected. Your checkout may "
|
159 |
"target=\"_blank\">SSL certificate</a>"
|
160 |
msgstr ""
|
161 |
|
162 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:206
|
163 |
+
msgid ""
|
164 |
+
"Stripe is now ready for Strong Customer Authentication (SCA) and 3D Secure "
|
165 |
+
"2! <a href=\"%1$s\" target=\"_blank\">Read about SCA</a>"
|
166 |
+
msgstr ""
|
167 |
+
|
168 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:229
|
169 |
#. translators: %1$s Payment method, %2$s List of supported currencies
|
170 |
msgid "%1$s is enabled - it requires store currency to be set to %2$s"
|
171 |
msgstr ""
|
172 |
|
173 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:243
|
174 |
msgid "Action failed. Please refresh the page and retry."
|
175 |
msgstr ""
|
176 |
|
177 |
+
#: includes/admin/class-wc-stripe-admin-notices.php:247
|
178 |
msgid "Cheatin’ huh?"
|
179 |
msgstr ""
|
180 |
|
210 |
|
211 |
#: includes/admin/class-wc-stripe-privacy.php:41
|
212 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:463
|
213 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:527
|
214 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:542
|
215 |
msgid "N/A"
|
216 |
msgstr ""
|
217 |
|
765 |
"your Stripe account keys</a>."
|
766 |
msgstr ""
|
767 |
|
768 |
+
#: includes/class-wc-gateway-stripe.php:191
|
769 |
#. translators: 1) Opening anchor tag 2) closing anchor tag
|
770 |
msgid ""
|
771 |
"If your billing address has been changed for saved payment methods, be sure "
|
772 |
"to remove any %1$ssaved payment methods%2$s on file and re-add them."
|
773 |
msgstr ""
|
774 |
|
775 |
+
#: includes/class-wc-gateway-stripe.php:267
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
776 |
#. translators: link to Stripe testing page
|
777 |
msgid ""
|
778 |
"TEST MODE ENABLED. In test mode, you can use the card number "
|
781 |
"card numbers."
|
782 |
msgstr ""
|
783 |
|
784 |
+
#: includes/class-wc-gateway-stripe.php:306
|
785 |
msgid "Credit or debit card"
|
786 |
msgstr ""
|
787 |
|
788 |
+
#: includes/class-wc-gateway-stripe.php:314
|
789 |
msgid "Card Number"
|
790 |
msgstr ""
|
791 |
|
792 |
+
#: includes/class-wc-gateway-stripe.php:325
|
793 |
msgid "Expiry Date"
|
794 |
msgstr ""
|
795 |
|
796 |
+
#: includes/class-wc-gateway-stripe.php:333
|
797 |
msgid "Card Code (CVC)"
|
798 |
msgstr ""
|
799 |
|
800 |
+
#: includes/class-wc-gateway-stripe.php:408
|
801 |
msgid "Please accept the terms and conditions first"
|
802 |
msgstr ""
|
803 |
|
804 |
+
#: includes/class-wc-gateway-stripe.php:409
|
805 |
msgid "Please fill in required checkout fields first"
|
806 |
msgstr ""
|
807 |
|
808 |
+
#: includes/class-wc-gateway-stripe.php:438
|
809 |
+
#: includes/class-wc-gateway-stripe.php:482
|
810 |
msgid ""
|
811 |
"Sorry, we're not accepting prepaid cards at this time. Your credit card has "
|
812 |
"not been charged. Please try with alternative payment method."
|
813 |
msgstr ""
|
814 |
|
815 |
+
#: includes/class-wc-gateway-stripe.php:439
|
816 |
msgid "Please enter your IBAN account name."
|
817 |
msgstr ""
|
818 |
|
819 |
+
#: includes/class-wc-gateway-stripe.php:440
|
820 |
msgid "Please enter your IBAN account number."
|
821 |
msgstr ""
|
822 |
|
823 |
+
#: includes/class-wc-gateway-stripe.php:441
|
824 |
msgid "We couldn't initiate the payment. Please try again."
|
825 |
msgstr ""
|
826 |
|
827 |
+
#: includes/class-wc-gateway-stripe.php:452
|
828 |
msgid "Billing First Name and Last Name are required."
|
829 |
msgstr ""
|
830 |
|
831 |
+
#: includes/class-wc-gateway-stripe.php:716
|
832 |
#. translators: error message
|
833 |
msgid "This represents the fee Stripe collects for the transaction."
|
834 |
msgstr ""
|
835 |
|
836 |
+
#: includes/class-wc-gateway-stripe.php:717
|
837 |
msgid "Stripe Fee:"
|
838 |
msgstr ""
|
839 |
|
840 |
+
#: includes/class-wc-gateway-stripe.php:753
|
841 |
msgid ""
|
842 |
"This represents the net total that will be credited to your Stripe bank "
|
843 |
"account. This may be in the currency that is set in your Stripe account."
|
844 |
msgstr ""
|
845 |
|
846 |
+
#: includes/class-wc-gateway-stripe.php:754
|
847 |
msgid "Stripe Payout:"
|
848 |
msgstr ""
|
849 |
|
850 |
+
#: includes/class-wc-gateway-stripe.php:801
|
851 |
#: includes/class-wc-stripe-order-handler.php:162
|
852 |
+
#: includes/class-wc-stripe-webhook-handler.php:238
|
853 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:263
|
854 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:271
|
855 |
#: includes/payment-methods/class-wc-gateway-stripe-sepa.php:373
|
856 |
msgid ""
|
857 |
"Sorry, we are unable to process your payment at this time. Please retry "
|
858 |
"later."
|
859 |
msgstr ""
|
860 |
|
861 |
+
#: includes/class-wc-gateway-stripe.php:854
|
862 |
msgid ""
|
863 |
"Almost there!\n"
|
864 |
"\n"
|
866 |
"done is for you to authorize the payment with your bank."
|
867 |
msgstr ""
|
868 |
|
869 |
+
#: includes/class-wc-gateway-stripe.php:1066
|
870 |
+
#: includes/class-wc-stripe-webhook-handler.php:685
|
871 |
+
#: includes/class-wc-stripe-webhook-handler.php:724
|
872 |
#. translators: 1) The error message that was received from Stripe.
|
873 |
msgid "Stripe SCA authentication failed. Reason: %s"
|
874 |
msgstr ""
|
875 |
|
876 |
+
#: includes/class-wc-gateway-stripe.php:1067
|
877 |
msgid "Stripe SCA authentication failed."
|
878 |
msgstr ""
|
879 |
|
906 |
"the issue. (Logging must be enabled to see recorded logs)"
|
907 |
msgstr ""
|
908 |
|
909 |
+
#: includes/class-wc-stripe-customer.php:120
|
910 |
+
#. translators: %1$s First name, %2$s Second name, %3$s Username.
|
911 |
+
msgid "Name: %1$s %2$s, Username: %s"
|
912 |
msgstr ""
|
913 |
|
914 |
+
#: includes/class-wc-stripe-customer.php:131
|
915 |
+
#. translators: %1$s First name, %2$s Second name.
|
916 |
+
msgid "Name: %1$s %2$s, Guest"
|
917 |
msgstr ""
|
918 |
|
919 |
+
#: includes/class-wc-stripe-customer.php:209
|
920 |
msgid "Unable to add payment source."
|
921 |
msgstr ""
|
922 |
|
1007 |
msgstr ""
|
1008 |
|
1009 |
#: includes/class-wc-stripe-order-handler.php:144
|
1010 |
+
#: includes/class-wc-stripe-webhook-handler.php:219
|
1011 |
#: includes/payment-methods/class-wc-gateway-stripe-sepa.php:353
|
1012 |
msgid "This card is no longer available and has been removed."
|
1013 |
msgstr ""
|
1034 |
msgid "SEPA IBAN ending in %s"
|
1035 |
msgstr ""
|
1036 |
|
1037 |
+
#: includes/class-wc-stripe-webhook-handler.php:296
|
1038 |
#. translators: 1) The URL to the order.
|
1039 |
msgid ""
|
1040 |
"A dispute was created for this order. Response is needed. Please go to your "
|
1042 |
"Dashboard</a> to review this dispute."
|
1043 |
msgstr ""
|
1044 |
|
1045 |
+
#: includes/class-wc-stripe-webhook-handler.php:342
|
1046 |
#. translators: partial captured amount
|
1047 |
msgid "This charge was partially captured via Stripe Dashboard in the amount of: %s"
|
1048 |
msgstr ""
|
1049 |
|
1050 |
+
#: includes/class-wc-stripe-webhook-handler.php:428
|
1051 |
msgid "This payment failed to clear."
|
1052 |
msgstr ""
|
1053 |
|
1054 |
+
#: includes/class-wc-stripe-webhook-handler.php:461
|
1055 |
msgid "This payment has cancelled."
|
1056 |
msgstr ""
|
1057 |
|
1058 |
+
#: includes/class-wc-stripe-webhook-handler.php:496
|
1059 |
msgid "Refunded via Stripe Dashboard"
|
1060 |
msgstr ""
|
1061 |
|
1062 |
+
#: includes/class-wc-stripe-webhook-handler.php:496
|
1063 |
+
#: includes/class-wc-stripe-webhook-handler.php:524
|
1064 |
msgid "Pre-Authorization Released via Stripe Dashboard"
|
1065 |
msgstr ""
|
1066 |
|
1067 |
+
#: includes/class-wc-stripe-webhook-handler.php:524
|
1068 |
#. translators: 1) dollar amount 2) transaction id 3) refund message
|
1069 |
msgid "Refunded %1$s - Refund ID: %2$s - %3$s"
|
1070 |
msgstr ""
|
1071 |
|
1072 |
+
#: includes/class-wc-stripe-webhook-handler.php:555
|
1073 |
#. translators: 1) The URL to the order. 2) The reason type.
|
1074 |
msgid ""
|
1075 |
"A review has been opened for this order. Action is needed. Please go to "
|
1077 |
"Dashboard</a> to review the issue. Reason: (%2$s)"
|
1078 |
msgstr ""
|
1079 |
|
1080 |
+
#: includes/class-wc-stripe-webhook-handler.php:588
|
1081 |
#. translators: 1) The reason type.
|
1082 |
msgid "The opened review for this order is now closed. Reason: (%s)"
|
1083 |
msgstr ""
|
1084 |
|
1085 |
+
#: includes/compat/class-wc-stripe-email-failed-authentication-retry.php:29
|
1086 |
+
msgid "Payment Authentication Requested Email"
|
1087 |
+
msgstr ""
|
1088 |
+
|
1089 |
+
#: includes/compat/class-wc-stripe-email-failed-authentication-retry.php:30
|
1090 |
+
msgid ""
|
1091 |
+
"Payment authentication requested emails are sent to chosen recipient(s) "
|
1092 |
+
"when an attempt to automatically process a subscription renewal payment "
|
1093 |
+
"fails because the transaction requires an SCA verification, the customer is "
|
1094 |
+
"requested to authenticate the payment, and a retry rule has been applied to "
|
1095 |
+
"notify the customer again within a certain time period."
|
1096 |
+
msgstr ""
|
1097 |
+
|
1098 |
+
#: includes/compat/class-wc-stripe-email-failed-authentication-retry.php:32
|
1099 |
+
msgid "Automatic renewal payment failed due to authentication required"
|
1100 |
+
msgstr ""
|
1101 |
+
|
1102 |
+
#: includes/compat/class-wc-stripe-email-failed-authentication-retry.php:33
|
1103 |
+
msgid ""
|
1104 |
+
"[{site_title}] Automatic payment failed for {order_number}. Customer asked "
|
1105 |
+
"to authenticate payment and will be notified again {retry_time}"
|
1106 |
+
msgstr ""
|
1107 |
+
|
1108 |
+
#: includes/compat/class-wc-stripe-email-failed-authentication.php:86
|
1109 |
+
msgid "Enable this email notification"
|
1110 |
+
msgstr ""
|
1111 |
+
|
1112 |
+
#: includes/compat/class-wc-stripe-email-failed-preorder-authentication.php:26
|
1113 |
+
msgid "Pre-order Payment Action Needed"
|
1114 |
+
msgstr ""
|
1115 |
+
|
1116 |
+
#: includes/compat/class-wc-stripe-email-failed-preorder-authentication.php:27
|
1117 |
+
msgid ""
|
1118 |
+
"This is an order notification sent to the customer once a pre-order is "
|
1119 |
+
"complete, but additional payment steps are required."
|
1120 |
+
msgstr ""
|
1121 |
+
|
1122 |
+
#: includes/compat/class-wc-stripe-email-failed-preorder-authentication.php:84
|
1123 |
+
#: includes/compat/class-wc-stripe-email-failed-preorder-authentication.php:93
|
1124 |
+
msgid "Payment authorization needed for pre-order {order_number}"
|
1125 |
+
msgstr ""
|
1126 |
+
|
1127 |
+
#: includes/compat/class-wc-stripe-email-failed-renewal-authentication.php:19
|
1128 |
+
msgid "Failed Subscription Renewal SCA Authentication"
|
1129 |
+
msgstr ""
|
1130 |
+
|
1131 |
+
#: includes/compat/class-wc-stripe-email-failed-renewal-authentication.php:20
|
1132 |
+
msgid ""
|
1133 |
+
"Sent to a customer when a renewal fails because the transaction requires an "
|
1134 |
+
"SCA verification. The email contains renewal order information and payment "
|
1135 |
+
"links."
|
1136 |
+
msgstr ""
|
1137 |
+
|
1138 |
+
#: includes/compat/class-wc-stripe-email-failed-renewal-authentication.php:67
|
1139 |
+
msgid ""
|
1140 |
+
"Payment authorization needed for renewal of {site_title} order "
|
1141 |
+
"{order_number}"
|
1142 |
+
msgstr ""
|
1143 |
+
|
1144 |
+
#: includes/compat/class-wc-stripe-email-failed-renewal-authentication.php:76
|
1145 |
+
msgid "Payment authorization needed for renewal of order {order_number}"
|
1146 |
+
msgstr ""
|
1147 |
+
|
1148 |
+
#: includes/compat/class-wc-stripe-pre-orders-compat.php:57
|
1149 |
msgid "Unable to store payment details. Please try again."
|
1150 |
msgstr ""
|
1151 |
|
1152 |
+
#: includes/compat/class-wc-stripe-pre-orders-compat.php:121
|
1153 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:303
|
1154 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:606
|
1155 |
+
msgid "Stripe charge awaiting authentication by user: %s."
|
1156 |
+
msgstr ""
|
1157 |
+
|
1158 |
+
#: includes/compat/class-wc-stripe-pre-orders-compat.php:138
|
1159 |
#. translators: error message
|
1160 |
msgid "Stripe Transaction Failed (%s)"
|
1161 |
msgstr ""
|
1162 |
|
1163 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:88
|
1164 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:97
|
1165 |
msgid ""
|
1166 |
"Update the Payment Method used for all of my active subscriptions "
|
1167 |
"(optional)."
|
1168 |
msgstr ""
|
1169 |
|
1170 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:226
|
1171 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:233
|
1172 |
msgid "Customer not found"
|
1173 |
msgstr ""
|
1174 |
|
1175 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:386
|
1176 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:450
|
1177 |
#. translators: error message
|
1178 |
msgid "A \"Stripe Customer ID\" value is required."
|
1179 |
msgstr ""
|
1180 |
|
1181 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:388
|
1182 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:452
|
1183 |
msgid ""
|
1184 |
"Invalid customer ID. A valid \"Stripe Customer ID\" must begin with "
|
1185 |
"\"cus_\"."
|
1186 |
msgstr ""
|
1187 |
|
1188 |
#: includes/compat/class-wc-stripe-sepa-subs-compat.php:397
|
1189 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:461
|
1190 |
msgid ""
|
1191 |
"Invalid source ID. A valid source \"Stripe Source ID\" must begin with "
|
1192 |
"\"src_\" or \"card_\"."
|
1197 |
msgid "Via SEPA Direct Debit ending in %1$s"
|
1198 |
msgstr ""
|
1199 |
|
1200 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:295
|
1201 |
+
msgid "This transaction requires authentication."
|
|
|
|
|
1202 |
msgstr ""
|
1203 |
|
1204 |
+
#: includes/compat/class-wc-stripe-subs-compat.php:542
|
1205 |
#. translators: 1) card brand 2) last 4 digits
|
1206 |
msgid "Via %1$s card ending in %2$s"
|
1207 |
msgstr ""
|
1208 |
|
1209 |
#: includes/payment-methods/class-wc-gateway-stripe-alipay.php:60
|
1210 |
+
#: woocommerce-gateway-stripe.php:256
|
1211 |
msgid "Stripe Alipay"
|
1212 |
msgstr ""
|
1213 |
|
1236 |
msgstr ""
|
1237 |
|
1238 |
#: includes/payment-methods/class-wc-gateway-stripe-bancontact.php:60
|
1239 |
+
#: woocommerce-gateway-stripe.php:250
|
1240 |
msgid "Stripe Bancontact"
|
1241 |
msgstr ""
|
1242 |
|
1243 |
#: includes/payment-methods/class-wc-gateway-stripe-eps.php:60
|
1244 |
+
#: woocommerce-gateway-stripe.php:253
|
1245 |
msgid "Stripe EPS"
|
1246 |
msgstr ""
|
1247 |
|
1248 |
#: includes/payment-methods/class-wc-gateway-stripe-giropay.php:60
|
1249 |
+
#: woocommerce-gateway-stripe.php:252
|
1250 |
msgid "Stripe Giropay"
|
1251 |
msgstr ""
|
1252 |
|
1253 |
#: includes/payment-methods/class-wc-gateway-stripe-ideal.php:60
|
1254 |
+
#: woocommerce-gateway-stripe.php:254
|
1255 |
msgid "Stripe iDeal"
|
1256 |
msgstr ""
|
1257 |
|
1258 |
#: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:60
|
1259 |
+
#: woocommerce-gateway-stripe.php:258
|
1260 |
msgid "Stripe Multibanco"
|
1261 |
msgstr ""
|
1262 |
|
1285 |
msgstr ""
|
1286 |
|
1287 |
#: includes/payment-methods/class-wc-gateway-stripe-p24.php:60
|
1288 |
+
#: woocommerce-gateway-stripe.php:255
|
1289 |
msgid "Stripe P24"
|
1290 |
msgstr ""
|
1291 |
|
1292 |
#: includes/payment-methods/class-wc-gateway-stripe-sepa.php:75
|
1293 |
+
#: woocommerce-gateway-stripe.php:257
|
1294 |
msgid "Stripe SEPA Direct Debit"
|
1295 |
msgstr ""
|
1296 |
|
1317 |
msgstr ""
|
1318 |
|
1319 |
#: includes/payment-methods/class-wc-gateway-stripe-sofort.php:60
|
1320 |
+
#: woocommerce-gateway-stripe.php:251
|
1321 |
msgid "Stripe SOFORT"
|
1322 |
msgstr ""
|
1323 |
|
1375 |
msgid "Discount"
|
1376 |
msgstr ""
|
1377 |
|
1378 |
+
#: templates/emails/failed-preorder-authentication.php:20
|
1379 |
+
msgid "Authorize the payment now »"
|
1380 |
+
msgstr ""
|
1381 |
+
|
1382 |
+
#: templates/emails/failed-preorder-authentication.php:56
|
1383 |
+
msgid "Thanks for shopping with us."
|
1384 |
+
msgstr ""
|
1385 |
+
|
1386 |
+
#: templates/emails/failed-renewal-authentication-requested.php:35
|
1387 |
+
#: templates/emails/plain/failed-renewal-authentication-requested.php:26
|
1388 |
+
msgid "The renewal order is as follows:"
|
1389 |
+
msgstr ""
|
1390 |
+
|
1391 |
+
#: templates/emails/failed-renewal-authentication.php:12
|
1392 |
+
msgid "Authorize the payment »"
|
1393 |
+
msgstr ""
|
1394 |
+
|
1395 |
#: woocommerce-gateway-stripe.php:32
|
1396 |
#. translators: 1. URL link.
|
1397 |
msgid ""
|
1399 |
"here."
|
1400 |
msgstr ""
|
1401 |
|
1402 |
+
#: woocommerce-gateway-stripe.php:197
|
1403 |
msgid "Settings"
|
1404 |
msgstr ""
|
1405 |
|
1406 |
+
#: woocommerce-gateway-stripe.php:198
|
1407 |
msgid "Docs"
|
1408 |
msgstr ""
|
1409 |
|
1410 |
+
#: woocommerce-gateway-stripe.php:199
|
1411 |
msgid "Support"
|
1412 |
msgstr ""
|
1413 |
|
1429 |
|
1430 |
#. Author URI of the plugin/theme
|
1431 |
msgid "https://woocommerce.com/"
|
1432 |
+
msgstr ""
|
1433 |
+
|
1434 |
+
#: includes/compat/class-wc-stripe-email-failed-authentication.php:84
|
1435 |
+
msgctxt "an email notification"
|
1436 |
+
msgid "Enable/Disable"
|
1437 |
+
msgstr ""
|
1438 |
+
|
1439 |
+
#: templates/emails/failed-preorder-authentication.php:19
|
1440 |
+
#. translators: %s is a link to the payment re-authentication URL.
|
1441 |
+
msgctxt "In failed SCA authentication for a pre-order."
|
1442 |
+
msgid ""
|
1443 |
+
"Your pre-order is now available, but payment cannot be completed "
|
1444 |
+
"automatically. %s"
|
1445 |
+
msgstr ""
|
1446 |
+
|
1447 |
+
#: templates/emails/failed-renewal-authentication-requested.php:23
|
1448 |
+
#: templates/emails/plain/failed-renewal-authentication-requested.php:17
|
1449 |
+
#. translators: %1$s: an order number, %2$s: the customer's full name, %3$s:
|
1450 |
+
#. lowercase human time diff in the form returned by wcs_get_human_time_diff(),
|
1451 |
+
#. e.g. 'in 12 hours'.
|
1452 |
+
msgctxt "In admin renewal failed email"
|
1453 |
+
msgid ""
|
1454 |
+
"The automatic recurring payment for order %1$s from %2$s has failed. The "
|
1455 |
+
"customer was sent an email requesting authentication of payment. If the "
|
1456 |
+
"customer does not authenticate the payment, they will be requested by email "
|
1457 |
+
"again %3$s."
|
1458 |
+
msgstr ""
|
1459 |
+
|
1460 |
+
#: templates/emails/failed-renewal-authentication.php:12
|
1461 |
+
#: templates/emails/plain/failed-renewal-authentication.php:9
|
1462 |
+
#. translators: %1$s: name of the blog, %2$s: link to payment re-authentication
|
1463 |
+
#. URL, note: no full stop due to url at the end
|
1464 |
+
#. translators: %1$s: name of the blog, %2$s: link to checkout payment url,
|
1465 |
+
#. note: no full stop due to url at the end
|
1466 |
+
msgctxt "In failed renewal authentication email"
|
1467 |
+
msgid ""
|
1468 |
+
"The automatic payment to renew your subscription with %1$s has failed. To "
|
1469 |
+
"reactivate the subscription, please login and authorize the renewal from "
|
1470 |
+
"your account page: %2$s"
|
1471 |
+
msgstr ""
|
1472 |
+
|
1473 |
+
#: templates/emails/plain/failed-preorder-authentication.php:10
|
1474 |
+
#. translators: %s is a link to the payment re-authentication URL.
|
1475 |
+
msgctxt "woocommerce-gateway-stripe"
|
1476 |
+
msgid ""
|
1477 |
+
"Your pre-order is now available, but payment cannot be completed "
|
1478 |
+
"automatically. Please complete the payment now: %s"
|
1479 |
msgstr ""
|
@@ -2,9 +2,9 @@
|
|
2 |
Contributors: automattic, royho, akeda, mattyza, bor0, woothemes
|
3 |
Tags: credit card, stripe, apple pay, payment request, google pay, sepa, sofort, bancontact, alipay, giropay, ideal, p24, woocommerce, automattic
|
4 |
Requires at least: 4.4
|
5 |
-
Tested up to: 5.2.
|
6 |
Requires PHP: 5.6
|
7 |
-
Stable tag: 4.
|
8 |
License: GPLv3
|
9 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
10 |
Attributions: thorsten-stripe
|
@@ -113,20 +113,19 @@ If you get stuck, you can ask for help in the Plugin Forum.
|
|
113 |
|
114 |
== Changelog ==
|
115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
= 4.2.5 - 2019-10-02 =
|
117 |
* Fix - WooCommerce Subscriptions that use only the Stripe customer ID can again be renewed
|
118 |
|
119 |
-
= 4.2.4 - 2019-09-18 =
|
120 |
-
* Fix - Unclear error message when email address not completely filled in.
|
121 |
-
* Fix - Add payment request button compatibility with variable subscriptions
|
122 |
-
* Tweak - Do not show payment request button for shippable trial subscription products
|
123 |
-
* Fix - Do not copy the payment intent id when creating a subscription renewal
|
124 |
-
* Fix - Return early from check intent status if no order - props strayobject
|
125 |
-
* Fix - Extend webhook time window from 1 to 5 minutes to match Stripe client
|
126 |
-
* Update - WooCommerce 3.7 compatibility
|
127 |
-
* Update - Apple Pay Domain association file
|
128 |
-
* Update - Grandfather pre-SCA subscription renewals for SCA
|
129 |
-
|
130 |
[See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce-gateway-stripe/master/changelog.txt).
|
131 |
|
132 |
== Upgrade Notice ==
|
2 |
Contributors: automattic, royho, akeda, mattyza, bor0, woothemes
|
3 |
Tags: credit card, stripe, apple pay, payment request, google pay, sepa, sofort, bancontact, alipay, giropay, ideal, p24, woocommerce, automattic
|
4 |
Requires at least: 4.4
|
5 |
+
Tested up to: 5.2.4
|
6 |
Requires PHP: 5.6
|
7 |
+
Stable tag: 4.3.0
|
8 |
License: GPLv3
|
9 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
10 |
Attributions: thorsten-stripe
|
113 |
|
114 |
== Changelog ==
|
115 |
|
116 |
+
= 4.3.0 2019-10-17 =
|
117 |
+
* Add - For WooCommerce Subscriptions optimize the payment flow for subsequent subscription payments when authentication may be required by using the `setup_future_usage` parameter for the first subscription payment
|
118 |
+
* Add - Allow customer to authenticate payment even if they are not charged right away for WooCommerce Subscriptions and Pre-Orders, for example for a WooCommerce Subscription that has a free trial
|
119 |
+
* Add - When an off-session payment requires authentication, create a link for customers to come back to the store to authenticate the payment
|
120 |
+
* Add - Send an email to WooCommerce Subscription and Pre-Orders customers who need to authenticate a payment that was automatically tried on their behalf
|
121 |
+
* Add - When an off-session payment requires authentication, send an email to the admin
|
122 |
+
* Add - Admin notice about SCA-readiness
|
123 |
+
* Fix - Avoid idempotency key errors for Pre-Orders
|
124 |
+
* Fix - Use unique anchor for link about checkout styling changes
|
125 |
+
|
126 |
= 4.2.5 - 2019-10-02 =
|
127 |
* Fix - WooCommerce Subscriptions that use only the Stripe customer ID can again be renewed
|
128 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
[See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce-gateway-stripe/master/changelog.txt).
|
130 |
|
131 |
== Upgrade Notice ==
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit; // Exit if accessed directly
|
4 |
+
}
|
5 |
+
?>
|
6 |
+
|
7 |
+
<?php do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
|
8 |
+
|
9 |
+
<?php
|
10 |
+
$pre_wc_30 = version_compare( WC_VERSION, '3.0', '<' );
|
11 |
+
$billing_email = $pre_wc_30 ? $order->billing_email : $order->get_billing_email();
|
12 |
+
$billing_phone = $pre_wc_30 ? $order->billing_phone : $order->get_billing_phone();
|
13 |
+
|
14 |
+
?>
|
15 |
+
<p><?php
|
16 |
+
echo wp_kses(
|
17 |
+
sprintf(
|
18 |
+
// translators: %s is a link to the payment re-authentication URL.
|
19 |
+
_x( 'Your pre-order is now available, but payment cannot be completed automatically. %s', 'In failed SCA authentication for a pre-order.', 'woocommerce-gateway-stripe' ),
|
20 |
+
'<a href="' . esc_url( $authorization_url ) . '">' . esc_html__( 'Authorize the payment now »', 'woocommerce-gateway-stripe' ) . '</a>'
|
21 |
+
),
|
22 |
+
array( 'a' => array( 'href' => true ) )
|
23 |
+
);
|
24 |
+
?></p>
|
25 |
+
|
26 |
+
<?php if ( $email->get_custom_message() ) : ?>
|
27 |
+
<blockquote><?php echo wpautop( wptexturize( $email->get_custom_message() ) ); ?></blockquote>
|
28 |
+
<?php endif; ?>
|
29 |
+
|
30 |
+
<?php
|
31 |
+
do_action( 'woocommerce_email_before_order_table', $order, false, $plain_text, $email );
|
32 |
+
|
33 |
+
/*
|
34 |
+
* @hooked WC_Emails::order_details() Shows the order details table.
|
35 |
+
* @hooked WC_Structured_Data::generate_order_data() Generates structured data.
|
36 |
+
* @hooked WC_Structured_Data::output_structured_data() Outputs structured data.
|
37 |
+
* @since 2.5.0
|
38 |
+
*/
|
39 |
+
do_action( 'woocommerce_email_order_details', $order, $sent_to_admin, $plain_text, $email );
|
40 |
+
|
41 |
+
/*
|
42 |
+
* @hooked WC_Emails::order_meta() Shows order meta data.
|
43 |
+
*/
|
44 |
+
do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email );
|
45 |
+
|
46 |
+
do_action( 'woocommerce_email_after_order_table', $order, false, $plain_text, $email );
|
47 |
+
|
48 |
+
/*
|
49 |
+
* @hooked WC_Emails::customer_details() Shows customer details
|
50 |
+
* @hooked WC_Emails::email_address() Shows email address
|
51 |
+
*/
|
52 |
+
do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email );
|
53 |
+
|
54 |
+
?>
|
55 |
+
<p>
|
56 |
+
<?php esc_html_e( 'Thanks for shopping with us.', 'woocommerce-gateway-stripe' ); ?>
|
57 |
+
</p>
|
58 |
+
<?php
|
59 |
+
|
60 |
+
/*
|
61 |
+
* @hooked WC_Emails::email_footer() Output the email footer
|
62 |
+
*/
|
63 |
+
do_action( 'woocommerce_email_footer', $email );
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Admin email about payment retry failed due to authentication
|
4 |
+
*
|
5 |
+
* @package WooCommerce_Stripe/Templates/Emails
|
6 |
+
* @version 4.3.0
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
+
exit;
|
11 |
+
}
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Output the email header.
|
15 |
+
*/
|
16 |
+
do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
|
17 |
+
|
18 |
+
<p>
|
19 |
+
<?php
|
20 |
+
echo esc_html(
|
21 |
+
sprintf(
|
22 |
+
// translators: %1$s: an order number, %2$s: the customer's full name, %3$s: lowercase human time diff in the form returned by wcs_get_human_time_diff(), e.g. 'in 12 hours'.
|
23 |
+
_x(
|
24 |
+
'The automatic recurring payment for order %1$s from %2$s has failed. The customer was sent an email requesting authentication of payment. If the customer does not authenticate the payment, they will be requested by email again %3$s.',
|
25 |
+
'In admin renewal failed email',
|
26 |
+
'woocommerce-gateway-stripe'
|
27 |
+
),
|
28 |
+
$order->get_order_number(),
|
29 |
+
$order->get_formatted_billing_full_name(),
|
30 |
+
wcs_get_human_time_diff( $retry->get_time() )
|
31 |
+
)
|
32 |
+
);
|
33 |
+
?>
|
34 |
+
</p>
|
35 |
+
<p><?php esc_html_e( 'The renewal order is as follows:', 'woocommerce-gateway-stripe' ); ?></p>
|
36 |
+
|
37 |
+
<?php
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Shows the order details table.
|
41 |
+
*/
|
42 |
+
do_action( 'woocommerce_email_order_details', $order, $sent_to_admin, $plain_text, $email );
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Shows order meta data.
|
46 |
+
*/
|
47 |
+
do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email );
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Shows customer details, and email address.
|
51 |
+
*/
|
52 |
+
do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email );
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Output the email footer.
|
56 |
+
*/
|
57 |
+
do_action( 'woocommerce_email_footer', $email );
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit; // Exit if accessed directly
|
4 |
+
}
|
5 |
+
?>
|
6 |
+
|
7 |
+
<?php do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
|
8 |
+
|
9 |
+
<p>
|
10 |
+
<?php
|
11 |
+
// translators: %1$s: name of the blog, %2$s: link to payment re-authentication URL, note: no full stop due to url at the end
|
12 |
+
echo wp_kses( sprintf( _x( 'The automatic payment to renew your subscription with %1$s has failed. To reactivate the subscription, please login and authorize the renewal from your account page: %2$s', 'In failed renewal authentication email', 'woocommerce-gateway-stripe' ), esc_html( get_bloginfo( 'name' ) ), '<a href="' . esc_url( $authorization_url ) . '">' . esc_html__( 'Authorize the payment »', 'woocommerce-gateway-stripe' ) . '</a>' ), array( 'a' => array( 'href' => true ) ) ); ?>
|
13 |
+
</p>
|
14 |
+
|
15 |
+
<?php do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); ?>
|
16 |
+
|
17 |
+
<?php do_action( 'woocommerce_email_footer', $email ); ?>
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit; // Exit if accessed directly
|
4 |
+
}
|
5 |
+
|
6 |
+
echo $email_heading . "\n\n";
|
7 |
+
|
8 |
+
printf(
|
9 |
+
// translators: %s is a link to the payment re-authentication URL.
|
10 |
+
_x( 'Your pre-order is now available, but payment cannot be completed automatically. Please complete the payment now: %s', 'woocommerce-gateway-stripe' ),
|
11 |
+
$authorization_url
|
12 |
+
);
|
13 |
+
|
14 |
+
if ( $email->get_custom_message() ) :
|
15 |
+
|
16 |
+
echo "----------\n\n";
|
17 |
+
echo wptexturize( $email->get_custom_message() ) . "\n\n";
|
18 |
+
echo "----------\n\n";
|
19 |
+
|
20 |
+
endif;
|
21 |
+
|
22 |
+
|
23 |
+
echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n";
|
24 |
+
|
25 |
+
do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email );
|
26 |
+
|
27 |
+
echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n";
|
28 |
+
|
29 |
+
echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) );
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Admin email about payment retry failed due to authentication
|
4 |
+
*
|
5 |
+
* @package WooCommerce_Stripe/Templates/Emails
|
6 |
+
* @version 4.3.0
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
+
exit;
|
11 |
+
}
|
12 |
+
|
13 |
+
echo '= ' . $email_heading . " =\n\n";
|
14 |
+
|
15 |
+
printf(
|
16 |
+
// translators: %1$s: an order number, %2$s: the customer's full name, %3$s: lowercase human time diff in the form returned by wcs_get_human_time_diff(), e.g. 'in 12 hours'.
|
17 |
+
_x(
|
18 |
+
'The automatic recurring payment for order %1$s from %2$s has failed. The customer was sent an email requesting authentication of payment. If the customer does not authenticate the payment, they will be requested by email again %3$s.',
|
19 |
+
'In admin renewal failed email',
|
20 |
+
'woocommerce-gateway-stripe'
|
21 |
+
),
|
22 |
+
$order->get_order_number(),
|
23 |
+
$order->get_formatted_billing_full_name(),
|
24 |
+
wcs_get_human_time_diff( $retry->get_time() )
|
25 |
+
) . "\n\n";
|
26 |
+
printf( __( 'The renewal order is as follows:', 'woocommerce-gateway-stripe' ) ) . "\n\n";
|
27 |
+
|
28 |
+
echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n";
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Shows the order details table.
|
32 |
+
*/
|
33 |
+
do_action( 'woocommerce_email_order_details', $order, $sent_to_admin, $plain_text, $email );
|
34 |
+
|
35 |
+
echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n";
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Shows order meta data.
|
39 |
+
*/
|
40 |
+
do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email );
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Shows customer details, and email address.
|
44 |
+
*/
|
45 |
+
do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email );
|
46 |
+
|
47 |
+
echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n";
|
48 |
+
|
49 |
+
echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) );
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
3 |
+
exit; // Exit if accessed directly
|
4 |
+
}
|
5 |
+
|
6 |
+
echo $email_heading . "\n\n";
|
7 |
+
|
8 |
+
// translators: %1$s: name of the blog, %2$s: link to checkout payment url, note: no full stop due to url at the end
|
9 |
+
printf( esc_html_x( 'The automatic payment to renew your subscription with %1$s has failed. To reactivate the subscription, please login and authorize the renewal from your account page: %2$s', 'In failed renewal authentication email', 'woocommerce-gateway-stripe' ), esc_html( get_bloginfo( 'name' ) ), esc_attr( $authorization_url ) );
|
10 |
+
|
11 |
+
echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n";
|
12 |
+
|
13 |
+
do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email );
|
14 |
+
|
15 |
+
echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n";
|
16 |
+
|
17 |
+
echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) );
|
@@ -5,11 +5,11 @@
|
|
5 |
* Description: Take credit card payments on your store using Stripe.
|
6 |
* Author: WooCommerce
|
7 |
* Author URI: https://woocommerce.com/
|
8 |
-
* Version: 4.
|
9 |
* Requires at least: 4.4
|
10 |
-
* Tested up to: 5.2.
|
11 |
* WC requires at least: 2.6
|
12 |
-
* WC tested up to: 3.7
|
13 |
* Text Domain: woocommerce-gateway-stripe
|
14 |
* Domain Path: /languages
|
15 |
*
|
@@ -46,7 +46,7 @@ function woocommerce_gateway_stripe_init() {
|
|
46 |
/**
|
47 |
* Required minimums and constants
|
48 |
*/
|
49 |
-
define( 'WC_STRIPE_VERSION', '4.
|
50 |
define( 'WC_STRIPE_MIN_PHP_VER', '5.6.0' );
|
51 |
define( 'WC_STRIPE_MIN_WC_VER', '2.6.0' );
|
52 |
define( 'WC_STRIPE_MAIN_FILE', __FILE__ );
|
@@ -145,6 +145,9 @@ function woocommerce_gateway_stripe_init() {
|
|
145 |
add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateways' ) );
|
146 |
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
|
147 |
|
|
|
|
|
|
|
148 |
if ( version_compare( WC_VERSION, '3.4', '<' ) ) {
|
149 |
add_filter( 'woocommerce_get_sections_checkout', array( $this, 'filter_gateway_order_admin' ) );
|
150 |
}
|
@@ -256,6 +259,26 @@ function woocommerce_gateway_stripe_init() {
|
|
256 |
|
257 |
return $sections;
|
258 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
}
|
260 |
|
261 |
WC_Stripe::get_instance();
|
5 |
* Description: Take credit card payments on your store using Stripe.
|
6 |
* Author: WooCommerce
|
7 |
* Author URI: https://woocommerce.com/
|
8 |
+
* Version: 4.3.0
|
9 |
* Requires at least: 4.4
|
10 |
+
* Tested up to: 5.2.4
|
11 |
* WC requires at least: 2.6
|
12 |
+
* WC tested up to: 3.7.1
|
13 |
* Text Domain: woocommerce-gateway-stripe
|
14 |
* Domain Path: /languages
|
15 |
*
|
46 |
/**
|
47 |
* Required minimums and constants
|
48 |
*/
|
49 |
+
define( 'WC_STRIPE_VERSION', '4.3.0' );
|
50 |
define( 'WC_STRIPE_MIN_PHP_VER', '5.6.0' );
|
51 |
define( 'WC_STRIPE_MIN_WC_VER', '2.6.0' );
|
52 |
define( 'WC_STRIPE_MAIN_FILE', __FILE__ );
|
145 |
add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateways' ) );
|
146 |
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
|
147 |
|
148 |
+
// Modify emails emails.
|
149 |
+
add_filter( 'woocommerce_email_classes', array( $this, 'add_emails' ), 20 );
|
150 |
+
|
151 |
if ( version_compare( WC_VERSION, '3.4', '<' ) ) {
|
152 |
add_filter( 'woocommerce_get_sections_checkout', array( $this, 'filter_gateway_order_admin' ) );
|
153 |
}
|
259 |
|
260 |
return $sections;
|
261 |
}
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Adds the failed SCA auth email to WooCommerce.
|
265 |
+
*
|
266 |
+
* @param WC_Email[] $email_classes All existing emails.
|
267 |
+
* @return WC_Email[]
|
268 |
+
*/
|
269 |
+
public function add_emails( $email_classes ) {
|
270 |
+
require_once WC_STRIPE_PLUGIN_PATH . '/includes/compat/class-wc-stripe-email-failed-authentication.php';
|
271 |
+
require_once WC_STRIPE_PLUGIN_PATH . '/includes/compat/class-wc-stripe-email-failed-renewal-authentication.php';
|
272 |
+
require_once WC_STRIPE_PLUGIN_PATH . '/includes/compat/class-wc-stripe-email-failed-preorder-authentication.php';
|
273 |
+
require_once WC_STRIPE_PLUGIN_PATH . '/includes/compat/class-wc-stripe-email-failed-authentication-retry.php';
|
274 |
+
|
275 |
+
// Add all emails, generated by the gateway.
|
276 |
+
$email_classes['WC_Stripe_Email_Failed_Renewal_Authentication'] = new WC_Stripe_Email_Failed_Renewal_Authentication( $email_classes );
|
277 |
+
$email_classes['WC_Stripe_Email_Failed_Preorder_Authentication'] = new WC_Stripe_Email_Failed_Preorder_Authentication( $email_classes );
|
278 |
+
$email_classes['WC_Stripe_Email_Failed_Authentication_Retry'] = new WC_Stripe_Email_Failed_Authentication_Retry( $email_classes );
|
279 |
+
|
280 |
+
return $email_classes;
|
281 |
+
}
|
282 |
}
|
283 |
|
284 |
WC_Stripe::get_instance();
|