ideal 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,766 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../helper', __FILE__)
4
+
5
+ module IdealTestCases
6
+ # This method is called at the end of the file when all fixture data has been loaded.
7
+ def self.setup_ideal_gateway!
8
+ Ideal::Gateway.class_eval do
9
+ self.acquirer = :ing
10
+
11
+ self.merchant_id = '123456789'
12
+
13
+ self.passphrase = 'passphrase'
14
+ self.private_key = PRIVATE_KEY
15
+ self.private_certificate = PRIVATE_CERTIFICATE
16
+ self.ideal_certificate = IDEAL_CERTIFICATE
17
+ end
18
+ end
19
+
20
+ VALID_PURCHASE_OPTIONS = {
21
+ :issuer_id => '0001',
22
+ :expiration_period => 'PT10M',
23
+ :return_url => 'http://return_to.example.com',
24
+ :order_id => '12345678901',
25
+ :description => 'A classic Dutch windmill',
26
+ :entrance_code => '1234'
27
+ }
28
+
29
+ class ClassMethodsTest < Test::Unit::TestCase
30
+ def test_merchant_id
31
+ assert_equal Ideal::Gateway.merchant_id, '123456789'
32
+ end
33
+
34
+ def test_verify_live_url_for_ing
35
+ Ideal::Gateway.acquirer = :ing
36
+ assert_equal 'https://ideal.secure-ing.com/ideal/iDeal', Ideal::Gateway.live_url
37
+ end
38
+
39
+ def test_verify_live_url_for_rabobank
40
+ Ideal::Gateway.acquirer = :rabobank
41
+ assert_equal 'https://ideal.rabobank.nl/ideal/iDeal', Ideal::Gateway.live_url
42
+ end
43
+
44
+ def test_verify_live_urls_for_abnamro
45
+ Ideal::Gateway.acquirer = :abnamro
46
+ assert_equal 'https://idealm.abnamro.nl/nl/issuerInformation/getIssuerInformation.xml', Ideal::Gateway.live_directory_url
47
+ assert_equal 'https://idealm.abnamro.nl/nl/acquirerTrxRegistration/getAcquirerTrxRegistration.xml', Ideal::Gateway.live_transaction_url
48
+ assert_equal 'https://idealm.abnamro.nl/nl/acquirerStatusInquiry/getAcquirerStatusInquiry.xml', Ideal::Gateway.live_status_url
49
+ end
50
+
51
+ def test_does_not_allow_configuration_of_unknown_acquirers
52
+ assert_raise(ArgumentError) do
53
+ Ideal::Gateway.acquirer = :unknown
54
+ end
55
+ end
56
+
57
+ def test_acquirers
58
+ assert_equal 'https://ideal.rabobank.nl/ideal/iDeal', Ideal::Gateway.acquirers['rabobank']['live_url']
59
+ assert_equal 'https://ideal.secure-ing.com/ideal/iDeal', Ideal::Gateway.acquirers['ing']['live_url']
60
+ assert_equal 'https://idealm.abnamro.nl/nl/acquirerTrxRegistration/getAcquirerTrxRegistration.xml', Ideal::Gateway.acquirers['abnamro']['live_transaction_url']
61
+ end
62
+
63
+ def test_private_certificate_returns_a_loaded_Certificate_instance
64
+ assert_equal Ideal::Gateway.private_certificate.to_text,
65
+ OpenSSL::X509::Certificate.new(PRIVATE_CERTIFICATE).to_text
66
+ end
67
+
68
+ def test_private_key_returns_a_loaded_PKey_RSA_instance
69
+ assert_equal Ideal::Gateway.private_key.to_text,
70
+ OpenSSL::PKey::RSA.new(PRIVATE_KEY, Ideal::Gateway.passphrase).to_text
71
+ end
72
+
73
+ def test_ideal_certificate_returns_a_loaded_Certificate_instance
74
+ assert_equal Ideal::Gateway.ideal_certificate.to_text,
75
+ OpenSSL::X509::Certificate.new(IDEAL_CERTIFICATE).to_text
76
+ end
77
+ end
78
+
79
+ class GeneralTest < Test::Unit::TestCase
80
+ def setup
81
+ @gateway = Ideal::Gateway.new
82
+ end
83
+
84
+ def test_optional_initialization_options
85
+ assert_equal 0, Ideal::Gateway.new.sub_id
86
+ assert_equal 1, Ideal::Gateway.new(:sub_id => 1).sub_id
87
+ end
88
+
89
+ def test_returns_the_test_url_when_in_the_test_env
90
+ Ideal::Gateway.acquirer = :ing
91
+ Ideal::Gateway.environment = :test
92
+ assert_equal Ideal::Gateway.test_url, @gateway.send(:request_url, :directory)
93
+ end
94
+
95
+ def test_returns_the_live_url_when_not_in_the_test_env
96
+ Ideal::Gateway.acquirer = :ing
97
+ Ideal::Gateway.environment = :live
98
+ assert_equal Ideal::Gateway.live_url, @gateway.send(:request_url, :directory)
99
+ end
100
+
101
+ def test_returns_the_special_urls_for_abnamro_when_in_the_test_env
102
+ Ideal::Gateway.acquirer = :abnamro
103
+ Ideal::Gateway.environment = :test
104
+ assert_equal Ideal::Gateway.test_directory_url, @gateway.send(:request_url, :directory)
105
+ assert_equal Ideal::Gateway.test_transaction_url, @gateway.send(:request_url, :transaction)
106
+ assert_equal Ideal::Gateway.test_status_url, @gateway.send(:request_url, :status)
107
+ end
108
+
109
+ def test_returns_created_at_timestamp
110
+ timestamp = '2001-12-17T09:30:47.000Z'
111
+ Time.any_instance.stubs(:gmtime).returns(DateTime.parse(timestamp))
112
+
113
+ assert_equal timestamp, @gateway.send(:created_at_timestamp)
114
+ end
115
+
116
+ def test_ruby_to_java_keys_conversion
117
+ keys = [
118
+ [:acquirer_transaction_request, 'AcquirerTrxReq'],
119
+ [:acquirer_status_request, 'AcquirerStatusReq'],
120
+ [:directory_request, 'DirectoryReq'],
121
+ [:created_at, 'createDateTimeStamp'],
122
+ [:issuer, 'Issuer'],
123
+ [:merchant, 'Merchant'],
124
+ [:transaction, 'Transaction'],
125
+ [:issuer_id, 'issuerID'],
126
+ [:merchant_id, 'merchantID'],
127
+ [:sub_id, 'subID'],
128
+ [:token_code, 'tokenCode'],
129
+ [:merchant_return_url, 'merchantReturnURL'],
130
+ [:purchase_id, 'purchaseID'],
131
+ [:expiration_period, 'expirationPeriod'],
132
+ [:entrance_code, 'entranceCode']
133
+ ]
134
+
135
+ keys.each do |key, expected_key|
136
+ assert_equal expected_key, @gateway.send(:javaize_key, key)
137
+ end
138
+ end
139
+
140
+ def test_does_not_convert_unknown_key_to_java_key
141
+ assert_equal 'not_a_registered_key', @gateway.send(:javaize_key, :not_a_registered_key)
142
+ end
143
+
144
+ def test_token_generation
145
+ expected_token = Digest::SHA1.hexdigest(OpenSSL::X509::Certificate.new(PRIVATE_CERTIFICATE).to_der).upcase
146
+ assert_equal expected_token, @gateway.send(:token)
147
+ end
148
+
149
+ def test_token_code_generation
150
+ Ideal::Gateway.acquirer = :ing
151
+ message = "Top\tsecret\tman.\nI could tell you, but then I'd have to kill you…"
152
+ stripped_message = message.gsub(/\s/m, '')
153
+
154
+ sha1 = OpenSSL::Digest::SHA1.new
155
+ OpenSSL::Digest::SHA1.stubs(:new).returns(sha1)
156
+
157
+ signature = Ideal::Gateway.private_key.sign(sha1, stripped_message)
158
+ encoded_signature = Base64.encode64(signature).strip.gsub(/\n/, '')
159
+
160
+ assert_equal encoded_signature, @gateway.send(:token_code, message)
161
+ end
162
+
163
+ def test_token_code_generation_on_abn_amro
164
+ Ideal::Gateway.acquirer = :abnamro
165
+ message = "Top\tsecret\tman.\nI could tell you, but\r then I'd have to kill you…"
166
+ stripped_message = message.gsub(/(\f|\n|\r|\t|\v)/m, '')
167
+
168
+ sha1 = OpenSSL::Digest::SHA1.new
169
+ OpenSSL::Digest::SHA1.stubs(:new).returns(sha1)
170
+
171
+ signature = Ideal::Gateway.private_key.sign(sha1, stripped_message)
172
+ encoded_signature = Base64.encode64(signature).strip.gsub(/\n/, '')
173
+
174
+ assert_equal encoded_signature, @gateway.send(:token_code, message)
175
+ end
176
+
177
+ def test_posts_data_with_ssl_to_request_url_and_return_the_correct_response_for_test
178
+ Ideal::Gateway.environment = :test
179
+ Ideal::Response.expects(:new).with('response', :test => true)
180
+ @gateway.expects(:ssl_post).with(@gateway.request_url(:directory), 'data').returns('response')
181
+ @gateway.send(:post_data, @gateway.request_url(:directory), 'data', Ideal::Response)
182
+ end
183
+
184
+ def test_posts_data_with_ssl_to_request_url_and_return_the_correct_response_for_live
185
+ Ideal::Gateway.environment = :live
186
+ Ideal::Response.expects(:new).with('response', :test => false)
187
+ @gateway.expects(:ssl_post).with(@gateway.request_url(:directory), 'data').returns('response')
188
+ @gateway.send(:post_data, @gateway.request_url(:directory), 'data', Ideal::Response)
189
+ end
190
+ end
191
+
192
+ class XMLBuildingTest < Test::Unit::TestCase
193
+ def setup
194
+ @gateway = Ideal::Gateway.new
195
+ end
196
+
197
+ def test_contains_correct_info_in_root_node
198
+ expected_xml = Builder::XmlMarkup.new
199
+ expected_xml.instruct!
200
+ expected_xml.tag!('AcquirerTrxReq', 'xmlns' => Ideal::Gateway::XML_NAMESPACE, 'version' => Ideal::Gateway::API_VERSION) {}
201
+
202
+ assert_equal expected_xml.target!, @gateway.send(:xml_for, :acquirer_transaction_request, [])
203
+ end
204
+
205
+ def test_creates_correct_xml_with_java_keys_from_array_with_ruby_keys
206
+ expected_xml = Builder::XmlMarkup.new
207
+ expected_xml.instruct!
208
+ expected_xml.tag!('AcquirerTrxReq', 'xmlns' => Ideal::Gateway::XML_NAMESPACE, 'version' => Ideal::Gateway::API_VERSION) do
209
+ expected_xml.tag!('a_parent') do
210
+ expected_xml.tag!('createDateTimeStamp', '2009-01-26')
211
+ end
212
+ end
213
+
214
+ assert_equal expected_xml.target!, @gateway.send(:xml_for, :acquirer_transaction_request, [[:a_parent, [[:created_at, '2009-01-26']]]])
215
+ end
216
+ end
217
+
218
+ class RequestBodyBuildingTest < Test::Unit::TestCase
219
+ def setup
220
+ @gateway = Ideal::Gateway.new
221
+
222
+ @gateway.stubs(:created_at_timestamp).returns('created_at_timestamp')
223
+ @gateway.stubs(:token).returns('the_token')
224
+ @gateway.stubs(:token_code)
225
+
226
+ @transaction_id = '0001023456789112'
227
+ end
228
+
229
+ def test_build_transaction_request_body_raises_ArgumentError_with_missing_required_options
230
+ options = VALID_PURCHASE_OPTIONS.dup
231
+ options.keys.each do |key|
232
+ options.delete(key)
233
+
234
+ assert_raise(ArgumentError) do
235
+ @gateway.send(:build_transaction_request_body, 100, options)
236
+ end
237
+ end
238
+ end
239
+
240
+ def test_valid_with_valid_options
241
+ assert_not_nil @gateway.send(:build_transaction_request_body, 4321, VALID_PURCHASE_OPTIONS)
242
+ end
243
+
244
+ def test_checks_that_fields_are_not_too_long
245
+ assert_raise ArgumentError do
246
+ @gateway.send(:build_transaction_request_body, 1234567890123, VALID_PURCHASE_OPTIONS) # 13 chars
247
+ end
248
+
249
+ [
250
+ [:order_id, '12345678901234567'], # 17 chars,
251
+ [:description, '123456789012345678901234567890123'], # 33 chars
252
+ [:entrance_code, '12345678901234567890123456789012345678901'] # 41
253
+ ].each do |key, value|
254
+ options = VALID_PURCHASE_OPTIONS.dup
255
+ options[key] = value
256
+
257
+ assert_raise ArgumentError do
258
+ @gateway.send(:build_transaction_request_body, 4321, options)
259
+ end
260
+ end
261
+ end
262
+
263
+ def test_checks_that_fields_do_not_contain_diacritical_characters
264
+ assert_raise ArgumentError do
265
+ @gateway.send(:build_transaction_request_body, 'graphème', VALID_PURCHASE_OPTIONS)
266
+ end
267
+
268
+ [:order_id, :description, :entrance_code].each do |key, value|
269
+ options = VALID_PURCHASE_OPTIONS.dup
270
+ options[key] = 'graphème'
271
+
272
+ assert_raise ArgumentError do
273
+ @gateway.send(:build_transaction_request_body, 4321, options)
274
+ end
275
+ end
276
+ end
277
+
278
+ def test_builds_a_transaction_request_body
279
+ money = 4321
280
+
281
+ message = 'created_at_timestamp' +
282
+ VALID_PURCHASE_OPTIONS[:issuer_id] +
283
+ Ideal::Gateway.merchant_id +
284
+ @gateway.sub_id.to_s +
285
+ VALID_PURCHASE_OPTIONS[:return_url] +
286
+ VALID_PURCHASE_OPTIONS[:order_id] +
287
+ money.to_s +
288
+ Ideal::Gateway::CURRENCY +
289
+ Ideal::Gateway::LANGUAGE +
290
+ VALID_PURCHASE_OPTIONS[:description] +
291
+ VALID_PURCHASE_OPTIONS[:entrance_code]
292
+
293
+ @gateway.expects(:token_code).with(message).returns('the_token_code')
294
+
295
+ @gateway.expects(:xml_for).with(:acquirer_transaction_request, [
296
+ [:created_at, 'created_at_timestamp'],
297
+ [:issuer, [[:issuer_id, VALID_PURCHASE_OPTIONS[:issuer_id]]]],
298
+
299
+ [:merchant, [
300
+ [:merchant_id, Ideal::Gateway.merchant_id],
301
+ [:sub_id, @gateway.sub_id],
302
+ [:authentication, Ideal::Gateway::AUTHENTICATION_TYPE],
303
+ [:token, 'the_token'],
304
+ [:token_code, 'the_token_code'],
305
+ [:merchant_return_url, VALID_PURCHASE_OPTIONS[:return_url]]
306
+ ]],
307
+
308
+ [:transaction, [
309
+ [:purchase_id, VALID_PURCHASE_OPTIONS[:order_id]],
310
+ [:amount, money],
311
+ [:currency, Ideal::Gateway::CURRENCY],
312
+ [:expiration_period, VALID_PURCHASE_OPTIONS[:expiration_period]],
313
+ [:language, Ideal::Gateway::LANGUAGE],
314
+ [:description, VALID_PURCHASE_OPTIONS[:description]],
315
+ [:entrance_code, VALID_PURCHASE_OPTIONS[:entrance_code]]
316
+ ]]
317
+ ])
318
+
319
+ @gateway.send(:build_transaction_request_body, money, VALID_PURCHASE_OPTIONS)
320
+ end
321
+
322
+ def test_builds_a_directory_request_body
323
+ message = 'created_at_timestamp' + Ideal::Gateway.merchant_id + @gateway.sub_id.to_s
324
+ @gateway.expects(:token_code).with(message).returns('the_token_code')
325
+
326
+ @gateway.expects(:xml_for).with(:directory_request, [
327
+ [:created_at, 'created_at_timestamp'],
328
+ [:merchant, [
329
+ [:merchant_id, Ideal::Gateway.merchant_id],
330
+ [:sub_id, @gateway.sub_id],
331
+ [:authentication, Ideal::Gateway::AUTHENTICATION_TYPE],
332
+ [:token, 'the_token'],
333
+ [:token_code, 'the_token_code']
334
+ ]]
335
+ ])
336
+
337
+ @gateway.send(:build_directory_request_body)
338
+ end
339
+
340
+ def test_builds_a_status_request_body_raises_ArgumentError_with_missing_required_options
341
+ assert_raise(ArgumentError) do
342
+ @gateway.send(:build_status_request_body, {})
343
+ end
344
+ end
345
+
346
+ def test_builds_a_status_request_body
347
+ options = { :transaction_id => @transaction_id }
348
+
349
+ message = 'created_at_timestamp' + Ideal::Gateway.merchant_id + @gateway.sub_id.to_s + options[:transaction_id]
350
+ @gateway.expects(:token_code).with(message).returns('the_token_code')
351
+
352
+ @gateway.expects(:xml_for).with(:acquirer_status_request, [
353
+ [:created_at, 'created_at_timestamp'],
354
+ [:merchant, [
355
+ [:merchant_id, Ideal::Gateway.merchant_id],
356
+ [:sub_id, @gateway.sub_id],
357
+ [:authentication, Ideal::Gateway::AUTHENTICATION_TYPE],
358
+ [:token, 'the_token'],
359
+ [:token_code, 'the_token_code']
360
+ ]],
361
+
362
+ [:transaction, [
363
+ [:transaction_id, options[:transaction_id]]
364
+ ]],
365
+ ])
366
+
367
+ @gateway.send(:build_status_request_body, options)
368
+ end
369
+ end
370
+
371
+ class GeneralResponseTest < Test::Unit::TestCase
372
+ def test_resturns_if_it_is_a_test_request
373
+ assert Ideal::Response.new(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS, :test => true).test?
374
+
375
+ assert !Ideal::Response.new(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS, :test => false).test?
376
+ assert !Ideal::Response.new(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS).test?
377
+ end
378
+ end
379
+
380
+ class SuccessfulResponseTest < Test::Unit::TestCase
381
+ def setup
382
+ @response = Ideal::Response.new(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS)
383
+ end
384
+
385
+ def test_initializes_with_only_response_body
386
+ assert_equal REXML::Document.new(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS).root.to_s,
387
+ @response.instance_variable_get(:@response).to_s
388
+ end
389
+
390
+ def test_successful
391
+ assert @response.success?
392
+ end
393
+
394
+ def test_returns_no_error_messages
395
+ assert_nil @response.error_message
396
+ end
397
+
398
+ def test_returns_no_error_code
399
+ assert_nil @response.error_code
400
+ end
401
+ end
402
+
403
+ class ErrorResponseTest < Test::Unit::TestCase
404
+ def setup
405
+ @response = Ideal::Response.new(ERROR_RESPONSE)
406
+ end
407
+
408
+ def test_unsuccessful
409
+ assert !@response.success?
410
+ end
411
+
412
+ def test_returns_error_messages
413
+ assert_equal 'Failure in system', @response.error_message
414
+ assert_equal 'System generating error: issuer', @response.error_details
415
+ assert_equal 'Betalen met iDEAL is nu niet mogelijk.', @response.consumer_error_message
416
+ end
417
+
418
+ def test_returns_error_code
419
+ assert_equal 'SO1000', @response.error_code
420
+ end
421
+
422
+ def test_returns_error_type
423
+ [
424
+ ['IX1000', :xml],
425
+ ['SO1000', :system],
426
+ ['SE2000', :security],
427
+ ['BR1200', :value],
428
+ ['AP1000', :application]
429
+ ].each do |code, type|
430
+ @response.stubs(:error_code).returns(code)
431
+ assert_equal type, @response.error_type
432
+ end
433
+ end
434
+ end
435
+
436
+ class DirectoryTest < Test::Unit::TestCase
437
+ def setup
438
+ @gateway = Ideal::Gateway.new
439
+ end
440
+
441
+ def test_returns_a_list_with_only_one_issuer
442
+ @gateway.stubs(:build_directory_request_body).returns('the request body')
443
+ @gateway.expects(:ssl_post).with(@gateway.request_url(:directory), 'the request body').returns(DIRECTORY_RESPONSE_WITH_ONE_ISSUER)
444
+
445
+ expected_issuers = [{ :id => '1006', :name => 'ABN AMRO Bank' }]
446
+
447
+ directory_response = @gateway.issuers
448
+ assert_instance_of Ideal::DirectoryResponse, directory_response
449
+ assert_equal expected_issuers, directory_response.list
450
+ end
451
+
452
+ def test_returns_list_of_issuers_from_response
453
+ @gateway.stubs(:build_directory_request_body).returns('the request body')
454
+ @gateway.expects(:ssl_post).with(@gateway.request_url(:directory), 'the request body').returns(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS)
455
+
456
+ expected_issuers = [
457
+ { :id => '1006', :name => 'ABN AMRO Bank' },
458
+ { :id => '1003', :name => 'Postbank' },
459
+ { :id => '1005', :name => 'Rabobank' },
460
+ { :id => '1017', :name => 'Asr bank' },
461
+ { :id => '1023', :name => 'Van Lanschot' }
462
+ ]
463
+
464
+ directory_response = @gateway.issuers
465
+ assert_instance_of Ideal::DirectoryResponse, directory_response
466
+ assert_equal expected_issuers, directory_response.list
467
+ end
468
+ end
469
+
470
+ class SetupPurchaseTest < Test::Unit::TestCase
471
+ def setup
472
+ @gateway = Ideal::Gateway.new
473
+
474
+ @gateway.stubs(:build_transaction_request_body).with(4321, VALID_PURCHASE_OPTIONS).returns('the request body')
475
+ @gateway.expects(:ssl_post).with(@gateway.request_url(:transaction), 'the request body').returns(ACQUIRER_TRANSACTION_RESPONSE)
476
+
477
+ @setup_purchase_response = @gateway.setup_purchase(4321, VALID_PURCHASE_OPTIONS)
478
+ end
479
+
480
+ def test_setup_purchase_returns_IdealTransactionResponse
481
+ assert_instance_of Ideal::TransactionResponse, @setup_purchase_response
482
+ end
483
+
484
+ def test_setup_purchase_returns_response_with_service_url
485
+ assert_equal 'https://ideal.example.com/long_service_url?X009=BETAAL&X010=20', @setup_purchase_response.service_url
486
+ end
487
+
488
+ def test_setup_purchase_returns_response_with_transaction_and_order_ids
489
+ assert_equal '0001023456789112', @setup_purchase_response.transaction_id
490
+ assert_equal 'iDEAL-aankoop 21', @setup_purchase_response.order_id
491
+ end
492
+ end
493
+
494
+ class CapturePurchaseTest < Test::Unit::TestCase
495
+ def setup
496
+ @gateway = Ideal::Gateway.new
497
+
498
+ @gateway.stubs(:build_status_request_body).
499
+ with(:transaction_id => '0001023456789112').returns('the request body')
500
+ end
501
+
502
+ def test_setup_purchase_returns_IdealStatusResponse
503
+ expects_request_and_returns ACQUIRER_SUCCEEDED_STATUS_RESPONSE
504
+ assert_instance_of Ideal::StatusResponse, @gateway.capture('0001023456789112')
505
+ end
506
+
507
+ # Because we don't have a real private key and certificate we stub
508
+ # verified? to return true. However, this is properly tested in the remote
509
+ # tests.
510
+ def test_capture_of_successful_payment
511
+ Ideal::StatusResponse.any_instance.stubs(:verified?).returns(true)
512
+
513
+ expects_request_and_returns ACQUIRER_SUCCEEDED_STATUS_RESPONSE
514
+ capture_response = @gateway.capture('0001023456789112')
515
+
516
+ assert capture_response.success?
517
+ end
518
+
519
+ def test_capture_of_failed_payment
520
+ expects_request_and_returns ACQUIRER_FAILED_STATUS_RESPONSE
521
+ capture_response = @gateway.capture('0001023456789112')
522
+
523
+ assert !capture_response.success?
524
+ end
525
+
526
+ def test_capture_of_successful_payment_but_message_does_not_match_signature
527
+ expects_request_and_returns ACQUIRER_SUCCEEDED_BUT_WRONG_SIGNATURE_STATUS_RESPONSE
528
+ capture_response = @gateway.capture('0001023456789112')
529
+
530
+ assert !capture_response.success?
531
+ end
532
+
533
+ def test_capture_of_consumer_fields
534
+ expects_request_and_returns ACQUIRER_SUCCEEDED_STATUS_RESPONSE
535
+ capture_response = @gateway.capture('0001023456789112')
536
+
537
+ assert_equal '0949298989', capture_response.consumer_account_number
538
+ assert_equal 'Onderheuvel', capture_response.consumer_name
539
+ assert_equal 'DEN HAAG', capture_response.consumer_city
540
+ end
541
+
542
+ def test_returns_status
543
+ response = Ideal::StatusResponse.new(ACQUIRER_SUCCEEDED_STATUS_RESPONSE)
544
+ [
545
+ ['Success', :success],
546
+ ['Cancelled', :cancelled],
547
+ ['Expired', :expired],
548
+ ['Open', :open],
549
+ ['Failure', :failure]
550
+ ].each do |raw_status, expected_status|
551
+ response.stubs(:text).with("//status").returns(raw_status)
552
+ assert_equal expected_status, response.status
553
+ end
554
+ end
555
+
556
+ private
557
+
558
+ def expects_request_and_returns(str)
559
+ @gateway.expects(:ssl_post).with(@gateway.request_url(:status), 'the request body').returns(str)
560
+ end
561
+ end
562
+
563
+ ###
564
+ #
565
+ # Fixture data
566
+ #
567
+
568
+ PRIVATE_CERTIFICATE = %{-----BEGIN CERTIFICATE-----
569
+ MIIC+zCCAmSgAwIBAgIJALVAygHjnd8ZMA0GCSqGSIb3DQEBBQUAMF0xCzAJBgNV
570
+ BAYTAk5MMRYwFAYDVQQIEw1Ob29yZC1Ib2xsYW5kMRIwEAYDVQQHEwlBbXN0ZXJk
571
+ YW0xIjAgBgNVBAoTGWlERUFMIEFjdGl2ZU1lcmNoYW50IFRlc3QwHhcNMDkwMTMw
572
+ MTMxNzQ5WhcNMjQxMjExMDM1MjI5WjBdMQswCQYDVQQGEwJOTDEWMBQGA1UECBMN
573
+ Tm9vcmQtSG9sbGFuZDESMBAGA1UEBxMJQW1zdGVyZGFtMSIwIAYDVQQKExlpREVB
574
+ TCBBY3RpdmVNZXJjaGFudCBUZXN0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
575
+ gQDmBpi+RVvZBA01kdP5lV5bDzu6Jp1zy78qhxxwlG8WMdUh0Qtg0kkYmeThFPoh
576
+ 2c3BYuFQ+AA6f1R0Spb+hTNrBxkZaRnHCfMMD9LXquFjJ/lvSGnwkjvBmGzyTPZ1
577
+ LIunpejm8hH0MJPqpp5AIeXjp1mv7BXA9y0FqObrrLAPaQIDAQABo4HCMIG/MB0G
578
+ A1UdDgQWBBTLqGWJt5+Ri6vrOpqGZhINbRtXczCBjwYDVR0jBIGHMIGEgBTLqGWJ
579
+ t5+Ri6vrOpqGZhINbRtXc6FhpF8wXTELMAkGA1UEBhMCTkwxFjAUBgNVBAgTDU5v
580
+ b3JkLUhvbGxhbmQxEjAQBgNVBAcTCUFtc3RlcmRhbTEiMCAGA1UEChMZaURFQUwg
581
+ QWN0aXZlTWVyY2hhbnQgVGVzdIIJALVAygHjnd8ZMAwGA1UdEwQFMAMBAf8wDQYJ
582
+ KoZIhvcNAQEFBQADgYEAGtgkmME9tgaxJIU3T7v1/xbKr6A/iwmt3sCmfJEl4Pty
583
+ aUGaHFy1KB7xmkna8gomxMWL2zZkdv4t1iGeuVCl9n77SL3MzapotdeNNqahblcN
584
+ RBshYCpWpsQQPF45/R5Xp7rXWWsjxgip7qTBNpgTx+Z/VKQpuQsFjYCYq4UCf2Y=
585
+ -----END CERTIFICATE-----}
586
+
587
+ PRIVATE_KEY = %{-----BEGIN RSA PRIVATE KEY-----
588
+ MIICXAIBAAKBgQDmBpi+RVvZBA01kdP5lV5bDzu6Jp1zy78qhxxwlG8WMdUh0Qtg
589
+ 0kkYmeThFPoh2c3BYuFQ+AA6f1R0Spb+hTNrBxkZaRnHCfMMD9LXquFjJ/lvSGnw
590
+ kjvBmGzyTPZ1LIunpejm8hH0MJPqpp5AIeXjp1mv7BXA9y0FqObrrLAPaQIDAQAB
591
+ AoGAfkccz0ewVoDc5424+wk/FWpVdaoBQjKWLbiiqkMygNK2mKv0PSD0M+c4OUCU
592
+ 2MSDKikoXJTpOzPvny/bmLpzMMGn9YJiWEQ5WdaTdppffdylfGPBZXZkt5M9nxJA
593
+ NL3fPT79R79mkCF8cgNUbLtNL4woSoFKwRHDU2CGvtTbxqkCQQD+TY1sGJv1VTQi
594
+ MYYx3FlEOqw3jp/2q7QluTDDGmvmVOSFnAPfmX0rKEtnBmG4ID7IaG+IQFthDudL
595
+ 3trqGQdTAkEA54+RxyCZiXDfkh23cD0QaApZaBuk6cKkx6qeFxeg1T+/idGgtWJI
596
+ Qg3i9fHzOIFUXwk51R3xh5IimvMJZ9Ii0wJAb7yrsx9tB3MUoSGZkTb8kholqZOl
597
+ fcEcOqcQYemuF1qdvoc6vHi4osnlt7L6JOkmLPCWcQu2GwNtZczZ65pruQJBAJ3p
598
+ vbtzUuF01TKbC18Cda7N5/zkZUl5ENCNXTRYS7lBuQhuqc8okChjufSJpJlTMUuC
599
+ Sis5OV5/3ROYTEC+ADsCQCwq6VQ1kXRrM+3tkMwi2rZi73dsFVuFx8crlBOmvhkD
600
+ U7Ar9bW13qhBeH9px8RCRDMWTGQcxY/C/TEQc/qvhkI=
601
+ -----END RSA PRIVATE KEY-----}
602
+
603
+ IDEAL_CERTIFICATE = %{-----BEGIN CERTIFICATE-----
604
+ MIIEAzCCA3CgAwIBAgIQMIEnzk1UPrPDLOY9dc2cUjANBgkqhkiG9w0BAQUFADBf
605
+ MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXUlNBIERhdGEgU2VjdXJpdHksIEluYy4x
606
+ LjAsBgNVBAsTJVNlY3VyZSBTZXJ2ZXIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
607
+ HhcNMDQwNjA4MDAwMDAwWhcNMDUwNjA4MjM1OTU5WjCBvDELMAkGA1UEBhMCTkwx
608
+ FjAUBgNVBAgTDU5vb3JkLUhvbGxhbmQxEjAQBgNVBAcUCUFtc3RlcmRhbTEbMBkG
609
+ A1UEChQSQUJOIEFNUk8gQmFuayBOLlYuMRYwFAYDVQQLFA1JTi9OUy9FLUlORlJB
610
+ MTMwMQYDVQQLFCpUZXJtcyBvZiB1c2UgYXQgd3d3LnZlcmlzaWduLmNvbS9ycGEg
611
+ KGMpMDAxFzAVBgNVBAMUDnd3dy5hYm5hbXJvLm5sMIGfMA0GCSqGSIb3DQEBAQUA
612
+ A4GNADCBiQKBgQD1hPZlFD01ZdQu0GVLkUQ7tOwtVw/jmZ1Axu8v+3bxrjKX9Qi1
613
+ 0w6EIadCXScDMmhCstExVptaTEQ5hG3DedV2IpMcwe93B1lfyviNYlmc/XIol1B7
614
+ PM70mI9XUTYAoJpquEv8AaupRO+hgxQlz3FACHINJxEIMgdxa1iyoJfCKwIDAQAB
615
+ o4IBZDCCAWAwCQYDVR0TBAIwADALBgNVHQ8EBAMCBaAwPAYDVR0fBDUwMzAxoC+g
616
+ LYYraHR0cDovL2NybC52ZXJpc2lnbi5jb20vUlNBU2VjdXJlU2VydmVyLmNybDBE
617
+ BgNVHSAEPTA7MDkGC2CGSAGG+EUBBxcDMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8v
618
+ d3d3LnZlcmlzaWduLmNvbS9ycGEwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF
619
+ BwMCMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AudmVy
620
+ aXNpZ24uY29tMG0GCCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAh
621
+ MB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dv
622
+ LnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMA0GCSqGSIb3DQEBBQUAA34AY7BYsNvj
623
+ i5fjnEHPlGOd2yxseCHU54HDPPCZOoP9a9kVWGX8tuj2b1oeiOsIbI1viIo+O4eQ
624
+ ilZjTJIlLOkXk6uE8vQGjZy0BUnjNPkXOQGkTyj4jDxZ2z+z9Vy8BwfothdcYbZK
625
+ 48ZOp3u74DdEfQejNxBeqLODzrxQTV4=
626
+ -----END CERTIFICATE-----}
627
+
628
+ DIRECTORY_RESPONSE_WITH_ONE_ISSUER = %{<?xml version="1.0" encoding="UTF-8"?>
629
+ <DirectoryRes xmlns="http://www.idealdesk.com/Message" version="1.1.0">
630
+ <createDateTimeStamp>2001-12-17T09:30:47.0Z</createDateTimeStamp>
631
+ <Acquirer>
632
+ <acquirerID>0245</acquirerID>
633
+ </Acquirer>
634
+ <Directory>
635
+ <directoryDateTimeStamp>2004-11-10T10:15:12.145Z</directoryDateTimeStamp>
636
+ <Issuer>
637
+ <issuerID>1006</issuerID>
638
+ <issuerName>ABN AMRO Bank</issuerName>
639
+ <issuerList>Short</issuerList>
640
+ </Issuer>
641
+ </Directory>
642
+ </DirectoryRes>}
643
+
644
+ DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS = %{<?xml version="1.0" encoding="UTF-8"?>
645
+ <DirectoryRes xmlns="http://www.idealdesk.com/Message" version="1.1.0">
646
+ <createDateTimeStamp>2001-12-17T09:30:47.0Z</createDateTimeStamp>
647
+ <Acquirer>
648
+ <acquirerID>0245</acquirerID>
649
+ </Acquirer>
650
+ <Directory>
651
+ <directoryDateTimeStamp>2004-11-10T10:15:12.145Z</directoryDateTimeStamp>
652
+ <Issuer>
653
+ <issuerID>1006</issuerID>
654
+ <issuerName>ABN AMRO Bank</issuerName>
655
+ <issuerList>Short</issuerList>
656
+ </Issuer>
657
+ <Issuer>
658
+ <issuerID>1003</issuerID>
659
+ <issuerName>Postbank</issuerName>
660
+ <issuerList>Short</issuerList>
661
+ </Issuer>
662
+ <Issuer>
663
+ <issuerID>1005</issuerID>
664
+ <issuerName>Rabobank</issuerName>
665
+ <issuerList>Short</issuerList>
666
+ </Issuer>
667
+ <Issuer>
668
+ <issuerID>1017</issuerID>
669
+ <issuerName>Asr bank</issuerName>
670
+ <issuerList>Long</issuerList>
671
+ </Issuer>
672
+ <Issuer>
673
+ <issuerID>1023</issuerID>
674
+ <issuerName>Van Lanschot</issuerName>
675
+ <issuerList>Long</issuerList>
676
+ </Issuer>
677
+ </Directory>
678
+ </DirectoryRes>}
679
+
680
+ ACQUIRER_TRANSACTION_RESPONSE = %{<?xml version="1.0" encoding="UTF-8"?>
681
+ <AcquirerTrxRes xmlns="http://www.idealdesk.com/Message" version="1.1.0">
682
+ <createDateTimeStamp>2001-12-17T09:30:47.0Z</createDateTimeStamp>
683
+ <Acquirer>
684
+ <acquirerID>1545</acquirerID>
685
+ </Acquirer>
686
+ <Issuer>
687
+ <issuerAuthenticationURL>https://ideal.example.com/long_service_url?X009=BETAAL&amp;X010=20</issuerAuthenticationURL>
688
+ </Issuer>
689
+ <Transaction>
690
+ <transactionID>0001023456789112</transactionID>
691
+ <purchaseID>iDEAL-aankoop 21</purchaseID>
692
+ </Transaction>
693
+ </AcquirerTrxRes>}
694
+
695
+ ACQUIRER_SUCCEEDED_STATUS_RESPONSE = %{<?xml version="1.0" encoding="UTF-8"?>
696
+ <AcquirerStatusRes xmlns="http://www.idealdesk.com/Message" version="1.1.0">
697
+ <createDateTimeStamp>2001-12-17T09:30:47.0Z</createDateTimeStamp>
698
+ <Acquirer>
699
+ <acquirerID>1234</acquirerID>
700
+ </Acquirer>
701
+ <Transaction>
702
+ <transactionID>0001023456789112</transactionID>
703
+ <status>Success</status>
704
+ <consumerName>Onderheuvel</consumerName>
705
+ <consumerAccountNumber>0949298989</consumerAccountNumber>
706
+ <consumerCity>DEN HAAG</consumerCity>
707
+ </Transaction>
708
+ <Signature>
709
+ <signatureValue>db82/jpJRvKQKoiDvu33X0yoDAQpayJOaW2Y8zbR1qk1i3epvTXi+6g+QVBY93YzGv4w+Va+vL3uNmzyRjYsm2309d1CWFVsn5Mk24NLSvhYfwVHEpznyMqizALEVUNSoiSHRkZUDfXowBAyLT/tQVGbuUuBj+TKblY826nRa7U=</signatureValue>
710
+ <fingerprint>1E15A00E3D7DF085768749D4ABBA3284794D8AE9</fingerprint>
711
+ </Signature>
712
+ </AcquirerStatusRes>}
713
+
714
+ ACQUIRER_SUCCEEDED_BUT_WRONG_SIGNATURE_STATUS_RESPONSE = %{<?xml version="1.0" encoding="UTF-8"?>
715
+ <AcquirerStatusRes xmlns="http://www.idealdesk.com/Message" version="1.1.0">
716
+ <createDateTimeStamp>2001-12-17T09:30:47.0Z</createDateTimeStamp>
717
+ <Acquirer>
718
+ <acquirerID>1234</acquirerID>
719
+ </Acquirer>
720
+ <Transaction>
721
+ <transactionID>0001023456789112</transactionID>
722
+ <status>Success</status>
723
+ <consumerName>Onderheuvel</consumerName>
724
+ <consumerAccountNumber>0949298989</consumerAccountNumber>
725
+ <consumerCity>DEN HAAG</consumerCity>
726
+ </Transaction>
727
+ <Signature>
728
+ <signatureValue>WRONG</signatureValue>
729
+ <fingerprint>1E15A00E3D7DF085768749D4ABBA3284794D8AE9</fingerprint>
730
+ </Signature>
731
+ </AcquirerStatusRes>}
732
+
733
+ ACQUIRER_FAILED_STATUS_RESPONSE = %{<?xml version="1.0" encoding="UTF-8"?>
734
+ <AcquirerStatusRes xmlns="http://www.idealdesk.com/Message" version="1.1.0">
735
+ <createDateTimeStamp>2001-12-17T09:30:47.0Z</createDateTimeStamp>
736
+ <Acquirer>
737
+ <acquirerID>1234</acquirerID>
738
+ </Acquirer>
739
+ <Transaction>
740
+ <transactionID>0001023456789112</transactionID>
741
+ <status>Failed</status>
742
+ <consumerName>Onderheuvel</consumerName>
743
+ <consumerAccountNumber>0949298989</consumerAccountNumber>
744
+ <consumerCity>DEN HAAG</consumerCity>
745
+ </Transaction>
746
+ <Signature>
747
+ <signatureValue>db82/jpJRvKQKoiDvu33X0yoDAQpayJOaW2Y8zbR1qk1i3epvTXi+6g+QVBY93YzGv4w+Va+vL3uNmzyRjYsm2309d1CWFVsn5Mk24NLSvhYfwVHEpznyMqizALEVUNSoiSHRkZUDfXowBAyLT/tQVGbuUuBj+TKblY826nRa7U=</signatureValue>
748
+ <fingerprint>1E15A00E3D7DF085768749D4ABBA3284794D8AE9</fingerprint>
749
+ </Signature>
750
+ </AcquirerStatusRes>}
751
+
752
+ ERROR_RESPONSE = %{<?xml version="1.0" encoding="UTF-8"?>
753
+ <ErrorRes xmlns="http://www.idealdesk.com/Message" version="1.1.0">
754
+ <createDateTimeStamp>2001-12-17T09:30:47.0Z</createDateTimeStamp>
755
+ <Error>
756
+ <errorCode>SO1000</errorCode>
757
+ <errorMessage>Failure in system</errorMessage>
758
+ <errorDetail>System generating error: issuer</errorDetail>
759
+ <suggestedAction></suggestedAction>
760
+ <suggestedExpirationPeriod></suggestedExpirationPeriod>
761
+ <consumerMessage>Betalen met iDEAL is nu niet mogelijk.</consumerMessage>
762
+ </Error>
763
+ </ErrorRes>}
764
+
765
+ setup_ideal_gateway!
766
+ end