solidus-adyen 0.2.2 → 1.0.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
  SHA1:
3
- metadata.gz: b981dfc62f2ab3ffa76996fe091a6ff639b86d32
4
- data.tar.gz: 0372a49ad6ff5763af8c0748315838c7b8976321
3
+ metadata.gz: 30642824e2cf52ec60990cff981d9031976d872b
4
+ data.tar.gz: c591f80c5901703cc01569d15af3617f62077140
5
5
  SHA512:
6
- metadata.gz: 1a2ec3751f1119a2d271fc03f8ace0a8364d6605ea9f68afe71caca65faca6e2d669b0fd2fb52bddb8d98c726b38a2b5ab6bb0d7f400fb1cc7b90032688f33dc
7
- data.tar.gz: 5145598ee3116a7ac02bbdbb7c2eef673f655ec34e52869d0352f4ac0fda0ff0e28f066c0f539138d45397c75db07546912ea49ebc3aeeeee09e67120e8f6d73
6
+ metadata.gz: 376c387db2a66a64c0a543bd3e470328fe3e6462b89f36b6e115cb3306a998c3d7dfbabdce96a2698b5b668a23ae49a18e0c2f99d54a2a3ad3853209213d91da
7
+ data.tar.gz: 5bc39e85ba846957b6ee7b0ad0fef4a9a5f129f5727d05412da6c5c0e689a4521ce62ce453a786200f955c52de80973bf560d715cca875d4c8ef33684c1ef678
@@ -0,0 +1 @@
1
+ 2.2.2
@@ -7,4 +7,5 @@ install:
7
7
  - bundle install
8
8
  script:
9
9
  - bundle exec rake test_app
10
+ - ( cd ./spec/dummy && bundle exec rake solidus-adyen:factory_girl:lint RAILS_ENV=test )
10
11
  - bundle exec rspec
data/Gemfile CHANGED
@@ -1,12 +1,20 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
- gem "solidus", "~> 1.0.0"
4
- gem "solidus_auth_devise", "~> 1.2.0"
3
+ group :development, :test do
4
+ gem "solidus"
5
+ gem "solidus_auth_devise"
6
+
7
+ gem "pg"
8
+ gem "mysql2"
9
+ gem "sqlite3"
10
+ end
5
11
 
6
12
  group :test do
13
+ gem "database_cleaner"
14
+ gem "factory_girl"
7
15
  gem "timecop"
8
- gem "webmock"
9
16
  gem "vcr"
17
+ gem "webmock", "~> 1.24"
10
18
  end
11
19
 
12
20
  gemspec
data/README.md CHANGED
@@ -1,4 +1,7 @@
1
- # Solidus-Adyen [![Build Status](https://travis-ci.org/StemboltHQ/solidus-adyen.svg)](https://travis-ci.org/StemboltHQ/solidus-adyen)
1
+ # Solidus-Adyen [![Build Status](https://travis-ci.org/StemboltHQ/solidus-adyen.svg)](https://travis-ci.org/StemboltHQ/solidus-adyen)
2
+
3
+ **NOTICE** From July 2016 Adyen will no longer support SHA1 HPP's, this extension is _not_ only compatible with the SHA256 skins.
4
+
2
5
  Adds support for Adyen Hosted Payment Page payments to Solidus stores using the
