solidus_six_saferpay 0.1.3 → 0.2.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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +35 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +17 -0
  5. data/.gitignore +18 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +2 -0
  8. data/.travis.yml +12 -0
  9. data/Gemfile +33 -0
  10. data/LICENSE +26 -0
  11. data/README.md +36 -20
  12. data/Rakefile +4 -54
  13. data/app/assets/config/solidus_six_saferpay_manifest.js +1 -0
  14. data/app/assets/images/solidus_six_saferpay/.keep +0 -0
  15. data/app/assets/javascripts/spree/backend/solidus_six_saferpay.js +2 -0
  16. data/app/assets/javascripts/spree/frontend/solidus_six_saferpay.js +2 -0
  17. data/app/assets/stylesheets/solidus_six_saferpay/loading_animation.scss +0 -27
  18. data/app/assets/stylesheets/solidus_six_saferpay/payments.scss +4 -1
  19. data/app/assets/stylesheets/spree/backend/solidus_six_saferpay.css +4 -0
  20. data/app/assets/stylesheets/spree/frontend/solidus_six_saferpay.css +4 -0
  21. data/app/controllers/spree/solidus_six_saferpay/checkout_controller.rb +56 -10
  22. data/app/services/spree/solidus_six_saferpay/inquire_payment.rb +1 -0
  23. data/app/views/spree/checkout/payment/_saferpay_payment.html.erb +1 -1
  24. data/app/views/spree/six_saferpay_payments/_six_saferpay_payment.html.erb +2 -2
  25. data/bin/console +17 -0
  26. data/bin/rails +18 -0
  27. data/bin/rake +7 -0
  28. data/bin/setup +8 -0
  29. data/config/initializers/assets.rb +3 -0
  30. data/config/locales/de.yml +1 -1
  31. data/config/locales/en.yml +1 -1
  32. data/config/locales/fr.yml +1 -1
  33. data/config/routes.rb +6 -6
  34. data/lib/generators/solidus_six_saferpay/install/install_generator.rb +15 -3
  35. data/lib/solidus_six_saferpay.rb +6 -3
  36. data/lib/solidus_six_saferpay/configuration.rb +4 -7
  37. data/lib/solidus_six_saferpay/engine.rb +19 -10
  38. data/lib/solidus_six_saferpay/gateway.rb +5 -4
  39. data/lib/solidus_six_saferpay/payment_page_gateway.rb +8 -9
  40. data/lib/solidus_six_saferpay/transaction_gateway.rb +8 -9
  41. data/lib/solidus_six_saferpay/version.rb +3 -1
  42. data/solidus_six_saferpay.gemspec +42 -0
  43. data/spec/controllers/spree/solidus_six_saferpay/checkout_controller_spec.rb +41 -0
  44. data/spec/controllers/spree/solidus_six_saferpay/payment_page/checkout_controller_spec.rb +206 -0
  45. data/spec/controllers/spree/solidus_six_saferpay/transaction/checkout_controller_spec.rb +229 -0
  46. data/spec/factories/payment_methods.rb +23 -0
  47. data/spec/factories/payments.rb +11 -0
  48. data/spec/factories/spree/six_saferpay_payments.rb +118 -0
  49. data/spec/models/spree/six_saferpay_payment_spec.rb +203 -0
  50. data/spec/rails_helper.rb +73 -0
  51. data/spec/services/spree/solidus_six_saferpay/assert_payment_page_spec.rb +148 -0
  52. data/spec/services/spree/solidus_six_saferpay/authorize_payment_spec.rb +39 -0
  53. data/spec/services/spree/solidus_six_saferpay/authorize_transaction_spec.rb +148 -0
  54. data/spec/services/spree/solidus_six_saferpay/initialize_payment_page_spec.rb +83 -0
  55. data/spec/services/spree/solidus_six_saferpay/initialize_payment_spec.rb +40 -0
  56. data/spec/services/spree/solidus_six_saferpay/initialize_transaction_spec.rb +85 -0
  57. data/spec/services/spree/solidus_six_saferpay/inquire_payment_page_payment_spec.rb +116 -0
  58. data/spec/services/spree/solidus_six_saferpay/inquire_payment_spec.rb +39 -0
  59. data/spec/services/spree/solidus_six_saferpay/inquire_transaction_payment_spec.rb +117 -0
  60. data/spec/services/spree/solidus_six_saferpay/payment_validator_spec.rb +100 -0
  61. data/spec/services/spree/solidus_six_saferpay/process_authorized_payment_spec.rb +39 -0
  62. data/spec/services/spree/solidus_six_saferpay/process_payment_page_payment_spec.rb +225 -0
  63. data/spec/services/spree/solidus_six_saferpay/process_transaction_payment_spec.rb +219 -0
  64. data/spec/solidus_six_saferpay/configuration_spec.rb +15 -0
  65. data/spec/solidus_six_saferpay/error_handler_spec.rb +65 -0
  66. data/spec/solidus_six_saferpay/gateway_response_spec.rb +70 -0
  67. data/spec/solidus_six_saferpay/gateway_spec.rb +365 -0
  68. data/spec/solidus_six_saferpay/payment_page_gateway_spec.rb +392 -0
  69. data/spec/solidus_six_saferpay/transaction_gateway_spec.rb +390 -0
  70. data/spec/spec_helper.rb +21 -0
  71. data/spec/support/route_access.rb +6 -0
  72. data/spec/support/uses_payment_page_gateway.rb +29 -0
  73. data/spec/support/uses_transaction_gateway.rb +28 -0
  74. metadata +240 -99
