Module: Europe::Vat

Defined in:
lib/europe/vat/vat.rb,
lib/europe/vat/rates.rb,
lib/europe/vat/format.rb

Overview

VAT

Defined Under Namespace

Modules: Format, Rates

Constant Summary collapse

WSDL =
'http://ec.europa.eu/taxation_customs/vies/' \
'services/checkVatService'
HEADERS =
{
  'Content-Type' => 'text/xml;charset=UTF-8',
  'SOAPAction' => ''
}.freeze
BODY =
"  <soapenv:Envelope\n  xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n  xmlns:urn=\"urn:ec.europa.eu:taxud:vies:services:checkVat:types\">\n    <soapenv:Header/>\n    <soapenv:Body>\n       <urn:checkVat>\n          <urn:countryCode>{COUNTRY_CODE}</urn:countryCode>\n          <urn:vatNumber>{NUMBER}</urn:vatNumber>\n       </urn:checkVat>\n    </soapenv:Body>\n  </soapenv:Envelope>\n"

Class Method Summary collapse

Class Method Details

.charge_vat?(origin_country, number) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
81
82
83
# File 'lib/europe/vat/vat.rb', line 78

def self.charge_vat?(origin_country, number)
  return false if number.nil? || number.empty?

  Europe::Vat::Fromat::VAT_REGEX.key?(origin_country.to_sym) ||
    Europe::Vat::Fromat::VAT_REGEX.key?(number[0..1].to_sym)
end

.convert_date(date) ⇒ Object



68
69
70
71
72
# File 'lib/europe/vat/vat.rb', line 68

def self.convert_date(date)
  return unless date

  Date.parse(date)
end

.extract_data(body, position) ⇒ Object



74
75
76
# File 'lib/europe/vat/vat.rb', line 74

def self.extract_data(body, position)
  body[position]&.text
end

.response_xml(response) ⇒ Object



63
64
65
66
# File 'lib/europe/vat/vat.rb', line 63

def self.response_xml(response)
  xml = REXML::Document.new(response.body)
  xml.elements.first.elements[2].elements[1]
end

.send_request(country_code, number) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/europe/vat/vat.rb', line 85

def self.send_request(country_code, number)
  uri = URI.parse(WSDL)

  body = BODY.dup.gsub('{COUNTRY_CODE}', country_code)
  body = body.gsub('{NUMBER}', number)

  # Create the HTTP objects
  http = Net::HTTP.new(uri.host, uri.port)
  request = Net::HTTP::Post.new(uri.request_uri, HEADERS)
  request.body = body

  # Send the request
  http.request(request)
end

.setup_response(response) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
# File 'lib/europe/vat/vat.rb', line 51

def self.setup_response(response)
  body = response_xml(response)
  {
    valid: extract_data(body, 3) == 'true',
    country_code: extract_data(body, 0),
    vat_number: extract_data(body, 1),
    request_date: convert_date(extract_data(body, 2)),
    name: extract_data(body, 4),
    address: extract_data(body, 5)
  }
end

.validate(number) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/europe/vat/vat.rb', line 35

def self.validate(number)
  return :failed if number.size < 4

  response = send_request(number[0..1], number[2..-1])
  return :failed unless response.is_a? Net::HTTPSuccess
  return :failed if response.body.include?('soap:Fault')
  return :timeout if response.body.include?('TIMEOUT')
  return :timeout if response.body.include?('MS_MAX_CONCURRENT_REQ')

  setup_response(response)
rescue Net::OpenTimeout
  :timeout
rescue Net::HTTPServerError
  :server_error
end