Module: NFGClient::Utils

Included in:
Client
Defined in:
lib/nfg-client/utils.rb

Constant Summary collapse

@@nfg_urls =
{
  'sandbox' => {
    'host' => 'api-sandbox.networkforgood.org',
    'url' => 'https://api-sandbox.networkforgood.org/PartnerDonationService/DonationServices.asmx',
    'wsdl' => 'https://api-sandbox.networkforgood.org/PartnerDonationService/DonationServices.asmx?wsdl'
  },
  'production' => {
    'host' => 'api.networkforgood.org',
    'url' => 'https://api.networkforgood.org/PartnerDonationService/DonationServices.asmx',
    'wsdl' => 'https://api.networkforgood.org/PartnerDonationService/DonationServices.asmx?wsdl'
  }
}

Instance Method Summary collapse

Instance Method Details

#build_nfg_soap_request(nfg_method, params) ⇒ Object

Returns a complete NFG SOAP request based on the provided target method and params



59
60
61
# File 'lib/nfg-client/utils.rb', line 59

def build_nfg_soap_request(nfg_method, params)
  get_nfg_soap_request_template.gsub('|body|',"<#{nfg_method} xmlns=\"http://api.networkforgood.org/partnerdonationservice\">#{hash_to_xml(params)}</#{nfg_method}>")
end

#encode_if_text(item) ⇒ Object

HTML Encodes the string if it is text, otherwise, leaves it as is



147
148
149
150
151
152
153
# File 'lib/nfg-client/utils.rb', line 147

def encode_if_text(item)
  if item.respond_to?(:gsub)
    CGI.escapeHTML(item)
  else
    item
  end
end

#format_headers(nfg_method, soap_request) ⇒ Object

Returns NFG friendly headers hash for HTTPS post

Arguments:

nfg_method: (String)
soap_request: (String)


112
113
114
115
116
117
118
119
# File 'lib/nfg-client/utils.rb', line 112

def format_headers(nfg_method, soap_request)
  {
    'Host' => host,
    'Content-Type' => 'application/soap+xml; charset=utf-8',
    'Content-Length' => soap_request.length.to_s,
    'SOAPAction' => "#{url}/#{nfg_method}".gsub('.asmx','')
  }
end

#get_nfg_soap_request_templateObject

Returns a SOAP template with no body



91
92
93
# File 'lib/nfg-client/utils.rb', line 91

def get_nfg_soap_request_template
  "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\"><soap12:Body>|body|</soap12:Body></soap12:Envelope>"
end

#hash_to_xml(hash) ⇒ Object

Returns a string containing an XML representation of the given hash

Arguments:

hash: (Hash)


137
138
139
140
141
142
143
144
# File 'lib/nfg-client/utils.rb', line 137

def hash_to_xml(hash)
  hash.map do |k, v|
    text = (v.is_a? Hash) ? hash_to_xml(v) : encode_if_text(v)
    # It removes the digits at the end of each "DonationItem" hash key
    xml_elem = (v.is_a? Hash) ? k.to_s.gsub(/(\d)/, "") : k
    "<%s>%s</%s>" % [xml_elem, text, xml_elem]
  end.join
end

#hostObject

Returns NFG target host



122
123
124
125
# File 'lib/nfg-client/utils.rb', line 122

def host
  return @@nfg_urls['sandbox']['host'] if @use_sandbox
  @@nfg_urls['production']['host']
end

#nfg_soap_request(nfg_method, params) ⇒ Object

Makes HTTP POST request to NFG server (sandbox or production) and returns parsed XML response.

Arguments:

nfg_method: (String)
params: (Hash)


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/nfg-client/utils.rb', line 26

def nfg_soap_request(nfg_method, params)
  @logger = defined?(Rails) ? Rails.logger : ::Logger.new(STDOUT)
  if (nfg_method.is_a? String) && (params.is_a? Hash)

    # Build SOAP 1.2 request
    soap_request = build_nfg_soap_request(nfg_method, params)

    headers = format_headers(nfg_method, soap_request)

    @logger.info headers
    @logger.info soap_request
    # Being HTTP Post
    begin
      response = ssl_post(soap_request, headers)
      @logger.info " nfg_soap_request succeeded: #{ response.body.inspect }"
      return_value = parse_result(response.code, response.body, response.message, nfg_method)
    rescue StandardError => e
      @logger.error " nfg_soap_request failed: #{ e.message }"
      @logger.error e.backtrace.join(' ')

      return_value = Hash.new
      return_value['StatusCode'] = 'UnexpectedError'
      return_value['Message'] = e
      return_value['ErrorDetails'] = e.backtrace.join(' ')
    end

    return_value
  else
    raise ArgumentError.new('http_post requires a nfg_method and a hash of params')
  end
end

#parse_result(code, body, message, nfg_method) ⇒ Object

Parses the response code and body and returns and appropriate result hash

Arguments:

code: (String)
body: (XML string)
message: string
nfg_method: string


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/nfg-client/utils.rb', line 70

def parse_result(code, body, message, nfg_method)
  return_value = Hash.new
  if code == '200'
    parsed = REXML::Document.new(body)
    # Build return hash parsing XML response
    if parsed.root.nil?
      return_value['StatusCode'] = 'MissingParameter'
      return_value['Message'] = body
      return_value['ErrorDetails'] = nil
    else
      return_value = parsed.root.elements['soap:Body'].elements["#{nfg_method}Response"].elements["#{nfg_method}Result"]
    end
  else
    return_value['StatusCode'] = 'UnexpectedError'
    return_value['Message'] = message
    return_value['ErrorDetails'] = body
  end
  return_value
end

#requires!(hash, *params) ⇒ Object

Raises an exception if the required params are not part of the given hash

Arguments:

hash: (Hash)
*params: (Array or Symbol)


160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/nfg-client/utils.rb', line 160

def requires!(hash, *params)
  params.each do |param|
    if param.is_a?(Array)
      raise ArgumentError.new("Missing required parameter: #{param.first}") unless hash.has_key?(param.first) || hash.has_key?(param.first.to_s)

      valid_options = param[1..-1]
      raise ArgumentError.new("Parameter: #{param.first} must be one of #{valid_options.to_sentence(:words_connector => 'or')}") unless valid_options.include?(hash[param.first]) || valid_options.include?(hash[param.first.to_s])
    else
      raise ArgumentError.new("Missing required parameter: #{param}") unless hash.has_key?(param) || hash.has_key?(param.to_s)
    end
  end
end

#ssl_post(soap_request, headers) ⇒ Object

Makes HTTPS post request with given body (soap_request) and headers

Arguments:

soap_request: (String)
headers: (Hash)


100
101
102
103
104
105
# File 'lib/nfg-client/utils.rb', line 100

def ssl_post(soap_request, headers)
   uri = URI.parse(url)
   https_conn = Net::HTTP.new(uri.host, uri.port)
   https_conn.use_ssl = true
   https_conn.post(uri.path, soap_request, headers)
end

#urlObject

Returns NFG target URL



128
129
130
131
# File 'lib/nfg-client/utils.rb', line 128

def url
  return @@nfg_urls['sandbox']['url'] if @use_sandbox
  @@nfg_urls['production']['url']
end