3
6
  [Adyen](https://github.com/wvanbergen/adyen/) gem.
4
7
 
@@ -14,7 +17,7 @@ notification is received from Adyen.
14
17
  # Installation
15
18
  Add this line to your application's Gemfile:
16
19
  ```ruby
17
- gem 'solidus-adyen', '~> 0.1'
20
+ gem 'solidus-adyen', '~> 1.0.0'
18
21
  ```
19
22
 
20
23
  Then run:
@@ -196,20 +199,17 @@ in the view.
196
199
 
197
200
  # Testing
198
201
  ```bash
199
- $ bundle exec rake test_app
202
+ $ DB=postgres bundle exec rake test_app
200
203
  $ rspec
204
+ $ cd spec/dummy
205
+ $ rake solidus-adyen:factory_girl:lint
201
206
  ```
202
207
 
203
208
  # Development
204
209
  My prefered method of setting up a sandbox is with
205
210
  ```bash
206
- $ rake test_app
207
- $ cd spec/dummy
208
- $ rake railties:install:migrations
209
- $ rake db:migrate
210
- $ rake db:seed
211
- $ rake db:spree_sample:load
212
- $ ./bin/rails s
211
+ $ ./bin/bootstrap.sh
212
+ $ ./spec/dummy/bin/rails s
213
213
  ```
214
214
  You will need to reverse tunnel or make your server publicly available by some
215
215
  other means - and update the server communication as well as the skin's url
@@ -217,7 +217,7 @@ with the proper end point to receive notifications.
217
217
 
218
218
  # Test Credit Card Info
219
219
 
220
- https://support.adyen.com/index.php?/Knowledgebase/Article/View/11/0/test-card-numbers
220
+ https://docs.adyen.com/support/integration#testcardnumbers
221
221
 
222
222
  # Terminology and other API information
223
223
  [More info about Adyen can be found here](https://docs.adyen.com/display/TD/3D+Secure).
@@ -10,7 +10,7 @@ module Spree
10
10
  layout false
11
11
 
12
12
  def directory
13
- @brands = Adyen::Form.payment_methods_from_directory(
13
+ @brands = Spree::Adyen::HPP.payment_methods_from_directory(
14
14
  @order,
15
15
  @payment_method)
16
16
 
@@ -43,7 +43,7 @@ module Spree
43
43
  state: "checkout"
44
44
  )
45
45
 
46
- if @order.complete
46
+ if complete
47
47
  redirect_to_order
48
48
  else
49
49
  #TODO void/cancel payment
@@ -52,13 +52,21 @@ module Spree
52
52
  end
53
53
 
54
54
  # If an authorization notification is received before the redirection the
55
- # payment is created there.In this case we just need to assign the addition
55
+ # payment is created there. In this case we just need to assign the addition
56
56
  # parameters received about the source.
57
57
  #
58
58
  # We do this because there is a chance that we never get redirected back
59
59
  # so we need to make sure we complete the payment and order.
60
60
  def confirm_order_already_completed
61
- payment = @order.payments.find_by!(response_code: psp_reference)
61
+ if psp_reference
62
+ payment = @order.payments.find_by!(response_code: psp_reference)
63
+ else
64
+ # If no psp_reference is present but the order is complete then the
65
+ # notification must have completed the order and created the payment.
66
+ # Therefore select the last Adyen payment.
67
+ payment =
68
+ @order.payments.where(source_type: "Spree::Adyen::HppSource").last
69
+ end
62
70
 
63
71
  payment.source.update(source_params)
64
72
 
@@ -66,12 +74,14 @@ module Spree
66
74
  end
67
75
 
68
76
  def redirect_to_order
77
+ @current_order = nil
69
78
  flash.notice = Spree.t(:order_processed_successfully)
79
+ flash['order_completed'] = true
70
80
  redirect_to order_path(@order)
71
81
  end
72
82
 
73
83
  def check_signature
74
- unless ::Adyen::Form.redirect_signature_check(params, @payment_method.shared_secret)
84
+ unless ::Adyen::HPP::Signature.verify(response_params, @payment_method.shared_secret)
75
85
  raise "Payment Method not found."
76
86
  end
77
87
  end
@@ -90,15 +100,23 @@ module Spree
90
100
  end
91
101
 
92
102
  def source_params
103
+ adyen_permitted_params
104
+ end
105
+
106
+ def response_params
107
+ adyen_permitted_params
108
+ end
109
+
110
+ def adyen_permitted_params
93
111
  params.permit(
94
112
  :authResult,
95
- :pspReference,
96
113
  :merchantReference,
97
- :skinCode,
114
+ :merchantReturnData,
98
115
  :merchantSig,
99
116
  :paymentMethod,
117
+ :pspReference,
100
118
  :shopperLocale,
101
- :merchantReturnData)
119
+ :skinCode)
102
120
  end
103
121
 
104
122
  def order_number
@@ -108,5 +126,10 @@ module Spree
108
126
  def psp_reference
109
127
  params[:pspReference]
110
128
  end
129
+
130
+ def complete
131
+ @order.contents.advance
132
+ @order.complete
133
+ end
111
134
  end
112
135
  end
@@ -83,7 +83,18 @@ class AdyenNotification < ActiveRecord::Base
83
83
  end
84
84
 
85
85
  def payment
86
- Spree::Payment.find_by response_code: original_reference || psp_reference
86
+ reference = original_reference || psp_reference
87
+ payment_with_reference = Spree::Payment.find_by response_code: reference
88
+ return payment_with_reference if payment_with_reference
89
+
90
+ # If no reference take the last payment in the associated order where the
91
+ # response_code was nil.
92
+ if order
93
+ order
94
+ .payments
95
+ .where(source_type: "Spree::Adyen::HppSource", response_code: nil)
96
+ .last
97
+ end
87
98
  end
88
99
 
89
100
  # Returns true if this notification is an AUTHORISATION notification
@@ -67,7 +67,6 @@ module Spree
67
67
  end
68
68
 
69
69
  def process &block
70
- check_environment
71
70
  response = nil
72
71
 
73
72
  Spree::Payment.transaction do
@@ -77,7 +77,7 @@ module Spree
77
77
 
78
78
  elsif notification.refund?
79
79
  payment.refunds.create!(
80
- amount: notification.value / 100, # cents to dollars
80
+ amount: notification.value / 100.0, # cents to dollars
81
81
  transaction_id: notification.psp_reference,
82
82
  refund_reason_id: ::Spree::RefundReason.first.id # FIXME
83
83
  )
@@ -89,6 +89,13 @@ module Spree
89
89
 
90
90
  # normal event is defined as just AUTHORISATION
91
91
  def handle_normal_event
92
+ # Payment may not have psp_reference. Add this from notification if it
93
+ # doesn't have one.
94
+ unless self.payment.response_code
95
+ payment.response_code = notification.psp_reference
96
+ payment.save
97
+ end
98
+
92
99
  if notification.auto_captured?
93
100
  complete_payment!
94
101
 
@@ -132,6 +139,7 @@ module Spree
132
139
  order: order
133
140
  )
