exact4r 1.2 → 1.4

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ == v1.4
2
+ Added support for specifying alternative SSL certificates
3
+
4
+ == v1.3
5
+ Added support for TaggedUpdate transactions
6
+ Added support for ReferencedVoid transactions
7
+
1
8
  == v1.2
2
9
  Updated with new SSL certificates for https://api.e-xact.com
3
10
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2
1
+ 1.4
@@ -0,0 +1,63 @@
1
+ module EWS # :nodoc:
2
+ module CertificateHelper
3
+
4
+ EXACT_ISSUER_CERT_FILE = File.dirname(__FILE__)+"/../../certs/valicert_class2_root.crt" unless defined?(EXACT_ISSUER_CERT_FILE)
5
+ EXACT_SERVER_CERT_FILE = File.dirname(__FILE__)+"/../../certs/e-xact.com.crt" unless defined?(EXACT_SERVER_CERT_FILE)
6
+
7
+ attr_accessor :issuer_cert_file, :server_cert
8
+
9
+ def configure_certificates(options)
10
+ self.issuer_cert_file = (options[:issuer_cert] || EXACT_ISSUER_CERT_FILE)
11
+ server_cert_file = (options[:server_cert] || EXACT_SERVER_CERT_FILE)
12
+ self.server_cert = File.new(server_cert_file).read
13
+ end
14
+ private :configure_certificates
15
+
16
+ def validate_certificate(is_ok, ctx)
17
+ cert = ctx.current_cert
18
+ return false if cert.nil?
19
+
20
+ # preverify failed?
21
+ return false unless is_ok
22
+
23
+ self_signed = false
24
+ ca = false
25
+ pathlen = nil
26
+ server_auth = true
27
+ self_signed = (cert.subject.cmp(cert.issuer) == 0)
28
+
29
+ # Check extensions for the certificate purpose according to http://www.openssl.org/docs/apps/x509.html (Certificate Extensions) and
30
+ # http://www.ietf.org/rfc/rfc3280.txt.
31
+ cert.extensions.each do |ex|
32
+ case ex.oid
33
+ when 'basicConstraints'
34
+ /CA:(TRUE|FALSE)(?:, pathlen:)*(\d*)/ =~ ex.value
35
+ ca ||= ($1 == 'TRUE')
36
+ pathlen = $2.to_i
37
+ when 'keyUsage'
38
+ usage = ex.value.split(/\s*,\s*/)
39
+ # a CA must have
40
+ ca &&= !usage.grep(/Certificate Sign/i).empty?
41
+ # Server Cert Must have
42
+ server_auth &&= !usage.grep(/Key Encipherment/i).empty?
43
+ when 'extendedKeyUsage'
44
+ usage = ex.value.split(/\s*,\s*/)
45
+ # Server Cert Must have
46
+ server_auth &&= !usage.grep(/TLS Web Server Authentication/i).empty?
47
+ when 'nsCertType'
48
+ usage = ex.value.split(/\s*,\s*/)
49
+ ca ||= !usage.grep(/SSL CA/i).empty?
50
+ server_auth ||= !usage.grep(/SSL Server/i).empty?
51
+ end
52
+ end
53
+
54
+ # We're looking for the server cert, so accept all CAs (which have already passed pre-verification)
55
+ return true if self_signed || ca
56
+
57
+ # ensure the server cert is the one we're expecting
58
+ return server_auth && self.server_cert == cert.to_pem
59
+ end
60
+ private :validate_certificate
61
+
62
+ end
63
+ end
@@ -37,6 +37,8 @@ module EWS # :nodoc:
37
37
  # :tagged_void
38
38
  # :tagged_refund
39
39
  # :tagged_online_debit_refund
40
+ # :tagged_update
41
+ # :referenced_void
40
42
  # :recurring_seed_pre_auth
41
43
  # :recurring_seed_purchase
42
44
  # :idebit_purchase
@@ -113,6 +115,8 @@ METHOD_EOS
113
115
  :tagged_void => '33',
114
116
  :tagged_refund => '34',
115
117
  :tagged_online_debit_refund => '35',
118
+ :referenced_void => '36',
119
+ :tagged_update => '37',
116
120
  :recurring_seed_pre_auth => '40',
117
121
  :recurring_seed_purchase => '41',
118
122
  :idebit_purchase => '50',
@@ -40,6 +40,8 @@ module EWS # :nodoc:
40
40
 
41
41
  if self.transaction_type == "CR"
42
42
  append_error(:transaction_tag, "transaction_tag must be supplied") if self.transaction_tag.to_i < 1
43
+ elsif self.transaction_type == "36"
44
+ validate_referenced_void
43
45
  elsif %w(80 81).include?(self.transaction_type)
44
46
  # do nothing, no validation required
45
47
  elsif %w(50 54).include?(self.transaction_type)
