adyen 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/adyen.gemspec +2 -2
  2. data/lib/adyen/soap.rb +97 -3
  3. data/spec/soap_spec.rb +336 -1
  4. metadata +28 -13
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'adyen'
3
- s.version = "0.3.5"
4
- s.date = "2010-02-09"
3
+ s.version = "0.3.6"
4
+ s.date = "2010-03-27"
5
5
 
6
6
  s.summary = "Integrate Adyen payment services in you Ruby on Rails application."
7
7
  s.description = <<-EOS
@@ -177,6 +177,65 @@ module Adyen
177
177
  parse_authorise(response)
178
178
  end
179
179
 
180
+ # Submits a direct debit recurring payment.
181
+ #
182
+ # @example
183
+ # Adyen::SOAP::PaymentService.directdebit(
184
+ # :merchant_account => 'MyAccount', :selected_recurring_detail_reference => 'LATEST',
185
+ # :shopper_reference => user.id, :shopper_email => user.email,
186
+ # :reference => invoice.id, :currency => invoice.currency, :value => invoice.amount)
187
+ #
188
+ # @param [Hash] args The paramaters to use for this call. These will be merged by any default
189
+ # parameters set using {Adyen::SOAP.default_arguments}. Note that every option defined below
190
+ # is required by the Adyen SOAP service, so please provide a value for all options.
191
+ # @option args [String] :selected_recurring_detail_reference ('LATEST') This is the
192
+ # recurringDetailReference you want to use for this payment. You can use the
193
+ # value "LATEST" to select the most recently used recurring detail, which is the default.
194
+ # @option args [String] :merchant_account The merchant account you want to process this payment
195
+ # with.
196
+ # @option args [String] :currency The currency code (EUR, GBP, USD, etc).
197
+ # @option args [Integer] :value The value of the payment in cents.
198
+ # @option args [String] :reference Your reference for this payment. This (merchant) reference
199
+ # will be used in all communication to you about the status of the payment.
200
+ # Although it is a good idea to make sure it is unique, this is not a requirement.
201
+ # @option args [String] :shopper_email The email address of the shopper. This does not have to
202
+ # match the email address supplied with the initial payment, since it may have
203
+ # changed in the mean time.
204
+ # @option args [String] :shopper_reference The reference of the shopper. This should be
205
+ # the same as the reference that was used to create the recurring contract.
206
+ #
207
+ # @return [nil] This action returns nothing of interest. The result of the authorization
208
+ # will be communicated using a {Adyen::Notification notification}.
209
+ #
210
+ # @see https://support.adyen.com/index.php?_m=downloads&_a=viewdownload&downloaditemid=1
211
+ # The Adyen integration manual
212
+ # @see https://support.adyen.com/index.php?_m=downloads&_a=viewdownload&downloaditemid=7&nav=0,3
213
+ # The Adyen recurring payments manual.
214
+ def directdebit(args = {})
215
+ invoke_args = Adyen::SOAP.default_arguments.merge(args)
216
+ invoke_args[:selected_recurring_detail_reference] ||= 'LATEST'
217
+
218
+ response = invoke('payment:directdebit') do |message|
219
+ message.add('payment:paymentRequest') do |req|
220
+ req.add('payment:selectedRecurringDetailReference', invoke_args[:selected_recurring_detail_reference])
221
+ req.add('payment:recurring') do |recurring|
222
+ recurring.add('payment:contract', 'RECURRING')
223
+ end
224
+ req.add('payment:merchantAccount', invoke_args[:merchant_account])
225
+ req.add('payment:amount') do |amount|
226
+ amount.add('common:currency', invoke_args[:currency])
227
+ amount.add('common:value', invoke_args[:value])
228
+ end
229
+ req.add('payment:reference', invoke_args[:reference])
230
+ req.add('payment:shopperEmail', invoke_args[:shopper_email])
231
+ req.add('payment:shopperReference', invoke_args[:shopper_reference])
232
+ req.add('payment:shopperInteraction', 'ContAuth')
233
+ end
234
+ end
235
+
236
+ parse_directdebit(response)
237
+ end
238
+
180
239
  # Capture a payment.
181
240
  #
182
241
  # @param [Hash] args The paramaters to use for this call. These will be merged by any default
@@ -305,6 +364,16 @@ module Adyen
305
364
  }
306
365
  end
307
366
 
367
+ def parse_directdebit(response)
368
+ response = response.xpath('//payment:directdebitResponse/payment:response')
369
+ {
370
+ :psp_reference => response.xpath('./payment:pspReference/text()').to_s,
371
+ :result_code => response.xpath('./payment:resultCode/text()').to_s,
372
+ :auth_code => response.xpath('./payment:authCode/text()').to_s,
373
+ :refusal_reason => response.xpath('./payment:refusalReason/text()').to_s
374
+ }
375
+ end
376
+
308
377
  def parse_capture(response)
