Class: OrangeData::Transport

Inherits:
Object
  • Object
show all
Defined in:
lib/orange_data/transport.rb

Overview

handles low-level http requests to orangedata, including auth

Defined Under Namespace

Classes: CorrectionIntermediateResult, IntermediateResult, ReceiptIntermediateResult, RequestSignatureMiddleware

Constant Summary collapse

DEFAULT_TEST_API_URL =
"https://apip.orangedata.ru:2443/api/v2/"
DEFAULT_PRODUCTION_API_URL =
"https://api.orangedata.ru:12003/api/v2/"

Instance Method Summary collapse

Constructor Details

#initialize(api_url = DEFAULT_TEST_API_URL, credentials = Credentials.default_test) ⇒ Transport

Returns a new instance of Transport.

Raises:

  • (ArgumentError)


15
16
17
18
19
20
# File 'lib/orange_data/transport.rb', line 15

def initialize(api_url=DEFAULT_TEST_API_URL, credentials=Credentials.default_test)
  raise ArgumentError, "Need full credentials for connection" unless credentials.valid?

  @credentials = credentials
  @api_url = api_url
end

Instance Method Details

#get_correction(inn, document_id) ⇒ Object



211
212
213
# File 'lib/orange_data/transport.rb', line 211

def get_correction(inn, document_id)
  CorrectionResult.from_hash(get_entity("corrections/#{inn}/status/#{document_id}"))
end

#get_document(inn, document_id) ⇒ Object



203
204
205
# File 'lib/orange_data/transport.rb', line 203

def get_document(inn, document_id)
  ReceiptResult.from_hash(get_entity("documents/#{inn}/status/#{document_id}"))
end

#get_entity(sub_url) ⇒ Object



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/orange_data/transport.rb', line 161

def get_entity(sub_url)
  res = transport.get(sub_url)

  case res.status
  when 200
    return res.body
  when 202
    # not processed yet
    return nil
  when 400
    raise "Cannot get doc: #{res.body['errors'] || res.body}"
  when 401
    raise 'Unauthorized'
  end
end

#pingObject

Below actual methods from api



179
180
181
182
183
184
# File 'lib/orange_data/transport.rb', line 179

def ping
  res = transport.get(''){|r| r.headers['Accept'] = 'text/plain' }
  res.status == 200 && res.body == "Nebula.Api v2"
rescue StandardError => _e
  return false
end

#post_correction(data, raise_errors: true) ⇒ Object



207
208
209
# File 'lib/orange_data/transport.rb', line 207

def post_correction(data, raise_errors:true)
  post_entity 'corrections', data, raise_errors:raise_errors, result_class:CorrectionIntermediateResult
end

#post_document(data, raise_errors: true) ⇒ Object



199
200
201
# File 'lib/orange_data/transport.rb', line 199

def post_document(data, raise_errors:true)
  post_entity 'documents', data, raise_errors:raise_errors, result_class:ReceiptIntermediateResult
end

#post_document_validate(data) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/orange_data/transport.rb', line 186

def post_document_validate(data)
  res = post_request 'validateDocument', data

  case res.status
  when 200
    return true
  when 400
    return res.body["errors"]
  else
    raise "Unexpected response: #{res.status} #{res.reason_phrase}"
  end
end

#post_entity(sub_url, data, raise_errors: true, result_class: IntermediateResult, retry_count: 0) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/orange_data/transport.rb', line 127

def post_entity(sub_url, data, raise_errors:true, result_class:IntermediateResult, retry_count:0)
  res = post_request(sub_url, data)

  case res.status
  when 201
    return result_class.new(success: true, data:data, sub_url:sub_url, retry_count:retry_count, transport:self)
  when 409
    raise "Conflict" if raise_errors

    return result_class.new(data:data, sub_url:sub_url, errors:["Duplicate id"], retry_count:retry_count)
  when 400
    raise "Invalid doc: #{res.body['errors'] || res.body}" if raise_errors

    return result_class.new(data:data, sub_url:sub_url, errors:res.body['errors'], retry_count:retry_count)
  when 503
    if res.headers['Retry-After']
      raise "Document queue full, retry in #{res.headers['Retry-After']}" if raise_errors

      return result_class.new(
        attempt_retry: true,
        retry_in: res.headers['Retry-After'].to_i,
        data: data,
        sub_url: sub_url,
        retry_count: retry_count,
        transport: self
      )
    end
  end

  raise "Unknown code from OD: #{res.status} #{res.reason_phrase} #{res.body}" if raise_errors

  result_class.new(attempt_retry:true, data:data, sub_url:sub_url, retry_count:0, transport:self)
end

#post_request(method, data) ⇒ Object



60
61
62
63
64
65
66
67
# File 'lib/orange_data/transport.rb', line 60

def post_request(method, data)
  raw_post(method, data).tap{|resp|
    if resp.status == 401
      # TODO: better exceptions
      raise 'Unauthorized'
    end
  }
end

#raw_post(method, data) ⇒ Object



56
57
58
# File 'lib/orange_data/transport.rb', line 56

def raw_post(method, data)
  transport.post(method, data)
end

#transportObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/orange_data/transport.rb', line 39

def transport
  @transport ||= Faraday.new(
    url: @api_url,
    ssl: {
      client_cert: @credentials.certificate,
      client_key: @credentials.certificate_key,
    }
  ) do |conn|
    conn.headers['User-Agent'] = "OrangeDataRuby/#{OrangeData::VERSION}"
    conn.headers['Accept'] = "application/json"
    conn.request(:json)
    conn.use(RequestSignatureMiddleware, @credentials.signature_key)
    conn.response :json, content_type: /\bjson$/
    conn.adapter(Faraday.default_adapter)
  end
end