134
141
 
142
+ order.contents.advance
135
143
  order.complete
136
144
  payment
137
145
  end
@@ -142,7 +150,6 @@ module Spree
142
150
  notification.order.present? &&
143
151
  payment.nil?
144
152
  end
145
-
146
153
  end
147
154
  end
148
155
  end
@@ -7,6 +7,7 @@ module Spree
7
7
  preference :api_username, :string
8
8
  preference :api_password, :string
9
9
  preference :merchant_account, :string
10
+ preference :restricted_brand_codes, :string, default: ''
10
11
 
11
12
  def merchant_account
12
13
  ENV["ADYEN_MERCHANT_ACCOUNT"] || preferred_merchant_account
@@ -73,6 +74,10 @@ module Spree
73
74
  psp_reference)
74
75
  end
75
76
 
77
+ def restricted_brand_codes
78
+ preferred_restricted_brand_codes.split(',').compact.uniq
79
+ end
80
+
76
81
  private
77
82
 
78
83
  def handle_response response, original_reference
@@ -0,0 +1,8 @@
1
+ #!/bin/bash
2
+ bundle exec rake test_app DB=postgres
3
+ cd spec/dummy
4
+ bundle exec rake db:schema:load
5
+ bundle exec rake db:seed AUTO_ACCEPT=1
6
+ bundle exec rake spree_sample:load
7
+
8
+ sed -i.bak "s/USD/EUR/" config/initializers/spree.rb
@@ -21,3 +21,4 @@ en:
21
21
  method only supports manual refunds.
22
22
  Please attempt to refund this payment through the Adyen customer area
23
23
  or contact an Adyen representative to assist.
24
+ restricted_brand_codes: "Restricted Brand Codes (comma delimited, no spaces)"
@@ -2,5 +2,5 @@ require "spree/adyen/version"
2
2
  require "adyen"
3
3
  require "spree_core"
4
4
  require "spree/adyen/engine"
5
- require "spree/adyen/form"
5
+ require "spree/adyen/hpp"
6
6
  require "spree/adyen/hpp_check"
@@ -2,8 +2,8 @@ require "json"
2
2
 
3
3
  module Spree
4
4
  module Adyen