@@ -166,12 +168,13 @@ module EWS # :nodoc:
166
168
  def validate_for_transaction_tag
167
169
  tt = self.transaction_type
168
170
 
169
- # mandatory: transaction_type must == (30, 31, 32, 33, 34, 35)
170
- append_error(:transaction_tag, "transaction_tag must only be set for tagged transactions") unless %w(30 31 32 33 34 35 CR).include?(tt)
171
+ # mandatory: transaction_type must == (30, 31, 32, 33, 34, 35, 37, CR)
172
+ append_error(:transaction_tag, "transaction_tag must only be set for tagged transactions") unless %w(30 31 32 33 34 35 37 CR).include?(tt)
171
173
 
172
174
  # transaction_tag, auth_num & amount mandatory
173
175
  mandatory = [:transaction_tag]
174
- mandatory << [:authorization_num, :amount] unless tt == 'CR'
176
+ mandatory << :authorization_num unless tt == 'CR'
177
+ mandatory << :amount unless %w(CR 37).include?(tt)
175
178
 
176
179
  # ensure no cc details sent
177
180
  append_error(:cc_number, "do not set cc_number for tagged transactions") unless self.cc_number.blank?
@@ -227,6 +230,15 @@ module EWS # :nodoc:
227
230
  check_mandatory(mandatory)
228
231
  end
229
232
 
233
+ def validate_referenced_void
234
+ [:cc_number, :pan, :track1, :track2, :transaction_tag].each do |attr_name|
235
+ append_error(attr_name, "#{attr_name} must not be set for referenced_void transactions") unless self.send(attr_name).nil?
236
+ end
237
+
238
+ check_mandatory([:reference_no, :customer_ref, :amount])
239
+ end
240
+
241
+
230
242
  def check_mandatory(mandatory)
231
243
  mandatory.each do |key|
232
244
  append_error(key, "#{key} must be supplied") if self.send(key).blank?
@@ -1,4 +1,5 @@
1
1
  require 'net/https'
2
+ require File.dirname(__FILE__) + '/certificate_helper'
2
3
 
3
4
  module EWS # :nodoc:
4
5
 
@@ -15,6 +16,7 @@ module EWS # :nodoc:
15
16
  # Once configured to connect to a particular service, it can be used repeatedly
16
17
  # to send as many transactions as required.
17
18
  class Transporter
19
+ include CertificateHelper
18
20
 
19
21
  # Initialize a Transporter.
20
22
  #
@@ -23,6 +25,8 @@ module EWS # :nodoc:
23
25
  #
24
26
  # You can also specify a hash of options as follows:
25
27
  # :transport_type the transport_type for this transporter (defaults to :rest)
28
+ # :server_cert the path to the server's certificate file (defaults to E-xact's Server Cert)
29
+ # :issuer_cert the path to the issuer's certificate file (defaults to E-xact's Issuer's Cert)
26
30
  #
27
31
  # The default certificates are those required to connect to https://api.e-xact.com and the
28
32
  # default <tt>transport_type</tt> is <tt>:rest</tt>. The default <tt>transport_type</tt> can be overridden on a per-transaction
@@ -31,8 +35,7 @@ module EWS # :nodoc:
31
35
  @url = URI.parse(url.gsub(/\/$/,''))
32
36
  @transport_type = options[:transport_type] || :rest
33
37
 
34
- @@issuer_cert ||= File.dirname(__FILE__)+"/../../certs/valicert_class2_root.crt"
35
- @@server_cert ||= File.new(File.dirname(__FILE__)+"/../../certs/e-xact.com.crt").read
38
+ configure_certificates(options)
36
39
  end
37
40
 
38
41
  # Submit a transaction request to the server
@@ -52,7 +55,7 @@ module EWS # :nodoc:
52
55
  request = build_http_request(transaction, transport_type, transport_details[:suffix])
53
56
  request.basic_auth(transaction.gateway_id, transaction.password)
54
57
  request.add_field "Accept", transport_details[:content_type]
55
- request.add_field "User-Agent", "exact4r v1.2"
58
+ request.add_field "User-Agent", "exact4r v1.4"
56
59
  request.add_field "Content-type", "#{transport_details[:content_type]}; charset=UTF-8"
57
60
 
58
61
  response = get_connection.request(request)
@@ -106,56 +109,11 @@ private
106
109
  @connection.use_ssl = true
107
110
  @connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
108
111
  @connection.verify_callback = method(:validate_certificate)
109
- @connection.ca_file = @@issuer_cert
112
+ @connection.ca_file = self.issuer_cert_file
110
113
  end
111
114
  @connection
112
115
  end
113
116
 
