adyen 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +2 -0
- data/README.rdoc +13 -22
- data/adyen.gemspec +12 -5
- data/lib/adyen.rb +2 -1
- data/lib/adyen/api.rb +42 -20
- data/lib/adyen/api/payment_service.rb +12 -10
- data/lib/adyen/api/recurring_service.rb +44 -16
- data/lib/adyen/api/response.rb +7 -0
- data/lib/adyen/api/simple_soap_client.rb +15 -10
- data/lib/adyen/api/templates/recurring_service.rb +12 -0
- data/lib/adyen/templates/notification_model.rb +2 -2
- data/spec/api/api_spec.rb +11 -0
- data/spec/api/payment_service_spec.rb +12 -13
- data/spec/api/recurring_service_spec.rb +42 -2
- data/spec/api/response_spec.rb +24 -0
- data/spec/api/simple_soap_client_spec.rb +51 -9
- data/spec/api/spec_helper.rb +15 -0
- data/spec/functional/api_spec.rb +17 -8
- data/spec/spec_helper.rb +1 -3
- data/tasks/github-gem.rake +7 -5
- metadata +22 -16
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.rdoc
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Package to simplify including the Adyen payments services into a Ruby on Rails application.
|
4
4
|
|
5
|
+
Visit the wiki for documentation: https://github.com/wvanbergen/adyen/wiki.
|
6
|
+
|
5
7
|
Adyen integration relies on three modes of communication between Adyen, your server and
|
6
8
|
your client/customer:
|
7
9
|
|
@@ -13,30 +15,9 @@ This library aims to ease the implementation of all these modes into your applic
|
|
13
15
|
Moreover, it provides matchers, assertions and mocks to make it easier to implement an
|
14
16
|
automated test suite to assert the integration is working correctly.
|
15
17
|
|
16
|
-
== Installation
|
17
|
-
|
18
|
-
<b>Bundler / Rails 3</b>: Add the following line to your <tt>Gemfile</tt>:
|
19
|
-
|
20
|
-
gem 'adyen'
|
21
|
-
|
22
|
-
<b>Rails 2.x</b>: Add the following line to your <tt>environment.rb</tt> and run <tt>rake gems:install</tt>
|
23
|
-
to make the Adyen functionality available in your Rails project:
|
24
|
-
|
25
|
-
config.gem 'adyen'
|
26
|
-
|
27
|
-
The Adyen gem will happily use REXML for communication with Adyen’s SOAP API, however, if
|
28
|
-
you have the Nokogiri gem installed and required the gem will use that for performance.
|
29
|
-
|
30
|
-
== Generators
|
31
|
-
|
32
|
-
The gem ships with a generator for Rails 3. To create an ActiveRecord migration, mode, and
|
33
|
-
ActionController for the notifications send by Adyen, run the following:
|
34
|
-
|
35
|
-
$ rails generate adyen:notification
|
36
|
-
|
37
18
|
== Usage
|
38
19
|
|
39
|
-
See the project wiki on
|
20
|
+
See the project wiki on https://github.com/wvanbergen/adyen/wiki to get started. Complete
|
40
21
|
RDoc documentation for the project can be found on http://rdoc.info/projects/wvanbergen/adyen.
|
41
22
|
|
42
23
|
* For more information about Adyen, see http://www.adyen.com
|
@@ -49,3 +30,13 @@ This package is written by Michel Barbosa and Willem van Bergen for Floorplanner
|
|
49
30
|
made public under the MIT license (see LICENSE). Its is currently maintained by Willem van
|
50
31
|
Bergen, Stefan Borsje and Eloy Duran. We are not affiliated with Adyen B.V. The software
|
51
32
|
comes without warranty of any kind, so use at your own risk.
|
33
|
+
|
34
|
+
Contributions are welcomed; this is very much a scratch your own itch project. Some notes:
|
35
|
+
|
36
|
+
* Fork the project, implement your stuff and issue a pull request. Topic branches not necessary.
|
37
|
+
* All functionality must include tests and preferably documentation.
|
38
|
+
* New SOAP API calls should include functional tests that actually test if the call is working.
|
39
|
+
Adyen has a nasty tendency to switch things up every now and then, so this is vital.
|
40
|
+
|
41
|
+
Please visit the changelog at https://github.com/wvanbergen/adyen/wiki/Changelog to see the
|
42
|
+
changes in the different releases.
|
data/adyen.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'adyen'
|
3
|
-
s.version = "1.
|
4
|
-
s.date = "2011-
|
3
|
+
s.version = "1.3.0"
|
4
|
+
s.date = "2011-10-10"
|
5
5
|
|
6
6
|
s.summary = "Integrate Adyen payment services in your Ruby on Rails application."
|
7
7
|
s.description = <<-EOS
|
@@ -16,15 +16,22 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.homepage = 'http://github.com/wvanbergen/adyen/wiki'
|
17
17
|
|
18
18
|
s.add_development_dependency('rake')
|
19
|
-
s.add_development_dependency('rspec', '~> 2
|
20
|
-
s.add_development_dependency('nokogiri')
|
19
|
+
s.add_development_dependency('rspec', '~> 2')
|
21
20
|
s.add_development_dependency('rails', '>= 2.3')
|
22
21
|
|
22
|
+
if RUBY_PLATFORM == 'java'
|
23
|
+
s.add_development_dependency('nokogiri', '~> 1.4.6')
|
24
|
+
else
|
25
|
+
s.add_development_dependency('nokogiri')
|
26
|
+
end
|
27
|
+
|
28
|
+
s.add_runtime_dependency('jruby-openssl') if RUBY_PLATFORM == 'java'
|
29
|
+
|
23
30
|
s.requirements << 'Having Nokogiri installed will speed up XML handling when using the SOAP API.'
|
24
31
|
|
25
32
|
s.rdoc_options << '--title' << s.name << '--main' << 'README.rdoc' << '--line-numbers' << '--inline-source'
|
26
33
|
s.extra_rdoc_files = ['README.rdoc']
|
27
34
|
|
28
|
-
s.files = %w(.gitignore .kick LICENSE README.rdoc Rakefile TODO adyen.gemspec lib/adyen.rb lib/adyen/api.rb lib/adyen/api/cacert.pem lib/adyen/api/payment_service.rb lib/adyen/api/recurring_service.rb lib/adyen/api/response.rb lib/adyen/api/simple_soap_client.rb lib/adyen/api/templates/payment_service.rb lib/adyen/api/templates/recurring_service.rb lib/adyen/api/test_helpers.rb lib/adyen/api/xml_querier.rb lib/adyen/configuration.rb lib/adyen/encoding.rb lib/adyen/form.rb lib/adyen/formatter.rb lib/adyen/matchers.rb lib/adyen/notification_generator.rb lib/adyen/railtie.rb lib/adyen/templates/notification_migration.rb lib/adyen/templates/notification_model.rb spec/adyen_spec.rb spec/api/api_spec.rb spec/api/payment_service_spec.rb spec/api/recurring_service_spec.rb spec/api/response_spec.rb spec/api/simple_soap_client_spec.rb spec/api/spec_helper.rb spec/api/test_helpers_spec.rb spec/form_spec.rb spec/functional/api_spec.rb spec/functional/initializer.rb.sample spec/spec_helper.rb tasks/github-gem.rake yard_extensions.rb)
|
35
|
+
s.files = %w(.gitignore .kick .travis.yml Gemfile LICENSE README.rdoc Rakefile TODO adyen.gemspec lib/adyen.rb lib/adyen/api.rb lib/adyen/api/cacert.pem lib/adyen/api/payment_service.rb lib/adyen/api/recurring_service.rb lib/adyen/api/response.rb lib/adyen/api/simple_soap_client.rb lib/adyen/api/templates/payment_service.rb lib/adyen/api/templates/recurring_service.rb lib/adyen/api/test_helpers.rb lib/adyen/api/xml_querier.rb lib/adyen/configuration.rb lib/adyen/encoding.rb lib/adyen/form.rb lib/adyen/formatter.rb lib/adyen/matchers.rb lib/adyen/notification_generator.rb lib/adyen/railtie.rb lib/adyen/templates/notification_migration.rb lib/adyen/templates/notification_model.rb spec/adyen_spec.rb spec/api/api_spec.rb spec/api/payment_service_spec.rb spec/api/recurring_service_spec.rb spec/api/response_spec.rb spec/api/simple_soap_client_spec.rb spec/api/spec_helper.rb spec/api/test_helpers_spec.rb spec/form_spec.rb spec/functional/api_spec.rb spec/functional/initializer.rb.sample spec/spec_helper.rb tasks/github-gem.rake yard_extensions.rb)
|
29
36
|
s.test_files = %w(spec/adyen_spec.rb spec/api/api_spec.rb spec/api/payment_service_spec.rb spec/api/recurring_service_spec.rb spec/api/response_spec.rb spec/api/simple_soap_client_spec.rb spec/api/test_helpers_spec.rb spec/form_spec.rb spec/functional/api_spec.rb)
|
30
37
|
end
|
data/lib/adyen.rb
CHANGED
@@ -12,7 +12,7 @@ module Adyen
|
|
12
12
|
# Version constant for the Adyen plugin.
|
13
13
|
# DO NOT CHANGE THIS VALUE BY HAND. It will be updated automatically by
|
14
14
|
# the gem:release rake task.
|
15
|
-
VERSION = "1.
|
15
|
+
VERSION = "1.3.0"
|
16
16
|
|
17
17
|
# @return [Configuration] The configuration singleton.
|
18
18
|
def self.configuration
|
@@ -24,5 +24,6 @@ require 'adyen/configuration'
|
|
24
24
|
require 'adyen/encoding'
|
25
25
|
require 'adyen/formatter'
|
26
26
|
require 'adyen/form'
|
27
|
+
require 'adyen/api'
|
27
28
|
|
28
29
|
require 'adyen/railtie' if defined?(::Rails) && ::Rails::VERSION::MAJOR >= 3
|
data/lib/adyen/api.rb
CHANGED
@@ -57,14 +57,15 @@ module Adyen
|
|
57
57
|
# invoice.id,
|
58
58
|
# { :currency => 'EUR', :value => invoice.amount },
|
59
59
|
# { :reference => user.id, :email => user.email, :ip => '8.8.8.8' },
|
60
|
-
# { :holder_name => "Simon Hopper", :number => '4444333322221111', :cvc => '737',
|
60
|
+
# { :holder_name => "Simon Hopper", :number => '4444333322221111', :cvc => '737',
|
61
|
+
# :expiry_month => 12, :expiry_year => 2012 }
|
61
62
|
# )
|
62
63
|
# response.authorised? # => true
|
63
64
|
#
|
64
65
|
# @param [Numeric,String] reference Your reference (ID) for this payment.
|
65
66
|
# @param [Hash] amount A hash describing the money to charge.
|
66
67
|
# @param [Hash] shopper A hash describing the shopper.
|
67
|
-
# @param [Hash] card A hash describing the
|
68
|
+
# @param [Hash] card A hash describing the credit card details.
|
68
69
|
#
|
69
70
|
# @option amount [String] :currency The ISO currency code (EUR, GBP, USD, etc).
|
70
71
|
# @option amount [Integer] :value The value of the payment in discrete cents,
|
@@ -278,15 +279,25 @@ module Adyen
|
|
278
279
|
}).disable
|
279
280
|
end
|
280
281
|
|
281
|
-
# Stores and tokenises the
|
282
|
-
# future.
|
282
|
+
# Stores and tokenises the payment details so that recurring payments can be made in the
|
283
|
+
# future. It can be either a credit card or ELV (Elektronisches Lastschriftverfahren).
|
283
284
|
#
|
284
|
-
#
|
285
|
+
# For instance, this is how you would store credit card details:
|
285
286
|
#
|
286
287
|
# # @example
|
287
288
|
# response = Adyen::API.store_recurring_token(
|
288
289
|
# { :reference => user.id, :email => user.email, :ip => '8.8.8.8' },
|
289
|
-
# { :holder_name => "Simon Hopper", :number => '4444333322221111',
|
290
|
+
# { :holder_name => "Simon Hopper", :number => '4444333322221111',
|
291
|
+
# :expiry_month => 12, :expiry_year => 2012 }
|
292
|
+
# )
|
293
|
+
#
|
294
|
+
# Or use the following to store ELV details:
|
295
|
+
#
|
296
|
+
# # @example
|
297
|
+
# response = Adyen::API.store_recurring_token(
|
298
|
+
# { :reference => user.id, :email => user.email, :ip => '8.8.8.8' },
|
299
|
+
# { :bank_location => "Berlin", :bank_name => "TestBank", :bank_location_id => "12345678",
|
300
|
+
# :holder_name => "Simon Hopper", :number => "1234567890" }
|
290
301
|
# )
|
291
302
|
# response.stored? # => true
|
292
303
|
#
|
@@ -299,24 +310,35 @@ module Adyen
|
|
299
310
|
# )
|
300
311
|
# authorize_response.authorised? # => true
|
301
312
|
#
|
302
|
-
# @param
|
303
|
-
#
|
313
|
+
# @param [Hash] params A hash describing the credit card or
|
314
|
+
# ELV details.
|
304
315
|
#
|
305
|
-
# @option shopper
|
306
|
-
# @option shopper
|
307
|
-
# @option shopper
|
316
|
+
# @option shopper [Numeric,String] :reference The shopper’s reference (ID).
|
317
|
+
# @option shopper [String] :email The shopper’s email address.
|
318
|
+
# @option shopper [String] :ip The shopper’s IP address.
|
308
319
|
#
|
309
|
-
# @option
|
310
|
-
#
|
311
|
-
# @option
|
312
|
-
#
|
320
|
+
# @option params [String] :holder_name The full name on the card or of the
|
321
|
+
# account holder.
|
322
|
+
# @option params [String] :number The card or account number.
|
323
|
+
#
|
324
|
+
# ##### Credit card specific options:
|
325
|
+
#
|
326
|
+
# @option params [Numeric,String] :expiry_month The month in which the card expires.
|
327
|
+
# @option params [Numeric,String] :expiry_year The year in which the card expires.
|
328
|
+
#
|
329
|
+
# ##### ELV specific options:
|
330
|
+
#
|
331
|
+
# @option params [String] :bank_location The Bank Location.
|
332
|
+
# @option params [String] :bank_name The Bank Name.
|
333
|
+
# @option params [Numeric,String] :bank_location_id The Bank Location ID (Bankleitzahl).
|
313
334
|
#
|
314
335
|
# @return [RecurringService::StoreTokenResponse] The response object
|
315
|
-
def store_recurring_token(shopper,
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
336
|
+
def store_recurring_token(shopper, params)
|
337
|
+
payment_method = params.include?(:bank_location_id) ? :elv : :card
|
338
|
+
RecurringService.new({
|
339
|
+
:shopper => shopper,
|
340
|
+
payment_method => params
|
341
|
+
}).store_token
|
320
342
|
end
|
321
343
|
end
|
322
344
|
end
|
@@ -158,14 +158,7 @@ module Adyen
|
|
158
158
|
}
|
159
159
|
|
160
160
|
AUTHORISED = 'Authorised'
|
161
|
-
|
162
|
-
def self.original_fault_message_for(attribute, message)
|
163
|
-
if error = ERRORS.find { |_, (a, m)| a == attribute && m == message }
|
164
|
-
error.first
|
165
|
-
else
|
166
|
-
message
|
167
|
-
end
|
168
|
-
end
|
161
|
+
REFUSED = 'Refused'
|
169
162
|
|
170
163
|
response_attrs :result_code, :auth_code, :refusal_reason, :psp_reference
|
171
164
|
|
@@ -173,7 +166,12 @@ module Adyen
|
|
173
166
|
super && params[:result_code] == AUTHORISED
|
174
167
|
end
|
175
168
|
|
176
|
-
|
169
|
+
def refused?
|
170
|
+
params[:result_code] == REFUSED
|
171
|
+
end
|
172
|
+
|
173
|
+
alias_method :authorised?, :success?
|
174
|
+
alias_method :authorized?, :success?
|
177
175
|
|
178
176
|
# @return [Boolean] Returns whether or not the request was valid.
|
179
177
|
def invalid_request?
|
@@ -193,8 +191,12 @@ module Adyen
|
|
193
191
|
def error(prefix = nil)
|
194
192
|
if error = ERRORS[fault_message]
|
195
193
|
prefix ? ["#{prefix}_#{error[0]}".to_sym, error[1]] : error
|
196
|
-
|
194
|
+
elsif fault_message
|
197
195
|
[:base, fault_message]
|
196
|
+
elsif refused?
|
197
|
+
[:base, 'Transaction was refused.']
|
198
|
+
else
|
199
|
+
[:base, 'Transaction failed for unkown reasons.']
|
198
200
|
end
|
199
201
|
end
|
200
202
|
|
@@ -46,6 +46,14 @@ module Adyen
|
|
46
46
|
CARD_PARTIAL % card
|
47
47
|
end
|
48
48
|
|
49
|
+
ELV_ATTRS = [:bank_location, :bank_name, :bank_location_id, :holder_name, :number]
|
50
|
+
# The ELV - (Elektronisches Lastschriftverfahren) does not require bank_location, so insert 'nil'.
|
51
|
+
def elv_partial
|
52
|
+
validate_parameters!(:elv => ELV_ATTRS)
|
53
|
+
elv = @params[:elv].values_at(*ELV_ATTRS)
|
54
|
+
ELV_PARTIAL % elv
|
55
|
+
end
|
56
|
+
|
49
57
|
def list_request_body
|
50
58
|
validate_parameters!(:merchant_account, :shopper => [:reference])
|
51
59
|
LIST_LAYOUT % [@params[:merchant_account], @params[:shopper][:reference]]
|
@@ -61,7 +69,10 @@ module Adyen
|
|
61
69
|
|
62
70
|
def store_token_request_body
|
63
71
|
validate_parameters!(:merchant_account, :shopper => [:email, :reference])
|
64
|
-
content =
|
72
|
+
content = []
|
73
|
+
content << card_partial unless @params[:card].nil?
|
74
|
+
content << elv_partial unless @params[:elv].nil?
|
75
|
+
raise ArgumentError, "The required parameter 'card' or 'elv' is missing." if content.empty?
|
65
76
|
STORE_TOKEN_LAYOUT % [@params[:merchant_account], @params[:shopper][:reference], @params[:shopper][:email], content]
|
66
77
|
end
|
67
78
|
|
@@ -74,7 +85,7 @@ module Adyen
|
|
74
85
|
super && DISABLED_RESPONSES.include?(params[:response])
|
75
86
|
end
|
76
87
|
|
77
|
-
|
88
|
+
alias_method :disabled?, :success?
|
78
89
|
|
79
90
|
def params
|
80
91
|
@params ||= { :response => xml_querier.text('//recurring:disableResponse/recurring:result/recurring:response') }
|
@@ -111,12 +122,17 @@ module Adyen
|
|
111
122
|
}
|
112
123
|
|
113
124
|
card = node.xpath('./recurring:card')
|
114
|
-
|
115
|
-
|
116
|
-
|
125
|
+
elv = node.xpath('./recurring:elv')
|
126
|
+
bank = node.xpath('./recurring:bank')
|
127
|
+
|
128
|
+
if !card.children.empty?
|
117
129
|
result[:card] = parse_card_details(card)
|
130
|
+
elsif !elv.children.empty?
|
131
|
+
result[:elv] = parse_elv_details(elv)
|
132
|
+
else
|
133
|
+
result[:bank] = parse_bank_details(bank)
|
118
134
|
end
|
119
|
-
|
135
|
+
|
120
136
|
result
|
121
137
|
end
|
122
138
|
|
@@ -128,15 +144,25 @@ module Adyen
|
|
128
144
|
}
|
129
145
|
end
|
130
146
|
|
147
|
+
def parse_elv_details(elv)
|
148
|
+
{
|
149
|
+
:holder_name => bank.text('./payment:accountHolderName'),
|
150
|
+
:number => bank.text('./payment:bankAccountNumber'),
|
151
|
+
:bank_location => bank.text('./payment:bankLocation'),
|
152
|
+
:bank_location_id => bank.text('./payment:bankLocationId'),
|
153
|
+
:bank_name => bank.text('./payment:bankName')
|
154
|
+
}
|
155
|
+
end
|
156
|
+
|
131
157
|
def parse_bank_details(bank)
|
132
158
|
{
|
133
|
-
:
|
134
|
-
:bank_location_id
|
135
|
-
:bank_name
|
136
|
-
:bic
|
137
|
-
:country_code
|
138
|
-
:iban
|
139
|
-
:
|
159
|
+
:number => bank.text('./payment:bankAccountNumber'),
|
160
|
+
:bank_location_id => bank.text('./payment:bankLocationId'),
|
161
|
+
:bank_name => bank.text('./payment:bankName'),
|
162
|
+
:bic => bank.text('./payment:bic'),
|
163
|
+
:country_code => bank.text('./payment:countryCode'),
|
164
|
+
:iban => bank.text('./payment:iban'),
|
165
|
+
:holder_name => bank.text('./payment:ownerName')
|
140
166
|
}
|
141
167
|
end
|
142
168
|
end
|
@@ -152,12 +178,14 @@ module Adyen
|
|
152
178
|
super && params[:response] == 'Success'
|
153
179
|
end
|
154
180
|
|
155
|
-
|
181
|
+
alias_method :stored?, :success?
|
156
182
|
|
157
183
|
def params
|
158
|
-
@params ||= {
|
184
|
+
@params ||= {
|
185
|
+
:response => xml_querier.text('//recurring:storeTokenResponse/recurring:result/recurring:result'),
|
159
186
|
:reference => xml_querier.text('//recurring:storeTokenResponse/recurring:result/recurring:rechargeReference'),
|
160
|
-
:recurring_detail_reference => xml_querier.text('//recurring:storeTokenResponse/recurring:result/recurring:recurringDetailReference')
|
187
|
+
:recurring_detail_reference => xml_querier.text('//recurring:storeTokenResponse/recurring:result/recurring:recurringDetailReference')
|
188
|
+
}
|
161
189
|
end
|
162
190
|
end
|
163
191
|
end
|
data/lib/adyen/api/response.rb
CHANGED
@@ -32,6 +32,13 @@ module Adyen
|
|
32
32
|
!@http_response.is_a?(Net::HTTPSuccess)
|
33
33
|
end
|
34
34
|
|
35
|
+
# @return [Boolean] Whether or not the SOAP request itself was a success.
|
36
|
+
# Adyen returns a 500 status code for e.g. failed CC validation and in this case, we don't
|
37
|
+
# want to throw a server error but rather treat it as something normal.
|
38
|
+
def server_error?
|
39
|
+
@http_response.is_a?(Net::HTTPServerError) && fault_message.nil?
|
40
|
+
end
|
41
|
+
|
35
42
|
# @return [XMLQuerier] The response body wrapped in a XMLQuerier.
|
36
43
|
def xml_querier
|
37
44
|
@xml_querier ||= XMLQuerier.new(@http_response.body)
|
@@ -22,23 +22,27 @@ EOS
|
|
22
22
|
# @see http://curl.haxx.se/ca/cacert.pem
|
23
23
|
CACERT = File.expand_path('../cacert.pem', __FILE__)
|
24
24
|
|
25
|
-
class
|
25
|
+
class StandardError < ::StandardError
|
26
26
|
def initialize(response, action, endpoint)
|
27
27
|
@response, @action, @endpoint = response, action, endpoint
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
private
|
31
|
+
|
32
|
+
def message_prefix
|
33
|
+
%{[#{@response.http_response.code} #{@response.http_response.message}] A %s error occurred while calling SOAP action `#{@action}' on endpoint `#{@endpoint}'.}
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
|
-
class
|
36
|
-
def
|
37
|
-
|
37
|
+
class ClientError < StandardError
|
38
|
+
def message
|
39
|
+
"#{message_prefix % "client"} Fault message: #{@response.fault_message}."
|
38
40
|
end
|
41
|
+
end
|
39
42
|
|
43
|
+
class ServerError < StandardError
|
40
44
|
def message
|
41
|
-
|
45
|
+
message_prefix % 'server'
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
@@ -118,9 +122,10 @@ EOS
|
|
118
122
|
|
119
123
|
request.start do |http|
|
120
124
|
http_response = http.request(post)
|
121
|
-
|
122
|
-
raise
|
123
|
-
|
125
|
+
response = response_class.new(http_response)
|
126
|
+
raise ClientError.new(response, action, endpoint) if http_response.is_a?(Net::HTTPClientError)
|
127
|
+
raise ServerError.new(response, action, endpoint) if response.server_error?
|
128
|
+
response
|
124
129
|
end
|
125
130
|
end
|
126
131
|
end
|
@@ -54,6 +54,18 @@ EOS
|
|
54
54
|
<payment:expiryMonth>%02d</payment:expiryMonth>
|
55
55
|
</recurring:card>
|
56
56
|
EOS
|
57
|
+
# Electronic bank debit in Germany. Semi real-time payment method.
|
58
|
+
# @private
|
59
|
+
ELV_PARTIAL = <<EOS
|
60
|
+
<recurring:elv>
|
61
|
+
<payment:bankLocation>%s</payment:bankLocation>
|
62
|
+
<payment:bankName>%s</payment:bankName>
|
63
|
+
<payment:bankLocationId>%s</payment:bankLocationId>
|
64
|
+
<payment:accountHolderName>%s</payment:accountHolderName>
|
65
|
+
<payment:bankAccountNumber>%02d</payment:bankAccountNumber>
|
66
|
+
</recurring:elv>
|
67
|
+
EOS
|
68
|
+
|
57
69
|
end
|
58
70
|
end
|
59
71
|
end
|
@@ -56,7 +56,7 @@ class AdyenNotification < ActiveRecord::Base
|
|
56
56
|
event_code == 'AUTHORISATION'
|
57
57
|
end
|
58
58
|
|
59
|
-
|
59
|
+
alias_method :authorization?, :authorisation?
|
60
60
|
|
61
61
|
# Returns true if this notification is an AUTHORISATION notification and
|
62
62
|
# the success status indicates that the authorization was successfull.
|
@@ -66,5 +66,5 @@ class AdyenNotification < ActiveRecord::Base
|
|
66
66
|
event_code == 'AUTHORISATION' && success?
|
67
67
|
end
|
68
68
|
|
69
|
-
|
69
|
+
alias_method :successful_authorization?, :successful_authorisation?
|
70
70
|
end
|
data/spec/api/api_spec.rb
CHANGED
@@ -131,6 +131,17 @@ describe Adyen::API do
|
|
131
131
|
)
|
132
132
|
end
|
133
133
|
|
134
|
+
it "performs a `tokenize ELV details' request" do
|
135
|
+
should_map_shortcut_to(:store_token,
|
136
|
+
:shopper => { :reference => 'user-id', :email => 's.hopper@example.com' },
|
137
|
+
:elv => { :bank_location => "Berlin", :bank_name => "TestBank", :bank_location_id => "12345678", :holder_name => "Simon Hopper", :number => "1234567890" }
|
138
|
+
)
|
139
|
+
Adyen::API.store_recurring_token(
|
140
|
+
{ :reference => 'user-id', :email => 's.hopper@example.com' },
|
141
|
+
{ :bank_location => "Berlin", :bank_name => "TestBank", :bank_location_id => "12345678", :holder_name => "Simon Hopper", :number => "1234567890" }
|
142
|
+
)
|
143
|
+
end
|
144
|
+
|
134
145
|
it "preforms a `list recurring details' request" do
|
135
146
|
should_map_shortcut_to(:list, :shopper => { :reference => 'user-id' })
|
136
147
|
Adyen::API.list_recurring_details('user-id')
|
@@ -156,6 +156,18 @@ describe Adyen::API::PaymentService do
|
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
|
+
describe "with a `refused' response" do
|
160
|
+
before do
|
161
|
+
stub_net_http(AUTHORISE_REQUEST_REFUSED_RESPONSE)
|
162
|
+
@response = @payment.authorise_payment
|
163
|
+
end
|
164
|
+
|
165
|
+
it "returns that the payment was refused" do
|
166
|
+
@response.should be_refused
|
167
|
+
@response.error.should == [:base, 'Transaction was refused.']
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
159
171
|
describe "with a `invalid' response" do
|
160
172
|
before do
|
161
173
|
stub_net_http(AUTHORISE_REQUEST_INVALID_RESPONSE % 'validation 101 Invalid card number')
|
@@ -202,19 +214,6 @@ describe Adyen::API::PaymentService do
|
|
202
214
|
end
|
203
215
|
end
|
204
216
|
|
205
|
-
it "returns the original message corresponding to the given attribute and message" do
|
206
|
-
[
|
207
|
-
["validation 101 Invalid card number", [:number, 'is not a valid creditcard number']],
|
208
|
-
["validation 103 CVC is not the right length", [:cvc, 'is not the right length']],
|
209
|
-
["validation 128 Card Holder Missing", [:holder_name, 'can\'t be blank']],
|
210
|
-
["validation Couldn't parse expiry year", [:expiry_year, 'could not be recognized']],
|
211
|
-
["validation Expiry month should be between 1 and 12 inclusive", [:expiry_month, 'could not be recognized']],
|
212
|
-
["validation 130 Reference Missing", [:base, 'validation 130 Reference Missing']],
|
213
|
-
].each do |expected, attr_and_message|
|
214
|
-
Adyen::API::PaymentService::AuthorisationResponse.original_fault_message_for(*attr_and_message).should == expected
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
217
|
private
|
219
218
|
|
220
219
|
def response_with_fault_message(message)
|
@@ -27,6 +27,14 @@ describe Adyen::API::RecurringService do
|
|
27
27
|
#:issue_number => ,
|
28
28
|
#:start_month => ,
|
29
29
|
#:start_year => ,
|
30
|
+
},
|
31
|
+
# German's Direct Debit (Elektronisches Lastschriftverfahren)
|
32
|
+
:elv => {
|
33
|
+
:holder_name => 'Simon わくわく Hopper',
|
34
|
+
:number => '1234567890',
|
35
|
+
:bank_location => 'Berlin',
|
36
|
+
:bank_location_id => '12345678',
|
37
|
+
:bank_name => 'TestBank',
|
30
38
|
}
|
31
39
|
}
|
32
40
|
@recurring = @object = Adyen::API::RecurringService.new(@params)
|
@@ -67,13 +75,13 @@ describe Adyen::API::RecurringService do
|
|
67
75
|
},
|
68
76
|
{
|
69
77
|
:bank => {
|
70
|
-
:
|
78
|
+
:number => '123456789',
|
71
79
|
:bank_location_id => 'bank-location-id',
|
72
80
|
:bank_name => 'AnyBank',
|
73
81
|
:bic => 'BBBBCCLLbbb',
|
74
82
|
:country_code => 'NL',
|
75
83
|
:iban => 'NL69PSTB0001234567',
|
76
|
-
:
|
84
|
+
:holder_name => 'S. Hopper'
|
77
85
|
},
|
78
86
|
:recurring_detail_reference => 'RecurringDetailReference2',
|
79
87
|
:variant => 'IDEAL',
|
@@ -161,6 +169,38 @@ describe Adyen::API::RecurringService do
|
|
161
169
|
text('./recurring:recurring/payment:contract').should == 'RECURRING'
|
162
170
|
end
|
163
171
|
end
|
172
|
+
|
173
|
+
describe_request_body_of :store_token, '//recurring:storeToken/recurring:request' do
|
174
|
+
it_should_validate_request_parameters :merchant_account,
|
175
|
+
:shopper => [:email, :reference]
|
176
|
+
|
177
|
+
it "includes the merchant account handle" do
|
178
|
+
text('./recurring:merchantAccount').should == 'SuperShopper'
|
179
|
+
end
|
180
|
+
|
181
|
+
it "includes the shopper’s reference" do
|
182
|
+
text('./recurring:shopperReference').should == 'user-id'
|
183
|
+
end
|
184
|
+
|
185
|
+
it "includes the shopper’s email" do
|
186
|
+
text('./recurring:shopperEmail').should == 's.hopper@example.com'
|
187
|
+
end
|
188
|
+
|
189
|
+
it "includes the ELV details" do
|
190
|
+
xpath('./recurring:elv') do |elv|
|
191
|
+
# there's no reason why Nokogiri should escape these characters, but as long as they're correct
|
192
|
+
elv.text('./payment:accountHolderName').should == 'Simon わくわく Hopper'
|
193
|
+
elv.text('./payment:bankAccountNumber').should == '1234567890'
|
194
|
+
elv.text('./payment:bankLocation').should == 'Berlin'
|
195
|
+
elv.text('./payment:bankLocationId').should == '12345678'
|
196
|
+
elv.text('./payment:bankName').should == 'TestBank'
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
it "includes the necessary recurring and one-click contract info if the `:recurring' param is truthful" do
|
201
|
+
text('./recurring:recurring/payment:contract').should == 'RECURRING'
|
202
|
+
end
|
203
|
+
end
|
164
204
|
|
165
205
|
describe_response_from :disable, (DISABLE_RESPONSE % '[detail-successfully-disabled]'), 'disable' do
|
166
206
|
it "returns whether or not it was disabled" do
|
data/spec/api/response_spec.rb
CHANGED
@@ -32,4 +32,28 @@ describe Adyen::API::Response do
|
|
32
32
|
@response.should_not be_a_success
|
33
33
|
end
|
34
34
|
end
|
35
|
+
|
36
|
+
describe "with a server error HTTP response and _no_ SOAP fault message" do
|
37
|
+
before do
|
38
|
+
http_response = Net::HTTPServerError.new('1.1', '500', 'Internal Server Error')
|
39
|
+
http_response.stub!(:body).and_return(%{<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body></soap:Body></soap:Envelope>})
|
40
|
+
@response = Adyen::API::Response.new(http_response)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "`server_error?` returns that the (HTTP) request did cause a server error" do
|
44
|
+
@response.server_error?.should be_true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "with a server error HTTP response _and_ SOAP fault message" do
|
49
|
+
before do
|
50
|
+
http_response = Net::HTTPServerError.new('1.1', '500', 'Internal Server Error')
|
51
|
+
http_response.stub!(:body).and_return(%{<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>Illegal argument. For input string: "100.0"</faultstring></soap:Fault></soap:Body></soap:Envelope>})
|
52
|
+
@response = Adyen::API::Response.new(http_response)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "`server_error?` returns that the (HTTP) request did not cause a server error" do
|
56
|
+
@response.server_error?.should be_false
|
57
|
+
end
|
58
|
+
end
|
35
59
|
end
|
@@ -76,16 +76,58 @@ describe Adyen::API::SimpleSOAPClient do
|
|
76
76
|
@response.xml_querier.to_s.should == AUTHORISE_RESPONSE
|
77
77
|
end
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
79
|
+
[
|
80
|
+
[
|
81
|
+
"[401 Bad request] A client",
|
82
|
+
Net::HTTPBadRequest.new('1.1', '401', 'Bad request'),
|
83
|
+
Adyen::API::SimpleSOAPClient::ClientError
|
84
|
+
]
|
85
|
+
].each do |label, response, expected_exception|
|
86
|
+
it "raises when the HTTP response is a subclass of #{response.class.name}" do
|
87
|
+
response.stub!(:body).and_return(%{<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>Illegal argument. For input string: "100.0"</faultstring></soap:Fault></soap:Body></soap:Envelope>})
|
88
|
+
Net::HTTP.stubbed_response = response
|
89
|
+
|
90
|
+
exception = nil
|
91
|
+
begin
|
92
|
+
@client.call_webservice_action('Action', '<bananas>Yes, please</bananas>', Adyen::API::Response)
|
93
|
+
rescue expected_exception => e
|
94
|
+
exception = e
|
95
|
+
end
|
96
|
+
exception.message.should == %{#{label} error occurred while calling SOAP action `Action' on endpoint `https://test.example.com/soap/Action'. Fault message: Illegal argument. For input string: "100.0".}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'server error' do
|
101
|
+
[
|
102
|
+
["[500 Internal Server Error] A server", Net::HTTPBadGateway.new('1.1', '500', 'Internal Server Error')],
|
103
|
+
["[501 Not Implemented] A server", Net::HTTPBadGateway.new('1.1', '501', 'Not Implemented')],
|
104
|
+
["[502 Bad Gateway] A server", Net::HTTPBadGateway.new('1.1', '502', 'Bad Gateway')],
|
105
|
+
["[503 Service Unavailable] A server", Net::HTTPBadGateway.new('1.1', '503', 'Service Unavailable')],
|
106
|
+
["[504 Gateway Timeout] A server", Net::HTTPBadGateway.new('1.1', '504', 'Gateway Timeout')],
|
107
|
+
["[505 HTTP Version Not Supported] A server", Net::HTTPBadGateway.new('1.1', '505', 'HTTP Version Not Supported')],
|
108
|
+
].each do |label, response|
|
109
|
+
it "is raised when the HTTP response is a `real` server error by status code" do
|
110
|
+
response.stub!(:body).and_return(%{<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body></soap:Body></soap:Envelope>})
|
111
|
+
Net::HTTP.stubbed_response = response
|
112
|
+
|
113
|
+
exception = nil
|
114
|
+
begin
|
115
|
+
@client.call_webservice_action('Action', '<bananas>Yes, please</bananas>', Adyen::API::Response)
|
116
|
+
rescue Adyen::API::SimpleSOAPClient::ServerError => e
|
117
|
+
exception = e
|
118
|
+
end
|
119
|
+
exception.message.should == %{#{label} error occurred while calling SOAP action `Action' on endpoint `https://test.example.com/soap/Action'.}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
it "is not raised when the HTTP response has a 500 status code with a fault message" do
|
124
|
+
response = Net::HTTPServerError.new('1.1', '500', 'Internal Server Error')
|
125
|
+
response.stub!(:body).and_return(%{<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>Illegal argument. For input string: "100.0"</faultstring></soap:Fault></soap:Body></soap:Envelope>})
|
126
|
+
|
127
|
+
lambda do
|
128
|
+
@client.call_webservice_action('Action', '<bananas>Yes, please</bananas>', Adyen::API::Response)
|
129
|
+
end.should_not raise_error Adyen::API::SimpleSOAPClient::ServerError
|
86
130
|
end
|
87
|
-
msg = "[401 Bad request] A client error occurred while calling SOAP action `Action' on endpoint `https://test.example.com/soap/Action'."
|
88
|
-
exception.message.should == msg
|
89
131
|
end
|
90
132
|
end
|
91
133
|
end
|
data/spec/api/spec_helper.rb
CHANGED
@@ -274,6 +274,21 @@ AUTHORISE_REQUEST_INVALID_RESPONSE = <<EOS
|
|
274
274
|
</soap:Envelope>
|
275
275
|
EOS
|
276
276
|
|
277
|
+
AUTHORISE_REQUEST_REFUSED_RESPONSE = <<EOS
|
278
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
279
|
+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
280
|
+
<soap:Body>
|
281
|
+
<ns1:authoriseResponse xmlns:ns1="http://payment.services.adyen.com">
|
282
|
+
<ns1:paymentResult>
|
283
|
+
<refusalReason xmlns="http://payment.services.adyen.com">You need to actually own money.</refusalReason>
|
284
|
+
<resultCode xmlns="http://payment.services.adyen.com">Refused</resultCode>
|
285
|
+
</ns1:paymentResult>
|
286
|
+
</ns1:authoriseResponse>
|
287
|
+
</soap:Body>
|
288
|
+
</soap:Envelope>
|
289
|
+
EOS
|
290
|
+
|
291
|
+
|
277
292
|
LIST_RESPONSE = <<EOS
|
278
293
|
<?xml version="1.0"?>
|
279
294
|
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
data/spec/functional/api_spec.rb
CHANGED
@@ -57,14 +57,23 @@ if File.exist?(API_SPEC_INITIALIZER)
|
|
57
57
|
response.psp_reference.should_not be_empty
|
58
58
|
end
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
{ :
|
64
|
-
|
65
|
-
|
66
|
-
response.
|
67
|
-
|
60
|
+
# TODO disabled for now: https://github.com/wvanbergen/adyen/issues/29
|
61
|
+
#it "stores the provided ELV account details" do
|
62
|
+
#response = Adyen::API.store_recurring_token(
|
63
|
+
#{ :email => "#{@user_id}@example.com", :reference => @user_id },
|
64
|
+
#{ :bank_location => "Berlin", :bank_name => "TestBank", :bank_location_id => "12345678", :holder_name => "Simon #{@user_id} Hopper", :number => "1234567890" }
|
65
|
+
#)
|
66
|
+
#response.should be_stored
|
67
|
+
#response.recurring_detail_reference.should_not be_empty
|
68
|
+
#end
|
69
|
+
#it "stores the provided creditcard details" do
|
70
|
+
#response = Adyen::API.store_recurring_token(
|
71
|
+
#{ :email => "#{@user_id}@example.com", :reference => @user_id },
|
72
|
+
#{ :expiry_month => 12, :expiry_year => 2012, :holder_name => "Simon #{@user_id} Hopper", :number => '4111111111111111' }
|
73
|
+
#)
|
74
|
+
#response.should be_stored
|
75
|
+
#response.recurring_detail_reference.should_not be_empty
|
76
|
+
#end
|
68
77
|
|
69
78
|
it "captures a payment" do
|
70
79
|
response = Adyen::API.capture_payment(@payment_response.psp_reference, { :currency => 'EUR', :value => '1234' })
|
data/spec/spec_helper.rb
CHANGED
data/tasks/github-gem.rake
CHANGED
@@ -13,8 +13,8 @@ module GithubGem
|
|
13
13
|
|
14
14
|
# Detects the main include file of this project using heuristics
|
15
15
|
def self.detect_main_include
|
16
|
-
if
|
17
|
-
"lib/#{
|
16
|
+
if File.exist?(File.expand_path("../lib/#{File.basename(detect_gemspec_file, '.gemspec').gsub(/-/, '/')}.rb", detect_gemspec_file))
|
17
|
+
"lib/#{File.basename(detect_gemspec_file, '.gemspec').gsub(/-/, '/')}.rb"
|
18
18
|
elsif FileList['lib/*.rb'].length == 1
|
19
19
|
FileList['lib/*.rb'].first
|
20
20
|
else
|
@@ -24,6 +24,8 @@ module GithubGem
|
|
24
24
|
|
25
25
|
class RakeTasks
|
26
26
|
|
27
|
+
include Rake::DSL if Rake.const_defined?('DSL')
|
28
|
+
|
27
29
|
attr_reader :gemspec, :modified_files
|
28
30
|
attr_accessor :gemspec_file, :task_namespace, :main_include, :root_dir, :spec_pattern, :test_pattern, :remote, :remote_branch, :local_branch
|
29
31
|
|
@@ -331,7 +333,7 @@ module GithubGem
|
|
331
333
|
|
332
334
|
# Reload the gemspec so the changes are incorporated
|
333
335
|
load_gemspec!
|
334
|
-
|
336
|
+
|
335
337
|
# Also mark the Gemfile.lock file as changed because of the new version.
|
336
338
|
modified_files << 'Gemfile.lock' if File.exist?(File.join(root_dir, 'Gemfile.lock'))
|
337
339
|
end
|
@@ -341,8 +343,8 @@ module GithubGem
|
|
341
343
|
def update_tasks_task
|
342
344
|
require 'net/https'
|
343
345
|
require 'uri'
|
344
|
-
|
345
|
-
uri = URI.parse('https://github.com/wvanbergen/github-gem/
|
346
|
+
|
347
|
+
uri = URI.parse('https://raw.github.com/wvanbergen/github-gem/master/tasks/github-gem.rake')
|
346
348
|
http = Net::HTTP.new(uri.host, uri.port)
|
347
349
|
http.use_ssl = true
|
348
350
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adyen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 1
|
7
|
-
-
|
8
|
+
- 3
|
8
9
|
- 0
|
9
|
-
version: 1.
|
10
|
+
version: 1.3.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Willem van Bergen
|
@@ -17,8 +18,7 @@ autorequire:
|
|
17
18
|
bindir: bin
|
18
19
|
cert_chain: []
|
19
20
|
|
20
|
-
date: 2011-
|
21
|
-
default_executable:
|
21
|
+
date: 2011-10-10 00:00:00 Z
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
24
24
|
name: rake
|
@@ -28,6 +28,7 @@ dependencies:
|
|
28
28
|
requirements:
|
29
29
|
- - ">="
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
+
hash: 3
|
31
32
|
segments:
|
32
33
|
- 0
|
33
34
|
version: "0"
|
@@ -41,37 +42,39 @@ dependencies:
|
|
41
42
|
requirements:
|
42
43
|
- - ~>
|
43
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 7
|
44
46
|
segments:
|
45
47
|
- 2
|
46
|
-
|
47
|
-
version: "2.0"
|
48
|
+
version: "2"
|
48
49
|
type: :development
|
49
50
|
version_requirements: *id002
|
50
51
|
- !ruby/object:Gem::Dependency
|
51
|
-
name:
|
52
|
+
name: rails
|
52
53
|
prerelease: false
|
53
54
|
requirement: &id003 !ruby/object:Gem::Requirement
|
54
55
|
none: false
|
55
56
|
requirements:
|
56
57
|
- - ">="
|
57
58
|
- !ruby/object:Gem::Version
|
59
|
+
hash: 5
|
58
60
|
segments:
|
59
|
-
-
|
60
|
-
|
61
|
+
- 2
|
62
|
+
- 3
|
63
|
+
version: "2.3"
|
61
64
|
type: :development
|
62
65
|
version_requirements: *id003
|
63
66
|
- !ruby/object:Gem::Dependency
|
64
|
-
name:
|
67
|
+
name: nokogiri
|
65
68
|
prerelease: false
|
66
69
|
requirement: &id004 !ruby/object:Gem::Requirement
|
67
70
|
none: false
|
68
71
|
requirements:
|
69
72
|
- - ">="
|
70
73
|
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
71
75
|
segments:
|
72
|
-
-
|
73
|
-
|
74
|
-
version: "2.3"
|
76
|
+
- 0
|
77
|
+
version: "0"
|
75
78
|
type: :development
|
76
79
|
version_requirements: *id004
|
77
80
|
description: " Package to simplify including the Adyen payments services into a Ruby on Rails application.\n The package provides functionality to create payment forms, handling and storing notifications \n sent by Adyen and consuming the SOAP services provided by Adyen. Moreover, it contains helper\n methods, mocks and matchers to simpify writing tests/specsfor your code.\n"
|
@@ -89,6 +92,8 @@ extra_rdoc_files:
|
|
89
92
|
files:
|
90
93
|
- .gitignore
|
91
94
|
- .kick
|
95
|
+
- .travis.yml
|
96
|
+
- Gemfile
|
92
97
|
- LICENSE
|
93
98
|
- README.rdoc
|
94
99
|
- Rakefile
|
@@ -128,7 +133,6 @@ files:
|
|
128
133
|
- spec/spec_helper.rb
|
129
134
|
- tasks/github-gem.rake
|
130
135
|
- yard_extensions.rb
|
131
|
-
has_rdoc: true
|
132
136
|
homepage: http://github.com/wvanbergen/adyen/wiki
|
133
137
|
licenses: []
|
134
138
|
|
@@ -147,6 +151,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
151
|
requirements:
|
148
152
|
- - ">="
|
149
153
|
- !ruby/object:Gem::Version
|
154
|
+
hash: 3
|
150
155
|
segments:
|
151
156
|
- 0
|
152
157
|
version: "0"
|
@@ -155,13 +160,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
160
|
requirements:
|
156
161
|
- - ">="
|
157
162
|
- !ruby/object:Gem::Version
|
163
|
+
hash: 3
|
158
164
|
segments:
|
159
165
|
- 0
|
160
166
|
version: "0"
|
161
167
|
requirements:
|
162
168
|
- Having Nokogiri installed will speed up XML handling when using the SOAP API.
|
163
169
|
rubyforge_project:
|
164
|
-
rubygems_version: 1.
|
170
|
+
rubygems_version: 1.8.7
|
165
171
|
signing_key:
|
166
172
|
specification_version: 3
|
167
173
|
summary: Integrate Adyen payment services in your Ruby on Rails application.
|