5
- module Form
6
- Form = ::Adyen::Form
5
+ module HPP
6
+ HPP = ::Adyen::HPP
7
7
  UrlHelper = Object.new.extend ActionView::Helpers::UrlHelper
8
8
 
9
9
  class << self
@@ -41,15 +41,21 @@ module Spree
41
41
  end
42
42
 
43
43
  def endpoint_url endpoint, order, payment_method, opts = {}
44
- base = URI::parse(url payment_method, endpoint)
44
+ adyen_request = hpp_request order, payment_method, opts
45
45
 
46
- URI::HTTPS.build(
47
- host: base.host,
48
- path: base.path,
49
- query: params(order, payment_method).merge(opts).to_query)
46
+ URI::parse("#{adyen_request.url(endpoint)}?#{adyen_request.flat_payment_parameters.to_query}")
50
47
  end
51
48
 
52
49
  private
50
+ def hpp_request order, payment_method, opts
51
+ server = payment_method.preferences.fetch(:server)
52
+ parameters = params(order, payment_method).merge(opts)
53
+
54
+ HPP::Request.new(parameters, environment: server,
55
+ skin: { skin_code: payment_method.skin_code },
56
+ shared_secret: payment_method.shared_secret)
57
+ end
58
+
53
59
  def payment_methods order, payment_method
54
60
  url = directory_url(order, payment_method)
55
61
 
@@ -60,18 +66,16 @@ module Spree
60
66
  )
61
67
  end
62
68
 
63
- def url payment_method, endpoint
64
- server = payment_method.preferences.fetch(:server)
65
- Form.url(server, endpoint)
66
- end
67
-
68
69
  def form_payment_methods_and_urls response, order, payment_method
69
70
  response.fetch("paymentMethods").map do |brand|
71
+ next unless payment_method_allows_brand_code?(payment_method, brand['brandCode'])
72
+
70
73
  issuers = brand.fetch("issuers", []).map do |issuer|
71
74
  form_issuer(issuer, order, payment_method, brand)
72
75
  end
76
+
73
77
  form_payment_method(brand, order, payment_method, issuers)
74
- end
78
+ end.compact
75
79
  end
76
80
 
77
81
  def form_issuer issuer, order, payment_method, brand
@@ -100,16 +104,20 @@ module Spree
100
104
  end
101
105
 
102
106
  def params order, payment_method
103
- merchant_return_data = [
104
- order.guest_token,
105
- payment_method.id
106
- ].
107
- join("|")
108
-
109
- Form.flat_payment_parameters default_params.
107
+ default_params.
110
108
  merge(order_params order).
111
109
  merge(payment_method_params payment_method).
112
- merge(merchant_return_data: merchant_return_data)
110
+ merge(merchant_return_data order, payment_method)
111
+ end
112
+
113
+ def merchant_return_data order, payment_method
114
+ { merchantReturnData: [order.guest_token, payment_method.id].join("|") }
115
+ end
116
+
117
+ def payment_method_allows_brand_code? payment_method, brand_code
118
+ return true if payment_method.restricted_brand_codes.empty?
119
+
120
+ payment_method.restricted_brand_codes.include?(brand_code)
113
121
  end
114
122
 
115
123
  # TODO set this in the adyen config
@@ -123,7 +131,8 @@ module Spree
123
131
  merchant_reference: order.number.to_s,
124
132
  country_code: order.billing_address.country.iso,
125
133
  payment_amount: (order.total * 100).to_int,
126
- shopper_locale: I18n.locale.to_s.gsub("-", "_")
134
+ shopper_locale: I18n.locale.to_s.gsub("-", "_"),
135
+ shopper_email: order.email
127
136
  }
128
137
  end
129
138
 
@@ -1,5 +1,5 @@
1
1
  module Spree
2
2
  module Adyen
3
- VERSION = "0.2.2"
3
+ VERSION = "1.0.0"
4
4
  end
5
5
  end
