stamps 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.gitignore +5 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +49 -0
  5. data/README.md +186 -0
  6. data/Rakefile +13 -0
  7. data/lib/stamps.rb +33 -0
  8. data/lib/stamps/api.rb +18 -0
  9. data/lib/stamps/client.rb +12 -0
  10. data/lib/stamps/client/account.rb +36 -0
  11. data/lib/stamps/client/address.rb +16 -0
  12. data/lib/stamps/client/rate.rb +39 -0
  13. data/lib/stamps/client/stamp.rb +62 -0
  14. data/lib/stamps/configuration.rb +69 -0
  15. data/lib/stamps/errors.rb +34 -0
  16. data/lib/stamps/mapping.rb +247 -0
  17. data/lib/stamps/request.rb +55 -0
  18. data/lib/stamps/response.rb +71 -0
  19. data/lib/stamps/trash.rb +29 -0
  20. data/lib/stamps/types.rb +68 -0
  21. data/lib/stamps/version.rb +3 -0
  22. data/stamps.gemspec +33 -0
  23. data/test/client/account_test.rb +64 -0
  24. data/test/client/address_test.rb +36 -0
  25. data/test/client/rate_test.rb +44 -0
  26. data/test/client/stamp_test.rb +89 -0
  27. data/test/fixtures/AuthenticateUser.xml +9 -0
  28. data/test/fixtures/CancelIndicium.xml +8 -0
  29. data/test/fixtures/CarrierPickup.xml +11 -0
  30. data/test/fixtures/CleanseAddress.xml +24 -0
  31. data/test/fixtures/CreateIndicium.xml +32 -0
  32. data/test/fixtures/GetAccountInfo.xml +87 -0
  33. data/test/fixtures/GetRate.xml +163 -0
  34. data/test/fixtures/GetRates.xml +645 -0
  35. data/test/fixtures/InsufficientPostage.xml +14 -0
  36. data/test/fixtures/InvalidSoap.xml +13 -0
  37. data/test/fixtures/PurchasePostage.xml +16 -0
  38. data/test/fixtures/TrackShipment.xml +43 -0
  39. data/test/helper.rb +58 -0
  40. data/test/mapping_test.rb +33 -0
  41. data/test/response_test.rb +66 -0
  42. data/test/stamps_test.rb +26 -0
  43. data/test/types_test.rb +25 -0
  44. metadata +228 -0
