easypost 1.1.3 → 2.0.0

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/.gitignore ADDED
@@ -0,0 +1,27 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ # iOS
21
+ .DS_Store
22
+ .AppleDouble
23
+ .LSOverride
24
+ Icon
25
+ ._*
26
+ .Spotlight-V100
27
+ .Trashes
data/CHANGELOG ADDED
File without changes
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,30 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ easypost (2.0.0)
5
+ multi_json (>= 1.0.4, < 2)
6
+ rest-client (~> 1.4)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ diff-lcs (1.2.4)
12
+ mime-types (1.23)
13
+ multi_json (1.7.7)
14
+ rest-client (1.6.7)
15
+ mime-types (>= 1.16)
16
+ rspec (2.13.0)
17
+ rspec-core (~> 2.13.0)
18
+ rspec-expectations (~> 2.13.0)
19
+ rspec-mocks (~> 2.13.0)
20
+ rspec-core (2.13.1)
21
+ rspec-expectations (2.13.0)
22
+ diff-lcs (>= 1.1.3, < 2.0)
23
+ rspec-mocks (2.13.1)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ easypost!
30
+ rspec (~> 2.13.0)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2013 EasyPost (Simpler Postage, Inc)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # EasyPost Ruby Client Library
2
+
3
+ EasyPost is a simple shipping API. You can sign up for an account at https://easypost.com
4
+
5
+ Installation
6
+ ---------------
7
+
8
+ Install the gem:
9
+
10
+ ```
11
+ gem install
12
+ ```
13
+
14
+ Import the EasyPost client in your application:
15
+
16
+ ```
17
+ require 'easypost'
18
+ ```
19
+
20
+ Example
21
+ ------------------
22
+
23
+ ```ruby
24
+ require 'easypost'
25
+ EasyPost.api_key = 'cueqNZUb3ldeWTNX7MU3Mel8UXtaAMUi'
26
+
27
+ to_address = EasyPost::Address.create(
28
+ :name => 'Sawyer Bateman',
29
+ :street1 => '1A Larkspur Cres.',
30
+ :city => 'St. Albert',
31
+ :state => 'AB',
32
+ :zip => 't8n2m4',
33
+ :country => 'CA',
34
+ :phone => '780-273-8374'
35
+ )
36
+ from_address = EasyPost::Address.create(
37
+ :company => 'Simpler Postage Inc',
38
+ :street1 => '388 Townsend Street',
39
+ :street2 => 'Apt 20',
40
+ :city => 'San Francisco',
41
+ :state => 'CA',
42
+ :zip => '94107',
43
+ :phone => '415-456-7890'
44
+ )
45
+
46
+ parcel = EasyPost::Parcel.create(
47
+ :width => 15.2,
48
+ :length => 18,
49
+ :height => 9.5,
50
+ :weight => 35.1
51
+ )
52
+
53
+ customs_item = EasyPost::CustomsItem.create(
54
+ :description => 'EasyPost T-shirts',
55
+ :quantity => 2,
56
+ :value => 23.56,
57
+ :weight => 33,
58
+ :origin_country => 'us',
59
+ :hs_tariff_number => 123456
60
+ )
61
+ customs_info = EasyPost::CustomsInfo.create(
62
+ :integrated_form_type => 'form_2976',
63
+ :customs_certify => true,
64
+ :customs_signer => 'Dr. Pepper',
65
+ :contents_type => 'gift',
66
+ :contents_explanation => '', # only required when contents_type => 'other'
67
+ :eel_pfc => 'NOEEI 30.37(a)',
68
+ :non_delivery_option => 'abandon',
69
+ :restriction_type => 'none',
70
+ :restriction_comments => '',
71
+ :customs_items => [customs_item]
72
+ )
73
+
74
+ shipment = EasyPost::Shipment.create(
75
+ :to_address => to_address,
76
+ :from_address => from_address,
77
+ :parcel => parcel,
78
+ :customs_info => customs_info
79
+ )
80
+
81
+ shipment.buy(
82
+ :rate => shipment.lowest_rate
83
+ )
84
+
85
+ puts shipment.postage_label.label_url
86
+
87
+ ```
88
+
89
+ Documentation
90
+ --------------------
91
+
92
+ Up-to-date documentation at: https://easypost.com/docs
93
+
94
+ Tests
95
+ --------------------
96
+
97
+ ```
98
+ rspec spec
99
+ ```
data/Rakefile ADDED
File without changes
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.0.0
data/bin/easypost-irb ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
3
+
4
+ libs = " -r irb/completion"
5
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/easypost'}"
6
+ puts "Initializing EasyPost..."
7
+ exec "#{irb} #{libs} --simple-prompt"
data/easypost.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'easypost/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'easypost'
8
+ spec.version = EasyPost::VERSION
9
+ spec.date = '2013-06-25'
10
+ spec.summary = 'EasyPost Ruby Client Library'
11
+ spec.description = 'Client library for accessing the EasyPost shipping API via Ruby.'
12
+ spec.authors = ['Jon Calhoun', 'Sawyer Bateman']
13
+ spec.email = 'contact@easypost.com'
14
+ spec.homepage = 'https://easypost.com/docs'
15
+
16
+ spec.files = `git ls-files`.split("\n")
17
+ spec.test_files = `git ls-files -- test/*`.split("\n")
18
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ spec.require_path = 'lib'
20
+
21
+ spec.add_dependency('rest-client', '~> 1.4')
22
+ spec.add_dependency('multi_json', '>= 1.0.4', '< 2')
23
+ spec.add_development_dependency('rspec', "~> 2.13.0")
24
+ end
data/lib/easypost.rb CHANGED
@@ -1,13 +1,33 @@
1
- require 'typhoeus'
2
- require 'json'
1
+ require 'cgi'
2
+ require 'set'
3
+ require 'openssl'
4
+ require 'rest_client'
5
+ require 'multi_json'
6
+
7
+ # Resources
8
+ require 'easypost/util'
9
+ require 'easypost/object'
10
+ require 'easypost/resource'
11
+ require 'easypost/address'
12
+ require 'easypost/parcel'
13
+ require 'easypost/customs_item'
14
+ require 'easypost/customs_info'
15
+ require 'easypost/shipment'
16
+ require 'easypost/rate'
17
+ require 'easypost/postage_label'
18
+ require 'easypost/scan_form'
19
+ require 'easypost/refund'
20
+ require 'easypost/batch'
21
+
22
+ require 'easypost/error'
3
23
 
