exact4r 0.6 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ == v0.7
2
+ Updated with latest certificates for api.e-xact.com
3
+ Fixed SOAP namespace issue
4
+ Ensured expiry_date always submitted at MMYY
5
+
1
6
  == v0.6
2
7
  Added client-side request validation
3
8
 
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'spec/rake/spectask'
2
2
  require 'rake/rdoctask'
3
3
  require "rubygems"
4
- Gem::manage_gems
4
+ # Gem::manage_gems
5
5
  require "rake/gempackagetask"
6
6
 
7
7
  task :default => :spec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6
1
+ 0.7
data/certs/exact.cer CHANGED
@@ -1,18 +1,18 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- MIIC7DCCAlWgAwIBAgIDCFDUMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
2
+ MIIC7DCCAlWgAwIBAgIDCqSQMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
3
3
  MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
4
- aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMTE1MDA0MDAyWhcNMDkwMjE0MDA0MDAy
4
+ aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkwMjEzMDAxMDQ2WhcNMTAwMzE1MjMxMDQ2
5
5
  WjB3MQswCQYDVQQGEwJDQTEZMBcGA1UECBMQQnJpdGlzaCBDb2x1bWJpYTESMBAG
6
6
  A1UEBxMJVmFuY291dmVyMSIwIAYDVQQKExlFLXhhY3QgVHJhbnNhY3Rpb25zLCBM
7
7
  dGQuMRUwEwYDVQQDFAwqLmUteGFjdC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A
8
- MIGJAoGBAKDWJW7DQ9EAkYE0j8QKZtGyRPx84NHaMLA9uJsqG9EMPfNCRd8Puafx
9
- dJ6phUS/gP/ELRmJLlKO7qg6hTfLB3UwvAoMfF8VZM8jNbd3/b+SQD6CiPX0vETH
10
- 85qIegdNrRQNm0ZKhq10bQlzKyoOrk0MDzDd6a98NyrLhVvb1nDlAgMBAAGjga4w
11
- gaswDgYDVR0PAQH/BAQDAgTwMB0GA1UdDgQWBBTsLqYhwlm0BeEOq0Mhl6P5lxWP
12
- cTA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxz
8
+ MIGJAoGBAKAEtyoEOQMqbYNTo/XGXx68vElKFb3lhQ9qimRlggadSCA3F1P40dMz
9
+ 3PlXDtKN9TcvqYalvmrntjmtY7/QgBu59AJOIoFDXe/XCtW16XAlANIrTvS9zhHd
10
+ nnLhCHcLAhEJIssWb3ddXiK8NDIyHtIbWYRIdzT0aPOLtoUXfcBLAgMBAAGjga4w
11
+ gaswDgYDVR0PAQH/BAQDAgTwMB0GA1UdDgQWBBSTkCQC1iSGLxD/+kL5elS75kLe
12
+ hDA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxz
13
13
  L3NlY3VyZWNhLmNybDAfBgNVHSMEGDAWgBRI5mj5K9KylddH2CMgEE8zmJCf1DAd
14
14
  BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEA
15
- X5PCTOTdEnxbG3qcrpgiwnh3ax0Orgy8VUEv3q08GlTu8b+p96/p9e4pWFnZ1FtH
16
- F8B9PGPeDGZDu0+d3HcMuPBgdl/qyVPI7BIfED7V/PXLj92QQP5VI49R9DI1dj+O
17
- bWaptb3x1gcxEP7ifBLl4fg080RlxAJmFrHTF2h9TQ4=
15
+ iHFOvsHR2SZ93jry4TaDWXXVN3gBuK9S7j4ubcGbT4HZe/1OJXE8Hpdc6lFaBgdi
16
+ ZK2qHFzZ7suhcOiF6f7HCtDDXdoGAhYJVWGvhd/2CsvaRzdVWkUQzfRgDXKoYU9W
17
+ BEQs/Y5lG23rmq4WJe6HSVN0FMaZS3aVIr54821hKPc=
18
18
  -----END CERTIFICATE-----
