solidus-adyen 0.1.2

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 (78) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +26 -0
  3. data/.rubocop.yml +9 -0
  4. data/.rubocop_todo.yml +325 -0
  5. data/Gemfile +9 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +238 -0
  8. data/Rakefile +16 -0
  9. data/app/assets/javascripts/spree/backend/solidus-adyen.js +1 -0
  10. data/app/assets/javascripts/spree/checkout/payment/adyen.js +10 -0
  11. data/app/assets/javascripts/spree/frontend/solidus-adyen.js +1 -0
  12. data/app/assets/stylesheets/spree/backend/solidus-adyen/buttons.scss +15 -0
  13. data/app/assets/stylesheets/spree/backend/solidus-adyen/communication.scss +121 -0
  14. data/app/assets/stylesheets/spree/backend/solidus-adyen/variables.scss +4 -0
  15. data/app/assets/stylesheets/spree/backend/solidus-adyen.css +5 -0
  16. data/app/assets/stylesheets/spree/frontend/solidus-adyen.css +3 -0
  17. data/app/controllers/concerns/spree/adyen/admin/refunds_controller.rb +59 -0
  18. data/app/controllers/spree/adyen/hpps_controller.rb +22 -0
  19. data/app/controllers/spree/adyen_notifications_controller.rb +34 -0
  20. data/app/controllers/spree/adyen_redirect_controller.rb +90 -0
  21. data/app/models/adyen_notification.rb +159 -0
  22. data/app/models/concerns/spree/adyen/order.rb +11 -0
  23. data/app/models/concerns/spree/adyen/payment.rb +95 -0
  24. data/app/models/spree/adyen/hpp_source.rb +101 -0
  25. data/app/models/spree/adyen/notification_processor.rb +102 -0
  26. data/app/models/spree/adyen/presenters/communication.rb +31 -0
  27. data/app/models/spree/adyen/presenters/communications/adyen_notification.rb +26 -0
  28. data/app/models/spree/adyen/presenters/communications/base.rb +50 -0
  29. data/app/models/spree/adyen/presenters/communications/hpp_source.rb +31 -0
  30. data/app/models/spree/adyen/presenters/communications/log_entry.rb +28 -0
  31. data/app/models/spree/adyen/presenters/communications.rb +9 -0
  32. data/app/models/spree/gateway/adyen_hpp.rb +95 -0
  33. data/app/overrides/spree/admin/shared/_order_summary.rb +6 -0
  34. data/app/views/spree/admin/payments/source_forms/_adyen.html.erb +1 -0
  35. data/app/views/spree/admin/payments/source_views/_adyen.html.erb +14 -0
  36. data/app/views/spree/adyen/_manual_refund.html.erb +9 -0
  37. data/app/views/spree/adyen/communication/_communication.html.erb +42 -0
  38. data/app/views/spree/adyen/hpps/directory.html.erb +10 -0
  39. data/app/views/spree/checkout/payment/_adyen.html.erb +33 -0
  40. data/bin/checkout.rb +111 -0
  41. data/bin/regen.sh +1 -0
  42. data/config/initializers/solidus_adyen.rb +1 -0
  43. data/config/locales/en.yml +23 -0
  44. data/config/routes.rb +13 -0
  45. data/db/migrate/20131017040945_create_adyen_notifications.rb +29 -0
  46. data/db/migrate/20150911201942_add_index_adyen_notifications_psp_reference.rb +5 -0
  47. data/db/migrate/20150914162539_create_spree_adyen_hpp_sources.rb +21 -0
  48. data/db/migrate/20151007090519_add_days_to_ship_to_config.rb +5 -0
  49. data/db/migrate/20151020230830_remove_indices_on_adyen_notifications.rb +6 -0
  50. data/db/migrate/20151106093023_allow_merchant_reference_to_be_null_for_adyen_notification.rb +5 -0
  51. data/lib/solidus-adyen.rb +1 -0
  52. data/lib/spree/adyen/engine.rb +32 -0
  53. data/lib/spree/adyen/form.rb +135 -0
  54. data/lib/spree/adyen/hpp_check.rb +11 -0
  55. data/lib/spree/adyen/url.rb +30 -0
  56. data/lib/spree/adyen/version.rb +5 -0
  57. data/lib/spree/adyen.rb +6 -0
  58. data/solidus-adyen.gemspec +51 -0
  59. data/spec/controllers/concerns/spree/adyen/admin/refunds_controller_spec.rb +76 -0
  60. data/spec/controllers/spree/adyen/hpps_controller_spec.rb +43 -0
  61. data/spec/controllers/spree/adyen_notifications_controller_spec.rb +118 -0
  62. data/spec/controllers/spree/adyen_redirect_controller_spec.rb +154 -0
  63. data/spec/factories/active_merchant_billing_response.rb +23 -0
  64. data/spec/factories/adyen_notification.rb +91 -0
  65. data/spec/factories/spree_adyen_hpp_source.rb +15 -0
  66. data/spec/factories/spree_gateway_adyen_hpp.rb +23 -0
  67. data/spec/factories/spree_payment.rb +13 -0
  68. data/spec/lib/spree/adyen/form_spec.rb +214 -0
  69. data/spec/models/adyen_notification_spec.rb +86 -0
  70. data/spec/models/concerns/spree/adyen/order_spec.rb +22 -0
  71. data/spec/models/concerns/spree/adyen/payment_spec.rb +93 -0
  72. data/spec/models/spree/adyen/hpp_source_spec.rb +101 -0
  73. data/spec/models/spree/adyen/notification_processor_spec.rb +205 -0
  74. data/spec/models/spree/adyen/presenters/communication_spec.rb +62 -0
  75. data/spec/models/spree/gateway/adyen_hpp_spec.rb +76 -0
  76. data/spec/spec_helper.rb +65 -0
  77. data/spec/support/shared_contexts/mock_adyen_api.rb +47 -0
  78. metadata +463 -0