4
24
  module EasyPost
5
- @@api_key = "..."
6
- @@api_base = 'https://www.geteasypost.com/api/'
25
+ @@api_key = nil
26
+ @@api_base = 'https://api.easypost.com/v2'
27
+ @@api_version = nil
7
28
 
8
- def self.api_url(args={})
9
- raise ArgumentError unless args.keys.eql?([:type, :action])
10
- return "#{@@api_base}#{args[:type]}/#{args[:action]}"
29
+ def self.api_url(url='')
30
+ @@api_base + url
11
31
  end
12
32
 
13
33
  def self.api_key=(api_key)
@@ -18,40 +38,91 @@ module EasyPost
18
38
  @@api_key
19
39
  end
20
40
 
21
- def self.symbolize_keys(hash={})
22
- hash.keys.each do |key|
23
- hash[(key.to_sym rescue key) || key] = hash.delete(key)
24
- end
25
- return hash
41
+ def self.api_base=(api_base)
42
+ @@api_base = api_base
26
43
  end
27
44
 
28
- def self.symbolize_keys_recursive(hash={})
29
- hash.keys.each do |key|
30
- keysym = (key.to_sym rescue key) || key
31
- hash[keysym] = hash.delete(key)
32
- if hash[keysym].is_a?(Hash)
33
- hash[keysym] = symbolize_keys_recursive(hash[keysym])
34
- end
35
- end
36
- return hash
45
+ def self.api_base
46
+ @@api_base
37
47
  end
38
48
 
39
- def self.get(url, params={})
40
- params = {:userpwd => @@api_key, :params => params}
41
- @response = Typhoeus::Request.get(url, params)
42
- return EasyPost.symbolize_keys_recursive(JSON.parse(@response.body))
49
+ def self.api_version=(version)
50
+ @@api_version = version
43
51
  end
44
52
 
45
- def self.post(url, params={})
46
- params = {:userpwd => @@api_key, :params => params}
47
- @response = Typhoeus::Request.post(url, params)
48
- return EasyPost.symbolize_keys_recursive(JSON.parse(@response.body))
53
+ def self.api_version
54
+ @@api_version
49
55
  end
50
56
 
51
- end
57
+ def self.request(method, url, api_key, params={}, headers={})
58
+ api_key ||= @@api_key
59
+ raise Error.new('No API key provided.') unless api_key
52
60
 