@@ -1,5 +1,4 @@
1
1
  require 'builder'
2
- require 'activesupport'
3
2
 
4
3
  module EWS # :nodoc:
5
4
  module Transaction # :nodoc:
@@ -105,7 +104,7 @@ module EWS # :nodoc:
105
104
 
106
105
  def self.json_to_response(content)
107
106
  response = EWS::Transaction::Response.new
108
- ActiveSupport::JSON.decode(content).each { |k,v| response.send "#{k}=", v if response.respond_to?(k) }
107
+ ActiveSupport::JSON.decode(content).each { |k,v| response.send "#{k}=", v if response.respond_to?("#{k}=") }
109
108
  response
110
109
  end
111
110
  def self.rest_to_response(content)
@@ -169,21 +168,17 @@ module EWS # :nodoc:
169
168
  # type-conversion from strings for certain attributes
170
169
  ATTR_FORMATS = {
171
170
  :transaction_tag => "i",
172
- :transaction_approved => "i",
173
- :amount => "f",
174
- :surcharge_amount => "f",
175
- :tax1_amount => "f",
176
- :tax2_amount => "f"
171
+ :transaction_approved => "i"
177
172
  }
178
173
 
179
174
  REQUEST_ENVELOPE_NAMESPACES = {
180
175
  "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
181
- "xmlns:env" => "http://schemas.xmlsoap.org/soap/envelope/",
176
+ "xmlns:soap" => "http://schemas.xmlsoap.org/soap/envelope/",
182
177
  "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance"
183
178
  }
184
179
  REQUEST_SAC_ATTRIBUTES = {
185
180
  "xmlns:n1" => "http://secure2.e-xact.com/vplug-in/transaction/rpc-enc/Request",
186
- "env:encodingStyle" => "http://schemas.xmlsoap.org/soap/encoding/"
181
+ "soap:encodingStyle" => "http://schemas.xmlsoap.org/soap/encoding/"
187
182
  }
188
183
  REQUEST_SAC_SOURCE_ATTRIBUTES = {
189
184
  "xmlns:n2" => "http://secure2.e-xact.com/vplug-in/transaction/rpc-enc/encodedTypes",
@@ -47,10 +47,10 @@ module EWS # :nodoc:
47
47
  append_error(:tax2_amount, "invalid tax2_amount supplied") unless valid_amount?(self.tax2_amount)
48
48
 
49
49
  # ensure our amounts are within range
50
- append_error(:amount, "amount must be between 0.00 and 99999.99") unless amount_too_big?(self.amount)
51
- append_error(:surcharge_amount, "amount must be between 0.00 and 99999.99") unless amount_too_big?(self.surcharge_amount)
52
- append_error(:tax1_amount, "amount must be between 0.00 and 99999.99") unless amount_too_big?(self.tax1_amount)
53
- append_error(:tax2_amount, "amount must be between 0.00 and 99999.99") unless amount_too_big?(self.tax2_amount)
50
+ append_error(:amount, "amount must be between 0.00 and 99999.99") unless amount_in_range?(self.amount)
51
+ append_error(:surcharge_amount, "amount must be between 0.00 and 99999.99") unless amount_in_range?(self.surcharge_amount)
52
+ append_error(:tax1_amount, "amount must be between 0.00 and 99999.99") unless amount_in_range?(self.tax1_amount)
53
+ append_error(:tax2_amount, "amount must be between 0.00 and 99999.99") unless amount_in_range?(self.tax2_amount)
54
54
 
55
55
  # ensure our credit card information is valid
56
56
  append_error(:cc_number, "invalid cc_number supplied") unless valid_card_number?
@@ -63,7 +63,7 @@ module EWS # :nodoc:
63
63
  def validate_lengths
64
64
  @@valid_lengths.each do |k,len|
65
65
  value = self.send k
66
- append_error(k, "#{k.to_s} is too long. maximum allowed length is #{len} characters") unless value.nil? or (value.length <= len)
66
+ append_error(k, "#{k.to_s} is too long. Maximum allowed length is #{len} characters") unless value.nil? or (value.length <= len)
67
67
  end
68
68
  end
69
69
 
@@ -76,15 +76,10 @@ module EWS # :nodoc:
76
76
  # c) encoded in a track1 value, or
77
77
  # d) encoded in a track2 value
78
78
  def validate_mandatory_fields
79
- if !self.cc_number.blank?
80
- validate_for_card
81
- elsif !self.transaction_tag.blank?
82
- validate_for_transaction_tag
83
- elsif !self.track1.blank?
84
- validate_for_track1
85
- elsif !self.track2.blank?
86
- validate_for_track2
87
- end
79
+ validate_for_card unless self.cc_number.blank?
80
+ validate_for_transaction_tag unless self.transaction_tag.blank?
81
+ validate_for_track1 unless self.track1.blank?
82
+ validate_for_track2 unless self.track2.blank?
88
83
  end
89
84
 
90
85
  def valid_amount?(amount)
@@ -92,7 +87,7 @@ module EWS # :nodoc:
92
87
 
93
88
  ((amount.class == Float) or (amount.class == Fixnum) or !amount.match(/[^0-9.]/))
94
89
  end
95
- def amount_too_big?(amount)
90
+ def amount_in_range?(amount)
96
91
  return true if amount.blank?
97
92
 
98
93
  return ((amount.to_f <= 99999.99) and (amount.to_f >= 0.0))
@@ -124,7 +119,8 @@ module EWS # :nodoc:
124
119
  return false unless self.cc_expiry.match(/^\d{4}$/)
125
120
 
126
121
  # check date is not in past
127
- year, month = 2000 + self.cc_expiry[2..3].to_i, self.cc_expiry[0..1].to_i
122
+ year, month = self.cc_expiry[2..3].to_i, self.cc_expiry[0..1].to_i
123
+ year += (year > 79) ? 1900 : 2000
128
124
 
129
125
  # CC is still considered valid during the month of expiry,
130
126
  # so just compare year and month, ignoring the rest.
@@ -146,7 +142,7 @@ module EWS # :nodoc:
146
142
  end
147
143
  end
148
144
 
149
- # validate presence of mandatort fields when cc_number present
145
+ # validate presence of mandatory fields when cc_number present
150
146
  def validate_for_card
151
147
  tt = self.transaction_type.to_i
152
148
 
@@ -208,7 +204,7 @@ module EWS # :nodoc:
208
204
  tt = self.transaction_type.to_i
209
205
 
210
206
  # mandatory: transaction_type must != (30, 31, 32, 34, 35, 50, 54)
211
- append_error(:track1, "track1 must not be set for tagged transactions") if [30,31,32,34,35,50,54].include?(tt)
207
+ append_error(:track2, "track2 must not be set for tagged transactions") if [30,31,32,34,35,50,54].include?(tt)
212
208
 
213
209
  # track2, expiry_date, cardholder_name, amount mandatory
214
210
  mandatory = [:track2, :cc_expiry, :cardholder_name, :amount]
@@ -22,19 +22,17 @@ module EWS # :nodoc:
22
22
  # to https://api.e-xact.com, the location of our transaction processing web service.
23
23
  #
24
24
  # You can also specify a hash of options as follows:
25
- # :server_cert the path to the server's certificate
26
- # :issuer_cert the path to the certificate of the issuer of the server certificate
27
25
  # :transport_type the transport_type for this transporter (defaults to :rest)
28
26
  #
29
27
  # The default certificates are those required to connect to https://api.e-xact.com and the
30
28
  # default <tt>transport_type</tt> is <tt>:rest</tt>. The default <tt>transport_type</tt> can be overridden on a per-transaction
31
29
  # basis, if you choose to do so, by specifying it as a parameter to the <tt>submit</tt> method.
32
- def initialize(url = "https://api.e-xact.com/", options = {})
30
+ def initialize(url = "https://api.e-xact.com", options = {})
33
31
  @url = URI.parse(url.gsub(/\/$/,''))
34
- base = File.dirname(__FILE__)
35
- @server_cert = options[:server_cert] || base+"/../../certs/exact.cer"
36
- @issuer_cert = options[:issuer_cert] || base+"/../../certs/equifax_ca.cer"
37
- @transport_type = options[:transport_type] || :json
32
+ @transport_type = options[:transport_type] || :rest
33
+
34
+ @@issuer_cert ||= File.dirname(__FILE__)+"/../../certs/equifax_ca.cer"
35
+ @@server_cert ||= File.new(File.dirname(__FILE__)+"/../../certs/exact.cer").read
38
36
  end
39
37
 
40
38
  # Submit a transaction request to the server
@@ -107,29 +105,21 @@ private
107
105
  if @url.scheme == 'https'
108
106
  @connection.use_ssl = true
109
107
  @connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
110
- @connection.ca_file = @issuer_cert
111
108
  @connection.verify_callback = method(:validate_certificate)
109
+ @connection.ca_file = @@issuer_cert
112
110
  end
113
111
  @connection
114
112
  end
115
113
 
116
- # from OpenSSL doco:
117
- # peer cert is always at chain[0], root CA at chain[n-1]
118
- # OpenSSL validates signatures, and issuer attributes at each step in the chain; is_ok reflects the status of these checks
119
114
  def validate_certificate(is_ok, ctx)
120
- # if OpenSSL has flagged an issue, then fail
121
- return false unless is_ok
122
-
123
- peer_cert = ctx.chain[0].to_pem
124
- current_cert = ctx.current_cert
125
-
126
- # we're not interested in additional checking of the CA certs
127
- return is_ok unless peer_cert == current_cert.to_pem
115
+ cert = ctx.current_cert
116
+
117
+ # Only check the server certificate, not the issuer.
118
+ unless (cert.subject.to_s == cert.issuer.to_s)
119
+ is_ok &&= (@@server_cert == cert.to_pem)
120
+ end
128
121
 
129
- # check that the peer_cert is the same as the one we expect for this URL
130
- contents = File.open(@server_cert).read
131
- cert = OpenSSL::X509::Certificate.new(contents)
132
- return OpenSSL::Digest::SHA1.new(current_cert.to_der) == OpenSSL::Digest::SHA1.new(cert.to_der)
122
+ is_ok
133
123
  end
134
124
 
135
125
  # what transport types we support, and their corresponding suffixes
data/lib/exact4r.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rubygems'
2
+ require 'activesupport'
2
3
 
3
4
  require 'ews/transaction/mapping'
4
5
  require 'ews/transaction/request'
data/spec/spec_helper.rb CHANGED
@@ -2,16 +2,18 @@ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
2
 
3
3
  require 'spec'
4
4
  require 'lib/exact4r'
5
+ require 'ruby-debug'
5
6
 
6
7
  REPLICATION_TIME = 20
7
8
 
8
9
  # address & authentication for testing against api.e-xact.com
9
- # LOCATION = "https://api.e-xact.com/"
10
- # BASIC_AUTH = {:gateway_id => "A00049-01", :password => "test1"}
10
+ LOCATION = "https://api.e-xact.com/"
11
+ BASIC_AUTH = {:gateway_id => "A00049-01", :password => "test1"}
11
12
 
12
13
  # address & authentication for local testing
13
- LOCATION = "http://localhost:3000/"
14
- BASIC_AUTH = {:gateway_id => "AD0008-01", :password => "7nfcpc7n"}
14
+ # LOCATION = "http://ws.local/" # I am a Passenger...
15
+ # LOCATION = "http://localhost:3000/" # old skool
16
+ # BASIC_AUTH = {:gateway_id => "AD0008-01", :password => "7nfcpc7n"}
15
17
 
16
18
  Spec::Runner.configure do |config|
17
19
  include EWS::Transaction
@@ -22,8 +22,6 @@ describe "Transporter creating transactions" do
22
22
  req = basic_find_transaction
23
23
  req.transaction_tag = 9000 # non-existent txn
24
24
 
25
- puts req.errors.inspect unless req.valid?
26
-
27
25
  tr = ::EWS::Transporter.new(LOCATION)
28
26
  resp = tr.submit(req, :json)
29
27
 
@@ -141,5 +141,10 @@ describe "credit card validation" do
141
141
  EWS::Transaction::Request.new(basic_params(:cc_expiry => sprintf("%02d%02d", month, year))).should be_valid
142
142
  EWS::Transaction::Request.new(basic_params(:cc_expiry => sprintf("%02d%02d", month+1, year))).should be_valid
143
143
  EWS::Transaction::Request.new(basic_params(:cc_expiry => sprintf("%02d%02d", month, year+1))).should be_valid
144
+
145
+ # we've chosen 1980 as our cutoff in the past, so check around this date
146
+ EWS::Transaction::Request.new(basic_params(:cc_expiry => "1279")).should be_valid # Dec 2079
147
+ EWS::Transaction::Request.new(basic_params(:cc_expiry => "0180")).should_not be_valid # Jan 1980
148
+ EWS::Transaction::Request.new(basic_params(:cc_expiry => "0199")).should_not be_valid # Jan 1999
144
149
  end
145
150
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exact4r
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.6"
4
+ version: "0.7"
5
5
  platform: ruby
6
6
  authors:
7
7
  - E-xact Transactions Ltd.
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-08-14 00:00:00 +10:00
12
+ date: 2009-03-10 00:00:00 +11:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -48,36 +48,6 @@ files:
48
48
  - ./certs/equifax_ca.cer
49
49
  - ./certs/exact.cer
50
50
  - ./CHANGELOG
51
- - ./doc
52
- - ./doc/classes
53
- - ./doc/classes/EWS
54
- - ./doc/classes/EWS/Transaction
55
- - ./doc/classes/EWS/Transaction/FakeResponse.html
56
- - ./doc/classes/EWS/Transaction/Request.html
57
- - ./doc/classes/EWS/Transaction/Response.html
58
- - ./doc/classes/EWS/Transaction/Validator.html
59
- - ./doc/classes/EWS/Transporter.html
60
- - ./doc/created.rid
61
- - ./doc/files
62
- - ./doc/files/CHANGELOG.html
63
- - ./doc/files/lib
64
- - ./doc/files/lib/ews
65
- - ./doc/files/lib/ews/transaction
66
- - ./doc/files/lib/ews/transaction/fake_response_rb.html
67
- - ./doc/files/lib/ews/transaction/mapping_rb.html
68
- - ./doc/files/lib/ews/transaction/request_rb.html
69
- - ./doc/files/lib/ews/transaction/response_rb.html
70
- - ./doc/files/lib/ews/transaction/validator_rb.html
71
- - ./doc/files/lib/ews/transporter_rb.html
72
- - ./doc/files/lib/exact4r_rb.html
73
- - ./doc/files/LICENCE.html
74
- - ./doc/files/README.html
75
- - ./doc/files/VERSION.html
76
- - ./doc/fr_class_index.html
77
- - ./doc/fr_file_index.html
78
- - ./doc/fr_method_index.html
79
- - ./doc/index.html
80
- - ./doc/rdoc-style.css
81
51
  - ./lib
82
52
  - ./lib/ews
83
53
  - ./lib/ews/transaction
@@ -92,7 +62,6 @@ files:
92
62
  - ./Rakefile
93
63
  - ./README
94
64
  - ./spec
95
- - ./spec/donncha_spec.rb
96
65
  - ./spec/mapping_spec.rb
97
66
  - ./spec/request_spec.rb
98
67
  - ./spec/spec_helper.rb
@@ -128,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
97
  requirements: []
129
98
 
130
99
  rubyforge_project: exact4r
131
- rubygems_version: 1.2.0
100
+ rubygems_version: 1.3.1
132
101
  signing_key:
133
102
  specification_version: 2
134
103
  summary: E-xact Web Services Client Library.