active_merchant_ideal 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -90,7 +90,7 @@ h3. First configure the gateway
90
90
  Put the following code in, for instance, an initializer:
91
91
 
92
92
  <pre>
93
- IdealGateway.live_url = 'https://ideal.secure-ing.com:443/ideal/iDeal'
93
+ IdealGateway.acquirer = :ing # Other banks preloaded are :abnamro and :rabobank
94
94
  IdealGateway.merchant_id = '00123456789'
95
95
  IdealGateway.passphrase = 'the_private_key_passphrase'
96
96
 
@@ -181,7 +181,7 @@ In 2007 this code was refactored as a patch for the ActiveMerchant library, this
181
181
 
182
182
  In 2009 Fingertips forked the ActiveMerchant library and added an iDEAL gateway (presumable based on the first ActiveMerchant patch) to a new ideal branch.
183
183
 
184
- In 2010 this code was extracted and converted into a separate gem, so it can be more easily used in combination with the latest version of ActiveMerchant. This library is just an extraction, nothing more and nothing less. There are no fundamental changes between the code from the ideal branch and the code of this gem.
184
+ In 2010 this code was extracted and converted into a separate gem, so it can be more easily used in combination with the latest version of ActiveMerchant. This library is just an extraction, nothing more and nothing less. There are no fundamental changes between the code from the ideal branch and the code of this gem. Later that year "Sernin van de Krol":http://github/companeidos added support for ABN AMRO.
185
185
 
186
186
  h2. Maintainer
