solidus-adyen 0.2.2 → 1.0.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.
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