Compare commits
	
		
			4 Commits
		
	
	
		
			7.x-3.1
			...
			add-metada
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					c0cb9f8f81 | ||
| 
						 | 
					0675dcb249 | ||
| 
						 | 
					8493a9c1f7 | ||
| 
						 | 
					c2a752501f | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
*.patch
 | 
			
		||||
							
								
								
									
										53
									
								
								README.txt
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								README.txt
									
									
									
									
									
								
							@@ -1,8 +1,4 @@
 | 
			
		||||
This is an Ubercart payment gateway module for Stripe. It maintains PCI SAQ A 
 | 
			
		||||
compliance which allows Stripe, the payment processor, to handle prcoessing and 
 | 
			
		||||
storing of payment card details.
 | 
			
		||||
 | 
			
		||||
It is compliant with 3D Secure, 3D Secure 2, and Strong Customer Authentication (SCA)
 | 
			
		||||
This is an Ubercart payment gateway module for Stripe.
 | 
			
		||||
 | 
			
		||||
Versions of the Stripe PHP Library and Stripe API that this module currently
 | 
			
		||||
supports are found in uc_stripe_libraries_info() in uc_stripe.module.
 | 
			
		||||
@@ -19,9 +15,9 @@ section, and enable the gateway under the Payment Gateways.
 | 
			
		||||
c) On that page, provide your Stripe API keys, from
 | 
			
		||||
https://dashboard.stripe.com/account/apikeys
 | 
			
		||||
 | 
			
		||||
d) Download and install the Stripe PHP Library version 6.38.0 with stripe api 
 | 
			
		||||
2019-05-16 or newer from https://github.com/stripe/stripe-php/releases. The 
 | 
			
		||||
recommended technique is to use the command
 | 
			
		||||
d) Download and install the Stripe PHP Library version 2.2.0 or >=3.13.0
 | 
			
		||||
from https://github.com/stripe/stripe-php/releases. The recommended technique is
 | 
			
		||||
to use the command
 | 
			
		||||
 | 
			
		||||
drush ldl stripe
 | 
			
		||||
 | 
			
		||||
@@ -29,7 +25,8 @@ If you don't use "drush ldl stripe", download and install the Stripe library in
 | 
			
		||||
sites/all/libraries/stripe such that the path to VERSION
 | 
			
		||||
is sites/all/libraries/stripe/VERSION. YOU MUST CLEAR THE CACHE AFTER
 | 
			
		||||
CHANGING THE STRIPE PHP LIBRARY. The Libraries module caches its memory of
 | 
			
		||||
libraries like the Stripe Library.
 | 
			
		||||
libraries like the Stripe Library.  (Version 2.2.0 support is maintained for
 | 
			
		||||
existing users; version 3.13.0+ supports PHP 7 and will get ongoing support.)
 | 
			
		||||
(With the latest version of the libraries module you can use the command:
 | 
			
		||||
 | 
			
		||||
e) If you are using recurring payments, install version 2.x
 | 
			
		||||
@@ -51,35 +48,14 @@ disabled on admin/store/settings/payment/method/credit - uc_credit never sees
 | 
			
		||||
the credit card number, so cannot properly validate it (and we don't want it to
 | 
			
		||||
ever know the credit card number.)
 | 
			
		||||
 | 
			
		||||
i) uc_stripe creates it's own payment pane. Ensure the correct ordering by visiting
 | 
			
		||||
store->configuration->checkout (admin/store/settings/checkout).
 | 
			
		||||
 | 
			
		||||
Upgrading from uc_stripe 7.x-2.x
 | 
			
		||||
Upgrading from uc_stripe 6.x-1.x or 7.x-1.x
 | 
			
		||||
===========================================
 | 
			
		||||
 | 
			
		||||
7.x-3.x maintains PCI SAQ A compliance and has major implementation changes from 
 | 
			
		||||
2.x. This version uses it's own payment pane in uc_cart to collect card info.
 | 
			
		||||
The card fields such as card number, expiration date, and cvc code have all been
 | 
			
		||||
 hidden, and is handled entirely by Stripe's Element implementation.
 | 
			
		||||
Which means no credit card information gets processed at all by drupal. The last4,
 | 
			
		||||
and expiration date are sent back to drupal by Stripe's api.
 | 
			
		||||
 | 
			
		||||
7.x-3.x no longer creates a new stripe customer for each order. If a drupal user 
 | 
			
		||||
already has a stripe customer ID, this module will attach future orders to that
 | 
			
		||||
exisiting stripe customer ID.
 | 
			
		||||
 | 
			
		||||
When upgrading from 2.x the ordering of the new stripe payment pane should be
 | 
			
		||||
verified at store->configuration->checkout (admin/store/settings/checkout).
 | 
			
		||||
 | 
			
		||||
An upgrade of the stripe library is required. See installation step d from above.
 | 
			
		||||
 | 
			
		||||
7.x-3.x Uses the uc_recurring module for recurring payments. It is also equipped 
 | 
			
		||||
to handle recurring payments that require authentication (See the uc_recurring 
 | 
			
		||||
steps below). Exisiting recurring payments set up with 7.x-2.x work without any 
 | 
			
		||||
configuration changes.
 | 
			
		||||
 | 
			
		||||
Upgrading from uc_stripe 6.x-1.x or 7.x-1.x 
 | 
			
		||||
============================================
 | 
			
		||||
7.x-2.x does not use Stripe subscriptions for recurring payments, but instead
 | 
			
		||||
uses the uc_recurring module. This means you have control of recurring
 | 
			
		||||
transactions without having to manage them on the Stripe dashboard. (Credit
 | 
			
		||||
card numbers and sensitive data are *not* stored on your site; only the Stripe
 | 
			
		||||
customer ID is stored.)
 | 
			
		||||
 | 
			
		||||
The upgrade hooks, however, must move the customer id stored in the obsolete
 | 
			
		||||
uc_recurring_stripe table into the user table. When this happens the old
 | 
			
		||||
@@ -108,11 +84,6 @@ Recurring payments require automatically triggered renewals using
 | 
			
		||||
uc_recurring_trigger_renewals ("Enabled triggered renewals" must be enabled
 | 
			
		||||
on admin/store/settings/payment/edit/recurring)
 | 
			
		||||
 | 
			
		||||
You should also set your email message for recurring payments that require
 | 
			
		||||
Authentication. The system will email your customers with a link so that they
 | 
			
		||||
can authenticate and have their payment processed.
 | 
			
		||||
(You can edit from here: admin/store/settings/payment/edit/gateways)
 | 
			
		||||
 | 
			
		||||
If you were using Stripe subscriptions in v1 of this module, you may have to
 | 
			
		||||