@@ -0,0 +1,17 @@
1
+ namespace :"solidus-adyen" do
2
+ namespace :factory_girl do
3
+ desc "Verify that all FactoryGirl factories are valid"
4
+ task lint: :environment do
5
+ if Rails.env.test?
6
+ begin
7
+ DatabaseCleaner.start
8
+ FactoryGirl.lint
9
+ ensure
10
+ DatabaseCleaner.clean
11
+ end
12
+ else
13
+ system("bundle exec rake soldius-adyen:factory_girl:lint RAILS_ENV='test'")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -18,31 +18,30 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_runtime_dependency "adyen", "~> 1.4"
22
- spec.add_runtime_dependency "solidus_core", "~> 1.0.0"
21
+ spec.add_runtime_dependency "adyen", "~> 2.2.0"
22
+ spec.add_runtime_dependency "solidus_core", "~> 1.1"
23
23
  spec.add_runtime_dependency "bourbon"
24
24
 
25
- spec.add_development_dependency "sass-rails", "~> 4.0.2"
25
+ spec.add_development_dependency "sass-rails"
26
26
  spec.add_development_dependency "coffee-rails"
27
27
 
28
28
  spec.add_development_dependency "pg"
29
29
 
30
30
  spec.add_development_dependency "rspec-rails", "~> 3.3"
31
31
  spec.add_development_dependency "rspec-activemodel-mocks"
32
- spec.add_development_dependency "factory_girl"
33
32
  spec.add_development_dependency "shoulda-matchers"
34
33
 
35
34
  spec.add_development_dependency "simplecov"
36
35
  spec.add_development_dependency "simplecov-rcov"
37
36
 
38
37
  spec.add_development_dependency "awesome_print"
39
- spec.add_development_dependency "pry-rails"
40
38
  spec.add_development_dependency "better_errors"
41
39
  spec.add_development_dependency "binding_of_caller"
40
+ spec.add_development_dependency "pry-byebug"
42
41
  spec.add_development_dependency "pry-stack_explorer"
42
+ spec.add_development_dependency "pry-rails"
43
43
 
44
44
  spec.add_development_dependency "capybara"
45
45
  spec.add_development_dependency "poltergeist"
46
46
  spec.add_development_dependency "launchy"
47
- spec.add_development_dependency "database_cleaner"
48
47
  end
@@ -10,7 +10,7 @@ RSpec.describe Spree::Adyen::HppsController, type: :controller do
10
10
  payment_url: "www.test-payment-url.com/amex"}] }
11
11
 
12
12
  before do
13
- allow(Spree::Adyen::Form).to receive(:payment_methods_from_directory).
13
+ allow(Spree::Adyen::HPP).to receive(:payment_methods_from_directory).
14
14
  with(order, payment_method).
15
15
  and_return(parsed_directory_response)
16
16
  end
@@ -33,7 +33,7 @@ RSpec.describe Spree::Adyen::HppsController, type: :controller do
33
33
  format: :json }
34
34
 
35
35
  it { is_expected.to have_http_status :ok }
36
-
36
+
37
37
  it "renders a json response" do
38
38
  subject
39
39
  expect(response.body).to eq parsed_directory_response.to_json
@@ -106,6 +106,7 @@ RSpec.describe Spree::AdyenRedirectController, type: :controller do
106
106
 
107
107
  create(:hpp_payment, source: source, order: order)
108
108
 
109
+ order.contents.advance
109
110
  order.complete
110
111
  end
111
112
 
@@ -2,7 +2,6 @@ FactoryGirl.define do
2
2
  factory :spree_gateway_adyen_hpp, aliases: [:hpp_gateway],
3
3
  class: "Spree::Gateway::AdyenHPP" do
4
4
  name "Adyen"
5
- environment "test"
6
5
  display_on "both"
7
6
  preferences(
8
7
  skin_code: "XXXXX",
@@ -11,6 +10,10 @@ FactoryGirl.define do
11
10
  days_to_ship: 3
12
11
  )
13
12
 
13
+ trait :with_restricted_brand_codes do
14
+ preferred_restricted_brand_codes 'paypal'
15
+ end
16
+
14
17
  trait :env_configured do
15
18
  preferred_test_mode true
16
19
  preferred_days_to_ship 1
@@ -1,6 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
- RSpec.describe Spree::Adyen::Form do
3
+ RSpec.describe Spree::Adyen::HPP do
4
4
  let(:order) { create :order, total: 39.98 }
5
5
  let(:payment_method) { create :hpp_gateway, preferences: preferences }
