tax_cloud 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ doc/*
6
+ html/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in taxcloud.gemspec
4
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,40 @@
1
+ = TaxCloud
2
+
3
+ TaxCloud is a service to calculate sales tax and generate tax reports.
4
+ tax\_cloud allows you to easily integrate with TaxCloud's API.
5
+
6
+ === Setup
7
+ Add the gem to your Gemfile
8
+ gem 'tax_cloud', '~> 0.1.0'
9
+
10
+ Configure your environment. For example, create an initializer in Rails in *config/initializers/tax_cloud.rb*
11
+ TaxCloud.configure do |config|
12
+ config.api_login_id = 'your_tax_cloud_api_login_id'
13
+ config.api_key = 'your_tax_cloud_api_key'
14
+ config.usps_username = 'your_usps_username'
15
+ end
16
+
17
+ === Using TaxCloud
18
+ Define the destination and origin addresses using <tt>TaxCloud::Address</tt>.
19
+ origin = TaxCloud::Address.new(:address1 => '123 Fake Street', :city => 'New York', :state => 'NY', :zip5 => '10001')
20
+ destination = TaxCloud::Address.new(:address1 => '239 Hollywood Drive', :city => 'Beverly Hills', :state => 'CA', :zip5 => '90210')
21
+
22
+ Create your Transaction and set up your cart items
23
+ transaction = TaxCloud::Transaction.new(:customer_id => '1', :cart_id => '1', :origin => origin, :destination => destination)
24
+ transaction.cart_items << TaxCloud::CartItem.new(:index => 0, :item_id => 'SKU-100', :tic => TaxCloud::TaxCodes::GENERAL, :price => 10.00, :quantity => 1)
25
+ lookup = transaction.lookup # this will return a Savon response object
26
+
27
+ After you've authorized and captured the transaction via your merchant account, you should do the same with TaxCloud for maintaining accurate tax information.
28
+ transaction.order_id = 100
29
+ transaction.authorized_with_capture # return Savon response object
30
+
31
+ === Todo
32
+ * Instead of returning Savon response objects, it should return TransactionLookupResponse, TransactionAuthorizedResponse, TransactionCapturedResponse, etc.
33
+ * Add all tax codes to TaxCloud::TaxCodes
34
+
35
+ === Bugs, fixes, etc
36
+ * Fork.
37
+ * Write test(s).
38
+ * Fix.
39
+ * Commit.
40
+ * Submit pull request.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'rdoc/task'
4
+
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/test_*.rb'
8
+ test.verbose = false
9
+ end
10
+
11
+ Rake::RDocTask.new do |rd|
12
+ README = 'README.rdoc'
13
+ rd.main = README
14
+ rd.rdoc_files.include(README, "lib/**/*.rb")
15
+ rd.rdoc_dir = 'doc'
16
+ rd.title = 'TaxCloud'
17
+ rd.options << '-f' << 'horo'
18
+ rd.options << '-c' << 'utf-8'
19
+ rd.options << '-m' << README
20
+ end
21
+
22
+
data/lib/hash.rb ADDED
@@ -0,0 +1,9 @@
1
+ class Hash
2
+ # Downcase the keys. Use this because <tt>TaxCloud::Address.verify</tt> requires downcased keys
3
+ def downcase_keys!
4
+ keys.each do |key|
5
+ self[key.to_s.downcase] = delete(key)
6
+ end
7
+ self
8
+ end
9
+ end
@@ -0,0 +1,30 @@
1
+ # Hack Savon to work properly with arrays
2
+ module Savon #:nodoc:
3
+ module SOAP #:nodoc:
4
+ class XML #:nodoc:
5
+ private
6
+ old_add_namespaces_to_body = self.instance_method(:add_namespaces_to_body)
7
+
8
+ def add_namespaces_to_body(hash, path = [input[1].to_s])
9
+ return unless hash
10
+ return hash if hash.kind_of? Array
11
+ return hash.to_s unless hash.kind_of? Hash
12
+
13
+ hash.inject({}) do |newhash, (key, value)|
14
+ camelcased_key = Gyoku::XMLKey.create(key)
15
+ newpath = path + [camelcased_key]
16
+
17
+ if used_namespaces[newpath]
18
+ newhash.merge(
19
+ "#{used_namespaces[newpath]}:#{camelcased_key}" =>
20
+ add_namespaces_to_body(value, types[newpath] ? [types[newpath]] : newpath)
21
+ )
22
+ else
23
+ newhash.merge(key => value)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
data/lib/tax_cloud.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'savon'
2
+ require 'savon_xml_override'
3
+ require 'tax_cloud/version'
4
+ require 'tax_cloud/transaction'
5
+ require 'tax_cloud/address'
6
+ require 'tax_cloud/cart_item'
7
+ require 'tax_cloud/tax_codes'
8
+ require 'tax_cloud/configuration'
9
+ require 'hash'
10
+
11
+ # TaxCloud is a web service to calculate and track sales tax for your ecommerce platform. Integration is easy to use.
12
+ # For information on configuring and using the TaxCloud API, look at the <tt>README</tt> file.
13
+ module TaxCloud
14
+ # WSDL location for TaxCloud
15
+ WSDL_URL = 'https://api.taxcloud.net/1.0/?wsdl'
16
+ # TaxCloud API version
17
+ API_VERSION = '1.0'
18
+
19
+ class << self
20
+ attr_accessor :configuration
21
+
22
+ # Configure the variables
23
+ def configure
24
+ self.configuration ||= Configuration.new
25
+ yield configuration
26
+ end
27
+
28
+ # Method to define and retrieve the SOAP methods
29
+ def client
30
+ @@client ||= Savon::Client.new do
31
+ wsdl.document = TaxCloud::WSDL_URL
32
+ end
33
+ end
34
+
35
+ # Authorization hash to use with all SOAP requests
36
+ def auth_params
37
+ {
38
+ 'apiLoginID' => configuration.api_login_id,
39
+ 'apiKey' => configuration.api_key
40
+ }
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,37 @@
1
+ module TaxCloud
2
+ # An address
3
+ class Address
4
+ attr_accessor :address1, :address2, :city, :state, :zip5, :zip4
5
+
6
+ # Initialize the object with the given variables
7
+ def initialize(attrs = {})
8
+ attrs.each do |sym, val|
9
+ self.send "#{sym}=", val
10
+ end
11
+ super
12
+ end
13
+
14
+ # Verify the address via TaxCloud
15
+ def verify
16
+ request_params = {
17
+ 'apiLoginId' => TaxCloud.configuration.api_login_id,
18
+ 'apiKey' => TaxCloud.configuration.api_key,
19
+ 'uspsUserID' => TaxCloud.configuration.usps_username
20
+ }.merge(to_hash.downcase_keys!)
21
+ response = TaxCloud.client.request :verify_address, :body => request_params
22
+ end
23
+
24
+ # Convert the object to a usable hash for SOAP requests
25
+ def to_hash
26
+ {
27
+ 'Address1' => address1,
28
+ 'Address2' => address2,
29
+ 'City' => city,
30
+ 'State' => state,
31
+ 'Zip5' => zip5,
32
+ 'Zip4' => zip4
33
+ }
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ require 'builder'
2
+
3
+ module TaxCloud
4
+ # A <tt>CartItem</tt> defines a single line item for the purchase. Used to calculate the tax amount.
5
+ #
6
+ # === Attributes
7
+ # * <tt>index</tt> - The unique index number for the line item. Must be unique for the scope of the cart.
8
+ # * <tt>item_id</tt> - The stock keeping unit (SKU) number
9
+ # * <tt>tic</tt> - The taxable information code. See <tt>TaxCloud::TaxCodes</tt>.
10
+ # * <tt>price</tt> - The price of the item. All prices are USD. Do not include currency symbol.
11
+ # * <tt>quantity</tt> - The total number of items.
12
+ class CartItem
13
+ attr_accessor :index, :item_id, :tic, :price, :quantity
14
+
15
+ def initialize(attrs = {})
16
+ attrs.each do |sym, val|
17
+ self.send "#{sym}=", val
18
+ end
19
+ super
20
+ end
21
+
22
+ # Convert the object to a usable hash for SOAP requests
23
+ def to_hash
24
+ {
25
+ 'Index' => index,
26
+ 'ItemID' => item_id,
27
+ 'TIC' => tic,
28
+ 'Price' => price,
29
+ 'Qty' => quantity
30
+ }
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ module TaxCloud
2
+ class Configuration
3
+ attr_accessor :api_login_id, :api_key, :usps_username
4
+ end
5
+ end
@@ -0,0 +1,52 @@
1
+ module TaxCloud
2
+ class TaxCodes
3
+ GENERAL = '00000'
4
+
5
+ # SHIPPING AND ADMINISTRATIVE
6
+ GIFT_CARD = '10005'
7
+ SERVICE_FEE = '10010'
8
+ INSTALLATION_FEE = '10040'
9
+ TRADE_IN_VALUE = '10060'
10
+ TELECOM = '10070'
11
+ HANDLING_FEE = '11000'
12
+ POSTAGE = '11010'
13
+ DMAIL_HANDLING_FEE = '11020'
14
+ DMAIL_TRANSPORTATION = '11021'
15
+ DMAIL_POSTAGE = '11022'
16
+
17
+ # CLOTHING, SPORTS, AND ACCESSORIES
18
+ CLOTHING = '20010'
19
+ ESSENTIAL_CLOTHING = '20015'
20
+ CLOTHING_ACCESSORY = '20020'
21
+ PROTECTIVE_EQUIPMENT = '20030'
22
+ SPORT_EQUIPMENT = '20040'
23
+ FUR_CLOTHING = '20050'
24
+ CLOTHING_TAX_HOLIDAY = '20130'
25
+ SCHOOL_SUPPLY = '20070'
26
+
27
+ DISASTER_PREPAREDNESS_SUPPLY = '20150'
28
+
29
+ # COMPUTERS, ELECTRONICS, AND APPLIANCES
30
+ ENERGY_STAR_APPLIANCE = '20060'
31
+ CUSTOM_SOFTWARE = '30015'
32
+ SOFTWARE = '30040'
33
+ COMPUTER = '30100'
34
+ DIGITAL_PRODUCT = '31000'
35
+
36
+ # FOOD RELATED
37
+ CANDY = '40010'
38
+ DIETARY_SUPPLEMENT = '40020'
39
+ FOOD = '40030'
40
+ VENDING_FOOD = '40040'
41
+ SOFT_DRINK = '40050'
42
+ BOTTLED_WATER = '40060'
43
+ PREPARED_FOOD = '41000'
44
+ BULK_FOOD__FROM_MANUFACTURER = '41010'
45
+ BULK_FOOD = '41020'
46
+ BAKERY_ITEM = '41030'
47
+
48
+ # MEDICAL AND HYGENE RELATED
49
+
50
+
51
+ end
52
+ end
@@ -0,0 +1,91 @@
1
+ module TaxCloud
2
+ # Lookup tax rate, authorize, and capture the information to be logged into TaxCloud.
3
+ #
4
+ # *Note:* The Transaction must not change between the <tt>lookup</tt> and <tt>authorization</tt> method calls.
5
+ #
6
+ # === Attributes
7
+ # * <tt>customer_id</tt> - Your defined customer ID for the <tt>Transaction</tt>.
8
+ # * <tt>cart_id</tt> - Your defined cart ID for the order.
9
+ # * <tt>cart_items</tt> - Array of <tt>CartItem</tt>s.
10
+ # * <tt>order_id</tt> - The order ID for <tt>authorized</tt>, <tt>captured</tt>, and <tt>authorzied_with_captured</tt> methods.
11
+ # * <tt>origin</tt> - The <tt>Address</tt> of which the shipment originates.
12
+ # * <tt>destination</tt> - The <tt>Address</tt> of which the shipment arrives.
13
+ class Transaction
14
+ attr_accessor :customer_id, :cart_id, :cart_items, :order_id, :origin, :destination
15
+
16
+ # Creates a new <tt>Transaction</tt> object with the given parameters
17
+ def initialize(params = {})
18
+ params = { :cart_items => [] }.merge(params)
19
+ params.each do |key, value|
20
+ self.send "#{key}=", value
21
+ end
22
+ end
23
+
24
+ # Lookup the tax rate for the transaction. The returned information is based on the originating address, destination address, and cart items.
25
+ def lookup
26
+ request_params = {
27
+ 'customerID' => customer_id,
28
+ 'cartID' => cart_id,
29
+ 'cartItems' => { 'CartItem' => cart_items.map(&:to_hash) },
30
+ 'origin' => origin.to_hash,
31
+ 'destination' => destination.to_hash
32
+ }.merge(TaxCloud.auth_params)
33
+
34
+ response = TaxCloud.client.request :lookup, :body => request_params
35
+
36
+ # In the event that a cart_id wasn't specified, TaxCloud will give you one
37
+ self.cart_id = response[:lookup_response][:lookup_result][:cart_id] if response[:lookup_response][:lookup_result][:cart_id]
38
+ return response
39
+ end
40
+
41
+ # Once a purchase has been made and payment has been authorized, this method must be called. A matching Lookup call must have been made before this is called.
42
+ #
43
+ # === Options
44
+ # * <tt>date_authorized</tt> - The date the transaction was authorized. Default is today.
45
+ def authorized(options = {})
46
+ options = { :date_authorized => Date.today }.merge(options)
47
+ request_params = {
48
+ 'customerID' => customer_id,
49
+ 'cartID' => cart_id,
50
+ 'orderID' => order_id,
51
+ 'dateAuthorized' => options[:date_authorized]
52
+ }.merge(TaxCloud.auth_params)
53
+
54
+ response = TaxCloud.client.request :authorized, :body => request_params
55
+ end
56
+
57
+ # Complete the transaction. The <tt>order_id</tt> passed into <tt>captured</tt> must match the <tt>order_id</tt> that was passed into <tt>authorized</tt>.
58
+ #
59
+ # === Options
60
+ # * <tt>date_captured</tt> - The time the transaction was captured. Default is today.
61
+ def captured(options = {})
62
+ options = { :date_captured => Date.today }.merge(options)
63
+ request_params = {
64
+ 'customerID' => customer_id,
65
+ 'cartID' => cart_id,
66
+ 'orderID' => order_id,
67
+ 'dateCaptured' => options[:date_captured]
68
+ }.merge(TaxCloud.auth_params)
69
+
70
+ response = TaxCloud.client.request :captured, :body => request_params
71
+ end
72
+
73
+ # Combines the <tt>authorized</tt> and <tt>captured</tt> methods into a single call
74
+ #
75
+ # === Options
76
+ # * <tt>date_authorized</tt> - The date the transaction was authorized. Default is today.
77
+ # * <tt>date_captured</tt> - The date the transaction was captured. Default is today.
78
+ def authorized_with_capture(options = {})
79
+ options = { :date_authorized => Date.today, :date_captured => Date.today }.merge(options)
80
+ request_params = {
81
+ 'customerID' => customer_id,
82
+ 'cartID' => cart_id,
83
+ 'orderID' => order_id,
84
+ 'dateAuthorized' => options[:date_authorized],
85
+ 'dateCaptured' => options[:date_captured]
86
+ }.merge(TaxCloud.auth_params)
87
+
88
+ response = TaxCloud.client.request :authorized_with_capture, :body => request_params
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,4 @@
1
+ module TaxCloud
2
+ # TaxCloud gem version
3
+ VERSION = "0.1.0"
4
+ end
data/tax_cloud.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "tax_cloud/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "tax_cloud"
6
+ s.version = TaxCloud::VERSION
7
+ s.authors = ["Drew Tempelmeyer"]
8
+ s.email = ["drewtemp@gmail.com"]
9
+ s.homepage = "https://github.com/drewtempelmeyer/tax_cloud"
10
+ s.summary = %q{Calculate sales tax using the TaxCloud.net API}
11
+ s.description = %q{Calculate sales tax using the TaxCloud.net API}
12
+
13
+ s.rubyforge_project = "tax_cloud"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_runtime_dependency 'savon', '~> 0.9.6'
21
+
22
+ # Development depencies
23
+ s.add_development_dependency 'rake', '0.9.2'
24
+ s.add_development_dependency 'horo'
25
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'test/unit'
2
+ require 'tax_cloud'
3
+ require 'json'
4
+
5
+ class Test::Unit::TestCase
6
+ def setup
7
+ TaxCloud.configure do |config|
8
+ config.api_login_id = 'taxcloud_api_login_id'
9
+ config.api_key = 'taxcloud_api_key'
10
+ config.usps_username = 'usps_username'
11
+ end
12
+ end
13
+ end
14
+
15
+ Savon.configure do |config|
16
+ # config.log = false
17
+ end
18
+
@@ -0,0 +1,28 @@
1
+ require 'helper'
2
+
3
+ class TestAddress < Test::Unit::TestCase
4
+
5
+ def setup
6
+ super
7
+ @address = TaxCloud::Address.new :address1 => '888 6th Ave', :city => 'New York', :state => 'New York', :zip5 => '10001'
8
+ end
9
+
10
+ def test_initialize
11
+ assert_equal '888 6th Ave', @address.address1
12
+ assert_equal nil, @address.address2
13
+ assert_equal 'New York', @address.city
14
+ assert_equal 'New York', @address.state
15
+ assert_equal '10001', @address.zip5
16
+ assert_equal nil, @address.zip4
17
+ end
18
+
19
+ def test_address_verify
20
+ assert_respond_to @address, :verify
21
+ verify = @address.verify
22
+ assert_equal '0', verify[:verify_address_response][:verify_address_result][:err_number]
23
+ bad_address = TaxCloud::Address.new :address1 => '10001 Test Street', :city => 'New York', :state => 'New York', :zip5 => '99999'
24
+ verify = bad_address.verify
25
+ assert_not_equal '0', verify[:verify_address_response][:verify_address_result][:err_number]
26
+ end
27
+
28
+ end
@@ -0,0 +1,17 @@
1
+ require 'helper'
2
+
3
+ class TestCartItem < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @cart_item = TaxCloud::CartItem.new :index => 0, :item_id => 'SKU-100', :tic => '0000', :price => 50.00, :quantity => 3
7
+ end
8
+
9
+ def test_variables
10
+ assert_equal 0, @cart_item.index
11
+ assert_equal 'SKU-100', @cart_item.item_id
12
+ assert_equal '0000', @cart_item.tic
13
+ assert_equal 50.00, @cart_item.price
14
+ assert_equal 3, @cart_item.quantity
15
+ end
16
+
17
+ end
@@ -0,0 +1,39 @@
1
+ require 'helper'
2
+
3
+ class TestTransaction < Test::Unit::TestCase
4
+
5
+ def setup
6
+ super
7
+ origin = TaxCloud::Address.new :address1 => '888 6th Ave', :city => 'New York', :state => 'NY', :zip5 => '10001'
8
+ destination = TaxCloud::Address.new :address1 => '888 6th Ave', :city => 'New York', :state => 'NY', :zip5 => '10001'
9
+ cart_items = []
10
+ cart_items << TaxCloud::CartItem.new(:index => 0, :item_id => 'SKU-TEST', :tic => TaxCloud::TaxCodes::GENERAL, :quantity => 1, :price => 50.00)
11
+ cart_items << TaxCloud::CartItem.new(:index => 1, :item_id => 'SKU-TEST1', :tic => TaxCloud::TaxCodes::GENERAL, :quantity => 1, :price => 50.00)
12
+ @transaction = TaxCloud::Transaction.new(:customer_id => rand(9999), :cart_id => rand(9999), :order_id => rand(9999), :cart_items => cart_items, :origin => origin, :destination => destination)
13
+ end
14
+
15
+ def test_lookup
16
+ result = @transaction.lookup[:lookup_response][:lookup_result]
17
+ result[:cart_items_response][:cart_item_response].each { |item| assert_not_nil item[:tax_amount] }
18
+ end
19
+
20
+ def test_authorized
21
+ @transaction.lookup[:lookup_response][:lookup_result]
22
+ result = @transaction.authorized
23
+ assert_equal 'OK', result[:authorized_response][:authorized_result][:response_type]
24
+ end
25
+
26
+ def test_captured
27
+ @transaction.lookup[:lookup_response][:lookup_result]
28
+ @transaction.authorized
29
+ result = @transaction.captured
30
+ assert_equal 'OK', result[:captured_response][:captured_result][:response_type]
31
+ end
32
+
33
+ def test_authorized_with_capture
34
+ @transaction.lookup[:lookup_response][:lookup_result]
35
+ result = @transaction.authorized_with_capture
36
+ assert_equal 'OK', result[:authorized_with_capture_response][:authorized_with_capture_result][:response_type]
37
+ end
38
+
39
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tax_cloud
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Drew Tempelmeyer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-24 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: savon
16
+ requirement: &2158465280 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.6
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2158465280
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &2158464760 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - =
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.2
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2158464760
36
+ - !ruby/object:Gem::Dependency
37
+ name: horo
38
+ requirement: &2158464380 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2158464380
47
+ description: Calculate sales tax using the TaxCloud.net API
48
+ email:
49
+ - drewtemp@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - README.rdoc
57
+ - Rakefile
58
+ - lib/hash.rb
59
+ - lib/savon_xml_override.rb
60
+ - lib/tax_cloud.rb
61
+ - lib/tax_cloud/address.rb
62
+ - lib/tax_cloud/cart_item.rb
63
+ - lib/tax_cloud/configuration.rb
64
+ - lib/tax_cloud/tax_codes.rb
65
+ - lib/tax_cloud/transaction.rb
66
+ - lib/tax_cloud/version.rb
67
+ - tax_cloud.gemspec
68
+ - test/helper.rb
69
+ - test/test_address.rb
70
+ - test/test_cart_item.rb
71
+ - test/test_transaction.rb
72
+ homepage: https://github.com/drewtempelmeyer/tax_cloud
73
+ licenses: []
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ segments:
85
+ - 0
86
+ hash: -748120043381049506
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ segments:
94
+ - 0
95
+ hash: -748120043381049506
96
+ requirements: []
97
+ rubyforge_project: tax_cloud
98
+ rubygems_version: 1.8.8
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: Calculate sales tax using the TaxCloud.net API
102
+ test_files: []