adyen 0.3.8 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.gitignore +4 -0
  2. data/.kick +35 -0
  3. data/LICENSE +3 -2
  4. data/README.rdoc +8 -4
  5. data/Rakefile +10 -0
  6. data/TODO +14 -4
  7. data/adyen.gemspec +9 -15
  8. data/lib/adyen.rb +10 -59
  9. data/lib/adyen/api.rb +281 -0
  10. data/lib/adyen/api/cacert.pem +3509 -0
  11. data/lib/adyen/api/payment_service.rb +258 -0
  12. data/lib/adyen/api/recurring_service.rb +126 -0
  13. data/lib/adyen/api/response.rb +54 -0
  14. data/lib/adyen/api/simple_soap_client.rb +118 -0
  15. data/lib/adyen/api/templates/payment_service.rb +103 -0
  16. data/lib/adyen/api/templates/recurring_service.rb +34 -0
  17. data/lib/adyen/api/test_helpers.rb +133 -0
  18. data/lib/adyen/api/xml_querier.rb +94 -0
  19. data/lib/adyen/configuration.rb +139 -0
  20. data/lib/adyen/form.rb +37 -109
  21. data/lib/adyen/formatter.rb +0 -10
  22. data/lib/adyen/matchers.rb +1 -1
  23. data/lib/adyen/notification_generator.rb +30 -0
  24. data/lib/adyen/railtie.rb +13 -0
  25. data/lib/adyen/templates/notification_migration.rb +29 -0
  26. data/lib/adyen/templates/notification_model.rb +70 -0
  27. data/spec/adyen_spec.rb +3 -45
  28. data/spec/api/api_spec.rb +139 -0
  29. data/spec/api/payment_service_spec.rb +439 -0
  30. data/spec/api/recurring_service_spec.rb +105 -0
  31. data/spec/api/response_spec.rb +35 -0
  32. data/spec/api/simple_soap_client_spec.rb +91 -0
  33. data/spec/api/spec_helper.rb +417 -0
  34. data/spec/api/test_helpers_spec.rb +83 -0
  35. data/spec/form_spec.rb +27 -23
  36. data/spec/functional/api_spec.rb +90 -0
  37. data/spec/functional/initializer.rb.sample +3 -0
  38. data/spec/spec_helper.rb +5 -5
  39. data/tasks/github-gem.rake +49 -55
  40. data/yard_extensions.rb +16 -0
  41. metadata +63 -82
  42. data/init.rb +0 -1
  43. data/lib/adyen/notification.rb +0 -151
  44. data/lib/adyen/soap.rb +0 -649
  45. data/spec/notification_spec.rb +0 -97
  46. data/spec/soap_spec.rb +0 -340