114
- def validate_certificate(is_ok, ctx)
115
- cert = ctx.current_cert
116
- return false if cert.nil?
117
-
118
- # preverify failed?
119
- return false unless is_ok
120
-
121
- self_signed = false
122
- ca = false
123
- pathlen = nil
124
- server_auth = true
125
- self_signed = (cert.subject.cmp(cert.issuer) == 0)
126
-
127
- # Check extensions for the certificate purpose according to http://www.openssl.org/docs/apps/x509.html (Certificate Extensions) and
128
- # http://www.ietf.org/rfc/rfc3280.txt.
129
- cert.extensions.each do |ex|
130
- case ex.oid
131
- when 'basicConstraints'
132
- /CA:(TRUE|FALSE)(?:, pathlen:)*(\d*)/ =~ ex.value
133
- ca ||= ($1 == 'TRUE')
134
- pathlen = $2.to_i
135
- when 'keyUsage'
136
- usage = ex.value.split(/\s*,\s*/)
137
- # a CA must have
138
- ca &&= !usage.grep(/Certificate Sign/i).empty?
139
- # Server Cert Must have
140
- server_auth &&= !usage.grep(/Key Encipherment/i).empty?
141
- when 'extendedKeyUsage'
142
- usage = ex.value.split(/\s*,\s*/)
143
- # Server Cert Must have
144
- server_auth &&= !usage.grep(/TLS Web Server Authentication/i).empty?
145
- when 'nsCertType'
146
- usage = ex.value.split(/\s*,\s*/)
147
- ca ||= !usage.grep(/SSL CA/i).empty?
148
- server_auth ||= !usage.grep(/SSL Server/i).empty?
149
- end
150
- end
151
-
152
- # We're looking for the server cert, so accept all CAs (which have already passed pre-verification)
153
- return true if self_signed || ca
154
-
155
- # ensure the server cert is the one we're expecting
156
- return server_auth && @@server_cert == cert.to_pem
157
- end
158
-
159
117
  # what transport types we support, and their corresponding suffixes
