ups_shipping 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,190 @@
1
+ require "nokogiri"
2
+ require "httparty"
3
+ require 'ups_shipping/address'
4
+ require 'ups_shipping/organization'
5
+ require 'ups_shipping/package'
6
+ require 'ups_shipping/pickup'
7
+
8
+ module Shipping
9
+
10
+ VERSION = '1.0.0'
11
+
12
+ class UPS
13
+
14
+ TEST_URL = "https://wwwcie.ups.com"
15
+ LIVE_URL = "https://onlinetools.ups.com"
16
+
17
+ class Http
18
+ include HTTParty
19
+ base_uri LIVE_URL
20
+
21
+ def initialize(access_request, options={})
22
+ @access_request = access_request
23
+
24
+ if (options[:test])
25
+ self.class.base_uri TEST_URL
26
+ end
27
+ end
28
+
29
+ def commit(url, request)
30
+ request = @access_request + request
31
+ self.class.post(url, :body => request).parsed_response
32
+ end
33
+ end
34
+
35
+ def initialize(user, password, license, options={})
36
+ @options = options
37
+ @shipper = options[:shipper]
38
+ @access_request = access_request(user, password, license)
39
+ @http = Http.new(@access_request, :test => @options[:test])
40
+
41
+ @services = {
42
+ "01" => "Next Day Air",
43
+ "02" => "2nd Day Air",
44
+ "03" => "Ground",
45
+ "07" => "Express",
46
+ "08" => "Expedited",
47
+ "11" => "UPS Standard",
48
+ "12" => "3 Day Select",
49
+ "13" => "Next Day Air Saver",
50
+ "14" => "Next Day Air Early AM",
51
+ "54" => "Express Plus",
52
+ "59" => "2nd Day Air A.M.",
53
+ "65" => "UPS Saver",
54
+ "82" => "UPS Today Standard",
55
+ "83" => "UPS Today Dedicated Courier",
56
+ "84" => "UPS Today Intercity",
57
+ "85" => "UPS Today Express",
58
+ "86" => "UPS Today Express Saver"
59
+ }
60
+
61
+ end
62
+
63
+ def validate_address(address)
64
+ validate_request = Nokogiri::XML::Builder.new do |xml|
65
+ xml.AddressValidationRequest {
66
+ xml.Request {
67
+ xml.RequestAction "XAV"
68
+ xml.RequestOption "3"
69
+ }
70
+ xml.AddressKeyFormat {
71
+ xml.AddressLine address.address_line[0]
72
+ xml.PoliticalDivision2 address.city
73
+ xml.PoliticalDivision1 address.state
74
+ xml.PostcodePrimaryLow address.zip
75
+ xml.CountryCode address.country
76
+ }
77
+ }
78
+ end
79
+ @http.commit("/ups.app/xml/XAV", validate_request.to_xml)
80
+ end
81
+
82
+ def find_rates(package, origin, destination, options={})
83
+ rate_request = Nokogiri::XML::Builder.new do |xml|
84
+ xml.RatingServiceSelectionRequest {
85
+ xml.Request {
86
+ xml.RequestAction "Rate"
87
+ xml.RequestOption "Rate"
88
+ }
89
+ if options[:pickup]
90
+ @options[:pickup].build_type(xml)
91
+ end
92
+ @shipper.build(xml, "Shipper")
93
+ destination.build(xml, "ShipTo")
94
+ origin.build(xml, "ShipFrom")
95
+ xml.PaymentInformation {
96
+ xml.Prepaid {
97
+ xml.BillShipper {
98
+ xml.AccountNumber "Ship Number"
99
+ }
100
+ }
101
+ }
102
+ package.build(xml)
103
+ }
104
+ end
105
+ @http.commit("/ups.app/xml/Rate", rate_request.to_xml)
106
+ end
107
+
108
+ def request_shipment(package, origin, destination, service, options={})
109
+ shipment_request = Nokogiri::XML::Builder.new do |xml|
110
+ xml.ShipmentConfirmRequest {
111
+ xml.Request {
112
+ xml.RequestAction "ShipConfirm"
113
+ xml.RequestOptions "validate"
114
+ }
115
+ if options[:label]
116
+ xml.LabelSpecification {
117
+ xml.LabelPrintMethod {
118
+ xml.Code "GIF"
119
+ xml.Description "gif file"
120
+ }
121
+ xml.HTTPUserAgent "Mozilla/4.5"
122
+ xml.LabelImageFormat {
123
+ xml.Code "GIF"
124
+ xml.Description "gif"
125
+ }
126
+ }
127
+ end
128
+ @shipper.build(xml, "Shipper")
129
+ destination.build(xml, "ShipTo")
130
+ origin.build(xml, "ShipFrom")
131
+ xml.PaymentInformation {
132
+ xml.Prepaid {
133
+ xml.BillShipper {
134
+ xml.AccountNumber "Ship Number"
135
+ }
136
+ }
137
+ }
138
+ xml.Service {
139
+ xml.Code service
140
+ xml.Description @services[service]
141
+ }
142
+ package.build(xml)
143
+ }
144
+ end
145
+ @http.commit("/ups.app/xml/ShipConfirm", shipment_request.to_xml)
146
+ end
147
+
148
+ def cancel_shipment(shipment_id)
149
+ cancel_request = Nokogiri::XML::Builder.new do |xml|
150
+ xml.VoidShipmentRequest {
151
+ xml.Request {
152
+ xml.RequestAction "1"
153
+ xml.RequestOption "1"
154
+ }
155
+ xml.ShipmentIdentificationNumber shipment_id
156
+ }
157
+ end
158
+ @http.commit("/ups.app/xml/Void", cancel_request.to_xml)
159
+ end
160
+
161
+ def track_shipment(tracking_number)
162
+ track_request = Nokogiri::XML::Builder.new do
163
+ TrackRequest {
164
+ Request {
165
+ RequestAction "Track"
166
+ RequestOption "activity"
167
+ }
168
+ TrackingNumber tracking_number
169
+ }
170
+ end
171
+
172
+ @http.commit("/ups.app/xml/Track", track_request.to_xml)
173
+ end
174
+
175
+
176
+ private
177
+ def access_request(user, password, license)
178
+ access_request = Nokogiri::XML::Builder.new do
179
+ AccessRequest {
180
+ AccessLicenseNumber license
181
+ UserId user
182
+ Password password
183
+ }
184
+ end
185
+
186
+ access_request.to_xml
187
+ end
188
+
189
+ end
190
+ end
@@ -0,0 +1,39 @@
1
+ require "nokogiri"
2
+
3
+ module Shipping
4
+ class Address
5
+ ADDRESS_TYPES = %w{residential commercial po_box}
6
+ attr_accessor :address_lines
7
+ :city
8
+ :state
9
+ :zip
10
+ :country
11
+ :type
12
+
13
+ def initialize(options={})
14
+ @address_lines = options[:address_lines]
15
+ @city = options[:city]
16
+ @state = options[:state]
17
+ @zip = options[:zip]
18
+ @country = options[:country]
19
+ @type = options[:type]
20
+ end
21
+
22
+ def build(xml)
23
+ xml.Address {
24
+ xml.AddressLine1 @address_lines[0]
25
+ xml.City @city
26
+ xml.StateProvinceCode @state
27
+ xml.PostalCode @zip
28
+ xml.CountryCode @country
29
+ }
30
+ end
31
+
32
+ def to_xml()
33
+ builder = Nokogiri::XML::Builder.new do |xml|
34
+ build(xml)
35
+ end
36
+ builder.to_xml
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ require "nokogiri"
2
+
3
+ module Shipping
4
+ class Organization
5
+ attr_accessor :name
6
+ :phone
7
+ :email
8
+ :address
9
+ :shipper_number
10
+
11
+
12
+ def initialize(options={})
13
+ @name = options[:name]
14
+ @phone = options[:phone]
15
+ @address = options[:address]
16
+ if options[:shipper_number]
17
+ @shipper_number = options[:shipper_number]
18
+ end
19
+ end
20
+
21
+ def build(xml, rootname)
22
+ xml.send(rootname) {
23
+ xml.CompanyName @name
24
+ xml.PhoneNumber @phone
25
+ if @shipper_number
26
+ xml.ShipperNumber @shipper_number
27
+ end
28
+ @address.build(xml)
29
+ }
30
+ end
31
+
32
+ def to_xml(rootname)
33
+ builder = Nokogiri::XML::Builder.new do |xml|
34
+ build(xml, rootname)
35
+ end
36
+ builder.to_xml
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,45 @@
1
+ require "nokogiri"
2
+
3
+ module Shipping
4
+ class Package
5
+ attr_accessor :large
6
+ :weight
7
+ :description
8
+ :monetary_value
9
+
10
+ def initialize(options={})
11
+ @large = options[:large]
12
+ @weight = options[:weight]
13
+ @description = options[:description]
14
+ @monetary_value = options[:monetary_value]
15
+ end
16
+
17
+ def build(xml)
18
+ xml.Package {
19
+ xml.PackagingType {
20
+ xml.Code "02"
21
+ xml.Description "Customer Supplied"
22
+ }
23
+ xml.Description @description
24
+ xml.ReferenceNumber {
25
+ xml.Code "00"
26
+ xml.Value "Package"
27
+ }
28
+ xml.PackageWeight {
29
+ xml.UnitOfMeasurement
30
+ xml.Weight @weight
31
+ }
32
+ if @large
33
+ xml.LargePackageIndicator
34
+ end
35
+ }
36
+ end
37
+
38
+ def to_xml()
39
+ builder = Nokogiri::XML::Builder.new do |xml|
40
+ build(xml)
41
+ end
42
+ builder.to_xml
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,49 @@
1
+ require "nokogiri"
2
+
3
+ module Shipping
4
+ class Pickup
5
+ attr_accessor :address_lines
6
+ :pickup_day
7
+ :contact_method
8
+ :type
9
+
10
+ def initialize(options={})
11
+ @type = options[:type]
12
+ if options[:pickup_day]
13
+ @pickup_day = options[:pickup_day]
14
+ end
15
+ if options[:contact_method]
16
+ @contact_method = options[:contact_method]
17
+ end
18
+
19
+ @pickupTypes = {
20
+ "01" => "Daily Pickup",
21
+ "03" => "Customer Counter",
22
+ "06" => "One Time Pickup",
23
+ "07" => "On Call Air",
24
+ "19" => "Letter Center",
25
+ "20" => "Air Service Center"
26
+ }
27
+ end
28
+
29
+ def build_schedule(xml)
30
+ xml.OnCallAir {
31
+ xml.Schedule {
32
+ if @pickup_day
33
+ xml.PickupDay @pickup_day
34
+ end
35
+ if @contact_method
36
+ xml.Method @contact_method
37
+ end
38
+ }
39
+ }
40
+ end
41
+
42
+ def build_type(xml)
43
+ xml.PickupType {
44
+ xml.Code type
45
+ xml.Description @pickupTypes[type]
46
+ }
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,42 @@
1
+ require "rspec"
2
+ require "ups_shipping"
3
+ require "address"
4
+ require "organization"
5
+
6
+ describe Shipping::UPS do
7
+ before(:all) do
8
+ @ups = Shipping::UPS.new("deanchen", "Transcriptic#1", "EC96D31A8D672E28", :test => true)
9
+ @address = Shipping::Address.new(
10
+ :address_lines => ["1402 Faber St."],
11
+ :city => "Durham",
12
+ :state => "NC",
13
+ :zip => "27705",
14
+ :country => "US"
15
+ )
16
+ end
17
+ it "address object" do
18
+ @address.to_xml.gsub(/^\s+/, "").gsub(/\s+$/, $/).should == '
19
+ <?xml version="1.0"?>
20
+ <Address>
21
+ <AddressLine1>1402 Faber St.</AddressLine1>
22
+ <City>Durham</City>
23
+ <StateProvinceCode>NC</StateProvinceCode>
24
+ <PostalCode>27705</PostalCode>
25
+ <CountryCode>US</CountryCode>
26
+ </Address>
27
+ '.gsub(/^\s+/, "").gsub(/\s+$/, $/)
28
+ end
29
+ it "organization object" do
30
+ @organization = Shipping::Organization.new(
31
+ :name => "Transcriptic",
32
+ :phone => "1233455678",
33
+ :address => @address
34
+ )
35
+ puts @organization.to_xml("Shipper")
36
+ end
37
+ it "#track_shipment" do
38
+ tracking_result = @ups.track_shipment("1ZXX31290231000092")
39
+ tracking_result.should have_key("TrackResponse")
40
+ tracking_result["TrackResponse"]["Response"]["ResponseStatusCode"].should == "1"
41
+ end
42
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ups_shipping
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Transcriptic, Inc
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-04 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: &70314021897160 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70314021897160
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &70314021896740 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70314021896740
36
+ - !ruby/object:Gem::Dependency
37
+ name: httparty
38
+ requirement: &70314021896320 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70314021896320
47
+ description: UPS shipping gem for integrating UPS's API into a Ruby script.
48
+ email: team@transcriptic.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - lib/ups_shipping.rb
54
+ - lib/ups_shipping/address.rb
55
+ - lib/ups_shipping/organization.rb
56
+ - lib/ups_shipping/package.rb
57
+ - lib/ups_shipping/pickup.rb
58
+ - spec/ups_shipping_spec.rb
59
+ homepage: http://www.github.com/transcriptic/ups-shipping
60
+ licenses: []
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 1.8.6
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: UPS shipping API integration.
83
+ test_files: []
84
+ has_rdoc: