companies-house-gateway 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/CHANGELOG.md +20 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +22 -0
  6. data/README.md +28 -0
  7. data/companies_house_gateway.gemspec +22 -0
  8. data/lib/companies_house_gateway.rb +60 -0
  9. data/lib/companies_house_gateway/checks/check.rb +66 -0
  10. data/lib/companies_house_gateway/checks/company_appointments.rb +14 -0
  11. data/lib/companies_house_gateway/checks/company_details.rb +11 -0
  12. data/lib/companies_house_gateway/checks/document.rb +10 -0
  13. data/lib/companies_house_gateway/checks/document_info.rb +11 -0
  14. data/lib/companies_house_gateway/checks/filing_history.rb +12 -0
  15. data/lib/companies_house_gateway/checks/mortgages.rb +16 -0
  16. data/lib/companies_house_gateway/checks/name_search.rb +17 -0
  17. data/lib/companies_house_gateway/checks/number_search.rb +13 -0
  18. data/lib/companies_house_gateway/checks/officer_details.rb +12 -0
  19. data/lib/companies_house_gateway/checks/officer_search.rb +16 -0
  20. data/lib/companies_house_gateway/client.rb +45 -0
  21. data/lib/companies_house_gateway/config.rb +31 -0
  22. data/lib/companies_house_gateway/constants.rb +8 -0
  23. data/lib/companies_house_gateway/errors/companies_house_gateway_error.rb +18 -0
  24. data/lib/companies_house_gateway/request.rb +105 -0
  25. data/lib/companies_house_gateway/util.rb +20 -0
  26. data/lib/companies_house_gateway/version.rb +3 -0
  27. data/spec/checks/company_appointments_spec.rb +16 -0
  28. data/spec/checks/company_details_spec.rb +10 -0
  29. data/spec/checks/document_info_spec.rb +16 -0
  30. data/spec/checks/document_spec.rb +11 -0
  31. data/spec/checks/filing_history_spec.rb +10 -0
  32. data/spec/checks/mortgages_spec.rb +16 -0
  33. data/spec/checks/name_search_spec.rb +10 -0
  34. data/spec/checks/number_search_spec.rb +10 -0
  35. data/spec/checks/officer_details_spec.rb +11 -0
  36. data/spec/checks/officer_search_spec.rb +11 -0
  37. data/spec/client_spec.rb +58 -0
  38. data/spec/companies_house_gateway_spec.rb +49 -0
  39. data/spec/fixtures/checks/chbase.xsd +1037 -0
  40. data/spec/fixtures/checks/company_appointments.xsd +74 -0
  41. data/spec/fixtures/checks/company_details.xsd +108 -0
  42. data/spec/fixtures/checks/document.xsd +56 -0
  43. data/spec/fixtures/checks/document_info.xsd +56 -0
  44. data/spec/fixtures/checks/filing_history.xsd +77 -0
  45. data/spec/fixtures/checks/mortgages.xsd +58 -0
  46. data/spec/fixtures/checks/name_search.xsd +41 -0
  47. data/spec/fixtures/checks/number_search.xsd +29 -0
  48. data/spec/fixtures/checks/officer_details.xsd +99 -0
  49. data/spec/fixtures/checks/officer_search.xsd +37 -0
  50. data/spec/fixtures/request.xsd +290 -0
  51. data/spec/request_spec.rb +77 -0
  52. data/spec/shared_examples.rb +40 -0
  53. data/spec/spec_helper.rb +17 -0
  54. 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,3 @@
1
+ module CompaniesHouseGateway
2
+ VERSION = '0.2.0'.freeze
3
+ 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
@@ -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