mc-fedex 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ gem 'soap4r'
9
+ group :development do
10
+ gem "rspec"
11
+ gem "bundler", "~> 1.0.0"
12
+ gem "jeweler", "~> 1.5.1"
13
+ gem "rcov", ">= 0"
14
+ gem "ruby-debug"
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,40 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ columnize (0.3.2)
5
+ diff-lcs (1.1.2)
6
+ git (1.2.5)
7
+ httpclient (2.1.6.1)
8
+ jeweler (1.5.2)
9
+ bundler (~> 1.0.0)
10
+ git (>= 1.2.5)
11
+ rake
12
+ linecache (0.43)
13
+ rake (0.8.7)
14
+ rcov (0.9.9)
15
+ rspec (2.4.0)
16
+ rspec-core (~> 2.4.0)
17
+ rspec-expectations (~> 2.4.0)
18
+ rspec-mocks (~> 2.4.0)
19
+ rspec-core (2.4.0)
20
+ rspec-expectations (2.4.0)
21
+ diff-lcs (~> 1.1.2)
22
+ rspec-mocks (2.4.0)
23
+ ruby-debug (0.10.4)
24
+ columnize (>= 0.1)
25
+ ruby-debug-base (~> 0.10.4.0)
26
+ ruby-debug-base (0.10.4)
27
+ linecache (>= 0.3)
28
+ soap4r (1.5.8)
29
+ httpclient (>= 2.1.1)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ bundler (~> 1.0.0)
36
+ jeweler (~> 1.5.1)
37
+ rcov
38
+ rspec
39
+ ruby-debug
40
+ soap4r
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Edwin & Adam
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,57 @@
1
+ = mc-fedex
2
+
3
+ A gem to generate a FedEx label. You must supply the WSDL file in roder for this to work. We've set up limited tests due to the fact that the WSDL is not included.
4
+
5
+ Some code were copied from: https://github.com/mcmire/fedex
6
+
7
+ == Usage
8
+
9
+ = Create an instance
10
+ These are the required options:
11
+
12
+ driver = McFedex::Base.new(:auth_key => AUTH_KEY,
13
+ :security_code => SECURITY_CODE,
14
+ :account_number => ACCOUNT_NUMBER,
15
+ :meter_number => METER_NUMBER,
16
+ :wsdl_path => WSDL_PATH,
17
+ :smart_post_hub => SMART_POST_HUB,
18
+ :use_smart_post => USE_SMART_POST)
19
+
20
+ Passing :debug => true will output XML passed to FedEx, and FedEx's response.
21
+
22
+ = Supplied variables
23
+ When setting :use_smart_post to true, you will generate a SmartPost returns label with the supplied :smart_post_hub id.
24
+ If set to false, it will default to a normal returns label.
25
+
26
+ You can set the default for your normal label, by specifying:
27
+ McFedex::ServiceTypes::FEDEX_GROUND as the service type.
28
+
29
+ = Generating the label
30
+ driver.label(
31
+ :shipper => {:contact => SHIPPER, :address => SHIPPER_ORIGIN},
32
+ :recipient => {:contact => RECIPIENT, :address => RECIPIENT_ADDRESS},
33
+ :count => PACKAGE_COUNT,
34
+ :weight => PACKAGE_WEIGHT,
35
+ :service_type => SERVICE_TYPE
36
+ )
37
+
38
+ This method will return 3 values:
39
+ * Price
40
+ * Label
41
+ * Tracking Number
42
+
43
+ == Contributing to mc-fedex
44
+
45
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
46
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
47
+ * Fork the project
48
+ * Start a feature/bugfix branch
49
+ * Commit and push until you are happy with your contribution
50
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
51
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
52
+
53
+ == Copyright
54
+
55
+ Copyright (c) 2011 Edwin & Adam. See LICENSE.txt for
56
+ further details.
57
+
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "mc-fedex"
16
+ gem.homepage = "http://github.com/modcloth/mc-fedex"
17
+ gem.license = "MIT"
18
+ gem.summary = "Fedex library on ruby"
19
+ gem.description = "Fedex wrapper to print FedEx labels"
20
+ gem.email = "github@modcloth.com"
21
+ gem.authors = ["Edwin & Adam & Eric"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ gem.add_runtime_dependency 'soap4r', ">= 1.5.8"
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'rspec/core'
31
+ require 'rspec/core/rake_task'
32
+ require 'ruby-debug'
33
+ RSpec::Core::RakeTask.new(:spec) do |spec|
34
+ spec.pattern = FileList['spec/**/*_spec.rb']
35
+ end
36
+
37
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
38
+ spec.pattern = 'spec/**/*_spec.rb'
39
+ end
40
+
41
+ task :default => :spec
42
+
43
+ require 'rake/rdoctask'
44
+ Rake::RDocTask.new do |rdoc|
45
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "mc-fedex #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
data/lib/constants.rb ADDED
@@ -0,0 +1,73 @@
1
+ module McFedex
2
+ # {http://fedex.com/ws/rate/v5}PackagingType
3
+ module PackagingTypes
4
+ FEDEX_10KG_BOX = "FEDEX_10KG_BOX"
5
+ FEDEX_25KG_BOX = "FEDEX_25KG_BOX"
6
+ FEDEX_BOX = "FEDEX_BOX"
7
+ FEDEX_ENVELOPE = "FEDEX_ENVELOPE"
8
+ FEDEX_PAK = "FEDEX_PAK"
9
+ FEDEX_TUBE = "FEDEX_TUBE"
10
+ YOUR_PACKAGING = "YOUR_PACKAGING"
11
+ end
12
+
13
+ # {http://fedex.com/ws/rate/v5}DropoffType
14
+ module DropoffTypes
15
+ BUSINESS_SERVICE_CENTER = "BUSINESS_SERVICE_CENTER"
16
+ DROP_BOX = "DROP_BOX"
17
+ REGULAR_PICKUP = "REGULAR_PICKUP"
18
+ REQUEST_COURIER = "REQUEST_COURIER"
19
+ STATION = "STATION"
20
+ end
21
+
22
+ # {http://fedex.com/ws/ship/v5}LabelFormatType
23
+ module LabelFormatTypes
24
+ COMMON2D = "COMMON2D"
25
+ LABEL_DATA_ONLY = "LABEL_DATA_ONLY"
26
+ end
27
+
28
+ # {http://fedex.com/ws/ship/v5}LabelSpecificationImageType
29
+ module LabelSpecificationImageTypes
30
+ DPL = "DPL"
31
+ EPL2 = "EPL2"
32
+ PDF = "PDF"
33
+ PNG = "PNG"
34
+ ZPLII = "ZPLII"
35
+ end
36
+
37
+ # {http://fedex.com/ws/rate/v5}RateRequestType
38
+ module RateRequestTypes
39
+ ACCOUNT = "ACCOUNT"
40
+ LIST = "LIST"
41
+ MULTIWEIGHT = "MULTIWEIGHT"
42
+ end
43
+ # {http://fedex.com/ws/rate/v5}PaymentType
44
+ module PaymentTypes
45
+ SENDER = "SENDER"
46
+ end
47
+ # {http://fedex.com/ws/rate/v5}WeightUnits
48
+ module WeightUnits
49
+ KG = "KG"
50
+ LB = "LB"
51
+ end
52
+
53
+ # {http://fedex.com/ws/rate/v5}ServiceType
54
+ module ServiceTypes
55
+ EUROPE_FIRST_INTERNATIONAL_PRIORITY = "EUROPE_FIRST_INTERNATIONAL_PRIORITY"
56
+ FEDEX_1_DAY_FREIGHT = "FEDEX_1_DAY_FREIGHT"
57
+ FEDEX_2_DAY = "FEDEX_2_DAY"
58
+ SMART_POST = "SMART_POST"
59
+ FEDEX_2_DAY_FREIGHT = "FEDEX_2_DAY_FREIGHT"
60
+ FEDEX_3_DAY_FREIGHT = "FEDEX_3_DAY_FREIGHT"
61
+ FEDEX_EXPRESS_SAVER = "FEDEX_EXPRESS_SAVER"
62
+ FEDEX_GROUND = "FEDEX_GROUND"
63
+ FIRST_OVERNIGHT = "FIRST_OVERNIGHT"
64
+ GROUND_HOME_DELIVERY = "GROUND_HOME_DELIVERY"
65
+ INTERNATIONAL_ECONOMY = "INTERNATIONAL_ECONOMY"
66
+ INTERNATIONAL_ECONOMY_FREIGHT = "INTERNATIONAL_ECONOMY_FREIGHT"
67
+ INTERNATIONAL_FIRST = "INTERNATIONAL_FIRST"
68
+ INTERNATIONAL_PRIORITY = "INTERNATIONAL_PRIORITY"
69
+ INTERNATIONAL_PRIORITY_FREIGHT = "INTERNATIONAL_PRIORITY_FREIGHT"
70
+ PRIORITY_OVERNIGHT = "PRIORITY_OVERNIGHT"
71
+ STANDARD_OVERNIGHT = "STANDARD_OVERNIGHT"
72
+ end
73
+ end
data/lib/mc-fedex.rb ADDED
@@ -0,0 +1,297 @@
1
+ require 'time'
2
+ require 'constants'
3
+ require 'soap/wsdlDriver'
4
+ #require 'cgi'
5
+ require 'base64'
6
+ module McFedex
7
+ class FedexError < StandardError; end #:nodoc
8
+
9
+ class Base
10
+ # Defines the required parameters for various methods
11
+ REQUIRED_OPTIONS = {
12
+ :base => [ :auth_key, :security_code, :account_number, :meter_number ],
13
+ :price => [ :shipper, :recipient, :weight ],
14
+ :label => [ :shipper, :recipient, :weight, :service_type ],
15
+ :contact => [ :name, :phone_number ],
16
+ :address => [ :country, :street, :city, :state, :zip ],
17
+ :ship_cancel => [ :tracking_number ]
18
+ }
19
+
20
+ # Defines the relative path to the WSDL files. Defaults assume lib/wsdl under plugin directory.
21
+ WSDL_PATHS = {
22
+ :ship => @wsdl_path,
23
+ }
24
+
25
+ # DIR = File.dirname(__FILE__)
26
+
27
+ # Defines the Web Services version implemented.
28
+ WS_VERSION = { :Major => 9, :Intermediate => 0, :Minor => 0, :ServiceId => 'ship' }
29
+
30
+ SUCCESSFUL_RESPONSES = ['SUCCESS', 'WARNING', 'NOTE'] #:nodoc:
31
+
32
+ # Initializes the Fedex::Base class, setting defaults where necessary.
33
+ #
34
+ # fedex = Fedex::Base.new(options = {})
35
+ #
36
+ # === Example:
37
+ # fedex = Fedex::Base.new(:auth_key => AUTH_KEY,
38
+ # :security_code => SECURITY_CODE
39
+ # :account_number => ACCOUNT_NUMBER,
40
+ # :meter_number => METER_NUMBER)
41
+ #
42
+ # === Required options for new
43
+ # :auth_key - Your Fedex Authorization Key
44
+ # :security_code - Your Fedex Security Code
45
+ # :account_number - Your Fedex Account Number
46
+ # :meter_number - Your Fedex Meter Number
47
+ #
48
+ # === Additional options
49
+ # :dropoff_type - One of Fedex::DropoffTypes. Defaults to DropoffTypes::REGULAR_PICKUP
50
+ # :packaging_type - One of Fedex::PackagingTypes. Defaults to PackagingTypes::YOUR_PACKAGING
51
+ # :label_type - One of Fedex::LabelFormatTypes. Defaults to LabelFormatTypes::COMMON2D. You'll only need to change this
52
+ # if you're generating completely custom labels with a format of your own design. If printing to Fedex stock
53
+ # leave this alone.
54
+ # :label_image_type - One of Fedex::LabelSpecificationImageTypes. Defaults to LabelSpecificationImageTypes::PDF.
55
+ # :rate_request_type - One of Fedex::RateRequestTypes. Defaults to RateRequestTypes::ACCOUNT
56
+ # :payment - One of Fedex::PaymentTypes. Defaults to PaymentTypes::SENDER
57
+ # :units - One of Fedex::WeightUnits. Defaults to WeightUnits::LB
58
+ # :currency - One of Fedex::CurrencyTypes. Defaults to CurrencyTypes::USD
59
+ # :debug - Enable or disable debug (wiredump) output. Defaults to false.
60
+ def initialize(options = {})
61
+ check_required_options(:base, options)
62
+
63
+ @auth_key = options[:auth_key]
64
+ @security_code = options[:security_code]
65
+ @account_number = options[:account_number]
66
+ @meter_number = options[:meter_number]
67
+
68
+ @wsdl_path = options[:wsdl_path]
69
+ @use_smart_post = options[:use_smart_post]
70
+ @smart_post_hub = options[:smart_post_hub]
71
+
72
+ @dropoff_type = options[:dropoff_type] || DropoffTypes::REGULAR_PICKUP
73
+ @packaging_type = options[:packaging_type] || PackagingTypes::YOUR_PACKAGING
74
+ @label_type = options[:label_type] || LabelFormatTypes::COMMON2D
75
+ @label_image_type = options[:label_image_type] || LabelSpecificationImageTypes::PDF
76
+ @rate_request_type = options[:rate_request_type] || RateRequestTypes::LIST
77
+ @payment_type = options[:payment] || PaymentTypes::SENDER
78
+ @units = options[:units] || WeightUnits::LB
79
+ @currency = options[:currency] || 'USD'
80
+ @debug = options[:debug] || false
81
+ end
82
+
83
+ # Generate a new shipment and return associated data, including price, tracking number, and the label itself.
84
+ #
85
+ # fedex = Fedex::Base.new(options)
86
+ # price, label, tracking_number = fedex.label(fields)
87
+ #
88
+ # Returns the actual price for the label, the Base64-decoded label in the format specified in Fedex::Base,
89
+ # and the tracking_number for the shipment.
90
+ #
91
+ # === Required options for label
92
+ # :shipper - A hash containing contact information and an address for the shipper. (See below.)
93
+ # :recipient - A hash containing contact information and an address for the recipient. (See below.)
94
+ # :weight - The total weight of the shipped package.
95
+ # :service_type - One of Fedex::ServiceTypes
96
+ #
97
+ # === Address format
98
+ # The 'shipper' and 'recipient' address values should be hashes. Like this:
99
+ #
100
+ # shipper = {:contact => {:name => 'John Doe',
101
+ # :phone_number => '4805551212'},
102
+ # :address => address} # See "Address" for under price.
103
+ def label(options = {})
104
+ puts options.inspect if @debug
105
+ # Check overall options
106
+ check_required_options(:label, options)
107
+
108
+ # Check Address Options
109
+ check_required_options(:contact, options[:shipper][:contact])
110
+ check_required_options(:address, options[:shipper][:address])
111
+
112
+ # Check Contact Options
113
+ check_required_options(:contact, options[:recipient][:contact])
114
+ check_required_options(:address, options[:recipient][:address])
115
+
116
+ # Prepare variables
117
+ shipper = options[:shipper]
118
+ recipient = options[:recipient]
119
+
120
+ shipper_contact = shipper[:contact]
121
+ shipper_address = shipper[:address]
122
+
123
+ recipient_contact = recipient[:contact]
124
+ recipient_address = recipient[:address]
125
+
126
+ service_type = options[:service_type]
127
+ count = options[:count] || 1
128
+ weight = options[:weight]
129
+ rma = options[:rma] || ""
130
+
131
+ time = options[:time] || Time.now
132
+ puts time.class
133
+ time = time.iso8601 if time.is_a?(Time)
134
+
135
+ residential = !!recipient_address[:residential]
136
+
137
+ service_type = resolve_service_type(service_type, residential)
138
+
139
+ # Create the driver
140
+ driver = create_driver(:ship)
141
+
142
+ smart_post_data = {
143
+ :SmartPostDetail => {
144
+ :Indicia => "PARCEL_RETURN",
145
+ :HubId => @smart_post_hub
146
+ },
147
+ :SpecialServicesRequested => {
148
+ :SpecialServiceTypes => "RETURN_SHIPMENT",
149
+ :ReturnShipmentDetail => {
150
+ :ReturnType => "PRINT_RETURN_LABEL",
151
+ :Rma => {
152
+ :Number => rma
153
+ }
154
+ }
155
+ }
156
+ } if @use_smart_post
157
+
158
+ result = driver.processShipment(common_options.merge(
159
+ :RequestedShipment => {
160
+ :ShipTimestamp => time,
161
+ :DropoffType => @dropoff_type,
162
+ :ServiceType => service_type,
163
+ :PackagingType => @packaging_type,
164
+ :TotalWeight => { :Units => @units, :Value => weight },
165
+ :PreferredCurrency => @currency,
166
+ :Shipper => {
167
+ :Contact => {
168
+ :PersonName => shipper_contact[:name],
169
+ :PhoneNumber => shipper_contact[:phone_number]
170
+ },
171
+ :Address => {
172
+ :CountryCode => shipper_address[:country],
173
+ :StreetLines => shipper_address[:street],
174
+ :City => shipper_address[:city],
175
+ :StateOrProvinceCode => shipper_address[:state],
176
+ :PostalCode => shipper_address[:zip]
177
+ }
178
+ },
179
+ :Recipient => {
180
+ :Contact => {
181
+ :PersonName => recipient_contact[:name],
182
+ :PhoneNumber => recipient_contact[:phone_number]
183
+ },
184
+ :Address => {
185
+ :CountryCode => recipient_address[:country],
186
+ :StreetLines => recipient_address[:street],
187
+ :City => recipient_address[:city],
188
+ :StateOrProvinceCode => recipient_address[:state],
189
+ :PostalCode => recipient_address[:zip],
190
+ :Residential => residential
191
+ }
192
+ },
193
+ :ShippingChargesPayment => {
194
+ :PaymentType => @payment_type,
195
+ :Payor => {
196
+ :AccountNumber => @account_number,
197
+ :CountryCode => shipper_address[:country]
198
+ }
199
+ },
200
+ :LabelSpecification => {
201
+ :LabelFormatType => @label_type,
202
+ :ImageType => @label_image_type
203
+ },
204
+ :RateRequestTypes => @rate_request_type,
205
+ :PackageCount => count,
206
+ :RequestedPackageLineItems => [ {:SequenceNumber=>1, :Weight => {:Units => @units, :Value => weight} } ]
207
+ }.merge(smart_post_data || {})
208
+ ))
209
+
210
+ successful = successful?(result)
211
+
212
+ msg = error_msg(result, false)
213
+ if successful && msg !~ /There are no valid services available/
214
+ if @use_smart_post
215
+ charge = 0
216
+ tracking_number = result.completedShipmentDetail.completedPackageDetails.trackingIds[1].trackingNumber
217
+ else
218
+ pre = result.completedShipmentDetail.shipmentRating.shipmentRateDetails
219
+ charge = ((pre.class == Array ? pre[0].totalNetCharge.amount.to_f : pre.totalNetCharge.amount.to_f) * 100).to_i
220
+ tracking_number = result.completedShipmentDetail.completedPackageDetails.trackingIds.trackingNumber
221
+ end
222
+ label = Base64.decode64(result.completedShipmentDetail.completedPackageDetails.label.parts.image)
223
+ [charge, label, tracking_number]
224
+ else
225
+ raise FedexError.new("Unable to get label from Fedex: #{msg}")
226
+ end
227
+ end
228
+
229
+ private
230
+ # Options that go along with each request
231
+ def common_options
232
+ {
233
+ :WebAuthenticationDetail => {:UserCredential => {:Key => @auth_key, :Password => @security_code}},
234
+ :ClientDetail => {:AccountNumber => @account_number, :MeterNumber => @meter_number},
235
+ :Version => WS_VERSION
236
+ }
237
+ end
238
+
239
+ # Checks the supplied options for a given method or field and throws an exception if anything is missing
240
+ def check_required_options(option_set_name, options = {})
241
+ required_options = REQUIRED_OPTIONS[option_set_name]
242
+ missing = []
243
+ required_options.each { |option| missing << option if options[option].nil? }
244
+
245
+ unless missing.empty?
246
+ raise MissingInformationError.new("Missing #{missing.collect { |m| ":#{m}" }.join(', ')}")
247
+ end
248
+ end
249
+
250
+ # Creates and returns a driver for the requested action
251
+ def create_driver(name)
252
+ path = File.expand_path(@wsdl_path)
253
+ wsdl = SOAP::WSDLDriverFactory.new(path)
254
+ driver = wsdl.create_rpc_driver
255
+ # /s+(1000|0|9c9|fcc)\s+/ => ""
256
+ driver.wiredump_dev = STDOUT if @debug
257
+
258
+ driver
259
+ end
260
+
261
+ # Resolves the ground+residential discrepancy. If a package is shipped via Fedex Ground to an address marked as residential the service type
262
+ # must be set to ServiceTypes::GROUND_HOME_DELIVERY and not ServiceTypes::FEDEX_GROUND.
263
+ def resolve_service_type(service_type, residential)
264
+ if residential && (service_type == ServiceTypes::FEDEX_GROUND)
265
+ ServiceTypes::GROUND_HOME_DELIVERY
266
+ else
267
+ service_type
268
+ end
269
+ end
270
+
271
+ # Returns a boolean determining whether a request was successful.
272
+ def successful?(result)
273
+ if defined?(result.cancelPackageReply)
274
+ SUCCESSFUL_RESPONSES.any? { |r| r == result.cancelPackageReply.highestSeverity }
275
+ else
276
+ SUCCESSFUL_RESPONSES.any? { |r| r == result.highestSeverity }
277
+ end
278
+ end
279
+
280
+ # Returns the error message contained in the SOAP response, if one exists.
281
+ def error_msg(result, return_nothing_if_successful=true)
282
+ return "" if successful?(result) && return_nothing_if_successful
283
+ notes = result.notifications
284
+ notes.respond_to?(:message) ? notes.message : notes.first.message
285
+ end
286
+
287
+ # Attempts to determine the carrier code for a tracking number based upon its length. Currently supports Fedex Ground and Fedex Express
288
+ def carrier_code_for_tracking_number(tracking_number)
289
+ case tracking_number.length
290
+ when 12
291
+ 'FDXE'
292
+ when 15
293
+ 'FDXG'
294
+ end
295
+ end
296
+ end
297
+ end
data/mc-fedex.gemspec ADDED
@@ -0,0 +1,73 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{mc-fedex}
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Edwin & Adam & Eric"]
12
+ s.date = %q{2011-02-25}
13
+ s.description = %q{Fedex wrapper to print FedEx labels}
14
+ s.email = %q{github@modcloth.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "LICENSE.txt",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/constants.rb",
27
+ "lib/mc-fedex.rb",
28
+ "mc-fedex.gemspec",
29
+ "spec/mc-fedex_spec.rb",
30
+ "spec/spec_helper.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/modcloth/mc-fedex}
33
+ s.licenses = ["MIT"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.7}
36
+ s.summary = %q{Fedex library on ruby}
37
+ s.test_files = [
38
+ "spec/mc-fedex_spec.rb",
39
+ "spec/spec_helper.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
+ s.add_runtime_dependency(%q<soap4r>, [">= 0"])
48
+ s.add_development_dependency(%q<rspec>, [">= 0"])
49
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
50
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
51
+ s.add_development_dependency(%q<rcov>, [">= 0"])
52
+ s.add_development_dependency(%q<ruby-debug>, [">= 0"])
53
+ s.add_runtime_dependency(%q<soap4r>, [">= 1.5.8"])
54
+ else
55
+ s.add_dependency(%q<soap4r>, [">= 0"])
56
+ s.add_dependency(%q<rspec>, [">= 0"])
57
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
58
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
59
+ s.add_dependency(%q<rcov>, [">= 0"])
60
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
61
+ s.add_dependency(%q<soap4r>, [">= 1.5.8"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<soap4r>, [">= 0"])
65
+ s.add_dependency(%q<rspec>, [">= 0"])
66
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
67
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
68
+ s.add_dependency(%q<rcov>, [">= 0"])
69
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
70
+ s.add_dependency(%q<soap4r>, [">= 1.5.8"])
71
+ end
72
+ end
73
+
@@ -0,0 +1,52 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe McFedex do
4
+
5
+ describe "create a shipping label" do
6
+ it "should call fedex api and get label" do
7
+ fedex = McFedex::Base.new(:auth_key => 'AUTH_KEY',
8
+ :security_code => 'SECURITY_CODE',
9
+ :account_number => 'ACCOUNT_NUMBER',
10
+ :meter_number => 'METER_NUMBER',
11
+ :wsdl => 'WSDL PATH HERE')
12
+ shipper = {
13
+ :name => "NAME",
14
+ :phone_number => 'PHONE_NUMBER'
15
+ }
16
+ recipient = {
17
+ :name => "NAME",
18
+ :phone_number => 'PHONE_NUMBER'
19
+ }
20
+ origin = {
21
+ :street => ['STREET1', 'STREET2'],
22
+ :city => 'CITY',
23
+ :state => 'STATE',
24
+ :zip => 'ZIP',
25
+ :country => 'COUNTRY'
26
+ }
27
+ destination = {
28
+ :street => 'STREET',
29
+ :city => 'CITY',
30
+ :state => 'STATE',
31
+ :zip => 'ZIP',
32
+ :country => 'COUNTRY',
33
+ :residential => false
34
+ }
35
+ pkg_count = 1
36
+ weight = 10
37
+ service_type = McFedex::ServiceTypes::FEDEX_GROUND
38
+
39
+ price, label, tracking_number = fedex.label(
40
+ :shipper => {:contact => shipper, :address => origin},
41
+ :recipient => {:contact => recipient, :address => destination},
42
+ :count => pkg_count,
43
+ :weight => weight,
44
+ :service_type => service_type
45
+ )
46
+
47
+ f = File.new("label.pdf", "w+")
48
+ f.write(label)
49
+ f.close
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+
11
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
12
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+ require 'mc-fedex'
14
+ require 'rspec'
15
+
16
+ # Requires supporting files with custom matchers and macros, etc,
17
+ # in ./support/ and its subdirectories.
18
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
19
+
20
+ RSpec.configure do |config|
21
+
22
+ end
metadata ADDED
@@ -0,0 +1,182 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mc-fedex
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Edwin & Adam & Eric
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-25 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ type: :runtime
24
+ name: soap4r
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ requirement: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ prerelease: false
37
+ type: :development
38
+ name: rspec
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ requirement: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ prerelease: false
51
+ type: :development
52
+ name: bundler
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ hash: 23
59
+ segments:
60
+ - 1
61
+ - 0
62
+ - 0
63
+ version: 1.0.0
64
+ requirement: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ prerelease: false
67
+ type: :development
68
+ name: jeweler
69
+ version_requirements: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ hash: 1
75
+ segments:
76
+ - 1
77
+ - 5
78
+ - 1
79
+ version: 1.5.1
80
+ requirement: *id004
81
+ - !ruby/object:Gem::Dependency
82
+ prerelease: false
83
+ type: :development
84
+ name: rcov
85
+ version_requirements: &id005 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ requirement: *id005
95
+ - !ruby/object:Gem::Dependency
96
+ prerelease: false
97
+ type: :development
98
+ name: ruby-debug
99
+ version_requirements: &id006 !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 3
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ requirement: *id006
109
+ - !ruby/object:Gem::Dependency
110
+ prerelease: false
111
+ type: :runtime
112
+ name: soap4r
113
+ version_requirements: &id007 !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ hash: 19
119
+ segments:
120
+ - 1
121
+ - 5
122
+ - 8
123
+ version: 1.5.8
124
+ requirement: *id007
125
+ description: Fedex wrapper to print FedEx labels
126
+ email: github@modcloth.com
127
+ executables: []
128
+
129
+ extensions: []
130
+
131
+ extra_rdoc_files:
132
+ - LICENSE.txt
133
+ - README.rdoc
134
+ files:
135
+ - Gemfile
136
+ - Gemfile.lock
137
+ - LICENSE.txt
138
+ - README.rdoc
139
+ - Rakefile
140
+ - VERSION
141
+ - lib/constants.rb
142
+ - lib/mc-fedex.rb
143
+ - mc-fedex.gemspec
144
+ - spec/mc-fedex_spec.rb
145
+ - spec/spec_helper.rb
146
+ has_rdoc: true
147
+ homepage: http://github.com/modcloth/mc-fedex
148
+ licenses:
149
+ - MIT
150
+ post_install_message:
151
+ rdoc_options: []
152
+
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ hash: 3
161
+ segments:
162
+ - 0
163
+ version: "0"
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ none: false
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ hash: 3
170
+ segments:
171
+ - 0
172
+ version: "0"
173
+ requirements: []
174
+
175
+ rubyforge_project:
176
+ rubygems_version: 1.3.7
177
+ signing_key:
178
+ specification_version: 3
179
+ summary: Fedex library on ruby
180
+ test_files:
181
+ - spec/mc-fedex_spec.rb
182
+ - spec/spec_helper.rb