309
378
  response = response.xpath('//payment:captureResponse/payment:captureResult')
310
379
  {
@@ -514,12 +583,23 @@ module Adyen
514
583
  }
515
584
  end
516
585
 
517
- # @todo add support for elv and bank
586
+ # @todo add support for elv
518
587
  def parse_recurring_detail(node)
519
- {
588
+ result = if(not node.xpath('./recurring:card').to_s.nil?)
589
+ parse_card(node)
590
+ elsif(not node.xpath('./recurring:bank').to_s.nil?)
591
+ parse_bank(node)
592
+ end
593
+
594
+ result.merge({
520
595
  :recurring_detail_reference => node.xpath('./recurring:recurringDetailReference/text()').to_s,
521
596
  :variant => node.xpath('./recurring:variant/text()').to_s,
522
- :creation_date => node.xpath('./recurring:creationDate/text()').to_date,
597
+ :creation_date => node.xpath('./recurring:creationDate/text()').to_date
598
+ })
599
+ end
600
+
601
+ def parse_card(node)
602
+ {
523
603
  :card => {
524
604
  :expiry_date => Date.new(node.xpath('./recurring:card/payment:expiryYear/text()').to_i, node.xpath('recurring:card/payment:expiryMonth').to_i, -1),
525
605
  :holder_name => node.xpath('./recurring:card/payment:holderName/text()').to_s,
@@ -528,6 +608,20 @@ module Adyen
528
608
  }
529
609
  end
530
610
 
611
+ def parse_bank(node)
612
+ {
613
+ :bank => {
614
+ :bank_account_number => node.xpath('./recurring:bank/payment:bankAccountNumber/text()').to_s,
615
+ :bank_location_id => node.xpath('./recurring:bank/payment:bankLocationId/text()').to_s,
616
+ :bank_name => node.xpath('./recurring:bank/payment:bankName/text()').to_s,
617
+ :bic => node.xpath('./recurring:bank/payment:bic/text()').to_s,
618
+ :country_code => node.xpath('./recurring:bank/payment:countryCode/text()').to_s,
619
+ :iban => node.xpath('./recurring:bank/payment:iban/text()').to_s,
620
+ :owner_name => node.xpath('./recurring:bank/payment:ownerName/text()').to_s
621
+ }
622
+ }
623
+ end
624
+
531
625
  def parse_disable(response)
532
626
  response = response.xpath('//recurring:disableResponse/recurring:result')
533
627
  {
@@ -1,5 +1,340 @@
1
1
  require "#{File.dirname(__FILE__)}/spec_helper.rb"
2
2
 
3
- describe Adyen::SOAP do
3
+ describe Adyen::SOAP::PaymentService do
4
+
5
+ describe '#authorise' do
6
+ before(:all) do
7
+ setup_mock_driver(<<EOF)
8
+ <?xml version="1.0" encoding="UTF-8"?>
9
+ <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">
10
+ <soap:Body>
11
+ <ns1:authoriseResponse xmlns:ns1="http://payment.services.adyen.com">
12
+ <ns1:paymentResult>
13
+ <additionalData xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
14
+ <authCode xmlns="http://payment.services.adyen.com">1234</authCode>
15
+ <dccAmount xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
16
+ <dccSignature xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
17
+ <fraudResult xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
18
+ <issuerUrl xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
19
+ <md xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
20
+ <paRequest xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
21
+ <pspReference xmlns="http://payment.services.adyen.com">9876543210987654</pspReference>
22
+ <refusalReason xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
23
+ <resultCode xmlns="http://payment.services.adyen.com">Authorised</resultCode>
24
+ </ns1:paymentResult>
25
+ </ns1:authoriseResponse>
26
+ </soap:Body>
27
+ </soap:Envelope>
28
+ EOF
29
+
30
+ @response = Adyen::SOAP::PaymentService.authorise({
31
+ :selected_recurring_detail_reference => '6543210987654321',
32
+ :merchant_account => 'YourMerchantAccount',
33
+ :currency => 'EUR',
34
+ :value => '1000',
35
+ :reference => '1234567890123456',
36
+ :shopper_email => 'user@example.com',
37
+ :shopper_reference => '1'
38
+ })
39
+ end
40
+
41
+ context 'request' do
42
+ before(:all) do
43
+ @root_node = get_last_request_body.xpath('//payment:authorise/payment:paymentRequest', ns)
44
+ end
45
+
46
+ it 'should setup a paymentRequest' do
47
+ @root_node.should_not be_empty
48
+ end
49
+
50
+ it 'should provide an selectedRecurringDetailReference' do
51
+ @root_node.xpath('./payment:selectedRecurringDetailReference/text()', ns).to_s.should == '6543210987654321'
52
+ end
53
+
54
+ it 'should provide a merchantAccount' do
55
+ @root_node.xpath('./payment:merchantAccount/text()', ns).to_s.should == 'YourMerchantAccount'
56
+ end
57
+
58
+ it 'should provide a currency' do
59
+ @root_node.xpath('./payment:amount/common:currency/text()', ns).to_s.should == 'EUR'
60
+ end
61
+
62
+ it 'should provide a value' do
63
+ @root_node.xpath('./payment:amount/common:value/text()', ns).to_s.should == '1000'
64
+ end
65
+
66
+ it 'should provide a reference' do
67
+ @root_node.xpath('./payment:reference/text()', ns).to_s.should == '1234567890123456'
68
+ end
69
+
70
+ it 'should provide a shopperEmail' do
71
+ @root_node.xpath('./payment:shopperEmail/text()', ns).to_s.should == 'user@example.com'
72
+ end
73
+
74
+ it 'should provide a shopperReference' do
75
+ @root_node.xpath('./payment:shopperReference/text()', ns).to_s.should == '1'
76
+ end
77
+ end
78
+
79
+ context 'response' do
80
+ it 'should get a authorised resultcode' do
81
+ @response[:result_code].should == 'Authorised'
82
+ end
83
+
84
+ it 'should get a new psp reference' do
85
+ @response[:psp_reference].should == '9876543210987654'
86
+ end
87
+
88
+ it 'should get an authCode' do
89
+ @response[:auth_code].should == '1234'
90
+ end
91
+ end
92
+ end
93
+
94
+ describe '#capture' do
95
+ before(:all) do
96
+ setup_mock_driver(<<EOF)
97
+ <?xml version="1.0" encoding="UTF-8"?>
98
+ <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">
99
+ <soap:Body>
100
+ <ns1:captureResponse xmlns:ns1="http://payment.services.adyen.com">
101
+ <ns1:captureResult>
102
+ <pspReference xmlns="http://payment.services.adyen.com">9876543210987654</pspReference>
103
+ <response xmlns="http://payment.services.adyen.com">[capture-received]</response>
104
+ </ns1:captureResult>
105
+ </ns1:captureResponse>
106
+ </soap:Body>
107
+ </soap:Envelope>
108
+ EOF
109
+
110
+ @response = Adyen::SOAP::PaymentService.capture({
111
+ :merchant_account => 'YourMerchantAccount',
112
+ :original_reference => '1234567890123456',
113
+ :currency => 'EUR',
114
+ :value => '1000'
115
+ })
116
+ end
117
+
118
+ context 'request' do
119
+ before(:all) do
120
+ @root_node = get_last_request_body.xpath('//payment:capture/payment:modificationRequest', ns)
121
+ end
122
+
123
+ it 'should setup a modificationRequest' do
124
+ @root_node.should_not be_empty
125
+ end
126
+
127
+ it 'should provide a merchantAccount' do
128
+ @root_node.xpath('./payment:merchantAccount/text()', ns).to_s.should == 'YourMerchantAccount'
129
+ end
130
+
131
+ it 'should provide an originalReference' do
132
+ @root_node.xpath('./payment:originalReference/text()', ns).to_s.should == '1234567890123456'
133
+ end
134
+
135
+ it 'should provide a currency' do
136
+ @root_node.xpath('./payment:modificationAmount/common:currency/text()', ns).to_s.should == 'EUR'
137
+ end
138
+
139
+ it 'should provide a value' do
140
+ @root_node.xpath('./payment:modificationAmount/common:value/text()', ns).to_s.should == '1000'
141
+ end
142
+ end
143
+
144
+ context 'response' do
145
+ it 'should get a capture-received message' do
146
+ @response[:response].should == '[capture-received]'
147
+ end
148
+
149
+ it 'should get a new psp reference' do
150
+ @response[:psp_reference].should == '9876543210987654'
151
+ end
152
+ end
153
+ end
154
+
155
+ describe "#cancel" do
156
+ before(:all) do
157
+ setup_mock_driver(<<EOF)
158
+ <?xml version="1.0" encoding="UTF-8"?>
159
+ <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">
160
+ <soap:Body>
161
+ <ns1:cancelResponse xmlns:ns1="http://payment.services.adyen.com">
162
+ <ns1:cancelResult>
163
+ <pspReference xmlns="http://payment.services.adyen.com">9876543210987654</pspReference>
164
+ <response xmlns="http://payment.services.adyen.com">[cancel-received]</response>
165
+ </ns1:cancelResult>
166
+ </ns1:cancelResponse>
167
+ </soap:Body>
168
+ </soap:Envelope>
169
+ EOF
170
+
171
+ @response = Adyen::SOAP::PaymentService.cancel({
172
+ :merchant_account => 'YourMerchantAccount',
173
+ :original_reference => '1234567890123456'
174
+ })
175
+ end
176
+
177
+ context 'request' do
178
+ before(:all) do
179
+ @root_node = get_last_request_body.xpath('//payment:cancel/payment:modificationRequest', ns)
180
+ end
181
+
182
+ it 'should setup a modificationRequest' do
183
+ @root_node.should_not be_empty
184
+ end
185
+
186
+ it 'should provide a merchantAccount' do
187
+ @root_node.xpath('./payment:merchantAccount/text()', ns).to_s.should == 'YourMerchantAccount'
188
+ end
189
+
190
+ it 'should provide an originalReference' do
191
+ @root_node.xpath('./payment:originalReference/text()', ns).to_s.should == '1234567890123456'
192
+ end
193
+ end
194
+
195
+ context 'response' do
196
+ it 'should get a cancel-received message' do
197
+ @response[:response].should == '[cancel-received]'
198
+ end
199
+
200
+ it 'should get a new psp reference' do
201
+ @response[:psp_reference].should == '9876543210987654'
202
+ end
203
+ end
204
+ end
205
+
206
+ describe "#refund" do
207
+ before(:all) do
208
+ setup_mock_driver(<<EOF)
209
+ <?xml version="1.0" encoding="UTF-8"?>
210
+ <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">
211
+ <soap:Body>
212
+ <ns1:refundResponse xmlns:ns1="http://payment.services.adyen.com">
213
+ <ns1:refundResult>
214
+ <pspReference xmlns="http://payment.services.adyen.com">9876543210987654</pspReference>
215
+ <response xmlns="http://payment.services.adyen.com">[refund-received]</response>
216
+ </ns1:refundResult>
217
+ </ns1:refundResponse>
218
+ </soap:Body>
219
+ </soap:Envelope>
220
+ EOF
221
+
222
+ @response = Adyen::SOAP::PaymentService.refund({
223
+ :merchant_account => 'YourMerchantAccount',
224
+ :currency => 'EUR',
225
+ :value => '1000'
226
+ })
227
+ end
228
+
229
+ context 'request' do
230
+ before(:all) do
231
+ @root_node = get_last_request_body.xpath('//payment:refund/payment:modificationRequest', ns)
232
+ end
233
+
234
+ it 'should setup a modificationRequest' do
235
+ @root_node.should_not be_empty
236
+ end
237
+
238
+ it 'should provide a merchantAccount' do
239
+ @root_node.xpath('./payment:merchantAccount/text()', ns).to_s.should == 'YourMerchantAccount'
240
+ end
241
+
242
+ it 'should provide a currency' do
243
+ @root_node.xpath('./payment:modificationAmount/common:currency/text()', ns).to_s.should == 'EUR'
244
+ end
245
+
246
+ it 'should provide a value' do
247
+ @root_node.xpath('./payment:modificationAmount/common:value/text()', ns).to_s.should == '1000'
248
+ end
249
+ end
250
+
251
+ context 'response' do
252
+ it 'should get a refund-received message' do
253
+ @response[:response].should == '[refund-received]'
254
+ end
255
+
256
+ it 'should get a new psp reference' do
257
+ @response[:psp_reference].should == '9876543210987654'
258
+ end
259
+ end
260
+ end
261
+
262
+ describe "#cancel_or_refund" do
263
+ before(:all) do
264
+ setup_mock_driver(<<EOF)
265
+ <?xml version="1.0" encoding="UTF-8"?>
266
+ <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">
267
+ <soap:Body>
268
+ <ns1:cancelOrRefundResponse xmlns:ns1="http://payment.services.adyen.com">
269
+ <ns1:cancelOrRefundResult>
270
+ <pspReference xmlns="http://payment.services.adyen.com">9876543210987654</pspReference>
271
+ <response xmlns="http://payment.services.adyen.com">[cancelOrRefund-received]</response>
272
+ </ns1:cancelOrRefundResult>
273
+ </ns1:cancelOrRefundResponse>
274
+ </soap:Body>
275
+ </soap:Envelope>
276
+ EOF
277
+
278
+ @response = Adyen::SOAP::PaymentService.cancel_or_refund({
279
+ :merchant_account => 'YourMerchantAccount',
280
+ :original_reference => '1234567890123456'
281
+ })
282
+ end
283
+
284
+ context 'request' do
285
+ before(:all) do
286
+ @root_node = get_last_request_body.xpath('//payment:cancelOrRefund/payment:modificationRequest', ns)
287
+ end
288
+
289
+ it 'should setup a modificationRequest' do
290
+ @root_node.should_not be_empty
291
+ end
292
+
293
+ it 'should provide a merchantAccount' do
294
+ @root_node.xpath('./payment:merchantAccount/text()', ns).to_s.should == 'YourMerchantAccount'
295
+ end
296
+
297
+ it 'should provide an originalReference' do
298
+ @root_node.xpath('./payment:originalReference/text()', ns).to_s.should == '1234567890123456'
299
+ end
300
+ end
301
+
302
+ context 'response' do
303
+ it 'should get a cancelOrRefund-received message' do
304
+ @response[:response].should == '[cancelOrRefund-received]'
305
+ end
306
+
307
+ it 'should get a new psp reference' do
308
+ @response[:psp_reference].should == '9876543210987654'
309
+ end
310
+ end
311
+ end
312
+
313
+ private
314
+
315
+ def setup_mock_driver(content)
316
+ Handsoap::Http.drivers[:mock] = Handsoap::Http::Drivers::MockDriver.new({
317
+ :status => 200,
318
+ :headers => [
319
+ 'Date: Sat, 09 Jan 2010 01:14:41 GMT',
320
+ 'Server: Apache',
321
+ 'Content-Type: text/xml;charset=UTF-8'
322
+ ].join("\r\n"),
323
+ :content => content
324
+ })
325
+ Handsoap.http_driver = :mock
326
+ end
327
+
328
+ def get_last_request_body
329
+ Nokogiri::XML::Document.parse(Handsoap::Http.drivers[:mock].last_request.body)
330
+ end
331
+
332
+ def ns
333
+ {
334
+ 'payment' => 'http://payment.services.adyen.com',
335
+ 'recurring' => 'http://recurring.services.adyen.com',
336
+ 'common' => 'http://common.services.adyen.com'
337
+ }
338
+ end
4
339
 
5
340
  end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: adyen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 6
9
+ version: 0.3.6
5
10
  platform: ruby
6
11
  authors:
7
12
  - Willem van Bergen
@@ -10,29 +15,37 @@ autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
17
 
13
- date: 2010-02-09 00:00:00 +01:00
18
+ date: 2010-03-27 00:00:00 +01:00
14
19
  default_executable:
15
20
  dependencies:
16
21
  - !ruby/object:Gem::Dependency
17
22
  name: rspec
18
- type: :development
19
- version_requirement:
20
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
21
25
  requirements:
22
26
  - - ">="
23
27
  - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 1
31
+ - 4
24
32
  version: 1.1.4
25
- version:
33
+ type: :development
34
+ version_requirements: *id001
26
35
  - !ruby/object:Gem::Dependency
27
36
  name: git
28
- type: :development
29
- version_requirement:
30
- version_requirements: !ruby/object:Gem::Requirement
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
31
39
  requirements:
32
40
  - - ">="
33
41
  - !ruby/object:Gem::Version
42
+ segments:
43
+ - 1
44
+ - 1
45
+ - 0
34
46
  version: 1.1.0
35
- version:
47
+ type: :development
48
+ version_requirements: *id002
36
49
  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"
37
50
  email:
38
51
  - willem@vanbergen.org
@@ -81,20 +94,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
94
  requirements:
82
95
  - - ">="
83
96
  - !ruby/object:Gem::Version
97
+ segments:
98
+ - 0
84
99
  version: "0"
85
- version:
86
100
  required_rubygems_version: !ruby/object:Gem::Requirement
87
101
  requirements:
88
102
  - - ">="
89
103
  - !ruby/object:Gem::Version
104
+ segments:
105
+ - 0
90
106
  version: "0"
91
- version:
92
107
  requirements:
93
108
  - Handsoap is required for accessing the SOAP services. See http://github.com/troelskn/handsoap.
94
109
  - LibXML is required for using the RSpec matchers.
95
110
  - ActiveRecord is required for storing the notifications in your database.
96
111
  rubyforge_project:
97
- rubygems_version: 1.3.5
112
+ rubygems_version: 1.3.6
98
113
  signing_key:
99
114
  specification_version: 3
100
115
  summary: Integrate Adyen payment services in you Ruby on Rails application.