data/bin/checkout.rb ADDED
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env ruby
2
+ require "bundler/setup"
3
+ require "capybara"
4
+ require "capybara"
5
+ require "capybara/dsl"
6
+ require "capybara/poltergeist"
7
+ require "pry"
8
+
9
+ Capybara.default_driver = :poltergeist
10
+
11
+ class Driver
12
+ include Capybara::DSL
13
+
14
+ def amex_purchase
15
+ checkout :norway
16
+
17
+ click_link "American Express"
18
+
19
+ fill_in "card.cardNumber", with: "370000000000002"
20
+ fill_in "card.cardHolderName", with: "John Doe"
21
+ select "08", from: "card.expiryMonth"
22
+ select "2018", from: "card.expiryYear"
23
+ fill_in "card.cvcCode", with: "7373"
24
+
25
+ click_button "continue"
26
+ click_button "pay"
27
+ end
28
+
29
+ def sofort_purchase
30
+ checkout :germany
31
+
32
+ click_link "Sofort Banking"
33
+ fill_in "Account number", with: "88888888"
34
+ fill_in "PIN", with: "12345"
35
+ click_button "Next"
36
+ find(
37
+ "label",
38
+ text: "23456789 - Girokonto (Max Mustermann)",
39
+ match: :prefer_exact).
40
+ click
41
+ click_button "Next"
42
+ fill_in "TAN", with: "12345"
43
+ click_button "Next"
44
+ end
45
+
46
+ def ideal_purchase issuer
47
+ checkout :norway
48
+
49
+ click_link "iDEAL"
50
+ select issuer
51
+ click_button "continue"
52
+ click_button "Continue"
53
+ end
54
+
55
+ def login
56
+ visit "http://localhost:3000/login"
57
+ fill_in "Email", with: "spree@example.com", match: :first
58
+ fill_in "Password", with: "spree123"
59
+
60
+ click_button "Login"
61
+ end
62
+
63
+ def checkout address_type
64
+ visit "http://localhost:3000/"
65
+ click_link "Ruby on Rails Tote", match: :first
66
+ click_button "Add To Cart"
67
+ click_button "Checkout"
68
+ fill_address address_type
69
+ click_button "Save and Continue"
70
+ click_button "Save and Continue"
71
+ choose "Adyen"
72
+ end
73
+
74
+ def fill_address type
75
+ fill_in "First Name", with: "John"
76
+ fill_in "Last Name", with: "Doe"
77
+ fill_in "Phone", with: "250-111-1111"
78
+ case type
79
+ when :norway
80
+ fill_norway_address
81
+ when :germany
82
+ fill_german_address
83
+ end
84
+ end
85
+
86
+ def fill_german_address
87
+ fill_in "Street Address", with: "Gleimstraße 62"
88
+ fill_in "City", with: "Berlin"
89
+ select "Germany"
90
+ select "Berlin"
91
+ fill_in "Zip", with: "13355"
92
+ end
93
+
94
+ def fill_norway_address
95
+ fill_in "Street Address", with: "Noordwal 540"
96
+ fill_in "City", with: "Den Haag"
97
+ select "Netherlands"
98
+ select "Zuid-Holland"
99
+ fill_in "Zip", with: "2513dz"
100
+ end
101
+ end
102
+
103
+ driver = Driver.new
104
+
105
+ driver.login
106
+ driver.sofort_purchase
107
+ driver.amex_purchase
108
+ driver.ideal_purchase "Test Issuer"
109
+ # driver.ideal_purchase "Test Issuer Refused"
110
+ # driver.ideal_purchase "Test Issuer Pending"
111
+ # driver.ideal_purchase "Test Issuer Cancelled"
data/bin/regen.sh ADDED
@@ -0,0 +1 @@
1
+ rm -rf spec/dummy && bundle install && rake test_app && cd spec/dummy && rake db:migrate && rails s
@@ -0,0 +1 @@
1
+ Rails.application.config.assets.precompile += %w( spree/checkout/payment/adyen.js )
@@ -0,0 +1,23 @@
1
+ ---
2
+ en:
3
+ spree:
4
+ adyen:
5
+ communication:
6
+ communication:
7
+ payment_method: "Payment method"
8
+ event_code: "Event code"
9
+ result: "Result"
10
+ message: "Message"
11
+ Reason: "Reason"
12
+ amount: "Amount"
13
+ solidus-adyen:
14
+ payment:
15
+ failure: "Action failed, check reason for more information."
16
+ success: "Action succeeded."
17
+ unprocessed: "Action was not processed: payment may require manual resolution."
18
+ manual_refund:
19
+ order_button: "manual refund required"
20
+ log_message: A cancellation was attempted on this payment but the payment
21
+ method only supports manual refunds.
22
+ Please attempt to refund this payment through the Adyen customer area
23
+ or contact an Adyen representative to assist.
data/config/routes.rb ADDED
@@ -0,0 +1,13 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ namespace :adyen do
3
+ resource :hpp, only: [] do
4
+ member do
5
+ get :directory
6
+ end
7
+ end
8
+ end
9
+
10
+ get "checkout/payment/adyen", to: "adyen_redirect#confirm", as: :adyen_confirmation
11
+ post "adyen/notify", to: "adyen_notifications#notify"
12
+ post "adyen/authorise3d", to: "adyen_redirect#authorise3d", as: :adyen_authorise3d
13
+ end
@@ -0,0 +1,29 @@
1
+ # @private
2
+ class CreateAdyenNotifications < ActiveRecord::Migration
3
+
4
+ def self.up
5
+ create_table :adyen_notifications do |t|
6
+ t.boolean :live, :null => false, :default => false
7
+ t.string :event_code, :null => false, :limit => 40
8
+ t.string :psp_reference, :null => false, :limit => 50
9
+ t.string :original_reference, :null => true
10
+ t.string :merchant_reference, :null => false
11
+ t.string :merchant_account_code, :null => false
12
+ t.datetime :event_date, :null => false
13
+ t.boolean :success, :null => false, :default => false
14
+ t.string :payment_method, :null => true
15
+ t.string :operations, :null => true
16
+ t.text :reason, :null => true
17
+ t.string :currency, :null => true, :limit => 3
18
+ t.integer :value, :null => true
19
+ t.boolean :processed, :null => false, :default => false
20
+ t.timestamps
21
+ end
22
+
23
+ add_index :adyen_notifications, [:psp_reference, :event_code, :success], :unique => true, :name => "adyen_notification_uniqueness"
24
+ end
25
+
26
+ def self.down
27
+ drop_table :adyen_notifications
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ class AddIndexAdyenNotificationsPspReference < ActiveRecord::Migration
2
+ def change
3
+ add_index :adyen_notifications, [:psp_reference], unique: true
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ # Fields come from
2
+ # https://docs.adyen.com/display/TD/HPP+payment+response
3
+ class CreateSpreeAdyenHppSources < ActiveRecord::Migration
4
+ def change
5
+ create_table :spree_adyen_hpp_sources do |t|
6
+ t.string :auth_result
7
+ t.string :psp_reference
8
+ t.string :merchant_reference
9
+ t.string :skin_code
10
+ t.string :merchant_sig
11
+ t.string :payment_method
12
+ t.string :shopper_locale
13
+ t.string :merchant_return_data
14
+
15
+ t.timestamps
16
+ end
17
+
18
+ add_index :spree_adyen_hpp_sources, :psp_reference, unique: true
19
+ add_index :spree_adyen_hpp_sources, :merchant_reference
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ class AddDaysToShipToConfig < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_adyen_hpp_sources, :days_to_ship, :integer
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class RemoveIndicesOnAdyenNotifications < ActiveRecord::Migration
2
+ def change
3
+ remove_index :adyen_notifications, name: "adyen_notification_uniqueness"
4
+ remove_index :adyen_notifications, [:psp_reference]
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AllowMerchantReferenceToBeNullForAdyenNotification < ActiveRecord::Migration
2
+ def change
3
+ change_column :adyen_notifications, :merchant_reference, :string, null: true
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ require "spree/adyen"
@@ -0,0 +1,32 @@
1
+ module Spree
2
+ module Adyen
3
+ class Engine < ::Rails::Engine
4
+ engine_name "solidus-adyen"
5
+
6
+ isolate_namespace Spree::Adyen
7
+
8
+ config.autoload_paths += Dir["#{config.root}/lib/**/"]
9
+
10
+ config.autoload_paths += %W(
11
+ #{config.root}/app/controllers/concerns
12
+ #{config.root}/app/models/concerns
13
+ )
14
+
15
+ config.generators do |g|
16
+ g.test_framework :rspec
17
+ end
18
+
19
+ initializer "spree.solidus-adyen.payment_methods", after: "spree.register.payment_methods" do |app|
20
+ app.config.spree.payment_methods << Gateway::AdyenHPP
21
+ end
22
+
23
+ def self.activate
24
+ Spree::Payment.include Spree::Adyen::Payment
25
+ Spree::Order.include Spree::Adyen::Order
26
+ Spree::Admin::RefundsController.include Spree::Adyen::Admin::RefundsController
27
+ end
28
+
29
+ config.to_prepare(&method(:activate).to_proc)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,135 @@
1
+ require "json"
2
+
3
+ module Spree
4
+ module Adyen
5
+ module Form
6
+ Form = ::Adyen::Form
7
+ UrlHelper = Object.new.extend ActionView::Helpers::UrlHelper
8
+
9
+ class << self
10
+ def payment_methods_from_directory order, payment_method
11
+ payment_methods(order, payment_method)
12
+ end
13
+
14
+ def select_url order, payment_method
15
+ endpoint_url "select", order, payment_method
16
+ end
17
+
18
+ def directory_url order, payment_method
19
+ endpoint_url "directory", order, payment_method
20
+ end
21
+
22
+ def details_url order, payment_method, brand_code
23
+ endpoint_url(
24
+ "details", order, payment_method, { brandCode: brand_code })
25
+ end
26
+
27
+ def details_url_with_issuer order, payment_method, brand_code, issuer_id
28
+ endpoint_url(
29
+ "details",
30
+ order,
31
+ payment_method,
32
+ {
33
+ brandCode: brand_code,
34
+ issuerId: issuer_id
35
+ }
36
+ )
37
+ end
38
+
39
+ def endpoint_url endpoint, order, payment_method, opts = {}
40
+ base = URI::parse(url payment_method, endpoint)
41
+
42
+ URI::HTTPS.build(
43
+ host: base.host,
44
+ path: base.path,
45
+ query: params(order, payment_method).merge(opts).to_query)
46
+ end
47
+
48
+ private
49
+ def payment_methods order, payment_method
50
+ url = directory_url(order, payment_method)
51
+
52
+ form_payment_methods_and_urls(
53
+ JSON.parse(::Net::HTTP.get(url)),
54
+ order,
55
+ payment_method
56
+ )
57
+ end
58
+
59
+ def url payment_method, endpoint
60
+ server = payment_method.preferences.fetch(:server)
61
+ Form.url(server, endpoint)
62
+ end
63
+
64
+ def form_payment_methods_and_urls response, order, payment_method
65
+ response.fetch("paymentMethods").map do |brand|
66
+ issuers = brand.fetch("issuers", []).map do |issuer|
67
+ form_issuer(issuer, order, payment_method, brand)
68
+ end
69
+ form_payment_method(brand, order, payment_method, issuers)
70
+ end
71
+ end
72
+
73
+ def form_issuer issuer, order, payment_method, brand
74
+ {
75
+ name: issuer["name"],
76
+ payment_url: details_url_with_issuer(
77
+ order,
78
+ payment_method,
79
+ brand["brandCode"],
80
+ issuer["issuerId"]
81
+ ).to_s
82
+ }
83
+ end
84
+
85
+ def form_payment_method brand, order, payment_method, issuers
86
+ {
87
+ brand_code: brand["brandCode"],
88
+ name: brand["name"],
89
+ payment_url: details_url(
90
+ order,
91
+ payment_method,
92
+ brand["brandCode"]
93
+ ).to_s,
94
+ issuers: issuers
95
+ }
96
+ end
97
+
98
+ def params order, payment_method
99
+ merchant_return_data = [
100
+ order.guest_token,
101
+ payment_method.id
102
+ ].
103
+ join("|")
104
+
105
+ Form.flat_payment_parameters default_params.
106
+ merge(order_params order).
107
+ merge(payment_method_params payment_method).
108
+ merge(merchant_return_data: merchant_return_data)
109
+ end
110
+
111
+ # TODO set this in the adyen config
112
+ def default_params
113
+ { session_validity: 10.minutes.from_now,
114
+ recurring: false }
115
+ end
116
+
117
+ def order_params order
118
+ { currency_code: order.currency,
119
+ merchant_reference: order.number.to_s,
120
+ country_code: order.billing_address.country.iso,
121
+ payment_amount: (order.total * 100).to_int
122
+ }
123
+ end
124
+
125
+ def payment_method_params payment_method
126
+ { merchant_account: payment_method.merchant_account,
127
+ skin_code: payment_method.skin_code,
128
+ shared_secret: payment_method.shared_secret,
129
+ ship_before_date: payment_method.ship_before_date
130
+ }
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ module Adyen
3
+ # Used when we have to override functionally inside spree, usually payments,
4
+ # that is a conditional flow only on hpp payments.
5
+ module HppCheck
6
+ def hpp_payment? payment = self
7
+ payment.source.class == Spree::Adyen::HppSource
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ module Spree
2
+ module Adyen
3
+ module URL
4
+ def self.payment_adyen_customer_area_url(psp_reference:, merchant_account:)
5
+ ::URI::HTTPS.build(
6
+ host: "ca-test.adyen.com",
7
+ path: "/ca/ca/accounts/showTx.shtml",
8
+ query:
9
+ { txType: "Payment",
10
+ accountKey: "MerchantAccount.#{merchant_account}",
11
+ pspReference: psp_reference
12
+ }.to_query
13
+ ).to_s
14
+ end
15
+
16
+ def self.modify_search_url(query:)
17
+ ::URI::HTTPS.build(
18
+ host: "ca-test.adyen.com",
19
+ path: "/ca/ca/payments/modifySearch.shtml",
20
+ query:
21
+ { uxEvent: "PAYMENT_SEARCH",
22
+ query: query,
23
+ search: "Search"
24
+ }.to_query
25
+ ).to_s
26
+ end
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,5 @@
1
+ module Spree
2
+ module Adyen
3
+ VERSION = "0.1.2"
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ require "spree/adyen/version"
2
+ require "adyen"
3
+ require "spree_core"
4
+ require "spree/adyen/engine"
5
+ require "spree/adyen/form"
6
+ require "spree/adyen/hpp_check"
@@ -0,0 +1,51 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "spree/adyen/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "solidus-adyen"
8
+ spec.version = Spree::Adyen::VERSION
9
+ spec.authors = ["Dylan Kendal"]
10
+ spec.email = ["dylan@stembolt.com"]
11
+ spec.description = "Adyen HPP payments for Solidus Stores"
12
+ spec.summary = "Adyen HPP payments for Solidus Stores"
13
+ spec.homepage = "https://github.com/StemboltHQ/solidus-adyen"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "adyen", "~> 1.4"
22
+ spec.add_runtime_dependency "solidus_core", "~> 1.0"
23
+ spec.add_runtime_dependency "bourbon"
24
+
25
+ spec.add_development_dependency "solidus", "~> 1.0"
26
+ spec.add_development_dependency "solidus_auth_devise", "~> 1.2"
27
+ spec.add_development_dependency "solidus_sample", "~> 1.0"
28
+
29
+ spec.add_development_dependency "sass-rails", "~> 4.0.2"
30
+ spec.add_development_dependency "coffee-rails"
31
+
32
+ spec.add_development_dependency "sqlite3"
33
+
34
+ spec.add_development_dependency "rspec-rails", "~> 3.3"
35
+ spec.add_development_dependency "rspec-activemodel-mocks"
36
+ spec.add_development_dependency "factory_girl"
37
+ spec.add_development_dependency "shoulda-matchers"
38
+
39
+ spec.add_development_dependency "simplecov"
40
+ spec.add_development_dependency "simplecov-rcov"
41
+
42
+ spec.add_development_dependency "awesome_print"
43
+ spec.add_development_dependency "pry-rails"
44
+ spec.add_development_dependency "better_errors"
45
+ spec.add_development_dependency "binding_of_caller"
46
+ spec.add_development_dependency "pry-stack_explorer"
47
+
48
+ spec.add_development_dependency "capybara"
49
+ spec.add_development_dependency "poltergeist"
50
+ spec.add_development_dependency "launchy"
51
+ end
@@ -0,0 +1,76 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Spree::Admin::RefundsController do
4
+ stub_authorization!
5
+ include_context "mock adyen api", success: true
6
+ routes { Spree::Core::Engine.routes }
7
+
8
+ describe "POST create" do
9
+ subject { post :create, params }
10
+
11
+ let(:params) do
12
+ {
13
+ "refund" => {
14
+ "amount" => amount,
15
+ "refund_reason_id" => reason.id
16
+ },
17
+ "order_id" => order.number,
18
+ "payment_id" => payment.id
19
+ }
20
+ end
21
+
22
+ let(:reason) { create :refund_reason }
23
+ let(:order) { create :order, currency: "EUR" }
24
+ let(:amount) { 100.0 }
25
+ let(:payment_opts) { {state: "completed", amount: 100.0} }
26
+
27
+ before do
28
+ payment.capture_events.create!(amount: 100.0)
29
+ end
30
+
31
+ context "when the payment comes from Adyen Hosted Payment Pages" do
32
+ let(:payment) { create :hpp_payment, order: order, **payment_opts }
33
+
34
+ it "does not create the record" do
35
+ expect { subject }.to_not change { payment.reload.refunds.count }
36
+ end
37
+
38
+ it "sets the success flash" do
39
+ subject
40
+ expect(flash[:success]).to eq "Refund request was received"
41
+ end
42
+
43
+ it "requests the refund" do
44
+ expect_any_instance_of(Spree::Payment).
45
+ to receive(:credit!).
46
+ with(10000, currency: "EUR")
47
+ subject
48
+ end
49
+
50
+ it { is_expected.to have_http_status :redirect }
51
+
52
+ context "and the refund is invalid" do
53
+ let(:amount) { 0 }
54
+
55
+ it "displays an error" do
56
+ is_expected.to have_http_status :ok
57
+ expect(flash[:error]).to be_present
58
+ end
59
+
60
+ it "doesn't attempt to credit the payment" do
61
+ expect_any_instance_of(Spree::Payment).
62
+ to_not receive(:credit!)
63
+ subject
64
+ end
65
+ end
66
+ end
67
+
68
+ context "when any other kind of payment" do
69
+ let(:payment) { create :payment, **payment_opts }
70
+
71
+ it "creates the refund" do
72
+ expect { subject }.to change { payment.reload.refunds.count }.by(1)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Spree::Adyen::HppsController, type: :controller do
4
+ describe "GET directory" do
5
+ let(:order) { create :order }
6
+ let(:payment_method) { create :hpp_gateway }
7
+ let(:parsed_directory_response) { [{
8
+ name: "American Express",
9
+ brandCode: "amex",
10
+ payment_url: "www.test-payment-url.com/amex"}] }
11
+
12
+ before do
13
+ allow(Spree::Adyen::Form).to receive(:payment_methods_from_directory).
14
+ with(order, payment_method).
15
+ and_return(parsed_directory_response)
16
+ end
17
+
18
+ context "html response" do
19
+ subject {
20
+ get :directory,
21
+ order_id: order.id,
22
+ payment_method_id: payment_method.id }
23
+
24
+ it { is_expected.to have_http_status :ok }
25
+ it { is_expected.to render_template "directory" }
26
+ end
27
+
28
+ context "json response" do
29
+ subject {
30
+ get :directory,
31
+ order_id: order.id,
32
+ payment_method_id: payment_method.id,
33
+ format: :json }
34
+
35
+ it { is_expected.to have_http_status :ok }
36
+
37
+ it "renders a json response" do
38
+ subject
39
+ expect(response.body).to eq parsed_directory_response.to_json
40
+ end
41
+ end
42
+ end
43
+ end