internetkassa 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ require 'abn-amro/internetkassa'
2
+ require 'abn-amro/internetkassa/helpers'
3
+
4
+ ActionView::Base.send(:include, AbnAmro::Internetkassa::Helpers)
@@ -0,0 +1,74 @@
1
+ RESPONSES = {
2
+ :succeeded => {
3
+ "CN" => "Buyer name",
4
+ "BRAND" => "iDEAL",
5
+ "orderID" => "1235052040",
6
+ "PAYID" => "3051611",
7
+ "ACCEPTANCE" => "0000000000",
8
+ "amount" => "10",
9
+ "CARDNO" => "11-XXXX-11",
10
+ "PM" => "iDEAL",
11
+ "STATUS" => "9",
12
+ "IP" => "83.68.2.74",
13
+ "TRXDATE" => "02/19/09",
14
+ "NCERROR" => "0",
15
+ "ED" => "",
16
+ "SHASIGN" => "7537DD222E35EE9F9842921BD90C2CBFCFA59466",
17
+ "currency" => "EUR"
18
+ },
19
+
20
+ :failed => {
21
+ "CN" => "",
22
+ "BRAND" => "iDEAL",
23
+ "orderID" => "1235052641",
24
+ "PAYID" => "3051687",
25
+ "ACCEPTANCE" => "",
26
+ "amount" => "10",
27
+ "CARDNO" => "",
28
+ "PM" => "iDEAL",
29
+ "STATUS" => "2",
30
+ "IP" => "83.68.2.74",
31
+ "TRXDATE" => "02/19/09",
32
+ "NCERROR" => "30001001",
33
+ "ED" => "",
34
+ "SHASIGN" => "BC9E821662DFD1EBC6E23BF044F6957796076B80",
35
+ "currency" => "EUR"
36
+ },
37
+
38
+ :cancelled => {
39
+ "CN" => "",
40
+ "BRAND" => "iDEAL",
41
+ "orderID" => "1235052559",
42
+ "PAYID" => "3051681",
43
+ "ACCEPTANCE" => "",
44
+ "amount" => "10",
45
+ "CARDNO" => "",
46
+ "PM" => "iDEAL",
47
+ "STATUS" => "2",
48
+ "IP" => "83.68.2.74",
49
+ "TRXDATE" => "02/19/09",
50
+ "NCERROR" => "30171001",
51
+ "ED" => "",
52
+ "SHASIGN" => "734AB5AD3033C46E1F69CBFB91EDD0AD34E7368D",
53
+ "currency" => "EUR"
54
+ },
55
+
56
+ :exception => {
57
+ "CN" => "",
58
+ "BRAND" => "iDEAL",
59
+ "orderID" => "1235052396",
60
+ "PAYID" => "3051657",
61
+ "action" => "index",
62
+ "ACCEPTANCE" => "",
63
+ "amount" => "10",
64
+ "CARDNO" => "",
65
+ "PM" => "iDEAL",
66
+ "STATUS" => "92",
67
+ "IP" => "83.68.2.74",
68
+ "TRXDATE" => "02/19/09",
69
+ "NCERROR" => "20002001",
70
+ "ED" => "",
71
+ "SHASIGN" => "614F540CC51607DA44CB8D2403B8DF1781B9712C",
72
+ "currency" => "EUR"
73
+ }
74
+ }
@@ -0,0 +1,7 @@
1
+ module FixturesHelper
2
+ def fixture(name)
3
+ RESPONSES[name]
4
+ end
5
+ end
6
+
7
+ Test::Unit::TestCase.send(:include, FixturesHelper)
@@ -0,0 +1,19 @@
1
+ require 'action_controller'
2
+ require 'action_view'
3
+ require 'action_view/test_case'
4
+
5
+ class TestController
6
+ attr_accessor :output_buffer
7
+
8
+ def initialize
9
+ @output_buffer = ''
10
+ end
11
+
12
+ def url_for(options)
13
+ "http://www.example.com"
14
+ end
15
+
16
+ def protect_against_forgery?
17
+ false
18
+ end
19
+ end
@@ -0,0 +1,45 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "AbnAmro::Internetkassa::Helpers", ActionView::TestCase do
4
+ tests AbnAmro::Internetkassa::Helpers
5
+
6
+ before do
7
+ @controller = TestController.new
8
+
9
+ @instance = AbnAmro::Internetkassa.new(
10
+ :order_id => 123,
11
+ :amount => 1000,
12
+ :description => "HappyHardcore vol. 123 - the ballads",
13
+ :endpoint_url => "http://example.com/payments",
14
+ :TITLE => 'HappyHardcore vol. 123 - the ballads'
15
+ )
16
+
17
+ # make sure we don't get bitten by sorting
18
+ ordered_data = @instance.data.to_a
19
+ @instance.stubs(:data).returns(ordered_data)
20
+ end
21
+
22
+ it "should create a form tag with the AbnAmro::Internetkassa.service_url as its action" do
23
+ expected = %{<form action="#{AbnAmro::Internetkassa.service_url}" method="post">}
24
+ internetkassa_form_tag(@instance)[0..expected.length-1].should == expected
25
+ end
26
+
27
+ it "should create a form with data from a AbnAmro::Internetkassa instance and yield" do
28
+ internetkassa_form_tag(@instance) { concat submit_tag('Betaal') }
29
+
30
+ expected = [%{<form action="#{AbnAmro::Internetkassa.service_url}" method="post">}]
31
+ @instance.data.each do |name, value|
32
+ expected << %{<input name="#{name}" type="hidden" value="#{value}" />}
33
+ end
34
+ expected << %{<input name="commit" type="submit" value="Betaal" />}
35
+ expected << "</form>"
36
+
37
+ assert_dom_equal expected.join("\n"), output_buffer
38
+ end
39
+
40
+ private
41
+
42
+ def method_missing(method, *args, &block)
43
+ @controller.send(method, *args, &block)
44
+ end
45
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ require 'rest'
4
+ require 'hpricot'
5
+
6
+ describe "AbnAmro::Internetkassa, when remote testing" do
7
+ before do
8
+ @instance = AbnAmro::Internetkassa.new(
9
+ :order_id => Time.now.to_i.to_s,
10
+ :amount => 1000,
11
+ :description => "HappyHardcore vol. 123 - the ballads",
12
+ :TITLE => 'HappyHardcore vol. 123 - the ballads'
13
+ )
14
+ end
15
+
16
+ it "should have the right data to make a successful POST request" do
17
+ response = post(AbnAmro::Internetkassa.service_url, @instance.data)
18
+ response.should.be.success
19
+
20
+ parse_response(response).should == {
21
+ :beneficiary => 'Fingertips BV',
22
+ :order_id => @instance.order_id,
23
+ :amount => '10.00 EUR',
24
+ :title => 'HappyHardcore vol. 123 - the ballads'
25
+ }
26
+ end
27
+
28
+ private
29
+
30
+ def post(uri, values)
31
+ body = values.map { |k,v| "#{k}=#{v.to_s.gsub(' ', '%20')}" }.join('&')
32
+ REST.post(uri, body)
33
+ end
34
+
35
+ def parse_response(response)
36
+ results = {}
37
+
38
+ doc = Hpricot(response.body)
39
+ (doc / '#ncol_ref' / 'tr').each do |row|
40
+ cols = (row / 'td')
41
+
42
+ key = case cols.first.inner_text
43
+ when /Ordernummer/
44
+ :order_id
45
+ when /Totaalbedrag/
46
+ :amount
47
+ when /Begunstigde/
48
+ :beneficiary
49
+ end
50
+
51
+ results[key] = cols.last.inner_text.strip
52
+ end
53
+
54
+ results[:title] = (doc / 'title').inner_text.strip
55
+ results
56
+ end
57
+ end
@@ -0,0 +1,151 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "AbnAmro::Internetkassa, class methods" do
4
+ it "should return whether or not it's in test mode" do
5
+ assert AbnAmro::Internetkassa.test?
6
+ end
7
+
8
+ it "should return the PSPID with #pspid or its aliased handsome cousin #merchant_id" do
9
+ AbnAmro::Internetkassa.pspid.should == 'fingertips'
10
+ AbnAmro::Internetkassa.merchant_id.should == 'fingertips'
11
+ end
12
+
13
+ it "should return the passphrase used to sign the messages to the payment server" do
14
+ AbnAmro::Internetkassa.shasign.should == 'supersecret'
15
+ AbnAmro::Internetkassa.passphrase.should == 'supersecret'
16
+ end
17
+
18
+ it "should have the correct service_urls" do
19
+ AbnAmro::Internetkassa::TEST_URL.should ==
20
+ "https://internetkassa.abnamro.nl/ncol/test/orderstandard.asp"
21
+
22
+ AbnAmro::Internetkassa::PRODUCTION_URL.should ==
23
+ "https://internetkassa.abnamro.nl/ncol/prod/orderstandard.asp"
24
+ end
25
+
26
+ it "should return the service_url for the current environment" do
27
+ begin
28
+ AbnAmro::Internetkassa.test = true
29
+ AbnAmro::Internetkassa.service_url.should ==
30
+ AbnAmro::Internetkassa::TEST_URL
31
+
32
+ AbnAmro::Internetkassa.test = false
33
+ AbnAmro::Internetkassa.service_url.should ==
34
+ AbnAmro::Internetkassa::PRODUCTION_URL
35
+ ensure
36
+ AbnAmro::Internetkassa.test = true
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "AbnAmro::Internetkassa, an instance" do
42
+ before do
43
+ @valid_attributes = {
44
+ :order_id => 123,
45
+ :amount => 1000,
46
+ :description => "HappyHardcore vol. 123 - the ballads",
47
+ :endpoint_url => "http://example.com/payments",
48
+ :url_variable => ":id",
49
+ :endpoint_params => [[:session_id, 'abcde12345'], [:message, '“Thanks for your purchase”']]
50
+ }
51
+ @instance = AbnAmro::Internetkassa.new(@valid_attributes)
52
+ end
53
+
54
+ it "should have assigned the constructor arguments" do
55
+ @instance.order_id.should == 123
56
+ @instance.amount.should == 1000
57
+ @instance.description.should == "HappyHardcore vol. 123 - the ballads"
58
+ end
59
+
60
+ it "should have used the endpoint_url shortcut to set all endpoint urls" do
61
+ @instance.accept_url.should == "http://example.com/payments"
62
+ @instance.decline_url.should == "http://example.com/payments"
63
+ @instance.exception_url.should == "http://example.com/payments"
64
+ @instance.cancel_url.should == "http://example.com/payments"
65
+ end
66
+
67
+ it "should have merged default values" do
68
+ @instance.currency.should == 'EUR'
69
+ @instance.language.should == 'nl_NL'
70
+ end
71
+
72
+ it "should return the url_variable" do
73
+ @instance.url_variable.should == ":id"
74
+ end
75
+
76
+ it "should return the extra params" do
77
+ @instance.endpoint_params.should == [[:session_id, 'abcde12345'], [:message, '“Thanks for your purchase”']]
78
+ end
79
+
80
+ it "should have access to the pspid/merchant_id" do
81
+ @instance.send(:merchant_id).should == AbnAmro::Internetkassa.merchant_id
82
+ end
83
+
84
+ it "should have access to the shasign/passphrase" do
85
+ @instance.send(:passphrase).should == AbnAmro::Internetkassa.passphrase
86
+ end
87
+
88
+ it "should verify that the mandatory values are specified or raise an ArgumentError" do
89
+ %w{ merchant_id order_id amount currency language }.each do |key|
90
+ instance = AbnAmro::Internetkassa.new(@valid_attributes)
91
+ instance.stubs(key).returns(nil)
92
+ lambda { instance.send(:verify_values!) }.should.raise ArgumentError
93
+ end
94
+ end
95
+
96
+ it "should create a SHA1 signature for the message" do
97
+ message = "#{@instance.order_id}#{@instance.amount}#{@instance.currency}#{AbnAmro::Internetkassa.merchant_id}#{AbnAmro::Internetkassa.passphrase}"
98
+ @instance.send(:signature).should == Digest::SHA1.hexdigest(message).upcase
99
+ end
100
+
101
+ it "should return the key-value pairs that should be POSTed, according to the Internetkassa specs" do
102
+ @instance.data.should == {
103
+ :PSPID => AbnAmro::Internetkassa.merchant_id,
104
+ :orderID => @instance.order_id,
105
+ :amount => @instance.amount,
106
+ :currency => @instance.currency,
107
+ :language => @instance.language,
108
+ :COM => @instance.description,
109
+ :SHASign => @instance.send(:signature),
110
+ :PARAMVAR => @instance.url_variable,
111
+ :PARAMPLUS => "session_id=abcde12345&message=%E2%80%9CThanks+for+your+purchase%E2%80%9D",
112
+ :accepturl => @valid_attributes[:endpoint_url],
113
+ :declineurl => @valid_attributes[:endpoint_url],
114
+ :exceptionurl => @valid_attributes[:endpoint_url],
115
+ :cancelurl => @valid_attributes[:endpoint_url]
116
+ }
117
+ end
118
+
119
+ it "should check if all mandatory values are specified before returning the `data'" do
120
+ @instance.expects(:verify_values!)
121
+ @instance.data
122
+ end
123
+
124
+ it "should merge any optional arguments with the data" do
125
+ @valid_attributes[:TITLE] = 'My Transaction'
126
+ AbnAmro::Internetkassa.new(@valid_attributes).data.should == {
127
+ :PSPID => AbnAmro::Internetkassa.merchant_id,
128
+ :orderID => @instance.order_id,
129
+ :amount => @instance.amount,
130
+ :currency => @instance.currency,
131
+ :language => @instance.language,
132
+ :COM => @instance.description,
133
+ :SHASign => @instance.send(:signature),
134
+ :PARAMVAR => @instance.url_variable,
135
+ :PARAMPLUS => "session_id=abcde12345&message=%E2%80%9CThanks+for+your+purchase%E2%80%9D",
136
+ :accepturl => @valid_attributes[:endpoint_url],
137
+ :declineurl => @valid_attributes[:endpoint_url],
138
+ :exceptionurl => @valid_attributes[:endpoint_url],
139
+ :cancelurl => @valid_attributes[:endpoint_url],
140
+ :TITLE => 'My Transaction'
141
+ }
142
+ end
143
+
144
+ it "should not return blank values in the `data'" do
145
+ @instance.url_variable = nil
146
+ @instance.data.should.not.has_key :PARAMVAR
147
+
148
+ @instance.url_variable = ''
149
+ @instance.data.should.not.has_key :PARAMVAR
150
+ end
151
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "AbnAmro::Internetkassa::Response, regression tests" do
4
+ before do
5
+ AbnAmro::Internetkassa::Response.any_instance.stubs(:valid?).returns(true)
6
+ @response = AbnAmro::Internetkassa::Response.new({})
7
+ end
8
+
9
+ it "should be retryable" do
10
+ retry_codes = AbnAmro::Internetkassa::Response::Codes::ERROR_CODES.select { |_,h| h[:retry] }
11
+ retry_codes.should.not.be.empty
12
+
13
+ retry_all = retry_codes.all? do |code, _|
14
+ @response.stubs(:error_code).returns(code)
15
+ @response.retry?
16
+ end
17
+
18
+ retry_all.should.be true
19
+ end
20
+
21
+ it "should not be retryable" do
22
+ dont_retry_codes = AbnAmro::Internetkassa::Response::Codes::ERROR_CODES.select { |_,h| !h[:retry] }
23
+ dont_retry_codes.should.not.be.empty
24
+
25
+ dont_retry_any = dont_retry_codes.all? do |code, _|
26
+ @response.stubs(:error_code).returns(code)
27
+ @response.retry? == false
28
+ end
29
+
30
+ dont_retry_any.should.be true
31
+ end
32
+ end
@@ -0,0 +1,185 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "AbnAmro::Internetkassa::Response, in general" do
4
+ before do
5
+ @response = AbnAmro::Internetkassa::Response.new(fixture(:succeeded))
6
+ end
7
+
8
+ it "should return the raw params" do
9
+ @response.params.should == fixture(:succeeded)
10
+ end
11
+
12
+ it "should return whether or not the transaction was authorized" do
13
+ @response.stubs(:status_code).returns('5')
14
+ @response.should.be.authorized
15
+
16
+ @response.stubs(:status_code).returns('9')
17
+ @response.should.not.be.authorized
18
+ end
19
+
20
+ it "should return whether or not the transaction was captured" do
21
+ @response.stubs(:status_code).returns('9')
22
+ @response.should.be.captured
23
+
24
+ @response.stubs(:status_code).returns('5')
25
+ @response.should.not.be.captured
26
+ end
27
+
28
+ it "should return the essential attributes" do
29
+ @response.order_id.should == '1235052040'
30
+ @response.payment_id.should == '3051611'
31
+ @response.payment_method.should == 'iDEAL'
32
+ @response.acceptance.should == '0000000000'
33
+ @response.status_code.should == '9'
34
+ @response.signature.should == '7537DD222E35EE9F9842921BD90C2CBFCFA59466'
35
+ @response.currency.should == 'EUR'
36
+ end
37
+
38
+ it "should return the optional attributes" do
39
+ @response.customer_name.should == 'Buyer name'
40
+ @response.card_number.should == '11-XXXX-11'
41
+ @response.card_brand.should == 'iDEAL'
42
+ @response.card_expiration_date.should == ''
43
+ end
44
+
45
+ it "should return the amount in cents" do
46
+ @response.instance_variable_set(:@params, 'amount' => '10')
47
+ @response.amount.should == 1000
48
+ end
49
+
50
+ it "should return the amount with decimals in cents" do
51
+ @response.instance_variable_set(:@params, 'amount' => '10.31')
52
+ @response.amount.should == 1031
53
+ end
54
+
55
+ it "should return the transaction date as a Date instance" do
56
+ @response.transaction_date.should == Date.parse('02/19/2009')
57
+ end
58
+
59
+ it "should create a SHA1 signature for the message" do
60
+ message = @response.order_id
61
+ message += @response.currency
62
+ message += @response.params['amount']
63
+ message += @response.payment_method
64
+ message += @response.acceptance
65
+ message += @response.status_code
66
+ message += @response.card_number
67
+ message += @response.payment_id
68
+ message += @response.params['NCERROR']
69
+ message += @response.card_brand
70
+
71
+ message += AbnAmro::Internetkassa.passphrase
72
+
73
+ @response.send(:calculated_signature).should == Digest::SHA1.hexdigest(message).upcase
74
+ end
75
+
76
+ it "should return that the signature matches the calculated_signature" do
77
+ @response.should.be.valid
78
+ end
79
+
80
+ it "should return that the signature does NOT match the calculated_signature" do
81
+ @response.stubs(:signature).returns('NOT A VALID SHA1 SIGNATURE')
82
+ @response.should.not.be.valid
83
+ end
84
+
85
+ it "should raise a SignatureInvalidError if initializing a response and the signature does not match the calculated_signature" do
86
+ params = fixture(:succeeded).dup
87
+ params['SHASIGN'] = 'NOT A VALID SHA1 SIGNATURE'
88
+
89
+ lambda {
90
+ AbnAmro::Internetkassa::Response.new(params)
91
+ }.should.raise AbnAmro::Internetkassa::Response::SignatureInvalidError
92
+ end
93
+
94
+ it "should return the message for the status code" do
95
+ @response.status_message.should == 'Payment requested'
96
+ end
97
+ end
98
+
99
+ describe "AbnAmro::Internetkassa::Response, with a successful payment" do
100
+ before do
101
+ @response = AbnAmro::Internetkassa::Response.new(fixture(:succeeded))
102
+ end
103
+
104
+ it "should be successful" do
105
+ @response.should.be.success
106
+ end
107
+
108
+ it "should not be retryable" do
109
+ @response.should.not.retry
110
+ end
111
+
112
+ it "should return `nil' as the error code" do
113
+ @response.error_code.should.be nil
114
+ end
115
+
116
+ it "should return `nil' as the error message" do
117
+ @response.error_message.should.be nil
118
+ end
119
+ end
120
+
121
+ describe "AbnAmro::Internetkassa::Response, with a failed payment" do
122
+ before do
123
+ @response = AbnAmro::Internetkassa::Response.new(fixture(:failed))
124
+ end
125
+
126
+ it "should not be successful" do
127
+ @response.should.not.be.success
128
+ end
129
+
130
+ it "should not be retryable" do
131
+ @response.should.not.retry
132
+ end
133
+
134
+ it "should return the error code" do
135
+ @response.error_code.should == "30001001"
136
+ end
137
+
138
+ it "should return the error message" do
139
+ @response.error_message.should == "Payment refused by the acquirer"
140
+ end
141
+ end
142
+
143
+ describe "AbnAmro::Internetkassa::Response, with a cancelled payment" do
144
+ before do
145
+ @response = AbnAmro::Internetkassa::Response.new(fixture(:cancelled))
146
+ end
147
+
148
+ it "should not be successful" do
149
+ @response.should.not.be.success
150
+ end
151
+
152
+ it "should not be retryable" do
153
+ @response.should.not.retry
154
+ end
155
+
156
+ it "should return the error code" do
157
+ @response.error_code.should == "30171001"
158
+ end
159
+
160
+ it "should return the error message" do
161
+ @response.error_message.should == "Payment method cancelled by the buyer"
162
+ end
163
+ end
164
+
165
+ describe "AbnAmro::Internetkassa::Response, when an exception occurred" do
166
+ before do
167
+ @response = AbnAmro::Internetkassa::Response.new(fixture(:exception))
168
+ end
169
+
170
+ it "should not be successful" do
171
+ @response.should.not.be.success
172
+ end
173
+
174
+ it "should not be retryable" do
175
+ @response.should.not.retry
176
+ end
177
+
178
+ it "should return the error code" do
179
+ @response.error_code.should == "20002001"
180
+ end
181
+
182
+ it "should return the error message" do
183
+ @response.error_message.should == "Origin for the response of the bank can not be checked"
184
+ end
185
+ end