@@ -0,0 +1,5 @@
1
+ coverage/*
2
+ pkg/*
3
+ *.gem
4
+ .bundle
5
+ runner.rb
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2@stamps --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in stamps.gemspec
4
+ gemspec
@@ -0,0 +1,49 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ stamps (0.0.1)
5
+ hashie (~> 1.0.0)
6
+ httpi (= 0.7.9)
7
+ json (~> 1.5.1)
8
+ multi_json (~> 0.0.5)
9
+ savon (>= 0.8.6)
10
+
11
+ GEM
12
+ remote: http://rubygems.org/
13
+ specs:
14
+ addressable (2.2.4)
15
+ awesome_print (0.3.2)
16
+ builder (2.1.2)
17
+ crack (0.1.8)
18
+ gyoku (0.4.2)
19
+ builder (>= 2.1.2)
20
+ hashie (1.0.0)
21
+ httpi (0.7.9)
22
+ rack
23
+ json (1.5.1)
24
+ mocha (0.9.12)
25
+ multi_json (0.0.5)
26
+ rack (1.2.2)
27
+ savon (0.8.6)
28
+ builder (>= 2.1.2)
29
+ crack (~> 0.1.8)
30
+ gyoku (>= 0.3.0)
31
+ httpi (>= 0.7.8)
32
+ shoulda (2.11.3)
33
+ simplecov (0.4.1)
34
+ simplecov-html (~> 0.4.3)
35
+ simplecov-html (0.4.3)
36
+ webmock (1.6.2)
37
+ addressable (>= 2.2.2)
38
+ crack (>= 0.1.7)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ awesome_print
45
+ mocha (~> 0.9.11)
46
+ shoulda (~> 2.11.3)
47
+ simplecov (~> 0.4.0)
48
+ stamps!
49
+ webmock (~> 1.6.2)
@@ -0,0 +1,186 @@
1
+ Stamps
2
+ ==========
3
+
4
+ Stamps is Stamps.com backed library for creating postage labels,
5
+ calculate the shipping cost of packages, standardize domestic
6
+ addresses via USPS CASS certified Address Matching Software, and track
7
+ shipments.
8
+
9
+ Main Features
10
+ ----------
11
+
12
+ 1. Create postage stamp labels in png and pdf formats.
13
+
14
+ 2. Standardizes shipping address that complies with the USPS address
15
+ formatting guidelines.
16
+
17
+ 3. Validates city, state, and postal code combinations.
18
+
19
+ 4. Calculate shipping rates based on distance and package weight.
20
+
21
+ 5. Request USPS carrier pick ups.
22
+
23
+ 6. Track shipment history.
24
+
25
+ 7. Purchase postage.
26
+
27
+ Pre-requisites
28
+ ----------
29
+ Register for the Stamps.com [Developer
30
+ Program](http://developer.stamps.com/developer) to receive a free
31
+ test account.
32
+
33
+ Sample Workflow
34
+ ----------
35
+
36
+ 1. Standardize Shipping Address - Ship-to addresses must be
37
+ standardized based on USPS rules for proper address conventions before
38
+ a shipping label can be issued.
39
+
40
+ 2. Get Rates - allow users to view and select the best shipping
41
+ service for their needs.
42
+
43
+ 3. Generate the Shipping Label - after choosing a shipping
44
+ service and ship-to address is standardized, the `Stamps.create` method
45
+ will generate the indicium required to ship the item. If
46
+ the customer changes their mind, they may want to select an option
47
+ that initiates a `Stamps.cancel`. `Stamps.cancel` refunds postage and
48
+ voids the shipping label.
49
+
50
+ 4. Print the Shipping Label - Call the returned URL to obtain the shipping label image.
51
+ A URL is returned by the `Stamps.create` call in the :url item. The
52
+ integration will connect to this URL to retrieve their shipping label
53
+ and customs forms for printing.
54
+
55
+ Getting Started
56
+ ----------
57
+ Once you have a test account with integration id, we can simple pass
58
+ them to the configure block:
59
+
60
+ # Authenticate you stamps.com credentials
61
+ Stamps.configure do |config|
62
+ config.integration_id = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX'
63
+ config.username = 'STAMPS USERNAME'
64
+ config.password = 'STAMPS PASSWORD'
65
+ end
66
+
67
+ Now we can now be able to retrieve information about our account:
68
+
69
+ Stamps.account
70
+
71
+ Standardized Shipping Address
72
+ ----------
73
+ Standardizes shipping address that complies with the USPS address
74
+ formatting guidelines
75
+
76
+ standardized_address = Stamps.clean_address(
77
+ :address => {
78
+ :full_name => 'The White House',
79
+ :address1 => '1600 Pennsylvania Avenue, NW',
80
+ :city => 'Washington',
81
+ :state => 'DC',
82
+ :zip_code => '20500'
83
+ })
84
+
85
+ Get Rates
86
+ ----------
87
+ To get a list of rates for all available USPS services based on the
88
+ ZIP Code or the foreign country being shipped to for a given package
89
+ weight and size.
90
+
91
+ rates = Stamps.get_rates(
92
+ :from_zip_code => '45440',
93
+ :to_zip_code => '20500',
94
+ :weight_lb => '0.5',
95
+ :ship_date => '2011-04-07'
96
+ )
97
+
98
+ Creating a shipping label
99
+ ----------
100
+ To generate the postage based on the shipping information provided in the request.
101
+ The `create!` method will return a URL that references either an image of the
102
+ domestic shipping label or a multi-page PDF document for international
103
+ labels with customs forms.
104
+
105
+ stamp = Stamps.create!(
106
+ :tracking_number => true,
107
+ :rate => rates.first,
108
+ :to => standardized_address,
109
+ :from => {
110
+ :full_name => 'Littlelines',
111
+ :address1 => '50 Chestnut Street',
112
+ :address2 => 'Suite 234',
113
+ :city => 'Beavervcreek',
114
+ :state => 'OH',
115
+ :zip_code => '45440'
116
+ },
117
+ :memo => 'Thanks for shopping with us!'
118
+ )
119
+
120
+ Now we can view or print the postage label:
121
+
122
+ stamp.url
123
+
124
+ General Configuration
125
+ ----------
126
+ If you want to see the data logged to and from the api:
127
+
128
+ Stamps.configure do |config|
129
+ config.log_messages = true
130
+ end
131
+
132
+ By default Stamps will return responses as a Hash. To make Stamps
133
+ return a Hashie instead:
134
+
135
+ Stamps.configure do |config|
136
+ config.format = :hashie
137
+ end
138
+
139
+ A return address can be specified in the configuration block as
140
+ well. This address will be used when the :from address is not specified
141
+ when creating new stamps
142
+
143
+ Stamps.configure do |config|
144
+ config.return_address = {
145
+ :full_name => 'Littlelines',
146
+ :address1 => '50 Chestnut Street',
147
+ :address2 => 'Suite 234',
148
+ :city => 'Beavercreek',
149
+ :state => 'OH',
150
+ :zip_code => '45440',
151
+ :phone_number => '9375545027'
152
+ }
153
+ end
154
+
155
+ Installation Steps
156
+ ----------
157
+ First install the gem:
158
+
159
+ gem install stamps
160
+
161
+ Add it to your Gemfile:
162
+
163
+ gem 'stamps'
164
+
165
+ Development
166
+ -----------
167
+
168
+ * Source hosted at [GitHub](https://github.com/mattsears/stamps).
169
+ * Report Issues/Questions/Feature requests on [GitHub Issues](https://github.com/mattsears/stamps/issues).
170
+
171
+ Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change
172
+ you make.
173
+
174
+ Author
175
+ ------
176
+ [Matt Sears](https://github.com/mattsears)
177
+
178
+
179
+
180
+
181
+
182
+
183
+
184
+
185
+
186
+
@@ -0,0 +1,13 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+ task :default => :test
6
+
7
+ desc 'Run tests (default)'
8
+ Rake::TestTask.new(:test) do |t|
9
+ t.test_files = FileList['test/**/*_test.rb']
10
+ t.ruby_opts = ['-Itest']
11
+ t.libs << "lib" << "test"
12
+ t.ruby_opts << '-rubygems' if defined? Gem
13
+ end
@@ -0,0 +1,33 @@
1
+ require 'stamps/errors'
2
+ require 'stamps/trash'
3
+ require 'stamps/configuration'
4
+ require 'stamps/api'
5
+ require 'stamps/mapping'
6
+ require 'stamps/types'
7
+ require 'stamps/client'
8
+
9
+ module Stamps
10
+ extend Configuration
11
+
12
+ API_VERSION = '1_0' # Stamps API version
13
+
14
+ # Alias for Stamps::Client.new
15
+ #
16
+ # @return [Stamps::Client]
17
+ #
18
+ def self.client(options={})
19
+ Stamps::Client.new(options)
20
+ end
21
+
22
+ # Delegate to Stamps::Client
23
+ def self.method_missing(method, *args, &block)
24
+ return super unless client.respond_to?(method)
25
+ client.send(method, *args, &block)
26
+ end
27
+
28
+ # Delegate to Stamps::Client
29
+ def self.respond_to?(method)
30
+ return client.respond_to?(method) || super
31
+ end
32
+
33
+ end
@@ -0,0 +1,18 @@
1
+ require File.expand_path('../request', __FILE__)
2
+
3
+ module Stamps
4
+ # @private
5
+ class API
6
+ # @private
7
+ attr_accessor *Configuration::VALID_OPTIONS_KEYS
8
+
9
+ # Creates a new API
10
+ def initialize(options={})
11
+ options = Stamps.options.merge(options)
12
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
13
+ send("#{key}=", options[key])
14
+ end
15
+ end
16
+ include Request
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ module Stamps
2
+ # Wrapper for the Stamps Web Services API
3
+ #
4
+ class Client < API
5
+ Dir[File.expand_path('../client/*.rb', __FILE__)].each{|f| require f}
6
+ include Stamps::Mapping
7
+ include Stamps::Client::Account
8
+ include Stamps::Client::Address
9
+ include Stamps::Client::Rate
10
+ include Stamps::Client::Stamp
11
+ end
12
+ end
@@ -0,0 +1,36 @@
1
+ module Stamps
2
+ class Client
3
+ module Account
4
+
5
+ # Returns information about the stamps account
6
+ #
7
+ # @param params [Hash] authenticator, address, rates.
8
+ # @return [Hash]
9
+ #
10
+ def account(params = {})
11
+ params[:authenticator] = authenticator_token
12
+ response = request('GetAccountInfo', Stamps::Mapping::Account.new(params) )
13
+ response[:get_account_info_response][:account_info] if response
14
+ end
15
+
16
+ # Add funds to postage account
17
+ #
18
+ def purchase_postage(params = {})
19
+ params[:authenticator] = authenticator_token
20
+ response = request('PurchasePostage', Stamps::Mapping::PurchasePostage.new(params))
21
+ response[:purchase_postage_response] if response
22
+ end
23
+
24
+ # Request carrier pickup
25
+ # TODO: Should this go somewhere else?
26
+ #
27
+ def carrier_pickup(params = {})
28
+ params[:authenticator] = authenticator_token
29
+ response = request('CarrierPickup', Stamps::Mapping::CarrierPickup.new(params))
30
+ response[:carrier_pickup_response] if response
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,16 @@
1
+ module Stamps
2
+ class Client
3
+ module Address
4
+
5
+ # Authorizes the User and returns authenticator token
6
+ #
7
+ def clean_address(params = {})
8
+ params[:authenticator] = authenticator_token
9
+ response = request('CleanseAddress', Stamps::Mapping::CleanseAddress.new(params))
10
+ response[:errors].empty? ? response[:cleanse_address_response] : response
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,39 @@
1
+ module Stamps
2
+ class Client
3
+
4
+ # Produces a list of rates for all available USPS services based
5
+ # on the ZIP Code or the foreign country being shipped to for
6
+ # a given package weight and size.
7
+ #
8
+ # == Examples:
9
+ #
10
+ # Stamps.get_rates(
11
+ # :from_zip_code => '45440',
12
+ # :to_zip_code => '45458',
13
+ # :weight_oz => '8.0',
14
+ # :ship_date => '2011-06-01'
15
+ # )
16
+ #
17
+ module Rate
18
+
19
+ # Produces a list of rates matching the criteria provided in
20
+ # the parameters
21
+ #
22
+ def get_rates(params = {})
23
+ rates = Stamps::Mapping::Rates.new({
24
+ :authenticator => authenticator_token,
25
+ :rate => Stamps::Mapping::Rate.new(params)
26
+ })
27
+ response = request('GetRates', rates)
28
+ response[:get_rates_response].nil? ? response : [response[:get_rates_response][:rates][:rate]].flatten
29
+ end
30
+
31
+ def get_rate(params = {})
32
+ rates = get_rates(params)
33
+ rates.is_a?(Array) ? rates.first : rates
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,62 @@
1
+ module Stamps
2
+ class Client
3
+
4
+ # == Stamp Module
5
+ #
6
+ # Stamp provides an interface to creating and cancelling postage labels
7
+ #
8
+ #
9
+ module Stamp
10
+
11
+ # Creates postage labels.
12
+ #
13
+ # In order to successfully create postage labels, the following steps
14
+ # must happen:
15
+ #
16
+ # 1. Authentiation - identify the user and ensure that the user is
17
+ # authorized to perform the operation.
18
+ #
19
+ # 2. CleanseAddress - Ship-to addresses must be standardized based on
20
+ # USPS rules for proper address conventions before a shipping label
21
+ # can be issued.
22
+ #
23
+ # 3. GetRates - A call to GetRates will allow users to view and select
24
+ # the best shipping service for their needs.
25
+ #
26
+ # @param params [Hash] authenticator, address, rates.
27
+ # @return [Hash]
28
+ #
29
+ def create!(params = {})
30
+ params[:authenticator] = authenticator_token unless params[:authenticator]
31
+ params[:from] ||= Hash.new
32
+ response = request('CreateIndicium', Stamps::Mapping::Stamp.new(params))
33
+ response[:errors].empty? ? response[:create_indicium_response] : response
34
+ end
35
+
36
+ # Refunds postage and voids the shipping label
37
+ #
38
+ # @param [Hash] authenticator
39
+ #
40
+ def cancel!(params = {})
41
+ params[:authenticator] = authenticator_token unless params[:authenticator]
42
+ response = request('CancelIndicium', Stamps::Mapping::CancelStamp.new(params))
43
+ response[:errors].empty? ? response[:cancel_indicium_response] : response
44
+ end
45
+
46
+ # Returns an array of tracking events
47
+ #
48
+ # @param [String] the transaction id of the stamp
49
+ #
50
+ def track(stamps_transaction_id)
51
+ params = {
52
+ :authenticator => authenticator_token,
53
+ :stamps_transaction_id => stamps_transaction_id
54
+ }
55
+ response = request('TrackShipment', Stamps::Mapping::TrackShipment.new(params))
56
+ response[:errors].empty? ? response[:track_shipment_response] : response
57
+ end
58
+
59
+ end
60
+ end
61
+ end
62
+