@@ -0,0 +1,139 @@
1
+ # encoding: UTF-8
2
+ require 'api/spec_helper'
3
+
4
+ describe Adyen::API do
5
+ include APISpecHelper
6
+
7
+ describe "shortcut methods" do
8
+ describe "for the PaymentService" do
9
+ before do
10
+ @payment = mock('PaymentService')
11
+ end
12
+
13
+ def should_map_shortcut_to(method, params)
14
+ Adyen::API::PaymentService.should_receive(:new).with(params).and_return(@payment)
15
+ @payment.should_receive(method)
16
+ end
17
+
18
+ it "performs a `authorise payment' request without enabling :recurring" do
19
+ should_map_shortcut_to(:authorise_payment,
20
+ :reference => 'order-id',
21
+ :amount => { :currency => 'EUR', :value => 1234 },
22
+ :shopper => { :reference => 'user-id', :email => 's.hopper@example.com' },
23
+ :card => { :expiry_month => 12, :expiry_year => 2012, :holder_name => "Simon Hopper", :number => '4444333322221111', :cvc => '737' },
24
+ :recurring => false
25
+ )
26
+ Adyen::API.authorise_payment('order-id',
27
+ { :currency => 'EUR', :value => 1234 },
28
+ { :reference => 'user-id', :email => 's.hopper@example.com' },
29
+ { :expiry_month => 12, :expiry_year => 2012, :holder_name => "Simon Hopper", :number => '4444333322221111', :cvc => '737' }
30
+ )
31
+ end
32
+
33
+ it "performs a `authorise payment' request with enabling :recurring" do
34
+ should_map_shortcut_to(:authorise_payment,
35
+ :reference => 'order-id',
36
+ :amount => { :currency => 'EUR', :value => 1234 },
37
+ :shopper => { :reference => 'user-id', :email => 's.hopper@example.com' },
38
+ :card => { :expiry_month => 12, :expiry_year => 2012, :holder_name => "Simon Hopper", :number => '4444333322221111', :cvc => '737' },
39
+ :recurring => true
40
+ )
41
+ Adyen::API.authorise_payment('order-id',
42
+ { :currency => 'EUR', :value => 1234 },
43
+ { :reference => 'user-id', :email => 's.hopper@example.com' },
44
+ { :expiry_month => 12, :expiry_year => 2012, :holder_name => "Simon Hopper", :number => '4444333322221111', :cvc => '737' },
45
+ true
46
+ )
47
+ end
48
+
49
+ it "performs a `authorise recurring payment' request without specific detail" do
50
+ should_map_shortcut_to(:authorise_recurring_payment,
51
+ :reference => 'order-id',
52
+ :amount => { :currency => 'EUR', :value => 1234 },
53
+ :shopper => { :reference => 'user-id', :email => 's.hopper@example.com' },
54
+ :recurring_detail_reference => 'LATEST'
55
+ )
56
+ Adyen::API.authorise_recurring_payment('order-id',
57
+ { :currency => 'EUR', :value => 1234 },
58
+ { :reference => 'user-id', :email => 's.hopper@example.com' }
59
+ )
60
+ end
61
+
62
+ it "performs a `authorise recurring payment' request with specific detail" do
63
+ should_map_shortcut_to(:authorise_recurring_payment,
64
+ :reference => 'order-id',
65
+ :amount => { :currency => 'EUR', :value => 1234 },
66
+ :shopper => { :reference => 'user-id', :email => 's.hopper@example.com' },
67
+ :recurring_detail_reference => 'recurring-detail-reference'
68
+ )
69
+ Adyen::API.authorise_recurring_payment('order-id',
70
+ { :currency => 'EUR', :value => 1234 },
71
+ { :reference => 'user-id', :email => 's.hopper@example.com' },
72
+ 'recurring-detail-reference'
73
+ )
74
+ end
75
+
76
+ it "performs a `authorise one-click payment' request with specific detail" do
77
+ should_map_shortcut_to(:authorise_one_click_payment,
78
+ :reference => 'order-id',
79
+ :amount => { :currency => 'EUR', :value => 1234 },
80
+ :shopper => { :reference => 'user-id', :email => 's.hopper@example.com' },
81
+ :card => { :cvc => '737' },
82
+ :recurring_detail_reference => 'recurring-detail-reference'
83
+ )
84
+ Adyen::API.authorise_one_click_payment('order-id',
85
+ { :currency => 'EUR', :value => 1234 },
86
+ { :reference => 'user-id', :email => 's.hopper@example.com' },
87
+ '737',
88
+ 'recurring-detail-reference'
89
+ )
90
+ end
91
+
92
+ it "performs a `capture' request" do
93
+ should_map_shortcut_to(:capture, :psp_reference => 'original-psp-reference', :amount => { :currency => 'EUR', :value => '1234' })
94
+ Adyen::API.capture_payment('original-psp-reference', { :currency => 'EUR', :value => '1234' })
95
+ end
96
+
97
+ it "performs a `refund payment' request" do
98
+ should_map_shortcut_to(:refund, :psp_reference => 'original-psp-reference', :amount => { :currency => 'EUR', :value => '1234' })
99
+ Adyen::API.refund_payment('original-psp-reference', { :currency => 'EUR', :value => '1234' })
100
+ end
101
+
102
+ it "performs a `cancel or refund payment' request" do
103
+ should_map_shortcut_to(:cancel_or_refund, :psp_reference => 'original-psp-reference')
104
+ Adyen::API.cancel_or_refund_payment('original-psp-reference')
105
+ end
106
+
107
+ it "performs a `cancel payment' request" do
108
+ should_map_shortcut_to(:cancel, :psp_reference => 'original-psp-reference')
109
+ Adyen::API.cancel_payment('original-psp-reference')
110
+ end
111
+ end
112
+
113
+ describe "for the RecurringService" do
114
+ before do
115
+ @recurring = mock('RecurringService')
116
+ end
117
+
118
+ def should_map_shortcut_to(method, params)
119
+ Adyen::API::RecurringService.should_receive(:new).with(params).and_return(@recurring)
120
+ @recurring.should_receive(method)
121
+ end
122
+
123
+ it "preforms a `list recurring details' request" do
124
+ should_map_shortcut_to(:list, :shopper => { :reference => 'user-id' })
125
+ Adyen::API.list_recurring_details('user-id')
126
+ end
127
+
128
+ it "performs a `disable recurring contract' request for all details" do
129
+ should_map_shortcut_to(:disable, :shopper => { :reference => 'user-id' }, :recurring_detail_reference => nil)
130
+ Adyen::API.disable_recurring_contract('user-id')
131
+ end
132
+
133
+ it "performs a `disable recurring contract' request for a specific detail" do
134
+ should_map_shortcut_to(:disable, :shopper => { :reference => 'user-id' }, :recurring_detail_reference => 'detail-id')
135
+ Adyen::API.disable_recurring_contract('user-id', 'detail-id')
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,439 @@
1
+ # encoding: UTF-8
2
+ require 'api/spec_helper'
3
+
4
+ shared_examples_for "payment requests" do
5
+ it "includes the merchant account handle" do
6
+ text('./payment:merchantAccount').should == 'SuperShopper'
7
+ end
8
+
9
+ it "includes the payment reference of the merchant" do
10
+ text('./payment:reference').should == 'order-id'
11
+ end
12
+
13
+ it "includes the given amount of `currency'" do
14
+ xpath('./payment:amount') do |amount|
15
+ amount.text('./common:currency').should == 'EUR'
16
+ amount.text('./common:value').should == '1234'
17
+ end
18
+ end
19
+
20
+ it "includes the shopper’s details" do
21
+ text('./payment:shopperReference').should == 'user-id'
22
+ text('./payment:shopperEmail').should == 's.hopper@example.com'
23
+ text('./payment:shopperIP').should == '61.294.12.12'
24
+ end
25
+
26
+ it "only includes shopper details for given parameters" do
27
+ # TODO pretty lame, but for now it will do
28
+ unless @method == "authorise_one_click_payment_request_body" || @method == "authorise_recurring_payment_request_body"
29
+ @payment.params[:shopper].delete(:reference)
30
+ xpath('./payment:shopperReference').should be_empty
31
+ @payment.params[:shopper].delete(:email)
32
+ xpath('./payment:shopperEmail').should be_empty
33
+ @payment.params[:shopper].delete(:ip)
34
+ xpath('./payment:shopperIP').should be_empty
35
+ end
36
+ end
37
+
38
+ it "does not include any shopper details if none are given" do
39
+ # TODO pretty lame, but for now it will do
40
+ unless @method == "authorise_one_click_payment_request_body" || @method == "authorise_recurring_payment_request_body"
41
+ @payment.params.delete(:shopper)
42
+ xpath('./payment:shopperReference').should be_empty
43
+ xpath('./payment:shopperEmail').should be_empty
44
+ xpath('./payment:shopperIP').should be_empty
45
+ end
46
+ end
47
+ end
48
+
49
+ shared_examples_for "recurring payment requests" do
50
+ it_should_behave_like "payment requests"
51
+
52
+ it "uses the given recurring detail reference" do
53
+ @payment.params[:recurring_detail_reference] = 'RecurringDetailReference1'
54
+ text('./payment:selectedRecurringDetailReference').should == 'RecurringDetailReference1'
55
+ end
56
+ end
57
+
58
+ describe Adyen::API::PaymentService do
59
+ include APISpecHelper
60
+
61
+ before do
62
+ @params = {
63
+ :reference => 'order-id',
64
+ :amount => {
65
+ :currency => 'EUR',
66
+ :value => '1234',
67
+ },
68
+ :shopper => {
69
+ :email => 's.hopper@example.com',
70
+ :reference => 'user-id',
71
+ :ip => '61.294.12.12',
72
+ },
73
+ :card => {
74
+ :expiry_month => 12,
75
+ :expiry_year => 2012,
76
+ :holder_name => 'Simon わくわく Hopper',
77
+ :number => '4444333322221111',
78
+ :cvc => '737',
79
+ # Maestro UK/Solo only
80
+ #:issue_number => ,
81
+ #:start_month => ,
82
+ #:start_year => ,
83
+ },
84
+ :recurring_detail_reference => 'RecurringDetailReference1'
85
+ }
86
+ @payment = @object = Adyen::API::PaymentService.new(@params)
87
+ end
88
+
89
+ describe_request_body_of :authorise_payment do
90
+ it_should_behave_like "payment requests"
91
+
92
+ it_should_validate_request_parameters :merchant_account,
93
+ :reference,
94
+ :amount => [:currency, :value],
95
+ :card => [:holder_name, :number, :cvc, :expiry_year, :expiry_month]
96
+
97
+ it_should_validate_request_param(:shopper) do
98
+ @payment.params[:recurring] = true
99
+ @payment.params[:shopper] = nil
100
+ end
101
+
102
+ [:reference, :email].each do |attr|
103
+ it_should_validate_request_param(:shopper) do
104
+ @payment.params[:recurring] = true
105
+ @payment.params[:shopper][attr] = ''
106
+ end
107
+ end
108
+
109
+ it "includes the creditcard details" do
110
+ xpath('./payment:card') do |card|
111
+ # there's no reason why Nokogiri should escape these characters, but as long as they're correct
112
+ card.text('./payment:holderName').should == 'Simon わくわく Hopper'
113
+ card.text('./payment:number').should == '4444333322221111'
114
+ card.text('./payment:cvc').should == '737'
115
+ card.text('./payment:expiryMonth').should == '12'
116
+ card.text('./payment:expiryYear').should == '2012'
117
+ end
118
+ end
119
+
120
+ it "formats the creditcard’s expiry month as a two digit number" do
121
+ @payment.params[:card][:expiry_month] = 6
122
+ text('./payment:card/payment:expiryMonth').should == '06'
123
+ end
124
+
125
+ it "includes the necessary recurring and one-click contract info if the `:recurring' param is truthful" do
126
+ xpath('./payment:recurring/payment:contract').should be_empty
127
+ @payment.params[:recurring] = true
128
+ text('./payment:recurring/payment:contract').should == 'RECURRING,ONECLICK'
129
+ end
130
+ end
131
+
132
+ describe_response_from :authorise_payment, AUTHORISE_RESPONSE do
133
+ it_should_return_params_for_each_xml_backend({
134
+ :psp_reference => '9876543210987654',
135
+ :result_code => 'Authorised',
136
+ :auth_code => '1234',
137
+ :refusal_reason => ''
138
+ })
139
+
140
+ describe "with a authorized response" do
141
+ it "returns that the request was authorised" do
142
+ @response.should be_success
143
+ @response.should be_authorized
144
+ end
145
+ end
146
+
147
+ describe "with a `declined' response" do
148
+ before do
149
+ stub_net_http(AUTHORISATION_DECLINED_RESPONSE)
150
+ @response = @payment.authorise_payment
151
+ end
152
+
153
+ it "returns that the request was not authorised" do
154
+ @response.should_not be_success
155
+ @response.should_not be_authorized
156
+ end
157
+ end
158
+
159
+ describe "with a `invalid' response" do
160
+ before do
161
+ stub_net_http(AUTHORISE_REQUEST_INVALID_RESPONSE % 'validation 101 Invalid card number')
162
+ @response = @payment.authorise_payment
163
+ end
164
+
165
+ it "returns that the request was not authorised" do
166
+ @response.should_not be_success
167
+ @response.should_not be_authorized
168
+ end
169
+
170
+ it "it returns that the request was invalid" do
171
+ @response.should be_invalid_request
172
+ end
173
+
174
+ it "returns the fault message from #refusal_reason" do
175
+ @response.refusal_reason.should == 'validation 101 Invalid card number'
176
+ @response.params[:refusal_reason].should == 'validation 101 Invalid card number'
177
+ end
178
+
179
+ it "returns creditcard validation errors" do
180
+ [
181
+ ["validation 101 Invalid card number", [:number, 'is not a valid creditcard number']],
182
+ ["validation 103 CVC is not the right length", [:cvc, 'is not the right length']],
183
+ ["validation 128 Card Holder Missing", [:holder_name, 'can\'t be blank']],
184
+ ["validation Couldn't parse expiry year", [:expiry_year, 'could not be recognized']],
185
+ ["validation Expiry month should be between 1 and 12 inclusive", [:expiry_month, 'could not be recognized']],
186
+ ].each do |message, error|
187
+ response_with_fault_message(message).error.should == error
188
+ end
189
+ end
190
+
191
+ it "returns any other fault messages on `base'" do
192
+ message = "validation 130 Reference Missing"
193
+ response_with_fault_message(message).error.should == [:base, message]
194
+ end
195
+
196
+ it "prepends the error attribute with the given prefix, except for :base" do
197
+ [
198
+ ["validation 101 Invalid card number", [:card_number, 'is not a valid creditcard number']],
199
+ ["validation 130 Reference Missing", [:base, "validation 130 Reference Missing"]],
200
+ ].each do |message, error|
201
+ response_with_fault_message(message).error(:card).should == error
202
+ end
203
+ end
204
+
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
+ private
219
+
220
+ def response_with_fault_message(message)
221
+ stub_net_http(AUTHORISE_REQUEST_INVALID_RESPONSE % message)
222
+ @response = @payment.authorise_payment
223
+ end
224
+ end
225
+ end
226
+
227
+ describe_request_body_of :authorise_recurring_payment do
228
+ it_should_behave_like "recurring payment requests"
229
+
230
+ it_should_validate_request_parameters :merchant_account,
231
+ :reference,
232
+ :amount => [:currency, :value],
233
+ :shopper => [:reference, :email]
234
+
235
+ it "includes the contract type, which is `RECURRING'" do
236
+ text('./payment:recurring/payment:contract').should == 'RECURRING'
237
+ end
238
+
239
+ it "uses the latest recurring detail reference, by default" do
240
+ @payment.params[:recurring_detail_reference] = nil
241
+ text('./payment:selectedRecurringDetailReference').should == 'LATEST'
242
+ end
243
+
244
+ it "obviously includes the obligatory self-‘describing’ nonsense parameters" do
245
+ text('./payment:shopperInteraction').should == 'ContAuth'
246
+ end
247
+
248
+ it "does not include any creditcard details" do
249
+ xpath('./payment:card').should be_empty
250
+ end
251
+ end
252
+
253
+ describe_response_from :authorise_recurring_payment, AUTHORISE_RESPONSE do
254
+ it_should_return_params_for_each_xml_backend({
255
+ :psp_reference => '9876543210987654',
256
+ :result_code => 'Authorised',
257
+ :auth_code => '1234',
258
+ :refusal_reason => ''
259
+ })
260
+ end
261
+
262
+ describe_request_body_of :authorise_one_click_payment do
263
+ it_should_behave_like "recurring payment requests"
264
+
265
+ it_should_validate_request_parameters :merchant_account,
266
+ :reference,
267
+ :recurring_detail_reference,
268
+ :amount => [:currency, :value],
269
+ :shopper => [:reference, :email],
270
+ :card => [:cvc]
271
+
272
+ it "includes the contract type, which is `ONECLICK'" do
273
+ text('./payment:recurring/payment:contract').should == 'ONECLICK'
274
+ end
275
+
276
+ it "does not include the self-‘describing’ nonsense parameters" do
277
+ xpath('./payment:shopperInteraction').should be_empty
278
+ end
279
+
280
+ it "includes only the creditcard's CVC code" do
281
+ xpath('./payment:card') do |card|
282
+ card.text('./payment:cvc').should == '737'
283
+
284
+ card.xpath('./payment:holderName').should be_empty
285
+ card.xpath('./payment:number').should be_empty
286
+ card.xpath('./payment:expiryMonth').should be_empty
287
+ card.xpath('./payment:expiryYear').should be_empty
288
+ end
289
+ end
290
+ end
291
+
292
+ describe_response_from :authorise_one_click_payment, AUTHORISE_RESPONSE do
293
+ it_should_return_params_for_each_xml_backend({
294
+ :psp_reference => '9876543210987654',
295
+ :result_code => 'Authorised',
296
+ :auth_code => '1234',
297
+ :refusal_reason => ''
298
+ })
299
+ end
300
+
301
+ describe_modification_request_body_of :capture do
302
+ it_should_validate_request_parameters :merchant_account,
303
+ :psp_reference,
304
+ :amount => [:currency, :value]
305
+
306
+ it "includes the amount to capture" do
307
+ xpath('./payment:modificationAmount') do |amount|
308
+ amount.text('./common:currency').should == 'EUR'
309
+ amount.text('./common:value').should == '1234'
310
+ end
311
+ end
312
+ end
313
+
314
+ describe_response_from :capture, CAPTURE_RESPONSE % '[capture-received]' do
315
+ it_should_return_params_for_each_xml_backend({
316
+ :psp_reference => '8512867956198946',
317
+ :response => '[capture-received]'
318
+ })
319
+
320
+ describe "with a successful response" do
321
+ it "returns that the request was received successfully" do
322
+ @response.should be_success
323
+ end
324
+ end
325
+
326
+ describe "with a failed response" do
327
+ before do
328
+ stub_net_http(CAPTURE_RESPONSE % 'failed')
329
+ @response = @payment.capture
330
+ end
331
+
332
+ it "returns that the request was not received successfully" do
333
+ @response.should_not be_success
334
+ end
335
+ end
336
+ end
337
+
338
+ describe_modification_request_body_of :refund do
339
+ it_should_validate_request_parameters :merchant_account,
340
+ :psp_reference,
341
+ :amount => [:currency, :value]
342
+
343
+ it "includes the amount to refund" do
344
+ xpath('./payment:modificationAmount') do |amount|
345
+ amount.text('./common:currency').should == 'EUR'
346
+ amount.text('./common:value').should == '1234'
347
+ end
348
+ end
349
+ end
350
+
351
+ describe_response_from :refund, REFUND_RESPONSE % '[refund-received]' do
352
+ it_should_return_params_for_each_xml_backend({
353
+ :psp_reference => '8512865475512126',
354
+ :response => '[refund-received]'
355
+ })
356
+
357
+ describe "with a successful response" do
358
+ it "returns that the request was received successfully" do
359
+ @response.should be_success
360
+ end
361
+ end
362
+
363
+ describe "with a failed response" do
364
+ before do
365
+ stub_net_http(REFUND_RESPONSE % 'failed')
366
+ @response = @payment.refund
367
+ end
368
+
369
+ it "returns that the request was not received successfully" do
370
+ @response.should_not be_success
371
+ end
372
+ end
373
+ end
374
+
375
+ describe_modification_request_body_of :cancel_or_refund, 'cancelOrRefund' do
376
+ it_should_validate_request_parameters :merchant_account,
377
+ :psp_reference
378
+ end
379
+
380
+ describe_response_from :cancel_or_refund, CANCEL_OR_REFUND_RESPONSE % '[cancelOrRefund-received]' do
381
+ it_should_return_params_for_each_xml_backend({
382
+ :psp_reference => '8512865521218306',
383
+ :response => '[cancelOrRefund-received]'
384
+ })
385
+
386
+ describe "with a successful response" do
387
+ it "returns that the request was received successfully" do
388
+ @response.should be_success
389
+ end
390
+ end
391
+
392
+ describe "with a failed response" do
393
+ before do
394
+ stub_net_http(CANCEL_OR_REFUND_RESPONSE % 'failed')
395
+ @response = @payment.cancel_or_refund
396
+ end
397
+
398
+ it "returns that the request was not received successfully" do
399
+ @response.should_not be_success
400
+ end
401
+ end
402
+ end
403
+
404
+ describe_modification_request_body_of :cancel do
405
+ it_should_validate_request_parameters :merchant_account,
406
+ :psp_reference
407
+ end
408
+
409
+ describe_response_from :cancel, CANCEL_RESPONSE % '[cancel-received]' do
410
+ it_should_return_params_for_each_xml_backend({
411
+ :psp_reference => '8612865544848013',
412
+ :response => '[cancel-received]'
413
+ })
414
+
415
+ describe "with a successful response" do
416
+ it "returns that the request was received successfully" do
417
+ @response.should be_success
418
+ end
419
+ end
420
+
421
+ describe "with a failed response" do
422
+ before do
423
+ stub_net_http(CANCEL_RESPONSE % 'failed')
424
+ @response = @payment.cancel
425
+ end
426
+
427
+ it "returns that the request was not received successfully" do
428
+ @response.should_not be_success
429
+ end
430
+ end
431
+ end
432
+
433
+ private
434
+
435
+ def node_for_current_method
436
+ node_for_current_object_and_method.xpath('//payment:authorise/payment:paymentRequest')
437
+ end
438
+ end
439
+