160
118
  @@transport_types = {
161
119
  :rest => {:suffix => "xml", :content_type => "application/xml"},
Binary file
data/test/credentials.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  DEV:
2
- location: http://ws.local/
2
+ location: http://localhost:3000/
3
3
  tsys:
4
4
  :gateway_id: AD0156-01
5
5
  :password: 4apitest
@@ -16,6 +16,24 @@ DEV:
16
16
  :gateway_id: AD0158-01
17
17
  :password: 4apitest
18
18
 
19
+ QA:
20
+ location: https://api.qa.e-xact.com/
21
+ tsys:
22
+ :gateway_id: A04766-01
23
+ :password: 4apitest
24
+ emergis:
25
+ :gateway_id: A04763-01
26
+ :password: 4apitest
27
+ moneris:
28
+ :gateway_id: A04760-01
29
+ :password: 4apitest
30
+ chase:
31
+ :gateway_id: A04757-02
32
+ :password: 4apitest
33
+ chase_batch:
34
+ :gateway_id: A04757-01
35
+ :password: 4apitest
36
+
19
37
  PROD:
20
38
  location: https://api.e-xact.com/
21
39
  tsys:
@@ -39,7 +39,9 @@ class ForcedPostTest < Test::Unit::TestCase
39
39
  assert request.valid?
40
40
  end
41
41
 
42
- def test_by_credit_card
42
+ def test_by_credit_card
43
+ return if @@credentials.chase? || @@credentials.moneris?
44
+
43
45
  request = EWS::Transaction::Request.new(cc_number_params.merge(:transaction_type => :forced_post))
44
46
  request.amount = 11.25
45
47
  request.authorization_num = "1234"
@@ -51,6 +53,8 @@ class ForcedPostTest < Test::Unit::TestCase
51
53
  end
52
54
 
53
55
  def test_by_track1
56
+ return if @@credentials.chase? || @@credentials.moneris?
57
+
54
58
  request = EWS::Transaction::Request.new(track1_params.merge(:transaction_type => :forced_post))
55
59
  request.amount = 11.25
56
60
  request.authorization_num = "1234"
@@ -62,6 +66,8 @@ class ForcedPostTest < Test::Unit::TestCase
62
66
  end
63
67
 
64
68
  def test_by_track2
69
+ return if @@credentials.chase? || @@credentials.moneris?
70
+
65
71
  request = EWS::Transaction::Request.new(track2_params.merge(:transaction_type => :forced_post))
66
72
  request.amount = 11.25
67
73
  request.authorization_num = "1234"
@@ -0,0 +1,131 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+
3
+ #
4
+ # A ReferencedVoid behaves the same as a TaggedVoid, except, instead of using transaction_tag,
5
+ # authorization_num and amount to lookup the transaction to be voided, you use reference_no,
6
+ # customer_ref and amount.
7
+ #
8
+ class ReferencedVoidTest < Test::Unit::TestCase
9
+
10
+ def setup
11
+ @transporter = EWS::Transporter.new(@@credentials.config['location'])
12
+
13
+ # do initial purchase
14
+ request = EWS::Transaction::Request.new(cc_number_params.merge({
15
+ :transaction_type => :purchase,
16
+ :amount => 11.25,
17
+ :reference_no => "reference_no_#{rand(10)}",
18
+ :customer_ref => "customer_ref_#{rand(10)}"
19
+ }))
20
+ assert request.valid?, request.errors.inspect
21
+
22
+ @purchase = @transporter.submit(request, :json)
23
+ assert @purchase.approved?
24
+ end
25
+
26
+ def test_mandatory
27
+ request = EWS::Transaction::Request.new(:transaction_type => :referenced_void)
28
+ assert !request.valid?
29
+ assert_equal "gateway_id must be supplied", request.errors[:gateway_id]
30
+
31
+ request.gateway_id = @@credentials.current_gateway[:gateway_id]
32
+ assert !request.valid?
33
+ assert_equal "password must be supplied", request.errors[:password]
34
+
35
+ request.password = @@credentials.current_gateway[:password]
36
+ assert !request.valid?
37
+ assert_equal "reference_no must be supplied", request.errors[:reference_no]
38
+
39
+ request.reference_no = "something"
40
+ assert !request.valid?
41
+ assert_equal "customer_ref must be supplied", request.errors[:customer_ref]
42
+
43
+ request.customer_ref = "something"
44
+ assert !request.valid?
45
+ assert_equal "amount must be supplied", request.errors[:amount]
46
+
47
+ request.amount = 11.25
48
+ assert request.valid?
49
+
50
+ # don't set any CC information
51
+ [:cc_number, :pan, :track1, :track2, :transaction_tag].each do |attr_name|
52
+ request.send("#{attr_name}=", "something")
53
+ assert !request.valid?
54
+ assert_equal "#{attr_name} must not be set for referenced_void transactions", request.errors[attr_name]
55
+ request.send("#{attr_name}=", nil)
56
+ end
57
+ end
58
+
59
+ def test_json
60
+ request = EWS::Transaction::Request.new({
61
+ :transaction_type => :referenced_void,
62
+ :amount => 11.25,
63
+ :reference_no => @purchase.reference_no,
64
+ :customer_ref => @purchase.customer_ref
65
+ }.merge(@@credentials.current_gateway))
66
+ assert request.valid?, request.errors.inspect
67
+
68
+ assert_details_correct request, @transporter.submit(request, :json)
69
+ end
70
+
71
+ def test_rest
72
+ request = EWS::Transaction::Request.new({
73
+ :transaction_type => :referenced_void,
74
+ :amount => 11.25,
75
+ :reference_no => @purchase.reference_no,
76
+ :customer_ref => @purchase.customer_ref
77
+ }.merge(@@credentials.current_gateway))
78
+ assert request.valid?, request.errors.inspect
79
+
80
+ assert_details_correct request, @transporter.submit(request, :rest)
81
+ end
82
+
83
+ def test_soap
84
+ request = EWS::Transaction::Request.new({
85
+ :transaction_type => :referenced_void,
86
+ :amount => 11.25,
87
+ :reference_no => @purchase.reference_no,
88
+ :customer_ref => @purchase.customer_ref
89
+ }.merge(@@credentials.current_gateway))
90
+ assert request.valid?, request.errors.inspect
91
+
92
+ assert_details_correct request, @transporter.submit(request, :soap)
93
+ end
94
+
95
+ def test_requires_correct_amount
96
+ request = EWS::Transaction::Request.new({
97
+ :transaction_type => :referenced_void,
98
+ :amount => 3.50,
99
+ :reference_no => @purchase.reference_no,
100
+ :customer_ref => @purchase.customer_ref
101
+ }.merge(@@credentials.current_gateway))
102
+ assert request.valid?, request.errors.inspect
103
+
104
+ response = @transporter.submit(request, :json)
105
+ assert !response.approved?
106
+
107
+ request.amount = 13.50
108
+ response = @transporter.submit(request, :rest)
109
+ assert !response.approved?
110
+
111
+ request.amount = 11.25
112
+ assert_details_correct request, @transporter.submit(request, :soap)
113
+ end
114
+
115
+ def test_multiple_voids_against_one_transaction
116
+ request = EWS::Transaction::Request.new({
117
+ :transaction_type => :referenced_void,
118
+ :amount => 11.25,
119
+ :reference_no => @purchase.reference_no,
120
+ :customer_ref => @purchase.customer_ref
121
+ }.merge(@@credentials.current_gateway))
122
+ assert request.valid?, request.errors.inspect
123
+
124
+ assert_details_correct request, @transporter.submit(request, :json)
125
+
126
+ # can't void an already-voided transaction
127
+ response = @transporter.submit(request, :json)
128
+ assert !response.approved?
129
+ end
130
+
131
+ end
@@ -43,7 +43,7 @@ class RefundCorrectionTest < Test::Unit::TestCase
43
43
  assert request.valid?
44
44
  end
45
45
 
46
- def test_by_credit_card
46
+ def test_by_credit_card
47
47
  return unless @@credentials.moneris?
48
48
 
49
49
  request = EWS::Transaction::Request.new(cc_number_params.merge(:transaction_type => :refund_correction).merge(@@credentials.current_gateway))
@@ -0,0 +1,158 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+
3
+ #
4
+ # A TaggedUpdate request allows a merchant to edit the reference_no and customer_ref values of a
5
+ # previous transaction. Please note that this is NOT a financial transaction, it merely allows
6
+ # you to change the values stored in our DB for a given transaction.
7
+ #
8
+ # In common with all other tagged transactions, you supply the transaction_tag and authorization_num
9
+ # for the transaction whose values you wish to change, along with the new values for reference_no
10
+ # and/or customer_ref.
11
+ #
12
+ # NOTE: nil, empty string ("") or whitespace string (" ") are not permitted, and, although the
13
+ # request will be approved, the relevant attribute WILL NOT CHANGE.
14
+ #
15
+ class TaggedUpdateTest < Test::Unit::TestCase
16
+
17
+ def setup
18
+ @transporter = EWS::Transporter.new(@@credentials.config['location'])
19
+
20
+ # do initial purchase request
21
+ request = EWS::Transaction::Request.new(cc_number_params.merge(:transaction_type => :purchase))
22
+ request.amount = 11.25
23
+ request.reference_no = "reference_no"
24
+ request.customer_ref = "customer_ref"
25
+ assert request.valid?, request.errors.inspect
26
+
27
+ @purchase = @transporter.submit(request, :json)
28
+ assert @purchase.approved?, @purchase.to_yaml
29
+ end
30
+
31
+ def test_mandatory
32
+ request = EWS::Transaction::Request.new(:transaction_type => :tagged_update)
33
+ assert !request.valid?
34
+ assert_equal "gateway_id must be supplied", request.errors[:gateway_id]
35
+
36
+ request.gateway_id = @@credentials.current_gateway[:gateway_id]
37
+ assert !request.valid?
38
+ assert_equal "password must be supplied", request.errors[:password]
39
+
40
+ request.password = @@credentials.current_gateway[:password]
41
+ assert !request.valid?
42
+ assert_equal "One of the following must be supplied: cc_number, track1, track2 or transaction_tag.", request.errors[:base]
43
+
44
+ request.transaction_tag = 1234
45
+ assert !request.valid?
46
+ assert_equal "authorization_num must be supplied", request.errors[:authorization_num]
47
+
48
+ request.authorization_num = "TH6754"
49
+ assert request.valid?, request.errors.inspect
50
+
51
+ request.cc_number = "4111111111111111"
52
+ assert !request.valid?
53
+ assert_equal "do not set cc_number for tagged transactions", request.errors[:cc_number]
54
+ end
55
+
56
+ def test_json
57
+ request = tagged_update_request(@purchase)
58
+ assert request.valid?, request.errors.inspect
59
+
60
+ response = @transporter.submit(request, :json)
61
+ assert response.approved?
62
+
63
+ # we're getting the details of the original transction returned
64
+ assert_equal @purchase.transaction_tag, response.transaction_tag
65
+ assert_equal "something_new", response.reference_no
66
+ assert_equal "something_old", response.customer_ref
67
+ end
68
+
69
+ def test_rest
70
+ request = tagged_update_request(@purchase)
71
+ assert request.valid?, request.errors.inspect
72
+
73
+ response = @transporter.submit(request, :rest)
74
+
75
+ # we're getting the details of the original transction returned
76
+ assert_equal @purchase.transaction_tag, response.transaction_tag
77
+ assert_equal "something_new", response.reference_no
78
+ assert_equal "something_old", response.customer_ref
79
+ end
80
+
81
+ def test_soap
82
+ request = tagged_update_request(@purchase)
83
+ assert request.valid?, request.errors.inspect
84
+
85
+ response = @transporter.submit(request, :soap)
86
+
87
+ # we're getting the details of the original transction returned
88
+ assert_equal @purchase.transaction_tag, response.transaction_tag
89
+ assert_equal "something_new", response.reference_no
90
+ assert_equal "something_old", response.customer_ref
91
+ end
92
+
93
+ def test_multiple_updates
94
+ request1 = tagged_update_request(@purchase)
95
+ assert request1.valid?, request1.errors.inspect
96
+
97
+ response1 = @transporter.submit(request1, :soap)
98
+ assert_equal "something_new", response1.reference_no
99
+ assert_equal "something_old", response1.customer_ref
100
+
101
+ request2 = tagged_update_request(@purchase, {
102
+ :reference_no => "bananas",
103
+ :customer_ref => "oranges"
104
+ })
105
+ assert request2.valid?, request2.errors.inspect
106
+
107
+ response2 = @transporter.submit(request2, :soap)
108
+ assert_equal "bananas", response2.reference_no
109
+ assert_equal "oranges", response2.customer_ref
110
+ end
111
+
112
+ def test_updating_single_attribute
113
+ # change only reference_no
114
+ request1 = tagged_update_request(@purchase, {:customer_ref => nil})
115
+ assert request1.valid?, request1.errors.inspect
116
+
117
+ response1 = @transporter.submit(request1, :soap)
118
+ assert_equal "something_new", response1.reference_no
119
+ assert_equal "customer_ref", response1.customer_ref
120
+
121
+ # change only customer_ref
122
+ request2 = tagged_update_request(@purchase, {:reference_no => nil})
123
+ assert request2.valid?, request2.errors.inspect
124
+
125
+ response2 = @transporter.submit(request2, :soap)
126
+ assert_equal "something_new", response2.reference_no
127
+ assert_equal "something_old", response2.customer_ref
128
+ end
129
+
130
+ def test_empty_strings_ignored
131
+ request1 = tagged_update_request(@purchase, {:customer_ref => ""})
132
+ assert request1.valid?, request1.errors.inspect
133
+
134
+ response1 = @transporter.submit(request1, :soap)
135
+ assert_equal "something_new", response1.reference_no
136
+ assert_equal "customer_ref", response1.customer_ref
137
+ end
138
+
139
+ def test_whitepaces_strings_ignored
140
+ request1 = tagged_update_request(@purchase, {:customer_ref => " "})
141
+ assert request1.valid?, request1.errors.inspect
142
+
143
+ response1 = @transporter.submit(request1, :soap)
144
+ assert_equal "something_new", response1.reference_no
145
+ assert_equal "customer_ref", response1.customer_ref
146
+ end
147
+
148
+ def tagged_update_request(original_txn, options = {})
149
+ EWS::Transaction::Request.new({
150
+ :transaction_type => :tagged_update,
151
+ :transaction_tag => original_txn.transaction_tag,
152
+ :authorization_num => original_txn.authorization_num,
153
+ :reference_no => "something_new",
154
+ :customer_ref => "something_old"
155
+ }.merge(options).merge(@@credentials.current_gateway))
156
+ end
157
+ private :tagged_update_request
158
+ end
@@ -70,18 +70,19 @@ class TransactionDetailsTest < Test::Unit::TestCase
70
70
  end
71
71
 
72
72
  def assert_details_match_original_response(original_response, details_response)
73
+ # exclude: client_ip, pan
73
74
  [:logon_message, :error_number, :error_description, :transaction_error, :transaction_approved, :exact_resp_code, :exact_message,
74
75
  :bank_resp_code, :bank_message, :bank_resp_code_2, :sequence_no, :avs, :cvv2, :retrieval_ref_no, :cavv_response, :merchant_name,
75
76
  :merchant_address, :merchant_city, :merchant_province, :merchant_country, :merchant_postal, :merchant_url, :gateway_id, :password,
76
- :transaction_type, :amount, :surcharge_amount, :cc_number, :transaction_tag, :track1, :track2, :pan, :authorization_num, :cc_expiry,
77
+ :transaction_type, :amount, :surcharge_amount, :cc_number, :transaction_tag, :track1, :track2, :authorization_num, :cc_expiry,
77
78
  :cardholder_name, :cc_verification_str1, :cc_verification_str2, :cvd_presence_ind, :tax1_amount, :tax1_number, :tax2_amount,
78
79
  :tax2_number, :secure_auth_required, :secure_auth_result, :ecommerce_flag, :xid, :cavv, :cavv_algorithm, :reference_no, :customer_ref,
79
- :reference_3, :language, :client_ip, :client_email, :user_name, :zip_code].each do |attr_name|
80
+ :reference_3, :language, :client_email, :user_name, :zip_code].each do |attr_name|
81
+ next if attr_name == :cc_expiry && %(35 50 54).include?(original_response.transaction_type)
82
+
80
83
  o_value = original_response.send(attr_name).to_s
