easypost 1.1.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +27 -0
- data/CHANGELOG +0 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +30 -0
- data/LICENSE +21 -0
- data/README.md +99 -0
- data/Rakefile +0 -0
- data/VERSION +1 -0
- data/bin/easypost-irb +7 -0
- data/easypost.gemspec +24 -0
- data/lib/easypost.rb +105 -34
- data/lib/easypost/address.rb +14 -7
- data/lib/easypost/batch.rb +34 -0
- data/lib/easypost/customs_info.rb +4 -0
- data/lib/easypost/customs_item.rb +4 -0
- data/lib/easypost/{errors/easypost_error.rb → error.rb} +10 -1
- data/lib/easypost/object.rb +120 -0
- data/lib/easypost/parcel.rb +4 -0
- data/lib/easypost/postage_label.rb +4 -0
- data/lib/easypost/rate.rb +4 -0
- data/lib/easypost/refund.rb +4 -0
- data/lib/easypost/resource.rb +67 -0
- data/lib/easypost/scan_form.rb +4 -0
- data/lib/easypost/shipment.rb +82 -0
- data/lib/easypost/util.rb +102 -0
- data/lib/easypost/version.rb +3 -0
- data/spec/address_spec.rb +75 -0
- data/spec/batch_spec.rb +96 -0
- data/spec/refund_spec.rb +65 -0
- data/spec/scan_form_spec.rb +63 -0
- data/spec/shipment_spec.rb +141 -0
- data/spec/spec_helper.rb +84 -0
- metadata +66 -15
- data/lib/easypost/errors/authentication_error.rb +0 -4
- data/lib/easypost/postage.rb +0 -52
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
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
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 '
|
2
|
-
require '
|
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://
|
25
|
+
@@api_key = nil
|
26
|
+
@@api_base = 'https://api.easypost.com/v2'
|
27
|
+
@@api_version = nil
|
7
28
|
|
8
|
-
def self.api_url(
|
9
|
-
|
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.
|
22
|
-
|
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.
|
29
|
-
|
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.
|
40
|
-
|
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.
|
46
|
-
|
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
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
data/lib/easypost/address.rb
CHANGED
@@ -1,13 +1,20 @@
|
|
1
1
|
module EasyPost
|
2
|
-
class Address
|
3
|
-
@@type = "address"
|
2
|
+
class Address < Resource
|
4
3
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
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
|
-
|
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
|