6
6
  let(:preferences){
@@ -29,10 +29,11 @@ RSpec.describe Spree::Adyen::Form do
29
29
  country_code: order.billing_address.country.iso,
30
30
  merchant_return_data: merchant_return_data,
31
31
  payment_amount: 3998,
32
- shopper_locale: locale
32
+ shopper_locale: locale,
33
+ shopper_email: order.email
33
34
  }
34
35
 
35
- ::Adyen::Form.redirect_url(redirect_params)
36
+ ::Adyen::HPP::Request.new(redirect_params, skin: { skin_code: 'XXXXXX' }).redirect_url
36
37
  end
37
38
 
38
39
  let(:merchant_return_data) do
@@ -170,6 +171,35 @@ RSpec.describe Spree::Adyen::Form do
170
171
  ]
171
172
  end
172
173
  end
174
+
175
+ context "when payment_method specifies restricted brand_codes" do
176
+ let(:adyen_response) {
177
+ {
178
+ "paymentMethods" => [
179
+ {
180
+ "brandCode" => "mc",
181
+ "name" => "MasterCard"
182
+ }, {
183
+ "brandCode" => "paypal",
184
+ "name" => "PayPal"
185
+ }
186
+ ]
187
+ }
188
+ }
189
+
190
+ let(:payment_method) { create(:hpp_gateway, :with_restricted_brand_codes) }
191
+
192
+ it "will only return paypal brand_code" do
193
+ expect(subject).to eq [
194
+ {
195
+ name: "PayPal",
196
+ brand_code: "paypal",
197
+ payment_url: payment_url,
198
+ issuers: []
199
+ }
200
+ ]
201
+ end
202
+ end
173
203
  end
174
204
 
175
205
  describe "details_url" do
@@ -88,42 +88,72 @@ RSpec.describe "Notification processing", type: :request do
88
88
 
89
89
  describe "full redirect, auth, capture flow", truncation: true do
90
90
  it "creates a payment, completes order, captures payment" do
91
- authorize_request = lambda do
92
- post "/adyen/notify", auth_params, headers
93
- expect(response).to have_http_status :ok
94
- expect(response.body).to eq "[accepted]"
95
- end
91
+ VCR.use_cassette "adyen capture" do
92
+ expect { initial_authorization }.
93
+ to change { order.payments.count }.by(1).
94
+ and change { order.reload.state}.to("complete").
95
+ and change { AdyenNotification.count }.by(1)
96
96
 
97
- redirect_request = lambda do
98
- get "/checkout/payment/adyen", checkout_params, headers
99
- expect(response).to have_http_status :redirect
97
+ capture_request
100
98
  end
99
+ end
100
+ end
101
101
 
102
- capture_request = lambda do
103
- expect do
104
- post "/adyen/notify", capture_params, headers
105
- end.
106
- to change { order.payments.last.reload.state }.
107
- from("processing").
108
- to("completed")
102
+ context "no psp reference in redirect" do
103
+ describe "full redirect, auth, capture flow", truncation: true do
104
+ let(:checkout_params) do
105
+ {
106
+ "merchantReference" => "R207199925",
107
+ "skinCode" => "xxxxxxxx",
108
+ "shopperLocale" => "en",
109
+ "paymentMethod" => "amex",
110
+ "authResult" => "AUTHORISED",
111
+ "merchantReturnData" => "adKbcFeXxOVE76UJRDF88g|#{payment_method.id}",
112
+ "merchantSig" => "SBdhua18U+8xkPmK/a/8VprF230="
113
+ }
109
114
  end
110
115
 
111
- VCR.use_cassette "adyen capture" do
112
- expect do
113
- # these come in at the same time
114
- [
115
- Thread.new(&authorize_request),
116
- Thread.new(&redirect_request)
117
- ].map(&:join)
118
- # typically get a duplicate auth notification
119
- authorize_request.call
120
- end.
121
- to change { order.payments.count }.by(1).
122
- and change { order.reload.state}.to("complete").
123
- and change { AdyenNotification.count }.by(1)
116
+ it "adds in psp reference to payment" do
117
+ VCR.use_cassette "adyen capture" do
118
+ expect { initial_authorization }.
119
+ to change { order.payments.count }.by(1).
120
+ and change { order.reload.state}.to("complete").
121
+ and change { AdyenNotification.count }.by(1)
124
122
 