81
84
  d_value = details_response.send(attr_name).to_s
82
- unless o_value == d_value
83
- puts "#{attr_name}: #{o_value} / #{d_value}"
84
- end
85
+ assert_equal o_value, d_value, "#{attr_name}: #{o_value} / #{d_value}"
85
86
  end
86
87
  end
87
88
  private :assert_details_match_original_response
@@ -40,42 +40,79 @@ class VoidTest < Test::Unit::TestCase
40
40
  end
41
41
 
42
42
  def test_by_credit_card
43
- return if @@credentials.chase? || @@credentials.moneris?
44
-
43
+ return if @@credentials.moneris?
44
+
45
+ response = send_purchase(cc_number_params)
46
+
45
47
  request = EWS::Transaction::Request.new(cc_number_params.merge(:transaction_type => :void))
46
48
  request.amount = 11.25
47
- request.authorization_num = "1234"
49
+ request.authorization_num = response.authorization_num
48
50
  assert request.valid?, request.errors.inspect
49
51
 
50
52
  assert_details_correct request, @transporter.submit(request, :json)
53
+
54
+ response = send_purchase(cc_number_params)
55
+ request.authorization_num = response.authorization_num
56
+
51
57
  assert_details_correct request, @transporter.submit(request, :rest)
58
+
59
+ response = send_purchase(cc_number_params)
60
+ request.authorization_num = response.authorization_num
61
+
52
62
  assert_details_correct request, @transporter.submit(request, :soap)
