loco_bill 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+