solidus_stripe 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +34 -0
 - data/README.md +46 -6
 - data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-elements.js +61 -25
 - data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-intents.js +1 -0
 - data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-request-button-shared.js +1 -0
 - data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment.js +7 -1
 - data/app/controllers/solidus_stripe/intents_controller.rb +29 -20
 - data/app/decorators/models/spree/order_update_attributes_decorator.rb +39 -0
 - data/app/decorators/models/spree/payment_decorator.rb +11 -0
 - data/app/models/solidus_stripe/create_intents_order_service.rb +70 -0
 - data/app/models/spree/payment_method/stripe_credit_card.rb +4 -9
 - data/lib/solidus_stripe/version.rb +1 -1
 - data/spec/features/stripe_checkout_spec.rb +136 -59
 - metadata +5 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 929c7fff2fc949fe3979ae7a9403903b563a3ef67c5c8588f171c9bf42181ce6
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: a00f65c3222947871e6a97e5fd3e7d72eb7e5edc134128e300578ff68b13f876
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 8090f338dfefc83e121000e88d467eabc6631e6501eea750b2103c31d285a1a28364e01968c0586f564099780d69bde29f736cc2bf4b34f9456b7bf02ea84501
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: d7e5b50dd60a80c74754acd3bbcc0552af926c04d05f380995319a0336daf2aa37f8c127966d68dcecf8bb308d7ef6607ff5d948bc2e23a1544179a41c93fac5
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,5 +1,39 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Changelog
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            ## [Unreleased](https://github.com/solidusio/solidus_stripe/tree/HEAD)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            [Full Changelog](https://github.com/solidusio/solidus_stripe/compare/v3.0.0...HEAD)
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            **Closed issues:**
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            - Pay with Apple Pay from cart page [\#23](https://github.com/solidusio/solidus_stripe/issues/23)
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            ## [v3.0.0](https://github.com/solidusio/solidus_stripe/tree/v3.0.0) (2020-03-11)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            [Full Changelog](https://github.com/solidusio/solidus_stripe/compare/v2.1.0...v3.0.0)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            **Implemented enhancements:**
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            - Rename v3/stripe partial as v3/elements [\#30](https://github.com/solidusio/solidus_stripe/pull/30) ([spaghetticode](https://github.com/spaghetticode))
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            **Merged pull requests:**
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            - Allow to customize Stripe Elements styles via JS [\#34](https://github.com/solidusio/solidus_stripe/pull/34) ([spaghetticode](https://github.com/spaghetticode))
         
     | 
| 
      
 22 
     | 
    
         
            +
            - Stop injecting css in host app while installing [\#33](https://github.com/solidusio/solidus_stripe/pull/33) ([kennyadsl](https://github.com/kennyadsl))
         
     | 
| 
      
 23 
     | 
    
         
            +
            - Manage Stripe V3 JS code via Sprokets [\#32](https://github.com/solidusio/solidus_stripe/pull/32) ([spaghetticode](https://github.com/spaghetticode))
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            ## [v2.1.0](https://github.com/solidusio/solidus_stripe/tree/v2.1.0) (2020-03-11)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            [Full Changelog](https://github.com/solidusio/solidus_stripe/compare/v2.0.0...v2.1.0)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            **Closed issues:**
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            - Preference :stripe\_country is not defined on Spree::PaymentMethod::StripeCreditCard \(RuntimeError\) [\#27](https://github.com/solidusio/solidus_stripe/issues/27)
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            **Merged pull requests:**
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            - Refactor Stripe V3 Intents, Elements and cart checkout JS code [\#31](https://github.com/solidusio/solidus_stripe/pull/31) ([spaghetticode](https://github.com/spaghetticode))
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
       3 
37 
     | 
    
         
             
            ## [v2.0.0](https://github.com/solidusio/solidus_stripe/tree/v2.0.0) (2020-03-03)
         
     | 
| 
       4 
38 
     | 
    
         | 
| 
       5 
39 
     | 
    
         
             
            [Full Changelog](https://github.com/solidusio/solidus_stripe/compare/v1.2.0...v2.0.0)
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -13,7 +13,7 @@ Installation 
     | 
|
| 
       13 
13 
     | 
    
         
             
            In your Gemfile:
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
            ```ruby
         
     | 
| 
       16 
     | 
    
         
            -
            gem 'solidus_stripe', '~>  
     | 
| 
      
 16 
     | 
    
         
            +
            gem 'solidus_stripe', '~> 3.0'
         
     | 
| 
       17 
17 
     | 
    
         
             
            ```
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
            Then run from the command line:
         
     | 
| 
         @@ -155,13 +155,13 @@ SolidusStripe.CartPageCheckout.prototype.onPrButtonMounted = function(id, result 
     | 
|
| 
       155 
155 
     | 
    
         
             
            }
         
     | 
| 
       156 
156 
     | 
    
         
             
            ```
         
     | 
| 
       157 
157 
     | 
    
         | 
| 
       158 
     | 
    
         
            -
             
     | 
| 
      
 158 
     | 
    
         
            +
            Customizing Stripe Elements
         
     | 
| 
       159 
159 
     | 
    
         
             
            -----------------------
         
     | 
| 
       160 
160 
     | 
    
         | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
       162 
     | 
    
         
            -
             
     | 
| 
       163 
     | 
    
         
            -
            method  
     | 
| 
       164 
     | 
    
         
            -
            object:
         
     | 
| 
      
 161 
     | 
    
         
            +
            ### Styling input fields
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
            The default style this gem provides for Stripe Elements input fields is defined in `SolidusStripe.Elements.prototype.baseStyle`. You can override this method to return your own custom style (make sure it returns a valid [Stripe Style](https://stripe.com/docs/js/appendix/style)
         
     | 
| 
      
 164 
     | 
    
         
            +
            object):
         
     | 
| 
       165 
165 
     | 
    
         | 
| 
       166 
166 
     | 
    
         
             
            ```js
         
     | 
| 
       167 
167 
     | 
    
         
             
            SolidusStripe.Elements.prototype.baseStyle = function () {
         
     | 
| 
         @@ -208,6 +208,46 @@ You can also style your element containers directly by using CSS rules like this 
     | 
|
| 
       208 
208 
     | 
    
         
             
              }
         
     | 
| 
       209 
209 
     | 
    
         
             
            ```
         
     | 
| 
       210 
210 
     | 
    
         | 
| 
      
 211 
     | 
    
         
            +
            ### Customizing individual input fields
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
            If you want to customize individual input fields, you can override these methods 
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
            * `SolidusStripe.Elements.prototype.cardNumberElementOptions`
         
     | 
| 
      
 216 
     | 
    
         
            +
            * `SolidusStripe.Elements.prototype.cardExpiryElementOptions`
         
     | 
| 
      
 217 
     | 
    
         
            +
            * `SolidusStripe.Elements.prototype.cardCvcElementOptions`
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
            and return a valid [options object](https://stripe.com/docs/js/elements_object/create_element?type=cardNumber) for the corresponding field type. For example, this code sets a custom placeholder and enables the credit card icon for the card number field 
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
            ```js
         
     | 
| 
      
 222 
     | 
    
         
            +
            SolidusStripe.Elements.prototype.cardNumberElementOptions = function () {
         
     | 
| 
      
 223 
     | 
    
         
            +
              return {
         
     | 
| 
      
 224 
     | 
    
         
            +
                style: this.baseStyle(),
         
     | 
| 
      
 225 
     | 
    
         
            +
                showIcon: true,
         
     | 
| 
      
 226 
     | 
    
         
            +
                placeholder: "I'm a custom placeholder!"
         
     | 
| 
      
 227 
     | 
    
         
            +
              }
         
     | 
| 
      
 228 
     | 
    
         
            +
            }
         
     | 
| 
      
 229 
     | 
    
         
            +
            ```
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
            ### Passing options to the Stripe Elements instance
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
      
 233 
     | 
    
         
            +
            By overriding the `SolidusStripe.Payment.prototype.elementsBaseOptions` method and returning a [valid options object](https://stripe.com/docs/js/elements_object/create), you can pass custom options to the Stripe Elements instance. 
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
            Note that in order to use web fonts with Stripe Elements, you must specify the fonts when creating the Stripe Elements instance. Here's an example specifying a custom web font and locale:
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
            ```js
         
     | 
| 
      
 238 
     | 
    
         
            +
            SolidusStripe.Payment.prototype.elementsBaseOptions = function () {
         
     | 
| 
      
 239 
     | 
    
         
            +
              return {
         
     | 
| 
      
 240 
     | 
    
         
            +
                locale: 'de',
         
     | 
| 
      
 241 
     | 
    
         
            +
                fonts: [
         
     | 
| 
      
 242 
     | 
    
         
            +
                  {
         
     | 
| 
      
 243 
     | 
    
         
            +
                    cssSrc: 'https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600'
         
     | 
| 
      
 244 
     | 
    
         
            +
                  }
         
     | 
| 
      
 245 
     | 
    
         
            +
                ]
         
     | 
| 
      
 246 
     | 
    
         
            +
              };
         
     | 
| 
      
 247 
     | 
    
         
            +
            };
         
     | 
| 
      
 248 
     | 
    
         
            +
            ```
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
       211 
251 
     | 
    
         
             
            Migrating from solidus_gateway
         
     | 
| 
       212 
252 
     | 
    
         
             
            ------------------------------
         
     | 
| 
       213 
253 
     | 
    
         | 
| 
         @@ -18,29 +18,45 @@ SolidusStripe.Elements.prototype.init = function() { 
     | 
|
| 
       18 
18 
     | 
    
         
             
            };
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
            SolidusStripe.Elements.prototype.initElements = function() {
         
     | 
| 
       21 
     | 
    
         
            -
              var  
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
              var cardExpiry = this.elements.create('cardExpiry', this.cardExpiryElementOptions());
         
     | 
| 
      
 22 
     | 
    
         
            +
              cardExpiry.mount('#card_expiry');
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
      
 24 
     | 
    
         
            +
              var cardCvc = this.elements.create('cardCvc', this.cardCvcElementOptions());
         
     | 
| 
      
 25 
     | 
    
         
            +
              cardCvc.mount('#card_cvc');
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 27 
     | 
    
         
            +
              this.cardNumber = this.elements.create('cardNumber', this.cardNumberElementOptions());
         
     | 
| 
      
 28 
     | 
    
         
            +
              this.cardNumber.mount('#card_number');
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                return cardNumber;
         
     | 
| 
       31 
     | 
    
         
            -
              }.bind(this);
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
              this.cardNumber = buildElements(this.elements);
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
              var cardChange = function(event) {
         
     | 
| 
       36 
     | 
    
         
            -
                if (event.error) {
         
     | 
| 
       37 
     | 
    
         
            -
                  this.showError(event.error.message);
         
     | 
| 
       38 
     | 
    
         
            -
                } else {
         
     | 
| 
       39 
     | 
    
         
            -
                  this.errorElement.hide().text('');
         
     | 
| 
       40 
     | 
    
         
            -
                }
         
     | 
| 
       41 
     | 
    
         
            -
              };
         
     | 
| 
       42 
     | 
    
         
            -
              this.cardNumber.addEventListener('change', cardChange.bind(this));
         
     | 
| 
       43 
30 
     | 
    
         
             
              this.form.bind('submit', this.onFormSubmit.bind(this));
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              // Listen for errors from each input field.
         
     | 
| 
      
 33 
     | 
    
         
            +
              // Adapted from https://github.com/stripe/elements-examples/blob/master/js/index.js
         
     | 
| 
      
 34 
     | 
    
         
            +
              var savedErrors = {};
         
     | 
| 
      
 35 
     | 
    
         
            +
              [cardExpiry, cardCvc, this.cardNumber].forEach(function(element, idx) {
         
     | 
| 
      
 36 
     | 
    
         
            +
                element.on('change', function(event) {
         
     | 
| 
      
 37 
     | 
    
         
            +
                  if (event.error) {
         
     | 
| 
      
 38 
     | 
    
         
            +
                    savedErrors[idx] = event.error.message;
         
     | 
| 
      
 39 
     | 
    
         
            +
                    this.showError(event.error.message);
         
     | 
| 
      
 40 
     | 
    
         
            +
                  } else {
         
     | 
| 
      
 41 
     | 
    
         
            +
                    savedErrors[idx] = null;
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    // Loop over the saved errors and find the first one, if any.
         
     | 
| 
      
 44 
     | 
    
         
            +
                    var nextError = Object.keys(savedErrors)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      .sort()
         
     | 
| 
      
 46 
     | 
    
         
            +
                      .reduce(function(maybeFoundError, key) {
         
     | 
| 
      
 47 
     | 
    
         
            +
                        return maybeFoundError || savedErrors[key];
         
     | 
| 
      
 48 
     | 
    
         
            +
                      }, null);
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    if (nextError) {
         
     | 
| 
      
 51 
     | 
    
         
            +
                      // Now that they've fixed the current error, show another one.
         
     | 
| 
      
 52 
     | 
    
         
            +
                      this.showError(nextError);
         
     | 
| 
      
 53 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 54 
     | 
    
         
            +
                      // The user fixed the last error; no more errors.
         
     | 
| 
      
 55 
     | 
    
         
            +
                      this.errorElement.hide().text('');
         
     | 
| 
      
 56 
     | 
    
         
            +
                    }
         
     | 
| 
      
 57 
     | 
    
         
            +
                  }
         
     | 
| 
      
 58 
     | 
    
         
            +
                }.bind(this));
         
     | 
| 
      
 59 
     | 
    
         
            +
              }.bind(this));
         
     | 
| 
       44 
60 
     | 
    
         
             
            };
         
     | 
| 
       45 
61 
     | 
    
         | 
| 
       46 
62 
     | 
    
         
             
            SolidusStripe.Elements.prototype.baseStyle = function () {
         
     | 
| 
         @@ -61,6 +77,24 @@ SolidusStripe.Elements.prototype.baseStyle = function () { 
     | 
|
| 
       61 
77 
     | 
    
         
             
              };
         
     | 
| 
       62 
78 
     | 
    
         
             
            };
         
     | 
| 
       63 
79 
     | 
    
         | 
| 
      
 80 
     | 
    
         
            +
            SolidusStripe.Elements.prototype.cardNumberElementOptions = function () {
         
     | 
| 
      
 81 
     | 
    
         
            +
              return {
         
     | 
| 
      
 82 
     | 
    
         
            +
                style: this.baseStyle()
         
     | 
| 
      
 83 
     | 
    
         
            +
              }
         
     | 
| 
      
 84 
     | 
    
         
            +
            }
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            SolidusStripe.Elements.prototype.cardExpiryElementOptions = function () {
         
     | 
| 
      
 87 
     | 
    
         
            +
              return {
         
     | 
| 
      
 88 
     | 
    
         
            +
                style: this.baseStyle()
         
     | 
| 
      
 89 
     | 
    
         
            +
              }
         
     | 
| 
      
 90 
     | 
    
         
            +
            }
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            SolidusStripe.Elements.prototype.cardCvcElementOptions = function () {
         
     | 
| 
      
 93 
     | 
    
         
            +
              return {
         
     | 
| 
      
 94 
     | 
    
         
            +
                style: this.baseStyle()
         
     | 
| 
      
 95 
     | 
    
         
            +
              }
         
     | 
| 
      
 96 
     | 
    
         
            +
            }
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
       64 
98 
     | 
    
         
             
            SolidusStripe.Elements.prototype.showError = function(error) {
         
     | 
| 
       65 
99 
     | 
    
         
             
              var message = error.message || error;
         
     | 
| 
       66 
100 
     | 
    
         | 
| 
         @@ -87,18 +121,20 @@ SolidusStripe.Elements.prototype.onFormSubmit = function(event) { 
     | 
|
| 
       87 
121 
     | 
    
         | 
| 
       88 
122 
     | 
    
         
             
            SolidusStripe.Elements.prototype.elementsTokenHandler = function(token) {
         
     | 
| 
       89 
123 
     | 
    
         
             
              var mapCC = function(ccType) {
         
     | 
| 
       90 
     | 
    
         
            -
                if (ccType === 'MasterCard') {
         
     | 
| 
      
 124 
     | 
    
         
            +
                if (ccType === 'MasterCard' || ccType === 'mastercard') {
         
     | 
| 
       91 
125 
     | 
    
         
             
                  return 'mastercard';
         
     | 
| 
       92 
     | 
    
         
            -
                } else if (ccType === 'Visa') {
         
     | 
| 
      
 126 
     | 
    
         
            +
                } else if (ccType === 'Visa' || ccType === 'visa') {
         
     | 
| 
       93 
127 
     | 
    
         
             
                  return 'visa';
         
     | 
| 
       94 
     | 
    
         
            -
                } else if (ccType === 'American Express') {
         
     | 
| 
      
 128 
     | 
    
         
            +
                } else if (ccType === 'American Express' || ccType === 'amex') {
         
     | 
| 
       95 
129 
     | 
    
         
             
                  return 'amex';
         
     | 
| 
       96 
     | 
    
         
            -
                } else if (ccType === 'Discover') {
         
     | 
| 
      
 130 
     | 
    
         
            +
                } else if (ccType === 'Discover' || ccType === 'discover') {
         
     | 
| 
       97 
131 
     | 
    
         
             
                  return 'discover';
         
     | 
| 
       98 
     | 
    
         
            -
                } else if (ccType === 'Diners Club') {
         
     | 
| 
      
 132 
     | 
    
         
            +
                } else if (ccType === 'Diners Club' || ccType === 'diners') {
         
     | 
| 
       99 
133 
     | 
    
         
             
                  return 'dinersclub';
         
     | 
| 
       100 
     | 
    
         
            -
                } else if (ccType === 'JCB') {
         
     | 
| 
      
 134 
     | 
    
         
            +
                } else if (ccType === 'JCB' || ccType === 'jcb') {
         
     | 
| 
       101 
135 
     | 
    
         
             
                  return 'jcb';
         
     | 
| 
      
 136 
     | 
    
         
            +
                } else if (ccType === 'Unionpay' || ccType === 'unionpay') {
         
     | 
| 
      
 137 
     | 
    
         
            +
                  return 'unionpay';
         
     | 
| 
       102 
138 
     | 
    
         
             
                }
         
     | 
| 
       103 
139 
     | 
    
         
             
              };
         
     | 
| 
       104 
140 
     | 
    
         | 
| 
         @@ -69,6 +69,7 @@ SolidusStripe.PaymentIntents.prototype.onIntentsPayment = function(payment) { 
     | 
|
| 
       69 
69 
     | 
    
         
             
                    'Content-Type': 'application/json'
         
     | 
| 
       70 
70 
     | 
    
         
             
                  },
         
     | 
| 
       71 
71 
     | 
    
         
             
                  body: JSON.stringify({
         
     | 
| 
      
 72 
     | 
    
         
            +
                    form_data: this.form.serialize(),
         
     | 
| 
       72 
73 
     | 
    
         
             
                    spree_payment_method_id: this.config.id,
         
     | 
| 
       73 
74 
     | 
    
         
             
                    stripe_payment_method_id: payment.paymentMethod.id,
         
     | 
| 
       74 
75 
     | 
    
         
             
                    authenticity_token: this.authToken
         
     | 
    
        data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-request-button-shared.js
    CHANGED
    
    | 
         @@ -100,6 +100,7 @@ 
     | 
|
| 
       100 
100 
     | 
    
         
             
                      method: 'POST',
         
     | 
| 
       101 
101 
     | 
    
         
             
                      headers: { 'Content-Type': 'application/json' },
         
     | 
| 
       102 
102 
     | 
    
         
             
                      body: JSON.stringify({
         
     | 
| 
      
 103 
     | 
    
         
            +
                        form_data: this.form.serialize(),
         
     | 
| 
       103 
104 
     | 
    
         
             
                        spree_payment_method_id: this.config.id,
         
     | 
| 
       104 
105 
     | 
    
         
             
                        stripe_payment_intent_id: result.paymentIntent.id,
         
     | 
| 
       105 
106 
     | 
    
         
             
                        authenticity_token: this.authToken
         
     | 
| 
         @@ -6,5 +6,11 @@ SolidusStripe.Payment = function() { 
     | 
|
| 
       6 
6 
     | 
    
         
             
              this.authToken = $('meta[name="csrf-token"]').attr('content');
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
              this.stripe = Stripe(this.config.publishable_key);
         
     | 
| 
       9 
     | 
    
         
            -
              this.elements = this.stripe.elements( 
     | 
| 
      
 9 
     | 
    
         
            +
              this.elements = this.stripe.elements(this.elementsBaseOptions());
         
     | 
| 
      
 10 
     | 
    
         
            +
            };
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            SolidusStripe.Payment.prototype.elementsBaseOptions = function () {
         
     | 
| 
      
 13 
     | 
    
         
            +
              return {
         
     | 
| 
      
 14 
     | 
    
         
            +
                locale: 'en'
         
     | 
| 
      
 15 
     | 
    
         
            +
              };
         
     | 
| 
       10 
16 
     | 
    
         
             
            };
         
     | 
| 
         @@ -6,25 +6,19 @@ module SolidusStripe 
     | 
|
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
                def confirm
         
     | 
| 
       8 
8 
     | 
    
         
             
                  begin
         
     | 
| 
       9 
     | 
    
         
            -
                     
     | 
| 
       10 
     | 
    
         
            -
                       
     | 
| 
       11 
     | 
    
         
            -
                         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
                         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                        confirm: true,
         
     | 
| 
       16 
     | 
    
         
            -
                        setup_future_usage: 'on_session',
         
     | 
| 
       17 
     | 
    
         
            -
                        metadata: { order_id: current_order.id }
         
     | 
| 
       18 
     | 
    
         
            -
                      )
         
     | 
| 
       19 
     | 
    
         
            -
                    elsif params[:stripe_payment_intent_id].present?
         
     | 
| 
       20 
     | 
    
         
            -
                      intent = stripe.confirm_intent(params[:stripe_payment_intent_id], nil)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @intent = begin
         
     | 
| 
      
 10 
     | 
    
         
            +
                      if params[:stripe_payment_method_id].present?
         
     | 
| 
      
 11 
     | 
    
         
            +
                        create_intent
         
     | 
| 
      
 12 
     | 
    
         
            +
                      elsif params[:stripe_payment_intent_id].present?
         
     | 
| 
      
 13 
     | 
    
         
            +
                        stripe.confirm_intent(params[:stripe_payment_intent_id], nil)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
       21 
15 
     | 
    
         
             
                    end
         
     | 
| 
       22 
16 
     | 
    
         
             
                  rescue Stripe::CardError => e
         
     | 
| 
       23 
17 
     | 
    
         
             
                    render json: { error: e.message }, status: 500
         
     | 
| 
       24 
18 
     | 
    
         
             
                    return
         
     | 
| 
       25 
19 
     | 
    
         
             
                  end
         
     | 
| 
       26 
20 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                  generate_payment_response 
     | 
| 
      
 21 
     | 
    
         
            +
                  generate_payment_response
         
     | 
| 
       28 
22 
     | 
    
         
             
                end
         
     | 
| 
       29 
23 
     | 
    
         | 
| 
       30 
24 
     | 
    
         
             
                private
         
     | 
| 
         @@ -33,20 +27,35 @@ module SolidusStripe 
     | 
|
| 
       33 
27 
     | 
    
         
             
                  @stripe ||= Spree::PaymentMethod::StripeCreditCard.find(params[:spree_payment_method_id])
         
     | 
| 
       34 
28 
     | 
    
         
             
                end
         
     | 
| 
       35 
29 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                def generate_payment_response 
     | 
| 
       37 
     | 
    
         
            -
                  response = intent.params
         
     | 
| 
      
 30 
     | 
    
         
            +
                def generate_payment_response
         
     | 
| 
      
 31 
     | 
    
         
            +
                  response = @intent.params
         
     | 
| 
       38 
32 
     | 
    
         
             
                  # Note that if your API version is before 2019-02-11, 'requires_action'
         
     | 
| 
       39 
33 
     | 
    
         
             
                  # appears as 'requires_source_action'.
         
     | 
| 
       40 
34 
     | 
    
         
             
                  if %w[requires_source_action requires_action].include?(response['status']) && response['next_action']['type'] == 'use_stripe_sdk'
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                  elsif response['status'] == ' 
     | 
| 
      
 35 
     | 
    
         
            +
                    render json: {
         
     | 
| 
      
 36 
     | 
    
         
            +
                      requires_action: true,
         
     | 
| 
      
 37 
     | 
    
         
            +
                      stripe_payment_intent_client_secret: response['client_secret']
         
     | 
| 
      
 38 
     | 
    
         
            +
                    }
         
     | 
| 
      
 39 
     | 
    
         
            +
                  elsif response['status'] == 'requires_capture'
         
     | 
| 
      
 40 
     | 
    
         
            +
                    SolidusStripe::CreateIntentsOrderService.new(@intent, stripe, self).call
         
     | 
| 
       46 
41 
     | 
    
         
             
                    render json: { success: true }
         
     | 
| 
       47 
42 
     | 
    
         
             
                  else
         
     | 
| 
       48 
43 
     | 
    
         
             
                    render json: { error: response['error']['message'] }, status: 500
         
     | 
| 
       49 
44 
     | 
    
         
             
                  end
         
     | 
| 
       50 
45 
     | 
    
         
             
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def create_intent
         
     | 
| 
      
 48 
     | 
    
         
            +
                  stripe.create_intent(
         
     | 
| 
      
 49 
     | 
    
         
            +
                    (current_order.total * 100).to_i,
         
     | 
| 
      
 50 
     | 
    
         
            +
                    params[:stripe_payment_method_id],
         
     | 
| 
      
 51 
     | 
    
         
            +
                    description: "Solidus Order ID: #{current_order.number} (pending)",
         
     | 
| 
      
 52 
     | 
    
         
            +
                    currency: current_order.currency,
         
     | 
| 
      
 53 
     | 
    
         
            +
                    confirmation_method: 'manual',
         
     | 
| 
      
 54 
     | 
    
         
            +
                    capture_method: 'manual',
         
     | 
| 
      
 55 
     | 
    
         
            +
                    confirm: true,
         
     | 
| 
      
 56 
     | 
    
         
            +
                    setup_future_usage: 'off_session',
         
     | 
| 
      
 57 
     | 
    
         
            +
                    metadata: { order_id: current_order.id }
         
     | 
| 
      
 58 
     | 
    
         
            +
                  )
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
       51 
60 
     | 
    
         
             
              end
         
     | 
| 
       52 
61 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Spree
         
     | 
| 
      
 4 
     | 
    
         
            +
              module OrderUpdateAttributesDecorator
         
     | 
| 
      
 5 
     | 
    
         
            +
                def assign_payments_attributes
         
     | 
| 
      
 6 
     | 
    
         
            +
                  return if payments_attributes.empty?
         
     | 
| 
      
 7 
     | 
    
         
            +
                  return if adding_new_stripe_payment_intents_card?
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  stripe_intents_pending_payments.each(&:void_transaction!)
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  super
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                private
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def adding_new_stripe_payment_intents_card?
         
     | 
| 
      
 17 
     | 
    
         
            +
                  paying_with_stripe_intents? && stripe_intents_pending_payments.any?
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def stripe_intents_pending_payments
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @stripe_intents_pending_payments ||= order.payments.valid.select do |payment|
         
     | 
| 
      
 22 
     | 
    
         
            +
                    payment_method = payment.payment_method
         
     | 
| 
      
 23 
     | 
    
         
            +
                    payment.pending? && stripe_intents?(payment_method)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def paying_with_stripe_intents?
         
     | 
| 
      
 28 
     | 
    
         
            +
                  if id = payments_attributes.first&.dig(:payment_method_id)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    stripe_intents?(Spree::PaymentMethod.find(id))
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def stripe_intents?(payment_method)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  payment_method.respond_to?(:v3_intents?) && payment_method.v3_intents?
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                ::Spree::OrderUpdateAttributes.prepend(self)
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,70 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module SolidusStripe
         
     | 
| 
      
 4 
     | 
    
         
            +
              class CreateIntentsOrderService
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :intent, :stripe, :controller
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                delegate :request, :current_order, :params, to: :controller
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(intent, stripe, controller)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @intent, @stripe, @controller = intent, stripe, controller
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def call
         
     | 
| 
      
 14 
     | 
    
         
            +
                  invalidate_previous_payment_intents_payments
         
     | 
| 
      
 15 
     | 
    
         
            +
                  payment = create_payment
         
     | 
| 
      
 16 
     | 
    
         
            +
                  description = "Solidus Order ID: #{payment.gateway_order_identifier}"
         
     | 
| 
      
 17 
     | 
    
         
            +
                  stripe.update_intent(nil, response['id'], nil, description: description)
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                private
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def invalidate_previous_payment_intents_payments
         
     | 
| 
      
 23 
     | 
    
         
            +
                  if stripe.v3_intents?
         
     | 
| 
      
 24 
     | 
    
         
            +
                    current_order.payments.pending.where(payment_method: stripe).each(&:void_transaction!)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def create_payment
         
     | 
| 
      
 29 
     | 
    
         
            +
                  Spree::OrderUpdateAttributes.new(
         
     | 
| 
      
 30 
     | 
    
         
            +
                    current_order,
         
     | 
| 
      
 31 
     | 
    
         
            +
                    payment_params,
         
     | 
| 
      
 32 
     | 
    
         
            +
                    request_env: request.headers.env
         
     | 
| 
      
 33 
     | 
    
         
            +
                  ).apply
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  Spree::Payment.find_by(response_code: response['id']).tap do |payment|
         
     | 
| 
      
 36 
     | 
    
         
            +
                    payment.update!(state: :pending)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def payment_params
         
     | 
| 
      
 41 
     | 
    
         
            +
                  card = response['charges']['data'][0]['payment_method_details']['card']
         
     | 
| 
      
 42 
     | 
    
         
            +
                  address_attributes = form_data['payment_source'][stripe.id.to_s]['address_attributes']
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  {
         
     | 
| 
      
 45 
     | 
    
         
            +
                    payments_attributes: [{
         
     | 
| 
      
 46 
     | 
    
         
            +
                      payment_method_id: stripe.id,
         
     | 
| 
      
 47 
     | 
    
         
            +
                      amount: current_order.total,
         
     | 
| 
      
 48 
     | 
    
         
            +
                      response_code: response['id'],
         
     | 
| 
      
 49 
     | 
    
         
            +
                      source_attributes: {
         
     | 
| 
      
 50 
     | 
    
         
            +
                        month: card['exp_month'],
         
     | 
| 
      
 51 
     | 
    
         
            +
                        year: card['exp_year'],
         
     | 
| 
      
 52 
     | 
    
         
            +
                        cc_type: card['brand'],
         
     | 
| 
      
 53 
     | 
    
         
            +
                        gateway_payment_profile_id: response['payment_method'],
         
     | 
| 
      
 54 
     | 
    
         
            +
                        last_digits: card['last4'],
         
     | 
| 
      
 55 
     | 
    
         
            +
                        name: current_order.bill_address.full_name,
         
     | 
| 
      
 56 
     | 
    
         
            +
                        address_attributes: address_attributes
         
     | 
| 
      
 57 
     | 
    
         
            +
                      }
         
     | 
| 
      
 58 
     | 
    
         
            +
                    }]
         
     | 
| 
      
 59 
     | 
    
         
            +
                  }
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                def response
         
     | 
| 
      
 63 
     | 
    
         
            +
                  intent.params
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                def form_data
         
     | 
| 
      
 67 
     | 
    
         
            +
                  Rack::Utils.parse_nested_query(params[:form_data])
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -15,6 +15,8 @@ module Spree 
     | 
|
| 
       15 
15 
     | 
    
         
             
                    'Visa' => 'visa'
         
     | 
| 
       16 
16 
     | 
    
         
             
                  }
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
      
 18 
     | 
    
         
            +
                  delegate :create_intent, :update_intent, :confirm_intent, to: :gateway
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       18 
20 
     | 
    
         
             
                  def stripe_config(order)
         
     | 
| 
       19 
21 
     | 
    
         
             
                    {
         
     | 
| 
       20 
22 
     | 
    
         
             
                      id: id,
         
     | 
| 
         @@ -59,14 +61,6 @@ module Spree 
     | 
|
| 
       59 
61 
     | 
    
         
             
                    true
         
     | 
| 
       60 
62 
     | 
    
         
             
                  end
         
     | 
| 
       61 
63 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
                  def create_intent(*args)
         
     | 
| 
       63 
     | 
    
         
            -
                    gateway.create_intent(*args)
         
     | 
| 
       64 
     | 
    
         
            -
                  end
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                  def confirm_intent(*args)
         
     | 
| 
       67 
     | 
    
         
            -
                    gateway.confirm_intent(*args)
         
     | 
| 
       68 
     | 
    
         
            -
                  end
         
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
64 
     | 
    
         
             
                  def purchase(money, creditcard, transaction_options)
         
     | 
| 
       71 
65 
     | 
    
         
             
                    gateway.purchase(*options_for_purchase_or_auth(money, creditcard, transaction_options))
         
     | 
| 
       72 
66 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -140,8 +134,9 @@ module Spree 
     | 
|
| 
       140 
134 
     | 
    
         | 
| 
       141 
135 
     | 
    
         
             
                  def options_for_purchase_or_auth(money, creditcard, transaction_options)
         
     | 
| 
       142 
136 
     | 
    
         
             
                    options = {}
         
     | 
| 
       143 
     | 
    
         
            -
                    options[:description] = " 
     | 
| 
      
 137 
     | 
    
         
            +
                    options[:description] = "Solidus Order ID: #{transaction_options[:order_id]}"
         
     | 
| 
       144 
138 
     | 
    
         
             
                    options[:currency] = transaction_options[:currency]
         
     | 
| 
      
 139 
     | 
    
         
            +
                    options[:off_session] = true if v3_intents?
         
     | 
| 
       145 
140 
     | 
    
         | 
| 
       146 
141 
     | 
    
         
             
                    if customer = creditcard.gateway_customer_profile_id
         
     | 
| 
       147 
142 
     | 
    
         
             
                      options[:customer] = customer
         
     | 
| 
         @@ -6,6 +6,8 @@ RSpec.describe "Stripe checkout", type: :feature do 
     | 
|
| 
       6 
6 
     | 
    
         
             
              let(:zone) { FactoryBot.create(:zone) }
         
     | 
| 
       7 
7 
     | 
    
         
             
              let(:country) { FactoryBot.create(:country) }
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
      
 9 
     | 
    
         
            +
              let(:card_3d_secure) { "4000 0025 0000 3155" }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
       9 
11 
     | 
    
         
             
              before do
         
     | 
| 
       10 
12 
     | 
    
         
             
                FactoryBot.create(:store)
         
     | 
| 
       11 
13 
     | 
    
         
             
                zone.members << Spree::ZoneMember.create!(zoneable: country)
         
     | 
| 
         @@ -301,24 +303,8 @@ RSpec.describe "Stripe checkout", type: :feature do 
     | 
|
| 
       301 
303 
     | 
    
         
             
                end
         
     | 
| 
       302 
304 
     | 
    
         | 
| 
       303 
305 
     | 
    
         
             
                context "when using a valid 3D Secure card" do
         
     | 
| 
       304 
     | 
    
         
            -
                  let(:card_number) { "4000 0027 6000 3184" }
         
     | 
| 
       305 
     | 
    
         
            -
             
     | 
| 
       306 
306 
     | 
    
         
             
                  it "successfully completes the checkout" do
         
     | 
| 
       307 
     | 
    
         
            -
                     
     | 
| 
       308 
     | 
    
         
            -
                      card_number.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
         
     | 
| 
       309 
     | 
    
         
            -
                    end
         
     | 
| 
       310 
     | 
    
         
            -
                    within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
         
     | 
| 
       311 
     | 
    
         
            -
                    within_frame(find '#card_expiry iframe') do
         
     | 
| 
       312 
     | 
    
         
            -
                      '0132'.split('').each { |n| find_field('exp-date').native.send_keys(n) }
         
     | 
| 
       313 
     | 
    
         
            -
                    end
         
     | 
| 
       314 
     | 
    
         
            -
             
     | 
| 
       315 
     | 
    
         
            -
                    click_button "Save and Continue"
         
     | 
| 
       316 
     | 
    
         
            -
             
     | 
| 
       317 
     | 
    
         
            -
                    within_3d_secure_modal do
         
     | 
| 
       318 
     | 
    
         
            -
                      expect(page).to have_content '$19.99 using 3D Secure'
         
     | 
| 
       319 
     | 
    
         
            -
             
     | 
| 
       320 
     | 
    
         
            -
                      click_button 'Complete authentication'
         
     | 
| 
       321 
     | 
    
         
            -
                    end
         
     | 
| 
      
 307 
     | 
    
         
            +
                    authenticate_3d_secure_card(card_3d_secure)
         
     | 
| 
       322 
308 
     | 
    
         | 
| 
       323 
309 
     | 
    
         
             
                    expect(page).to have_current_path("/checkout/confirm")
         
     | 
| 
       324 
310 
     | 
    
         | 
| 
         @@ -368,59 +354,133 @@ RSpec.describe "Stripe checkout", type: :feature do 
     | 
|
| 
       368 
354 
     | 
    
         
             
                  end
         
     | 
| 
       369 
355 
     | 
    
         
             
                end
         
     | 
| 
       370 
356 
     | 
    
         | 
| 
       371 
     | 
    
         
            -
                 
     | 
| 
       372 
     | 
    
         
            -
                   
     | 
| 
       373 
     | 
    
         
            -
                    "4000 0027 6000 3184".split('').each { |n| find_field('cardnumber').native.send_keys(n) }
         
     | 
| 
       374 
     | 
    
         
            -
                  end
         
     | 
| 
       375 
     | 
    
         
            -
                  within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
         
     | 
| 
       376 
     | 
    
         
            -
                  within_frame(find '#card_expiry iframe') do
         
     | 
| 
       377 
     | 
    
         
            -
                    '0132'.split('').each { |n| find_field('exp-date').native.send_keys(n) }
         
     | 
| 
       378 
     | 
    
         
            -
                  end
         
     | 
| 
       379 
     | 
    
         
            -
                  click_button "Save and Continue"
         
     | 
| 
      
 357 
     | 
    
         
            +
                context "when reusing a card" do
         
     | 
| 
      
 358 
     | 
    
         
            +
                  stub_authorization!
         
     | 
| 
       380 
359 
     | 
    
         | 
| 
       381 
     | 
    
         
            -
                   
     | 
| 
       382 
     | 
    
         
            -
                     
     | 
| 
      
 360 
     | 
    
         
            +
                  it "succesfully creates a second payment that can be captured in the backend" do
         
     | 
| 
      
 361 
     | 
    
         
            +
                    authenticate_3d_secure_card(card_3d_secure)
         
     | 
| 
      
 362 
     | 
    
         
            +
             
     | 
| 
      
 363 
     | 
    
         
            +
                    expect(page).to have_current_path("/checkout/confirm")
         
     | 
| 
      
 364 
     | 
    
         
            +
                    click_button "Place Order"
         
     | 
| 
      
 365 
     | 
    
         
            +
                    expect(page).to have_content("Your order has been processed successfully")
         
     | 
| 
      
 366 
     | 
    
         
            +
             
     | 
| 
      
 367 
     | 
    
         
            +
                    visit spree.root_path
         
     | 
| 
      
 368 
     | 
    
         
            +
                    click_link "DL-44"
         
     | 
| 
      
 369 
     | 
    
         
            +
                    click_button "Add To Cart"
         
     | 
| 
      
 370 
     | 
    
         
            +
             
     | 
| 
      
 371 
     | 
    
         
            +
                    expect(page).to have_current_path("/cart")
         
     | 
| 
      
 372 
     | 
    
         
            +
                    click_button "Checkout"
         
     | 
| 
      
 373 
     | 
    
         
            +
             
     | 
| 
      
 374 
     | 
    
         
            +
                    # Address
         
     | 
| 
      
 375 
     | 
    
         
            +
                    expect(page).to have_current_path("/checkout/address")
         
     | 
| 
      
 376 
     | 
    
         
            +
             
     | 
| 
      
 377 
     | 
    
         
            +
                    within("#billing") do
         
     | 
| 
      
 378 
     | 
    
         
            +
                      fill_in_name
         
     | 
| 
      
 379 
     | 
    
         
            +
                      fill_in "Street Address", with: "YT-1300"
         
     | 
| 
      
 380 
     | 
    
         
            +
                      fill_in "City", with: "Mos Eisley"
         
     | 
| 
      
 381 
     | 
    
         
            +
                      select "United States of America", from: "Country"
         
     | 
| 
      
 382 
     | 
    
         
            +
                      select country.states.first.name, from: "order_bill_address_attributes_state_id"
         
     | 
| 
      
 383 
     | 
    
         
            +
                      fill_in "Zip", with: "12010"
         
     | 
| 
      
 384 
     | 
    
         
            +
                      fill_in "Phone", with: "(555) 555-5555"
         
     | 
| 
      
 385 
     | 
    
         
            +
                    end
         
     | 
| 
      
 386 
     | 
    
         
            +
                    click_on "Save and Continue"
         
     | 
| 
      
 387 
     | 
    
         
            +
             
     | 
| 
      
 388 
     | 
    
         
            +
                    # Delivery
         
     | 
| 
      
 389 
     | 
    
         
            +
                    expect(page).to have_current_path("/checkout/delivery")
         
     | 
| 
      
 390 
     | 
    
         
            +
                    expect(page).to have_content("UPS Ground")
         
     | 
| 
      
 391 
     | 
    
         
            +
                    click_on "Save and Continue"
         
     | 
| 
      
 392 
     | 
    
         
            +
             
     | 
| 
      
 393 
     | 
    
         
            +
                    # Payment
         
     | 
| 
      
 394 
     | 
    
         
            +
                    expect(page).to have_current_path("/checkout/payment")
         
     | 
| 
      
 395 
     | 
    
         
            +
                    choose "Use an existing card on file"
         
     | 
| 
      
 396 
     | 
    
         
            +
                    click_button "Save and Continue"
         
     | 
| 
      
 397 
     | 
    
         
            +
             
     | 
| 
      
 398 
     | 
    
         
            +
                    # Confirm
         
     | 
| 
      
 399 
     | 
    
         
            +
                    expect(page).to have_current_path("/checkout/confirm")
         
     | 
| 
      
 400 
     | 
    
         
            +
                    click_button "Place Order"
         
     | 
| 
      
 401 
     | 
    
         
            +
                    expect(page).to have_content("Your order has been processed successfully")
         
     | 
| 
      
 402 
     | 
    
         
            +
             
     | 
| 
      
 403 
     | 
    
         
            +
                    # Capture in backend
         
     | 
| 
      
 404 
     | 
    
         
            +
                    Spree::Order.complete.each do |order|
         
     | 
| 
      
 405 
     | 
    
         
            +
                      visit spree.admin_path
         
     | 
| 
      
 406 
     | 
    
         
            +
             
     | 
| 
      
 407 
     | 
    
         
            +
                      expect(page).to have_selector("#listing_orders tbody tr", count: 2)
         
     | 
| 
      
 408 
     | 
    
         
            +
             
     | 
| 
      
 409 
     | 
    
         
            +
                      click_link order.number
         
     | 
| 
      
 410 
     | 
    
         
            +
             
     | 
| 
      
 411 
     | 
    
         
            +
                      click_link "Payments"
         
     | 
| 
      
 412 
     | 
    
         
            +
                      find(".fa-capture").click
         
     | 
| 
      
 413 
     | 
    
         
            +
             
     | 
| 
      
 414 
     | 
    
         
            +
                      expect(page).to have_content "Payment Updated"
         
     | 
| 
      
 415 
     | 
    
         
            +
                      expect(find("table#payments")).to have_content "Completed"
         
     | 
| 
      
 416 
     | 
    
         
            +
                    end
         
     | 
| 
       383 
417 
     | 
    
         
             
                  end
         
     | 
| 
      
 418 
     | 
    
         
            +
                end
         
     | 
| 
       384 
419 
     | 
    
         | 
| 
       385 
     | 
    
         
            -
             
     | 
| 
       386 
     | 
    
         
            -
                   
     | 
| 
       387 
     | 
    
         
            -
                  expect(page).to have_content("Your order has been processed successfully")
         
     | 
| 
      
 420 
     | 
    
         
            +
                context "when paying with multiple payment methods" do
         
     | 
| 
      
 421 
     | 
    
         
            +
                  stub_authorization!
         
     | 
| 
       388 
422 
     | 
    
         | 
| 
       389 
     | 
    
         
            -
                   
     | 
| 
       390 
     | 
    
         
            -
             
     | 
| 
       391 
     | 
    
         
            -
                  click_button "Add To Cart"
         
     | 
| 
      
 423 
     | 
    
         
            +
                  context "when paying first with regular card, then with 3D-Secure card" do
         
     | 
| 
      
 424 
     | 
    
         
            +
                    let(:regular_card) { "4242 4242 4242 4242"}
         
     | 
| 
       392 
425 
     | 
    
         | 
| 
       393 
     | 
    
         
            -
             
     | 
| 
       394 
     | 
    
         
            -
             
     | 
| 
      
 426 
     | 
    
         
            +
                    it "voids the first stripe payment and successfully pays with 3DS card" do
         
     | 
| 
      
 427 
     | 
    
         
            +
                      within_frame find('#card_number iframe') do
         
     | 
| 
      
 428 
     | 
    
         
            +
                        regular_card.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
         
     | 
| 
      
 429 
     | 
    
         
            +
                      end
         
     | 
| 
      
 430 
     | 
    
         
            +
                      within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
         
     | 
| 
      
 431 
     | 
    
         
            +
                      within_frame(find '#card_expiry iframe') do
         
     | 
| 
      
 432 
     | 
    
         
            +
                        '0132'.split('').each { |n| find_field('exp-date').native.send_keys(n) }
         
     | 
| 
      
 433 
     | 
    
         
            +
                      end
         
     | 
| 
      
 434 
     | 
    
         
            +
                      click_button "Save and Continue"
         
     | 
| 
       395 
435 
     | 
    
         | 
| 
       396 
     | 
    
         
            -
             
     | 
| 
       397 
     | 
    
         
            -
                  expect(page).to have_current_path("/checkout/address")
         
     | 
| 
      
 436 
     | 
    
         
            +
                      expect(page).to have_content "Ending in 4242"
         
     | 
| 
       398 
437 
     | 
    
         | 
| 
       399 
     | 
    
         
            -
             
     | 
| 
       400 
     | 
    
         
            -
             
     | 
| 
       401 
     | 
    
         
            -
             
     | 
| 
       402 
     | 
    
         
            -
             
     | 
| 
       403 
     | 
    
         
            -
             
     | 
| 
       404 
     | 
    
         
            -
             
     | 
| 
       405 
     | 
    
         
            -
             
     | 
| 
       406 
     | 
    
         
            -
             
     | 
| 
      
 438 
     | 
    
         
            +
                      click_link "Payment"
         
     | 
| 
      
 439 
     | 
    
         
            +
             
     | 
| 
      
 440 
     | 
    
         
            +
                      authenticate_3d_secure_card(card_3d_secure)
         
     | 
| 
      
 441 
     | 
    
         
            +
                      click_button "Place Order"
         
     | 
| 
      
 442 
     | 
    
         
            +
                      expect(page).to have_content "Your order has been processed successfully"
         
     | 
| 
      
 443 
     | 
    
         
            +
             
     | 
| 
      
 444 
     | 
    
         
            +
                      visit spree.admin_path
         
     | 
| 
      
 445 
     | 
    
         
            +
                      click_link Spree::Order.complete.first.number
         
     | 
| 
      
 446 
     | 
    
         
            +
                      click_link "Payments"
         
     | 
| 
      
 447 
     | 
    
         
            +
             
     | 
| 
      
 448 
     | 
    
         
            +
                      payments = all('table#payments tbody tr')
         
     | 
| 
      
 449 
     | 
    
         
            +
             
     | 
| 
      
 450 
     | 
    
         
            +
                      expect(payments.first).to have_content "Stripe"
         
     | 
| 
      
 451 
     | 
    
         
            +
                      expect(payments.first).to have_content "Void"
         
     | 
| 
      
 452 
     | 
    
         
            +
             
     | 
| 
      
 453 
     | 
    
         
            +
                      expect(payments.last).to have_content "Stripe"
         
     | 
| 
      
 454 
     | 
    
         
            +
                      expect(payments.last).to have_content "Pending"
         
     | 
| 
      
 455 
     | 
    
         
            +
                    end
         
     | 
| 
       407 
456 
     | 
    
         
             
                  end
         
     | 
| 
       408 
     | 
    
         
            -
                  click_on "Save and Continue"
         
     | 
| 
       409 
457 
     | 
    
         | 
| 
       410 
     | 
    
         
            -
                   
     | 
| 
       411 
     | 
    
         
            -
             
     | 
| 
       412 
     | 
    
         
            -
                  expect(page).to have_content("UPS Ground")
         
     | 
| 
       413 
     | 
    
         
            -
                  click_on "Save and Continue"
         
     | 
| 
      
 458 
     | 
    
         
            +
                  context "when paying first with 3D-Secure card, then with check" do
         
     | 
| 
      
 459 
     | 
    
         
            +
                    before { create :check_payment_method }
         
     | 
| 
       414 
460 
     | 
    
         | 
| 
       415 
     | 
    
         
            -
             
     | 
| 
       416 
     | 
    
         
            -
             
     | 
| 
       417 
     | 
    
         
            -
             
     | 
| 
       418 
     | 
    
         
            -
                  click_button "Save and Continue"
         
     | 
| 
      
 461 
     | 
    
         
            +
                    it "voids the stripe payment and successfully pays with check" do
         
     | 
| 
      
 462 
     | 
    
         
            +
                      authenticate_3d_secure_card(card_3d_secure)
         
     | 
| 
      
 463 
     | 
    
         
            +
                      expect(page).to have_current_path("/checkout/confirm")
         
     | 
| 
       419 
464 
     | 
    
         | 
| 
       420 
     | 
    
         
            -
             
     | 
| 
       421 
     | 
    
         
            -
             
     | 
| 
       422 
     | 
    
         
            -
             
     | 
| 
       423 
     | 
    
         
            -
             
     | 
| 
      
 465 
     | 
    
         
            +
                      click_link "Payment"
         
     | 
| 
      
 466 
     | 
    
         
            +
                      choose "Check"
         
     | 
| 
      
 467 
     | 
    
         
            +
                      click_button "Save and Continue"
         
     | 
| 
      
 468 
     | 
    
         
            +
                      expect(find(".payment-info")).to have_content "Check"
         
     | 
| 
      
 469 
     | 
    
         
            +
                      expect(page).to have_content "Your order has been processed successfully"
         
     | 
| 
      
 470 
     | 
    
         
            +
             
     | 
| 
      
 471 
     | 
    
         
            +
                      visit spree.admin_path
         
     | 
| 
      
 472 
     | 
    
         
            +
                      click_link Spree::Order.complete.first.number
         
     | 
| 
      
 473 
     | 
    
         
            +
                      click_link "Payments"
         
     | 
| 
      
 474 
     | 
    
         
            +
                      payments = all('table#payments tbody tr')
         
     | 
| 
      
 475 
     | 
    
         
            +
             
     | 
| 
      
 476 
     | 
    
         
            +
                      stripe_payment = payments.first
         
     | 
| 
      
 477 
     | 
    
         
            +
                      expect(stripe_payment).to have_content "Stripe"
         
     | 
| 
      
 478 
     | 
    
         
            +
                      expect(stripe_payment).to have_content "Void"
         
     | 
| 
      
 479 
     | 
    
         
            +
             
     | 
| 
      
 480 
     | 
    
         
            +
                      check_payment = payments.last
         
     | 
| 
      
 481 
     | 
    
         
            +
                      expect(check_payment).to have_content "Check"
         
     | 
| 
      
 482 
     | 
    
         
            +
                    end
         
     | 
| 
      
 483 
     | 
    
         
            +
                  end
         
     | 
| 
       424 
484 
     | 
    
         
             
                end
         
     | 
| 
       425 
485 
     | 
    
         | 
| 
       426 
486 
     | 
    
         
             
                it_behaves_like "Stripe Elements invalid payments"
         
     | 
| 
         @@ -433,4 +493,21 @@ RSpec.describe "Stripe checkout", type: :feature do 
     | 
|
| 
       433 
493 
     | 
    
         
             
                  end
         
     | 
| 
       434 
494 
     | 
    
         
             
                end
         
     | 
| 
       435 
495 
     | 
    
         
             
              end
         
     | 
| 
      
 496 
     | 
    
         
            +
             
     | 
| 
      
 497 
     | 
    
         
            +
              def authenticate_3d_secure_card(card_number)
         
     | 
| 
      
 498 
     | 
    
         
            +
                within_frame find('#card_number iframe') do
         
     | 
| 
      
 499 
     | 
    
         
            +
                  card_number.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
         
     | 
| 
      
 500 
     | 
    
         
            +
                end
         
     | 
| 
      
 501 
     | 
    
         
            +
                within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
         
     | 
| 
      
 502 
     | 
    
         
            +
                within_frame(find '#card_expiry iframe') do
         
     | 
| 
      
 503 
     | 
    
         
            +
                  '0132'.split('').each { |n| find_field('exp-date').native.send_keys(n) }
         
     | 
| 
      
 504 
     | 
    
         
            +
                end
         
     | 
| 
      
 505 
     | 
    
         
            +
                click_button "Save and Continue"
         
     | 
| 
      
 506 
     | 
    
         
            +
             
     | 
| 
      
 507 
     | 
    
         
            +
                within_3d_secure_modal do
         
     | 
| 
      
 508 
     | 
    
         
            +
                  expect(page).to have_content '$19.99 using 3D Secure'
         
     | 
| 
      
 509 
     | 
    
         
            +
             
     | 
| 
      
 510 
     | 
    
         
            +
                  click_button 'Complete authentication'
         
     | 
| 
      
 511 
     | 
    
         
            +
                end
         
     | 
| 
      
 512 
     | 
    
         
            +
              end
         
     | 
| 
       436 
513 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: solidus_stripe
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 3. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 3.1.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Solidus Team
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2020- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2020-04-10 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: solidus_core
         
     | 
| 
         @@ -101,7 +101,10 @@ files: 
     | 
|
| 
       101 
101 
     | 
    
         
             
            - app/controllers/solidus_stripe/intents_controller.rb
         
     | 
| 
       102 
102 
     | 
    
         
             
            - app/controllers/solidus_stripe/payment_request_controller.rb
         
     | 
| 
       103 
103 
     | 
    
         
             
            - app/controllers/spree/stripe_controller.rb
         
     | 
| 
      
 104 
     | 
    
         
            +
            - app/decorators/models/spree/order_update_attributes_decorator.rb
         
     | 
| 
      
 105 
     | 
    
         
            +
            - app/decorators/models/spree/payment_decorator.rb
         
     | 
| 
       104 
106 
     | 
    
         
             
            - app/models/solidus_stripe/address_from_params_service.rb
         
     | 
| 
      
 107 
     | 
    
         
            +
            - app/models/solidus_stripe/create_intents_order_service.rb
         
     | 
| 
       105 
108 
     | 
    
         
             
            - app/models/solidus_stripe/prepare_order_for_payment_service.rb
         
     | 
| 
       106 
109 
     | 
    
         
             
            - app/models/solidus_stripe/shipping_rates_service.rb
         
     | 
| 
       107 
110 
     | 
    
         
             
            - app/models/spree/payment_method/stripe_credit_card.rb
         
     |