fedex-web-services 1.1.51 → 2.0.1

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. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/Gemfile +4 -0
  4. data/README.md +113 -0
  5. data/Rakefile +3 -0
  6. data/examples/create_shipments.rb +81 -0
  7. data/fedex-web-services.gemspec +26 -0
  8. data/lib/fedex_web_services.rb +13 -0
  9. data/lib/fedex_web_services/api.rb +66 -0
  10. data/lib/fedex_web_services/close_smart_post_request.rb +23 -0
  11. data/lib/fedex_web_services/delete_shipment_request.rb +31 -0
  12. data/lib/fedex_web_services/process_shipment_request.rb +96 -0
  13. data/lib/fedex_web_services/process_shipment_response.rb +28 -0
  14. data/lib/fedex_web_services/railtie.rb +7 -0
  15. data/lib/fedex_web_services/request.rb +57 -0
  16. data/lib/fedex_web_services/response.rb +16 -0
  17. data/lib/fedex_web_services/soap.rb +6 -0
  18. data/lib/fedex_web_services/soap/CloseServiceDefinitions.rb +910 -0
  19. data/lib/fedex_web_services/soap/CloseServiceDefinitionsDriver.rb +93 -0
  20. data/lib/fedex_web_services/soap/CloseServiceDefinitionsMappingRegistry.rb +1201 -0
  21. data/lib/fedex_web_services/soap/RateServiceDefinitions.rb +4318 -0
  22. data/lib/fedex_web_services/soap/RateServiceDefinitionsDriver.rb +53 -0
  23. data/lib/fedex_web_services/soap/RateServiceDefinitionsMappingRegistry.rb +4655 -0
  24. data/lib/fedex_web_services/soap/ShipServiceDefinitions.rb +4911 -0
  25. data/lib/fedex_web_services/soap/ShipServiceDefinitionsDriver.rb +101 -0
  26. data/lib/fedex_web_services/soap/ShipServiceDefinitionsMappingRegistry.rb +5405 -0
  27. data/lib/fedex_web_services/version.rb +3 -0
  28. data/license.txt +7 -0
  29. data/tasks/generate_definitions.rake +23 -0
  30. data/tasks/test.rake +5 -0
  31. data/test/integration_test.rb +109 -0
  32. metadata +76 -34
  33. data/lib/fedex.rb +0 -2
  34. data/lib/fedex/version.rb +0 -3
  35. data/lib/fedex/web_services.rb +0 -10
  36. data/lib/fedex/web_services/definitions.rb +0 -46
  37. data/lib/fedex/web_services/request/base.rb +0 -69
  38. data/lib/fedex/web_services/request/delete_shipment.rb +0 -27
  39. data/lib/fedex/web_services/request/get_rates.rb +0 -61
  40. data/lib/fedex/web_services/request/process_shipment.rb +0 -76
  41. data/lib/fedex/web_services/service/base.rb +0 -72
  42. data/lib/fedex/web_services/service/rate.rb +0 -40
  43. data/lib/fedex/web_services/service/ship.rb +0 -85
  44. data/lib/generators/fedex/generate_definitions_generator.rb +0 -38
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 06101ed7cbcb38c975dea29b6d42f1f60c056f20
4
+ data.tar.gz: 40b93297679f25e79fba9217a4a91f7d5d08c773
5
+ SHA512:
6
+ metadata.gz: 34cd181423a2cdeb1d359216226612366f9b846ab2a569ef31650ffd7081fb944f815afe0421a7137923f6590d02f35a7ad92b54d2bef1a5b8510b1ffefbf6bf
7
+ data.tar.gz: a03f180826690354ad97a84a7ccb78c41a98baa75c3014488127c4de9b76e53784fb8a0c04ebacf0b5b96bf42d339276870624dc0eba255358aa7a932dfc0b21
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in fedex-web-services.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # fedex-web-services
2
+ ## Description
3
+ This gem provides an interface to the FedEx web services API. It supports version 12 of the ship service and version 4 of the close service.
4
+
5
+ ## Testing
6
+ This gem includes a small integration test suite to test several of the API methods in the FedEx sandbox environment. You can run the tests from the source of this gem, or from within a rails application that includes this gem:
7
+
8
+ ```bash
9
+ export FEDEX_ACCOUNT=account FEDEX_METER=meter FEDEX_AUTH_KEY=authkey FEDEX_SECURITY_CODE=code
10
+ bundle exec rake fedex_web_services:test
11
+ ```
12
+
13
+ ## Examples
14
+ ### Creating a shipment with multiple packages
15
+
16
+ ```ruby
17
+ require 'fedex_web_services'
18
+
19
+ include FedexWebServices
20
+ include FedexWebServices::Soap
21
+
22
+ credentials = Api::Credentials.new(
23
+ ENV.fetch('FEDEX_ACCOUNT'),
24
+ ENV.fetch('FEDEX_METER'),
25
+ ENV.fetch('FEDEX_AUTH_KEY'),
26
+ ENV.fetch('FEDEX_SECURITY_CODE'),
27
+ :test # or :production
28
+ )
29
+ api = Api.new(credentials)
30
+
31
+ service = Ship::ServiceType::FEDEX_2_DAY
32
+
33
+ from = Ship::Party.new.tap do |shipper|
34
+ shipper.contact = Ship::Contact.new.tap do |contact|
35
+ contact.personName = "Joe Shmoe"
36
+ contact.phoneNumber = "(123) 456 789"
37
+ end
38
+
39
+ shipper.address = Ship::Address.new.tap do |address|
40
+ address.streetLines = [ "123 4th St" ]
41
+ address.city = "San Luis Obispo"
42
+ address.stateOrProvinceCode = "CA"
43
+ address.postalCode = "93401"
44
+ address.countryCode = "US"
45
+ address.residential = true
46
+ end
47
+ end
48
+
49
+ to = Ship::Party.new.tap do |recipient|
50
+ recipient.contact = Ship::Contact.new.tap do |contact|
51
+ contact.personName = "Ahwahnee Hotel"
52
+ contact.phoneNumber = "(801) 559-5000"
53
+ end
54
+ recipient.address = Ship::Address.new.tap do |address|
55
+ address.streetLines = [ "9006 Yosemite Lodge Drive" ]
56
+ address.city = "Yosemite National Park"
57
+ address.stateOrProvinceCode = "CA"
58
+ address.postalCode = "95389"
59
+ address.countryCode = "US"
60
+ address.residential = true
61
+ end
62
+ end
63
+
64
+ label_spec = Ship::LabelSpecification.new
65
+ label_spec.labelFormatType = Ship::LabelFormatType::COMMON2D
66
+ label_spec.imageType = Ship::ShippingDocumentImageType::PDF
67
+ label_spec.labelStockType = Ship::ShippingDocumentStockType::PAPER_LETTER
68
+
69
+ weights = [ 10, 55.34, 10.2 ].map do |weight|
70
+ Ship::Weight.new.tap do |w|
71
+ w.units = "LB"
72
+ w.value = weight
73
+ end
74
+ end
75
+
76
+ requests = ProcessShipmentRequest.shipment_requests(service, from, to, label_spec, weights)
77
+ requests.each do |request|
78
+ request.sender_paid!(credentials.account_number)
79
+ request.list_rate!
80
+ request.regular_pickup!
81
+ request.customer_reference!("01234")
82
+ request.customer_invoice!("56789")
83
+ end
84
+
85
+ tracking_numbers = api.process_shipments(requests).map do |response|
86
+ filename = "#{response.tracking_number}.pdf"
87
+ File.write(filename, response.label)
88
+ puts "Wrote #{filename}"
89
+ response.tracking_number
90
+ end
91
+ ```
92
+
93
+ ### Canceling a shipment
94
+
95
+ ```ruby
96
+ tracking_numbers.each do |tracking_number|
97
+ delete_request = DeleteShipmentRequest.new
98
+ delete_request.delete_all_packages!(tracking_number, Ship::TrackingIdType::EXPRESS)
99
+ api.delete_shipment(delete_request)
100
+ puts "Deleted shipment #{tracking_number}"
101
+ end
102
+ ```
103
+
104
+ ### Debugging
105
+ You can see the SOAP wiredump by accessing Api#wiredump after issuing a request.
106
+ ```ruby
107
+ begin
108
+ api.process_shipments(...)
109
+ rescue
110
+ puts api.wiredump
111
+ raise $!
112
+ end
113
+ ```
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ Dir.glob(File.expand_path("../tasks/*.rake", __FILE__)).each(&method(:import))
@@ -0,0 +1,81 @@
1
+ require 'fedex_web_services'
2
+
3
+ include FedexWebServices
4
+ include FedexWebServices::Soap
5
+
6
+ credentials = Api::Credentials.new(
7
+ ENV.fetch('FEDEX_ACCOUNT'),
8
+ ENV.fetch('FEDEX_METER'),
9
+ ENV.fetch('FEDEX_AUTH_KEY'),
10
+ ENV.fetch('FEDEX_SECURITY_CODE'),
11
+ :test # or :production
12
+ )
13
+ api = Api.new(credentials)
14
+
15
+ service = Ship::ServiceType::FEDEX_2_DAY
16
+
17
+ from = Ship::Party.new.tap do |shipper|
18
+ shipper.contact = Ship::Contact.new.tap do |contact|
19
+ contact.personName = "Joe Shmoe"
20
+ contact.phoneNumber = "(123) 456 789"
21
+ end
22
+
23
+ shipper.address = Ship::Address.new.tap do |address|
24
+ address.streetLines = [ "123 4th St" ]
25
+ address.city = "San Luis Obispo"
26
+ address.stateOrProvinceCode = "CA"
27
+ address.postalCode = "93401"
28
+ address.countryCode = "US"
29
+ address.residential = true
30
+ end
31
+ end
32
+
33
+ to = Ship::Party.new.tap do |recipient|
34
+ recipient.contact = Ship::Contact.new.tap do |contact|
35
+ contact.personName = "Ahwahnee Hotel"
36
+ contact.phoneNumber = "(801) 559-5000"
37
+ end
38
+ recipient.address = Ship::Address.new.tap do |address|
39
+ address.streetLines = [ "9006 Yosemite Lodge Drive" ]
40
+ address.city = "Yosemite National Park"
41
+ address.stateOrProvinceCode = "CA"
42
+ address.postalCode = "95389"
43
+ address.countryCode = "US"
44
+ address.residential = true
45
+ end
46
+ end
47
+
48
+ label_spec = Ship::LabelSpecification.new
49
+ label_spec.labelFormatType = Ship::LabelFormatType::COMMON2D
50
+ label_spec.imageType = Ship::ShippingDocumentImageType::PDF
51
+ label_spec.labelStockType = Ship::ShippingDocumentStockType::PAPER_LETTER
52
+
53
+ weights = [ 10, 55.34, 10.2 ].map do |weight|
54
+ Ship::Weight.new.tap do |w|
55
+ w.units = "LB"
56
+ w.value = weight
57
+ end
58
+ end
59
+
60
+ requests = ProcessShipmentRequest.shipment_requests(service, from, to, label_spec, weights)
61
+ requests.each do |request|
62
+ request.sender_paid!(credentials.account_number)
63
+ request.list_rate!
64
+ request.regular_pickup!
65
+ request.customer_reference!("01234")
66
+ request.customer_invoice!("56789")
67
+ end
68
+
69
+ tracking_numbers = api.process_shipments(requests).map do |response|
70
+ filename = "#{response.tracking_number}.pdf"
71
+ File.write(filename, response.label)
72
+ puts "Wrote #{filename}"
73
+ response.tracking_number
74
+ end
75
+
76
+ tracking_numbers.each do |tracking_number|
77
+ delete_request = DeleteShipmentRequest.new
78
+ delete_request.delete_all_packages!(tracking_number, Ship::TrackingIdType::EXPRESS)
79
+ api.delete_shipment(delete_request)
80
+ puts "Deleted shipment #{tracking_number}"
81
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fedex_web_services/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fedex-web-services"
8
+ spec.version = FedexWebServices::VERSION
9
+ spec.authors = ["Brian Abreu"]
10
+ spec.email = ["brian@nuts.com"]
11
+ spec.description = %q{Interfaces with the FedEx SOAP web services API}
12
+ spec.summary = %q{Provides an interface to the FedEx web services API}
13
+ spec.homepage = "https://github.com/brewski/fedex-web-services"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "soap4r-ng", '~> 2.0'
22
+ spec.required_ruby_version = '>= 2.0.0'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ end
@@ -0,0 +1,13 @@
1
+ module FedexWebServices
2
+ end
3
+
4
+ require "fedex_web_services/soap"
5
+
6
+ require 'fedex_web_services/request'
7
+ require 'fedex_web_services/close_smart_post_request'
8
+ require 'fedex_web_services/delete_shipment_request'
9
+ require 'fedex_web_services/process_shipment_request'
10
+
11
+ require "fedex_web_services/api"
12
+
13
+ require "fedex_web_services/railtie" if (defined?(Rails))
@@ -0,0 +1,66 @@
1
+ module FedexWebServices
2
+ class Api
3
+ include FedexWebServices::Soap
4
+
5
+ class ServiceException < RuntimeError
6
+ attr_accessor :details
7
+ end
8
+
9
+ Credentials = Struct.new(*%i(account_number meter_number key password environment))
10
+
11
+ attr_reader :wiredump
12
+
13
+ def initialize(credentials)
14
+ @credentials = credentials
15
+ @wiredump = ""
16
+ end
17
+
18
+ def process_shipments(requests)
19
+ port = Ship::ShipPortType.new(service_url)
20
+ first_response = nil
21
+
22
+ requests.map.with_index do |request, ndx|
23
+ if (ndx == 0)
24
+ first_response = issue_request(port, request)
25
+ else
26
+ request.for_master_tracking_number!(first_response.tracking_number)
27
+ issue_request(port, request)
28
+ end
29
+ end
30
+ end
31
+
32
+ def delete_shipment(request)
33
+ issue_request(Ship::ShipPortType.new(service_url), request)
34
+ end
35
+
36
+ def get_rates(request)
37
+ end
38
+
39
+ def close_smart_post(request)
40
+ issue_request(Close::ClosePortType.new(service_url), request)
41
+ end
42
+
43
+ def service_url
44
+ @service_url ||= (@credentials.environment.to_sym == :production) ?
45
+ 'https://ws.fedex.com/web-services' :
46
+ 'https://wsbeta.fedex.com/web-services'
47
+ end
48
+
49
+ private
50
+ def issue_request(port, request)
51
+ port.wiredump_dev = StringIO.new(request_wiredump = "")
52
+ request.issue_request(port, @credentials).tap do |response|
53
+ if (response.errors.any?)
54
+ raise response.errors.map(&:message) * ". "
55
+ end
56
+ end
57
+ rescue Exception => root_exception
58
+ raise
59
+ err = ServiceException.new(root_exception.message)
60
+ err.details = root_exception.detail.fault.details.validationFailureDetail.message rescue nil
61
+ raise err
62
+ ensure
63
+ @wiredump << request_wiredump if (request_wiredump)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,23 @@
1
+ module FedexWebServices
2
+ class CloseSmartPostRequest < Request
3
+ def initialize
4
+ @contents = soap_module::SmartPostCloseRequest.new
5
+ end
6
+
7
+ def soap_module
8
+ FedexWebServices::Soap::Close
9
+ end
10
+
11
+ def remote_method
12
+ :smartPostClose
13
+ end
14
+
15
+ def service_id
16
+ :clos
17
+ end
18
+
19
+ def version
20
+ 4
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ module FedexWebServices
2
+ class DeleteShipmentRequest < Request
3
+ def initialize
4
+ @contents = soap_module::DeleteShipmentRequest.new
5
+ end
6
+
7
+ def soap_module
8
+ FedexWebServices::Soap::Ship
9
+ end
10
+
11
+ def remote_method
12
+ :deleteShipment
13
+ end
14
+
15
+ def service_id
16
+ :ship
17
+ end
18
+
19
+ def version
20
+ 12
21
+ end
22
+
23
+ def delete_all_packages!(tracking_number, tracking_number_type)
24
+ contents.deletionControl = soap_module::DeletionControlType::DELETE_ALL_PACKAGES
25
+ contents.trackingId = soap_module::TrackingId.new.tap do |ti|
26
+ ti.trackingNumber = tracking_number
27
+ ti.trackingIdType = tracking_number_type
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,96 @@
1
+ require 'fedex_web_services/process_shipment_response'
2
+
3
+ module FedexWebServices
4
+ class ProcessShipmentRequest < Request
5
+ def initialize
6
+ @contents = soap_module::ProcessShipmentRequest.new
7
+ end
8
+
9
+ def soap_module
10
+ FedexWebServices::Soap::Ship
11
+ end
12
+
13
+ def remote_method
14
+ :processShipment
15
+ end
16
+
17
+ def service_id
18
+ :ship
19
+ end
20
+
21
+ def version
22
+ 12
23
+ end
24
+
25
+ def issue_request(port, credentials)
26
+ ProcessShipmentResponse.new(port.send(remote_method, request_contents(credentials)))
27
+ end
28
+
29
+ def sender_paid!(account_number)
30
+ mod = self.soap_module
31
+
32
+ contents.requestedShipment.shippingChargesPayment = mod::Payment.new.tap do |scp|
33
+ scp.paymentType = mod::PaymentType::SENDER
34
+
35
+ scp.payor = mod::Payor.new
36
+ scp.payor.responsibleParty = contents.requestedShipment.shipper.dup
37
+ scp.payor.responsibleParty.accountNumber = account_number
38
+ end
39
+ end
40
+
41
+ def regular_pickup!
42
+ contents.requestedShipment.dropoffType = soap_module::DropoffType::REGULAR_PICKUP
43
+ end
44
+
45
+ def list_rate!
46
+ contents.requestedShipment.rateRequestTypes = [ soap_module::RateRequestType::LIST ]
47
+ end
48
+
49
+ def for_master_tracking_number!(tracking_number)
50
+ contents.requestedShipment.masterTrackingId = soap_module::TrackingId.new.tap do |ti|
51
+ ti.trackingNumber = tracking_number
52
+ end
53
+ end
54
+
55
+ def customer_reference!(reference)
56
+ mod = self.soap_module
57
+ ref = mod::CustomerReference.new(mod::CustomerReferenceType::CUSTOMER_REFERENCE, reference)
58
+
59
+ contents.requestedShipment.requestedPackageLineItems.customerReferences ||= []
60
+ contents.requestedShipment.requestedPackageLineItems.customerReferences << ref
61
+ end
62
+
63
+ def customer_invoice!(invoice_number)
64
+ mod = self.soap_module
65
+ ref = mod::CustomerReference.new(mod::CustomerReferenceType::INVOICE_NUMBER, invoice_number)
66
+
67
+ contents.requestedShipment.requestedPackageLineItems.customerReferences ||= []
68
+ contents.requestedShipment.requestedPackageLineItems.customerReferences << ref
69
+ end
70
+
71
+ def self.shipment_requests(service_type, from, to, label_specification, package_weights)
72
+ package_weights.map.with_index do |weight, ndx|
73
+ new.tap do |request|
74
+ mod = request.soap_module
75
+
76
+ request.contents.requestedShipment = mod::RequestedShipment.new.tap do |rs|
77
+ rs.shipTimestamp = Time.now.iso8601
78
+ rs.serviceType = service_type
79
+ rs.packagingType = mod::PackagingType::YOUR_PACKAGING
80
+
81
+ rs.shipper = from
82
+ rs.recipient = to
83
+
84
+ rs.labelSpecification = label_specification
85
+
86
+ rs.packageCount = package_weights.size
87
+ rs.requestedPackageLineItems = mod::RequestedPackageLineItem.new.tap do |rpli|
88
+ rpli.sequenceNumber = ndx + 1
89
+ rpli.weight = weight
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end