@@ -0,0 +1,73 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ require 'spec_helper'
3
+ ENV['RAILS_ENV'] ||= 'test'
4
+ require File.expand_path('../dummy/config/environment', __FILE__)
5
+ # Prevent database truncation if the environment is production
6
+ abort("The Rails environment is running in production mode!") if Rails.env.production?
7
+ require 'rspec/rails'
8
+ require 'rails-controller-testing'
9
+ Rails::Controller::Testing.install
10
+ # Add additional requires below this line. Rails is not loaded until this point!
11
+
12
+ # require 'active_support/core_ext/string/deep_symbolize_keys'
13
+
14
+ require 'shoulda/matchers'
15
+
16
+ # Requires supporting ruby files with custom matchers and macros, etc, in
17
+ # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
18
+ # run as spec files by default. This means that files in spec/support that end
19
+ # in _spec.rb will both be required and run as specs, causing the specs to be
20
+ # run twice. It is recommended that you do not name files matching this glob to
21
+ # end with _spec.rb. You can configure this pattern with the --pattern
22
+ # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
23
+ #
24
+ # The following line is provided for convenience purposes. It has the downside
25
+ # of increasing the boot-up time by auto-requiring all files in the support
26
+ # directory. Alternatively, in the individual `*_spec.rb` files, manually
27
+ # require only the support files necessary.
28
+ #
29
+ Dir[SolidusSixSaferpay::Engine.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
30
+
31
+
32
+ # Set route host
33
+ Spree::Core::Engine.routes.default_url_options = {
34
+ host: 'shop.localhost:3000'
35
+ }
36
+
37
+ RSpec.configure do |config|
38
+ Shoulda::Matchers.configure do |c|
39
+ c.integrate do |with|
40
+ with.test_framework :rspec
41
+ with.library :rails
42
+ end
43
+
44
+ # include url_helpers in specs
45
+ include Spree::Core::Engine.routes.url_helpers
46
+ end
47
+
48
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
49
+ # examples within a transaction, remove the following line or assign false
50
+ # instead of true.
51
+ config.use_transactional_fixtures = true
52
+
53
+ # RSpec Rails can automatically mix in different behaviours to your tests
54
+ # based on their file location, for example enabling you to call `get` and
55
+ # `post` in specs under `spec/controllers`.
56
+ #
57
+ # You can disable this behaviour by removing the line below, and instead
58
+ # explicitly tag your specs with their type, e.g.:
59
+ #
60
+ # RSpec.describe UsersController, :type => :controller do
61
+ # # ...
62
+ # end
63
+ #
64
+ # The different available types are documented in the features, such as in
65
+ # https://relishapp.com/rspec/rspec-rails/docs
66
+ config.infer_spec_type_from_file_location!
67
+
68
+ # Filter lines from Rails gems in backtraces.
69
+ config.filter_rails_from_backtrace!
70
+ # arbitrary gems may also be filtered via:
71
+ # config.filter_gems_from_backtrace("gem name")
72
+ end
73
+
@@ -0,0 +1,148 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe AssertPaymentPage do
6
+
7
+ let(:payment) { create(:six_saferpay_payment) }
8
+
9
+ subject { described_class.new(payment) }
10
+
11
+
12
+ describe '#gateway' do
13
+ it_behaves_like "it uses the payment page gateway"
14
+ end
15
+
16
+ describe '#call' do
17
+ let(:transaction_status) { "AUTHORIZED" }
18
+ let(:transaction_id) { "723n4MAjMdhjSAhAKEUdA8jtl9jb" }
19
+ let(:transaction_date) { "2015-01-30T12:45:22.258+01:00" }
20
+ let(:amount_value) { "100" }
21
+ let(:amount_currency) { "USD" }
22
+ let(:brand_name) { 'PaymentBrand' }
23
+ let(:display_text) { "xxxx xxxx xxxx 1234" }
24
+ let(:six_transaction_reference) { "0:0:3:723n4MAjMdhjSAhAKEUdA8jtl9jb" }
25
+
26
+ let(:payment_means) do
27
+ SixSaferpay::ResponsePaymentMeans.new(
28
+ brand: SixSaferpay::Brand.new(name: brand_name),
29
+ display_text: display_text
30
+ )
31
+ end
32
+
33
+ # https://saferpay.github.io/jsonapi/#Payment_v1_PaymentPage_Initialize
34
+ let(:api_response) do
35
+ SixSaferpay::SixPaymentPage::AssertResponse.new(
36
+ response_header: SixSaferpay::ResponseHeader.new(request_id: 'test', spec_version: 'test'),
37
+ transaction: SixSaferpay::Transaction.new(
38
+ type: "PAYMENT",
39
+ status: transaction_status,
40
+ id: transaction_id,
41
+ date: transaction_date,
42
+ amount: SixSaferpay::Amount.new(value: amount_value, currency_code: amount_currency),
43
+ six_transaction_reference: six_transaction_reference,
44
+ ),
45
+ payment_means: payment_means
46
+ )
47
+ end
48
+
49
+ let(:gateway_response) do
50
+ ::SolidusSixSaferpay::GatewayResponse.new(
51
+ gateway_success,
52
+ "initialize success: #{gateway_success}",
53
+ api_response
54
+ )
55
+ end
56
+
57
+ # stub gateway to return our mock response
58
+ before do
59
+ allow(subject).to receive(:gateway).
60
+ and_return(double('gateway', authorize: gateway_response))
61
+ end
62
+
63
+ context 'when not successful' do
64
+ let(:gateway_success) { false }
65
+
66
+ it 'indicates failure' do
67
+ subject.call
68
+
69
+ expect(subject).not_to be_success
70
+ end
71
+
72
+ it 'does not update the payment attributes' do
73
+ expect { subject.call }.not_to change { payment.transaction_id }
74
+ expect { subject.call }.not_to change { payment.transaction_status }
75
+ expect { subject.call }.not_to change { payment.transaction_date }
76
+ expect { subject.call }.not_to change { payment.six_transaction_reference }
77
+ expect { subject.call }.not_to change { payment.display_text }
78
+ expect { subject.call }.not_to change { payment.response_hash }
79
+ end
80
+ end
81
+
82
+ context 'when successful' do
83
+ let(:gateway_success) { true }
84
+
85
+ it 'updates the transaction_id' do
86
+ expect { subject.call }.to change { payment.transaction_id }.from(nil).to(transaction_id)
87
+ end
88
+
89
+ it 'updates the transaction status' do
90
+ expect { subject.call }.to change { payment.transaction_status }.from(nil).to(transaction_status)
91
+ end
92
+
93
+ it 'updates the transaction date' do
94
+ expect { subject.call }.to change { payment.transaction_date }.from(nil).to(DateTime.parse(transaction_date))
95
+ end
96
+
97
+ it 'updates the six_transaction_reference' do
98
+ expect { subject.call }.to change { payment.six_transaction_reference }.from(nil).to(six_transaction_reference)
99
+ end
100
+
101
+ it 'updates the display_text' do
102
+ expect { subject.call }.to change { payment.display_text }.from(nil).to(display_text)
103
+ end
104
+
105
+ it 'updates the response hash' do
106
+ expect { subject.call }.to change { payment.response_hash }.from(payment.response_hash).to(api_response.to_h)
107
+ end
108
+
109
+ context 'when the payment was made with a card' do
110
+ let(:masked_number) { "xxxx xxxx xxxx 5555" }
111
+ let(:exp_year) { "19" }
112
+ let(:exp_month) { "5" }
113
+ let(:payment_means) do
114
+ SixSaferpay::ResponsePaymentMeans.new(
115
+ brand: SixSaferpay::Brand.new(name: brand_name),
116
+ display_text: display_text,
117
+ card: SixSaferpay::ResponseCard.new(
118
+ masked_number: masked_number,
119
+ exp_year: exp_year,
120
+ exp_month: exp_month
121
+ )
122
+ )
123
+ end
124
+
125
+ it 'updates the masked number' do
126
+ expect { subject.call }.to change { payment.masked_number }.from(nil).to(masked_number)
127
+ end
128
+
129
+ it 'updates the expiry year' do
130
+ expect { subject.call }.to change { payment.expiration_year }.from(nil).to(exp_year)
131
+ end
132
+
133
+ it 'updates the expiry month' do
134
+ expect { subject.call }.to change { payment.expiration_month }.from(nil).to(exp_month)
135
+ end
136
+ end
137
+
138
+ it 'indicates success' do
139
+ subject.call
140
+
141
+ expect(subject).to be_success
142
+ end
143
+ end
144
+ end
145
+
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,39 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe AuthorizePayment do
6
+
7
+ let(:payment) { create(:six_saferpay_payment) }
8
+
9
+ let(:service) { described_class.new(payment) }
10
+
11
+ describe '.call' do
12
+ it 'calls an initialized service with given order and payment method' do
13
+ expect(described_class).to receive(:new).with(payment).and_return(service)
14
+ expect(service).to receive(:call)
15
+
16
+ described_class.call(payment)
17
+ end
18
+ end
19
+
20
+ describe '#call' do
21
+ it 'fails because gateway raises an error' do
22
+ expect { service.call }.to raise_error(NotImplementedError)
23
+ end
24
+ end
25
+
26
+ describe '#gateway' do
27
+ it 'raises an error because the gateway must be defined in subclasses' do
28
+ expect { service.gateway }.to raise_error(NotImplementedError)
29
+ end
30
+ end
31
+
32
+ describe '#success?' do
33
+ it 'is initially false' do
34
+ expect(service).not_to be_success
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,148 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe AuthorizeTransaction do
6
+
7
+ let(:payment) { create(:six_saferpay_payment) }
8
+
9
+ subject { described_class.new(payment) }
10
+
11
+
12
+ describe '#gateway' do
13
+ it_behaves_like "it uses the transaction gateway"
14
+ end
15
+
16
+ describe '#call' do
17
+ let(:transaction_status) { "AUTHORIZED" }
18
+ let(:transaction_id) { "723n4MAjMdhjSAhAKEUdA8jtl9jb" }
19
+ let(:transaction_date) { "2015-01-30T12:45:22.258+01:00" }
20
+ let(:amount_value) { "100" }
21
+ let(:amount_currency) { "USD" }
22
+ let(:brand_name) { 'PaymentBrand' }
23
+ let(:display_text) { "xxxx xxxx xxxx 1234" }
24
+ let(:six_transaction_reference) { "0:0:3:723n4MAjMdhjSAhAKEUdA8jtl9jb" }
25
+
26
+ let(:payment_means) do
27
+ SixSaferpay::ResponsePaymentMeans.new(
28
+ brand: SixSaferpay::Brand.new(name: brand_name),
29
+ display_text: display_text
30
+ )
31
+ end
32
+
33
+ # https://saferpay.github.io/jsonapi/#Payment_v1_PaymentPage_Initialize
34
+ let(:api_response) do
35
+ SixSaferpay::SixPaymentPage::AssertResponse.new(
36
+ response_header: SixSaferpay::ResponseHeader.new(request_id: 'test', spec_version: 'test'),
37
+ transaction: SixSaferpay::Transaction.new(
38
+ type: "PAYMENT",
39
+ status: transaction_status,
40
+ id: transaction_id,
41
+ date: transaction_date,
42
+ amount: SixSaferpay::Amount.new(value: amount_value, currency_code: amount_currency),
43
+ six_transaction_reference: six_transaction_reference,
44
+ ),
45
+ payment_means: payment_means
46
+ )
47
+ end
48
+
49
+ let(:gateway_response) do
50
+ ::SolidusSixSaferpay::GatewayResponse.new(
51
+ gateway_success,
52
+ "initialize success: #{gateway_success}",
53
+ api_response
54
+ )
55
+ end
56
+
57
+ # stub gateway to return our mock response
58
+ before do
59
+ allow(subject).to receive(:gateway).
60
+ and_return(double('gateway', authorize: gateway_response))
61
+ end
62
+
63
+ context 'when not successful' do
64
+ let(:gateway_success) { false }
65
+
66
+ it 'indicates failure' do
67
+ subject.call
68
+
69
+ expect(subject).not_to be_success
70
+ end
71
+
72
+ it 'does not update the payment attributes' do
73
+ expect { subject.call }.not_to change { payment.transaction_id }
74
+ expect { subject.call }.not_to change { payment.transaction_status }
75
+ expect { subject.call }.not_to change { payment.transaction_date }
76
+ expect { subject.call }.not_to change { payment.six_transaction_reference }
77
+ expect { subject.call }.not_to change { payment.display_text }
78
+ expect { subject.call }.not_to change { payment.response_hash }
79
+ end
80
+ end
81
+
82
+ context 'when successful' do
83
+ let(:gateway_success) { true }
84
+
85
+ it 'updates the transaction_id' do
86
+ expect { subject.call }.to change { payment.transaction_id }.from(nil).to(transaction_id)
87
+ end
88
+
89
+ it 'updates the transaction status' do
90
+ expect { subject.call }.to change { payment.transaction_status }.from(nil).to(transaction_status)
91
+ end
92
+
93
+ it 'updates the transaction date' do
94
+ expect { subject.call }.to change { payment.transaction_date }.from(nil).to(DateTime.parse(transaction_date))
95
+ end
96
+
97
+ it 'updates the six_transaction_reference' do
98
+ expect { subject.call }.to change { payment.six_transaction_reference }.from(nil).to(six_transaction_reference)
99
+ end
100
+
101
+ it 'updates the display_text' do
102
+ expect { subject.call }.to change { payment.display_text }.from(nil).to(display_text)
103
+ end
104
+
105
+ it 'updates the response hash' do
106
+ expect { subject.call }.to change { payment.response_hash }.from(payment.response_hash).to(api_response.to_h)
107
+ end
108
+
109
+ context 'when the payment was made with a card' do
110
+ let(:masked_number) { "xxxx xxxx xxxx 5555" }
111
+ let(:exp_year) { "19" }
112
+ let(:exp_month) { "5" }
113
+ let(:payment_means) do
114
+ SixSaferpay::ResponsePaymentMeans.new(
115
+ brand: SixSaferpay::Brand.new(name: brand_name),
116
+ display_text: display_text,
117
+ card: SixSaferpay::ResponseCard.new(
118
+ masked_number: masked_number,
119
+ exp_year: exp_year,
120
+ exp_month: exp_month
121
+ )
122
+ )
123
+ end
124
+
125
+ it 'updates the masked number' do
126
+ expect { subject.call }.to change { payment.masked_number }.from(nil).to(masked_number)
127
+ end
128
+
129
+ it 'updates the expiry year' do
130
+ expect { subject.call }.to change { payment.expiration_year }.from(nil).to(exp_year)
131
+ end
132
+
133
+ it 'updates the expiry month' do
134
+ expect { subject.call }.to change { payment.expiration_month }.from(nil).to(exp_month)
135
+ end
136
+ end
137
+
138
+ it 'indicates success' do
139
+ subject.call
140
+
141
+ expect(subject).to be_success
142
+ end
143
+ end
144
+ end
145
+
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,83 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe InitializePaymentPage do
6
+
7
+ let(:order) { create(:order) }
8
+ let(:payment_method) { create(:saferpay_payment_method) }
9
+
10
+ subject { described_class.new(order, payment_method) }
11
+
12
+
13
+ describe '#gateway' do
14
+ it_behaves_like "it uses the payment page gateway"
15
+ end
16
+
17
+ describe '#call' do
18
+ let(:token) { '234uhfh78234hlasdfh8234e1234' }
19
+ let(:expiration) { '2015-01-30T12:45:22.258+01:00' }
20
+ let(:redirect_url) { '/saferpay/redirect/url' }
21
+
22
+ # https://saferpay.github.io/jsonapi/#Payment_v1_PaymentPage_Initialize
23
+ let(:api_response) do
24
+ SixSaferpay::SixPaymentPage::InitializeResponse.new(
25
+ response_header: SixSaferpay::ResponseHeader.new(request_id: 'test', spec_version: 'test'),
26
+ token: token,
27
+ expiration: expiration,
28
+ redirect_url: redirect_url
29
+ )
30
+ end
31
+
32
+ let(:gateway_response) do
33
+ ::SolidusSixSaferpay::GatewayResponse.new(
34
+ gateway_success,
35
+ "initialize success: #{gateway_success}",
36
+ api_response
37
+ )
38
+ end
39
+
40
+ # stub gateway to return our mock response
41
+ before do
42
+ allow(subject).to receive(:gateway).
43
+ and_return(double('gateway', initialize_payment: gateway_response))
44
+ end
45
+
46
+ context 'when not successful' do
47
+ let(:gateway_success) { false }
48
+
49
+ it 'indicates failure' do
50
+ subject.call
51
+
52
+ expect(subject).not_to be_success
53
+ end
54
+
55
+ it 'does not create a saferpay payment' do
56
+ expect { subject.call }.not_to change { Spree::SixSaferpayPayment.count }
57
+ end
58
+ end
59
+
60
+ context 'when successful' do
61
+ let(:gateway_success) { true }
62
+
63
+ it 'creates a new saferpay payment' do
64
+ expect { subject.call }.to change { Spree::SixSaferpayPayment.count }.from(0).to(1)
65
+ end
66
+
67
+ it 'sets the redirect_url' do
68
+ subject.call
69
+
70
+ expect(subject.redirect_url).to eq(redirect_url)
71
+ end
72
+
73
+ it 'indicates success' do
74
+ subject.call
75
+
76
+ expect(subject).to be_success
77
+ end
78
+ end
79
+ end
80
+
81
+ end
82
+ end
83
+ end