187
187
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.1.5
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{active_merchant_ideal}
8
- s.version = "0.1.4"
8
+ s.version = "0.1.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Soemirno Kartosoewito, Matthijs Kadijk, Aloy Duran, Frank Oxener"]
12
- s.date = %q{2010-05-20}
12
+ s.date = %q{2010-12-02}
13
13
  s.description = %q{iDEAL payment gateway for ActiveMerchant (see http://www.ideal.nl and http://www.activemerchant.org/)}
14
14
  s.email = %q{frank.oxener@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  "active_merchant_ideal.gemspec",
27
27
  "init.rb",
28
28
  "lib/active_merchant_ideal.rb",
29
+ "lib/active_merchant_ideal/acquirers.yml",
29
30
  "lib/active_merchant_ideal/ideal.rb",
30
31
  "lib/active_merchant_ideal/ideal_response.rb",
31
32
  "test/fixtures.yml",
@@ -0,0 +1,18 @@
1
+ ing:
2
+ live: https://ideal.secure-ing.com/ideal/iDeal
3
+ test: https://idealtest.secure-ing.com/ideal/iDeal
4
+
5
+ rabobank:
6
+ live: https://ideal.rabobank.nl/ideal/iDeal
7
+ test: https://idealtest.rabobank.nl/ideal/iDeal
8
+
9
+ abnamro:
10
+ live:
11
+ directory: https://idealm.abnamro.nl/nl/issuerInformation/getIssuerInformation.xml
12
+ transaction: https://idealm.abnamro.nl/nl/acquirerTrxRegistration/getAcquirerTrxRegistration.xml
13
+ status: https://idealm.abnamro.nl/nl/acquirerStatusInquiry/getAcquirerStatusInquiry.xml
14
+
15
+ test:
16
+ directory: https://itt.idealdesk.com/ITTEmulatorAcquirer/Directory.aspx
17
+ transaction: https://itt.idealdesk.com/ITTEmulatorAcquirer/Transaction.aspx
18
+ status: https://itt.idealdesk.com/ITTEmulatorAcquirer/Status.aspx
@@ -20,12 +20,20 @@ module ActiveMerchant #:nodoc:
20
20
  API_VERSION = '1.1.0'
21
21
  XML_NAMESPACE = 'http://www.idealdesk.com/Message'
22
22
 
23
+ def self.acquirers
24
+ config_file = File.dirname(__FILE__) + '/acquirers.yml'
25
+ File.exists?(config_file) ? YAML.load(File.read(config_file)) : {}
26
+ end
27
+
23
28
  # Assigns the global iDEAL merchant id. Make sure to use a string with
24
29
  # leading zeroes if needed.
25
30
  cattr_accessor :merchant_id
26
31
 
27
32
  # Assigns the passphrase that should be used for the merchant private_key.
28
33
  cattr_accessor :passphrase
34
+
35
+ # Defines the whitespace behaviour, this is different for ABN AMRO. Possible values: :abn, :normal
36
+ cattr_accessor :whitespace_behaviour
29
37
 
30
38
  # Loads the global merchant private_key from disk.
31
39
  def self.private_key_file=(pkey_file)
@@ -63,25 +71,39 @@ module ActiveMerchant #:nodoc:
63
71
  def self.ideal_certificate_file=(certificate_file)
64
72
  self.ideal_certificate = File.read(certificate_file)
65
73
  end
66
-
74
+
67
75
  # Instantiates and assings a OpenSSL::X509::Certificate instance with the
68
76
  # provided iDEAL certificate data.
69
77
  def self.ideal_certificate=(certificate_data)
70
78
  @ideal_certificate = OpenSSL::X509::Certificate.new(certificate_data)
71
79
  end
72
-
80
+
73
81
  # Returns the global merchant ideal_certificate.
74
82
  def self.ideal_certificate
75
83
  @ideal_certificate
76
84
  end
77
85
 
78
86
  # Assign the test and production urls for your iDeal acquirer.
79
- #
80
- # For instance, for ING:
81
- #
82
- # ActiveMerchant::Billing::IdealGateway.test_url = "https://idealtest.secure-ing.com:443/ideal/iDeal"
83
- # ActiveMerchant::Billing::IdealGateway.live_url = "https://ideal.secure-ing.com:443/ideal/iDeal"
84
- cattr_accessor :test_url, :live_url
87
+ # For ABN AMRO only assign the three separate directory, transaction and status urls.
88
+ cattr_accessor :live_url, :test_url
89
+ cattr_accessor :live_directory_url, :test_directory_url
90
+ cattr_accessor :live_transaction_url, :test_transaction_url
91
+ cattr_accessor :live_status_url, :test_status_url
92
+
93
+ # Set the correct acquirer url based on the specific Bank
94
+ # Currently supported arguments: :ing, :rabobank, :abnamro
95
+ def self.acquirer=(acquirer)
96
+ acquirer = acquirer.to_s
97
+ if self.acquirers.include?(acquirer)
98
+ if self.acquirers[acquirer]['live'].is_a?(Hash) #Assume acquirer is abnamro
99
+ self.acquirers[acquirer].each{|env, url| url.each{|sort,value| self.send("#{env}_#{sort}_url=",value)}}
100
+ self.whitespace_behaviour = :abnamro
101
+ else
102
+ self.live_url = self.acquirers[acquirer]['live']
103
+ self.test_url = self.acquirers[acquirer]['test']
104
+ end
105
+ end
106
+ end
85
107
 
86
108
  # Returns the merchant `subID' being used for this IdealGateway instance.
87
109
  # Defaults to 0.
@@ -99,8 +121,8 @@ module ActiveMerchant #:nodoc:
99
121
  #
100
122
  # When #test? returns +true+ the IdealGateway.test_url is used, otherwise
101
123
  # the IdealGateway.live_url is used.
102
- def acquirer_url
103
- test? ? self.class.test_url : self.class.live_url
124
+ def acquirer_url(request_type)
125
+ self.class.send("#{test_or_live}#{sort_request(request_type)}_url")
104
126
  end
105
127
 
106
128
  # Sends a directory request to the acquirer and returns an
@@ -109,7 +131,7 @@ module ActiveMerchant #:nodoc:
109
131
  #
110
132
  # gateway.issuers.list # => [{ :id => '1006', :name => 'ABN AMRO Bank' }, …]
111
133
  def issuers
112
- post_data build_directory_request_body, IdealDirectoryResponse
134
+ post_data acquirer_url(:directory), build_directory_request_body, IdealDirectoryResponse
113
135
  end
114
136
 
115
137
  # Starts a purchase by sending an acquirer transaction request for the
@@ -157,7 +179,7 @@ module ActiveMerchant #:nodoc:
157
179
  #
158
180
  # See the IdealGateway class description for a more elaborate example.
159
181
  def setup_purchase(money, options)
160
- post_data build_transaction_request_body(money, options), IdealTransactionResponse
182
+ post_data acquirer_url(:transaction), build_transaction_request_body(money, options), IdealTransactionResponse
161
183
  end
162
184
 
163
185
  # Sends a acquirer status request for the specified +transaction_id+ and
@@ -177,13 +199,27 @@ module ActiveMerchant #:nodoc:
177
199
  #
178
200
  # See the IdealGateway class description for a more elaborate example.
179
201
  def capture(transaction_id)
180
- post_data build_status_request_body(:transaction_id => transaction_id), IdealStatusResponse
202
+ post_data acquirer_url(:status), build_status_request_body(:transaction_id => transaction_id), IdealStatusResponse
181
203
  end
182
204
 
183
205
  private
184
206
 
185
- def post_data(data, response_klass)
186
- response_klass.new(ssl_post(acquirer_url, data), :test => test?)
207
+ def abnamro?
208
+ self.class.whitespace_behaviour == :abnamro
209
+ end
210
+
211
+ # Set correct mode for acquirer_url
212
+ def test_or_live
213
+ test? ? 'test' : 'live'
214
+ end
215
+
216
+ # Determine type of request used by ABN AMRO
217
+ def sort_request(request_type)
218
+ request_type && abnamro? ? "_#{request_type.to_s}" : nil
219
+ end
220
+
221
+ def post_data(gateway_url, data, response_klass)
222
+ response_klass.new(ssl_post(gateway_url, data), :test => test?)
187
223
  end
188
224
 
189
225
  # This is the list of charaters that are not supported by iDEAL according
@@ -205,10 +241,14 @@ module ActiveMerchant #:nodoc:
205
241
  Digest::SHA1.hexdigest(self.class.private_certificate.to_der).upcase
206
242
  end
207
243
 
244
+ def strip_whitespace(str)
245
+ abnamro? ? str.gsub(/(\f|\n|\r|\t|\v)/m, '') : str.gsub(/\s/m,'')
246
+ end
247
+
208
248
  # Creates a +tokenCode+ from the specified +message+.
209
249
  def token_code(message)
210
- signature = self.class.private_key.sign(OpenSSL::Digest::SHA1.new, message.gsub(/\s/m, ''))
211
- Base64.encode64(signature).gsub(/\s/m, '')
250
+ signature = self.class.private_key.sign(OpenSSL::Digest::SHA1.new, strip_whitespace(message))
251
+ strip_whitespace(Base64.encode64(signature))
212
252
  end
213
253
 
214
254
  # Returns a string containing the current UTC time, formatted as per the
data/test/fixtures.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  # You can also paste the contents of the key and certificates here,
2
2
  # if you want to do so remove the “_file” part of the keys.
3
3
  ideal_ing_postbank:
4
- test_url: https://idealtest.secure-ing.com:443/ideal/iDeal
4
+ acquirer: ing
5
5
  merchant_id: ID
6
6
  passphrase: PRIVATE KEY PASSPHRASE
7
7
  private_key_file: |--
@@ -10,9 +10,7 @@ module IdealTestCases
10
10
  self.private_key = PRIVATE_KEY
11
11
  self.private_certificate = PRIVATE_CERTIFICATE
12
12
  self.ideal_certificate = IDEAL_CERTIFICATE
13
-
14
- self.test_url = "https://idealtest.example.com:443/ideal/iDeal"
15
- self.live_url = "https://ideal.example.com:443/ideal/iDeal"
13
+ self.acquirer = :ing
16
14
  end
17
15
  end
18
16
 
@@ -25,16 +23,34 @@ module IdealTestCases
25
23
  :entrance_code => '1234'
26
24
  }
27
25
 
28
- ###
29
- #
30
- # Actual test cases
31
- #
32
-
33
26
  class ClassMethodsTest < Test::Unit::TestCase
34
27
  def test_merchant_id
35
28
  assert_equal IdealGateway.merchant_id, '123456789'
36
29
  end
37
30
 
31
+ def test_verify_live_url_for_ing
32
+ ActiveMerchant::Billing::IdealGateway.acquirer = :ing
33
+ assert_equal 'https://ideal.secure-ing.com/ideal/iDeal', IdealGateway.live_url
34
+ end
35
+
36
+ def test_verify_live_url_for_rabobank
37
+ ActiveMerchant::Billing::IdealGateway.acquirer = :rabobank
38
+ assert_equal 'https://ideal.rabobank.nl/ideal/iDeal', IdealGateway.live_url
39
+ end
40
+
41
+ def test_verify_live_urls_for_abnamro
42
+ ActiveMerchant::Billing::IdealGateway.acquirer = :abnamro
43
+ assert_equal 'https://idealm.abnamro.nl/nl/issuerInformation/getIssuerInformation.xml', IdealGateway.live_directory_url
44
+ assert_equal 'https://idealm.abnamro.nl/nl/acquirerTrxRegistration/getAcquirerTrxRegistration.xml', IdealGateway.live_transaction_url
45
+ assert_equal 'https://idealm.abnamro.nl/nl/acquirerStatusInquiry/getAcquirerStatusInquiry.xml', IdealGateway.live_status_url
46
+ end
47
+
48
+ def test_acquirers
49
+ assert_equal 'https://ideal.rabobank.nl/ideal/iDeal', IdealGateway.acquirers['rabobank']['live']
50
+ assert_equal 'https://ideal.secure-ing.com/ideal/iDeal', IdealGateway.acquirers['ing']['live']
51
+ assert_equal 'https://idealm.abnamro.nl/nl/acquirerTrxRegistration/getAcquirerTrxRegistration.xml', IdealGateway.acquirers['abnamro']['live']['transaction']
52
+ end
53
+
38
54
  def test_private_certificate_returns_a_loaded_Certificate_instance
39
55
  assert_equal IdealGateway.private_certificate.to_text,
40
56
  OpenSSL::X509::Certificate.new(PRIVATE_CERTIFICATE).to_text
@@ -63,12 +79,16 @@ module IdealTestCases
63
79
 
64
80
  def test_returns_the_test_url_when_in_the_test_env
65
81
  @gateway.stubs(:test?).returns(true)
66
- assert_equal IdealGateway.test_url, @gateway.send(:acquirer_url)
82
+ assert_equal IdealGateway.test_directory_url, @gateway.send(:acquirer_url,:directory)
83
+ assert_equal IdealGateway.test_transaction_url, @gateway.send(:acquirer_url,:transaction)
84
+ assert_equal IdealGateway.test_status_url, @gateway.send(:acquirer_url,:status)
67
85
  end
68
86
 
69
87
  def test_returns_the_live_url_when_not_in_the_test_env
70
88
  @gateway.stubs(:test?).returns(false)
71
- assert_equal IdealGateway.live_url, @gateway.send(:acquirer_url)
89
+ assert_equal IdealGateway.live_directory_url, @gateway.send(:acquirer_url,:directory)
90
+ assert_equal IdealGateway.live_transaction_url, @gateway.send(:acquirer_url,:transaction)
91
+ assert_equal IdealGateway.live_status_url, @gateway.send(:acquirer_url,:status)
72
92
  end
73
93
 
74
94
  def test_returns_created_at_timestamp
@@ -112,6 +132,7 @@ module IdealTestCases
112
132
  end
113
133
 
114
134
  def test_token_code_generation
135
+ IdealGateway.whitespace_behaviour = nil
115
136
  message = "Top\tsecret\tman.\nI could tell you, but then I'd have to kill you…"
116
137
  stripped_message = message.gsub(/\s/m, '')
117
138
 
@@ -124,15 +145,29 @@ module IdealTestCases
124
145
  assert_equal encoded_signature, @gateway.send(:token_code, message)
125
146
  end
126
147
 
148
+ def test_token_code_generation_on_abn_amro
149
+ IdealGateway.whitespace_behaviour = :abnamro
150
+ message = "Top\tsecret\tman.\nI could tell you, but\r then I'd have to kill you…"
151
+ stripped_message = message.gsub(/(\f|\n|\r|\t|\v)/m, '')
152
+
153
+ sha1 = OpenSSL::Digest::SHA1.new
154
+ OpenSSL::Digest::SHA1.stubs(:new).returns(sha1)
155
+
156
+ signature = IdealGateway.private_key.sign(sha1, stripped_message)
157
+ encoded_signature = Base64.encode64(signature).strip.gsub(/\n/, '')
158
+
159
+ assert_equal encoded_signature, @gateway.send(:token_code, message)
160
+ end
161
+
127
162
  def test_posts_data_with_ssl_to_acquirer_url_and_return_the_correct_response
128
163
  IdealResponse.expects(:new).with('response', :test => true)
129
- @gateway.expects(:ssl_post).with(@gateway.acquirer_url, 'data').returns('response')
130
- @gateway.send(:post_data, 'data', IdealResponse)
164
+ @gateway.expects(:ssl_post).with(@gateway.acquirer_url(:directory), 'data').returns('response')
165
+ @gateway.send(:post_data, @gateway.acquirer_url(:directory), 'data', IdealResponse)
131
166
 
132
167
  @gateway.stubs(:test?).returns(false)
133
168
  IdealResponse.expects(:new).with('response', :test => false)
134
- @gateway.expects(:ssl_post).with(@gateway.acquirer_url, 'data').returns('response')
135
- @gateway.send(:post_data, 'data', IdealResponse)
169
+ @gateway.expects(:ssl_post).with(@gateway.acquirer_url(:directory), 'data').returns('response')
170
+ @gateway.send(:post_data, @gateway.acquirer_url(:directory), 'data', IdealResponse)
136
171
  end
137
172
  end
138
173
 
@@ -387,7 +422,7 @@ module IdealTestCases
387
422
 
388
423
  def test_returns_a_list_with_only_one_issuer
389
424
  @gateway.stubs(:build_directory_request_body).returns('the request body')
390
- @gateway.expects(:ssl_post).with(@gateway.acquirer_url, 'the request body').returns(DIRECTORY_RESPONSE_WITH_ONE_ISSUER)
425
+ @gateway.expects(:ssl_post).with(@gateway.acquirer_url(:directory), 'the request body').returns(DIRECTORY_RESPONSE_WITH_ONE_ISSUER)
391
426
 
392
427
  expected_issuers = [{ :id => '1006', :name => 'ABN AMRO Bank' }]
393
428
 
@@ -398,7 +433,7 @@ module IdealTestCases
398
433
 
399
434
  def test_returns_list_of_issuers_from_response
400
435
  @gateway.stubs(:build_directory_request_body).returns('the request body')
401
- @gateway.expects(:ssl_post).with(@gateway.acquirer_url, 'the request body').returns(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS)
436
+ @gateway.expects(:ssl_post).with(@gateway.acquirer_url(:directory), 'the request body').returns(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS)
402
437
 
403
438
  expected_issuers = [
404
439
  { :id => '1006', :name => 'ABN AMRO Bank' },
@@ -419,7 +454,7 @@ module IdealTestCases
419
454
  @gateway = IdealGateway.new
420
455
 
421
456
  @gateway.stubs(:build_transaction_request_body).with(4321, VALID_PURCHASE_OPTIONS).returns('the request body')
422
- @gateway.expects(:ssl_post).with(@gateway.acquirer_url, 'the request body').returns(ACQUIRER_TRANSACTION_RESPONSE)
457
+ @gateway.expects(:ssl_post).with(@gateway.acquirer_url(:transaction), 'the request body').returns(ACQUIRER_TRANSACTION_RESPONSE)
423
458
 
424
459
  @setup_purchase_response = @gateway.setup_purchase(4321, VALID_PURCHASE_OPTIONS)
425
460
  end
@@ -494,7 +529,7 @@ module IdealTestCases
494
529
  private
495
530
 
496
531
  def expects_request_and_returns(str)
497
- @gateway.expects(:ssl_post).with(@gateway.acquirer_url, 'the request body').returns(str)
532
+ @gateway.expects(:ssl_post).with(@gateway.acquirer_url(:status), 'the request body').returns(str)
498
533
  end
499
534
  end
500
535
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 4
9
- version: 0.1.4
8
+ - 5
9
+ version: 0.1.5
10
10
  platform: ruby
11
11
  authors:
12
12
  - Soemirno Kartosoewito, Matthijs Kadijk, Aloy Duran, Frank Oxener
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-20 00:00:00 +02:00
17
+ date: 2010-12-02 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -64,6 +64,7 @@ files:
64
64
  - active_merchant_ideal.gemspec
65
65
  - init.rb
66
66
  - lib/active_merchant_ideal.rb
67
+ - lib/active_merchant_ideal/acquirers.yml
67
68
  - lib/active_merchant_ideal/ideal.rb
68
69
  - lib/active_merchant_ideal/ideal_response.rb
69
70
  - test/fixtures.yml