53
- require 'easypost/address'
54
- require 'easypost/postage'
55
- require 'easypost/errors/easypost_error'
56
- require 'easypost/errors/authentication_error'
61
+ ssl_opts = { :verify_ssl => false }
62
+
63
+ params = Util.objects_to_ids(params)
64
+ url = self.api_url(url)
65
+ case method.to_s.downcase.to_sym
66
+ when :get, :head, :delete
67
+ # Make params into GET parameters
68
+ if params && params.count > 0
69
+ query_string = Util.flatten_params(params).collect{|key, value| "#{key}=#{Util.url_encode(value)}"}.join('&')
70
+ url += "#{URI.parse(url).query ? '&' : '?'}#{query_string}"
71
+ end
72
+ payload = nil
73
+ else
74
+ payload = Util.flatten_params(params).collect{|(key, value)| "#{key}=#{Util.url_encode(value)}"}.join('&')
75
+ end
76
+
77
+ headers = {
78
+ :user_agent => "EasyPost/v2 RubyClient/2.0.0",
79
+ :authorization => "Bearer #{api_key}",
80
+ :content_type => 'application/x-www-form-urlencoded'
81
+ }.merge(headers)
57
82
 
83
+ opts = {
84
+ :method => method,
85
+ :url => url,
86
+ :headers => headers,
87
+ :open_timeout => 30,
88
+ :payload => payload,
89
+ :timeout => 60
90
+ }.merge(ssl_opts)
91
+
92
+ begin
93
+ response = execute_request(opts)
94
+ rescue RestClient::ExceptionWithResponse => e
95
+ if response_code = e.http_code and response_body = e.http_body
96
+ begin
97
+ response_json = MultiJson.load(response_body, :symbolize_keys => true)
98
+ rescue MultiJson::DecodeError
99
+ raise Error.new("Invalid response from API, unable to decode.", response_code, response_body)
100
+ end
101
+ begin
102
+ raise NoMethodError if response_json[:error][:message] == nil
103
+ raise Error.new(response_json[:error][:message], response_code, response_body, response_json)
104
+ rescue NoMethodError, TypeError
105
+ raise Error.new(response_json[:error], response_code, response_body, response_json)
106
+ end
107
+ else
108
+ raise Error.new(e.message)
109
+ end
110
+ rescue RestClient::Exception, Errno::ECONNREFUSED => e
111
+ raise Error.new(e.message)
112
+ end
113
+
114
+ begin
115
+ response_json = MultiJson.load(response.body, :symbolize_keys => true)
116
+ rescue MultiJson::DecodeError
117
+ raise Error.new("Invalid response object from API, unable to decode.", response.code, response.body)
118
+ end
119
+
120
+ return [response_json, api_key]
121
+ end
122
+
123
+ private
124
+
125
+ def self.execute_request(opts)
126
+ RestClient::Request.execute(opts)
127
+ end
128
+ end
@@ -1,13 +1,20 @@
1
1
  module EasyPost
2
- class Address
3
- @@type = "address"
2
+ class Address < Resource
4
3
 
5
- def self.test
6
- puts EasyPost.api_url("verify")
7
- end
4
+ def verify(params={})
5
+ response, api_key = EasyPost.request(:get, url + '/verify', @api_key, params)
6
+
7
+ if response.has_key?(:address)
8
+ if response.has_key?(:message)
9
+ response[:address][:message] = response[:message]
10
+ end
11
+ verified_address = EasyPost::Util::convert_to_easypost_object(response[:address], api_key)
12
+ return verified_address
13
+ else
14
+ raise Error.new("Unable to verify address.")
15
+ end
8
16
 
9
- def self.verify(address={})
10
- @verified_address = EasyPost.get(EasyPost.api_url(:type => @@type, :action => "verify"), :address => address)
17
+ return self
11
18
  end
12
19
 
13
20
  end
@@ -0,0 +1,34 @@
1
+ module EasyPost
2
+ class Batch < Resource
3
+
4
+ def self.create_and_buy(params={})
5
+ wrapped_params = {}
6
+ wrapped_params[self.class_name().to_sym] = params
7
+ response, api_key = EasyPost.request(:post, url + '/create_and_buy', @api_key, wrapped_params)
8
+
9
+ return Util.convert_to_easypost_object(response, api_key)
10
+ end
11
+
12
+ def label(params={})
13
+ response, api_key = EasyPost.request(:post, url + '/label', @api_key, params)
14
+ self.refresh_from(response, @api_key, true)
15
+
16
+ return self
17
+ end
18
+
19
+ def remove_shipments(params={})
20
+ response, api_key = EasyPost.request(:post, url + '/remove_shipments', @api_key, params)
21
+ self.refresh_from(response, @api_key, true)
22
+
23
+ return self
24
+ end
25
+
26
+ def add_shipments(params={})
27
+ response, api_key = EasyPost.request(:post, url + '/add_shipments', @api_key, params)
28
+ self.refresh_from(response, @api_key, true)
29
+
30
+ return self
31
+ end
32
+
33
+ end
34
+ end