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,29 @@
1
+ require 'hashie/trash'
2
+
3
+ module Hashie
4
+ class Trash
5
+
6
+ class << self
7
+ attr_reader :properties
8
+ end
9
+
10
+ # Use a n Array instead of a set since order is important
11
+ # TODO: Look at https://github.com/ahoward/map
12
+ instance_variable_set('@properties', Array.new)
13
+
14
+
15
+ # Sort the hash by the order in which the properties are declared
16
+ def to_hash
17
+ sorted_keys = self.class.properties.map{|prop| prop.to_s} & self.keys
18
+
19
+ # Use active_support for ordering hashes for Ruby < 1.9
20
+ out = RUBY_VERSION >= '1.9' ? {} : ActiveSupport::OrderedHash.new
21
+ sorted_keys.each do |k|
22
+ next if self[k].nil?
23
+ out[k] = Hashie::Hash === self[k] ? self[k].to_hash : self[k]
24
+ end
25
+ out
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,68 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Stamps
3
+ module Types
4
+
5
+ # TODO: Need to figure out how to parse the wsdl file for types
6
+ # instead of hard-coding them here
7
+ PACKAGE = [
8
+ 'Postcard',
9
+ 'Letter',
10
+ 'Large envelope or flat',
11
+ 'Thick envelope',
12
+ 'Package',
13
+ 'Flat Rate Box',
14
+ 'Small Flat Rate Box',
15
+ 'Large Flat Rate Box',
16
+ 'Flat Rate Envelope',
17
+ 'Flat Rate Padded Envelope',
18
+ 'Large Package',
19
+ 'Oversized Package'].freeze
20
+
21
+ SERVICE = {
22
+ 'US-FC' => 'USPS First-Class Mail',
23
+ 'US-MM' => 'USPS Media Mail',
24
+ 'US-PP' => 'USPS Parcel Post',
25
+ 'US-PM' => 'USPS Priority Mail',
26
+ 'US-XM' => 'USPS Express Mail',
27
+ 'US-EMI' => 'USPS Express Mail International',
28
+ 'US-PMI' => 'USPS Priority Mail International',
29
+ 'US-FCI' => 'USPS First Class Mail International'
30
+ }
31
+
32
+ ADD_ONS = {
33
+ 'SC-A-HP' => 'Hidden Postage',
34
+ 'SC-A-INS' => 'Insurance',
35
+ 'SC-A-INSRM' => 'Insurance for Registered Mail',
36
+ 'US-A-CM' => 'Certified Mail',
37
+ 'US-A-COD' => 'Collect on Delivery',
38
+ 'US-A-COM' => 'Certificate of Mailing',
39
+ 'US-A-DC' => 'USPS Delivery Confirmation',
40
+ 'US-A-ESH' => 'USPS Express - Sunday / Holiday Guaranteed',
41
+ 'US-A-INS' => 'USPS Insurance',
42
+ 'US-A-NDW' => 'USPS Express - No Delivery on Saturdays',
43
+ 'US-A-RD' => 'Restricted Delivery',
44
+ 'US-A-REG' => 'Registered Mail',
45
+ 'US-A-RR' => 'Return Receipt Requested',
46
+ 'US-A-RRM' => 'Return Receipt for Merchandise',
47
+ 'US-A-SC' => 'USPS Signature Confirmation',
48
+ 'US-A-SH' => 'Special Handling',
49
+ 'US-A-WDS' => 'USPS Express - Waive Delivery Signature',
50
+ 'US-A-NDW' => 'Do not Deliver on Saturday',
51
+ 'US-A-ESH' => 'Sunday/Holiday Delivery Guaranteed',
52
+ 'US-A-NND' => 'Notice of non-delivery',
53
+ }
54
+
55
+ CARRIER_PICKUP_LOCATION = {
56
+ 'FrontDoor' => 'Packages are at front door',
57
+ 'BackDoor' => 'Packages are at back door',
58
+ 'SideDoor' => 'Packages are at side door',
59
+ 'KnockOnDoorOrRingBell' => 'Knock on door or ring bell',
60
+ 'MailRoom' => 'Packages are in mail room',
61
+ 'Office' => 'Packages are in office',
62
+ 'Reception' => 'Packages are at reception area',
63
+ 'InOrAtMailbox' => 'Packages are in mail box',
64
+ 'Other' => 'Other Location'
65
+ }
66
+
67
+ end
68
+ end
@@ -0,0 +1,3 @@
1
+ module Stamps
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "stamps/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "stamps"
7
+ s.version = Stamps::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Matt Sears"]
10
+ s.email = ["matt@mattsears.com"]
11
+ s.homepage = "http://rubygems.org/gems/stamps"
12
+ s.summary = %q{Ruby wrapper for the Stamps.com Web Services API}
13
+ s.description = %q{Stamps is Stamps.com backed library for creating postage labels, calculate the shipping cost of packages, standardize domestic addresses via USPS CASS certified Address Matching Software, and track shipments.}
14
+
15
+ s.rubyforge_project = "stamps"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency('simplecov', '~> 0.4.0')
23
+ s.add_development_dependency('shoulda', '~> 2.11.3')
24
+ s.add_development_dependency('mocha', '~> 0.9.11')
25
+ s.add_development_dependency('webmock', '~> 1.6.2')
26
+ s.add_development_dependency('awesome_print')
27
+
28
+ s.add_runtime_dependency('httpi', '0.7.9')
29
+ s.add_runtime_dependency('savon', '>= 0.8.6')
30
+ s.add_runtime_dependency('json', '~> 1.5.1')
31
+ s.add_runtime_dependency('multi_json', '~> 0.0.5')
32
+ s.add_runtime_dependency('hashie', '~> 1.0.0')
33
+ end
@@ -0,0 +1,64 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../' # allows command line to execute tests
2
+ require 'helper'
3
+
4
+ class AccountTest < Test::Unit::TestCase
5
+
6
+ context '#account' do
7
+ setup { stub_post('AuthenticateUser') }
8
+
9
+ context 'with valid data' do
10
+ setup do
11
+ stub_post('GetAccountInfo')
12
+ @account = Stamps.account
13
+ end
14
+
15
+ should 'assign the user id' do
16
+ assert_equal '1111111', @account[:user_id]
17
+ end
18
+ end
19
+ end
20
+
21
+ context '#purchase_postage' do
22
+ setup { stub_post('AuthenticateUser') }
23
+
24
+ context 'with valid data' do
25
+ setup do
26
+ stub_post('PurchasePostage')
27
+ @purchase = Stamps.purchase_postage
28
+ end
29
+
30
+ should 'return reject reason' do
31
+ assert_equal 'order being processed', @purchase[:rejection_reason]
32
+ end
33
+
34
+ should 'return postage balannce' do
35
+ assert_equal '23.4300', @purchase[:postage_balance][:available_postage]
36
+ end
37
+
38
+ end
39
+ end
40
+
41
+ context '#carrier_pickup' do
42
+ setup { stub_post('AuthenticateUser') }
43
+
44
+ context 'with valid data' do
45
+
46
+ setup do
47
+ stub_post('CarrierPickup')
48
+ @carrier_pickup = Stamps.carrier_pickup()
49
+ end
50
+
51
+ should 'return pickup date' do
52
+ assert '01/29/2011', @carrier_pickup[:pickup_date]
53
+ end
54
+
55
+ should 'return pickup day of the week' do
56
+ assert 'Saturday', @carrier_pickup[:pick_up_day_of_week]
57
+ end
58
+
59
+ should 'return a confirmation number' do
60
+ assert 'WTC7812296', @carrier_pickup[:confirmation_number]
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,36 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../' # allows command line to execute tests
2
+ require 'helper'
3
+
4
+ class AddressTest < Test::Unit::TestCase
5
+
6
+ context '#clean_address' do
7
+ setup {stub_post('AuthenticateUser') }
8
+
9
+ context 'with valid data' do
10
+ setup do
11
+ stub_post('CleanseAddress')
12
+ @address = Stamps.clean_address(
13
+ :address => {
14
+ :full_name => 'Matt Sears'
15
+ }
16
+ )
17
+ end
18
+
19
+ should 'return the clean address' do
20
+ assert_equal 'MATT SEARS', @address[:address][:full_name]
21
+ assert_equal 'MATT SEARS', @address[:address][:full_name]
22
+ end
23
+
24
+ should 'return a cleanse hash' do
25
+ assert 'W9pHbVsNIdYE8/B6SyQ4wOkIIr9kZWFkYmVlZg==20110713', @address[:address][:cleanse_hash]
26
+ end
27
+
28
+ should 'indicate if the address match' do
29
+ assert @address[:address_match]
30
+ assert @address[:city_state_zip_ok]
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,44 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../' # allows command line to execute tests
2
+ require 'helper'
3
+
4
+ class StampsTest < Test::Unit::TestCase
5
+ context "Stamp::Client:Rate" do
6
+ setup do
7
+ stub_post("AuthenticateUser")
8
+ end
9
+
10
+ context ".get_rates" do
11
+
12
+ setup do
13
+ stub_post("GetRates")
14
+ @rates = Stamps.get_rates
15
+ end
16
+
17
+ should 'return an array of rates' do
18
+ assert_equal Array, @rates.class
19
+ end
20
+
21
+ should 'assign the amount for a given rate' do
22
+ assert_equal '2.41', @rates.first[:amount]
23
+ end
24
+
25
+ end
26
+
27
+ context '.get_rates with package and service types' do
28
+
29
+ setup do
30
+ stub_post("GetRate", 'GetRates')
31
+ @rate = Stamps.get_rate
32
+ end
33
+
34
+ should 'return an hash for the single rate' do
35
+ assert_equal Hash, @rate.class
36
+ end
37
+
38
+ should 'return an array of addons' do
39
+ assert_equal Hash, @rate[:add_ons].class
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,89 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../' # allows command line to execute tests
2
+ require 'helper'
3
+
4
+ class StampTest < Test::Unit::TestCase
5
+
6
+ context '.create' do
7
+ setup {stub_post('AuthenticateUser') }
8
+
9
+ context 'with valid data' do
10
+ setup do
11
+ stub_post('CreateIndicium')
12
+ @stamp = Stamps.create!(
13
+ :transaction_id => "1234567890ABCDEFG",
14
+ :rate => {
15
+ :add_ons => {
16
+ :add_on => [
17
+ { :type => 'US-A-COD' },
18
+ { :amount => '0.19', :type => 'US-A-DC' }
19
+ ]
20
+ }
21
+ },
22
+ :to => {:full_name => 'Matt Sears'},
23
+ :customs => {
24
+ :customs_lines => [
25
+ :custom => {
26
+ :description => 'Tee Shirt',
27
+ :quantity => 1,
28
+ :weight_oz => '7.8',
29
+ :value => 18.00
30
+ }
31
+ ]
32
+ })
33
+ end
34
+
35
+ should 'return the url for the stamp' do
36
+ assert @stamp[:url]
37
+ end
38
+
39
+ should 'return the postage balance' do
40
+ assert_equal '5.8600', @stamp[:postage_balance][:available_postage]
41
+ assert_equal '10.00', @stamp[:postage_balance][:control_total]
42
+ end
43
+
44
+ end
45
+ end
46
+
47
+ context '.cancel' do
48
+ setup {stub_post('AuthenticateUser') }
49
+
50
+ context 'with valid data' do
51
+ setup do
52
+ stub_post('CancelIndicium')
53
+ @cancel = Stamps.cancel!
54
+ end
55
+
56
+ should 'return just the authenticator' do
57
+ assert @cancel[:authenticator]
58
+ end
59
+
60
+ end
61
+ end
62
+
63
+ context '.track' do
64
+ setup {stub_post('AuthenticateUser') }
65
+
66
+ context 'with valid data' do
67
+
68
+ setup do
69
+ stub_post('TrackShipment')
70
+ @track = Stamps.track('342343243243')
71
+ end
72
+
73
+ should 'return an list of tracking events' do
74
+ assert_equal 3, @track[:tracking_events][:tracking_event].size
75
+ end
76
+
77
+ should 'map individual tracking event properties' do
78
+ tracking_event = @track[:tracking_events][:tracking_event].first
79
+ assert_equal 'DELIVERED', tracking_event[:event]
80
+ assert_equal 'FORT WAYNE', tracking_event[:city]
81
+ assert_equal 'IN', tracking_event[:state]
82
+ assert_equal '46809', tracking_event[:zip]
83
+ assert_equal 'US', tracking_event[:country]
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema">
4
+ <soap:Body>
5
+ <AuthenticateUserResponse xmlns="http://stamps.com/xml/namespace/2010/11/swsim/swsimv12">
6
+ <Authenticator>SdU5rk6BkFZahwAsmH6EwLVu2Iw=</Authenticator>
7
+ </AuthenticateUserResponse>
8
+ </soap:Body>
9
+ </soap:Envelope>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3
+ <soap:Body>
4
+ <CancelIndiciumResponse xmlns="http://stamps.com/xml/namespace/2010/11/swsim/swsimv12">
5
+ <Authenticator>yxj7EBWLh1EraJrawFhslf+L+Qs=</Authenticator>
6
+ </CancelIndiciumResponse>
7
+ </soap:Body>
8
+ </soap:Envelope>
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3
+ <soap:Body>
4
+ <CarrierPickupResponse xmlns="http://stamps.com/xml/namespace/2010/11/swsim/swsimv12">
5
+ <Authenticator>***authenticator***</Authenticator>
6
+ <PickupDate>01/29/2011</PickupDate>
7
+ <PickUpDayOfWeek>Saturday</PickUpDayOfWeek>
8
+ <ConfirmationNumber>WTC7812296</ConfirmationNumber>
9
+ </CarrierPickupResponse>
10
+ </soap:Body>
11
+ </soap:Envelope>
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3
+ <soap:Body>
4
+ <CleanseAddressResponse xmlns="http://stamps.com/xml/namespace/2010/11/swsim/swsimv12">
5
+ <Authenticator>ZVk2fjKAIR8AgCYYo+3EQuylEHg=</Authenticator>
6
+ <Address>
7
+ <FullName>MATT SEARS</FullName>
8
+ <Address1>123 MOCKINGBIRD LANE</Address1>
9
+ <Address2 />
10
+ <City>NEW YORK</City>
11
+ <State>NY</State>
12
+ <ZIPCode>11111</ZIPCode>
13
+ <ZIPCodeAddOn>222</ZIPCodeAddOn>
14
+ <DPB>06</DPB>
15
+ <CheckDigit>5</CheckDigit>
16
+ <Urbanization />
17
+ <CleanseHash>W9pHbVsNIdYE8/B6SyQ4wOkIIr9kZWFkYmVlZg==20110713</CleanseHash>
18
+ <OverrideHash>PxU7xsTh5+lebMpE9IcjOWQS0alkZWFkYmVlZg==20110713</OverrideHash>
19
+ </Address>
20
+ <AddressMatch>true</AddressMatch>
21
+ <CityStateZipOK>true</CityStateZipOK>
22
+ </CleanseAddressResponse>
23
+ </soap:Body>
24
+ </soap:Envelope>
@@ -0,0 +1,32 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3
+ <soap:Body>
4
+ <CreateIndiciumResponse xmlns="http://stamps.com/xml/namespace/2010/11/swsim/swsimv12">
5
+ <Authenticator>SfOQgTEPIqQRO6ZgZvfcegLDUzA=</Authenticator>
6
+ <IntegratorTxID>1234567890ABCDEF</IntegratorTxID>
7
+ <Rate>
8
+ <FromZIPCode>10008</FromZIPCode>
9
+ <ToZIPCode>45458</ToZIPCode>
10
+ <Amount>2.07</Amount>
11
+ <ServiceType>US-FC</ServiceType>
12
+ <PrintLayout>Untrackable</PrintLayout>
13
+ <DeliverDays>1</DeliverDays>
14
+ <WeightLb>0.5</WeightLb>
15
+ <PackageType>Large Envelope or Flat</PackageType>
16
+ <ShipDate>2011-04-07</ShipDate>
17
+ <DimWeighting>N</DimWeighting>
18
+ <EffectiveWeightInOunces>8</EffectiveWeightInOunces>
19
+ <IsIntraBMC>true</IsIntraBMC>
20
+ <Zone>1</Zone>
21
+ <RateCategory>268959776</RateCategory>
22
+ </Rate>
23
+ <StampsTxID>fa7618c4-013c-4e5f-b42e-7591dd55bea6</StampsTxID>
24
+ <URL>https://swsim.testing.example.com.com/Label/label.ashx/label-200-r90.png</URL>
25
+ <PostageBalance>
26
+ <AvailablePostage>5.8600</AvailablePostage>
27
+ <ControlTotal>10.00</ControlTotal>
28
+ </PostageBalance>
29
+ <Mac>KDTpVEcj3SyynhawyTYT1ikB5IE=</Mac>
30
+ </CreateIndiciumResponse>
31
+ </soap:Body>
32
+ </soap:Envelope>