exact4r 0.6 → 0.7

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,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.