loco_bill 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,16 @@
1
+ An interface for interacting with Bill.com's API. Expects the following constants to be set (in environment.rb or an initializer or what have you):
2
+
3
+ BILL_API_APPLICATION_KEY
4
+ BILL_API_USERNAME
5
+ BILL_API_PASSWORD
6
+ BILL_API_ORG_ID
7
+
8
+ Requires Nokogiri.
9
+
10
+ Use like so:
11
+
12
+ login = LocoBill.login
13
+ login.result.inspect => #<BillApi::RequestResult status="OK", sessionId="xxx", orgID="yyy">
14
+
15
+ vendor = BillApi.create_vendor :vendor => {:name => 'Test'} # will auto-login for you, if you're not already logged in
16
+ vendor.result.inspect => #<BillApi::RequestResult transactionId="Transaction1", status="OK", id="xxy">
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'loco_bill'
@@ -0,0 +1,5 @@
1
+ module LocoBill
2
+ def self.login
3
+ Request.new(:login, :username => BILL_API_USERNAME, :password => BILL_API_PASSWORD, :orgID => BILL_API_ORG_ID)
4
+ end
5
+ end
@@ -0,0 +1,100 @@
1
+ module LocoBill
2
+ class Request
3
+ attr_accessor :result
4
+ @@api_domain = 'api.bill.com'
5
+ @@api_endpoint = "/crudApi"
6
+ @@session_id = nil
7
+ @@transaction_id = 0
8
+ NON_OPERATION_WRAPPED_ACTIONS = [:login, :logout, :getorglist]
9
+ INLINE_PARAMS_ACTIONS = {:get_list => :object}
10
+
11
+ def initialize(action, params={})
12
+ @action = action.to_sym
13
+ # auto-login & grab session id if we don't already have one.
14
+ if @@session_id.nil? && @action != :login
15
+ @@session_id = LocoBill.login.result.sessionId
16
+ end
17
+ @params = params
18
+ @result = process_response(api(build_request_xml))
19
+ end
20
+
21
+ def build_request_xml
22
+ operation_wrapped = !NON_OPERATION_WRAPPED_ACTIONS.include?(@action)
23
+
24
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
25
+ xml.request(:version => '1.0', :applicationkey => BILL_API_APPLICATION_KEY) {
26
+ if operation_wrapped
27
+ # gotta wrap most of the api calls in an "operation" block with a transaction id & session id
28
+ xml.operation(:transactionId => transaction_id, :sessionId => @@session_id) { action_xml(xml) }
29
+ else
30
+ action_xml(xml)
31
+ end
32
+ }
33
+ end.to_xml
34
+ end
35
+
36
+ # called from build_request_xml, just the xml related to the action we're doing
37
+ # TODO: refactor into a method that takes a wrapper &block
38
+ def action_xml(xml)
39
+ inline_params = INLINE_PARAMS_ACTIONS.has_key?(@action) ? {INLINE_PARAMS_ACTIONS[@action] => @params[INLINE_PARAMS_ACTIONS[@action]]} : nil
40
+ xml.send(@action, inline_params) do
41
+ params_xml(xml, @params)
42
+ end
43
+ end
44
+
45
+ # recursive, so you can do things like:
46
+ # BillApi.create_vendor :vendor => {:name => 'Test'}
47
+ def params_xml(xml, params)
48
+ params.each do |k, v|
49
+ if v.is_a?(Hash)
50
+ xml.send(k) { params_xml(xml, v) }
51
+ else
52
+ xml.send(k) { xml.text(v) }
53
+ end
54
+ end
55
+ end
56
+
57
+ # generate a transaction id for operation requests
58
+ def transaction_id
59
+ @@transaction_id += 1
60
+ "Transaction#{@@transaction_id}"
61
+ end
62
+
63
+ def api(xml_body)
64
+ # puts "XML BODY: #{xml_body}"
65
+ https = Net::HTTP.new(@@api_domain, 443)
66
+ https.use_ssl = true
67
+ https.read_timeout=5 # 5 second timeout
68
+ https.verify_mode = OpenSSL::SSL::VERIFY_NONE
69
+ req = Net::HTTP::Post.new(@@api_endpoint)
70
+ req.body = "request=#{req.send(:urlencode, xml_body)}" # prefixing the request with "request=" showed up in the docs absolutely nowhere. thanks, bill.com.
71
+ req.content_type = 'application/x-www-form-urlencoded'
72
+
73
+ resp = https.start {|http|
74
+ http.request(req)
75
+ }
76
+ case resp
77
+ when Net::HTTPSuccess
78
+ resp.body
79
+ else
80
+ resp.error!
81
+ end
82
+ end
83
+
84
+ def process_response(raw_response)
85
+ # puts "RAW RESPONSE: #{raw_response}"
86
+ res = Hash.from_xml(raw_response)['response']
87
+ res = res["#{@action}result"] || res["operationresult"]
88
+ res.symbolize_keys!
89
+
90
+ if res[:status] == 'OK'
91
+ RequestResult.new(res)
92
+ else
93
+ raise RequestError.new "#{res[:errorcode]}: #{res[:errormessage]}"
94
+ end
95
+ end
96
+ end
97
+
98
+ class RequestResult < OpenStruct; end
99
+ class RequestError < StandardError; end
100
+ end
data/lib/loco_bill.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'nokogiri'
2
+ require 'ostruct'
3
+ require 'bill_api/request'
4
+ require 'bill_api/login'
5
+
6
+ module LocoBill
7
+ # might not be 100% correct
8
+ ALLOWED_METHODS = [:login, :logout, :getorglist, :operationbatch, :filter, :expression, :get_list, :org_info, :pay_bill, :vendor, :create_vendor, :update_vendor, :create_chartofaccount, :update_chartofaccount, :create_department, :update_department, :create_job, :update_job, :billpay, :bill, :billLineItem, :billLineItems, :create_bill, :chartOfAccount, :department, :job, :upload_document]
9
+
10
+ def self.method_missing(m, *args, &block)
11
+ ALLOWED_METHODS.include?(m) ? Request.new(m, *args) : super
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: loco_bill
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - chris mcc
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-06-14 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: nokogiri
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.3.3
24
+ version:
25
+ description: A ruby wrapper for interacting with Bill.com's developer API
26
+ email:
27
+ - cmcclelland@digitaladvisor.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - lib/loco_bill/login.rb
36
+ - lib/loco_bill/request.rb
37
+ - lib/loco_bill.rb
38
+ - README
39
+ - init.rb
40
+ has_rdoc: true
41
+ homepage: http://github.com/DigitalAdvisor/loco_bill
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --main
47
+ - README
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project: loco_bill
65
+ rubygems_version: 1.3.5
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: A ruby wrapper for interacting with Bill.com's developer API
69
+ test_files: []
70
+