companies-house-gateway 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +20 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +28 -0
- data/companies_house_gateway.gemspec +22 -0
- data/lib/companies_house_gateway.rb +60 -0
- data/lib/companies_house_gateway/checks/check.rb +66 -0
- data/lib/companies_house_gateway/checks/company_appointments.rb +14 -0
- data/lib/companies_house_gateway/checks/company_details.rb +11 -0
- data/lib/companies_house_gateway/checks/document.rb +10 -0
- data/lib/companies_house_gateway/checks/document_info.rb +11 -0
- data/lib/companies_house_gateway/checks/filing_history.rb +12 -0
- data/lib/companies_house_gateway/checks/mortgages.rb +16 -0
- data/lib/companies_house_gateway/checks/name_search.rb +17 -0
- data/lib/companies_house_gateway/checks/number_search.rb +13 -0
- data/lib/companies_house_gateway/checks/officer_details.rb +12 -0
- data/lib/companies_house_gateway/checks/officer_search.rb +16 -0
- data/lib/companies_house_gateway/client.rb +45 -0
- data/lib/companies_house_gateway/config.rb +31 -0
- data/lib/companies_house_gateway/constants.rb +8 -0
- data/lib/companies_house_gateway/errors/companies_house_gateway_error.rb +18 -0
- data/lib/companies_house_gateway/request.rb +105 -0
- data/lib/companies_house_gateway/util.rb +20 -0
- data/lib/companies_house_gateway/version.rb +3 -0
- data/spec/checks/company_appointments_spec.rb +16 -0
- data/spec/checks/company_details_spec.rb +10 -0
- data/spec/checks/document_info_spec.rb +16 -0
- data/spec/checks/document_spec.rb +11 -0
- data/spec/checks/filing_history_spec.rb +10 -0
- data/spec/checks/mortgages_spec.rb +16 -0
- data/spec/checks/name_search_spec.rb +10 -0
- data/spec/checks/number_search_spec.rb +10 -0
- data/spec/checks/officer_details_spec.rb +11 -0
- data/spec/checks/officer_search_spec.rb +11 -0
- data/spec/client_spec.rb +58 -0
- data/spec/companies_house_gateway_spec.rb +49 -0
- data/spec/fixtures/checks/chbase.xsd +1037 -0
- data/spec/fixtures/checks/company_appointments.xsd +74 -0
- data/spec/fixtures/checks/company_details.xsd +108 -0
- data/spec/fixtures/checks/document.xsd +56 -0
- data/spec/fixtures/checks/document_info.xsd +56 -0
- data/spec/fixtures/checks/filing_history.xsd +77 -0
- data/spec/fixtures/checks/mortgages.xsd +58 -0
- data/spec/fixtures/checks/name_search.xsd +41 -0
- data/spec/fixtures/checks/number_search.xsd +29 -0
- data/spec/fixtures/checks/officer_details.xsd +99 -0
- data/spec/fixtures/checks/officer_search.xsd +37 -0
- data/spec/fixtures/request.xsd +290 -0
- data/spec/request_spec.rb +77 -0
- data/spec/shared_examples.rb +40 -0
- data/spec/spec_helper.rb +17 -0
- metadata +206 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
module CompaniesHouseGateway
|
2
|
+
class Config
|
3
|
+
DEFAULT_OPTIONS = {
|
4
|
+
adapter: Faraday.default_adapter,
|
5
|
+
sender_id: nil,
|
6
|
+
password: nil,
|
7
|
+
email: nil,
|
8
|
+
raw: false,
|
9
|
+
api_endpoint: "http://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/Gateway",
|
10
|
+
user_agent: "CompaniesHouseGateway Ruby Gem #{CompaniesHouseGateway::VERSION}".freeze
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@config = {}
|
15
|
+
yield self if block_given?
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](name)
|
19
|
+
@config.fetch(name, DEFAULT_OPTIONS[name])
|
20
|
+
end
|
21
|
+
|
22
|
+
def []=(name, val)
|
23
|
+
@config[name] = val
|
24
|
+
end
|
25
|
+
|
26
|
+
def clone
|
27
|
+
Config.new { |config| @config.each { |k,v| config[k] = v } }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module CompaniesHouseGateway
|
2
|
+
module Constants
|
3
|
+
# Check types suported by the Companies House XML Gateway
|
4
|
+
SUPPORTED_REQUESTS = %w(NameSearch NumberSearch CompanyAppointments
|
5
|
+
CompanyDetails OfficerSearch OfficerDetails
|
6
|
+
Mortgages FilingHistory DocumentInfo Document)
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module CompaniesHouseGateway
|
2
|
+
class CompaniesHouseGatewayError < StandardError
|
3
|
+
attr_reader :message
|
4
|
+
attr_reader :status
|
5
|
+
attr_reader :response_body
|
6
|
+
|
7
|
+
def initialize(message=nil, status=nil, response=nil)
|
8
|
+
@message = message
|
9
|
+
@status = status
|
10
|
+
@response_body = response_body
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
status_string = @status.nil? ? "" : "(Status #{@status}) "
|
15
|
+
"#{status_string}#{@message}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module CompaniesHouseGateway
|
2
|
+
class Request
|
3
|
+
def initialize(connection, config)
|
4
|
+
@connection = connection
|
5
|
+
@config = config
|
6
|
+
end
|
7
|
+
|
8
|
+
# Perform a check
|
9
|
+
def perform(request_type, request_data = {})
|
10
|
+
request_type = Util.camelize(request_type)
|
11
|
+
unless Constants::SUPPORTED_REQUESTS.include?(request_type)
|
12
|
+
msg = "Unsupported request type #{request_type}"
|
13
|
+
raise CompaniesHouseGatewayError.new(msg)
|
14
|
+
end
|
15
|
+
|
16
|
+
response = @connection.post do |request|
|
17
|
+
request.path = @config[:api_endpoint]
|
18
|
+
request.body = build_request_xml(request_type, request_data).to_s
|
19
|
+
end
|
20
|
+
@config[:raw] ? response : response.body
|
21
|
+
rescue Faraday::Error::ClientError => e
|
22
|
+
raise CompaniesHouseGatewayError.new(e.response[:body],
|
23
|
+
e.response[:status],
|
24
|
+
e.response)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Compile the complete XML request to send to Companies House
|
28
|
+
def build_request_xml(request_type, request_data={})
|
29
|
+
transaction_id = (Time.now.to_f * 100).to_i
|
30
|
+
|
31
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
32
|
+
xml.GovTalkMessage(header_namespace) do
|
33
|
+
xml.EnvelopeVersion "2.0"
|
34
|
+
xml.Header do
|
35
|
+
message_details(xml, request_type, transaction_id)
|
36
|
+
authentication(xml, transaction_id)
|
37
|
+
end
|
38
|
+
xml.GovTalkDetails
|
39
|
+
xml.Body do
|
40
|
+
request_body(xml, request_type, request_data)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
builder.doc
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def header_namespace
|
50
|
+
{
|
51
|
+
'xmlns' => "http://www.govtalk.gov.uk/CM/envelope",
|
52
|
+
'xmlns:dsig' => "http://www.w3.org/2000/09/xmldsig#",
|
53
|
+
'xmlns:gt' => "http://www.govtalk.gov.uk/CM/core",
|
54
|
+
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
|
55
|
+
'xsi:schemaLocation' => "http://www.govtalk.gov.uk/CM/envelope " +
|
56
|
+
"http://xmlgw.companieshouse.gov.uk/v1-1/schema/Egov_ch-v2-0.xsd"
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def message_details(xml, request_type, transaction_id)
|
61
|
+
xml.MessageDetails do
|
62
|
+
xml.Class request_type
|
63
|
+
xml.Qualifier "request"
|
64
|
+
xml.TransactionID transaction_id
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def authentication(xml, transaction_id)
|
69
|
+
xml.SenderDetails do
|
70
|
+
xml.IDAuthentication do
|
71
|
+
xml.SenderID @config[:sender_id]
|
72
|
+
xml.Authentication do
|
73
|
+
xml.Method "CHMD5"
|
74
|
+
xml.Value create_digest(transaction_id)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
xml.EmailAddress @config[:email] if @config[:email]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def request_body(xml, request_type, search_data)
|
82
|
+
xml.send("#{request_type}Request", request_namespace(request_type)) do
|
83
|
+
search_data.each do |key, value|
|
84
|
+
if value
|
85
|
+
element_name = Util.camelize(key).sub(/Id\z/, "ID")
|
86
|
+
xml.send(element_name, value)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def request_namespace(request_type)
|
93
|
+
{
|
94
|
+
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
|
95
|
+
'xsi:schemaLocation' => "http://xmlgw.companieshouse.gov.uk/v1-0/schema " +
|
96
|
+
"http://xmlgw.companieshouse.gov.uk/v1-0/schema/#{request_type}.xsd"
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
def create_digest(transaction_id)
|
101
|
+
creds = "#{@config[:sender_id]}#{@config[:password]}#{transaction_id}"
|
102
|
+
Digest::MD5.hexdigest(creds)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CompaniesHouseGateway
|
2
|
+
module Util
|
3
|
+
extend self
|
4
|
+
# String helper
|
5
|
+
def camelize(str)
|
6
|
+
str.to_s.split('_').map(&:capitalize).join
|
7
|
+
end
|
8
|
+
|
9
|
+
def underscore(str)
|
10
|
+
str.to_s.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
11
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
12
|
+
tr("-", "_").
|
13
|
+
downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
def demodulize(str)
|
17
|
+
str.to_s.split('::').last
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CompaniesHouseGateway::Checks::CompanyAppointments do
|
4
|
+
describe "#perform" do
|
5
|
+
let(:check_data) do
|
6
|
+
{ company_name: "GoCardless",
|
7
|
+
company_number: "07495895",
|
8
|
+
user_reference: 1 }
|
9
|
+
end
|
10
|
+
|
11
|
+
it_behaves_like "it generates_valid_xml"
|
12
|
+
it_behaves_like "it validates presence", :company_number
|
13
|
+
it_behaves_like "it validates presence", :company_name
|
14
|
+
it_behaves_like "it validates presence", :user_reference
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CompaniesHouseGateway::Checks::CompanyDetails do
|
4
|
+
describe "#perform" do
|
5
|
+
let(:check_data) { { company_number: "07495895" } }
|
6
|
+
|
7
|
+
it_behaves_like "it generates_valid_xml"
|
8
|
+
it_behaves_like "it validates presence", :company_number
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CompaniesHouseGateway::Checks::DocumentInfo do
|
4
|
+
describe "#perform" do
|
5
|
+
let(:check_data) do
|
6
|
+
{ company_number: "07495895",
|
7
|
+
company_name: "GoCardless",
|
8
|
+
image_key: "asd121a" }
|
9
|
+
end
|
10
|
+
|
11
|
+
it_behaves_like "it generates_valid_xml"
|
12
|
+
it_behaves_like "it validates presence", :company_name
|
13
|
+
it_behaves_like "it validates presence", :company_number
|
14
|
+
it_behaves_like "it validates presence", :image_key
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CompaniesHouseGateway::Checks::Document do
|
4
|
+
describe "#perform" do
|
5
|
+
let(:check_data) { { doc_request_key: "als123lkj123", user_reference: 1 } }
|
6
|
+
|
7
|
+
it_behaves_like "it generates_valid_xml"
|
8
|
+
it_behaves_like "it validates presence", :doc_request_key
|
9
|
+
it_behaves_like "it validates presence", :user_reference
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CompaniesHouseGateway::Checks::FilingHistory do
|
4
|
+
describe "#perform" do
|
5
|
+
let(:check_data) { { company_number: "07495895" } }
|
6
|
+
|
7
|
+
it_behaves_like "it generates_valid_xml"
|
8
|
+
it_behaves_like "it validates presence", :company_number
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CompaniesHouseGateway::Checks::Mortgages do
|
4
|
+
describe "#perform" do
|
5
|
+
let(:check_data) do
|
6
|
+
{ company_name: "GoCardless",
|
7
|
+
company_number: "07495895",
|
8
|
+
user_reference: "asd121a" }
|
9
|
+
end
|
10
|
+
|
11
|
+
it_behaves_like "it generates_valid_xml"
|
12
|
+
it_behaves_like "it validates presence", :company_name
|
13
|
+
it_behaves_like "it validates presence", :company_number
|
14
|
+
it_behaves_like "it validates presence", :user_reference
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CompaniesHouseGateway::Checks::NameSearch do
|
4
|
+
describe "#perform" do
|
5
|
+
let(:check_data) { { company_name: "GoCardless", data_set: "LIVE" } }
|
6
|
+
|
7
|
+
it_behaves_like "it generates_valid_xml"
|
8
|
+
it_behaves_like "it validates presence", :company_name
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CompaniesHouseGateway::Checks::NumberSearch do
|
4
|
+
describe "#perform" do
|
5
|
+
let(:check_data) { { partial_company_number: "123", data_set: "LIVE" } }
|
6
|
+
|
7
|
+
it_behaves_like "it generates_valid_xml"
|
8
|
+
it_behaves_like "it validates presence", :partial_company_number
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CompaniesHouseGateway::Checks::OfficerDetails do
|
4
|
+
describe "#perform" do
|
5
|
+
let(:check_data) { { person_id: "alsdkj123", user_reference: 1 } }
|
6
|
+
|
7
|
+
it_behaves_like "it generates_valid_xml"
|
8
|
+
it_behaves_like "it validates presence", :person_id
|
9
|
+
it_behaves_like "it validates presence", :user_reference
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CompaniesHouseGateway::Checks::OfficerSearch do
|
4
|
+
describe "#perform" do
|
5
|
+
let(:check_data) { { surname: "Baker", officer_type: "DIS" } }
|
6
|
+
|
7
|
+
it_behaves_like "it generates_valid_xml"
|
8
|
+
it_behaves_like "it validates presence", :surname
|
9
|
+
it_behaves_like "it validates presence", :officer_type
|
10
|
+
end
|
11
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples "it delegates to the check" do |method_name|
|
4
|
+
it "delegates #{method_name} to " +
|
5
|
+
"#{CompaniesHouseGateway::Util.camelize(method_name)}" do
|
6
|
+
expect_any_instance_of(CompaniesHouseGateway::Checks.
|
7
|
+
const_get(CompaniesHouseGateway::Util.camelize(method_name))).
|
8
|
+
to receive(:perform).once
|
9
|
+
client.send(method_name, {})
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe CompaniesHouseGateway::Client do
|
14
|
+
let(:client) { CompaniesHouseGateway::Client.new(config) }
|
15
|
+
let(:config) { CompaniesHouseGateway::Config.new }
|
16
|
+
|
17
|
+
describe "#new" do
|
18
|
+
context "without a config" do
|
19
|
+
before { configure_companies_house_gateway }
|
20
|
+
subject(:new_client) { CompaniesHouseGateway::Client.new }
|
21
|
+
|
22
|
+
its(:config) { should_not == CompaniesHouseGateway.config }
|
23
|
+
it "has the attributes of the global config" do
|
24
|
+
new_client.config[:sender_id] ==
|
25
|
+
CompaniesHouseGateway.config[:sender_id]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "with a config" do
|
30
|
+
before { config[:first_name] = "test" }
|
31
|
+
subject(:new_client) { CompaniesHouseGateway::Client.new(config) }
|
32
|
+
|
33
|
+
its(:config) { should_not == config }
|
34
|
+
it "has the attributes of the passed in config" do
|
35
|
+
new_client.config[:sender_id] == config[:sender_id]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#perform_check" do
|
41
|
+
it "delegates to an instance of Request" do
|
42
|
+
expect_any_instance_of(CompaniesHouseGateway::Request).
|
43
|
+
to receive(:perform).once
|
44
|
+
client.perform_check({})
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it_behaves_like "it delegates to the check", :name_search
|
49
|
+
it_behaves_like "it delegates to the check", :number_search
|
50
|
+
it_behaves_like "it delegates to the check", :company_appointments
|
51
|
+
it_behaves_like "it delegates to the check", :company_details
|
52
|
+
it_behaves_like "it delegates to the check", :officer_search
|
53
|
+
it_behaves_like "it delegates to the check", :officer_details
|
54
|
+
it_behaves_like "it delegates to the check", :mortgages
|
55
|
+
it_behaves_like "it delegates to the check", :filing_history
|
56
|
+
it_behaves_like "it delegates to the check", :document_info
|
57
|
+
it_behaves_like "it delegates to the check", :document
|
58
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples "it delegates to the client" do |method_name|
|
4
|
+
before { configure_companies_house_gateway }
|
5
|
+
let(:data) { "data" }
|
6
|
+
|
7
|
+
it "delegates #{method_name} to the client" do
|
8
|
+
CompaniesHouseGateway::Client.any_instance.
|
9
|
+
should_receive(method_name).with(data)
|
10
|
+
CompaniesHouseGateway.send(method_name, data)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe CompaniesHouseGateway do
|
15
|
+
before { CompaniesHouseGateway.instance_variable_set(:@config, nil) }
|
16
|
+
|
17
|
+
describe '#configure' do
|
18
|
+
subject { CompaniesHouseGateway.config }
|
19
|
+
CompaniesHouseGateway::Config::DEFAULT_OPTIONS.keys.each do |key|
|
20
|
+
context "setting #{key}" do
|
21
|
+
before do
|
22
|
+
CompaniesHouseGateway.configure { |config| config[key] = key }
|
23
|
+
end
|
24
|
+
its([key]) { should == key }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#config" do
|
30
|
+
subject(:config) { CompaniesHouseGateway.config }
|
31
|
+
|
32
|
+
it "raises an error if CompaniesHouseGateway hasn't been configured" do
|
33
|
+
expect { config }.
|
34
|
+
to raise_error CompaniesHouseGateway::CompaniesHouseGatewayError
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it_behaves_like "it delegates to the client", :perform_check
|
39
|
+
it_behaves_like "it delegates to the client", :name_search
|
40
|
+
it_behaves_like "it delegates to the client", :number_search
|
41
|
+
it_behaves_like "it delegates to the client", :company_appointments
|
42
|
+
it_behaves_like "it delegates to the client", :company_details
|
43
|
+
it_behaves_like "it delegates to the client", :officer_search
|
44
|
+
it_behaves_like "it delegates to the client", :officer_details
|
45
|
+
it_behaves_like "it delegates to the client", :mortgages
|
46
|
+
it_behaves_like "it delegates to the client", :filing_history
|
47
|
+
it_behaves_like "it delegates to the client", :document_info
|
48
|
+
it_behaves_like "it delegates to the client", :document
|
49
|
+
end
|