Update from official release #9
							
								
								
									
										120
									
								
								js/uc_stripe.js
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								js/uc_stripe.js
									
									
									
									
									
								
							@@ -9,6 +9,20 @@
 | 
				
			|||||||
  Drupal.behaviors.uc_stripe = {
 | 
					  Drupal.behaviors.uc_stripe = {
 | 
				
			||||||
    attach: function (context) {
 | 
					    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.
 | 
					      // Map stripe names to (partial) Ubercart field names; Ubercart names add "billing_" or "shipping_" on the front.
 | 
				
			||||||
        const address_field_mapping = {
 | 
					        const address_field_mapping = {
 | 
				
			||||||
          "address_line1": "street1",
 | 
					          "address_line1": "street1",
 | 
				
			||||||
@@ -20,15 +34,17 @@
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
        var submitButton = $('.uc-cart-checkout-form #edit-continue');
 | 
					        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_container = $('.payment-details-credit');
 | 
				
			||||||
        var cc_num = cc_container.find(':input[id*="edit-panes-payment-details-cc-numbe"]');
 | 
					        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_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');
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
      // Make sure that when the page is being loaded the token value is reset
 | 
					        // Make sure that when the page is being loaded the paymentMethod value is reset
 | 
				
			||||||
        // Browser or other caching might do otherwise.
 | 
					        // Browser or other caching might do otherwise.
 | 
				
			||||||
      $("[name='panes[payment][details][stripe_token]']").val('default');
 | 
					        $("[name='panes[payment-stripe][details][stripe_payment_method]']").val('default');
 | 
				
			||||||
 | 
					 | 
				
			||||||
      $('span#stripe-nojs-warning').parent().hide();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // JS must enable the button; otherwise form might disclose cc info. It starts disabled
 | 
					        // JS must enable the button; otherwise form might disclose cc info. It starts disabled
 | 
				
			||||||
        submitButton.attr('disabled', false);
 | 
					        submitButton.attr('disabled', false);
 | 
				
			||||||
@@ -43,6 +59,34 @@
 | 
				
			|||||||
          cc_num.val('');
 | 
					          cc_num.val('');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					     // 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",
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // 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) {
 | 
					        submitButton.click(function (e) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // We must find the various fields again, because they may have been swapped
 | 
					          // We must find the various fields again, because they may have been swapped
 | 
				
			||||||
@@ -50,58 +94,27 @@
 | 
				
			|||||||
          cc_container = $('.payment-details-credit');
 | 
					          cc_container = $('.payment-details-credit');
 | 
				
			||||||
          cc_num = cc_container.find(':input[id*="edit-panes-payment-details-cc-numbe"]');
 | 
					          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_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 token field, just let the submit go on
 | 
					          // If not credit card processing or no payment method field, just let the submit go on
 | 
				
			||||||
          // Also continue if we've received the tokenValue
 | 
					          // Also continue if we've received the tokenValue
 | 
				
			||||||
        var tokenField = $("[name='panes[payment][details][stripe_token]']");
 | 
					          var paymentMethodField = $("[name='panes[payment-stripe][details][stripe_payment_method]']");
 | 
				
			||||||
        if (!$("div.payment-details-credit").length || !tokenField.length || tokenField.val().indexOf('tok_') == 0) {
 | 
					          if (!$("div.payment-details-credit").length || !paymentMethodField.length || paymentMethodField.val().indexOf('pm_') == 0) {
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // If we've requested and are waiting for token, prevent any further submit
 | 
					          // If we've requested and are waiting for token, prevent any further submit
 | 
				
			||||||
        if (tokenField.val() == 'requested') {
 | 
					          if (paymentMethodField.val() == 'requested') {
 | 
				
			||||||
            return false; // Prevent any submit processing until token is received
 | 
					            return false; // Prevent any submit processing until token is received
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // Go ahead and request the token
 | 
					          // Go ahead and request the token
 | 
				
			||||||
        tokenField.val('requested');
 | 
					          paymentMethodField.val('requested');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          try {
 | 
					          try {
 | 
				
			||||||
          var name = undefined;
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
          if ($(':input[name="panes[billing][billing_first_name]"]').length) {
 | 
					            stripe.createPaymentMethod('card', card).then(function (response) {
 | 
				
			||||||
            name = $(':input[name="panes[billing][billing_first_name]"]').val() + " " + $(':input[name="panes[billing][billing_last_name]"]').val();
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          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();
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          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
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          // 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
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          Stripe.createToken(params, function (status, response) {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
              if (response.error) {
 | 
					              if (response.error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -129,21 +142,27 @@
 | 
				
			|||||||
                // And show the hidden original button which has the behavior attached to it.
 | 
					                // And show the hidden original button which has the behavior attached to it.
 | 
				
			||||||
                submitButton.show();
 | 
					                submitButton.show();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              tokenField.val('default'); // Make sure token field set back to default
 | 
					                paymentMethodField.val('default'); // Make sure token field set back to default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              } else {
 | 
					              } else {
 | 
				
			||||||
                // token contains id, last4, and card type
 | 
					                // token contains id, last4, and card type
 | 
				
			||||||
              var token = response.id;
 | 
					                var paymentMethodId = response.paymentMethod.id;
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // Insert the token into the form so it gets submitted to the server
 | 
					                // Insert the token into the form so it gets submitted to the server
 | 
				
			||||||
              tokenField.val(token);
 | 
					                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
 | 
					                // 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
 | 
					                // find values it objects to; after "fixing" set the name back on the
 | 
				
			||||||
                // form element.
 | 
					                // form element.
 | 
				
			||||||
 | 
					                // add dummy tweleve 5's and the last 4 of credit card so that last 4 show
 | 
				
			||||||
                cc_num
 | 
					                cc_num
 | 
				
			||||||
                  .css('visibility', 'hidden')
 | 
					                  .css('visibility', 'hidden')
 | 
				
			||||||
                .val('555555555555' + response.card.last4)
 | 
					                  .val('555555555555' + response.paymentMethod.card.last4)
 | 
				
			||||||
                  .attr('name', 'panes[payment][details][cc_number]');
 | 
					                  .attr('name', 'panes[payment][details][cc_number]');
 | 
				
			||||||
                cc_cvv
 | 
					                cc_cvv
 | 
				
			||||||
                  .css('visibility', 'hidden')
 | 
					                  .css('visibility', 'hidden')
 | 
				
			||||||
@@ -151,7 +170,7 @@
 | 
				
			|||||||
                  .attr('name', 'panes[payment][details][cc_cvv]');
 | 
					                  .attr('name', 'panes[payment][details][cc_cvv]');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // now actually submit to Drupal. The only "real" things going
 | 
					                // now actually submit to Drupal. The only "real" things going
 | 
				
			||||||
              // are the token and the expiration date.
 | 
					                // are the token and the expiration date and last 4 of cc
 | 
				
			||||||
                submitButton.click();
 | 
					                submitButton.click();
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@@ -165,7 +184,10 @@
 | 
				
			|||||||
          // Prevent processing until we get the token back
 | 
					          // Prevent processing until we get the token back
 | 
				
			||||||
          return false;
 | 
					          return false;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					      });
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}(jQuery));
 | 
					}(jQuery));
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										91
									
								
								js/uc_stripe_process_payment.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								js/uc_stripe_process_payment.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @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));
 | 
				
			||||||
							
								
								
									
										62
									
								
								uc_stripe.mail.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								uc_stripe.mail.inc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					<?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;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										149
									
								
								uc_stripe.pages.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								uc_stripe.pages.inc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
				
			|||||||
 | 
					<?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