fedex-web-services 1.1.51 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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