solidus_six_saferpay 0.1.7 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) 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/solidus_six_saferpay/saferpay_payment.js +4 -1
  16. data/app/assets/javascripts/spree/backend/solidus_six_saferpay.js +2 -0
  17. data/app/assets/javascripts/spree/frontend/solidus_six_saferpay.js +2 -0
  18. data/app/assets/stylesheets/spree/backend/solidus_six_saferpay.css +4 -0
  19. data/app/assets/stylesheets/spree/frontend/solidus_six_saferpay.css +4 -0
  20. data/app/controllers/spree/solidus_six_saferpay/checkout_controller.rb +82 -16
  21. data/app/controllers/spree/solidus_six_saferpay/transaction/checkout_controller.rb +1 -1
  22. data/app/models/spree/payment_method/saferpay_payment_method.rb +1 -1
  23. data/app/models/spree/payment_method/saferpay_payment_page.rb +2 -2
  24. data/app/models/spree/payment_method/saferpay_transaction.rb +2 -2
  25. data/app/services/spree/solidus_six_saferpay/cancel_authorized_payment.rb +33 -0
  26. data/app/services/spree/solidus_six_saferpay/initialize_payment.rb +0 -1
  27. data/app/services/spree/solidus_six_saferpay/initialize_transaction.rb +0 -1
  28. data/app/services/spree/solidus_six_saferpay/inquire_payment.rb +27 -1
  29. data/app/services/spree/solidus_six_saferpay/order_not_found_handler.rb +28 -0
  30. data/app/services/spree/solidus_six_saferpay/payment_not_found_handler.rb +28 -0
  31. data/app/services/spree/solidus_six_saferpay/payment_processing_success_handler.rb +26 -0
  32. data/app/views/spree/checkout/payment/_saferpay_payment.html.erb +2 -2
  33. data/app/views/spree/solidus_six_saferpay/checkout/{iframe_breakout_redirect.html.erb → iframe_breakout_redirect.erb} +1 -1
  34. data/bin/console +17 -0
  35. data/bin/rails +18 -0
  36. data/bin/rake +7 -0
  37. data/bin/setup +8 -0
  38. data/config/initializers/assets.rb +3 -0
  39. data/config/locales/de.yml +3 -0
  40. data/config/locales/en.yml +3 -0
  41. data/config/locales/fr.yml +3 -0
  42. data/config/routes.rb +8 -8
  43. data/lib/generators/solidus_six_saferpay/install/install_generator.rb +15 -3
  44. data/lib/solidus_six_saferpay.rb +6 -3
  45. data/lib/solidus_six_saferpay/configuration.rb +2 -7
  46. data/lib/solidus_six_saferpay/engine.rb +19 -10
  47. data/lib/solidus_six_saferpay/gateway.rb +11 -11
  48. data/lib/solidus_six_saferpay/payment_page_gateway.rb +8 -9
  49. data/lib/solidus_six_saferpay/transaction_gateway.rb +8 -9
  50. data/lib/solidus_six_saferpay/version.rb +3 -1
  51. data/solidus_six_saferpay.gemspec +42 -0
  52. data/spec/controllers/spree/solidus_six_saferpay/payment_page/checkout_controller_spec.rb +16 -0
  53. data/spec/controllers/spree/solidus_six_saferpay/transaction/checkout_controller_spec.rb +16 -0
  54. data/spec/factories/payment_methods.rb +23 -0
  55. data/spec/factories/payments.rb +11 -0
  56. data/spec/factories/spree/six_saferpay_payments.rb +118 -0
  57. data/spec/models/spree/six_saferpay_payment_spec.rb +203 -0
  58. data/spec/rails_helper.rb +73 -0
  59. data/spec/services/spree/solidus_six_saferpay/assert_payment_page_spec.rb +22 -0
  60. data/spec/services/spree/solidus_six_saferpay/authorize_payment_spec.rb +39 -0
  61. data/spec/services/spree/solidus_six_saferpay/authorize_transaction_spec.rb +24 -0
  62. data/spec/services/spree/solidus_six_saferpay/cancel_authorized_payment_spec.rb +58 -0
  63. data/spec/services/spree/solidus_six_saferpay/initialize_payment_page_spec.rb +81 -0
  64. data/spec/services/spree/solidus_six_saferpay/initialize_payment_spec.rb +40 -0
  65. data/spec/services/spree/solidus_six_saferpay/initialize_transaction_spec.rb +84 -0
  66. data/spec/services/spree/solidus_six_saferpay/inquire_payment_page_payment_spec.rb +20 -0
  67. data/spec/services/spree/solidus_six_saferpay/inquire_payment_spec.rb +39 -0
  68. data/spec/services/spree/solidus_six_saferpay/inquire_transaction_payment_spec.rb +21 -0
  69. data/spec/services/spree/solidus_six_saferpay/order_not_found_handler_spec.rb +30 -0
  70. data/spec/services/spree/solidus_six_saferpay/payment_not_found_handler_spec.rb +30 -0
  71. data/spec/services/spree/solidus_six_saferpay/payment_processing_success_handler_spec.rb +34 -0
  72. data/spec/services/spree/solidus_six_saferpay/payment_validator_spec.rb +100 -0
  73. data/spec/services/spree/solidus_six_saferpay/process_authorized_payment_spec.rb +39 -0
  74. data/spec/services/spree/solidus_six_saferpay/process_payment_page_payment_spec.rb +20 -0
  75. data/spec/services/spree/solidus_six_saferpay/process_transaction_payment_spec.rb +20 -0
  76. data/spec/solidus_six_saferpay/configuration_spec.rb +12 -0
  77. data/spec/solidus_six_saferpay/error_handler_spec.rb +65 -0
  78. data/spec/solidus_six_saferpay/gateway_response_spec.rb +70 -0
  79. data/spec/solidus_six_saferpay/gateway_spec.rb +365 -0
  80. data/spec/solidus_six_saferpay/payment_page_gateway_spec.rb +392 -0
  81. data/spec/solidus_six_saferpay/transaction_gateway_spec.rb +390 -0
  82. data/spec/spec_helper.rb +21 -0
  83. data/spec/support/route_access.rb +6 -0
  84. data/spec/support/shared_examples/authorize_payment.rb +132 -0
  85. data/spec/support/shared_examples/checkout_controller.rb +294 -0
  86. data/spec/support/shared_examples/inquire_payment.rb +118 -0
  87. data/spec/support/shared_examples/process_authorized_payment.rb +202 -0
  88. data/spec/support/uses_payment_page_gateway.rb +29 -0
  89. data/spec/support/uses_transaction_gateway.rb +28 -0
  90. metadata +261 -62
  91. data/app/services/spree/solidus_six_saferpay/inquire_transaction.rb +0 -7
@@ -0,0 +1,39 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe InquirePayment do
6
+
7
+ let(:payment) { create(:six_saferpay_payment, :authorized) }
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,21 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe InquireTransactionPayment do
6
+
7
+ let(:payment) { create(:six_saferpay_payment) }
8
+ subject { described_class.new(payment) }
9
+
10
+ describe '#gateway' do
11
+ it_behaves_like "it uses the transaction gateway"
12
+ end
13
+
14
+ describe '#call' do
15
+ let(:api_response_class) { SixSaferpay::SixTransaction::InquireResponse }
16
+ it_behaves_like "inquire_payment"
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe OrderNotFoundHandler do
6
+
7
+ let(:controller) { instance_double(SolidusSixSaferpay::CheckoutController) }
8
+ let(:order_number) { "R123445678" }
9
+
10
+ subject { described_class.new(controller_context: controller, order_number: order_number) }
11
+
12
+ describe '.call' do
13
+ it 'calls a new instance with given parameters' do
14
+ expect(described_class).to receive(:new).with(controller_context: controller, order_number: order_number).and_return(subject)
15
+ expect(subject).to receive(:call)
16
+
17
+ described_class.call(controller_context: controller, order_number: order_number)
18
+ end
19
+ end
20
+
21
+ describe '#call' do
22
+ it 'informs about the error' do
23
+ expect(::SolidusSixSaferpay::ErrorHandler).to receive(:handle).with(instance_of(StandardError))
24
+
25
+ subject.call
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe PaymentNotFoundHandler do
6
+
7
+ let(:controller) { instance_double(SolidusSixSaferpay::CheckoutController) }
8
+ let(:order) { instance_double(Spree::Order, number: "R12345678") }
9
+
10
+ subject { described_class.new(controller_context: controller, order: order) }
11
+
12
+ describe '.call' do
13
+ it 'calls a new instance with given parameters' do
14
+ expect(described_class).to receive(:new).with(controller_context: controller, order: order).and_return(subject)
15
+ expect(subject).to receive(:call)
16
+
17
+ described_class.call(controller_context: controller, order: order)
18
+ end
19
+ end
20
+
21
+ describe '#call' do
22
+ it 'informs about the error' do
23
+ expect(::SolidusSixSaferpay::ErrorHandler).to receive(:handle).with(instance_of(StandardError))
24
+
25
+ subject.call
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe PaymentProcessingSuccessHandler do
6
+
7
+ let(:controller) { instance_double(SolidusSixSaferpay::CheckoutController) }
8
+ let(:order) { instance_double(Spree::Order, number: "R12345678") }
9
+
10
+ subject { described_class.new(controller_context: controller, order: order) }
11
+
12
+ describe '.call' do
13
+ it 'calls a new instance with given parameters' do
14
+ expect(described_class).to receive(:new).with(controller_context: controller, order: order).and_return(subject)
15
+ expect(subject).to receive(:call)
16
+
17
+ described_class.call(controller_context: controller, order: order)
18
+ end
19
+ end
20
+
21
+ describe '#call' do
22
+ context 'when the order is in payment state' do
23
+ let(:order) { instance_double(Spree::Order, number: "R12345678", payment?: true) }
24
+
25
+ it 'advances the order to the next state' do
26
+ expect(order).to receive(:next!)
27
+
28
+ subject.call
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,100 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe PaymentValidator do
6
+
7
+ let(:payment) { create(:six_saferpay_payment, :authorized) }
8
+
9
+ let(:service) { described_class.new(payment) }
10
+
11
+ describe '.call' do
12
+ it 'calls an initialized service with given saferpay payment' 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 'performs multiple validations on the payment' do
22
+ expect(service).to receive(:validate_payment_authorized).with(payment.transaction)
23
+ expect(service).to receive(:validate_order_reference).with(payment.transaction)
24
+ expect(service).to receive(:validate_order_amount).with(payment.transaction)
25
+
26
+ service.call
27
+ end
28
+ end
29
+
30
+ describe '#validate_payment_authorized' do
31
+ let(:saferpay_transaction) { instance_double("SixSaferpay::Transaction", status: "AUTHORIZED") }
32
+
33
+ context 'when the saferpay status is AUTHORIZED' do
34
+ it 'passes validation' do
35
+ expect(service.validate_payment_authorized(saferpay_transaction)).to be true
36
+ end
37
+ end
38
+
39
+ context 'when the saferpay status is CAPTURED' do
40
+ let(:saferpay_transaction) { instance_double("SixSaferpay::Transaction", status: "CAPTURED") }
41
+ it 'raises an error' do
42
+ expect{ service.validate_payment_authorized(saferpay_transaction) }.to raise_error(::SolidusSixSaferpay::InvalidSaferpayPayment)
43
+ end
44
+ end
45
+
46
+ context 'when the saferpay status is PENDING' do
47
+ let(:saferpay_transaction) { instance_double("SixSaferpay::Transaction", status: "PENDING") }
48
+ it 'raises an error' do
49
+ expect{ service.validate_payment_authorized(saferpay_transaction) }.to raise_error(::SolidusSixSaferpay::InvalidSaferpayPayment)
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '#validate_order_reference' do
55
+ context 'when the saferpay order reference matches the solidus order' do
56
+ let(:saferpay_transaction) { instance_double("SixSaferpay::Transaction", order_id: payment.order.number) }
57
+
58
+ it 'passes validation' do
59
+ expect(service.validate_order_reference(saferpay_transaction)).to be true
60
+ end
61
+ end
62
+
63
+ context 'when the saferpay order reference does not match the solidus order' do
64
+ let(:saferpay_transaction) { instance_double("SixSaferpay::Transaction", order_id: "OTHER") }
65
+
66
+ it 'raises an error' do
67
+ expect{ service.validate_order_reference(saferpay_transaction) }.to raise_error(::SolidusSixSaferpay::InvalidSaferpayPayment)
68
+ end
69
+ end
70
+ end
71
+
72
+ describe '#validate_order_amount' do
73
+ let(:saferpay_transaction) { instance_double("SixSaferpay::Transaction", amount: saferpay_amount) }
74
+ context 'when the saferpay payment values match the solidus order values' do
75
+ let(:saferpay_amount) { instance_double("SixSaferpay::Amount", value: (payment.order.amount * 100).to_s, currency_code: payment.order.currency) }
76
+
77
+ it 'passes validation' do
78
+ expect(service.validate_order_amount(saferpay_transaction)).to be true
79
+ end
80
+ end
81
+
82
+ context 'when the saferpay payment currency does not match the solidus order currency' do
83
+ let(:saferpay_amount) { instance_double("SixSaferpay::Amount", value: (payment.order.amount * 100).to_s, currency_code: "OTHER") }
84
+
85
+ it 'raises an error' do
86
+ expect{ service.validate_order_amount(saferpay_transaction) }.to raise_error(::SolidusSixSaferpay::InvalidSaferpayPayment)
87
+ end
88
+ end
89
+
90
+ context 'when the saferpay payment value does not match the solidus order value' do
91
+ let(:saferpay_amount) { instance_double("SixSaferpay::Amount", value: ((payment.order.amount + 5) * 100).to_s, currency_code: payment.order.currency) }
92
+
93
+ it 'raises an error' do
94
+ expect{ service.validate_order_amount(saferpay_transaction) }.to raise_error(::SolidusSixSaferpay::InvalidSaferpayPayment)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,39 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe ProcessAuthorizedPayment do
6
+
7
+ let(:payment) { create(:six_saferpay_payment, :authorized) }
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,20 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe ProcessPaymentPagePayment do
6
+
7
+ let(:payment) { create(:six_saferpay_payment, :authorized) }
8
+
9
+ subject { described_class.new(payment) }
10
+
11
+ describe '#gateway' do
12
+ it_behaves_like "it uses the payment page gateway"
13
+ end
14
+
15
+ describe '#call' do
16
+ it_behaves_like 'process_authorized_payment'
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'rails_helper'
2
+
3
+ module Spree
4
+ module SolidusSixSaferpay
5
+ RSpec.describe ProcessTransactionPayment do
6
+
7
+ let(:payment) { create(:six_saferpay_payment, :authorized) }
8
+
9
+ subject { described_class.new(payment) }
10
+
11
+ describe '#gateway' do
12
+ it_behaves_like "it uses the transaction gateway"
13
+ end
14
+
15
+ describe '#call' do
16
+ it_behaves_like 'process_authorized_payment'
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ require 'rails_helper'
2
+
3
+ module SolidusSixSaferpay
4
+ RSpec.describe Configuration do
5
+
6
+ describe '.config' do
7
+ it 'exposes a configurable list of error handlers' do
8
+ expect(described_class).to respond_to(:error_handlers)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,65 @@
1
+ require 'rails_helper'
2
+
3
+ module SolidusSixSaferpay
4
+ RSpec.describe ErrorHandler do
5
+
6
+ let(:error) { StandardError.new }
7
+ let(:error_handlers) { [] }
8
+
9
+ before do
10
+ allow(Configuration).to receive(:error_handlers).and_return(error_handlers)
11
+ end
12
+
13
+ describe '.handle' do
14
+
15
+ it 'defaults to level :error' do
16
+ expect(Rails.logger).to receive(:error).with(error)
17
+ described_class.handle(error)
18
+ end
19
+
20
+ it 'allows for configuring the error level' do
21
+ expect(Rails.logger).to receive(:info).with(error)
22
+ described_class.handle(error, level: :info)
23
+ end
24
+
25
+ context 'when any attached handler can not receive our error messages' do
26
+ let(:error_handler1) { double("Handler1", to_s: 'handler1', call: true) }
27
+ let(:error_handler2) { double("Handler2", to_s: 'handler2') }
28
+ let(:error_handler3) { double("Handler3", to_s: 'handler3', call: true) }
29
+
30
+ let(:error_handlers) { [error_handler1, error_handler2, error_handler3] }
31
+
32
+ before do
33
+ allow(error_handler1).to receive(:respond_to?).with(:call).and_return(true)
34
+ allow(error_handler2).to receive(:respond_to?).with(:call).and_return(false)
35
+ allow(error_handler3).to receive(:respond_to?).with(:call).and_return(true)
36
+ end
37
+
38
+ it 'informs about the misconfiguration via Rails logger' do
39
+ expect(Rails.logger).to receive(:warn).with(/ERROR:.*handler2.*/)
40
+
41
+ described_class.handle(error)
42
+ end
43
+
44
+ it 'skips to the next error handler' do
45
+ expect(error_handler1).to receive(:call).with(error, level: :error)
46
+ expect(error_handler2).not_to receive(:call)
47
+ expect(error_handler3).to receive(:call).with(error, level: :error)
48
+
49
+ described_class.handle(error)
50
+ end
51
+ end
52
+
53
+ context 'when an attached handler can receive our error messages' do
54
+ let(:error_handler) { double("CustomErrorHandler", call: true) }
55
+ let(:error_handlers) { [error_handler] }
56
+
57
+ it 'forwards the error to the error handler' do
58
+ expect(error_handler).to receive(:call).with(error, level: :error)
59
+
60
+ described_class.handle(error)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,70 @@
1
+ require 'rails_helper'
2
+
3
+ module SolidusSixSaferpay
4
+ RSpec.describe GatewayResponse do
5
+ let(:success) { true }
6
+ let(:message) { double('message') }
7
+ let(:api_response) { double('API response') }
8
+ let(:options) { {} }
9
+
10
+ subject { described_class.new(success, message, api_response, options) }
11
+
12
+ describe '#initialize' do
13
+ let(:error_name) { double("error_name") }
14
+ let(:authorization) { double("authorization") }
15
+
16
+ describe 'when given option :error_name' do
17
+ let(:options) { { error_name: error_name } }
18
+
19
+ it 'sets the error name' do
20
+ expect(subject.error_name).to eq(error_name)
21
+ end
22
+ end
23
+
24
+ describe 'when given option :authorization' do
25
+ let(:options) { { authorization: authorization } }
26
+
27
+ it 'sets the authorization' do
28
+ expect(subject.authorization).to eq(authorization)
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ describe '#success?' do
35
+ context 'when initialized as a success' do
36
+ let(:success) { true }
37
+
38
+ it 'is true' do
39
+ expect(subject).to be_success
40
+ end
41
+ end
42
+
43
+ context 'when initialized as failure' do
44
+ let(:success) { false }
45
+
46
+ it 'is false' do
47
+ expect(subject).not_to be_success
48
+ end
49
+ end
50
+ end
51
+
52
+ describe '#to_s' do
53
+ it 'returns the message' do
54
+ expect(subject.to_s).to eq(message)
55
+ end
56
+ end
57
+
58
+ describe '#avs_result' do
59
+ it 'should be an empty hash' do
60
+ expect(subject.avs_result).to eq({})
61
+ end
62
+ end
63
+
64
+ describe '#cvv_result' do
65
+ it 'should be nil' do
66
+ expect(subject.cvv_result).to be_nil
67
+ end
68
+ end
69
+ end
70
+ end