exact4r 0.5 → 1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +69 -0
- data/LICENCE +3 -0
- data/README +186 -0
- data/Rakefile +74 -0
- data/VERSION +1 -0
- data/certs/e-xact.com.crt +31 -0
- data/certs/exact.cer +10 -10
- data/certs/valicert_class2_root.crt +18 -0
- data/lib/ews/certificate_helper.rb +68 -0
- data/lib/ews/transaction/fake_response.rb +137 -0
- data/lib/ews/transaction/mapping.rb +87 -65
- data/lib/ews/transaction/request.rb +51 -62
- data/lib/ews/transaction/response.rb +11 -2
- data/lib/ews/transaction/rexml-expansion-fix.rb +42 -0
- data/lib/ews/transaction/validator.rb +250 -0
- data/lib/ews/transporter.rb +139 -0
- data/lib/exact4r.rb +10 -2
- data/prod.log +49 -0
- data/test/credentials.rb +63 -0
- data/test/credentials.yml +53 -0
- data/test/exhaustive/batch_query_close_test.rb +205 -0
- data/test/exhaustive/forced_post_test.rb +81 -0
- data/test/exhaustive/online_debit_purchase_test.rb +70 -0
- data/test/exhaustive/online_debit_refund_test.rb +70 -0
- data/test/exhaustive/pre_auth_completion_test.rb +99 -0
- data/test/exhaustive/pre_auth_only_test.rb +74 -0
- data/test/exhaustive/pre_auth_test.rb +68 -0
- data/test/exhaustive/purchase_correction_test.rb +85 -0
- data/test/exhaustive/purchase_test.rb +68 -0
- data/test/exhaustive/recurring_seed_pre_auth_test.rb +68 -0
- data/test/exhaustive/recurring_seed_purchase_test.rb +68 -0
- data/test/exhaustive/referenced_void_test.rb +131 -0
- data/test/exhaustive/refund_correction_test.rb +85 -0
- data/test/exhaustive/refund_test.rb +68 -0
- data/test/exhaustive/secure_storage_test.rb +75 -0
- data/test/exhaustive/tagged_online_debit_refund_test.rb +195 -0
- data/test/exhaustive/tagged_pre_auth_completion_test.rb +119 -0
- data/test/exhaustive/tagged_pre_auth_test.rb +116 -0
- data/test/exhaustive/tagged_purchase_test.rb +116 -0
- data/test/exhaustive/tagged_refund_test.rb +142 -0
- data/test/exhaustive/tagged_update_test.rb +158 -0
- data/test/exhaustive/tagged_void_test.rb +174 -0
- data/test/exhaustive/transaction_details_test.rb +145 -0
- data/test/exhaustive/void_test.rb +118 -0
- data/test/general/avs_test.rb +87 -0
- data/test/general/client_certificate_test.rb +64 -0
- data/test/general/json_encoding_test.rb +62 -0
- data/test/general/request_test.rb +179 -0
- data/test/general/rest_encoding_test.rb +174 -0
- data/test/general/soap_encoding_test.rb +211 -0
- data/test/general/transporter_test.rb +74 -0
- data/test/general/validator_test.rb +150 -0
- data/test/samples/dsa_cert.pem +22 -0
- data/test/samples/dsa_key.pem +12 -0
- data/test/samples/rest.dodgy.response.xml +60 -0
- data/test/samples/rest.everything.response.xml +67 -0
- data/test/samples/rest.response.xml +60 -0
- data/test/samples/rsa_cert.pem +63 -0
- data/test/samples/rsa_key.pem +15 -0
- data/test/samples/soap.deserialization.fault.xml +10 -0
- data/test/samples/soap.dodgy.response.xml +95 -0
- data/test/samples/soap.everything.response.xml +75 -0
- data/test/samples/soap.generalfailure.fault.xml +13 -0
- data/test/samples/soap.nulltransaction.fault.xml +14 -0
- data/test/samples/soap.response.xml +95 -0
- data/test/test_helper.rb +107 -0
- metadata +127 -45
- data/doc/classes/EWS/Transaction/Request.html +0 -488
- data/doc/classes/EWS/Transaction/Response.html +0 -280
- data/doc/classes/EWS/Transaction/Transporter.html +0 -251
- data/doc/created.rid +0 -1
- data/doc/files/README.html +0 -230
- data/doc/files/lib/ews/transaction/mapping_rb.html +0 -108
- data/doc/files/lib/ews/transaction/request_rb.html +0 -101
- data/doc/files/lib/ews/transaction/response_rb.html +0 -101
- data/doc/files/lib/ews/transaction/transporter_rb.html +0 -108
- data/doc/files/lib/exact4r_rb.html +0 -113
- data/doc/fr_class_index.html +0 -29
- data/doc/fr_file_index.html +0 -32
- data/doc/fr_method_index.html +0 -33
- data/doc/index.html +0 -24
- data/doc/rdoc-style.css +0 -208
- data/lib/ews/transaction/transporter.rb +0 -128
data/CHANGELOG
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
== v1.7
|
2
|
+
Added support for setting a client certificate/key pair for use w/ SSL connections.
|
3
|
+
|
4
|
+
== v1.6
|
5
|
+
Added support for use w/ ActiveSupport v3.
|
6
|
+
|
7
|
+
== v1.5
|
8
|
+
Added support for specifying authorization_num & reference_no in CR requests, to obtain decrypted CC numbers.
|
9
|
+
|
10
|
+
== v1.4
|
11
|
+
Added support for specifying alternative SSL certificates
|
12
|
+
|
13
|
+
== v1.3
|
14
|
+
Added support for TaggedUpdate transactions
|
15
|
+
Added support for ReferencedVoid transactions
|
16
|
+
|
17
|
+
== v1.2
|
18
|
+
Updated with new SSL certificates for https://api.e-xact.com
|
19
|
+
|
20
|
+
== v1.1
|
21
|
+
Removed debugger statement. Sorry!
|
22
|
+
|
23
|
+
== v1.0
|
24
|
+
Added support for Batch Query and Batch Close transactions.
|
25
|
+
|
26
|
+
== v0.9.3
|
27
|
+
Reinstated Tagged Void support.
|
28
|
+
|
29
|
+
== v0.9.2
|
30
|
+
Converted tests to Test::Unit
|
31
|
+
Added complete test suite, testing all transaction types.
|
32
|
+
Enhanced validation of mandatory request information.
|
33
|
+
|
34
|
+
== v0.9.1
|
35
|
+
Added unified Address Verification API
|
36
|
+
|
37
|
+
== v0.9
|
38
|
+
Fixed incorrect decoding of boolean attributes from SOAP response
|
39
|
+
|
40
|
+
== v0.8
|
41
|
+
Added User-Agent string to HTTP requests
|
42
|
+
|
43
|
+
== v0.7
|
44
|
+
Updated with latest certificates for api.e-xact.com
|
45
|
+
Fixed SOAP namespace issue
|
46
|
+
Ensured expiry_date always submitted at MMYY
|
47
|
+
|
48
|
+
== v0.6
|
49
|
+
Added client-side request validation
|
50
|
+
|
51
|
+
== v0.5.3
|
52
|
+
Added fake response messages for testing purposes
|
53
|
+
Moved EWS::Transaction::Transporter to EWS::Transporter
|
54
|
+
Fixed typos
|
55
|
+
|
56
|
+
== v0.5.2
|
57
|
+
Updated Transporter to play nicely with mod_security
|
58
|
+
Stripped trailing '/'s from URLs
|
59
|
+
Transporter ow re-uses connection
|
60
|
+
Updated RDoc with test login details
|
61
|
+
|
62
|
+
== v0.5.1
|
63
|
+
Added CHANGELOG, LICENCE & VERSION
|
64
|
+
Ensured README etc. were included in gem and displayed as default in RDoc
|
65
|
+
Renamed send() to submit() in Transporter
|
66
|
+
Fixed path to default E-xact certificates
|
67
|
+
|
68
|
+
== v0.5
|
69
|
+
Initial Release
|
data/LICENCE
ADDED
data/README
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
= exact4r
|
2
|
+
A gem which provides access to E-xact's Web Services API, allowing the submission
|
3
|
+
of financial transactions via REST, JSON or SOAP.
|
4
|
+
|
5
|
+
== Getting Started
|
6
|
+
|
7
|
+
To submit requests to our transaction processing service, you must first have a Gateway ID,
|
8
|
+
and a password. Test logins are as follows:
|
9
|
+
|
10
|
+
Account 1: :gateway_id => "A00049-01", :password => "test1"
|
11
|
+
Account 2: :gateway_id => "A00427-01", :password => "testus"
|
12
|
+
|
13
|
+
|
14
|
+
=1. Submit a transaction
|
15
|
+
|
16
|
+
require 'rubygems'
|
17
|
+
require 'exact4r'
|
18
|
+
|
19
|
+
# build a purchase request
|
20
|
+
request = EWS::Transaction::Request.new({
|
21
|
+
:transaction_type => :purchase,
|
22
|
+
:amount => 10.50,
|
23
|
+
:cardholder_name => "Simon Brown",
|
24
|
+
:cc_number => "4111111111111111",
|
25
|
+
:cc_expiry => "1012", # MUST be MMYY format
|
26
|
+
:gateway_id => "XXXXXXX", # which gateway to submit the request to
|
27
|
+
:password => "YYYYYY" # your password for that gateway
|
28
|
+
})
|
29
|
+
|
30
|
+
transporter = EWS::Transporter.new
|
31
|
+
response = transporter.submit(request) # submits using REST (XML) by default
|
32
|
+
|
33
|
+
# submit using JSON, or
|
34
|
+
response = transporter.submit(request, :json)
|
35
|
+
|
36
|
+
# submit using SOAP, or
|
37
|
+
response = transporter.submit(request, :soap)
|
38
|
+
|
39
|
+
# submit explicitly via REST
|
40
|
+
response = transporter.submit(request, :rest)
|
41
|
+
|
42
|
+
# The response object is independent of type of transport chosen.
|
43
|
+
# We decode the payload into a regular object
|
44
|
+
response.transaction_tag # 1234
|
45
|
+
response.exact_resp_code # "00"
|
46
|
+
response.exact_message # "Transaction Normal"
|
47
|
+
response.bank_resp_code # "00"
|
48
|
+
response.bank_message # "APPROVED"
|
49
|
+
|
50
|
+
=2. Find information on an existing transaction
|
51
|
+
|
52
|
+
require 'rubygems'
|
53
|
+
require 'exact4r'
|
54
|
+
|
55
|
+
# build a purchase request
|
56
|
+
request = EWS::Transaction::Request.new({
|
57
|
+
:transaction_type => :purchase,
|
58
|
+
:amount => 10.50,
|
59
|
+
:cardholder_name => "Simon Brown",
|
60
|
+
:cc_number => "4111111111111111",
|
61
|
+
:cc_expiry => "1012", # MUST be MMYY format
|
62
|
+
:gateway_id => "XXXXXXX", # which gateway to submit the request to
|
63
|
+
:password => "YYYYYY" # your password for that gateway
|
64
|
+
})
|
65
|
+
|
66
|
+
transporter = EWS::Transporter.new
|
67
|
+
response = transporter.submit(request) # submits using REST (XML) by default
|
68
|
+
|
69
|
+
# you need to know the transaction tag of the transaction you are looking for
|
70
|
+
find_request = EWS::Transaction::Request.new({
|
71
|
+
:transaction_type => :transaction_details,
|
72
|
+
:transaction_tag => response.transaction_tag,
|
73
|
+
:gateway_id => "XXXXXXX",
|
74
|
+
:password => "YYYYYY"
|
75
|
+
})
|
76
|
+
|
77
|
+
find_response = transporter.submit(find_request, :json) # again, can choose your transport type as before
|
78
|
+
find_response.cc_number # 4111111111111111
|
79
|
+
find_response.amount # 10.50
|
80
|
+
|
81
|
+
=3. Re-using a Transporter
|
82
|
+
|
83
|
+
require 'rubygems'
|
84
|
+
require 'exact4r'
|
85
|
+
|
86
|
+
# The transporter object can be re-used across multiple transactions, so set it up once
|
87
|
+
# and forget about it.
|
88
|
+
# In this example, we will continue to use E-xact's default web-service URL, but we
|
89
|
+
# will specify a default transport_type of :soap
|
90
|
+
transporter = EWS::Transporter.new("https://api.e-xact.com/", {:transaction_type => :soap})
|
91
|
+
|
92
|
+
# now let's submit do a recurring seed purchase...
|
93
|
+
rsp_req = EWS::Transaction::Request.new({
|
94
|
+
:transaction_type => :recurring_seed_purchase,
|
95
|
+
:amount => 12.00,
|
96
|
+
:cardholder_name => "Simon Brown",
|
97
|
+
:cc_number => "4111111111111111",
|
98
|
+
:cc_expiry => "1012",
|
99
|
+
:gateway_id => "XXXXXX",
|
100
|
+
:password => "YYYYYY"
|
101
|
+
})
|
102
|
+
|
103
|
+
rsp_resp = transporter.submit(rsp_req)
|
104
|
+
raise "Seed Purchase failed" unless rsp_resp.approved?
|
105
|
+
|
106
|
+
# ...then do multiple refunds against it
|
107
|
+
1.upto(10) do
|
108
|
+
rf_req = EWS::Transaction::Request.new({
|
109
|
+
:transaction_type => :tagged_refund,
|
110
|
+
:transaction_tag => rsp_resp.transaction_tag, # need to know which transaction we're refunding against...
|
111
|
+
:authorization_num => rsp_resp.authorization_num, # and its authorization_num
|
112
|
+
:amount => 1.00, # refund a dollar at a time
|
113
|
+
:gateway_id => "XXXXXX",
|
114
|
+
:password => "YYYYYY"
|
115
|
+
})
|
116
|
+
rf_resp = transporter.submit(rf_req)
|
117
|
+
raise "Refund failed: #{rf_resp.exact_resp_code}, #{rf_resp.exact_message}" unless rf_resp.approved?
|
118
|
+
end
|
119
|
+
|
120
|
+
=4. Using the AVS API
|
121
|
+
|
122
|
+
Allowable AVS params are:
|
123
|
+
|
124
|
+
- :avs_street_address => "7501ELMST."
|
125
|
+
- :avs_unit_no => "801"
|
126
|
+
- :avs_po_box => nil # P.O. Box or street address may be specified, but not both
|
127
|
+
- :avs_postal_code => "90210"
|
128
|
+
- :avs_test_flag => "X" # AVS test flag (optional)
|
129
|
+
|
130
|
+
|
131
|
+
===Test Flags
|
132
|
+
In order to simulate an AVS response in the test environment, set the :+avs_test_flag+ to the AVS result code you would like
|
133
|
+
returned. The AVS result is a one-character response that indicates the degree of match for the provided address.
|
134
|
+
The following AVS responses are currently supported:
|
135
|
+
|
136
|
+
===North American Response Codes
|
137
|
+
AVS Code - ABS Definition - Explanation
|
138
|
+
- X - Exact match, 9 digit zip - Street Address, and 9 digit ZIP Code match
|
139
|
+
- Y - Exact match, 5 digit zip - Street Address, and 5 digit ZIP Code match
|
140
|
+
- A - Partial match - Street Address matches, ZIP Code does not
|
141
|
+
- W - Partial match - ZIP Code matches, Street Address does not
|
142
|
+
- Z - Partial match - 5 digit ZIP Code match only
|
143
|
+
- N - No match - No Address or ZIP Code match
|
144
|
+
- U - Unavailable - Address information is unavailable for that account number, or the card issuer does not support
|
145
|
+
- G - Service Not supported, non-US Issuer does not participate
|
146
|
+
- R - Retry - Issuer system unavailable, retry later
|
147
|
+
- E - Not a mail or phone order
|
148
|
+
- S - Service not supported
|
149
|
+
|
150
|
+
===International Response Codes
|
151
|
+
AVS Code - ABS Definition and Explanation
|
152
|
+
- G - Global non-AVS participant
|
153
|
+
- B - Address matches only
|
154
|
+
- C - Address and Postal Code do not match
|
155
|
+
- D - Address and Postal Code match
|
156
|
+
- F - Address and Postal Code match (UK only)
|
157
|
+
- I - Address information not verified for international transaction
|
158
|
+
- M - Address and Postal Code match
|
159
|
+
- P - Postal Code matches only
|
160
|
+
|
161
|
+
===Code Sample
|
162
|
+
avs_params = {
|
163
|
+
:avs_test_flag => 'N',
|
164
|
+
:avs_street_address => '123BROWNSTREET',
|
165
|
+
:avs_unit_no => '4,
|
166
|
+
:avs_po_box => nil,
|
167
|
+
:avs_postal_code => '902101234'
|
168
|
+
}
|
169
|
+
|
170
|
+
tx_params = {
|
171
|
+
:transaction_type => :purchase,
|
172
|
+
:amount => 10.50,
|
173
|
+
:cardholder_name => "Simon Brown",
|
174
|
+
:cc_number => "4111111111111111",
|
175
|
+
:cc_expiry => "1012",
|
176
|
+
:gateway_id => "XXXXXXX",
|
177
|
+
:password => "YYYYYY"
|
178
|
+
}.merge(avs_params)
|
179
|
+
|
180
|
+
request = EWS::Transaction::Request.new(tx_params)
|
181
|
+
|
182
|
+
transporter = EWS::Transporter.new("https://api.e-xact.com/")
|
183
|
+
response = transporter.submit(request)
|
184
|
+
|
185
|
+
response.cc_verification_str1.should == "N123BROWNSTREET4902101234"
|
186
|
+
response.avs.should == N
|
data/Rakefile
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'rake/rdoctask'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require "rubygems"
|
4
|
+
require "rake/gempackagetask"
|
5
|
+
|
6
|
+
task :default => :'test:chase'
|
7
|
+
|
8
|
+
namespace :test do
|
9
|
+
|
10
|
+
desc 'Run all tests against all processors. Use LOCATION to specify web service URL.'
|
11
|
+
task :all do
|
12
|
+
%w(chase tsys emergis moneris).each do |processor|
|
13
|
+
3.times { puts }
|
14
|
+
puts "#-----------------------"
|
15
|
+
puts "# Testing: " + processor
|
16
|
+
puts "#-----------------------"
|
17
|
+
|
18
|
+
ENV['PROCESSOR'] = processor
|
19
|
+
begin
|
20
|
+
Rake::Task[:'test:processor'].execute
|
21
|
+
rescue
|
22
|
+
# don't care, just run it again. can examine output later
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Run all tests against Chase processor and Production web service. Use LOCATION to specify web service URL.'
|
28
|
+
task :chase do
|
29
|
+
ENV['PROCESSOR'] = 'chase'
|
30
|
+
ENV['LOCATION'] = 'PROD' if ENV['LOCATION'].nil?
|
31
|
+
begin
|
32
|
+
Rake::Task[:'test:processor'].execute
|
33
|
+
rescue
|
34
|
+
# don't care, just run it again. can examine output later
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'Run all the tests against a specific processor. Use LOCATION to specify web service URL.'
|
39
|
+
Rake::TestTask.new(:processor) do |t|
|
40
|
+
t.libs << 'lib'
|
41
|
+
t.pattern = 'test/**/*_test.rb'
|
42
|
+
t.verbose = true
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Build the RDoc"
|
48
|
+
Rake::RDocTask.new { |rdoc|
|
49
|
+
rdoc.rdoc_dir = 'doc'
|
50
|
+
rdoc.title = "exact4r"
|
51
|
+
rdoc.options << '--main' << 'README' << "--inline-source" << "--line-numbers"
|
52
|
+
rdoc.rdoc_files.include('CHANGELOG', 'LICENCE', 'README', 'VERSION', 'lib/**/*.rb')
|
53
|
+
}
|
54
|
+
|
55
|
+
desc "Build the exact4r gem"
|
56
|
+
spec = Gem::Specification.new do |s|
|
57
|
+
s.name="exact4r"
|
58
|
+
s.author = "E-xact Transactions Ltd."
|
59
|
+
s.homepage = "http://e-xact4r.rubyforge.org/"
|
60
|
+
s.rubyforge_project = "exact4r"
|
61
|
+
s.email = "dredmond@e-xact.com"
|
62
|
+
s.version=`cat VERSION`
|
63
|
+
s.summary = 'E-xact Web Services Client Library.'
|
64
|
+
s.files = FileList["./**/**"].to_a
|
65
|
+
s.has_rdoc = true
|
66
|
+
s.extra_rdoc_files = ['CHANGELOG', 'LICENCE', 'README', 'VERSION']
|
67
|
+
s.rdoc_options << '--main' << 'README' << '--inline-source' << '--line-numbers'
|
68
|
+
s.add_dependency('activesupport', '>= 2.3.2')
|
69
|
+
s.add_dependency('builder', '>= 2.1.2')
|
70
|
+
end
|
71
|
+
|
72
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
73
|
+
pkg.need_tar = true
|
74
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.7
|
@@ -0,0 +1,31 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIFVTCCBD2gAwIBAgIHBITApWVLMTANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
|
3
|
+
BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY
|
4
|
+
BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm
|
5
|
+
aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5
|
6
|
+
IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky
|
7
|
+
ODcwHhcNMTAwMjE2MjMzNTQzWhcNMTUwMjE2MjMzNTQzWjBRMRUwEwYDVQQKDAwq
|
8
|
+
LmUteGFjdC5jb20xITAfBgNVBAsMGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEV
|
9
|
+
MBMGA1UEAwwMKi5lLXhhY3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
10
|
+
CgKCAQEApvqzJMP4vtbvyXwepZhj8uaKXONIo4H8aN51FOL1PDdGEfWktlWw38Xj
|
11
|
+
dU0KJrGeTcBgsfg8NehFwasilW6IbojhMmnvWyYaTzklEjMDmgda3hGRJRqbg/dW
|
12
|
+
v0nZRMO7Xy0NNMGHeN9Sxs8977LRV5Y1VjK1M3WhilP3oxe49Ov1K4FEZrxT0fbn
|
13
|
+
sqClwAm059XM+qWkUY5tBs6KSZQf1/+Xlx5txB/IqDWLrN5oRuCa+mBi5mIFE7nA
|
14
|
+
suFtI/26szCYVuK6r8spbsYeo13c/qTv4yaZbLW3uXgbgTuI4FAtOR9NpUYvLQHR
|
15
|
+
9kYYPeusqj0DnLD6ELMXkujHW0V6MQIDAQABo4IBtjCCAbIwDwYDVR0TAQH/BAUw
|
16
|
+
AwEBADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQD
|
17
|
+
AgWgMDMGA1UdHwQsMCowKKAmoCSGImh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Rz
|
18
|
+
MS0xNC5jcmwwUwYDVR0gBEwwSjBIBgtghkgBhv1tAQcXATA5MDcGCCsGAQUFBwIB
|
19
|
+
FitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMIGA
|
20
|
+
BggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdvZGFkZHku
|
21
|
+
Y29tLzBKBggrBgEFBQcwAoY+aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv
|
22
|
+
bS9yZXBvc2l0b3J5L2dkX2ludGVybWVkaWF0ZS5jcnQwHwYDVR0jBBgwFoAU/axh
|
23
|
+
MpNsRdbi7oVfmrrndplozOcwIwYDVR0RBBwwGoIMKi5lLXhhY3QuY29tggplLXhh
|
24
|
+
Y3QuY29tMB0GA1UdDgQWBBRmlEOazZNz8dfnnl7UimMDqciOOzANBgkqhkiG9w0B
|
25
|
+
AQUFAAOCAQEArQNhlZ3ij3Yz1U2GHiNY4fpYtNCAhzlrnNZUHaDlhiWEvOcXSB4j
|
26
|
+
ER77sgaHmZOm8PW0mXg3eK0+Km5ANWbNbPLe0yPpKRa1GbmgxQx/P4MWMiM+872l
|
27
|
+
QmpZlgLw2cGvivALAt7S74QTiqjYX10nNyHlpnlvB9Am2WgzQHQDzyKuKGglFjlw
|
28
|
+
ItZpTFFkSGEWK99cxE69GMwtZCsr4b+RB80sDA+ckd45GISg808GkWHfqJVa64k8
|
29
|
+
dlXVgRNQwLfrWN+BQeUsfsKu5jiNI7H2a8zrRt4mCa9urh15O+d4pDhXhrYSkQpI
|
30
|
+
ezmbzKzCEd1mpiT+sjCzByN3uX6n7eF/Eg==
|
31
|
+
-----END CERTIFICATE-----
|
data/certs/exact.cer
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
-----BEGIN CERTIFICATE-----
|
2
|
-
|
2
|
+
MIIC7DCCAlWgAwIBAgIDCqSQMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
|
3
3
|
MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
|
4
|
-
|
4
|
+
aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkwMjEzMDAxMDQ2WhcNMTAwMzE1MjMxMDQ2
|
5
5
|
WjB3MQswCQYDVQQGEwJDQTEZMBcGA1UECBMQQnJpdGlzaCBDb2x1bWJpYTESMBAG
|
6
6
|
A1UEBxMJVmFuY291dmVyMSIwIAYDVQQKExlFLXhhY3QgVHJhbnNhY3Rpb25zLCBM
|
7
7
|
dGQuMRUwEwYDVQQDFAwqLmUteGFjdC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
gaswDgYDVR0PAQH/
|
12
|
-
|
8
|
+
MIGJAoGBAKAEtyoEOQMqbYNTo/XGXx68vElKFb3lhQ9qimRlggadSCA3F1P40dMz
|
9
|
+
3PlXDtKN9TcvqYalvmrntjmtY7/QgBu59AJOIoFDXe/XCtW16XAlANIrTvS9zhHd
|
10
|
+
nnLhCHcLAhEJIssWb3ddXiK8NDIyHtIbWYRIdzT0aPOLtoUXfcBLAgMBAAGjga4w
|
11
|
+
gaswDgYDVR0PAQH/BAQDAgTwMB0GA1UdDgQWBBSTkCQC1iSGLxD/+kL5elS75kLe
|
12
|
+
hDA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxz
|
13
13
|
L3NlY3VyZWNhLmNybDAfBgNVHSMEGDAWgBRI5mj5K9KylddH2CMgEE8zmJCf1DAd
|
14
14
|
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEA
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
iHFOvsHR2SZ93jry4TaDWXXVN3gBuK9S7j4ubcGbT4HZe/1OJXE8Hpdc6lFaBgdi
|
16
|
+
ZK2qHFzZ7suhcOiF6f7HCtDDXdoGAhYJVWGvhd/2CsvaRzdVWkUQzfRgDXKoYU9W
|
17
|
+
BEQs/Y5lG23rmq4WJe6HSVN0FMaZS3aVIr54821hKPc=
|
18
18
|
-----END CERTIFICATE-----
|
@@ -0,0 +1,18 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
|
3
|
+
IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
|
4
|
+
BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
|
5
|
+
aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
|
6
|
+
9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
|
7
|
+
NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
|
8
|
+
azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
|
9
|
+
YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
|
10
|
+
Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
|
11
|
+
cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
|
12
|
+
dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
|
13
|
+
WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
|
14
|
+
v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
|
15
|
+
UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
|
16
|
+
IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
|
17
|
+
W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
|
18
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,68 @@
|
|
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, :client_cert, :client_key
|
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
|
+
if options[:client_cert]
|
14
|
+
raise ArgumentError.new "Key file not supplied" if options[:client_key].blank?
|
15
|
+
self.client_cert = OpenSSL::X509::Certificate.new(File.new(options[:client_cert]).read)
|
16
|
+
self.client_key = client_cert.public_key.class.send(:new, File.new(options[:client_key]).read)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
private :configure_certificates
|
20
|
+
|
21
|
+
def validate_certificate(is_ok, ctx)
|
22
|
+
cert = ctx.current_cert
|
23
|
+
return false if cert.nil?
|
24
|
+
|
25
|
+
# preverify failed?
|
26
|
+
return false unless is_ok
|
27
|
+
|
28
|
+
self_signed = false
|
29
|
+
ca = false
|
30
|
+
pathlen = nil
|
31
|
+
server_auth = true
|
32
|
+
self_signed = (cert.subject.cmp(cert.issuer) == 0)
|
33
|
+
|
34
|
+
# Check extensions for the certificate purpose according to http://www.openssl.org/docs/apps/x509.html (Certificate Extensions) and
|
35
|
+
# http://www.ietf.org/rfc/rfc3280.txt.
|
36
|
+
cert.extensions.each do |ex|
|
37
|
+
case ex.oid
|
38
|
+
when 'basicConstraints'
|
39
|
+
/CA:(TRUE|FALSE)(?:, pathlen:)*(\d*)/ =~ ex.value
|
40
|
+
ca ||= ($1 == 'TRUE')
|
41
|
+
pathlen = $2.to_i
|
42
|
+
when 'keyUsage'
|
43
|
+
usage = ex.value.split(/\s*,\s*/)
|
44
|
+
# a CA must have
|
45
|
+
ca &&= !usage.grep(/Certificate Sign/i).empty?
|
46
|
+
# Server Cert Must have
|
47
|
+
server_auth &&= !usage.grep(/Key Encipherment/i).empty?
|
48
|
+
when 'extendedKeyUsage'
|
49
|
+
usage = ex.value.split(/\s*,\s*/)
|
50
|
+
# Server Cert Must have
|
51
|
+
server_auth &&= !usage.grep(/TLS Web Server Authentication/i).empty?
|
52
|
+
when 'nsCertType'
|
53
|
+
usage = ex.value.split(/\s*,\s*/)
|
54
|
+
ca ||= !usage.grep(/SSL CA/i).empty?
|
55
|
+
server_auth ||= !usage.grep(/SSL Server/i).empty?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# We're looking for the server cert, so accept all CAs (which have already passed pre-verification)
|
60
|
+
return true if self_signed || ca
|
61
|
+
|
62
|
+
# ensure the server cert is the one we're expecting
|
63
|
+
return server_auth && self.server_cert == cert.to_pem
|
64
|
+
end
|
65
|
+
private :validate_certificate
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|