53
63
  end
54
64
 
55
65
  def test_by_track1
56
- return if @@credentials.chase? || @@credentials.moneris?
66
+ return if @@credentials.moneris?
57
67
 
68
+ response = send_purchase(track1_params)
69
+
58
70
  request = EWS::Transaction::Request.new(track1_params.merge(:transaction_type => :void))
59
71
  request.amount = 11.25
60
- request.authorization_num = "1234"
72
+ request.authorization_num = response.authorization_num
61
73
  assert request.valid?, request.errors.inspect
62
74
 
63
75
  assert_details_correct request, @transporter.submit(request, :json)
76
+
77
+ response = send_purchase(track1_params)
78
+ request.authorization_num = response.authorization_num
79
+
64
80
  assert_details_correct request, @transporter.submit(request, :rest)
81
+
82
+ response = send_purchase(track1_params)
83
+ request.authorization_num = response.authorization_num
84
+
65
85
  assert_details_correct request, @transporter.submit(request, :soap)
66
86
  end
67
87
 
68
88
  def test_by_track2
69
- return if @@credentials.chase? || @@credentials.moneris?
89
+ return if @@credentials.moneris?
70
90
 
91
+ response = send_purchase(track2_params)
92
+
71
93
  request = EWS::Transaction::Request.new(track2_params.merge(:transaction_type => :void))
