ideal 0.2.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.kick +5 -0
- data/README.textile +164 -124
- data/lib/ideal/acquirers.rb +2 -7
- data/lib/ideal/gateway.rb +18 -25
- data/lib/ideal/response.rb +1 -1
- data/lib/ideal/version.rb +1 -1
- data/test/gateway_test.rb +99 -123
- data/test/remote_test.rb +7 -2
- metadata +5 -4
data/README.textile
CHANGED
@@ -1,19 +1,8 @@
|
|
1
|
-
h1.
|
1
|
+
h1. iDEAL
|
2
2
|
|
3
3
|
"!https://secure.travis-ci.org/Fingertips/Ideal.png!":http://travis-ci.org/Fingertips/Ideal
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
Recently ING issued a new iDEAL certificate, which should be in production before May 23 2011. See "Wijzigen van een acquiring certificaat in
|
8
|
-
iDEAL Advanced":http://www.ing.nl/Images/Wijzigen_van_een_acquiring_certificaat_in_iDEAL_Advanced_internet_tcm7-82882.pdf. However ING is not able to say exactly when this migration will take place. This means there will be a transition period in which it's uncertain which iDEAL certificate is needed.
|
9
|
-
|
10
|
-
Luckily Roel van Dijk (Voormedia BV) has written a gem/patch, so you can use the old and the new certificate during this transition period.
|
11
|
-
|
12
|
-
See "active_merchant_ideal_multicert":https://github.com/rdvdijk/active_merchant_ideal_multicert
|
13
|
-
|
14
|
-
h2. Description:
|
15
|
-
|
16
|
-
"iDEAL":http://www.ideal.nl payment gateway for "ActiveMerchant":http://www.activemerchant.org.
|
5
|
+
Library for the "iDEAL":http://www.ideal.nl payment standard.
|
17
6
|
|
18
7
|
h2. What is iDEAL?
|
19
8
|
|
@@ -33,172 +22,223 @@ In order to use iDEAL you will need to get an iDEAL merchant account from your b
|
|
33
22
|
* Rabobank: Rabo iDEAL Professional. (Unverified)
|
34
23
|
* SNS Bank: "Not yet available":http://www.snsbank.nl/zakelijk/betalingsverkeer/kan-ik-ideal-gebruiken-voor-mijn-webwinkel.html
|
35
24
|
|
36
|
-
|
25
|
+
h2. Install
|
37
26
|
|
38
|
-
|
27
|
+
The iDEAL gem does not have any large external dependencies. It depends on Nap (a small HTTP library) and Builder (for building XML files). Because of these minor dependencies it's suited to use in Ruby projects other than Ruby on Rails.
|
39
28
|
|
40
|
-
|
29
|
+
The easiest way to install is as a gem.
|
41
30
|
|
42
|
-
<pre>
|
43
|
-
sudo gem install active_merchant_ideal
|
44
|
-
</pre>
|
31
|
+
<pre><code>sudo gem install ideal</code></pre>
|
45
32
|
|
46
|
-
|
33
|
+
Or you can add it as a dependency in your Gemfile.
|
47
34
|
|
48
|
-
<pre>
|
49
|
-
gem 'active_merchant_ideal'
|
50
|
-
</pre>
|
35
|
+
<pre><code>gem 'ideal'</code></pre>
|
51
36
|
|
52
|
-
|
53
|
-
<pre>
|
54
|
-
./script/plugin install git://github.com/dovadi/active_merchant_ideal.git
|
55
|
-
</pre>
|
37
|
+
Finally, if you don't dig any of that gemming that's so popular nowadays, you can install it as a plugin;
|
56
38
|
|
57
|
-
|
39
|
+
<pre><code>cd vendor/plugins
|
40
|
+
git clone --depth 1 git://github.com/Fingertips/Ideal.git ideal</code></pre>
|
58
41
|
|
59
|
-
|
42
|
+
h2. Generate private keys and certificates
|
60
43
|
|
61
|
-
|
44
|
+
Messages between you and the acquirer are all signed in order to prove their authenticity. You will need a certificate for your side, this can be self-issued. If you like spending money, you can buy a certificate from some SSL authority. The certificate of the acquirer is probably hidden somewhere in plain sight in their documentation.
|
62
45
|
|
63
46
|
To create a self-signed certificate follow these steps:
|
64
47
|
|
65
48
|
* /usr/bin/openssl genrsa -des3 -out private_key.pem -passout pass:the_passphrase 1024
|
66
49
|
* /usr/bin/openssl req -x509 -new -key private_key.pem -passin pass:the_passphrase -days 3650 -out private_certificate.cer
|
67
50
|
|
68
|
-
Substitute
|
51
|
+
Substitute _the_passphrase_ with your own passphrase. You will need to configure that passphrase later on, so hand on to it.
|
69
52
|
|
70
|
-
|
53
|
+
You will need to upload your public key (certificate) to your iDEAL dashboard. Usually they have a completely independent test and live environment so you _can_ use different certificates for both.
|
71
54
|
|
72
|
-
For more information see:
|
55
|
+
For more information on certificates and encryption see:
|
73
56
|
* "http://en.wikipedia.org/wiki/Certificate_authority":http://en.wikipedia.org/wiki/Certificate_authority
|
74
57
|
* "http://en.wikipedia.org/wiki/Self-signed_certificate":http://en.wikipedia.org/wiki/Self-signed_certificate
|
75
58
|
|
76
|
-
h2. Test
|
59
|
+
h2. Test and activation
|
77
60
|
|
78
|
-
|
61
|
+
Once you've uploaded the certificate you need to initiate a number of transactions to complete the activation process. Luckily these transactions are part of the remote test for the gem. It's still kind of a pain, but here we go!
|
79
62
|
|
80
|
-
|
63
|
+
<pre><code>git clone --depth 1 git://github.com/Fingertips/Ideal.git ideal
|
64
|
+
cd ideal
|
65
|
+
bundle install</code></pre>
|
81
66
|
|
82
|
-
<
|
83
|
-
|
84
|
-
|
85
|
-
</pre>
|
67
|
+
* Create the <code>~/.ideal</code> directory.
|
68
|
+
* Copy <code>test/fixtures.yml</code> to <code>~/.ideal</code>.
|
69
|
+
* Fill in your own merchant id, passphrase and the correct locations to your private key and certificates.
|
86
70
|
|
87
|
-
|
71
|
+
<pre><code>ruby test/remote_test.rb</code></pre>
|
88
72
|
|
89
|
-
|
90
|
-
* Copy test/fixtures.yml to the .active_merchant directory
|
91
|
-
* Fill in your own merchant id, passphrase and the correct locations to your private key and certificates.
|
92
|
-
* For running the *seven prescribed remote test transactions* (ING bank and Rabobank) which are needed to activate the iDEAL account use
|
73
|
+
If you've succeeded you will see the following:
|
93
74
|
|
94
|
-
<pre>
|
95
|
-
|
96
|
-
|
75
|
+
<pre><code>ruby test/remote_test.rb
|
76
|
+
Loaded suite test/remote_test
|
77
|
+
Started
|
78
|
+
...........
|
79
|
+
Finished in 9.768389 seconds.
|
97
80
|
|
98
|
-
|
81
|
+
11 tests, 33 assertions, 0 failures, 0 errors</code></pre>
|
99
82
|
|
100
|
-
|
83
|
+
If you see test errors, you're on your own (; You can run the test in debug mode to check what's sent across the wire.
|
101
84
|
|
102
|
-
|
85
|
+
<pre><code>ruby -d test/remote_test.rb </code></pre>
|
103
86
|
|
104
|
-
|
87
|
+
h2. Dashboards
|
105
88
|
|
106
|
-
|
89
|
+
h3. ING
|
90
|
+
|
91
|
+
* "Test dashboard":https://idealtest.secure-ing.com/ideal/logon_ing.do
|
92
|
+
* "Live dashboard":https://ideal.secure-ing.com/ideal/logon_ing.do
|
107
93
|
|
108
|
-
|
109
|
-
ActiveMerchant::Billing::IdealGateway.acquirer = :ing # Other banks preloaded are :abnamro and :rabobank
|
110
|
-
ActiveMerchant::Billing::IdealGateway.merchant_id = '00123456789'
|
111
|
-
ActiveMerchant::Billing::IdealGateway.passphrase = 'the_private_key_passphrase'
|
112
|
-
|
113
|
-
# CERTIFICATE_ROOT points to a directory where the key and certificates are located
|
114
|
-
ActiveMerchant::Billing::IdealGateway.private_key_file = File.join(CERTIFICATE_ROOT, 'private_key.pem')
|
115
|
-
ActiveMerchant::Billing::IdealGateway.private_certificate_file = File.join(CERTIFICATE_ROOT, 'private_certificate.cer')
|
116
|
-
ActiveMerchant::Billing::IdealGateway.ideal_certificate_file = File.join(CERTIFICATE_ROOT, 'ideal.cer')
|
117
|
-
</pre>
|
94
|
+
h3. ABN AMRO
|
118
95
|
|
119
|
-
|
96
|
+
* "Test dashboard":https://abnamro-test.ideal-payment.de/ideal/signupInitiatePreAction.do
|
97
|
+
* "Live dashboard":https://abnamro.ideal-payment.de/ideal/signupInitiatePreAction.do
|
120
98
|
|
121
|
-
|
99
|
+
h3. Compatibility
|
122
100
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
101
|
+
We run continuous integration tests with Ruby 1.8.7, 1.9.2, and 1.9.3. We're pretty sure that means it works (see the badge at the top of this file).
|
102
|
+
|
103
|
+
h2. Example (Rails)
|
104
|
+
|
105
|
+
The following code was written as an example and should not be used without further testing in your application. USE AT YOUR OWN PERIL. Remember to have fun (;
|
106
|
+
|
107
|
+
h3. Config
|
129
108
|
|
130
|
-
|
109
|
+
Configure the Gateway somewhere. One place could be <code>config/initializers/ideal.rb</code>.
|
131
110
|
|
132
111
|
<pre>
|
133
|
-
|
112
|
+
unless Rails.env.production?
|
113
|
+
Ideal::Gateway.environment = :test
|
114
|
+
end
|
115
|
+
|
116
|
+
# Other banks preloaded are :abnamro and :rabobank
|
117
|
+
Ideal::Gateway::IdealGateway.acquirer = :ing
|
118
|
+
Ideal::Gateway::IdealGateway.merchant_id = '00123456789'
|
119
|
+
|
120
|
+
# Maybe you'd like another location
|
121
|
+
ideal_directory = Rails.root + 'config/ideal'
|
122
|
+
Ideal::Gateway::IdealGateway.passphrase = 'the_passphrase'
|
123
|
+
Ideal::Gateway::IdealGateway.private_key_file = ideal_directory + 'private_key.pem'
|
124
|
+
Ideal::Gateway::IdealGateway.private_certificate_file = ideal_directory + 'private_certificate.cer'
|
125
|
+
Ideal::Gateway::IdealGateway.ideal_certificate_file = ideal_directory + 'ideal.cer'
|
126
|
+
</pre>
|
127
|
+
|
128
|
+
h3. Show a payment form
|
129
|
+
|
130
|
+
Show a list of all issuers (banks) to choose from.
|
131
|
+
|
132
|
+
<pre><code>class PaymentsController < ActionController::Base
|
133
|
+
def new
|
134
|
+
@payment = Payment.new
|
135
|
+
@issuers = sorted_issuers
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def ideal
|
141
|
+
Ideal::Gateway.new
|
142
|
+
end
|
143
|
+
|
144
|
+
def sorted_issuers
|
145
|
+
# NOTE: this does a GET on the bankend, you might want to memoize this
|
146
|
+
ideal.issuers.list.sort_by do |issuer|
|
147
|
+
issuer[:name]
|
148
|
+
end.map do |issuer|
|
149
|
+
[issuer[:name], issuer[:id]]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
</code></pre>
|
154
|
+
|
155
|
+
<pre><code>
|
156
|
+
<%= form_for(@payment) do |f| %
|
157
|
+
<%= f.select(:issuer_id, @issuers)
|
158
|
+
<% end %</code></pre>
|
159
|
+
|
160
|
+
Would result in something like:
|
161
|
+
|
162
|
+
<select name="payment[issuer_id]">
|
134
163
|
<option value="1006" selected="selected">ABN AMRO Bank</option>
|
135
164
|
<option value="1017">Asr bank</option>
|
136
165
|
<option value="1003">Postbank</option>
|
137
166
|
<option value="1005">Rabobank</option>
|
138
167
|
<option value="1023">Van Lanschot</option>
|
139
168
|
</select>
|
140
|
-
</pre>
|
141
169
|
|
142
|
-
h3.
|
170
|
+
h3. Set up a payment
|
143
171
|
|
144
172
|
First you'll need to setup a transaction and redirect the consumer there so she can make the payment:
|
145
173
|
|
146
|
-
<pre>
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
174
|
+
<pre><code>class Payment < ActiveRecord::Base
|
175
|
+
# Validation code used to validate returning notifications from iDeal
|
176
|
+
def ideal_entrance_code
|
177
|
+
Digest::SHA1.hexdigest("#{id}-#{created_at}-#{access_token}")
|
178
|
+
end
|
179
|
+
|
180
|
+
def ideal_attributes
|
181
|
+
{
|
182
|
+
# The customer has 30 minutes to complete the iDeal transaction (ISO 8601)
|
183
|
+
:expiration_period => "PT30M",
|
184
|
+
:issuer_id => issuer_id,
|
185
|
+
:return_url => return_url,
|
186
|
+
:order_id => id.to_s,
|
187
|
+
:description => description,
|
188
|
+
:entrance_code => ideal_entrance_code
|
189
|
+
}
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
class PaymentsController < ActionController::Base
|
194
|
+
def create
|
195
|
+
payment = Payment.create(params[:payment].merge(
|
196
|
+
:price_in_cents => 1000, # €10.00 in cents
|
197
|
+
:return_url => payment_url(payment), # This is where the customer will be returned to
|
198
|
+
:description => 'A Dutch windmill' # This will end up on the customer's bank statement (max 32 ASCII chars)
|
199
|
+
))
|
200
|
+
|
201
|
+
response = ideal.setup_purchase(payment.price_in_cents, payment.ideal_attributes)
|
202
|
+
if response.success?
|
203
|
+
payment.transaction_id = response.transaction_id
|
204
|
+
payment.status = 'pending'
|
205
|
+
payment.save(false)
|
206
|
+
else
|
207
|
+
Rails.logger.info("Payment initialization failed: [#{response.error_message}] #{response.error_details}")
|
208
|
+
end
|
209
|
+
|
210
|
+
# Redirect the consumer to the issuer’s payment page.
|
211
|
+
redirect_to response.service_url
|
212
|
+
end
|
213
|
+
end</code></pre>
|
175
214
|
|
176
215
|
After the consumer is done with the payment she will be redirected to the _:return_url_. It's now _your_ responsibility as merchant to check if the payment has been made:
|
177
216
|
|
178
|
-
<pre>
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
</pre>
|
217
|
+
<pre><code>
|
218
|
+
class PaymentsController < ActionController::Base
|
219
|
+
def show
|
220
|
+
@payment = Payment.find(params[:id])
|
221
|
+
status = ideal.capture(@payment.transaction_id)
|
222
|
+
if status.success?
|
223
|
+
@payment.update_attributes!(:status => 'paid')
|
224
|
+
flash[:notice] = "Congratulations, you are now the proud owner of a Dutch windmill!"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
</code></pre>
|
191
229
|
|
192
|
-
h2.
|
230
|
+
h2. Help out!
|
193
231
|
|
194
|
-
|
232
|
+
If you find anything wrong with the gem, we would love to hear from you. Please "create an issue with a patch":https://github.com/Fingertips/iDeal/issues if you run into anything.
|
233
|
+
|
234
|
+
h2. History
|
195
235
|
|
196
|
-
In
|
236
|
+
In 2006 an iDEAL payment library was written in Ruby for a web shop build in Rails for selling mobile phone credits. It was basically a translation of the PHP example given by the iDEAL organization (see iDEAL Advanced Integration Manual PHP). Is was released as the ideal-on-rails library.
|
197
237
|
|
198
|
-
In
|
238
|
+
In 2007 this code was refactored as a patch for the ActiveMerchant library, this was mainly done by "Fingertips":http://www.fngtps.com/ for a client project. This patch was never accepted due to the fact it was too different (and maybe too obscure) from the 'normal' credit card gateways. After some lobbying an older patch of the code eventually found it's way into ActiveMerchant.
|
199
239
|
|
200
|
-
In
|
240
|
+
In 2009 Fingertips forked the ActiveMerchant library and added an iDEAL gateway based on the ActiveMerchant path.
|
201
241
|
|
202
|
-
|
242
|
+
In 2010 this code was extracted and converted into a separate gem by Frank Oxener of Agile Dovadi, so it can be more easily used in combination with the latest version of ActiveMerchant. This library was just an extraction, nothing more and nothing less. There were 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.com/paneidos added support for ABN AMRO.
|
203
243
|
|
204
|
-
|
244
|
+
At the end of 2011 Fingertips made yet another fork of the code as the iDeal gem. They ripped out all ActiveMerchant and Rails dependencies. In 2012 ABN AMRO switched their backend and support for this was also added.
|
data/lib/ideal/acquirers.rb
CHANGED
@@ -11,13 +11,8 @@ module Ideal
|
|
11
11
|
'test_url' => 'https://idealtest.rabobank.nl/ideal/iDeal'
|
12
12
|
},
|
13
13
|
'abnamro' => {
|
14
|
-
'
|
15
|
-
'
|
16
|
-
'live_status_url' => 'https://idealm.abnamro.nl/nl/acquirerStatusInquiry/getAcquirerStatusInquiry.xml',
|
17
|
-
|
18
|
-
'test_directory_url' => 'https://itt.idealdesk.com/ITTEmulatorAcquirer/Directory.aspx',
|
19
|
-
'test_transaction_url' => 'https://itt.idealdesk.com/ITTEmulatorAcquirer/Transaction.aspx',
|
20
|
-
'test_status_url' => 'https://itt.idealdesk.com/ITTEmulatorAcquirer/Status.aspx'
|
14
|
+
'live_url' => 'https://abnamro.ideal-payment.de/ideal/iDeal',
|
15
|
+
'test_url' => 'https://abnamro-test.ideal-payment.de/ideal/iDeal'
|
21
16
|
}
|
22
17
|
}
|
23
18
|
end
|
data/lib/ideal/gateway.rb
CHANGED
@@ -40,12 +40,7 @@ module Ideal
|
|
40
40
|
attr_accessor :passphrase
|
41
41
|
|
42
42
|
# Holds the test and production urls for your iDeal acquirer.
|
43
|
-
attr_accessor :live_url,
|
44
|
-
|
45
|
-
# For ABN AMRO only assign the three separate directory, transaction and status urls.
|
46
|
-
attr_accessor :live_directory_url, :test_directory_url
|
47
|
-
attr_accessor :live_transaction_url, :test_transaction_url
|
48
|
-
attr_accessor :live_status_url, :test_status_url
|
43
|
+
attr_accessor :live_url, :test_url
|
49
44
|
end
|
50
45
|
|
51
46
|
# Environment defaults to test
|
@@ -119,11 +114,6 @@ module Ideal
|
|
119
114
|
end
|
120
115
|
end
|
121
116
|
|
122
|
-
# Returns true when the acquirer was set to :abnamro
|
123
|
-
def self.abn_amro?
|
124
|
-
acquirer.to_sym == :abnamro
|
125
|
-
end
|
126
|
-
|
127
117
|
# Returns the merchant `subID' being used for this Gateway instance.
|
128
118
|
# Defaults to 0.
|
129
119
|
attr_reader :sub_id
|
@@ -135,11 +125,11 @@ module Ideal
|
|
135
125
|
@sub_id = options[:sub_id] || 0
|
136
126
|
end
|
137
127
|
|
138
|
-
# Returns the endpoint for
|
128
|
+
# Returns the endpoint for the request.
|
139
129
|
#
|
140
130
|
# Automatically uses test or live URLs based on the configuration.
|
141
|
-
def request_url
|
142
|
-
self.class.send("#{self.class.environment}
|
131
|
+
def request_url
|
132
|
+
self.class.send("#{self.class.environment}_url")
|
143
133
|
end
|
144
134
|
|
145
135
|
# Sends a directory request to the acquirer and returns an
|
@@ -148,7 +138,7 @@ module Ideal
|
|
148
138
|
#
|
149
139
|
# gateway.issuers.list # => [{ :id => '1006', :name => 'ABN AMRO Bank' }, …]
|
150
140
|
def issuers
|
151
|
-
post_data request_url
|
141
|
+
post_data request_url, build_directory_request_body, DirectoryResponse
|
152
142
|
end
|
153
143
|
|
154
144
|
# Starts a purchase by sending an acquirer transaction request for the
|
@@ -196,7 +186,7 @@ module Ideal
|
|
196
186
|
#
|
197
187
|
# See the Gateway class description for a more elaborate example.
|
198
188
|
def setup_purchase(money, options)
|
199
|
-
post_data request_url
|
189
|
+
post_data request_url, build_transaction_request_body(money, options), TransactionResponse
|
200
190
|
end
|
201
191
|
|
202
192
|
# Sends a acquirer status request for the specified +transaction_id+ and
|
@@ -216,23 +206,22 @@ module Ideal
|
|
216
206
|
#
|
217
207
|
# See the Gateway class description for a more elaborate example.
|
218
208
|
def capture(transaction_id)
|
219
|
-
post_data request_url
|
209
|
+
post_data request_url, build_status_request_body(:transaction_id => transaction_id), StatusResponse
|
220
210
|
end
|
221
211
|
|
222
212
|
private
|
223
213
|
|
224
|
-
# Returns the prefix to locate the setting for a certain request type. Only applies
|
225
|
-
# in the case of ABN AMRO because they use more than one endpoint.
|
226
|
-
def request_url_prefix(request_type)
|
227
|
-
(request_type && self.class.abn_amro?) ? "_#{request_type.to_s}" : nil
|
228
|
-
end
|
229
|
-
|
230
214
|
def ssl_post(url, body)
|
231
|
-
|
215
|
+
log('URL', url)
|
216
|
+
log('Request', body)
|
217
|
+
response = REST.post(url, body, {
|
218
|
+
'Content-Type' => 'application/xml; charset=utf-8'
|
219
|
+
}, {
|
232
220
|
:tls_verify => true,
|
233
221
|
:tls_key => self.class.private_key,
|
234
222
|
:tls_certificate => self.class.private_certificate
|
235
223
|
})
|
224
|
+
log('Response', response.body)
|
236
225
|
response.body
|
237
226
|
end
|
238
227
|
|
@@ -260,7 +249,7 @@ module Ideal
|
|
260
249
|
end
|
261
250
|
|
262
251
|
def strip_whitespace(str)
|
263
|
-
|
252
|
+
str.gsub(/\s/m,'')
|
264
253
|
end
|
265
254
|
|
266
255
|
# Creates a +tokenCode+ from the specified +message+.
|
@@ -421,5 +410,9 @@ module Ideal
|
|
421
410
|
]]
|
422
411
|
])
|
423
412
|
end
|
413
|
+
|
414
|
+
def log(thing, contents)
|
415
|
+
$stderr.write("\n#{thing}:\n\n#{contents}\n") if $DEBUG
|
416
|
+
end
|
424
417
|
end
|
425
418
|
end
|
data/lib/ideal/response.rb
CHANGED
@@ -196,7 +196,7 @@ module Ideal
|
|
196
196
|
# Returns whether or not the authenticity of the message could be
|
197
197
|
# verified.
|
198
198
|
def verified?
|
199
|
-
@verified ||= Gateway.ideal_certificate.public_key.
|
199
|
+
@verified ||= Ideal::Gateway.ideal_certificate.public_key.
|
200
200
|
verify(OpenSSL::Digest::SHA1.new, signature, message)
|
201
201
|
end
|
202
202
|
|
data/lib/ideal/version.rb
CHANGED
data/test/gateway_test.rb
CHANGED
@@ -43,9 +43,7 @@ module IdealTestCases
|
|
43
43
|
|
44
44
|
def test_verify_live_urls_for_abnamro
|
45
45
|
Ideal::Gateway.acquirer = :abnamro
|
46
|
-
assert_equal 'https://
|
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
|
46
|
+
assert_equal 'https://abnamro.ideal-payment.de/ideal/iDeal', Ideal::Gateway.live_url
|
49
47
|
end
|
50
48
|
|
51
49
|
def test_does_not_allow_configuration_of_unknown_acquirers
|
@@ -57,7 +55,7 @@ module IdealTestCases
|
|
57
55
|
def test_acquirers
|
58
56
|
assert_equal 'https://ideal.rabobank.nl/ideal/iDeal', Ideal::Gateway.acquirers['rabobank']['live_url']
|
59
57
|
assert_equal 'https://ideal.secure-ing.com/ideal/iDeal', Ideal::Gateway.acquirers['ing']['live_url']
|
60
|
-
assert_equal 'https://
|
58
|
+
assert_equal 'https://abnamro.ideal-payment.de/ideal/iDeal', Ideal::Gateway.acquirers['abnamro']['live_url']
|
61
59
|
end
|
62
60
|
|
63
61
|
def test_private_certificate_returns_a_loaded_Certificate_instance
|
@@ -80,39 +78,31 @@ module IdealTestCases
|
|
80
78
|
def setup
|
81
79
|
@gateway = Ideal::Gateway.new
|
82
80
|
end
|
83
|
-
|
81
|
+
|
84
82
|
def test_optional_initialization_options
|
85
83
|
assert_equal 0, Ideal::Gateway.new.sub_id
|
86
84
|
assert_equal 1, Ideal::Gateway.new(:sub_id => 1).sub_id
|
87
85
|
end
|
88
|
-
|
86
|
+
|
89
87
|
def test_returns_the_test_url_when_in_the_test_env
|
90
88
|
Ideal::Gateway.acquirer = :ing
|
91
89
|
Ideal::Gateway.environment = :test
|
92
|
-
assert_equal Ideal::Gateway.test_url, @gateway.send(:request_url
|
90
|
+
assert_equal Ideal::Gateway.test_url, @gateway.send(:request_url)
|
93
91
|
end
|
94
|
-
|
92
|
+
|
95
93
|
def test_returns_the_live_url_when_not_in_the_test_env
|
96
94
|
Ideal::Gateway.acquirer = :ing
|
97
95
|
Ideal::Gateway.environment = :live
|
98
|
-
assert_equal Ideal::Gateway.live_url, @gateway.send(:request_url
|
96
|
+
assert_equal Ideal::Gateway.live_url, @gateway.send(:request_url)
|
99
97
|
end
|
100
98
|
|
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
99
|
def test_returns_created_at_timestamp
|
110
100
|
timestamp = '2001-12-17T09:30:47.000Z'
|
111
101
|
Time.any_instance.stubs(:gmtime).returns(DateTime.parse(timestamp))
|
112
|
-
|
102
|
+
|
113
103
|
assert_equal timestamp, @gateway.send(:created_at_timestamp)
|
114
104
|
end
|
115
|
-
|
105
|
+
|
116
106
|
def test_ruby_to_java_keys_conversion
|
117
107
|
keys = [
|
118
108
|
[:acquirer_transaction_request, 'AcquirerTrxReq'],
|
@@ -131,77 +121,63 @@ module IdealTestCases
|
|
131
121
|
[:expiration_period, 'expirationPeriod'],
|
132
122
|
[:entrance_code, 'entranceCode']
|
133
123
|
]
|
134
|
-
|
124
|
+
|
135
125
|
keys.each do |key, expected_key|
|
136
126
|
assert_equal expected_key, @gateway.send(:javaize_key, key)
|
137
127
|
end
|
138
128
|
end
|
139
|
-
|
129
|
+
|
140
130
|
def test_does_not_convert_unknown_key_to_java_key
|
141
131
|
assert_equal 'not_a_registered_key', @gateway.send(:javaize_key, :not_a_registered_key)
|
142
132
|
end
|
143
|
-
|
133
|
+
|
144
134
|
def test_token_generation
|
145
135
|
expected_token = Digest::SHA1.hexdigest(OpenSSL::X509::Certificate.new(PRIVATE_CERTIFICATE).to_der).upcase
|
146
136
|
assert_equal expected_token, @gateway.send(:token)
|
147
137
|
end
|
148
|
-
|
138
|
+
|
149
139
|
def test_token_code_generation
|
150
140
|
Ideal::Gateway.acquirer = :ing
|
151
141
|
message = "Top\tsecret\tman.\nI could tell you, but then I'd have to kill you…"
|
152
142
|
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
|
-
|
143
|
+
|
168
144
|
sha1 = OpenSSL::Digest::SHA1.new
|
169
145
|
OpenSSL::Digest::SHA1.stubs(:new).returns(sha1)
|
170
|
-
|
146
|
+
|
171
147
|
signature = Ideal::Gateway.private_key.sign(sha1, stripped_message)
|
172
148
|
encoded_signature = Base64.encode64(signature).strip.gsub(/\n/, '')
|
173
|
-
|
149
|
+
|
174
150
|
assert_equal encoded_signature, @gateway.send(:token_code, message)
|
175
151
|
end
|
176
|
-
|
152
|
+
|
177
153
|
def test_posts_data_with_ssl_to_request_url_and_return_the_correct_response_for_test
|
178
154
|
Ideal::Gateway.environment = :test
|
179
155
|
Ideal::Response.expects(:new).with('response', :test => true)
|
180
|
-
@gateway.expects(:ssl_post).with(@gateway.request_url
|
181
|
-
@gateway.send(:post_data, @gateway.request_url
|
156
|
+
@gateway.expects(:ssl_post).with(@gateway.request_url, 'data').returns('response')
|
157
|
+
@gateway.send(:post_data, @gateway.request_url, 'data', Ideal::Response)
|
182
158
|
end
|
183
|
-
|
159
|
+
|
184
160
|
def test_posts_data_with_ssl_to_request_url_and_return_the_correct_response_for_live
|
185
161
|
Ideal::Gateway.environment = :live
|
186
162
|
Ideal::Response.expects(:new).with('response', :test => false)
|
187
|
-
@gateway.expects(:ssl_post).with(@gateway.request_url
|
188
|
-
@gateway.send(:post_data, @gateway.request_url
|
163
|
+
@gateway.expects(:ssl_post).with(@gateway.request_url, 'data').returns('response')
|
164
|
+
@gateway.send(:post_data, @gateway.request_url, 'data', Ideal::Response)
|
189
165
|
end
|
190
166
|
end
|
191
|
-
|
167
|
+
|
192
168
|
class XMLBuildingTest < Test::Unit::TestCase
|
193
169
|
def setup
|
194
170
|
@gateway = Ideal::Gateway.new
|
195
171
|
end
|
196
|
-
|
172
|
+
|
197
173
|
def test_contains_correct_info_in_root_node
|
198
174
|
expected_xml = Builder::XmlMarkup.new
|
199
175
|
expected_xml.instruct!
|
200
176
|
expected_xml.tag!('AcquirerTrxReq', 'xmlns' => Ideal::Gateway::XML_NAMESPACE, 'version' => Ideal::Gateway::API_VERSION) {}
|
201
|
-
|
177
|
+
|
202
178
|
assert_equal expected_xml.target!, @gateway.send(:xml_for, :acquirer_transaction_request, [])
|
203
179
|
end
|
204
|
-
|
180
|
+
|
205
181
|
def test_creates_correct_xml_with_java_keys_from_array_with_ruby_keys
|
206
182
|
expected_xml = Builder::XmlMarkup.new
|
207
183
|
expected_xml.instruct!
|
@@ -210,42 +186,42 @@ module IdealTestCases
|
|
210
186
|
expected_xml.tag!('createDateTimeStamp', '2009-01-26')
|
211
187
|
end
|
212
188
|
end
|
213
|
-
|
189
|
+
|
214
190
|
assert_equal expected_xml.target!, @gateway.send(:xml_for, :acquirer_transaction_request, [[:a_parent, [[:created_at, '2009-01-26']]]])
|
215
191
|
end
|
216
192
|
end
|
217
|
-
|
193
|
+
|
218
194
|
class RequestBodyBuildingTest < Test::Unit::TestCase
|
219
195
|
def setup
|
220
196
|
@gateway = Ideal::Gateway.new
|
221
|
-
|
197
|
+
|
222
198
|
@gateway.stubs(:created_at_timestamp).returns('created_at_timestamp')
|
223
199
|
@gateway.stubs(:token).returns('the_token')
|
224
200
|
@gateway.stubs(:token_code)
|
225
|
-
|
201
|
+
|
226
202
|
@transaction_id = '0001023456789112'
|
227
203
|
end
|
228
|
-
|
204
|
+
|
229
205
|
def test_build_transaction_request_body_raises_ArgumentError_with_missing_required_options
|
230
206
|
options = VALID_PURCHASE_OPTIONS.dup
|
231
207
|
options.keys.each do |key|
|
232
208
|
options.delete(key)
|
233
|
-
|
209
|
+
|
234
210
|
assert_raise(ArgumentError) do
|
235
211
|
@gateway.send(:build_transaction_request_body, 100, options)
|
236
212
|
end
|
237
213
|
end
|
238
214
|
end
|
239
|
-
|
215
|
+
|
240
216
|
def test_valid_with_valid_options
|
241
217
|
assert_not_nil @gateway.send(:build_transaction_request_body, 4321, VALID_PURCHASE_OPTIONS)
|
242
218
|
end
|
243
|
-
|
219
|
+
|
244
220
|
def test_checks_that_fields_are_not_too_long
|
245
221
|
assert_raise ArgumentError do
|
246
222
|
@gateway.send(:build_transaction_request_body, 1234567890123, VALID_PURCHASE_OPTIONS) # 13 chars
|
247
223
|
end
|
248
|
-
|
224
|
+
|
249
225
|
[
|
250
226
|
[:order_id, '12345678901234567'], # 17 chars,
|
251
227
|
[:description, '123456789012345678901234567890123'], # 33 chars
|
@@ -253,31 +229,31 @@ module IdealTestCases
|
|
253
229
|
].each do |key, value|
|
254
230
|
options = VALID_PURCHASE_OPTIONS.dup
|
255
231
|
options[key] = value
|
256
|
-
|
232
|
+
|
257
233
|
assert_raise ArgumentError do
|
258
234
|
@gateway.send(:build_transaction_request_body, 4321, options)
|
259
235
|
end
|
260
236
|
end
|
261
237
|
end
|
262
|
-
|
238
|
+
|
263
239
|
def test_checks_that_fields_do_not_contain_diacritical_characters
|
264
240
|
assert_raise ArgumentError do
|
265
241
|
@gateway.send(:build_transaction_request_body, 'graphème', VALID_PURCHASE_OPTIONS)
|
266
242
|
end
|
267
|
-
|
243
|
+
|
268
244
|
[:order_id, :description, :entrance_code].each do |key, value|
|
269
245
|
options = VALID_PURCHASE_OPTIONS.dup
|
270
246
|
options[key] = 'graphème'
|
271
|
-
|
247
|
+
|
272
248
|
assert_raise ArgumentError do
|
273
249
|
@gateway.send(:build_transaction_request_body, 4321, options)
|
274
250
|
end
|
275
251
|
end
|
276
252
|
end
|
277
|
-
|
253
|
+
|
278
254
|
def test_builds_a_transaction_request_body
|
279
255
|
money = 4321
|
280
|
-
|
256
|
+
|
281
257
|
message = 'created_at_timestamp' +
|
282
258
|
VALID_PURCHASE_OPTIONS[:issuer_id] +
|
283
259
|
Ideal::Gateway.merchant_id +
|
@@ -289,13 +265,13 @@ module IdealTestCases
|
|
289
265
|
Ideal::Gateway::LANGUAGE +
|
290
266
|
VALID_PURCHASE_OPTIONS[:description] +
|
291
267
|
VALID_PURCHASE_OPTIONS[:entrance_code]
|
292
|
-
|
268
|
+
|
293
269
|
@gateway.expects(:token_code).with(message).returns('the_token_code')
|
294
|
-
|
270
|
+
|
295
271
|
@gateway.expects(:xml_for).with(:acquirer_transaction_request, [
|
296
272
|
[:created_at, 'created_at_timestamp'],
|
297
273
|
[:issuer, [[:issuer_id, VALID_PURCHASE_OPTIONS[:issuer_id]]]],
|
298
|
-
|
274
|
+
|
299
275
|
[:merchant, [
|
300
276
|
[:merchant_id, Ideal::Gateway.merchant_id],
|
301
277
|
[:sub_id, @gateway.sub_id],
|
@@ -304,7 +280,7 @@ module IdealTestCases
|
|
304
280
|
[:token_code, 'the_token_code'],
|
305
281
|
[:merchant_return_url, VALID_PURCHASE_OPTIONS[:return_url]]
|
306
282
|
]],
|
307
|
-
|
283
|
+
|
308
284
|
[:transaction, [
|
309
285
|
[:purchase_id, VALID_PURCHASE_OPTIONS[:order_id]],
|
310
286
|
[:amount, money],
|
@@ -315,14 +291,14 @@ module IdealTestCases
|
|
315
291
|
[:entrance_code, VALID_PURCHASE_OPTIONS[:entrance_code]]
|
316
292
|
]]
|
317
293
|
])
|
318
|
-
|
294
|
+
|
319
295
|
@gateway.send(:build_transaction_request_body, money, VALID_PURCHASE_OPTIONS)
|
320
296
|
end
|
321
|
-
|
297
|
+
|
322
298
|
def test_builds_a_directory_request_body
|
323
299
|
message = 'created_at_timestamp' + Ideal::Gateway.merchant_id + @gateway.sub_id.to_s
|
324
300
|
@gateway.expects(:token_code).with(message).returns('the_token_code')
|
325
|
-
|
301
|
+
|
326
302
|
@gateway.expects(:xml_for).with(:directory_request, [
|
327
303
|
[:created_at, 'created_at_timestamp'],
|
328
304
|
[:merchant, [
|
@@ -333,22 +309,22 @@ module IdealTestCases
|
|
333
309
|
[:token_code, 'the_token_code']
|
334
310
|
]]
|
335
311
|
])
|
336
|
-
|
312
|
+
|
337
313
|
@gateway.send(:build_directory_request_body)
|
338
314
|
end
|
339
|
-
|
315
|
+
|
340
316
|
def test_builds_a_status_request_body_raises_ArgumentError_with_missing_required_options
|
341
317
|
assert_raise(ArgumentError) do
|
342
318
|
@gateway.send(:build_status_request_body, {})
|
343
319
|
end
|
344
320
|
end
|
345
|
-
|
321
|
+
|
346
322
|
def test_builds_a_status_request_body
|
347
323
|
options = { :transaction_id => @transaction_id }
|
348
|
-
|
324
|
+
|
349
325
|
message = 'created_at_timestamp' + Ideal::Gateway.merchant_id + @gateway.sub_id.to_s + options[:transaction_id]
|
350
326
|
@gateway.expects(:token_code).with(message).returns('the_token_code')
|
351
|
-
|
327
|
+
|
352
328
|
@gateway.expects(:xml_for).with(:acquirer_status_request, [
|
353
329
|
[:created_at, 'created_at_timestamp'],
|
354
330
|
[:merchant, [
|
@@ -358,67 +334,67 @@ module IdealTestCases
|
|
358
334
|
[:token, 'the_token'],
|
359
335
|
[:token_code, 'the_token_code']
|
360
336
|
]],
|
361
|
-
|
337
|
+
|
362
338
|
[:transaction, [
|
363
339
|
[:transaction_id, options[:transaction_id]]
|
364
340
|
]],
|
365
341
|
])
|
366
|
-
|
342
|
+
|
367
343
|
@gateway.send(:build_status_request_body, options)
|
368
344
|
end
|
369
345
|
end
|
370
|
-
|
346
|
+
|
371
347
|
class GeneralResponseTest < Test::Unit::TestCase
|
372
348
|
def test_resturns_if_it_is_a_test_request
|
373
349
|
assert Ideal::Response.new(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS, :test => true).test?
|
374
|
-
|
350
|
+
|
375
351
|
assert !Ideal::Response.new(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS, :test => false).test?
|
376
352
|
assert !Ideal::Response.new(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS).test?
|
377
353
|
end
|
378
354
|
end
|
379
|
-
|
355
|
+
|
380
356
|
class SuccessfulResponseTest < Test::Unit::TestCase
|
381
357
|
def setup
|
382
358
|
@response = Ideal::Response.new(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS)
|
383
359
|
end
|
384
|
-
|
360
|
+
|
385
361
|
def test_initializes_with_only_response_body
|
386
362
|
assert_equal REXML::Document.new(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS).root.to_s,
|
387
363
|
@response.instance_variable_get(:@response).to_s
|
388
364
|
end
|
389
|
-
|
365
|
+
|
390
366
|
def test_successful
|
391
367
|
assert @response.success?
|
392
368
|
end
|
393
|
-
|
369
|
+
|
394
370
|
def test_returns_no_error_messages
|
395
371
|
assert_nil @response.error_message
|
396
372
|
end
|
397
|
-
|
373
|
+
|
398
374
|
def test_returns_no_error_code
|
399
375
|
assert_nil @response.error_code
|
400
376
|
end
|
401
377
|
end
|
402
|
-
|
378
|
+
|
403
379
|
class ErrorResponseTest < Test::Unit::TestCase
|
404
380
|
def setup
|
405
381
|
@response = Ideal::Response.new(ERROR_RESPONSE)
|
406
382
|
end
|
407
|
-
|
383
|
+
|
408
384
|
def test_unsuccessful
|
409
385
|
assert !@response.success?
|
410
386
|
end
|
411
|
-
|
387
|
+
|
412
388
|
def test_returns_error_messages
|
413
389
|
assert_equal 'Failure in system', @response.error_message
|
414
390
|
assert_equal 'System generating error: issuer', @response.error_details
|
415
391
|
assert_equal 'Betalen met iDEAL is nu niet mogelijk.', @response.consumer_error_message
|
416
392
|
end
|
417
|
-
|
393
|
+
|
418
394
|
def test_returns_error_code
|
419
395
|
assert_equal 'SO1000', @response.error_code
|
420
396
|
end
|
421
|
-
|
397
|
+
|
422
398
|
def test_returns_error_type
|
423
399
|
[
|
424
400
|
['IX1000', :xml],
|
@@ -432,27 +408,27 @@ module IdealTestCases
|
|
432
408
|
end
|
433
409
|
end
|
434
410
|
end
|
435
|
-
|
411
|
+
|
436
412
|
class DirectoryTest < Test::Unit::TestCase
|
437
413
|
def setup
|
438
414
|
@gateway = Ideal::Gateway.new
|
439
415
|
end
|
440
|
-
|
416
|
+
|
441
417
|
def test_returns_a_list_with_only_one_issuer
|
442
418
|
@gateway.stubs(:build_directory_request_body).returns('the request body')
|
443
|
-
@gateway.expects(:ssl_post).with(@gateway.request_url
|
444
|
-
|
419
|
+
@gateway.expects(:ssl_post).with(@gateway.request_url, 'the request body').returns(DIRECTORY_RESPONSE_WITH_ONE_ISSUER)
|
420
|
+
|
445
421
|
expected_issuers = [{ :id => '1006', :name => 'ABN AMRO Bank' }]
|
446
|
-
|
422
|
+
|
447
423
|
directory_response = @gateway.issuers
|
448
424
|
assert_instance_of Ideal::DirectoryResponse, directory_response
|
449
425
|
assert_equal expected_issuers, directory_response.list
|
450
426
|
end
|
451
|
-
|
427
|
+
|
452
428
|
def test_returns_list_of_issuers_from_response
|
453
429
|
@gateway.stubs(:build_directory_request_body).returns('the request body')
|
454
|
-
@gateway.expects(:ssl_post).with(@gateway.request_url
|
455
|
-
|
430
|
+
@gateway.expects(:ssl_post).with(@gateway.request_url, 'the request body').returns(DIRECTORY_RESPONSE_WITH_MULTIPLE_ISSUERS)
|
431
|
+
|
456
432
|
expected_issuers = [
|
457
433
|
{ :id => '1006', :name => 'ABN AMRO Bank' },
|
458
434
|
{ :id => '1003', :name => 'Postbank' },
|
@@ -460,85 +436,85 @@ module IdealTestCases
|
|
460
436
|
{ :id => '1017', :name => 'Asr bank' },
|
461
437
|
{ :id => '1023', :name => 'Van Lanschot' }
|
462
438
|
]
|
463
|
-
|
439
|
+
|
464
440
|
directory_response = @gateway.issuers
|
465
441
|
assert_instance_of Ideal::DirectoryResponse, directory_response
|
466
442
|
assert_equal expected_issuers, directory_response.list
|
467
443
|
end
|
468
444
|
end
|
469
|
-
|
445
|
+
|
470
446
|
class SetupPurchaseTest < Test::Unit::TestCase
|
471
447
|
def setup
|
472
448
|
@gateway = Ideal::Gateway.new
|
473
|
-
|
449
|
+
|
474
450
|
@gateway.stubs(:build_transaction_request_body).with(4321, VALID_PURCHASE_OPTIONS).returns('the request body')
|
475
|
-
@gateway.expects(:ssl_post).with(@gateway.request_url
|
476
|
-
|
451
|
+
@gateway.expects(:ssl_post).with(@gateway.request_url, 'the request body').returns(ACQUIRER_TRANSACTION_RESPONSE)
|
452
|
+
|
477
453
|
@setup_purchase_response = @gateway.setup_purchase(4321, VALID_PURCHASE_OPTIONS)
|
478
454
|
end
|
479
|
-
|
455
|
+
|
480
456
|
def test_setup_purchase_returns_IdealTransactionResponse
|
481
457
|
assert_instance_of Ideal::TransactionResponse, @setup_purchase_response
|
482
458
|
end
|
483
|
-
|
459
|
+
|
484
460
|
def test_setup_purchase_returns_response_with_service_url
|
485
461
|
assert_equal 'https://ideal.example.com/long_service_url?X009=BETAAL&X010=20', @setup_purchase_response.service_url
|
486
462
|
end
|
487
|
-
|
463
|
+
|
488
464
|
def test_setup_purchase_returns_response_with_transaction_and_order_ids
|
489
465
|
assert_equal '0001023456789112', @setup_purchase_response.transaction_id
|
490
466
|
assert_equal 'iDEAL-aankoop 21', @setup_purchase_response.order_id
|
491
467
|
end
|
492
468
|
end
|
493
|
-
|
469
|
+
|
494
470
|
class CapturePurchaseTest < Test::Unit::TestCase
|
495
471
|
def setup
|
496
472
|
@gateway = Ideal::Gateway.new
|
497
|
-
|
473
|
+
|
498
474
|
@gateway.stubs(:build_status_request_body).
|
499
475
|
with(:transaction_id => '0001023456789112').returns('the request body')
|
500
476
|
end
|
501
|
-
|
477
|
+
|
502
478
|
def test_setup_purchase_returns_IdealStatusResponse
|
503
479
|
expects_request_and_returns ACQUIRER_SUCCEEDED_STATUS_RESPONSE
|
504
480
|
assert_instance_of Ideal::StatusResponse, @gateway.capture('0001023456789112')
|
505
481
|
end
|
506
|
-
|
482
|
+
|
507
483
|
# Because we don't have a real private key and certificate we stub
|
508
484
|
# verified? to return true. However, this is properly tested in the remote
|
509
485
|
# tests.
|
510
486
|
def test_capture_of_successful_payment
|
511
487
|
Ideal::StatusResponse.any_instance.stubs(:verified?).returns(true)
|
512
|
-
|
488
|
+
|
513
489
|
expects_request_and_returns ACQUIRER_SUCCEEDED_STATUS_RESPONSE
|
514
490
|
capture_response = @gateway.capture('0001023456789112')
|
515
|
-
|
491
|
+
|
516
492
|
assert capture_response.success?
|
517
493
|
end
|
518
|
-
|
494
|
+
|
519
495
|
def test_capture_of_failed_payment
|
520
496
|
expects_request_and_returns ACQUIRER_FAILED_STATUS_RESPONSE
|
521
497
|
capture_response = @gateway.capture('0001023456789112')
|
522
|
-
|
498
|
+
|
523
499
|
assert !capture_response.success?
|
524
500
|
end
|
525
|
-
|
501
|
+
|
526
502
|
def test_capture_of_successful_payment_but_message_does_not_match_signature
|
527
503
|
expects_request_and_returns ACQUIRER_SUCCEEDED_BUT_WRONG_SIGNATURE_STATUS_RESPONSE
|
528
504
|
capture_response = @gateway.capture('0001023456789112')
|
529
|
-
|
505
|
+
|
530
506
|
assert !capture_response.success?
|
531
507
|
end
|
532
|
-
|
508
|
+
|
533
509
|
def test_capture_of_consumer_fields
|
534
510
|
expects_request_and_returns ACQUIRER_SUCCEEDED_STATUS_RESPONSE
|
535
511
|
capture_response = @gateway.capture('0001023456789112')
|
536
|
-
|
512
|
+
|
537
513
|
assert_equal '0949298989', capture_response.consumer_account_number
|
538
514
|
assert_equal 'Onderheuvel', capture_response.consumer_name
|
539
515
|
assert_equal 'DEN HAAG', capture_response.consumer_city
|
540
516
|
end
|
541
|
-
|
517
|
+
|
542
518
|
def test_returns_status
|
543
519
|
response = Ideal::StatusResponse.new(ACQUIRER_SUCCEEDED_STATUS_RESPONSE)
|
544
520
|
[
|
@@ -552,11 +528,11 @@ module IdealTestCases
|
|
552
528
|
assert_equal expected_status, response.status
|
553
529
|
end
|
554
530
|
end
|
555
|
-
|
531
|
+
|
556
532
|
private
|
557
|
-
|
533
|
+
|
558
534
|
def expects_request_and_returns(str)
|
559
|
-
@gateway.expects(:ssl_post).with(@gateway.request_url
|
535
|
+
@gateway.expects(:ssl_post).with(@gateway.request_url, 'the request body').returns(str)
|
560
536
|
end
|
561
537
|
end
|
562
538
|
|
data/test/remote_test.rb
CHANGED
@@ -9,8 +9,10 @@ class IdealTest < Test::Unit::TestCase
|
|
9
9
|
|
10
10
|
@gateway = Ideal::Gateway.new
|
11
11
|
|
12
|
+
@@issuer ||= @gateway.issuers.list[0]
|
13
|
+
|
12
14
|
@valid_options = {
|
13
|
-
:issuer_id =>
|
15
|
+
:issuer_id => @@issuer[:id],
|
14
16
|
:expiration_period => 'PT10M',
|
15
17
|
:return_url => 'http://return_to.example.com',
|
16
18
|
:order_id => '123456789012',
|
@@ -59,7 +61,10 @@ class IdealTest < Test::Unit::TestCase
|
|
59
61
|
#
|
60
62
|
|
61
63
|
def test_retrieval_of_issuers
|
62
|
-
|
64
|
+
issuer_list = @gateway.issuers.list
|
65
|
+
assert_equal 1, issuer_list.length
|
66
|
+
assert_match /^Issuer\ Sim/, issuer_list[0][:name]
|
67
|
+
assert_match /^\d{4}$/, issuer_list[0][:id]
|
63
68
|
end
|
64
69
|
|
65
70
|
def test_successful_transaction
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ideal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 59
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 9
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.9.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Soemirno Kartosoewito
|
@@ -19,7 +19,7 @@ autorequire:
|
|
19
19
|
bindir: bin
|
20
20
|
cert_chain: []
|
21
21
|
|
22
|
-
date: 2012-01-
|
22
|
+
date: 2012-01-19 00:00:00 Z
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
25
25
|
name: builder
|
@@ -75,6 +75,7 @@ extra_rdoc_files:
|
|
75
75
|
files:
|
76
76
|
- .document
|
77
77
|
- .gitignore
|
78
|
+
- .kick
|
78
79
|
- .travis.yml
|
79
80
|
- Gemfile
|
80
81
|
- Gemfile.lock
|