usps 0.1.2 → 0.1.3
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.
- checksums.yaml +7 -0
- data/README.md +84 -0
- data/Rakefile +6 -8
- data/lib/usps.rb +6 -5
- data/lib/usps/address.rb +1 -1
- data/lib/usps/configuration.rb +1 -1
- data/lib/usps/request.rb +2 -1
- data/lib/usps/request/tracking_field_lookup.rb +28 -0
- data/lib/usps/response.rb +1 -0
- data/lib/usps/response/address_standardization.rb +15 -1
- data/lib/usps/response/city_and_state_lookup.rb +16 -2
- data/lib/usps/response/tracking_field_lookup.rb +34 -0
- data/lib/usps/response/tracking_lookup.rb +1 -1
- data/lib/usps/track_detail.rb +49 -0
- data/lib/usps/version.rb +1 -1
- data/spec/address_spec.rb +14 -14
- data/spec/configuration_spec.rb +4 -4
- data/spec/data/tracking_field_lookup.xml +41 -0
- data/spec/data/tracking_field_lookup_2.xml +17 -0
- data/spec/request/address_standardization_spec.rb +13 -13
- data/spec/request/base_spec.rb +2 -2
- data/spec/request/city_and_state_lookup_spec.rb +10 -10
- data/spec/request/delivery_confirmation_certify_spec.rb +3 -3
- data/spec/request/delivery_confirmation_spec.rb +27 -27
- data/spec/request/tracking_field_spec.rb +20 -0
- data/spec/request/tracking_spec.rb +5 -5
- data/spec/request/zip_code_lookup_spec.rb +11 -11
- data/spec/response/address_standardization_spec.rb +9 -9
- data/spec/response/city_and_state_lookup_spec.rb +6 -6
- data/spec/response/delivery_confirmation_spec.rb +19 -19
- data/spec/response/tracking_field_lookup_spec.rb +28 -0
- data/spec/response/tracking_lookup_spec.rb +10 -10
- data/spec/track_detail_spec.rb +51 -0
- data/spec/usps_spec.rb +1 -1
- metadata +66 -90
- data/README.rdoc +0 -60
- data/lib/usps/request/signature_confirmation.rb +0 -44
- data/spec/request/signature_confirmation_spec.rb +0 -0
- data/spec/response/signature_confirmation_spec.rb +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 32013f6daa8af9cd35517d0b37b200bf9db91974
|
4
|
+
data.tar.gz: d9309024e63911cf3cb3d3b150160e77963f4ee3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 391f24ffa46925ac60facbfa9ee5ab1add219781d35c216b093257c12866ffc329f59f2ca8d89165567bbae8a051f57be706329366c3d7e84d3edfb28dee21d6
|
7
|
+
data.tar.gz: c1f48611b6b72cd797266ddb77efba8d5a7736fdedfeaebc4a3d839e63c543720cdedfa9c5f2e93be35d436c02c02c626ab41cd4652bc60c288ede67098a6992
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# usps
|
2
|
+
|
3
|
+
[](https://travis-ci.org/gaffneyc/usps)
|
4
|
+
|
5
|
+
Ruby API for accessing the USPS WebTools API found here: https://www.usps.com/business/webtools.htm
|
6
|
+
|
7
|
+
PDF Guides can be found here: https://www.usps.com/business/webtools-technical-guides.htm
|
8
|
+
|
9
|
+
Usage of this library assumes you already have a USPS API account and that all priviledges have been granted.
|
10
|
+
|
11
|
+
## Project Status - Looking for a Maintainer
|
12
|
+
|
13
|
+
This code is no longer properly maintained as I'm no longer with the company it was developed for.
|
14
|
+
If you're using it and would be interested in maintaining it please send me a message and I can
|
15
|
+
get you set up.
|
16
|
+
|
17
|
+
## Exposed API Calls
|
18
|
+
|
19
|
+
The following USPS API calls are currently exposed through this library:
|
20
|
+
|
21
|
+
```
|
22
|
+
<AddressValidateRequest> -- USPS::Request::AddressStandardization
|
23
|
+
<CityStateLookupRequest> -- USPS::Request::CityAndStateLookup
|
24
|
+
<ZipCodeLookupRequest> -- USPS::Request::ZipCodeLookup
|
25
|
+
<TrackRequest> -- USPS::Request::TrackingLookup
|
26
|
+
<TrackFieldRequest> -- USPS::Request::TrackingFieldLookup
|
27
|
+
|
28
|
+
<DeliveryConfirmationV3.0Request> -- USPS::Request::DeliveryConfirmation (for production)
|
29
|
+
<DeliveryConfirmCertifyV3.0Request> -- USPS::Request::DeliveryConfirmationCertify (for testing)
|
30
|
+
```
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
Using the library is as simple as building a new USPS::Request::[type] object, calling #send! and using the response.
|
35
|
+
For example, to send a tracking request you'd do the following:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
request = USPS::Request::TrackingLookup.new(tracking_number)
|
39
|
+
response = request.send!
|
40
|
+
|
41
|
+
response.summary
|
42
|
+
response.details
|
43
|
+
```
|
44
|
+
|
45
|
+
The library assumes that either ENV['USPS_USER'] is set, or that you set USPS.username to your USPS API username.
|
46
|
+
|
47
|
+
See the individual USPS::Request classes for details on how to use them.
|
48
|
+
|
49
|
+
## USPS API Certification
|
50
|
+
|
51
|
+
Part of the process of setting up an account with the USPS API is to run certain tests against the USPS API.
|
52
|
+
This library has all the requisite tests built in, runnable with rake:
|
53
|
+
|
54
|
+
```
|
55
|
+
$ USPS_USER="[username]" rake certify
|
56
|
+
```
|
57
|
+
|
58
|
+
or as an installed gem:
|
59
|
+
|
60
|
+
```
|
61
|
+
$ USPS_USER="[username]" ruby -rubygems -e "require 'usps/test'"
|
62
|
+
```
|
63
|
+
|
64
|
+
If any of the tests fail, you don't have access to that API and may need to work with USPS to fix it.
|
65
|
+
|
66
|
+
## Note on Patches/Pull Requests
|
67
|
+
|
68
|
+
* Fork the project.
|
69
|
+
* Make your feature addition or bug fix.
|
70
|
+
* Add tests for it. This is important so I don't break it in a
|
71
|
+
future version unintentionally.
|
72
|
+
* Commit, do not mess with rakefile, version, or history.
|
73
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
74
|
+
* Send me a pull request. Bonus points for topic branches.
|
75
|
+
|
76
|
+
## Testing
|
77
|
+
|
78
|
+
```
|
79
|
+
$ rspec
|
80
|
+
```
|
81
|
+
|
82
|
+
## Copyright
|
83
|
+
|
84
|
+
Copyright (c) 2014 Chris Gaffney. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -2,16 +2,14 @@ require 'bundler/setup'
|
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
3
|
|
4
4
|
require 'rake'
|
5
|
-
require '
|
6
|
-
|
7
|
-
Spec::Rake::SpecTask.new(:spec) do |spec|
|
8
|
-
spec.libs << 'lib' << 'spec'
|
9
|
-
spec.spec_files = FileList['spec/**/*_spec.rb']
|
10
|
-
end
|
11
|
-
|
12
|
-
task :default => :spec
|
5
|
+
require 'rspec/core/rake_task'
|
13
6
|
|
14
7
|
desc "Run the certification tests against USPS's API. Requires ENV['USPS_USER'] to be set or passed in."
|
15
8
|
task :certify do
|
16
9
|
ruby "-rubygems -Ilib lib/usps/test.rb"
|
17
10
|
end
|
11
|
+
|
12
|
+
desc "Run RSpec tests"
|
13
|
+
RSpec::Core::RakeTask.new
|
14
|
+
|
15
|
+
task :default => :spec
|
data/lib/usps.rb
CHANGED
@@ -5,11 +5,12 @@ module USPS
|
|
5
5
|
require 'usps/errors'
|
6
6
|
require 'usps/configuration'
|
7
7
|
|
8
|
-
autoload :Client,
|
9
|
-
autoload :Address,
|
10
|
-
autoload :Request,
|
11
|
-
autoload :VERSION,
|
12
|
-
autoload :Response,
|
8
|
+
autoload :Client, 'usps/client'
|
9
|
+
autoload :Address, 'usps/address'
|
10
|
+
autoload :Request, 'usps/request'
|
11
|
+
autoload :VERSION, 'usps/version'
|
12
|
+
autoload :Response, 'usps/response'
|
13
|
+
autoload :TrackDetail, 'usps/track_detail'
|
13
14
|
|
14
15
|
class << self
|
15
16
|
attr_writer :config
|
data/lib/usps/address.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# the apartment, suite, etc... I have switched them to match how I see them on an envelope.
|
5
5
|
# Additionally they are refered to address and extra_address though both address1 and address2
|
6
6
|
# work. Just remember they are flip flopped based on the USPS documentation.
|
7
|
-
class USPS::Address < Struct.new(:name, :company, :address1, :address2, :city, :state, :zip5, :zip4)
|
7
|
+
class USPS::Address < Struct.new(:name, :company, :address1, :address2, :city, :state, :zip5, :zip4, :return_text)
|
8
8
|
|
9
9
|
# Alias address getters and setters for a slightly more expressive api
|
10
10
|
alias :address :address1
|
data/lib/usps/configuration.rb
CHANGED
data/lib/usps/request.rb
CHANGED
@@ -9,5 +9,6 @@ module USPS::Request
|
|
9
9
|
autoload :DeliveryConfirmation, 'usps/request/delivery_confirmation'
|
10
10
|
autoload :DeliveryConfirmationCertify, 'usps/request/delivery_confirmation_certify'
|
11
11
|
|
12
|
-
autoload :TrackingLookup,
|
12
|
+
autoload :TrackingLookup, 'usps/request/tracking_lookup'
|
13
|
+
autoload :TrackingFieldLookup, 'usps/request/tracking_field_lookup'
|
13
14
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module USPS::Request
|
2
|
+
# Given a valid USPS tracking number, use this class to request
|
3
|
+
# tracking information from USPS's systems.
|
4
|
+
#
|
5
|
+
# Returns a USPS::Response::TrackingFieldLookup object with the pertinent
|
6
|
+
# information
|
7
|
+
class TrackingFieldLookup < Base
|
8
|
+
config(
|
9
|
+
:api => 'TrackV2',
|
10
|
+
:tag => 'TrackFieldRequest',
|
11
|
+
:secure => false,
|
12
|
+
:response => USPS::Response::TrackingFieldLookup
|
13
|
+
)
|
14
|
+
|
15
|
+
# Build a new TrackingLookup request.
|
16
|
+
# Takes the USPS tracking number to request information for
|
17
|
+
def initialize(track_id)
|
18
|
+
@track_id = track_id
|
19
|
+
end
|
20
|
+
|
21
|
+
def build
|
22
|
+
super do |builder|
|
23
|
+
builder.tag!('TrackID', :ID => @track_id)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
data/lib/usps/response.rb
CHANGED
@@ -4,4 +4,5 @@ module USPS::Response
|
|
4
4
|
autoload :DeliveryConfirmation, 'usps/response/delivery_confirmation'
|
5
5
|
autoload :AddressStandardization, 'usps/response/address_standardization'
|
6
6
|
autoload :TrackingLookup, 'usps/response/tracking_lookup'
|
7
|
+
autoload :TrackingFieldLookup, 'usps/response/tracking_field_lookup'
|
7
8
|
end
|
@@ -21,6 +21,19 @@ module USPS::Response
|
|
21
21
|
@addresses[address]
|
22
22
|
end
|
23
23
|
alias :[] :get
|
24
|
+
|
25
|
+
def addresses
|
26
|
+
@addresses
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_h
|
30
|
+
hash = {}
|
31
|
+
@addresses.each_pair do |key, value|
|
32
|
+
hash[key.to_h] = value.to_h
|
33
|
+
end
|
34
|
+
|
35
|
+
hash
|
36
|
+
end
|
24
37
|
|
25
38
|
private
|
26
39
|
def parse(node)
|
@@ -31,7 +44,8 @@ module USPS::Response
|
|
31
44
|
:city => node.search('City').text,
|
32
45
|
:state => node.search('State').text,
|
33
46
|
:zip5 => node.search('Zip5').text,
|
34
|
-
:zip4 => node.search('Zip4').text
|
47
|
+
:zip4 => node.search('Zip4').text,
|
48
|
+
:return_text => node.search('ReturnText').text,
|
35
49
|
)
|
36
50
|
end
|
37
51
|
end
|
@@ -17,12 +17,26 @@ module USPS::Response
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
# Returns
|
21
|
-
# address from the results of the query.
|
20
|
+
# Returns a single city/state pair given a zip5
|
22
21
|
def get(zip)
|
23
22
|
@data[zip.to_i]
|
24
23
|
end
|
25
24
|
alias :[] :get
|
25
|
+
|
26
|
+
# Returns all city/state data from the query results
|
27
|
+
def data
|
28
|
+
@data
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns all city/state data as a pure Ruby hash (e.g. no Structs as values)
|
32
|
+
def to_h
|
33
|
+
hash = {}
|
34
|
+
@data.each_pair do |key, value|
|
35
|
+
hash[key] = value.to_h
|
36
|
+
end
|
37
|
+
|
38
|
+
hash
|
39
|
+
end
|
26
40
|
end
|
27
41
|
end
|
28
42
|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module USPS::Response
|
2
|
+
# Response object from a USPS::Request::TrackingLookup request.
|
3
|
+
# Includes a summary of the current status of the shipment, along with
|
4
|
+
# an array of details of the shipment's progress
|
5
|
+
class TrackingFieldLookup < Base
|
6
|
+
|
7
|
+
attr_accessor :summary, :details
|
8
|
+
|
9
|
+
|
10
|
+
def initialize(xml)
|
11
|
+
@summary = parse(xml.search("TrackSummary"))
|
12
|
+
@details = []
|
13
|
+
xml.search("TrackDetail").each do |detail|
|
14
|
+
@details << parse(detail)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def parse(node)
|
20
|
+
USPS::TrackDetail.new(
|
21
|
+
:event_time => node.search('EventTime').text,
|
22
|
+
:event_date => node.search('EventDate').text,
|
23
|
+
:event => node.search('Event').text,
|
24
|
+
:event_city => node.search('EventCity').text,
|
25
|
+
:event_state => node.search('EventState').text,
|
26
|
+
:event_zip_code => node.search('EventZIPCode').text,
|
27
|
+
:event_country => node.search('EventCountry').text,
|
28
|
+
:firm_name => node.search('FirmName').text,
|
29
|
+
:name => node.search('Name').text,
|
30
|
+
:authorized_agent => node.search('AuthorizedAgent').text
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'time'
|
2
|
+
# TODO: Documentation
|
3
|
+
#
|
4
|
+
class USPS::TrackDetail < Struct.new(:event_time, :event_date, :event, :event_city, :event_state, :event_zip_code, :event_country, :firm_name, :name, :authorized_agent)
|
5
|
+
|
6
|
+
# Alias address getters and setters for a slightly more expressive api
|
7
|
+
alias :city :event_city
|
8
|
+
alias :city= :event_city=
|
9
|
+
alias :state :event_state
|
10
|
+
alias :state= :event_state=
|
11
|
+
alias :zip_code :event_zip_code
|
12
|
+
alias :zip_code= :event_zip_code=
|
13
|
+
alias :country :event_country
|
14
|
+
alias :country= :event_country=
|
15
|
+
|
16
|
+
attr_reader :error
|
17
|
+
|
18
|
+
def initialize(options = {}, &block)
|
19
|
+
options.each_pair do |k, v|
|
20
|
+
self.send("#{k}=", v)
|
21
|
+
end
|
22
|
+
|
23
|
+
block.call(self) if block
|
24
|
+
end
|
25
|
+
|
26
|
+
def date
|
27
|
+
time = "#{event_date} #{event_time}".strip
|
28
|
+
begin
|
29
|
+
Time.parse(time) unless time.empty?
|
30
|
+
rescue ArgumentError
|
31
|
+
return nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Similar to Hash#replace, overwrite the values of this object with the other.
|
36
|
+
# It will not replace a provided key on the original object that does not exist
|
37
|
+
# on the replacing object (such as name with verification requests).
|
38
|
+
def replace(other)
|
39
|
+
raise ArgumentError unless other.is_a?(USPS::Address)
|
40
|
+
|
41
|
+
other.each_pair do |key, val|
|
42
|
+
# Do not overwrite values that may exist on the original but not on
|
43
|
+
# the replacement.
|
44
|
+
self[key] = val unless val.nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
self
|
48
|
+
end
|
49
|
+
end
|
data/lib/usps/version.rb
CHANGED
data/spec/address_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe USPS::Address do
|
|
4
4
|
it "should have the expected fields" do
|
5
5
|
address = USPS::Address.new
|
6
6
|
|
7
|
-
address.
|
7
|
+
expect(address).to respond_to(
|
8
8
|
:name, :name=,
|
9
9
|
:address1, :address1=,
|
10
10
|
:address2, :address2=,
|
@@ -22,21 +22,21 @@ describe USPS::Address do
|
|
22
22
|
:city => 'Holland'
|
23
23
|
)
|
24
24
|
|
25
|
-
address.name.
|
26
|
-
address.address.
|
27
|
-
address.city.
|
25
|
+
expect(address.name).to eq('Chris')
|
26
|
+
expect(address.address).to eq('123 Main St')
|
27
|
+
expect(address.city).to eq('Holland')
|
28
28
|
end
|
29
29
|
|
30
30
|
it "know how to combine the zip coes" do
|
31
|
-
USPS::Address.new(:zip5 => 12345).zip.
|
32
|
-
USPS::Address.new(:zip5 => 12345, :zip4 => 9999).zip.
|
31
|
+
expect(USPS::Address.new(:zip5 => 12345).zip).to eq('12345')
|
32
|
+
expect(USPS::Address.new(:zip5 => 12345, :zip4 => 9999).zip).to eq('12345-9999')
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should be able to parse zip into individual parts" do
|
36
36
|
addy = USPS::Address.new(:zip => '12345-9988')
|
37
|
-
addy.zip5.
|
38
|
-
addy.zip4.
|
39
|
-
addy.zip.
|
37
|
+
expect(addy.zip5).to eq('12345')
|
38
|
+
expect(addy.zip4).to eq('9988')
|
39
|
+
expect(addy.zip).to eq('12345-9988')
|
40
40
|
end
|
41
41
|
|
42
42
|
it "should be able to be verified with the USPS" do
|
@@ -48,18 +48,18 @@ describe USPS::Address do
|
|
48
48
|
:zip => 20006
|
49
49
|
)
|
50
50
|
|
51
|
-
USPS.client.
|
51
|
+
expect(USPS.client).to receive(:request).and_return(
|
52
52
|
USPS::Response::AddressStandardization.new(
|
53
53
|
addy, load_xml('address_standardization_1.xml')
|
54
54
|
)
|
55
55
|
)
|
56
56
|
|
57
|
-
addy.valid
|
57
|
+
expect(addy.valid?).to be_truthy
|
58
58
|
|
59
59
|
error = USPS::Error.new('error', '1234', 'source')
|
60
60
|
# Failure
|
61
|
-
USPS.client.
|
62
|
-
addy.valid
|
63
|
-
addy.error.
|
61
|
+
expect(USPS.client).to receive(:request).and_raise(error)
|
62
|
+
expect(addy.valid?).to be_falsey
|
63
|
+
expect(addy.error).to be(error)
|
64
64
|
end
|
65
65
|
end
|
data/spec/configuration_spec.rb
CHANGED
@@ -7,13 +7,13 @@ describe USPS::Configuration do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should have some sensible defaults" do
|
10
|
-
@config.username.
|
11
|
-
@config.timeout.
|
12
|
-
@config.testing.
|
10
|
+
expect(@config.username).to be_nil
|
11
|
+
expect(@config.timeout).to eq(5)
|
12
|
+
expect(@config.testing).to be_falsey
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should grab the username from the environment if available" do
|
16
16
|
ENV['USPS_USER'] = 'malcom77'
|
17
|
-
USPS::Configuration.new.username.
|
17
|
+
expect(USPS::Configuration.new.username).to eq('malcom77')
|
18
18
|
end
|
19
19
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<TrackResponse>
|
3
|
+
<TrackInfo ID="01805213907042762274">
|
4
|
+
<TrackSummary>
|
5
|
+
<EventTime>12:12 pm</EventTime>
|
6
|
+
<EventDate>May 21, 2001</EventDate>
|
7
|
+
<Event>DELIVERED</Event>
|
8
|
+
<EventCity>NEWTON</EventCity>
|
9
|
+
<EventState>IA</EventState>
|
10
|
+
<EventZIPCode>50208</EventZIPCode>
|
11
|
+
<EventCountry/>
|
12
|
+
<FirmName></FirmName>
|
13
|
+
<Name></Name>
|
14
|
+
<AuthorizedAgent></AuthorizedAgent>
|
15
|
+
</TrackSummary>
|
16
|
+
<TrackDetail>
|
17
|
+
<EventTime>9:24 pm</EventTime>
|
18
|
+
<EventDate>March 28, 2001</EventDate>
|
19
|
+
<Event>ENROUTE</Event>
|
20
|
+
<EventCity>DES MOINES</EventCity>
|
21
|
+
<EventState>IA</EventState>
|
22
|
+
<EventZIPCode>50395</EventZIPCode>
|
23
|
+
<EventCountry/>
|
24
|
+
<FirmName/>
|
25
|
+
<Name/>
|
26
|
+
<AuthorizedAgent/>
|
27
|
+
</TrackDetail>
|
28
|
+
<TrackDetail>
|
29
|
+
<EventTime>10:00 pm</EventTime>
|
30
|
+
<EventDate>March 27, 2001</EventDate>
|
31
|
+
<Event>ACCEPTANCE</Event>
|
32
|
+
<EventCity>BLAINE</EventCity>
|
33
|
+
<EventState>WA</EventState>
|
34
|
+
<EventZIPCode>98231</EventZIPCode>
|
35
|
+
<EventCountry/>
|
36
|
+
<FirmName/>
|
37
|
+
<Name/>
|
38
|
+
<AuthorizedAgent/>
|
39
|
+
</TrackDetail>
|
40
|
+
</TrackInfo>
|
41
|
+
</TrackResponse>
|