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 +4 -4
- data/.ruby-version +1 -0
- data/.travis.yml +1 -0
- data/Gemfile +12 -4
- data/README.md +11 -11
- data/app/controllers/spree/adyen/hpps_controller.rb +1 -1
- data/app/controllers/spree/adyen_redirect_controller.rb +30 -7
- data/app/models/adyen_notification.rb +12 -1
- data/app/models/concerns/spree/adyen/payment.rb +0 -1
- data/app/models/spree/adyen/notification_processor.rb +9 -2
- data/app/models/spree/gateway/adyen_hpp.rb +5 -0
- data/bin/bootstrap.sh +8 -0
- data/config/locales/en.yml +1 -0
- data/lib/spree/adyen.rb +1 -1
- data/lib/spree/adyen/{form.rb → hpp.rb} +31 -22
- data/lib/spree/adyen/version.rb +1 -1
- data/lib/tasks/solidus-adyen/factory_girl.rake +17 -0
- data/solidus-adyen.gemspec +5 -6
- data/spec/controllers/spree/adyen/hpps_controller_spec.rb +2 -2
- data/spec/controllers/spree/adyen_redirect_controller_spec.rb +1 -0
- data/spec/factories/spree_gateway_adyen_hpp.rb +4 -1
- data/spec/lib/spree/adyen/form_spec.rb +33 -3
- data/spec/lib/tasks/requests/notification_processing_spec.rb +59 -29
- data/spec/models/adyen_notification_spec.rb +18 -0
- data/spec/models/spree/adyen/hpp_source_spec.rb +1 -1
- data/spec/models/spree/adyen/notification_processor_spec.rb +5 -0
- metadata +23 -35
- data/bin/regen.sh +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30642824e2cf52ec60990cff981d9031976d872b
|
4
|
+
data.tar.gz: c591f80c5901703cc01569d15af3617f62077140
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 376c387db2a66a64c0a543bd3e470328fe3e6462b89f36b6e115cb3306a998c3d7dfbabdce96a2698b5b668a23ae49a18e0c2f99d54a2a3ad3853209213d91da
|
7
|
+
data.tar.gz: 5bc39e85ba846957b6ee7b0ad0fef4a9a5f129f5727d05412da6c5c0e689a4521ce62ce453a786200f955c52de80973bf560d715cca875d4c8ef33684c1ef678
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.2
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,12 +1,20 @@
|
|
1
|
-
source "
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
|
-
|
4
|
-
gem "
|
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.
|
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
|
-
$
|
207
|
-
$
|
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://
|
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).
|
@@ -43,7 +43,7 @@ module Spree
|
|
43
43
|
state: "checkout"
|
44
44
|
)
|
45
45
|
|
46
|
-
if
|
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
|
-
|
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::
|
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
|
-
:
|
114
|
+
:merchantReturnData,
|
98
115
|
:merchantSig,
|
99
116
|
:paymentMethod,
|
117
|
+
:pspReference,
|
100
118
|
:shopperLocale,
|
101
|
-
:
|
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
|
-
|
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
|
@@ -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
|
data/bin/bootstrap.sh
ADDED
data/config/locales/en.yml
CHANGED
data/lib/spree/adyen.rb
CHANGED
@@ -2,8 +2,8 @@ require "json"
|
|
2
2
|
|
3
3
|
module Spree
|
4
4
|
module Adyen
|
5
|
-
module
|
6
|
-
|
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
|
-
|
44
|
+
adyen_request = hpp_request order, payment_method, opts
|
45
45
|
|
46
|
-
URI::
|
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
|
-
|
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
|
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
|
|
data/lib/spree/adyen/version.rb
CHANGED
@@ -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
|
data/solidus-adyen.gemspec
CHANGED
@@ -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", "~>
|
22
|
-
spec.add_runtime_dependency "solidus_core", "~> 1.
|
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"
|
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::
|
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
|
@@ -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::
|
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
|
-
|
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
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
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
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
-
|
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
|
@@ -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.
|
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:
|
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:
|
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:
|
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.
|
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.
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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/
|
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
|
406
|
+
rubygems_version: 2.4.5
|
419
407
|
signing_key:
|
420
408
|
specification_version: 4
|
421
409
|
summary: Adyen HPP payments for Solidus Stores
|
data/bin/regen.sh
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rm -rf spec/dummy && bundle install && rake test_app && cd spec/dummy && rake db:migrate && rails s
|