solidus_stripe 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20cb6dc5a1a623991ffb0903a8135ef20993fa54858bf1f58c19eaf5fefdea35
4
- data.tar.gz: 823bc46c1d66e7f6a85a7c7b50bee7ffa978e3e0daaf4454a2b2d89130595f59
3
+ metadata.gz: b4105fb7ad047aa377a29ebc364dc19d861ce07e4bbcb264fb5494fcf9bbb8f1
4
+ data.tar.gz: 43fa8a0106162cd0c26f7ff1e6fc65da2547137d98a1e4650aff04d639daae7d
5
5
  SHA512:
6
- metadata.gz: e6820bf570104f254774f6504ebb7ce0a1d3ed8a9f35d0a09f2c38e9d00a41006f94d89ed774ecf8f9ddcb58d7947cfa12433bc03d11c6df603280094c744a4b
7
- data.tar.gz: e4ad550366c57a70990576c1c17257bea819b2a89154cdb6e4fa0cad1d1254d84ea716a72d18232b3102070b02b323f656c08437ad6df1d94c3358361961ff56
6
+ metadata.gz: 2c891474a71412e3a03443ece9b16be6e49a0e7c6c1f6b6ad69f56d09608976fdc816211e779ce45556cfbc573c380334a65f7747170a3071763cb65b768dad6
7
+ data.tar.gz: cf52ef3d344bb3335f795b6e708d1b35151b80159e6a52ced595c09b0339c47b85a2bbf89932d14ff8661b35a3cbd22fb8da0b1cebcb8a95736221e6645609e8
data/CHANGELOG.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased](https://github.com/solidusio/solidus_stripe/tree/HEAD)
3
+ ## [v2.0.0](https://github.com/solidusio/solidus_stripe/tree/v2.0.0) (2020-03-03)
4
4
 
5
- [Full Changelog](https://github.com/solidusio/solidus_stripe/compare/v1.2.0...HEAD)
5
+ [Full Changelog](https://github.com/solidusio/solidus_stripe/compare/v1.2.0...v2.0.0)
6
6
 
7
7
  **Implemented enhancements:**
8
8
 
data/README.md CHANGED
@@ -73,10 +73,20 @@ Using Stripe Payment Intents API
73
73
  --------------------------------
74
74
 
75
75
  If you want to use the new SCA-ready Stripe Payment Intents API you need
76
- to change the `v3_intents` preference from the code above to true and,
77
- if you want to allow also Apple Pay and Google Pay payments, set the
78
- `stripe_country` preference, which represents the two-letter country
79
- code of your Stripe account:
76
+ to change the `v3_intents` preference from the code above to true.
77
+
78
+ Also, if you want to allow Apple Pay and Google Pay payments using the
79
+ Stripe payment request button API, you only need to set the `stripe_country`
80
+ preference, which represents the two-letter country code of your Stripe
81
+ account. Conversely, if you need to disable the button you can simply remove
82
+ the `stripe_country` preference.
83
+
84
+ Please refer to Stripe official
85
+ [documentation](https://stripe.com/docs/stripe-js/elements/payment-request-button)
86
+ for further instructions on how to make this work properly.
87
+
88
+ The following configuration will use both Payment Intents and the
89
+ payment request button API on the store payment page:
80
90
 
81
91
 
82
92
  ```ruby
@@ -120,8 +130,8 @@ payment method configured for Stripe via the local variable
120
130
  <%= render 'stripe_payment_request_button', cart_checkout_payment_method: Spree::PaymentMethod::StripeCreditCard.first %>
121
131
  ```
122
132
 
123
- Of course, rules stated in the paragraph above (remember to add the stripe country
124
- config value, for example) apply also for this payment method.
133
+ Of course, the rules listed in the Payment Intents section (adding the stripe
134
+ country config value, for example) apply also for this feature.
125
135
 
126
136
 
127
137
  Migrating from solidus_gateway
@@ -0,0 +1,88 @@
1
+ SolidusStripe.CartPageCheckout = function() {
2
+ SolidusStripe.Payment.call(this);
3
+
4
+ this.errorElement = $('#card-errors');
5
+ };
6
+
7
+ SolidusStripe.CartPageCheckout.prototype = Object.create(SolidusStripe.Payment.prototype);
8
+ Object.defineProperty(SolidusStripe.CartPageCheckout.prototype, 'constructor', {
9
+ value: SolidusStripe.CartPageCheckout,
10
+ enumerable: false,
11
+ writable: true
12
+ });
13
+
14
+ SolidusStripe.CartPageCheckout.prototype.init = function() {
15
+ this.setUpPaymentRequest({requestShipping: true});
16
+ };
17
+
18
+ SolidusStripe.CartPageCheckout.prototype.showError = function(error) {
19
+ this.errorElement.text(error).show();
20
+ };
21
+
22
+ SolidusStripe.CartPageCheckout.prototype.submitPayment = function(payment) {
23
+ var showError = this.showError.bind(this);
24
+
25
+ $.ajax({
26
+ url: $('[data-submit-url]').data('submit-url'),
27
+ headers: {
28
+ 'X-Spree-Order-Token': $('[data-order-token]').data('order-token')
29
+ },
30
+ type: 'PATCH',
31
+ contentType: 'application/json',
32
+ data: JSON.stringify(this.prTokenHandler(payment.paymentMethod)),
33
+ success: function() {
34
+ window.location = $('[data-complete-url]').data('complete-url');
35
+ },
36
+ error: function(xhr,status,error) {
37
+ showError(xhr.responseJSON.error);
38
+ }
39
+ });
40
+ };
41
+
42
+ SolidusStripe.CartPageCheckout.prototype.onPrPayment = function(result) {
43
+ var handleServerResponse = this.handleServerResponse.bind(this);
44
+
45
+ fetch('/stripe/update_order', {
46
+ method: 'POST',
47
+ headers: { 'Content-Type': 'application/json' },
48
+ body: JSON.stringify({
49
+ shipping_address: result.shippingAddress,
50
+ shipping_option: result.shippingOption,
51
+ email: result.payerEmail,
52
+ name: result.payerName,
53
+ authenticity_token: this.authToken
54
+ })
55
+ }).then(function(response) {
56
+ response.json().then(function(json) {
57
+ handleServerResponse(json, result);
58
+ })
59
+ });
60
+ };
61
+
62
+ SolidusStripe.CartPageCheckout.prototype.onPrButtonMounted = function(buttonId, success) {
63
+ var container = document.getElementById(buttonId).parentElement;
64
+
65
+ if (success) {
66
+ container.style.display = '';
67
+ } else {
68
+ container.style.display = 'none';
69
+ }
70
+ };
71
+
72
+ SolidusStripe.CartPageCheckout.prototype.prTokenHandler = function(token) {
73
+ return {
74
+ order: {
75
+ payments_attributes: [
76
+ {
77
+ payment_method_id: this.config.id,
78
+ source_attributes: {
79
+ gateway_payment_profile_id: token.id,
80
+ last_digits: token.card.last4,
81
+ month: token.card.exp_month,
82
+ year: token.card.exp_year
83
+ }
84
+ }
85
+ ]
86
+ }
87
+ }
88
+ };
@@ -0,0 +1,108 @@
1
+ SolidusStripe.Elements = function() {
2
+ SolidusStripe.Payment.call(this);
3
+
4
+ this.form = this.element.parents('form');
5
+ this.errorElement = this.form.find('#card-errors');
6
+ this.submitButton = this.form.find('input[type="submit"]');
7
+ };
8
+
9
+ SolidusStripe.Elements.prototype = Object.create(SolidusStripe.Payment.prototype);
10
+ Object.defineProperty(SolidusStripe.Elements.prototype, 'constructor', {
11
+ value: SolidusStripe.Elements,
12
+ enumerable: false,
13
+ writable: true
14
+ });
15
+
16
+ SolidusStripe.Elements.prototype.init = function() {
17
+ this.initElements();
18
+ };
19
+
20
+ SolidusStripe.Elements.prototype.initElements = function() {
21
+ var buildElements = function(elements) {
22
+ var style = {
23
+ base: {
24
+ color: 'black',
25
+ fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
26
+ fontSmoothing: 'antialiased',
27
+ fontSize: '14px',
28
+ '::placeholder': {
29
+ color: 'silver'
30
+ }
31
+ },
32
+ invalid: {
33
+ color: 'red',
34
+ iconColor: 'red'
35
+ }
36
+ };
37
+
38
+ elements.create('cardExpiry', {style: style}).mount('#card_expiry');
39
+ elements.create('cardCvc', {style: style}).mount('#card_cvc');
40
+
41
+ var cardNumber = elements.create('cardNumber', {style: style});
42
+ cardNumber.mount('#card_number');
43
+
44
+ return cardNumber;
45
+ };
46
+
47
+ this.cardNumber = buildElements(this.elements);
48
+
49
+ var cardChange = function(event) {
50
+ if (event.error) {
51
+ this.showError(event.error.message);
52
+ } else {
53
+ this.errorElement.hide().text('');
54
+ }
55
+ };
56
+ this.cardNumber.addEventListener('change', cardChange.bind(this));
57
+ this.form.bind('submit', this.onFormSubmit.bind(this));
58
+ };
59
+
60
+ SolidusStripe.Elements.prototype.showError = function(error) {
61
+ var message = error.message || error;
62
+
63
+ this.errorElement.text(message).show();
64
+ this.submitButton.removeAttr('disabled').removeClass('disabled');
65
+ };
66
+
67
+ SolidusStripe.Elements.prototype.onFormSubmit = function(event) {
68
+ if (this.element.is(':visible')) {
69
+ event.preventDefault();
70
+
71
+ var onTokenCreate = function(result) {
72
+ if (result.error) {
73
+ this.showError(result.error.message);
74
+ } else {
75
+ this.elementsTokenHandler(result.token);
76
+ this.form[0].submit();
77
+ }
78
+ };
79
+
80
+ this.stripe.createToken(this.cardNumber).then(onTokenCreate.bind(this));
81
+ }
82
+ };
83
+
84
+ SolidusStripe.Elements.prototype.elementsTokenHandler = function(token) {
85
+ var mapCC = function(ccType) {
86
+ if (ccType === 'MasterCard') {
87
+ return 'mastercard';
88
+ } else if (ccType === 'Visa') {
89
+ return 'visa';
90
+ } else if (ccType === 'American Express') {
91
+ return 'amex';
92
+ } else if (ccType === 'Discover') {
93
+ return 'discover';
94
+ } else if (ccType === 'Diners Club') {
95
+ return 'dinersclub';
96
+ } else if (ccType === 'JCB') {
97
+ return 'jcb';
98
+ }
99
+ };
100
+
101
+ var baseSelector = `<input type='hidden' class='stripeToken' name='payment_source[${this.config.id}]`;
102
+
103
+ this.element.append(`${baseSelector}[gateway_payment_profile_id]' value='${token.id}'/>`);
104
+ this.element.append(`${baseSelector}[last_digits]' value='${token.card.last4}'/>`);
105
+ this.element.append(`${baseSelector}[month]' value='${token.card.exp_month}'/>`);
106
+ this.element.append(`${baseSelector}[year]' value='${token.card.exp_year}'/>`);
107
+ this.form.find('input#cc_type').val(mapCC(token.card.brand || token.card.type));
108
+ };
@@ -0,0 +1,82 @@
1
+ SolidusStripe.PaymentIntents = function() {
2
+ SolidusStripe.Elements.call(this);
3
+ };
4
+
5
+ SolidusStripe.PaymentIntents.prototype = Object.create(SolidusStripe.Elements.prototype);
6
+ Object.defineProperty(SolidusStripe.PaymentIntents.prototype, 'constructor', {
7
+ value: SolidusStripe.PaymentIntents,
8
+ enumerable: false,
9
+ writable: true
10
+ });
11
+
12
+ SolidusStripe.PaymentIntents.prototype.init = function() {
13
+ this.setUpPaymentRequest();
14
+ this.initElements();
15
+ };
16
+
17
+ SolidusStripe.PaymentIntents.prototype.onPrPayment = function(payment) {
18
+ if (payment.error) {
19
+ this.showError(payment.error.message);
20
+ } else {
21
+ var that = this;
22
+
23
+ this.elementsTokenHandler(payment.paymentMethod);
24
+ fetch('/stripe/confirm_payment', {
25
+ method: 'POST',
26
+ headers: {
27
+ 'Content-Type': 'application/json'
28
+ },
29
+ body: JSON.stringify({
30
+ spree_payment_method_id: this.config.id,
31
+ stripe_payment_method_id: payment.paymentMethod.id,
32
+ authenticity_token: this.authToken
33
+ })
34
+ }).then(function(response) {
35
+ response.json().then(function(json) {
36
+ that.handleServerResponse(json, payment);
37
+ })
38
+ });
39
+ }
40
+ };
41
+
42
+ SolidusStripe.PaymentIntents.prototype.onFormSubmit = function(event) {
43
+ if (this.element.is(':visible')) {
44
+ event.preventDefault();
45
+
46
+ this.errorElement.text('').hide();
47
+
48
+ this.stripe.createPaymentMethod(
49
+ 'card',
50
+ this.cardNumber
51
+ ).then(this.onIntentsPayment.bind(this));
52
+ }
53
+ };
54
+
55
+ SolidusStripe.PaymentIntents.prototype.submitPayment = function(_payment) {
56
+ this.form.unbind('submit').submit();
57
+ };
58
+
59
+ SolidusStripe.PaymentIntents.prototype.onIntentsPayment = function(payment) {
60
+ if (payment.error) {
61
+ this.showError(payment.error.message);
62
+ } else {
63
+ var that = this;
64
+
65
+ this.elementsTokenHandler(payment.paymentMethod);
66
+ fetch('/stripe/confirm_intents', {
67
+ method: 'POST',
68
+ headers: {
69
+ 'Content-Type': 'application/json'
70
+ },
71
+ body: JSON.stringify({
72
+ spree_payment_method_id: this.config.id,
73
+ stripe_payment_method_id: payment.paymentMethod.id,
74
+ authenticity_token: this.authToken
75
+ })
76
+ }).then(function(response) {
77
+ response.json().then(function(json) {
78
+ that.handleServerResponse(json, payment);
79
+ })
80
+ });
81
+ }
82
+ };
@@ -0,0 +1,122 @@
1
+ // Shared code between Payment Intents and Payment Request Button on cart page
2
+
3
+ (function() {
4
+ var PaymentRequestButtonShared;
5
+
6
+ PaymentRequestButtonShared = {
7
+ authToken: $('meta[name="csrf-token"]').attr('content'),
8
+
9
+ setUpPaymentRequest: function(opts) {
10
+ var opts = opts || {};
11
+ var config = this.config.payment_request;
12
+
13
+ if (config) {
14
+ config.requestShipping = opts.requestShipping || false;
15
+
16
+ var paymentRequest = this.stripe.paymentRequest({
17
+ country: config.country,
18
+ currency: config.currency,
19
+ total: {
20
+ label: config.label,
21
+ amount: config.amount
22
+ },
23
+ requestPayerName: true,
24
+ requestPayerEmail: true,
25
+ requestShipping: config.requestShipping,
26
+ shippingOptions: []
27
+ });
28
+
29
+ var prButton = this.elements.create('paymentRequestButton', {
30
+ paymentRequest: paymentRequest
31
+ });
32
+
33
+ var onButtonMount = function(result) {
34
+ var id = 'payment-request-button';
35
+
36
+ if (result) {
37
+ prButton.mount('#' + id);
38
+ } else {
39
+ document.getElementById(id).style.display = 'none';
40
+ }
41
+ if (typeof this.onPrButtonMounted === 'function') {
42
+ this.onPrButtonMounted(id, result);
43
+ }
44
+ }
45
+ paymentRequest.canMakePayment().then(onButtonMount.bind(this));
46
+
47
+ var onPrPaymentMethod = function(result) {
48
+ this.errorElement.text('').hide();
49
+ this.onPrPayment(result);
50
+ };
51
+ paymentRequest.on('paymentmethod', onPrPaymentMethod.bind(this));
52
+
53
+ onShippingAddressChange = function(ev) {
54
+ var showError = this.showError.bind(this);
55
+
56
+ fetch('/stripe/shipping_rates', {
57
+ method: 'POST',
58
+ headers: { 'Content-Type': 'application/json' },
59
+ body: JSON.stringify({
60
+ authenticity_token: this.authToken,
61
+ shipping_address: ev.shippingAddress
62
+ })
63
+ }).then(function(response) {
64
+ return response.json();
65
+ }).then(function(result) {
66
+ if (result.error) {
67
+ showError(result.error);
68
+ return false;
69
+ } else {
70
+ ev.updateWith({
71
+ status: 'success',
72
+ shippingOptions: result.shipping_rates
73
+ });
74
+ }
75
+ });
76
+ };
77
+ paymentRequest.on('shippingaddresschange', onShippingAddressChange.bind(this));
78
+ }
79
+ },
80
+
81
+ handleServerResponse: function(response, payment) {
82
+ if (response.error) {
83
+ this.showError(response.error);
84
+ this.completePaymentRequest(payment, 'fail');
85
+ } else if (response.requires_action) {
86
+ this.stripe.handleCardAction(
87
+ response.stripe_payment_intent_client_secret
88
+ ).then(this.onIntentsClientSecret.bind(this));
89
+ } else {
90
+ this.completePaymentRequest(payment, 'success');
91
+ this.submitPayment(payment);
92
+ }
93
+ },
94
+
95
+ onIntentsClientSecret: function(result) {
96
+ if (result.error) {
97
+ this.showError(result.error);
98
+ } else {
99
+ fetch('/stripe/confirm_intents', {
100
+ method: 'POST',
101
+ headers: { 'Content-Type': 'application/json' },
102
+ body: JSON.stringify({
103
+ spree_payment_method_id: this.config.id,
104
+ stripe_payment_intent_id: result.paymentIntent.id,
105
+ authenticity_token: this.authToken
106
+ })
107
+ }).then(function(confirmResult) {
108
+ return confirmResult.json();
109
+ }).then(this.handleServerResponse.bind(this));
110
+ }
111
+ },
112
+
113
+ completePaymentRequest: function(payment, state) {
114
+ if (payment && typeof payment.complete === 'function') {
115
+ payment.complete(state);
116
+ }
117
+ }
118
+ };
119
+
120
+ Object.assign(SolidusStripe.PaymentIntents.prototype, PaymentRequestButtonShared);
121
+ Object.assign(SolidusStripe.CartPageCheckout.prototype, PaymentRequestButtonShared);
122
+ })()
@@ -0,0 +1,10 @@
1
+ window.SolidusStripe = window.SolidusStripe || {};
2
+
3
+ SolidusStripe.Payment = function() {
4
+ this.config = $('[data-stripe-config]').data('stripe-config');
5
+ this.element = $('#payment_method_' + this.config.id);
6
+ this.authToken = $('meta[name="csrf-token"]').attr('content');
7
+
8
+ this.stripe = Stripe(this.config.publishable_key);
9
+ this.elements = this.stripe.elements({locale: 'en'});
10
+ };
@@ -0,0 +1,5 @@
1
+ //= require ./stripe-payments/stripe-payment
2
+ //= require ./stripe-payments/stripe-elements
3
+ //= require ./stripe-payments/stripe-payment-intents
4
+ //= require ./stripe-payments/stripe-cart-page-checkout
5
+ //= require ./stripe-payments/stripe-payment-request-button-shared
@@ -21,7 +21,7 @@ module SolidusStripe
21
21
 
22
22
  if SolidusSupport.frontend_available?
23
23
  paths["app/views"] << "lib/views/frontend"
24
- config.assets.precompile += ['solidus_stripe/stripe-init.js']
24
+ config.assets.precompile += ['spree/stripe-v3-payments.js']
25
25
  end
26
26
 
27
27
  if SolidusSupport.api_available?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusStripe
4
- VERSION = "2.0.0"
4
+ VERSION = "2.1.0"
5
5
  end
@@ -1,5 +1,9 @@
1
1
  <%= render 'spree/checkout/payment/v3/form_elements', payment_method: payment_method %>
2
2
 
3
- <%= javascript_include_tag "solidus_stripe/stripe-init.js" %>
3
+ <%= javascript_include_tag 'spree/stripe-v3-payments' %>
4
4
 
5
- <%= render "spree/checkout/payment/v3/intents_js" %>
5
+ <script>
6
+ $(function() {
7
+ new SolidusStripe.PaymentIntents().init();
8
+ });
9
+ </script>
@@ -1,5 +1,9 @@
1
1
  <%= render 'spree/checkout/payment/v3/form_elements', payment_method: payment_method %>
2
2
 
3
- <%= javascript_include_tag "solidus_stripe/stripe-init.js" %>
3
+ <%= javascript_include_tag 'spree/stripe-v3-payments' %>
4
4
 
5
- <%= render "spree/checkout/payment/v3/elements_js" %>
5
+ <script>
6
+ $(function() {
7
+ new SolidusStripe.Elements().init();
8
+ });
9
+ </script>
@@ -13,80 +13,11 @@
13
13
  </div>
14
14
 
15
15
  <script src="https://js.stripe.com/v3/"></script>
16
- <%= javascript_include_tag "solidus_stripe/stripe-init" %>
17
16
 
17
+ <%= javascript_include_tag 'spree/stripe-v3-payments' %>
18
18
  <script>
19
- var paymentRequestConfig = SolidusStripe.paymentMethod.config.payment_request;
20
- var errorElement = $('#card-errors');
21
-
22
- if (typeof paymentRequestConfig !== 'undefined') {
23
- paymentRequestConfig.requestShipping = true;
24
-
25
- var onPrButtonMounted = function(buttonId, success) {
26
- var container = document.getElementById('stripe-payment-request');
27
-
28
- if (success) {
29
- container.style.display = '';
30
- } else {
31
- container.style.display = 'none';
32
- }
33
- };
34
-
35
- var paymentRequest = setUpPaymentRequest(paymentRequestConfig, onPrButtonMounted);
36
-
37
- function handlePayment(result) {
38
- fetch('/stripe/update_order', {
39
- method: 'POST',
40
- headers: { 'Content-Type': 'application/json' },
41
- body: JSON.stringify({
42
- shipping_address: result.shippingAddress,
43
- shipping_option: result.shippingOption,
44
- email: result.payerEmail,
45
- name: result.payerName,
46
- authenticity_token: authToken
47
- })
48
- }).then(function(response) {
49
- response.json().then(function(json) {
50
- handleServerResponse(json, result);
51
- })
52
- });
53
- };
54
-
55
- function stripeTokenHandler(token) {
56
- return {
57
- order: {
58
- payments_attributes: [
59
- {
60
- payment_method_id: SolidusStripe.paymentMethod.config.id,
61
- source_attributes: {
62
- gateway_payment_profile_id: token.id,
63
- last_digits: token.card.last4,
64
- month: token.card.exp_month,
65
- year: token.card.exp_year
66
- }
67
- }
68
- ]
69
- }
70
- }
71
- };
72
-
73
- function submitPayment(payment) {
74
- $.ajax({
75
- url : $('[data-submit-url]').data('submit-url'),
76
- headers: {
77
- 'X-Spree-Order-Token': $('[data-order-token]').data('order-token')
78
- },
79
- type : 'PATCH',
80
- contentType: 'application/json',
81
- data : JSON.stringify(stripeTokenHandler(payment.paymentMethod)),
82
- success: function() {
83
- window.location = $('[data-complete-url]').data('complete-url');
84
- },
85
- error: function(xhr,status,error) {
86
- showError(xhr.responseJSON.error);
87
- }
88
- });
89
- };
90
- }
19
+ $(function() {
20
+ new SolidusStripe.CartPageCheckout().init()
21
+ });
91
22
  </script>
92
23
  <% end %>
@@ -41,8 +41,7 @@ RSpec.describe "Stripe checkout", type: :feature do
41
41
  expect(page).to have_current_path("/checkout/address")
42
42
 
43
43
  within("#billing") do
44
- fill_in "First Name", with: "Han"
45
- fill_in "Last Name", with: "Solo"
44
+ fill_in_name
46
45
  fill_in "Street Address", with: "YT-1300"
47
46
  fill_in "City", with: "Mos Eisley"
48
47
  select "United States of America", from: "Country"
@@ -100,8 +99,7 @@ RSpec.describe "Stripe checkout", type: :feature do
100
99
  expect(page).to have_current_path("/checkout/address")
101
100
 
102
101
  within("#billing") do
103
- fill_in "First Name", with: "Han"
104
- fill_in "Last Name", with: "Solo"
102
+ fill_in_name
105
103
  fill_in "Street Address", with: "YT-1300"
106
104
  fill_in "City", with: "Mos Eisley"
107
105
  select "United States of America", from: "Country"
@@ -264,8 +262,7 @@ RSpec.describe "Stripe checkout", type: :feature do
264
262
  expect(page).to have_current_path("/checkout/address")
265
263
 
266
264
  within("#billing") do
267
- fill_in "First Name", with: "Han"
268
- fill_in "Last Name", with: "Solo"
265
+ fill_in_name
269
266
  fill_in "Street Address", with: "YT-1300"
270
267
  fill_in "City", with: "Mos Eisley"
271
268
  select "United States of America", from: "Country"
@@ -400,8 +397,7 @@ RSpec.describe "Stripe checkout", type: :feature do
400
397
  expect(page).to have_current_path("/checkout/address")
401
398
 
402
399
  within("#billing") do
403
- fill_in "First Name", with: "Han"
404
- fill_in "Last Name", with: "Solo"
400
+ fill_in_name
405
401
  fill_in "Street Address", with: "YT-1300"
406
402
  fill_in "City", with: "Mos Eisley"
407
403
  select "United States of America", from: "Country"
data/spec/spec_helper.rb CHANGED
@@ -19,4 +19,5 @@ RSpec.configure do |config|
19
19
  config.infer_spec_type_from_file_location!
20
20
  FactoryBot.find_definitions
21
21
  config.use_transactional_fixtures = false
22
+ config.include SolidusAddressNameHelper, type: :feature
22
23
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Since https://github.com/solidusio/solidus/pull/3524 was merged,
4
+ # we need to verify if we're using the single "Name" field or the
5
+ # previous first/last name combination.
6
+ module SolidusAddressNameHelper
7
+ def fill_in_name
8
+ if Spree::Config.preferences[:use_combined_first_and_last_name_in_address]
9
+ fill_in "Name", with: "Han Solo"
10
+ else
11
+ fill_in "First Name", with: "Han"
12
+ fill_in "Last Name", with: "Solo"
13
+ end
14
+ end
15
+ 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: 2.0.0
4
+ version: 2.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-03-03 00:00:00.000000000 Z
11
+ date: 2020-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: solidus_core
@@ -91,8 +91,12 @@ files:
91
91
  - LICENSE.md
92
92
  - README.md
93
93
  - Rakefile
94
- - app/assets/javascripts/solidus_stripe/stripe-init.js
95
- - app/assets/javascripts/solidus_stripe/stripe-init/base.js
94
+ - app/assets/javascripts/spree/stripe-payments/stripe-cart-page-checkout.js
95
+ - app/assets/javascripts/spree/stripe-payments/stripe-elements.js
96
+ - app/assets/javascripts/spree/stripe-payments/stripe-payment-intents.js
97
+ - app/assets/javascripts/spree/stripe-payments/stripe-payment-request-button-shared.js
98
+ - app/assets/javascripts/spree/stripe-payments/stripe-payment.js
99
+ - app/assets/javascripts/spree/stripe-v3-payments.js
96
100
  - app/controllers/solidus_stripe/intents_controller.rb
97
101
  - app/controllers/solidus_stripe/payment_request_controller.rb
98
102
  - app/controllers/spree/stripe_controller.rb
@@ -119,10 +123,8 @@ files:
119
123
  - lib/views/frontend/spree/checkout/existing_payment/_stripe.html.erb
120
124
  - lib/views/frontend/spree/checkout/payment/_stripe.html.erb
121
125
  - lib/views/frontend/spree/checkout/payment/v2/_javascript.html.erb
122
- - lib/views/frontend/spree/checkout/payment/v3/_elements_js.html.erb
123
126
  - lib/views/frontend/spree/checkout/payment/v3/_form_elements.html.erb
124
127
  - lib/views/frontend/spree/checkout/payment/v3/_intents.html.erb
125
- - lib/views/frontend/spree/checkout/payment/v3/_intents_js.html.erb
126
128
  - lib/views/frontend/spree/checkout/payment/v3/_stripe.html.erb
127
129
  - lib/views/frontend/spree/orders/_stripe_payment_request_button.html.erb
128
130
  - solidus_stripe.gemspec
@@ -132,6 +134,7 @@ files:
132
134
  - spec/models/solidus_stripe/shipping_rates_service_spec.rb
133
135
  - spec/models/spree/payment_method/stripe_credit_card_spec.rb
134
136
  - spec/spec_helper.rb
137
+ - spec/support/solidus_address_helper.rb
135
138
  homepage: https://solidus.io
136
139
  licenses:
137
140
  - BSD-3
@@ -165,3 +168,4 @@ test_files:
165
168
  - spec/models/solidus_stripe/shipping_rates_service_spec.rb
166
169
  - spec/models/spree/payment_method/stripe_credit_card_spec.rb
167
170
  - spec/spec_helper.rb
171
+ - spec/support/solidus_address_helper.rb
@@ -1 +0,0 @@
1
- //= require ./stripe-init/base
@@ -1,180 +0,0 @@
1
- window.SolidusStripe = window.SolidusStripe || {};
2
-
3
- SolidusStripe.paymentMethod = {
4
- config: $('[data-stripe-config').data('stripe-config'),
5
- requestShipping: false
6
- }
7
-
8
- var authToken = $('meta[name="csrf-token"]').attr('content');
9
-
10
- var stripe = Stripe(SolidusStripe.paymentMethod.config.publishable_key)
11
- var elements = stripe.elements({locale: 'en'});
12
-
13
- var element = $('#payment_method_' + SolidusStripe.paymentMethod.config.id);
14
- var form = element.parents('form');
15
- var errorElement = form.find('#card-errors');
16
- var submitButton = form.find('input[type="submit"]');
17
-
18
- function stripeTokenHandler(token) {
19
- var baseSelector = `<input type='hidden' class='stripeToken' name='payment_source[${SolidusStripe.paymentMethod.config.id}]`;
20
-
21
- element.append(`${baseSelector}[gateway_payment_profile_id]' value='${token.id}'/>`);
22
- element.append(`${baseSelector}[last_digits]' value='${token.card.last4}'/>`);
23
- element.append(`${baseSelector}[month]' value='${token.card.exp_month}'/>`);
24
- element.append(`${baseSelector}[year]' value='${token.card.exp_year}'/>`);
25
- form.find('input#cc_type').val(mapCC(token.card.brand || token.card.type));
26
- };
27
-
28
- function initElements() {
29
- var style = {
30
- base: {
31
- color: 'black',
32
- fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
33
- fontSmoothing: 'antialiased',
34
- fontSize: '14px',
35
- '::placeholder': {
36
- color: 'silver'
37
- }
38
- },
39
- invalid: {
40
- color: 'red',
41
- iconColor: 'red'
42
- }
43
- };
44
-
45
- elements.create('cardExpiry', {style: style}).mount('#card_expiry');
46
- elements.create('cardCvc', {style: style}).mount('#card_cvc');
47
-
48
- var cardNumber = elements.create('cardNumber', {style: style});
49
- cardNumber.mount('#card_number');
50
-
51
- return cardNumber;
52
- }
53
-
54
- function setUpPaymentRequest(config, onPrButtonMounted) {
55
- if (typeof config !== 'undefined') {
56
- var paymentRequest = stripe.paymentRequest({
57
- country: config.country,
58
- currency: config.currency,
59
- total: {
60
- label: config.label,
61
- amount: config.amount
62
- },
63
- requestPayerName: true,
64
- requestPayerEmail: true,
65
- requestShipping: config.requestShipping,
66
- shippingOptions: [
67
- ]
68
- });
69
-
70
- var prButton = elements.create('paymentRequestButton', {
71
- paymentRequest: paymentRequest
72
- });
73
-
74
- paymentRequest.canMakePayment().then(function(result) {
75
- var id = 'payment-request-button';
76
-
77
- if (result) {
78
- prButton.mount('#' + id);
79
- } else {
80
- document.getElementById(id).style.display = 'none';
81
- }
82
- if (typeof onPrButtonMounted === 'function') {
83
- onPrButtonMounted(id, result);
84
- }
85
- });
86
-
87
- paymentRequest.on('paymentmethod', function(result) {
88
- errorElement.text('').hide();
89
- handlePayment(result);
90
- });
91
-
92
- paymentRequest.on('shippingaddresschange', function(ev) {
93
- fetch('/stripe/shipping_rates', {
94
- method: 'POST',
95
- headers: { 'Content-Type': 'application/json' },
96
- body: JSON.stringify({
97
- authenticity_token: authToken,
98
- shipping_address: ev.shippingAddress
99
- })
100
- }).then(function(response) {
101
- return response.json();
102
- }).then(function(result) {
103
- if (result.error) {
104
- showError(result.error);
105
- return false;
106
- } else {
107
- ev.updateWith({
108
- status: 'success',
109
- shippingOptions: result.shipping_rates
110
- });
111
- }
112
- });
113
- });
114
-
115
- return paymentRequest;
116
- }
117
- };
118
-
119
- function handleServerResponse(response, payment) {
120
- if (response.error) {
121
- showError(response.error);
122
- completePaymentRequest(payment, 'fail');
123
- } else if (response.requires_action) {
124
- stripe.handleCardAction(
125
- response.stripe_payment_intent_client_secret
126
- ).then(function(result) {
127
- if (result.error) {
128
- showError(result.error.message);
129
- } else {
130
- fetch('/stripe/confirm_intents', {
131
- method: 'POST',
132
- headers: { 'Content-Type': 'application/json' },
133
- body: JSON.stringify({
134
- spree_payment_method_id: SolidusStripe.paymentMethod.config.id,
135
- stripe_payment_intent_id: result.paymentIntent.id,
136
- authenticity_token: authToken
137
- })
138
- }).then(function(confirmResult) {
139
- return confirmResult.json();
140
- }).then(handleServerResponse);
141
- }
142
- });
143
- } else {
144
- completePaymentRequest(payment, 'success');
145
- submitPayment(payment);
146
- }
147
- }
148
-
149
- function completePaymentRequest(payment, state) {
150
- if (payment && typeof payment.complete === 'function') {
151
- payment.complete(state);
152
- }
153
- }
154
-
155
- function showError(error) {
156
- errorElement.text(error).show();
157
-
158
- if (submitButton.length) {
159
- setTimeout(function() {
160
- $.rails.enableElement(submitButton[0]);
161
- submitButton.removeAttr('disabled').removeClass('disabled');
162
- }, 100);
163
- }
164
- };
165
-
166
- function mapCC(ccType) {
167
- if (ccType === 'MasterCard') {
168
- return 'mastercard';
169
- } else if (ccType === 'Visa') {
170
- return 'visa';
171
- } else if (ccType === 'American Express') {
172
- return 'amex';
173
- } else if (ccType === 'Discover') {
174
- return 'discover';
175
- } else if (ccType === 'Diners Club') {
176
- return 'dinersclub';
177
- } else if (ccType === 'JCB') {
178
- return 'jcb';
179
- }
180
- };
@@ -1,28 +0,0 @@
1
- <script>
2
- // Stripe V3 elements specific JS code
3
-
4
- var cardNumber = initElements();
5
-
6
- cardNumber.addEventListener('change', function(event) {
7
- if (event.error) {
8
- showError(event.error.message);
9
- } else {
10
- errorElement.hide().text('');
11
- }
12
- });
13
-
14
- form.bind('submit', function(event) {
15
- if (element.is(':visible')) {
16
- event.preventDefault();
17
-
18
- stripe.createToken(cardNumber).then(function(result) {
19
- if (result.error) {
20
- showError(result.error.message);
21
- } else {
22
- stripeTokenHandler(result.token);
23
- form[0].submit();
24
- }
25
- });
26
- }
27
- });
28
- </script>
@@ -1,48 +0,0 @@
1
- <script>
2
- // Stripe Intents JS code
3
-
4
- var cardNumber = initElements();
5
- var paymentRequest = setUpPaymentRequest(SolidusStripe.paymentMethod.config.payment_request);
6
-
7
- form.bind('submit', function(event) {
8
- if (element.is(':visible')) {
9
- event.preventDefault();
10
-
11
- errorElement.text('').hide();
12
-
13
- stripe.createPaymentMethod(
14
- 'card',
15
- cardNumber
16
- ).then(function(result) {
17
- handlePayment(result);
18
- });
19
- }
20
- });
21
-
22
- function handlePayment(payment) {
23
- if (payment.error) {
24
- showError(payment.error.message);
25
- } else {
26
- stripeTokenHandler(payment.paymentMethod);
27
- fetch('/stripe/confirm_intents', {
28
- method: 'POST',
29
- headers: {
30
- 'Content-Type': 'application/json'
31
- },
32
- body: JSON.stringify({
33
- spree_payment_method_id: SolidusStripe.paymentMethod.config.id,
34
- stripe_payment_method_id: payment.paymentMethod.id,
35
- authenticity_token: authToken
36
- })
37
- }).then(function(response) {
38
- response.json().then(function(json) {
39
- handleServerResponse(json, payment);
40
- })
41
- });
42
- }
43
- };
44
-
45
- function submitPayment(_payment) {
46
- form.unbind('submit').submit();
47
- }
48
- </script>