72
94
  request.amount = 11.25
73
- request.authorization_num = "1234"
95
+ request.authorization_num = response.authorization_num
74
96
  assert request.valid?, request.errors.inspect
75
97
 
76
98
  assert_details_correct request, @transporter.submit(request, :json)
99
+
100
+ response = send_purchase(track2_params)
101
+ request.authorization_num = response.authorization_num
102
+
77
103
  assert_details_correct request, @transporter.submit(request, :rest)
104
+
105
+ response = send_purchase(track2_params)
106
+ request.authorization_num = response.authorization_num
107
+
78
108
  assert_details_correct request, @transporter.submit(request, :soap)
79
109
  end
80
110
 
111
+ def send_purchase(params)
112
+ request = EWS::Transaction::Request.new(params.merge(:transaction_type => :purchase, :amount => 11.25))
113
+ assert request.valid?, request.errors.inspect
114
+ response = @transporter.submit(request, :json)
115
+ assert response.approved?
116
+ response
117
+ end
81
118
  end
@@ -48,7 +48,27 @@ class TransporterTest < Test::Unit::TestCase
48
48
 
49
49
  assert_not_nil resp
50
50
  assert_equal 404, resp.error_number
51
- assert_equal "Not Found", resp.error_description
51
+ assert_equal "Not Found", resp.error_description.strip
52
+ end
53
+
54
+ def test_uses_supplied_certificates
55
+ req = ::EWS::Transaction::Request.new({
56
+ :transaction_type => :purchase,
57
+ :amount => "10.13",
58
+ :cardholder_name => "Simon Brown",
59
+ :cc_number => "4111111111111111",
60
+ :cc_expiry => "1012",
61
+ :reference_no => "987987",
62
+ }.merge(@@credentials.current_gateway))
63
+
64
+ tr = ::EWS::Transporter.new(@@credentials.config['location'], {
65
+ :issuer_cert => File.dirname(__FILE__)+"/../../certs/valicert_class2_root.crt",
66
+ :server_cert => File.dirname(__FILE__)+"/../../certs/e-xact.com.crt"
67
+ })
68
+ resp = tr.submit(req, :json)
69
+
70
+ assert_not_nil resp
71
+ assert resp.approved?
52
72
  end
53
73
 
54
74
  end
data/test/test_helper.rb CHANGED
@@ -38,7 +38,7 @@ end
38
38
 
39
39
  def assert_details_correct(request, response)
40
40
  assert_not_nil response, "response should not be nil"
41
- assert response.approved?, "#{response.error_number} / #{response.error_description} / #{response.exact_message} / #{response.bank_message}"
41
+ assert response.approved?, "#{response.error_number} / #{response.error_description} / #{response.exact_resp_code} / #{response.exact_message} / #{response.bank_message}"
42
42
 
43
43
  assert_not_nil response.transaction_tag
44
44
  assert_not_nil response.authorization_num