disable those subscriptions in order to not double-charge your customers.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,5 +30,3 @@ a.poweredbylink:hover {
 | 
			
		||||
#uc_stripe_messages.hidden {display: none;}
 | 
			
		||||
 | 
			
		||||
.stripe-warning {color: red; font-style: oblique; }
 | 
			
		||||
 | 
			
		||||
#edit-panes-payment-details-stripe-card-element{max-width: 600px}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										304
									
								
								js/uc_stripe.js
									
									
									
									
									
								
							
							
						
						
									
										304
									
								
								js/uc_stripe.js
									
									
									
									
									
								
							@@ -9,185 +9,163 @@
 | 
			
		||||
  Drupal.behaviors.uc_stripe = {
 | 
			
		||||
    attach: function (context) {
 | 
			
		||||
 | 
			
		||||
      // Once function prevents stripe from reloading. Any dom changes to stripe area will destroy element
 | 
			
		||||
      // as a Stripe security feature
 | 
			
		||||
      $('#uc-cart-checkout-form', context).once('uc_stripe', function(){
 | 
			
		||||
        
 | 
			
		||||
        var stripe_card_element = '#stripe-card-element';
 | 
			
		||||
        
 | 
			
		||||
        if (Drupal.settings && Drupal.settings.uc_stripe ) {
 | 
			
		||||
          var apikey = Drupal.settings.uc_stripe.apikey;
 | 
			
		||||
          
 | 
			
		||||
          var stripe = Stripe(apikey);
 | 
			
		||||
          var elements = stripe.elements();
 | 
			
		||||
        }
 | 
			
		||||
           
 | 
			
		||||
        
 | 
			
		||||
      // Map stripe names to (partial) Ubercart field names; Ubercart names add "billing_" or "shipping_" on the front.
 | 
			
		||||
        const address_field_mapping = {
 | 
			
		||||
          "address_line1": "street1",
 | 
			
		||||
          "address_line2": "street2",
 | 
			
		||||
          "address_city": "city",
 | 
			
		||||
          "address_state": "zone",
 | 
			
		||||
          "address_zip": "postal_code",
 | 
			
		||||
          "address_country": "country"
 | 
			
		||||
        };
 | 
			
		||||
        var submitButton = $('.uc-cart-checkout-form #edit-continue');
 | 
			
		||||
      const address_field_mapping = {
 | 
			
		||||
        "address_line1": "street1",
 | 
			
		||||
        "address_line2": "street2",
 | 
			
		||||
        "address_city": "city",
 | 
			
		||||
        "address_state": "zone",
 | 
			
		||||
        "address_zip": "postal_code",
 | 
			
		||||
        "address_country": "country"
 | 
			
		||||
      };
 | 
			
		||||
      var submitButton = $('.uc-cart-checkout-form #edit-continue');
 | 
			
		||||
 | 
			
		||||
        // Load the js reference to these fields so that on the review page 
 | 
			
		||||
        // we can input the last 4 and expiration date which is returned to us by stripe paymentMethod call
 | 
			
		||||
        var cc_container = $('.payment-details-credit');
 | 
			
		||||
        var cc_num = cc_container.find(':input[id*="edit-panes-payment-details-cc-numbe"]');
 | 
			
		||||
        var cc_cvv = cc_container.find(':input[id*="edit-panes-payment-details-cc-cv"]');
 | 
			
		||||
        var cc_exp_month = cc_container.find('#edit-panes-payment-details-cc-exp-month');
 | 
			
		||||
        var cc_exp_year = cc_container.find('#edit-panes-payment-details-cc-exp-year');
 | 
			
		||||
      var cc_container = $('.payment-details-credit');
 | 
			
		||||
      var cc_num = cc_container.find(':input[id*="edit-panes-payment-details-cc-numbe"]');
 | 
			
		||||
      var cc_cvv = cc_container.find(':input[id*="edit-panes-payment-details-cc-cv"]');
 | 
			
		||||
 | 
			
		||||
        // Make sure that when the page is being loaded the paymentMethod value is reset
 | 
			
		||||
        // Browser or other caching might do otherwise.
 | 
			
		||||
        $("[name='panes[payment-stripe][details][stripe_payment_method]']").val('default');
 | 
			
		||||
      // Make sure that when the page is being loaded the token value is reset
 | 
			
		||||
      // Browser or other caching might do otherwise.
 | 
			
		||||
      $("[name='panes[payment][details][stripe_token]']").val('default');
 | 
			
		||||
 | 
			
		||||
        // JS must enable the button; otherwise form might disclose cc info. It starts disabled
 | 
			
		||||
        submitButton.attr('disabled', false);
 | 
			
		||||
      $('span#stripe-nojs-warning').parent().hide();
 | 
			
		||||
 | 
			
		||||
        // When this behavior fires, we can clean the form so it will behave properly,
 | 
			
		||||
        // Remove 'name' from sensitive form elements so there's no way they can be submitted.
 | 
			
		||||
        cc_num.removeAttr('name').removeAttr('disabled');
 | 
			
		||||
        $('div.form-item-panes-payment-details-cc-number').removeClass('form-disabled');
 | 
			
		||||
        cc_cvv.removeAttr('name').removeAttr('disabled');
 | 
			
		||||
        var cc_val_val = cc_num.val();
 | 
			
		||||
        if (cc_val_val && cc_val_val.indexOf('Last 4')) {
 | 
			
		||||
          cc_num.val('');
 | 
			
		||||
      // JS must enable the button; otherwise form might disclose cc info. It starts disabled
 | 
			
		||||
      submitButton.attr('disabled', false);
 | 
			
		||||
 | 
			
		||||
      // When this behavior fires, we can clean the form so it will behave properly,
 | 
			
		||||
      // Remove 'name' from sensitive form elements so there's no way they can be submitted.
 | 
			
		||||
      cc_num.removeAttr('name').removeAttr('disabled');
 | 
			
		||||
      $('div.form-item-panes-payment-details-cc-number').removeClass('form-disabled');
 | 
			
		||||
      cc_cvv.removeAttr('name').removeAttr('disabled');
 | 
			
		||||
      var cc_val_val = cc_num.val();
 | 
			
		||||
      if (cc_val_val && cc_val_val.indexOf('Last 4')) {
 | 
			
		||||
        cc_num.val('');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      submitButton.click(function (e) {
 | 
			
		||||
 | 
			
		||||
        // We must find the various fields again, because they may have been swapped
 | 
			
		||||
        // in by ajax action of the form.
 | 
			
		||||
        cc_container = $('.payment-details-credit');
 | 
			
		||||
        cc_num = cc_container.find(':input[id*="edit-panes-payment-details-cc-numbe"]');
 | 
			
		||||
        cc_cvv = cc_container.find(':input[id*="edit-panes-payment-details-cc-cv"]');
 | 
			
		||||
 | 
			
		||||
        // If not credit card processing or no token field, just let the submit go on
 | 
			
		||||
        // Also continue if we've received the tokenValue
 | 
			
		||||
        var tokenField = $("[name='panes[payment][details][stripe_token]']");
 | 
			
		||||
        if (!$("div.payment-details-credit").length || !tokenField.length || tokenField.val().indexOf('tok_') == 0) {
 | 
			
		||||
          return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If we've requested and are waiting for token, prevent any further submit
 | 
			
		||||
        if (tokenField.val() == 'requested') {
 | 
			
		||||
          return false; // Prevent any submit processing until token is received
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
     // Custom styling can be passed to options when creating an Element.
 | 
			
		||||
        var style = {
 | 
			
		||||
          base: {
 | 
			
		||||
            // Add your base input styles here. For example:
 | 
			
		||||
            fontSize: '24px',
 | 
			
		||||
            color: "#000000",
 | 
			
		||||
            iconColor: "blue",
 | 
			
		||||
        // Go ahead and request the token
 | 
			
		||||
        tokenField.val('requested');
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
          var name = undefined;
 | 
			
		||||
 | 
			
		||||
          if ($(':input[name="panes[billing][billing_first_name]"]').length) {
 | 
			
		||||
            name = $(':input[name="panes[billing][billing_first_name]"]').val() + " " + $(':input[name="panes[billing][billing_last_name]"]').val();
 | 
			
		||||
          }
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        // Create an instance of the card Element.
 | 
			
		||||
        var card = elements.create('card', {style: style});
 | 
			
		||||
 | 
			
		||||
        // Add an instance of the card Element into the #stripe-card-element <div>.
 | 
			
		||||
        card.mount(stripe_card_element);
 | 
			
		||||
        
 | 
			
		||||
        // Display errors from stripe
 | 
			
		||||
        card.addEventListener('change', function(event) {
 | 
			
		||||
          var displayError = document.getElementById('uc_stripe_messages');
 | 
			
		||||
          if (event.error) {
 | 
			
		||||
            displayError.textContent = event.error.message;
 | 
			
		||||
            console.log(event.error.message)
 | 
			
		||||
          } else {
 | 
			
		||||
            displayError.textContent = '';
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        submitButton.click(function (e) {
 | 
			
		||||
 | 
			
		||||
          // We must find the various fields again, because they may have been swapped
 | 
			
		||||
          // in by ajax action of the form.
 | 
			
		||||
          cc_container = $('.payment-details-credit');
 | 
			
		||||
          cc_num = cc_container.find(':input[id*="edit-panes-payment-details-cc-numbe"]');
 | 
			
		||||
          cc_cvv = cc_container.find(':input[id*="edit-panes-payment-details-cc-cv"]');
 | 
			
		||||
          cc_exp_year = cc_container.find('#edit-panes-payment-details-cc-exp-month');
 | 
			
		||||
          cc_exp_month = cc_container.find('#edit-panes-payment-details-cc-exp-year');
 | 
			
		||||
 | 
			
		||||
          // If not credit card processing or no payment method field, just let the submit go on
 | 
			
		||||
          // Also continue if we've received the tokenValue
 | 
			
		||||
          var paymentMethodField = $("[name='panes[payment-stripe][details][stripe_payment_method]']");
 | 
			
		||||
          if (!$("div.payment-details-credit").length || !paymentMethodField.length || paymentMethodField.val().indexOf('pm_') == 0) {
 | 
			
		||||
            return true;
 | 
			
		||||
          if (typeof name === "undefined" && $(':input[name="panes[delivery][delivery_first_name]"]').length) {
 | 
			
		||||
            name = $(':input[name="panes[delivery][delivery_first_name]"]').val() + " " + $(':input[name="panes[delivery][delivery_last_name]"]').val();
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // If we've requested and are waiting for token, prevent any further submit
 | 
			
		||||
          if (paymentMethodField.val() == 'requested') {
 | 
			
		||||
            return false; // Prevent any submit processing until token is received
 | 
			
		||||
          }
 | 
			
		||||
          var params = {
 | 
			
		||||
            number: cc_num.val(),
 | 
			
		||||
            cvc: cc_cvv.val(),
 | 
			
		||||
            exp_month: $(':input[name="panes[payment][details][cc_exp_month]"]').val(),
 | 
			
		||||
            exp_year: $(':input[name="panes[payment][details][cc_exp_year]"]').val(),
 | 
			
		||||
            name: name
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          // Go ahead and request the token
 | 
			
		||||
          paymentMethodField.val('requested');
 | 
			
		||||
 | 
			
		||||
          try {
 | 
			
		||||
            
 | 
			
		||||
            stripe.createPaymentMethod('card', card).then(function (response) {
 | 
			
		||||
 | 
			
		||||
              if (response.error) {
 | 
			
		||||
 | 
			
		||||
                // Show the errors on the form
 | 
			
		||||
                $('#uc_stripe_messages')
 | 
			
		||||
                  .removeClass("hidden")
 | 
			
		||||
                  .text(response.error.message);
 | 
			
		||||
                $('#edit-stripe-messages').val(response.error.message);
 | 
			
		||||
 | 
			
		||||
                // Make the fields visible again for retry
 | 
			
		||||
                cc_num
 | 
			
		||||
                  .css('visibility', 'visible')
 | 
			
		||||
                  .val('')
 | 
			
		||||
                  .attr('name', 'panes[payment][details][cc_number]');
 | 
			
		||||
                cc_cvv
 | 
			
		||||
                  .css('visibility', 'visible')
 | 
			
		||||
                  .val('')
 | 
			
		||||
                  .attr('name', 'panes[payment][details][cc_cvv]');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                // Turn off the throbber
 | 
			
		||||
                $('.ubercart-throbber').remove();
 | 
			
		||||
                // Remove the bogus copy of the submit button added in uc_cart.js ucSubmitOrderThrobber
 | 
			
		||||
                submitButton.next().remove();
 | 
			
		||||
                // And show the hidden original button which has the behavior attached to it.
 | 
			
		||||
                submitButton.show();
 | 
			
		||||
 | 
			
		||||
                paymentMethodField.val('default'); // Make sure token field set back to default
 | 
			
		||||
 | 
			
		||||
              } else {
 | 
			
		||||
                // token contains id, last4, and card type
 | 
			
		||||
                var paymentMethodId = response.paymentMethod.id;
 | 
			
		||||
                
 | 
			
		||||
                
 | 
			
		||||
                // Insert the token into the form so it gets submitted to the server
 | 
			
		||||
                paymentMethodField.val(paymentMethodId);
 | 
			
		||||
                
 | 
			
		||||
                // set cc expiration date received from stripe so that it is available on checkout review
 | 
			
		||||
                cc_exp_year.val(response.paymentMethod.card.exp_month);
 | 
			
		||||
                cc_exp_month.val(response.paymentMethod.card.exp_year);
 | 
			
		||||
                
 | 
			
		||||
                // Since we're now submitting, make sure that uc_credit doesn't
 | 
			
		||||
                // find values it objects to; after "fixing" set the name back on the
 | 
			
		||||
                // form element.
 | 
			
		||||
                // add dummy tweleve 5's and the last 4 of credit card so that last 4 show
 | 
			
		||||
                cc_num
 | 
			
		||||
                  .css('visibility', 'hidden')
 | 
			
		||||
                  .val('555555555555' + response.paymentMethod.card.last4)
 | 
			
		||||
                  .attr('name', 'panes[payment][details][cc_number]');
 | 
			
		||||
                cc_cvv
 | 
			
		||||
                  .css('visibility', 'hidden')
 | 
			
		||||
                  .val('999')
 | 
			
		||||
                  .attr('name', 'panes[payment][details][cc_cvv]');
 | 
			
		||||
 | 
			
		||||
                // now actually submit to Drupal. The only "real" things going
 | 
			
		||||
                // are the token and the expiration date and last 4 of cc
 | 
			
		||||
                submitButton.click();
 | 
			
		||||
          // Translate the Ubercart billing/shipping fields to Stripe values
 | 
			
		||||
          for (var key in address_field_mapping) {
 | 
			
		||||
            const prefixes = ['billing', 'delivery'];
 | 
			
		||||
            for (var i = 0; i < prefixes.length; i++) {
 | 
			
		||||
              var prefix = prefixes[i];
 | 
			
		||||
              var uc_field_name = prefix + '_' + address_field_mapping[key];
 | 
			
		||||
              var location = ':input[name="panes[' + prefix + '][' + uc_field_name + ']"]';
 | 
			
		||||
              if ($(location).length) {
 | 
			
		||||
                params[key] = $(location).val();
 | 
			
		||||
                if ($(location).attr('type') == 'select-one') {
 | 
			
		||||
                  params[key] = $(location + " option:selected").text();
 | 
			
		||||
                }
 | 
			
		||||
                break;  // break out of billing/shipping loop because we got the info
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
          } catch (e) {
 | 
			
		||||
            $('#uc_stripe_messages')
 | 
			
		||||
              .removeClass("hidden")
 | 
			
		||||
              .text(e.message);
 | 
			
		||||
            $('#edit-stripe-messages').val(e.message);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // Prevent processing until we get the token back
 | 
			
		||||
          return false;
 | 
			
		||||
        });
 | 
			
		||||
          Stripe.createToken(params, function (status, response) {
 | 
			
		||||
 | 
			
		||||
            if (response.error) {
 | 
			
		||||
 | 
			
		||||
              // Show the errors on the form
 | 
			
		||||
              $('#uc_stripe_messages')
 | 
			
		||||
                .removeClass("hidden")
 | 
			
		||||
                .text(response.error.message);
 | 
			
		||||
              $('#edit-stripe-messages').val(response.error.message);
 | 
			
		||||
 | 
			
		||||
              // Make the fields visible again for retry
 | 
			
		||||
              cc_num
 | 
			
		||||
                .css('visibility', 'visible')
 | 
			
		||||
                .val('')
 | 
			
		||||
                .attr('name', 'panes[payment][details][cc_number]');
 | 
			
		||||
              cc_cvv
 | 
			
		||||
                .css('visibility', 'visible')
 | 
			
		||||
                .val('')
 | 
			
		||||
                .attr('name', 'panes[payment][details][cc_cvv]');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
              // Turn off the throbber
 | 
			
		||||
              $('.ubercart-throbber').remove();
 | 
			
		||||
              // Remove the bogus copy of the submit button added in uc_cart.js ucSubmitOrderThrobber
 | 
			
		||||
              submitButton.next().remove();
 | 
			
		||||
              // And show the hidden original button which has the behavior attached to it.
 | 
			
		||||
              submitButton.show();
 | 
			
		||||
 | 
			
		||||
              tokenField.val('default'); // Make sure token field set back to default
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
              // token contains id, last4, and card type
 | 
			
		||||
              var token = response.id;
 | 
			
		||||
 | 
			
		||||
              // Insert the token into the form so it gets submitted to the server
 | 
			
		||||
              tokenField.val(token);
 | 
			
		||||
 | 
			
		||||
              // Since we're now submitting, make sure that uc_credit doesn't
 | 
			
		||||
              // find values it objects to; after "fixing" set the name back on the
 | 
			
		||||
              // form element.
 | 
			
		||||
              cc_num
 | 
			
		||||
                .css('visibility', 'hidden')
 | 
			
		||||
                .val('555555555555' + response.card.last4)
 | 
			
		||||
                .attr('name', 'panes[payment][details][cc_number]');
 | 
			
		||||
              cc_cvv
 | 
			
		||||
                .css('visibility', 'hidden')
 | 
			
		||||
                .val('999')
 | 
			
		||||
                .attr('name', 'panes[payment][details][cc_cvv]');
 | 
			
		||||
 | 
			
		||||
              // now actually submit to Drupal. The only "real" things going
 | 
			
		||||
              // are the token and the expiration date.
 | 
			
		||||
              submitButton.click();
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          $('#uc_stripe_messages')
 | 
			
		||||
            .removeClass("hidden")
 | 
			
		||||
            .text(e.message);
 | 
			
		||||
          $('#edit-stripe-messages').val(e.message);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Prevent processing until we get the token back
 | 
			
		||||
        return false;
 | 
			
		||||
      });
 | 
			
		||||
      
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
}(jQuery));
 | 
			
		||||
 
 | 
			
		||||
@@ -1,91 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * uc_stripe.js
 | 
			
		||||
 *
 | 
			
		||||
 * Handles all interactions with Stripe on the client side for PCI-DSS compliance
 | 
			
		||||
 */
 | 
			
		||||
(function ($) {
 | 
			
		||||
 | 
			
		||||
  Drupal.behaviors.uc_stripe_process_payment = {
 | 
			
		||||
    attach: function (context) {
 | 
			
		||||
      
 | 
			
		||||
      $('#uc-cart-checkout-review-form, #uc-stripe-authenticate-payment-form', context).once('uc_stripe', function(){
 | 
			
		||||
        
 | 
			
		||||
        if (Drupal.settings && Drupal.settings.uc_stripe ) {
 | 
			
		||||
          var apikey = Drupal.settings.uc_stripe.apikey;
 | 
			
		||||
          var methodId = Drupal.settings.uc_stripe.methodId;
 | 
			
		||||
          var orderId = Drupal.settings.uc_stripe.orderId
 | 
			
		||||
          var stripe = Stripe(apikey);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        var submitButton = $('#edit-submit');
 | 
			
		||||
        var processed = false;
 | 
			
		||||
 | 
			
		||||
        submitButton.click(function (e) {
 | 
			
		||||
          if(!processed){
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
            
 | 
			
		||||
            $.ajax({
 | 
			
		||||
              url: '/uc_stripe/ajax/confirm_payment',
 | 
			
		||||
              type: "POST",
 | 
			
		||||
              data: JSON.stringify({ payment_method_id: methodId, order_id: orderId }),
 | 
			
		||||
              contentType: 'application/json;',
 | 
			
		||||
              dataType: 'json',
 | 
			
		||||
              success: function(result){
 | 
			
		||||
                handleServerResponse(result);
 | 
			
		||||
              },
 | 
			
		||||
              error: function(result){
 | 
			
		||||
                handleServerResponse(result);
 | 
			
		||||
              }
 | 
			
		||||
            })
 | 
			
		||||
            
 | 
			
		||||
          }
 | 
			
		||||
          
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
        function handleServerResponse(response) {
 | 
			
		||||
          if (response.error) {
 | 
			
		||||
            processed = true;
 | 
			
		||||
            submitButton.click();
 | 
			
		||||
            // Show error from server on payment form
 | 
			
		||||
          } else if (response.requires_action) {
 | 
			
		||||
            // Use Stripe.js to handle required card action
 | 
			
		||||
            stripe.handleCardAction(
 | 
			
		||||
              response.payment_intent_client_secret
 | 
			
		||||
            ).then(function(result) {
 | 
			
		||||
              if (result.error) {
 | 
			
		||||
                // Show error in payment form
 | 
			
		||||
                processed = true;
 | 
			
		||||
                submitButton.click();
 | 
			
		||||
              } else {
 | 
			
		||||
                // The card action has been handled
 | 
			
		||||
                // The PaymentIntent can be confirmed again on the server
 | 
			
		||||
                $.ajax({
 | 
			
		||||
                  url: '/uc_stripe/ajax/confirm_payment',
 | 
			
		||||
                  type: 'POST',
 | 
			
		||||
                  data: JSON.stringify({ payment_intent_id: result.paymentIntent.id, order_id: orderId }),
 | 
			
		||||
                  contentType: 'application/json;',
 | 
			
		||||
                  dataType: 'json',
 | 
			
		||||
                  success: function(confirmResult){
 | 
			
		||||
                    return handleServerResponse(confirmResult);
 | 
			
		||||
                  },
 | 
			
		||||
                  error: function(confirmResult){
 | 
			
		||||
                    return handleServerResponse(confirmResult);
 | 
			
		||||
                  },
 | 
			
		||||
                })
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
          } else {
 | 
			
		||||
            // Show success message
 | 
			
		||||
            processed = true;
 | 
			
		||||
            submitButton.click();
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      });
 | 
			
		||||
      
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
}(jQuery));
 | 
			
		||||
@@ -8,8 +8,9 @@ core = 7.x
 | 
			
		||||
php = 5.3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
; Information added by Drupal.org packaging script on 2019-08-08
 | 
			
		||||
version = "7.x-3.1"
 | 
			
		||||
; Information added by Drupal.org packaging script on 2017-05-19
 | 
			
		||||
version = "7.x-2.2+2-dev"
 | 
			
		||||
core = "7.x"
 | 
			
		||||
project = "uc_stripe"
 | 
			
		||||
datestamp = "1565244191"
 | 
			
		||||
datestamp = "1495159090"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -92,57 +92,6 @@ function uc_stripe_install() {
 | 
			
		||||
  variable_set('uc_credit_validate_numbers', FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_uninstall().
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_uninstall() {
 | 
			
		||||
  variable_del('uc_stripe_authenticaiton_required_email');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_schema().
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_schema() {
 | 
			
		||||
  $schema['uc_stripe_pending_auth'] = array(
 | 
			
		||||
    'description' => 'Ubercart Stripe - Track orders pending authentication',
 | 
			
		||||
    'fields' => array(
 | 
			
		||||
      'id' => array(
 | 
			
		||||
        'description' => 'id of entry',
 | 
			
		||||
        'type' => 'serial',
 | 
			
		||||
        'not null' => TRUE
 | 
			
		||||
      ),
 | 
			
		||||
      'order_id' => array(
 | 
			
		||||
        'description' => 'Order Id of pending order',
 | 
			
		||||
        'type' => 'int',
 | 
			
		||||
        'not null' => TRUE
 | 
			
		||||
      ),
 | 
			
		||||
      'rfee_id' => array(
 | 
			
		||||
        'description' => 'Recurring Fee Id of pending order',
 | 
			
		||||
        'type' => 'int',
 | 
			
		||||
        'not null' => TRUE
 | 
			
		||||
      ),
 | 
			
		||||
      'completed' => array(
 | 
			
		||||
        'description' => 'Competion status of this pending order',
 | 
			
		||||
      'type' => 'int',
 | 
			
		||||
      'not null' => TRUE
 | 
			
		||||
      ),
 | 
			
		||||
      'hash' => array (
 | 
			
		||||
        'description' => 'The unqiue has of order and payment id',
 | 
			
		||||
        'type' => 'varchar',
 | 
			
		||||
        'length' => '100',
 | 
			
		||||
        'not null' => TRUE
 | 
			
		||||
      ),
 | 
			
		||||
    ),
 | 
			
		||||
    'unique keys' => array(
 | 
			
		||||
      'hash' => array(
 | 
			
		||||
        'hash'
 | 
			
		||||
      )
 | 
			
		||||
    ),
 | 
			
		||||
    'primary key' => array('id'),
 | 
			
		||||
  );
 | 
			
		||||
  return $schema;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Enable triggered renewals, as uc_recurring manages renewals with this version.
 | 
			
		||||
 */
 | 
			
		||||
@@ -232,52 +181,3 @@ function _uc_stripe_move_customer_id(&$sandbox) {
 | 
			
		||||
    $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * create table to track orders that require extra authentication verification.
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_update_7301() {
 | 
			
		||||
 | 
			
		||||
  $table = array(
 | 
			
		||||
    'description' => 'Ubercart Stripe - Track orders pending authentication',
 | 
			
		||||
    'fields' => array(
 | 
			
		||||
      'id' => array(
 | 
			
		||||
        'description' => 'id of entry',
 | 
			
		||||
        'type' => 'serial',
 | 
			
		||||
        'not null' => TRUE
 | 
			
		||||
      ),
 | 
			
		||||
      'order_id' => array(
 | 
			
		||||
        'description' => 'Order Id of pending order',
 | 
			
		||||
        'type' => 'int',
 | 
			
		||||
        'not null' => TRUE
 | 
			
		||||
      ),
 | 
			
		||||
      'rfee_id' => array(
 | 
			
		||||
        'description' => 'Recurring Fee Id of pending order',
 | 
			
		||||
        'type' => 'int',
 | 
			
		||||
        'not null' => TRUE
 | 
			
		||||
      ),
 | 
			
		||||
      'completed' => array(
 | 
			
		||||
        'description' => 'Competion status of this pending order',
 | 
			
		||||
        'type' => 'int',
 | 
			
		||||
        'not null' => TRUE
 | 
			
		||||
      ),
 | 
			
		||||
      'hash' => array(
 | 
			
		||||
        'description' => 'The unqiue has of order and payment id',
 | 
			
		||||
        'type' => 'varchar',
 | 
			
		||||
        'length' => '100',
 | 
			
		||||
        'not null' => TRUE
 | 
			
		||||
      )
 | 
			
		||||
    ),
 | 
			
		||||
    'unique keys' => array(
 | 
			
		||||
      'hash' => array(
 | 
			
		||||
        'hash'
 | 
			
		||||
      )
 | 
			
		||||
    ),
 | 
			
		||||
    'primary key' => array(
 | 
			
		||||
      'id'
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  db_create_table('uc_stripe_pending_auth', $table);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,62 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This function returns the default off session authention email text.
 | 
			
		||||
 * @return $text - Email text
 | 
			
		||||
 */
 | 
			
		||||
function _uc_stripe_get_authentication_required_email_text(){
 | 
			
		||||
  $text = t("Dear [user:name],
 | 
			
		||||
 | 
			
		||||
We were unable to process your subscription payment.
 | 
			
		||||
 | 
			
		||||
Your financial institution is requesting additional verification before your subscription can be renewed.
 | 
			
		||||
 | 
			
		||||
Please visit this link to return to our site and complete the verification step.
 | 
			
		||||
 | 
			
		||||
[uc_stripe:verification-link]
 | 
			
		||||
 | 
			
		||||
-- [site:name] team
 | 
			
		||||
 | 
			
		||||
");
 | 
			
		||||
 | 
			
		||||
  return $text;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * Token callback that adds the authentication link to user mails.
 | 
			
		||||
 *
 | 
			
		||||
 * This function is used by the token_replace() call in uc_stripe_mail() to add
 | 
			
		||||
 * the url to verify payment information
 | 
			
		||||
 *
 | 
			
		||||
 * @param $replacements
 | 
			
		||||
 *   An associative array variable containing mappings from token names to
 | 
			
		||||
 *   values (for use with strtr()).
 | 
			
		||||
 * @param $data
 | 
			
		||||
 *   An associative array of token replacement values.
 | 
			
		||||
 * @param $options
 | 
			
		||||
 *   Unused parameter required by the token_replace() function. */
 | 
			
		||||
function uc_stripe_mail_tokens(&$replacements, $data, $options) {
 | 
			
		||||
  global $base_url;
 | 
			
		||||
  $replacements['[uc_stripe:verification-link]'] = $base_url.'/stripe/authenticate-payment/'.$data['authentication_key'];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_mail().
 | 
			
		||||
 *
 | 
			
		||||
 * Send mail and replace token with authenticaion link.
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_mail($key, &$message, $params) {
 | 
			
		||||
 | 
			
		||||
  switch ($key) {
 | 
			
		||||
    case 'authentication_required' :
 | 
			
		||||
 | 
			
		||||
      $message['subject'] = t('Additional Verification Required to Process Subscription.');
 | 
			
		||||
      $variables = array('user' => $params['user'], 'authentication_key' => $params['hash']);
 | 
			
		||||
 | 
			
		||||
      $message['body'][]= token_replace($params['body'], $variables, array('language' => language_default(), 'callback' => 'uc_stripe_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE));
 | 
			
		||||
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										709
									
								
								uc_stripe.module
									
									
									
									
									
								
							
							
						
						
									
										709
									
								
								uc_stripe.module
									
									
									
									
									
								
							@@ -14,57 +14,83 @@
 | 
			
		||||
 *
 | 
			
		||||
 * @return mixed
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
module_load_include('inc', 'uc_stripe', 'uc_stripe.mail');
 | 
			
		||||
 | 
			
		||||
function uc_stripe_libraries_info() {
 | 
			
		||||
 | 
			
		||||
  $libraries['stripe'] = array(
 | 
			
		||||
    'name' => 'Stripe PHP Library',
 | 
			
		||||
    'vendor url' => 'http://stripe.com',
 | 
			
		||||
    'download url' => 'https://github.com/stripe/stripe-php/releases',
 | 
			
		||||
    'download file url' => 'https://github.com/stripe/stripe-php/archive/v6.38.0.tar.gz',
 | 
			
		||||
    'download file url' => 'https://github.com/stripe/stripe-php/archive/v3.20.0.tar.gz',
 | 
			
		||||
    'version arguments' => array(
 | 
			
		||||
      'file' => 'VERSION',
 | 
			
		||||
      'pattern' => '/(\d+\.\d+\.\d+)/',
 | 
			
		||||
    ),
 | 
			
		||||
    'versions' => array(
 | 
			
		||||
      '6.38.0' => array(
 | 
			
		||||
      '2.2.0' => array(
 | 
			
		||||
        'files' => array(
 | 
			
		||||
          'php' => array(
 | 
			
		||||
            'lib/Util/RequestOptions.php',
 | 
			
		||||
            'lib/Util/Set.php',
 | 
			
		||||
            'lib/Util/Util.php',
 | 
			
		||||
            'lib/Object.php',
 | 
			
		||||
            'lib/ApiResource.php',
 | 
			
		||||
            'lib/Account.php',
 | 
			
		||||
            'lib/ExternalAccount.php',
 | 
			
		||||
            'lib/AlipayAccount.php',
 | 
			
		||||
            'lib/ApiRequestor.php',
 | 
			
		||||
            'lib/ApplicationFee.php',
 | 
			
		||||
            'lib/ApplicationFeeRefund.php',
 | 
			
		||||
            'lib/AttachedObject.php',
 | 
			
		||||
            'lib/SingletonApiResource.php',
 | 
			
		||||
            'lib/Balance.php',
 | 
			
		||||
            'lib/BalanceTransaction.php',
 | 
			
		||||
            'lib/BankAccount.php',
 | 
			
		||||
            'lib/BitcoinReceiver.php',
 | 
			
		||||
            'lib/BitcoinTransaction.php',
 | 
			
		||||
            'lib/Card.php',
 | 
			
		||||
            'lib/Charge.php',
 | 
			
		||||
            'lib/Collection.php',
 | 
			
		||||
            'lib/Coupon.php',
 | 
			
		||||
            'lib/Customer.php',
 | 
			
		||||
            'lib/Error/Base.php',
 | 
			
		||||
            'lib/Error/Api.php',
 | 
			
		||||
            'lib/Error/ApiConnection.php',
 | 
			
		||||
            'lib/Error/Authentication.php',
 | 
			
		||||
            'lib/Error/Card.php',
 | 
			
		||||
            'lib/Error/InvalidRequest.php',
 | 
			
		||||
            'lib/Error/RateLimit.php',
 | 
			
		||||
            'lib/Event.php',
 | 
			
		||||
            'lib/FileUpload.php',
 | 
			
		||||
            'lib/HttpClient/ClientInterface.php',
 | 
			
		||||
            'lib/HttpClient/CurlClient.php',
 | 
			
		||||
            'lib/Invoice.php',
 | 
			
		||||
            'lib/InvoiceItem.php',
 | 
			
		||||
            'lib/Plan.php',
 | 
			
		||||
            'lib/Recipient.php',
 | 
			
		||||
            'lib/Refund.php',
 | 
			
		||||
            'lib/Stripe.php',
 | 
			
		||||
            'lib/Subscription.php',
 | 
			
		||||
            'lib/Token.php',
 | 
			
		||||
            'lib/Transfer.php',
 | 
			
		||||
            'lib/TransferReversal.php',
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        'stripe_api_version' => '2015-06-15',
 | 
			
		||||
      ),
 | 
			
		||||
      '3.0' => array(
 | 
			
		||||
        'files' => array(
 | 
			
		||||
          'php' => array(
 | 
			
		||||
            'init.php',
 | 
			
		||||
          )
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        'stripe_api_version' => '2019-05-16'
 | 
			
		||||
      )
 | 
			
		||||
        'stripe_api_version' => '2016-03-07',
 | 
			
		||||
      ),
 | 
			
		||||
    ),
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return $libraries;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_menu().
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_menu() {
 | 
			
		||||
  $items = array();
 | 
			
		||||
 | 
			
		||||
  $items['uc_stripe/ajax/confirm_payment'] = array(
 | 
			
		||||
    'access callback' => true,
 | 
			
		||||
    'page callback' => '_uc_stripe_confirm_payment',
 | 
			
		||||
    'delivery callback' => 'drupal_json_output',
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $items['stripe/authenticate-payment/%'] = array(
 | 
			
		||||
    'access callback' => true,
 | 
			
		||||
    'page callback' => 'drupal_get_form',
 | 
			
		||||
    'page arguments' => array('uc_stripe_authenticate_payment_form', 2),
 | 
			
		||||
    'file' => 'uc_stripe.pages.inc'
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  return $items;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_payment_gateway to register this payment gateway
 | 
			
		||||
 * @return array
 | 
			
		||||
@@ -105,47 +131,6 @@ function uc_stripe_recurring_info() {
 | 
			
		||||
  return $items;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_form_FORMID_alter() to do JS Stripe processing when processing
 | 
			
		||||
 * from the order review page
 | 
			
		||||
 *
 | 
			
		||||
 * @param unknown $form
 | 
			
		||||
 * @param unknown $form_state
 | 
			
		||||
 * @param unknown $form_id
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_form_uc_cart_checkout_review_form_alter(&$form, &$form_state, $form_id){
 | 
			
		||||
 | 
			
		||||
  //This alter hook should only take action when payment method is credit.
 | 
			
		||||
  if($form_state['uc_order']->payment_method != 'credit'){
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If payment method is not found, hide submit button, and show error to user
 | 
			
		||||
  if (empty($_SESSION['stripe']['payment_method'])) {
 | 
			
		||||
    $form['actions']['submit']['#type'] = 'hidden';
 | 
			
		||||
    $fail_message = variable_get('uc_credit_fail_message', t('We were unable to process your credit card payment. Please verify your details and try again.  If the problem persists, contact us to complete your order.'));
 | 
			
		||||
    watchdog('uc_stripe', 'Stripe charge failed for order @order, message: @message', array('@order' => $form_state['uc_order']->order_id, '@message' => 'Payment method not found'));
 | 
			
		||||
    drupal_set_message($fail_message, 'error');
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // When a payment fails, remove the Submit Order button because it will most
 | 
			
		||||
  // likely fail again. Instead, the customer should hit back to try again.
 | 
			
		||||
  if(isset($_SESSION['stripe']['payment_failed'])){
 | 
			
		||||
    $form['actions']['submit']['#type'] = 'hidden';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $stripe_payment_method_id = $_SESSION['stripe']['payment_method'];
 | 
			
		||||
  $order_id = $form_state['uc_order']->order_id;
 | 
			
		||||
  $apikey = variable_get('uc_stripe_testmode', TRUE) ? check_plain(variable_get('uc_stripe_api_key_test_publishable', '')) : check_plain(variable_get('uc_stripe_api_key_live_publishable', ''));
 | 
			
		||||
  $settings = array('methodId' => $stripe_payment_method_id, 'apikey' => $apikey, 'orderId' => $order_id);
 | 
			
		||||
 | 
			
		||||
  //Attach Stripe v3 JS library and JS for processing payment
 | 
			
		||||
  $form['#attached']['js']['https://js.stripe.com/v3/'] = array('type' => 'external');
 | 
			
		||||
  $form['#attached']['js'][] = array('data' => array('uc_stripe' => $settings), 'type' => 'setting');
 | 
			
		||||
  $form['#attached']['js'][] = drupal_get_path('module', 'uc_stripe') . '/js/uc_stripe_process_payment.js';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_form_FORMID_alter() to change the checkout form
 | 
			
		||||
@@ -157,49 +142,37 @@ function uc_stripe_form_uc_cart_checkout_review_form_alter(&$form, &$form_state,
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_form_uc_cart_checkout_form_alter(&$form, &$form_state) {
 | 
			
		||||
 | 
			
		||||
  $form['panes']['payment-stripe']['#attached']['css'][] = array(
 | 
			
		||||
      'data' => '#payment-stripe-pane { display: none; }',
 | 
			
		||||
      'type' => 'inline',
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $form['panes']['payment-stripe']['#states'] = array(
 | 
			
		||||
    'visible' => array(
 | 
			
		||||
      ':input[name="panes[payment][payment_method]"]' => array(
 | 
			
		||||
        'value' => 'credit'
 | 
			
		||||
      )
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $stripe_payment_form = &$form['panes']['payment-stripe']['details'];
 | 
			
		||||
  $payment_form = &$form['panes']['payment']['details'];
 | 
			
		||||
 | 
			
		||||
  // Markup text will not be displayed when JS and stripe are functioning properly
 | 
			
		||||
  // since Stripe Elements will replace the contents of this div
 | 
			
		||||
  $stripe_payment_form['stripe_card_element'] = array(
 | 
			
		||||
    '#prefix' => '<div id="stripe-card-element">',
 | 
			
		||||
    '#weight' => - 10,
 | 
			
		||||
    '#markup' => '<div class="stripe-warning">' . t('Sorry, for security reasons your card cannot be processed. Please refresh this page and try again. If the problem persists please check that Javascript is enabled your browser.') . '</div>',
 | 
			
		||||
    '#suffix' => '</div>',
 | 
			
		||||
  $payment_form['stripe_nojs_warning'] = array(
 | 
			
		||||
    '#type' => 'item',
 | 
			
		||||
    '#markup' => '<span id="stripe-nojs-warning" class="stripe-warning">' . t('Sorry, for security reasons your card cannot be processed because Javascript is disabled in your browser.') . '</span>',
 | 
			
		||||
    '#weight' => -1000,
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  // Powered by Stripe (logo from https://stripe.com/about/resources)
 | 
			
		||||
  if (variable_get('uc_stripe_poweredby', FALSE)) {
 | 
			
		||||
    $payment_form['field_message'] = array(
 | 
			
		||||
      '#type' => 'item',
 | 
			
		||||
      '#markup' => "<a target='_blank' href='http://stripe.com'><img src=" . '/' . drupal_get_path('module', 'uc_stripe') . '/images/solid-dark.svg' . " alt='Powered by Stripe'></a>",
 | 
			
		||||
      '#markup' => "<a href='http://stripe.com'><img src=" . '/' . drupal_get_path('module', 'uc_stripe') . '/images/solid-dark.svg' . " alt='Powered by Stripe'></a>",
 | 
			
		||||
      '#weight' => 1,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Used for payment method Id when retrieved from stripe.
 | 
			
		||||
  $stripe_payment_form['stripe_payment_method'] = array(
 | 
			
		||||
  $payment_form['stripe_token'] = array(
 | 
			
		||||
    '#type' => 'hidden',
 | 
			
		||||
    '#default_value' => 'default',
 | 
			
		||||
    '#attributes' => array(
 | 
			
		||||
      'id' => 'edit-panes-stripe-payment-details-stripe-payment-method',
 | 
			
		||||
      'id' => 'edit-panes-payment-details-stripe-token',
 | 
			
		||||
    ),
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  // Prevent form Credit card fill and submission if javascript has not removed
 | 
			
		||||
  // the "disabled" attributes..
 | 
			
		||||
  // If JS happens to be disabled, we don't want user to be able to enter CC data.
 | 
			
		||||
  // Note that we can't use '#disabled', as it causes Form API to discard all input,
 | 
			
		||||
  // so use the disabled attribute instead.
 | 
			
		||||
  $form['panes']['payment']['details']['cc_number']['#attributes']['disabled'] = 'disabled';
 | 
			
		||||
  if (empty($form['actions']['continue']['#attributes'])) {
 | 
			
		||||
    $form['actions']['continue']['#attributes'] = array();
 | 
			
		||||
  }
 | 
			
		||||
@@ -207,38 +180,13 @@ function uc_stripe_form_uc_cart_checkout_form_alter(&$form, &$form_state) {
 | 
			
		||||
 | 
			
		||||
  $apikey = variable_get('uc_stripe_testmode', TRUE) ? check_plain(variable_get('uc_stripe_api_key_test_publishable', '')) : check_plain(variable_get('uc_stripe_api_key_live_publishable', ''));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // Add custom JS and CSS
 | 
			
		||||
  $settings = array('apikey' => $apikey);
 | 
			
		||||
  $form['#attached']['js']['https://js.stripe.com/v3/'] = array('type' => 'external');
 | 
			
		||||
  $form['#attached']['js'][] = array('data' => array('uc_stripe' => $settings), 'type' => 'setting');
 | 
			
		||||
  $form['#attached']['js']['https://js.stripe.com/v2/'] = array('type' => 'external');
 | 
			
		||||
  $form['#attached']['js'][] = array('data' => "Stripe.setPublishableKey('$apikey')", 'type' => 'inline');
 | 
			
		||||
  $form['#attached']['js'][] = drupal_get_path('module', 'uc_stripe') . '/js/uc_stripe.js';
 | 
			
		||||
  $form['#attached']['css'][] = drupal_get_path('module', 'uc_stripe') . '/css/uc_stripe.css';
 | 
			
		||||
 | 
			
		||||
  // hide cc fields and set defaults since we rely fully on stripe's dynamic cc fields
 | 
			
		||||
  $payment_form['cc_number']['#type'] = 'hidden';
 | 
			
		||||
  $payment_form['cc_number']['#default_value'] = '';
 | 
			
		||||
  $payment_form['cc_number']['#attributes']['id'] = 'edit-panes-payment-details-cc-number';
 | 
			
		||||
 | 
			
		||||
  $payment_form['cc_cvv']['#type'] = 'hidden';
 | 
			
		||||
  $payment_form['cc_cvv']['#default_value'] = '';
 | 
			
		||||
  $payment_form['cc_cvv']['#attributes']['id'] = 'edit-panes-payment-details-cc-cvv';
 | 
			
		||||
 | 
			
		||||
  $payment_form['cc_exp_year']['#type'] = 'hidden';
 | 
			
		||||
  $payment_form['cc_exp_year']['#attributes']['id'] = 'edit-panes-payment-details-cc-exp-year';
 | 
			
		||||
 | 
			
		||||
  //Stripe CC expiration can be up to 50 years in future. The normal ubercart  select
 | 
			
		||||
  // options only go up to 20 years in the future.
 | 
			
		||||
  $min = intval(date('Y'));
 | 
			
		||||
  $max = intval(date('Y')) + 50;
 | 
			
		||||
  $default = intval(date('Y'));
 | 
			
		||||
 | 
			
		||||
  $payment_form['cc_exp_year']['#options'] = drupal_map_assoc(range($min, $max));
 | 
			
		||||
  $payment_form['cc_exp_year']['#default_value'] = $default;
 | 
			
		||||
 | 
			
		||||
  $payment_form['cc_exp_month']['#type'] = 'hidden';
 | 
			
		||||
  $payment_form['cc_exp_month']['#default_value'] = 1;
 | 
			
		||||
  $payment_form['cc_exp_month']['#attributes']['id'] = 'edit-panes-payment-details-cc-exp-month';
 | 
			
		||||
 | 
			
		||||
  // Add custom submit which will do saving away of token during submit.
 | 
			
		||||
  $form['#submit'][] = 'uc_stripe_checkout_form_customsubmit';
 | 
			
		||||
 | 
			
		||||
@@ -247,11 +195,6 @@ function uc_stripe_form_uc_cart_checkout_form_alter(&$form, &$form_state) {
 | 
			
		||||
    '#markup' => "<div id='uc_stripe_messages' class='messages error hidden'></div>",
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  //Clear any previous card payment failures
 | 
			
		||||
  if(isset($_SESSION['stripe']['payment_failed'])){
 | 
			
		||||
    unset($_SESSION['stripe']['payment_failed']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (uc_credit_default_gateway() == 'uc_stripe') {
 | 
			
		||||
    if (variable_get('uc_stripe_testmode', TRUE)) {
 | 
			
		||||
      $form['panes']['testmode'] = array(
 | 
			
		||||
@@ -283,51 +226,6 @@ function uc_stripe_uc_order_pane() {
 | 
			
		||||
  return $panes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_uc_checkout_pane to add checkout pane for stripe payment details
 | 
			
		||||
 *
 | 
			
		||||
 * @return array
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_uc_checkout_pane() {
 | 
			
		||||
  $panes['payment-stripe'] = array(
 | 
			
		||||
    'callback' => '_uc_stripe_payment_pane_callback',
 | 
			
		||||
    'title' => t('Payment Information'),
 | 
			
		||||
    'desc' => t("Accept stripe payment from customer."),
 | 
			
		||||
    'weight' => 6,
 | 
			
		||||
    'process' => FALSE,
 | 
			
		||||
    'collapsible' => FALSE,
 | 
			
		||||
  );
 | 
			
		||||
  return $panes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements uc_checkout_pane_callback() specified in 'callback' of
 | 
			
		||||
 * uc_stripe_uc_checkout_pane()
 | 
			
		||||
 *
 | 
			
		||||
 * Provides empty pane for stripe elements to be added
 | 
			
		||||
 * @param $op
 | 
			
		||||
 * @param $order
 | 
			
		||||
 * @param $form
 | 
			
		||||
 * @param $form_state
 | 
			
		||||
 * @return array
 | 
			
		||||
 */
 | 
			
		||||
function _uc_stripe_payment_pane_callback($op, $order, $form = NULL, &$form_state = NULL) {
 | 
			
		||||
  // Create separate payment pane for stripe because the normal payment pane is refreshed many times
 | 
			
		||||
  // by ajax, by country changes, etc.. Refreshing the payment section triggers Stripe Api's security feature
 | 
			
		||||
  // and destroys the Stripe Element in the DOM.
 | 
			
		||||
  // Emtpy values needed so that pane still appears.
 | 
			
		||||
  switch ($op) {
 | 
			
		||||
    case 'view':
 | 
			
		||||
      $description = t('');
 | 
			
		||||
      $contents['stripe_card_element'] = array(
 | 
			
		||||
          '#markup' => '',
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      return array('description' => $description, 'contents' => $contents);
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_uc_checkout_complete()
 | 
			
		||||
 *
 | 
			
		||||
@@ -339,15 +237,12 @@ function _uc_stripe_payment_pane_callback($op, $order, $form = NULL, &$form_stat
 | 
			
		||||
function uc_stripe_uc_checkout_complete($order, $account) {
 | 
			
		||||
 | 
			
		||||
  if ($order->payment_method == "credit") {
 | 
			
		||||
    // Pull the stripe payment method ID from the session.
 | 
			
		||||
    // Pull the stripe customer ID from the session.
 | 
			
		||||
    // It got there in uc_stripe_checkout_form_customsubmit()
 | 
			
		||||
    $stripe_payment_id = $_SESSION['stripe']['payment_method'];
 | 
			
		||||
 | 
			
		||||
    $stripe_customer_id = $order->data['stripe_customer_id'];
 | 
			
		||||
    $stripe_customer_id = $_SESSION['stripe']['customer_id'];
 | 
			
		||||
 | 
			
		||||
    $loaded_user = user_load($account->uid);
 | 
			
		||||
    user_save($loaded_user, array('data' => array('uc_stripe_customer_id' => $stripe_customer_id)));
 | 
			
		||||
    user_save($loaded_user, array('data' => array('uc_stripe_payment_id' => $stripe_payment_id)));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -414,15 +309,6 @@ function uc_stripe_settings_form() {
 | 
			
		||||
    '#description' => t('Your Live Stripe API Key. Must be the "publishable" key, not the "secret" one.'),
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $email_text = _uc_stripe_get_authentication_required_email_text();
 | 
			
		||||
 | 
			
		||||
  $form['uc_stripe_settings']['uc_stripe_authenticaiton_required_email'] = array(
 | 
			
		||||
    '#type' => 'textarea',
 | 
			
		||||
    '#title' => t('Email for Recurring payment authentication'),
 | 
			
		||||
    '#default_value' => variable_get('uc_stripe_authenticaiton_required_email', $email_text),
 | 
			
		||||
    '#description' => t('If your site uses recurring payments, some transactions will require the customer to return to the site and authenticate before the subscrption payment can be processed.')
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $form['uc_stripe_settings']['uc_stripe_testmode'] = array(
 | 
			
		||||
    '#type' => 'checkbox',
 | 
			
		||||
    '#title' => t('Test mode'),
 | 
			
		||||
@@ -437,6 +323,20 @@ function uc_stripe_settings_form() {
 | 
			
		||||
    '#default_value' => variable_get('uc_stripe_poweredby', FALSE),
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $form['uc_stripe_settings']['uc_stripe_metadata_titles'] = array(
 | 
			
		||||
    '#type' => 'checkbox',
 | 
			
		||||
    '#title' => t('Metadata: Title'),
 | 
			
		||||
    '#description' => t('Include order item title(s) in Stripe metadata.'),
 | 
			
		||||
    '#default_value' => variable_get('uc_stripe_metadata_titles', FALSE),
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
    $form['uc_stripe_settings']['uc_stripe_metadata_models'] = array(
 | 
			
		||||
    '#type' => 'checkbox',
 | 
			
		||||
    '#title' => t('Metadata: Model'),
 | 
			
		||||
    '#description' => t('Include item model(s) (SKU(s)) in Stripe metadata.'),
 | 
			
		||||
    '#default_value' => variable_get('uc_stripe_metadata_models', FALSE),
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return $form;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -510,8 +410,8 @@ function _uc_stripe_validate_key($key) {
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_checkout_form_customsubmit($form, &$form_state) {
 | 
			
		||||
  // This submit may be entered on another payment type, so don't set session in that case.
 | 
			
		||||
  if (!empty($form_state['values']['panes']['payment-stripe']['details']['stripe_payment_method'])) {
 | 
			
		||||
    $_SESSION['stripe']['payment_method'] = $form_state['values']['panes']['payment-stripe']['details']['stripe_payment_method'];
 | 
			
		||||
  if (!empty($form_state['values']['panes']['payment']['details']['stripe_token'])) {
 | 
			
		||||
    $_SESSION['stripe']['token'] = $form_state['values']['panes']['payment']['details']['stripe_token'];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -557,6 +457,85 @@ function uc_stripe_charge($order_id, $amount, $data) {
 | 
			
		||||
  // Format the amount in cents, which is what Stripe wants
 | 
			
		||||
  $amount = uc_currency_format($amount, FALSE, FALSE, FALSE);
 | 
			
		||||
 | 
			
		||||
  $stripe_customer_id = FALSE;
 | 
			
		||||
 | 
			
		||||
  // If the user running the order is not the order's owner
 | 
			
		||||
  // (like if an admin is processing an order on someone's behalf)
 | 
			
		||||
  // then load the customer ID from the user object.
 | 
			
		||||
  // Otherwise, make a brand new customer each time a user checks out.
 | 
			
		||||
  if ($user->uid != $order->uid) {
 | 
			
		||||
    $stripe_customer_id = _uc_stripe_get_customer_id($order->uid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // Always Create a new customer in stripe for new orders
 | 
			
		||||
 | 
			
		||||
  if (!$stripe_customer_id) {
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      // If the token is not in the user's session, we can't set up a new customer
 | 
			
		||||
      if (empty($_SESSION['stripe']['token'])) {
 | 
			
		||||
        throw new Exception('Token not found');
 | 
			
		||||
      }
 | 
			
		||||
      $stripe_token = $_SESSION['stripe']['token'];
 | 
			
		||||
 | 
			
		||||
      $shipping_info = array();
 | 
			
		||||
      if (!empty($order->delivery_postal_code)) {
 | 
			
		||||
        $shipping_info = array(
 | 
			
		||||
          'name' => @"{$order->delivery_first_name} {$order->delivery_last_name}",
 | 
			
		||||
          'phone' => @$order->delivery_phone,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $delivery_country = uc_get_country_data(array('country_id' => $order->delivery_country));
 | 
			
		||||
        if ($delivery_country === FALSE) {
 | 
			
		||||
          $delivery_country = array(0 => array('country_iso_code_2' => 'US'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $shipping_info['address'] = array(
 | 
			
		||||
          'city' => @$order->delivery_city,
 | 
			
		||||
          'country' => @$delivery_country[0]['country_iso_code_2'],
 | 
			
		||||
          'line1' => @$order->delivery_street1,
 | 
			
		||||
          'line2' => @$order->delivery_street2,
 | 
			
		||||
          'postal_code' => @$order->delivery_postal_code,
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      $params = array(
 | 
			
		||||
        "source" => $stripe_token,
 | 
			
		||||
        'description' => "OrderID: {$order->order_id}",
 | 
			
		||||
        'email' => "$order->primary_email"
 | 
			
		||||
      );
 | 
			
		||||
      if (!empty($shipping_info)) {
 | 
			
		||||
        $params['shipping'] = $shipping_info;
 | 
			
		||||
      }
 | 
			
		||||
      //Create the customer in stripe
 | 
			
		||||
      $customer = \Stripe\Customer::create($params);
 | 
			
		||||
 | 
			
		||||
      // Store the customer ID in the session,
 | 
			
		||||
      // We'll pick it up later to save it in the database since we might not have a $user object at this point anyway
 | 
			
		||||
      $stripe_customer_id = $_SESSION['stripe']['customer_id'] = $customer->id;
 | 
			
		||||
 | 
			
		||||
    } catch (Exception $e) {
 | 
			
		||||
      $result = array(
 | 
			
		||||
        'success' => FALSE,
 | 
			
		||||
        'comment' => $e->getCode(),
 | 
			
		||||
        'message' => t("Stripe Customer Creation Failed for order !order: !message", array(
 | 
			
		||||
          "!order" => $order_id,
 | 
			
		||||
          "!message" => $e->getMessage()
 | 
			
		||||
        )),
 | 
			
		||||
        'uid' => $user->uid,
 | 
			
		||||
        'order_id' => $order_id,
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      uc_order_comment_save($order_id, $user->uid, $result['message'], 'admin');
 | 
			
		||||
 | 
			
		||||
      watchdog('uc_stripe', 'Failed stripe customer creation: @message', array('@message' => $result['message']));
 | 
			
		||||
 | 
			
		||||
      return $result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //  Charge the stripe customer the amount in the order
 | 
			
		||||
 | 
			
		||||
  //--Handle transactions for $0
 | 
			
		||||
@@ -574,67 +553,47 @@ function uc_stripe_charge($order_id, $amount, $data) {
 | 
			
		||||
    return $result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $stripe_customer_id = null;
 | 
			
		||||
 | 
			
		||||
  if(key_exists('stripe_customer_id', $order->data)){
 | 
			
		||||
    $stripe_customer_id = $order->data['stripe_customer_id'];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Rexamine Payment Intent and Record payment or failure to the customer
 | 
			
		||||
  // Charge the customer
 | 
			
		||||
  try {
 | 
			
		||||
 | 
			
		||||
    if(!key_exists('payment_intent_id', $order->data)){
 | 
			
		||||
      throw new Exception('The payment Intent has failed.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //Bail if there's no customer ID
 | 
			
		||||
    if (empty($stripe_customer_id) || is_null($stripe_customer_id)) {
 | 
			
		||||
    if (empty($stripe_customer_id)) {
 | 
			
		||||
      throw new Exception('No customer ID found');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //Bail if there's no payment method
 | 
			
		||||
    if (empty($_SESSION['stripe']['payment_method'])) {
 | 
			
		||||
      throw new Exception('Token not found');
 | 
			
		||||
    }
 | 
			
		||||
    $stripe_payment_method_id = $_SESSION['stripe']['payment_method'];
 | 
			
		||||
    foreach($order->products as $item){
 | 
			
		||||
      $titles[] = $item->title;
 | 
			
		||||
      $models[] = $item->model;
 | 
			
		||||
      }
 | 
			
		||||
    $metadata = array();
 | 
			
		||||
 | 
			
		||||
    if (!empty($models)) {
 | 
			
		||||
      $metadata['models'] = implode(";", $models);
 | 
			
		||||
      }
 | 
			
		||||
    if (!empty($titles)) {
 | 
			
		||||
      $metadata['titles'] = implode(";", $titles);
 | 
			
		||||
      }
 | 
			
		||||
    $params = array(
 | 
			
		||||
      "amount" => $amount,
 | 
			
		||||
      "currency" => strtolower($order->currency),
 | 
			
		||||
      "customer" => $stripe_customer_id,
 | 
			
		||||
      "description" => t("Order #@order_id", array("@order_id" => $order_id)),
 | 
			
		||||
      "payment_method" => $stripe_payment_method_id,
 | 
			
		||||
      "payment_method_types" => ['card'],
 | 
			
		||||
      "confirm" => true,
 | 
			
		||||
 | 
			
		||||
      "metadata" => $metadata,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    $intent_id = $order->data['payment_intent_id'];
 | 
			
		||||
 | 
			
		||||
    if (!empty($shipping_info)) {
 | 
			
		||||
      $params['shipping'] = $shipping_info;
 | 
			
		||||
      \Stripe\PaymentIntent::update($intent_id, ['shipping' => $shipping_info]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // charge the Customer the amount in the order
 | 
			
		||||
    $payment_intent = \Stripe\PaymentIntent::retrieve($intent_id);
 | 
			
		||||
 | 
			
		||||
    if ($payment_intent->status != 'succeeded') {
 | 
			
		||||
      throw new Exception($payment_intent['last_payment_error']['message']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $charge_id = $payment_intent->charges->data[0]['id'];
 | 
			
		||||
    $charge = \Stripe\Charge::create($params);
 | 
			
		||||
 | 
			
		||||
    $formatted_amount = $amount / 100;
 | 
			
		||||
    $formatted_amount = number_format($formatted_amount, 2);
 | 
			
		||||
 | 
			
		||||
//     $payment_method = \Stripe\PaymentMethod::retrieve($payment_intent->payment_method);
 | 
			
		||||
//     $payment_method->attach(['customer' => $stripe_customer_id]);
 | 
			
		||||
 | 
			
		||||
    $result = array(
 | 
			
		||||
      'success' => TRUE,
 | 
			
		||||
      'message' => t('Payment of @amount processed successfully, Stripe transaction id @transaction_id.', array('@amount' => $formatted_amount, '@transaction_id' => $charge_id)),
 | 
			
		||||
      'comment' => t('Stripe transaction ID: @transaction_id', array('@transaction_id' => $charge_id)),
 | 
			
		||||
      'message' => t('Payment of @amount processed successfully, Stripe transaction id @transaction_id.', array('@amount' => $formatted_amount, '@transaction_id' => $charge->id)),
 | 
			
		||||
      'comment' => t('Stripe transaction ID: @transaction_id', array('@transaction_id' => $charge->id)),
 | 
			
		||||
      'uid' => $user->uid,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
@@ -657,8 +616,6 @@ function uc_stripe_charge($order_id, $amount, $data) {
 | 
			
		||||
    uc_order_comment_save($order_id, $user->uid, $result['message'], 'admin');
 | 
			
		||||
    watchdog('uc_stripe', 'Stripe charge failed for order @order, message: @message', array('@order' => $order_id, '@message' => $result['message']));
 | 
			
		||||
 | 
			
		||||
    $_SESSION['stripe']['payment_failed'] = TRUE;
 | 
			
		||||
 | 
			
		||||
    return $result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -676,8 +633,6 @@ function uc_stripe_charge($order_id, $amount, $data) {
 | 
			
		||||
 | 
			
		||||
  watchdog('uc_stripe', 'Stripe gateway error for order @order_id', array('order_id' => $order_id));
 | 
			
		||||
 | 
			
		||||
  $_SESSION['stripe']['payment_failed'] = TRUE;
 | 
			
		||||
 | 
			
		||||
  return $result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -701,65 +656,33 @@ function uc_stripe_renew($order, &$fee) {
 | 
			
		||||
 | 
			
		||||
    //Get the customer ID
 | 
			
		||||
    $stripe_customer_id = _uc_stripe_get_customer_id($order->uid);
 | 
			
		||||
    $stripe_payment_id = _uc_stripe_get_payment_id($order->uid);
 | 
			
		||||
 | 
			
		||||
    if (empty($stripe_customer_id)) {
 | 
			
		||||
      throw new Exception('No stripe customer ID found');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //Create the charge
 | 
			
		||||
    $amount = $fee->fee_amount;
 | 
			
		||||
    $amount = $amount * 100;
 | 
			
		||||
 | 
			
		||||
    //create intent Array
 | 
			
		||||
    $intent_params = array(
 | 
			
		||||
        'amount' => $amount,
 | 
			
		||||
        'currency' => strtolower($order->currency),
 | 
			
		||||
        'payment_method_types' => ['card'],
 | 
			
		||||
        'customer' => $stripe_customer_id,
 | 
			
		||||
        'off_session' => true,
 | 
			
		||||
        'confirm' => true,
 | 
			
		||||
    $charge = \Stripe\Charge::create(array(
 | 
			
		||||
        "amount" => $amount,
 | 
			
		||||
        "currency" => strtolower($order->currency),
 | 
			
		||||
        "customer" => $stripe_customer_id
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Payment methods added with Stripe PaymentIntent API will be saved to customer
 | 
			
		||||
    // object in drupal. Payment cards saved with 2.x tokens will not have a value
 | 
			
		||||
    // saved to customer object, but the payment Intent will still continue because
 | 
			
		||||
    // Stipe will use default payment in those situations.
 | 
			
		||||
    if($stripe_payment_id){
 | 
			
		||||
      $intent_params['payment_method'] = $stripe_payment_id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $payment_intent = \Stripe\PaymentIntent::create($intent_params);
 | 
			
		||||
 | 
			
		||||
    uc_payment_enter($order->order_id, $order->payment_method, $order->order_total, $fee->uid, $payment_intent, "Success");
 | 
			
		||||
    uc_payment_enter($order->order_id, $order->payment_method, $order->order_total, $fee->uid, $charge, "Success");
 | 
			
		||||
 | 
			
		||||
    $formatted_amount = number_format($fee->fee_amount, 2);
 | 
			
		||||
    $message = t('Card renewal payment of @amount processed successfully.', array('@amount' => $formatted_amount));
 | 
			
		||||
    uc_order_comment_save($fee->order_id, $order->uid, $message, 'order', 'completed', FALSE);
 | 
			
		||||
    uc_order_comment_save($fee->order_id, $order->uid, $message, 'admin');
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  } catch (\Stripe\Error\Card $e) {
 | 
			
		||||
 | 
			
		||||
    if ($e->getDeclineCode() === 'authentication_required') {
 | 
			
		||||
      $NOT_COMPLETED = 0;
 | 
			
		||||
      // Create and store hash so that we can prompt user to authenticate payment.
 | 
			
		||||
      $hash = drupal_hmac_base64(REQUEST_TIME . $order->order_id, drupal_get_hash_salt() . $stripe_payment_id);
 | 
			
		||||
      db_insert('uc_stripe_pending_auth')->fields(array(
 | 
			
		||||
        'order_id' => $order->order_id,
 | 
			
		||||
        'completed' => $NOT_COMPLETED,
 | 
			
		||||
        'rfee_id' => $fee->rfid,
 | 
			
		||||
        'hash' => $hash
 | 
			
		||||
      ))->execute();
 | 
			
		||||
 | 
			
		||||
      // Prepare email to alert user that authentication is required.
 | 
			
		||||
      $params['body'] = variable_get('uc_stripe_authenticaiton_required_email', _uc_stripe_get_authentication_required_email_text());
 | 
			
		||||
      $params['user'] = user_load($order->uid);
 | 
			
		||||
      $params['hash'] = $hash;
 | 
			
		||||
      drupal_mail('uc_stripe', 'authentication_required', $params['user']->mail,language_default(), $params);
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  } catch (Exception $e) {
 | 
			
		||||
    $result = array(
 | 
			
		||||
      'success' => FALSE,
 | 
			
		||||
      'comment' => $e->getCode(),
 | 
			
		||||
@@ -769,14 +692,10 @@ function uc_stripe_renew($order, &$fee) {
 | 
			
		||||
      )),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    uc_order_comment_save($order->order_id, $order->uid, $result['message'], 'admin');
 | 
			
		||||
 | 
			
		||||
    watchdog('uc_stripe', 'Renewal failed for order @order_id, code=@code, message: @message', array('@order_id' => $order->order_id, '@code' => $e->getCode(), '@message' => $e->getMessage()));
 | 
			
		||||
    watchdog('uc_stripe', 'Renewal failed for order @order_id, code=@code, message: @message', array('@order_id' => $order->order_id, '@code' => $result['comment'], '@message' => $result['message']));
 | 
			
		||||
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  } catch (Exception $e) {
 | 
			
		||||
    watchdog('uc_stripe', 'Renewal failed for order @order_id, code=@code, message: @message', array('@order_id' => $order->order_id, '@code' => $e->getCode(), '@message' => $e->getMessage()));
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -840,13 +759,6 @@ function _uc_stripe_prepare_api() {
 | 
			
		||||
  } catch (Exception $e) {
 | 
			
		||||
    watchdog('uc_stripe', 'Error setting the Stripe API Key. Payments will not be processed: %error', array('%error' => $e->getMessage()));
 | 
			
		||||
  }
 | 
			
		||||
  try{
 | 
			
		||||
    $module_info = system_get_info('module', "uc_stripe");
 | 
			
		||||
    $uc_stripe_version = is_null($module_info['version']) ? 'dev-unknown' : $module_info['version'];
 | 
			
		||||
    \Stripe\Stripe::setAppInfo("Drupal Ubercart Stripe", $uc_stripe_version, "https://www.drupal.org/project/uc_stripe");
 | 
			
		||||
  } catch (Exception $e){
 | 
			
		||||
    watchdog('uc_stripe', 'Error setting Stripe plugin information: %error', array('%error' => $e->getMessage()));
 | 
			
		||||
  }
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -877,20 +789,6 @@ function _uc_stripe_get_customer_id($uid) {
 | 
			
		||||
  return $id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieve the Stripe payment id for a user
 | 
			
		||||
 *
 | 
			
		||||
 * @param $uid
 | 
			
		||||
 * @return bool
 | 
			
		||||
 */
 | 
			
		||||
function _uc_stripe_get_payment_id($uid) {
 | 
			
		||||
 | 
			
		||||
  $account = user_load($uid);
 | 
			
		||||
 | 
			
		||||
  $id = !empty($account->data['uc_stripe_payment_id']) ? $account->data['uc_stripe_payment_id'] : FALSE;
 | 
			
		||||
  return $id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_theme_registry_alter() to make sure that we render
 | 
			
		||||
@@ -910,222 +808,13 @@ function uc_stripe_theme_registry_alter(&$theme_registry) {
 | 
			
		||||
 * @return string
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_uc_payment_method_credit_form($form) {
 | 
			
		||||
  $output = drupal_render($form['stripe_nojs_warning']);
 | 
			
		||||
  $output .= drupal_render($form['config_error']);
 | 
			
		||||
  $output .= theme('uc_payment_method_credit_form',$form);
 | 
			
		||||
  $output .= drupal_render($form['stripe_payment_method']);
 | 
			
		||||
  $output .= drupal_render($form['stripe_token']);
 | 
			
		||||
  $output .= drupal_render($form['dummy_image_load']);
 | 
			
		||||
 | 
			
		||||
  return $output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Used to return the appropriate response after checking Stripe Payment Intent
 | 
			
		||||
 * status
 | 
			
		||||
 * @param Object $intent
 | 
			
		||||
 * @return string response
 | 
			
		||||
 */
 | 
			
		||||
function _generatePaymentResponse($intent) {
 | 
			
		||||
 | 
			
		||||
  if ($intent->status == 'requires_action' &&
 | 
			
		||||
      $intent->next_action->type == 'use_stripe_sdk') {
 | 
			
		||||
        # Tell the client to handle the action
 | 
			
		||||
        $response = [
 | 
			
		||||
            'requires_action' => true,
 | 
			
		||||
            'payment_intent_client_secret' => $intent->client_secret
 | 
			
		||||
        ];
 | 
			
		||||
      } else if ($intent->status == 'succeeded') {
 | 
			
		||||
        # The payment didn’t need any additional actions and completed!
 | 
			
		||||
        # Handle post-payment fulfillment
 | 
			
		||||
        $response = ['success' => true];
 | 
			
		||||
      } else {
 | 
			
		||||
        # Invalid status
 | 
			
		||||
        http_response_code(500);
 | 
			
		||||
        $response = ['error' => 'Invalid PaymentIntent status'];
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return $response;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Ajax page callback for callback uc_stripe/ajax/confirm_payment page
 | 
			
		||||
 * This is used to send payment and intent status back to JS client
 | 
			
		||||
 * @return string Json response
 | 
			
		||||
 */
 | 
			
		||||
function _uc_stripe_confirm_payment(){
 | 
			
		||||
 | 
			
		||||
  global $user;
 | 
			
		||||
 | 
			
		||||
  # retrieve json from POST body
 | 
			
		||||
  $received_json = file_get_contents("php://input",  TRUE);
 | 
			
		||||
  $data = drupal_json_decode($received_json, TRUE);
 | 
			
		||||
 | 
			
		||||
  $order_id = $data['order_id'];
 | 
			
		||||
  $order = uc_order_load($order_id);
 | 
			
		||||
 | 
			
		||||
  if (!_uc_stripe_prepare_api()) {
 | 
			
		||||
 | 
			
		||||
    $message = 'Stripe API not found.';
 | 
			
		||||
 | 
			
		||||
    watchdog('uc_stripe', 'Error in Stripe API: @message', array('@message' => $message));
 | 
			
		||||
    return ['error' => $message];
 | 
			
		||||
  }
 | 
			
		||||
  // Format the amount in cents, which is what Stripe wants
 | 
			
		||||
  $amount = uc_currency_format($order->order_total, FALSE, FALSE, FALSE);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  $stripe_customer_id = False;
 | 
			
		||||
  $order_has_stripe_id = key_exists('stripe_customer_id', $order->data) ? True : False;
 | 
			
		||||
 | 
			
		||||
  // Check various places to get the stripe_customer_id. If not found we'll create
 | 
			
		||||
  // a new stripe user.
 | 
			
		||||
  if($order_has_stripe_id){
 | 
			
		||||
    $stripe_customer_id = $order->data['stripe_customer_id'];
 | 
			
		||||
  }
 | 
			
		||||
  else if ($user->uid != $order->uid) {
 | 
			
		||||
    $stripe_customer_id = _uc_stripe_get_customer_id($order->uid);
 | 
			
		||||
  } else {
 | 
			
		||||
    $stripe_customer_id = _uc_stripe_get_customer_id($user->uid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // In the case where the stored customer_id is not a valid customer in Stripe
 | 
			
		||||
  // then we'll need to create a new stripe customer. see #3071712
 | 
			
		||||
  if($stripe_customer_id && !_uc_stripe_is_stripe_id_valid($stripe_customer_id)){
 | 
			
		||||
    watchdog('uc_stripe', 'Stripe customer: @customer is not valid in this instance of Stripe. A new customer will be created.', array('@customer' => $stripe_customer_id));
 | 
			
		||||
    $stripe_customer_id = false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $intent = null;
 | 
			
		||||
  try {
 | 
			
		||||
    if (isset($data['payment_method_id'])) {
 | 
			
		||||
 | 
			
		||||
      $params = array(
 | 
			
		||||
          'payment_method' => $data['payment_method_id'],
 | 
			
		||||
          "description" => t("Order #@order_id", array("@order_id" => $order_id)),
 | 
			
		||||
          'amount' => $amount,
 | 
			
		||||
          'currency' => strtolower($order->currency),
 | 
			
		||||
          'confirmation_method' => 'manual',
 | 
			
		||||
          'confirm' => true,
 | 
			
		||||
          'setup_future_usage' => 'off_session',
 | 
			
		||||
          'save_payment_method' => true,
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      if(!$stripe_customer_id) {
 | 
			
		||||
        $customer = _uc_stripe_create_stripe_customer($order, $data['payment_method_id']);
 | 
			
		||||
        if(!$customer){
 | 
			
		||||
          $message = 'Customer creation failed.';
 | 
			
		||||
          $_SESSION['stripe']['payment_failed'] = TRUE;
 | 
			
		||||
          return ['error' => $message];
 | 
			
		||||
        }
 | 
			
		||||
        $stripe_customer_id = $customer->id;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      $params['customer'] = $stripe_customer_id;
 | 
			
		||||
 | 
			
		||||
      # Create the PaymentIntent
 | 
			
		||||
      $intent = \Stripe\PaymentIntent::create($params);
 | 
			
		||||
 | 
			
		||||
      if(!$order_has_stripe_id){
 | 
			
		||||
        $order->data['stripe_customer_id'] = $stripe_customer_id;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      $order->data['payment_intent_id'] = $intent->id;
 | 
			
		||||
      uc_order_save($order);
 | 
			
		||||
    }
 | 
			
		||||
    if (isset($data['payment_intent_id'])) {
 | 
			
		||||
      $intent = \Stripe\PaymentIntent::retrieve(
 | 
			
		||||
          $data['payment_intent_id']
 | 
			
		||||
          );
 | 
			
		||||
      $intent->confirm();
 | 
			
		||||
 | 
			
		||||
      $order->data['payment_intent_id'] = $data['payment_intent_id'];
 | 
			
		||||
      uc_order_save($order);
 | 
			
		||||
    }
 | 
			
		||||
    return _generatePaymentResponse($intent);
 | 
			
		||||
  } catch (Exception $e) {
 | 
			
		||||
    watchdog('uc_stripe', 'Payment could not be processed: @message', array('@message' => $e->getMessage()));
 | 
			
		||||
    return ['error' => $e->getMessage()];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _uc_stripe_create_stripe_customer($order, $payment_method_id = NULL){
 | 
			
		||||
 | 
			
		||||
  $stripe_customer_id = FALSE;
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    // If the token is not in the user's session, we can't set up a new customer
 | 
			
		||||
 | 
			
		||||
    $shipping_info = array();
 | 
			
		||||
    if (!empty($order->delivery_postal_code)) {
 | 
			
		||||
      $shipping_info = array(
 | 
			
		||||
          'name' => @"{$order->delivery_first_name} {$order->delivery_last_name}",
 | 
			
		||||
          'phone' => @$order->delivery_phone,
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      $delivery_country = uc_get_country_data(array('country_id' => $order->delivery_country));
 | 
			
		||||
      if ($delivery_country === FALSE) {
 | 
			
		||||
        $delivery_country = array(0 => array('country_iso_code_2' => 'US'));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      $shipping_info['address'] = array(
 | 
			
		||||
          'city' => @$order->delivery_city,
 | 
			
		||||
          'country' => @$delivery_country[0]['country_iso_code_2'],
 | 
			
		||||
          'line1' => @$order->delivery_street1,
 | 
			
		||||
          'line2' => @$order->delivery_street2,
 | 
			
		||||
          'postal_code' => @$order->delivery_postal_code,
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $params = array(
 | 
			
		||||
        'description' => "OrderID: {$order->order_id}",
 | 
			
		||||
        'email' => "$order->primary_email"
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (!empty($shipping_info)) {
 | 
			
		||||
      $params['shipping'] = $shipping_info;
 | 
			
		||||
    }
 | 
			
		||||
    //Create the customer in stripe
 | 
			
		||||
    $customer = \Stripe\Customer::create($params);
 | 
			
		||||
 | 
			
		||||
    return $customer;
 | 
			
		||||
 | 
			
		||||
  } catch (Exception $e) {
 | 
			
		||||
    $message = t("Stripe Customer Creation Failed for order !order: !message", array(
 | 
			
		||||
        "!order" => $order_id,
 | 
			
		||||
        "!message" => $e->getMessage()
 | 
			
		||||
    ));
 | 
			
		||||
 | 
			
		||||
    uc_order_comment_save($order_id, $user->uid, $message, 'admin');
 | 
			
		||||
 | 
			
		||||
    watchdog('uc_stripe', 'Failed stripe customer creation: @message', array('@message' => $message));
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @param string $stripe_id
 | 
			
		||||
 * @return boolean result - if stripe_id is valid based on stripe api customer call
 | 
			
		||||
 */
 | 
			
		||||
function _uc_stripe_is_stripe_id_valid($stripe_id){
 | 
			
		||||
  try{
 | 
			
		||||
 | 
			
		||||
    if (!_uc_stripe_prepare_api()) {
 | 
			
		||||
 | 
			
		||||
      $message = 'Stripe API not found.';
 | 
			
		||||
 | 
			
		||||
      watchdog('uc_stripe', 'Error in Stripe API: @message', array('@message' => $message));
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $customer = \Stripe\Customer::retrieve($stripe_id);
 | 
			
		||||
 | 
			
		||||
    // Count deleted stripe customers as invalid
 | 
			
		||||
    return !$customer->deleted;
 | 
			
		||||
 | 
			
		||||
  } catch (Exception $e) {
 | 
			
		||||
    // IF customer is not found, an exception is thrown.
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,149 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_form().
 | 
			
		||||
 *
 | 
			
		||||
 * This form allows the user to authenticate in order for their recurring payment
 | 
			
		||||
 * to be processed.
 | 
			
		||||
 */
 | 
			
		||||
function uc_stripe_authenticate_payment_form($form, &$form_state, $hash) {
 | 
			
		||||
  $form = array();
 | 
			
		||||
 | 
			
		||||
  $pending_order = db_select('uc_stripe_pending_auth', 'u')
 | 
			
		||||
  ->fields('u', array('order_id', 'completed', 'rfee_id'))
 | 
			
		||||
  ->condition('hash', $hash)
 | 
			
		||||
  ->execute()
 | 
			
		||||
  ->fetchObject();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  if(!$pending_order){
 | 
			
		||||
    $form['error'] = array(
 | 
			
		||||
        '#markup' => t('Sorry, we could not verify your payment details. Please verify the link and try again. Contact support if the problem persists.'),
 | 
			
		||||
    );
 | 
			
		||||
    return $form;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $order_id = $pending_order->order_id;
 | 
			
		||||
  $completed = $pending_order->completed;
 | 
			
		||||
  $rfee_id = $pending_order->rfee_id;
 | 
			
		||||
 | 
			
		||||
  if ($completed) {
 | 
			
		||||
    $form['error'] = array(
 | 
			
		||||
        '#markup' => t('This payment has already been verified.'),
 | 
			
		||||
    );
 | 
			
		||||
    return $form;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  $form['heading'] = array(
 | 
			
		||||
    '#markup' => t('<p>Your financial institution has requested additional verification to process your scheduled payment.</p>'),
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $form['order_id'] = array(
 | 
			
		||||
    '#type' => 'hidden',
 | 
			
		||||
    '#value' => $order_id,
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $form['rfee_id'] = array(
 | 
			
		||||
      '#type' => 'hidden',
 | 
			
		||||
      '#value' => $rfee_id,
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $form['hash'] = array(
 | 
			
		||||
      '#type' => 'hidden',
 | 
			
		||||
      '#value' => $hash,
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $form['submit'] = array(
 | 
			
		||||
    '#type' => 'submit',
 | 
			
		||||
    '#value' => t('Verify Payment')
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  $order = uc_order_load($order_id);
 | 
			
		||||
  $user = user_load($order->uid);
 | 
			
		||||
  $payment_method_id = _uc_stripe_get_payment_id($user->uid);
 | 
			
		||||
  $stripe_customer_id = _uc_stripe_get_customer_id($user->uid);
 | 
			
		||||
 | 
			
		||||
  $order_id = $order_id;
 | 
			
		||||
  $apikey = variable_get('uc_stripe_testmode', TRUE) ? check_plain(variable_get('uc_stripe_api_key_test_publishable', '')) : check_plain(variable_get('uc_stripe_api_key_live_publishable', ''));
 | 
			
		||||
  $settings = array('apikey' => $apikey, 'methodId' => $payment_method_id, 'orderId' => $order_id);
 | 
			
		||||
 | 
			
		||||
  //Attach Stripe v3 JS library and JS for processing payment
 | 
			
		||||
  $form['#attached']['js']['https://js.stripe.com/v3/'] = array('type' => 'external');
 | 
			
		||||
  $form['#attached']['js'][] = array('data' => array('uc_stripe' => $settings), 'type' => 'setting');
 | 
			
		||||
  $form['#attached']['js'][] = drupal_get_path('module', 'uc_stripe') . '/js/uc_stripe_process_payment.js';
 | 
			
		||||
  $form['#attached']['css'][] = drupal_get_path('module', 'uc_stripe') . '/css/uc_stripe.css';
 | 
			
		||||
 | 
			
		||||
  return $form;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function uc_stripe_authenticate_payment_form_submit($form, &$form_state){
 | 
			
		||||
 | 
			
		||||
  $order_id = $form_state['values']['order_id'];
 | 
			
		||||
  $rfee_id = $form_state['values']['rfee_id'];
 | 
			
		||||
  $hash = $form_state['values']['hash'];
 | 
			
		||||
 | 
			
		||||
  $order = uc_order_load($order_id);
 | 
			
		||||
  $intent_id = $order->data['payment_intent_id'];
 | 
			
		||||
 | 
			
		||||
  try{
 | 
			
		||||
    _uc_stripe_prepare_api();
 | 
			
		||||
    $payment_intent = \Stripe\PaymentIntent::retrieve($intent_id);
 | 
			
		||||
 | 
			
		||||
    if ($payment_intent->status != 'succeeded') {
 | 
			
		||||
      throw new Exception('Payment intent failed');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $charge_id = $payment_intent->charges->data[0]['id'];
 | 
			
		||||
    $amount = uc_currency_format($order->order_total, FALSE, FALSE, FALSE);
 | 
			
		||||
 | 
			
		||||
    $formatted_amount = $amount / 100;
 | 
			
		||||
    $formatted_amount = number_format($formatted_amount, 2);
 | 
			
		||||
 | 
			
		||||
    $message = t('Payment of @amount processed successfully, Stripe transaction id @transaction_id.', array('@amount' => $formatted_amount, '@transaction_id' => $charge_id));
 | 
			
		||||
    $COMPLETED = 1;
 | 
			
		||||
 | 
			
		||||
    //Set all orders matching the order id and fee id to completed. This is incase
 | 
			
		||||
    // there were multiple attempts to process the subscription.
 | 
			
		||||
    db_update('uc_stripe_pending_auth')
 | 
			
		||||
    ->fields(array(
 | 
			
		||||
        'completed' => $COMPLETED,
 | 
			
		||||
    ))
 | 
			
		||||
    ->condition('order_id', $order_id)
 | 
			
		||||
    ->condition('rfee_id', $rfee_id)
 | 
			
		||||
    ->execute();
 | 
			
		||||
 | 
			
		||||
    $fee = uc_recurring_fee_user_load($rfee_id);
 | 
			
		||||
    uc_payment_enter($order->order_id, $order->payment_method, $order->order_total, $fee->uid, $payment_intent, "Success");
 | 
			
		||||
 | 
			
		||||
    // Since we have processed the payment here already, we'll temporarily change the fee
 | 
			
		||||
    // handler to the the default uc_recurring fee handler that simply returns TRUE
 | 
			
		||||
    // without any processing.
 | 
			
		||||
    $fee->fee_handler = 'default';
 | 
			
		||||
    $id = uc_recurring_renew($fee);
 | 
			
		||||
 | 
			
		||||
    // We need to reset the fee handler for this order back to uc_stripe so that
 | 
			
		||||
    // future subscriptions work.
 | 
			
		||||
    $fee = uc_recurring_fee_user_load($fee->rfid);
 | 
			
		||||
    $fee->fee_handler = 'uc_stripe';
 | 
			
		||||
    uc_recurring_fee_user_save($fee);
 | 
			
		||||
 | 
			
		||||
    uc_order_comment_save($order_id, $order->uid, $message, 'admin');
 | 
			
		||||
    uc_order_comment_save($order_id, $order->uid, $message, 'order', 'completed', FALSE);
 | 
			
		||||
 | 
			
		||||
    $form_state['redirect'] = '/';
 | 
			
		||||
    drupal_set_message('You have successfully completed your payment');
 | 
			
		||||
 | 
			
		||||
  } catch (Exception $e) {
 | 
			
		||||
 | 
			
		||||
    $message = t("Stripe Charge Failed for order !order: !message", array(
 | 
			
		||||
        "!order" => $order_id,
 | 
			
		||||
        "!message" => $e->getMessage()
 | 
			
		||||
    ));
 | 
			
		||||
 | 
			
		||||
    uc_order_comment_save($order_id, $order->uid, $message, 'admin');
 | 
			
		||||
    watchdog('uc_stripe', 'Stripe charge failed for order @order, message: @message', array('@order' => $order_id, '@message' => $message));
 | 
			
		||||
    $fail_message = variable_get('uc_credit_fail_message', t('We were unable to process your credit card payment. Please verify your details and try again.  If the problem persists, contact us to complete your order.'));
 | 
			
		||||
    drupal_set_message($fail_message, 'error');
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user