125
- capture_request.call
123
+ capture_request
124
+ expect(order.payments.first.response_code).to eq "7914483013255061"
125
+ end
126
126
  end
127
127
  end
128
128
  end
129
+
130
+ def initial_authorization
131
+ # these come in at the same time
132
+ [
133
+ Thread.new { authorize_request },
134
+ Thread.new { redirect_request }
135
+ ].map(&:join)
136
+ # typically get a duplicate auth notification
137
+ authorize_request
138
+ end
139
+
140
+ def authorize_request
141
+ post "/adyen/notify", auth_params, headers
142
+ expect(response).to have_http_status :ok
143
+ expect(response.body).to eq "[accepted]"
144
+ end
145
+
146
+ def redirect_request
147
+ response_code = get "/checkout/payment/adyen", checkout_params, headers
148
+ expect(response_code).to eq 302
149
+ end
150
+
151
+ def capture_request
152
+ expect do
153
+ post "/adyen/notify", capture_params, headers
154
+ end.
155
+ to change { order.payments.last.reload.state }.
156
+ from("processing").
157
+ to("completed")
158
+ end
129
159
  end
@@ -25,6 +25,24 @@ RSpec.describe AdyenNotification do
25
25
  let(:attr) { :psp_reference }
26
26
  include_examples "finds the payment"
27
27
  end
28
+
29
+ context "payment with no reference" do
30
+ let!(:payment) { create :payment, response_code: nil }
31
+
32
+ context "normal notification" do
33
+ let!(:notification) {
34
+ described_class.new :merchant_reference => payment.order.number
35
+ }
36
+ include_examples "finds the payment"
37
+ end
38
+ end
39
+
40
+ context "no connected order" do
41
+ let!(:notification) {
42
+ described_class.new :merchant_reference => "notarealorder"
43
+ }
44
+ it { is_expected.to eq nil }
45
+ end
28
46
  end
29
47
 
30
48
  describe "#build" do
@@ -11,7 +11,7 @@ RSpec.describe Spree::Adyen::HppSource do
11
11
  create :hpp_source,
12
12
  psp_reference: "999999999",
13
13
  merchant_reference: "R11111111",
14
- payment: create(:hpp_payment)
14
+ payment: create(:hpp_payment, amount: 1)
15
15
  end
16
16
 
17
17
  describe ".actions" do
@@ -200,6 +200,11 @@ RSpec.describe Spree::Adyen::NotificationProcessor do
200
200
  from(0).
201
201
  to(1)
202
202
  end
203
+
204
+ it "creates a refund of the correct value" do
205
+ subject
206
+ expect(payment.reload.refunds.last.amount).to eq 23.99
207
+ end
203
208
  end
204
209
 
205
210
  context "when refunded from Solidus" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidus-adyen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dylan Kendal
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-26 00:00:00.000000000 Z
11
+ date: 2016-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: adyen
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.4'
19
+ version: 2.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.4'
26
+ version: 2.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: solidus_core
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.0.0
33
+ version: '1.1'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.0.0
40
+ version: '1.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bourbon
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: sass-rails
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 4.0.2
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 4.0.2
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: coffee-rails
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -122,20 +122,6 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: factory_girl
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
125
  - !ruby/object:Gem::Dependency
140
126
  name: shoulda-matchers
141
127
  requirement: !ruby/object:Gem::Requirement
@@ -193,7 +179,7 @@ dependencies:
193
179
  - !ruby/object:Gem::Version
194
180
  version: '0'
195
181
  - !ruby/object:Gem::Dependency
196
- name: pry-rails
182
+ name: better_errors
197
183
  requirement: !ruby/object:Gem::Requirement
198
184
  requirements:
199
185
  - - ">="
@@ -207,7 +193,7 @@ dependencies:
207
193
  - !ruby/object:Gem::Version
208
194
  version: '0'
209
195
  - !ruby/object:Gem::Dependency
210
- name: better_errors
196
+ name: binding_of_caller
211
197
  requirement: !ruby/object:Gem::Requirement
212
198
  requirements:
213
199
  - - ">="