@@ -49,9 +49,11 @@ def assert_details_correct(request, response)
49
49
  end
50
50
 
51
51
  def assert_card_details(response)
52
- assert_match /............1111/, response.cc_number
53
- assert_equal TEST_CARD_HOLDER, response.cardholder_name
54
- assert_equal TEST_CARD_EXPIRY, response.cc_expiry unless %w(35 50 54).include?(response.transaction_type)
52
+ unless %w(35 50 54).include?(response.transaction_type)
53
+ assert_match /............1111/, response.cc_number
54
+ assert_equal TEST_CARD_HOLDER, response.cardholder_name
55
+ assert_equal TEST_CARD_EXPIRY, response.cc_expiry
56
+ end
55
57
  end
56
58
 
57
59
  def basic_params(options = {})
metadata CHANGED
@@ -1,7 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exact4r
3
3
  version: !ruby/object:Gem::Version
4
- version: "1.2"
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 4
8
+ version: "1.4"
5
9
  platform: ruby
6
10
  authors:
7
11
  - E-xact Transactions Ltd.
@@ -9,29 +13,37 @@ autorequire:
9
13
  bindir: bin
10
14
  cert_chain: []
11
15
 
12
- date: 2010-03-11 00:00:00 +11:00
16
+ date: 2010-07-09 00:00:00 +10:00
13
17
  default_executable:
14
18
  dependencies:
15
19
  - !ruby/object:Gem::Dependency
16
20
  name: activesupport
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
20
23
  requirements:
21
24
  - - ">="
22
25
  - !ruby/object:Gem::Version
26
+ segments:
27
+ - 2
28
+ - 0
29
+ - 2
23
30
  version: 2.0.2
24
- version:
31
+ type: :runtime
32
+ version_requirements: *id001
25
33
  - !ruby/object:Gem::Dependency
26
34
  name: builder
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
30
37
  requirements:
31
38
  - - ">="
32
39
  - !ruby/object:Gem::Version
40
+ segments:
41
+ - 2
42
+ - 1
43
+ - 2
33
44
  version: 2.1.2
34
- version:
45
+ type: :runtime
46
+ version_requirements: *id002
35
47
  description:
36
48
  email: dredmond@e-xact.com
37
49
  executables: []
@@ -49,6 +61,7 @@ files:
49
61
  - ./certs/exact.cer
50
62
  - ./certs/valicert_class2_root.crt
51
63
  - ./CHANGELOG
64
+ - ./lib/ews/certificate_helper.rb
52
65
  - ./lib/ews/transaction/fake_response.rb
53
66
  - ./lib/ews/transaction/mapping.rb
54
67
  - ./lib/ews/transaction/request.rb
@@ -58,6 +71,7 @@ files:
58
71
  - ./lib/ews/transporter.rb
59
72
  - ./lib/exact4r.rb
60
73
  - ./LICENCE
74
+ - ./pkg/exact4r-1.2.gem
61
75
  - ./Rakefile
62
76
  - ./README
63
77
  - ./test/credentials.rb
@@ -73,6 +87,7 @@ files:
73
87
  - ./test/exhaustive/purchase_test.rb
74
88
  - ./test/exhaustive/recurring_seed_pre_auth_test.rb
75
89
  - ./test/exhaustive/recurring_seed_purchase_test.rb
90
+ - ./test/exhaustive/referenced_void_test.rb
76
91
  - ./test/exhaustive/refund_correction_test.rb
77
92
  - ./test/exhaustive/refund_test.rb
78
93
  - ./test/exhaustive/secure_storage_test.rb
@@ -81,6 +96,7 @@ files:
81
96
  - ./test/exhaustive/tagged_pre_auth_test.rb
82
97
  - ./test/exhaustive/tagged_purchase_test.rb
83
98
  - ./test/exhaustive/tagged_refund_test.rb
99
+ - ./test/exhaustive/tagged_update_test.rb
84
100
  - ./test/exhaustive/tagged_void_test.rb
85
101
  - ./test/exhaustive/transaction_details_test.rb
86
102
  - ./test/exhaustive/void_test.rb
@@ -122,18 +138,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
138
  requirements:
123
139
  - - ">="
124
140
  - !ruby/object:Gem::Version
141
+ segments:
142
+ - 0
125
143
  version: "0"
126
- version:
127
144
  required_rubygems_version: !ruby/object:Gem::Requirement
128
145
  requirements:
129
146
  - - ">="
130
147
  - !ruby/object:Gem::Version
148
+ segments:
149
+ - 0
131
150
  version: "0"
132
- version:
133
151
  requirements: []
134
152
 
135
153
  rubyforge_project: exact4r
136
- rubygems_version: 1.3.5
154
+ rubygems_version: 1.3.6
137
155
  signing_key:
138
156
  specification_version: 3
139
157
  summary: E-xact Web Services Client Library.