stamps 0.2.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.
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
+