@@ -221,7 +207,7 @@ dependencies:
221
207
  - !ruby/object:Gem::Version
222
208
  version: '0'
223
209
  - !ruby/object:Gem::Dependency
224
- name: binding_of_caller
210
+ name: pry-byebug
225
211
  requirement: !ruby/object:Gem::Requirement
226
212
  requirements:
227
213
  - - ">="
@@ -249,7 +235,7 @@ dependencies:
249
235
  - !ruby/object:Gem::Version
250
236
  version: '0'
251
237
  - !ruby/object:Gem::Dependency
252
- name: capybara
238
+ name: pry-rails
253
239
  requirement: !ruby/object:Gem::Requirement
254
240
  requirements:
255
241
  - - ">="
@@ -263,7 +249,7 @@ dependencies:
263
249
  - !ruby/object:Gem::Version
264
250
  version: '0'
265
251
  - !ruby/object:Gem::Dependency
266
- name: poltergeist
252
+ name: capybara
267
253
  requirement: !ruby/object:Gem::Requirement
268
254
  requirements:
269
255
  - - ">="
@@ -277,7 +263,7 @@ dependencies:
277
263
  - !ruby/object:Gem::Version
278
264
  version: '0'
279
265
  - !ruby/object:Gem::Dependency
280
- name: launchy
266
+ name: poltergeist
281
267
  requirement: !ruby/object:Gem::Requirement
282
268
  requirements:
283
269
  - - ">="
@@ -291,7 +277,7 @@ dependencies:
291
277
  - !ruby/object:Gem::Version
292
278
  version: '0'
293
279
  - !ruby/object:Gem::Dependency
294
- name: database_cleaner
280
+ name: launchy
295
281
  requirement: !ruby/object:Gem::Requirement
296
282
  requirements:
297
283
  - - ">="
@@ -308,14 +294,15 @@ description: Adyen HPP payments for Solidus Stores
308
294
  email:
309
295
  - dylan@stembolt.com
310
296
  executables:
297
+ - bootstrap.sh
311
298
  - checkout.rb
312
- - regen.sh
313
299
  extensions: []
314
300
  extra_rdoc_files: []
315
301
  files:
316
302
  - ".gitignore"
317
303
  - ".rubocop.yml"
318
304
  - ".rubocop_todo.yml"
305
+ - ".ruby-version"
319
306
  - ".travis.yml"
320
307
  - CHANGELOG.md
321
308
  - Gemfile
@@ -353,8 +340,8 @@ files:
353
340
  - app/views/spree/adyen/communication/_communication.html.erb
354
341
  - app/views/spree/adyen/hpps/directory.html.erb
355
342
  - app/views/spree/checkout/payment/_adyen.html.erb
343
+ - bin/bootstrap.sh
356
344
  - bin/checkout.rb
357
- - bin/regen.sh
358
345
  - config/initializers/solidus_adyen.rb
359
346
  - config/locales/en.yml
360
347
  - config/routes.rb
@@ -368,10 +355,11 @@ files:
368
355
  - lib/solidus-adyen.rb
369
356
  - lib/spree/adyen.rb
370
357
  - lib/spree/adyen/engine.rb
371
- - lib/spree/adyen/form.rb
358
+ - lib/spree/adyen/hpp.rb
372
359
  - lib/spree/adyen/hpp_check.rb
373
360
  - lib/spree/adyen/url.rb
374
361
  - lib/spree/adyen/version.rb
362
+ - lib/tasks/solidus-adyen/factory_girl.rake
375
363
  - solidus-adyen.gemspec
376
364
  - spec/cassettes/adyen_capture.yml
377
365
  - spec/controllers/concerns/spree/adyen/admin/refunds_controller_spec.rb
@@ -415,7 +403,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
415
403
  version: '0'
416
404
  requirements: []
417
405
  rubyforge_project:
418
- rubygems_version: 2.4.5.1
406
+ rubygems_version: 2.4.5
419
407
  signing_key:
420
408
  specification_version: 4
421
409
  summary: Adyen HPP payments for Solidus Stores
@@ -1 +0,0 @@
1
- rm -rf spec/dummy && bundle install && rake test_app && cd spec/dummy && rake db:migrate && rails s