dhl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fa40048126f12bd3fc7c5ed6c7d6f57801961ab5
4
+ data.tar.gz: 591643d4d78424fdd97b645735bb40e1ab5c118a
5
+ SHA512:
6
+ metadata.gz: 12afcfbbeee3de8265bd66bd737d20f25f239f1a6cf1e946f8ec200344fa292569bd6523d9aa2658299fc0e568c1c95acf5d8a13b5677290112114d64102b180
7
+ data.tar.gz: 393580cbca56eaabf094bdea4092e80b501de3a4018c7a918471fd17466cde9f31c736e46ea324b2cf92f30299301e96dc6527a443a04266b9a568b1689898f9
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ # uncomment this line if your project needs to run something other than `rake`:
6
+ # script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,22 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dhl.gemspec
4
+ gemspec
5
+
6
+
7
+ source 'https://rubygems.org'
8
+
9
+ gem 'savon', '~> 2.2.0'
10
+
11
+ group :test do
12
+ gem 'factory_girl', '~> 4.2.0'
13
+ gem 'webmock', "~> 1.9.0"
14
+ gem 'vcr', "~> 2.4.0"
15
+ # gem 'turn'
16
+ gem 'rake'
17
+ gem 'rspec', "~> 2.13.0"
18
+ gem 'pry'
19
+ end
20
+
21
+ # Specify your gem's dependencies in the_tvdb.gemspec
22
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Alessandro Mencarini
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,93 @@
1
+ # DHL
2
+
3
+ [![Build Status](https://travis-ci.org/momitians/dhl.png?branch=master)](https://travis-ci.org/momitians/dhl)
4
+ [![Code Climate](https://codeclimate.com/github/momitians/dhl.png)](https://codeclimate.com/github/momitians/dhl)
5
+
6
+ This gem will provide a wrapper to DHL SOAP API. Given DHL credentials and the addresses, will generate a shipping label.
7
+
8
+ It refers to the DHL test environment and cannot be used, as of yet, for production environments.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'dhl'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install dhl
23
+
24
+ ## Usage
25
+
26
+ ### Package Tracking
27
+
28
+ TBD
29
+
30
+ ### Request Shipment
31
+
32
+ ```ruby
33
+ # Start by creating a new shipment request
34
+ shipment_request = Dhl::ShipmentRequest.new
35
+
36
+ # Set sender info
37
+ shipment_request.shipper.name = 'Package Sender'
38
+ shipment_request.shipper.company = 'The Packs Inc'
39
+ shipment_request.shipper.phone = '555-4321'
40
+ shipment_request.shipper.email = 'ps@example.com'
41
+ shipment_request.shipper.address = 'Geary Boulevard, 1234'
42
+ shipment_request.shipper.address2 = 'First floor, Apt 2'
43
+ shipment_request.shipper.postal_code = '54321'
44
+ shipment_request.shipper.city = 'San Francisco'
45
+ shipment_request.shipper.state_name = 'CA'
46
+ shipment_request.shipper.country_code = 'USA'
47
+
48
+ # Set recipient info
49
+ shipment_request.recipient.name = 'Package Receiver'
50
+ shipment_request.recipient.company = 'Pack It Ltd'
51
+ shipment_request.recipient.phone = '555-1234'
52
+ shipment_request.recipient.email = 'pr@example.com'
53
+ shipment_request.recipient.address = 'Times Square, 1234'
54
+ shipment_request.recipient.address2 = 'Third floor, Apt 5'
55
+ shipment_request.recipient.postal_code = '12345'
56
+ shipment_request.recipient.city = 'New York'
57
+ shipment_request.recipient.state_name = 'NY'
58
+ shipment_request.recipient.country_code = 'USA'
59
+
60
+ # Set a pickup date and time
61
+ shipment_request.shipment.pickup_time = Time.new(2013, 05, 20, 10, 00, 00, "-08:00")
62
+
63
+ # Add Packages with weight, width, height, length and a reference string
64
+ shipment_request.packages.add(10, 15, 5, 20, 'Pack')
65
+
66
+ # Execute the reeuqest
67
+ result = Dhl.client.request_shipment(shipment_request)
68
+
69
+ ```
70
+
71
+ If everything goes well, result will be a hash with:
72
+ * tracking_numbers: Shipment tracking number
73
+ * shipping_label: Path to the shipping label PDF
74
+
75
+ ## Testing
76
+
77
+ For testing purposes please set the timezone to UTC
78
+
79
+ ```shell
80
+ $ export TZ=UTC
81
+ ```
82
+
83
+ ## Contributing
84
+
85
+ 1. Fork it
86
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
87
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
88
+ 4. Push to the branch (`git push origin my-new-feature`)
89
+ 5. Create new Pull Request
90
+
91
+ ## Licence
92
+
93
+ Released under the [MIT License](http://www.opensource.org/licenses/MIT). © 2013 [Momit S.r.l.](http://momit.it/)
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ task :default => :spec
4
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dhl/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dhl"
8
+ spec.version = Dhl::VERSION
9
+ spec.authors = ["Alessandro Mencarini"]
10
+ spec.email = ["a.mencarini@freegoweb.it"]
11
+ spec.description = %q{A wrapper for DHL SOAP interface. }
12
+ spec.summary = %q{This gem will provide a wrapper to DHL SOAP API. Given DHL credentials and the addresses, will generate a shipping label.}
13
+ spec.homepage = "http://momitians.github.io/dhl"
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 "savon", "~> 2.2.0"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec", "~> 2.13.0"
26
+ spec.add_development_dependency "factory_girl", "~> 4.2.0"
27
+ spec.add_development_dependency "vcr", "~> 2.4.0"
28
+ spec.add_development_dependency "webmock", "~> 1.9.0"
29
+ end
@@ -0,0 +1,34 @@
1
+ require 'savon'
2
+
3
+ require "dhl/client"
4
+ require "dhl/configuration"
5
+ require "dhl/contact"
6
+ require "dhl/packages"
7
+ require "dhl/package"
8
+ require "dhl/shipment"
9
+ require "dhl/shipment_request"
10
+ require "dhl/tracking_request"
11
+
12
+ require "dhl/version"
13
+
14
+ module Dhl
15
+
16
+ def self.setup
17
+ yield self.config
18
+ end
19
+
20
+ def self.config
21
+ @config ||= Configuration.new
22
+ end
23
+
24
+ def self.client(options={})
25
+ @client ||= Client.new(options)
26
+ end
27
+
28
+ end
29
+
30
+ class Hash
31
+ def remove_empty
32
+ reject{ |key, value| value.nil? || value == '' }
33
+ end
34
+ end
@@ -0,0 +1,78 @@
1
+ module Dhl
2
+ class Client
3
+
4
+ def config
5
+ Dhl.config
6
+ end
7
+
8
+ def client_options
9
+ {
10
+ wsse_auth: [config.username, config.password],
11
+ wsse_timestamp: true,
12
+ convert_request_keys_to: :camelcase
13
+ }
14
+ end
15
+
16
+ def initialize(options)
17
+ config.username ||= options[:username]
18
+ raise 'Provide a username (e.g.: `export DHL_USERNAME=dhlusername`).' if !config.username
19
+
20
+ config.password ||= options[:password]
21
+ raise 'Provide a password (e.g.: `export DHL_PASSWORD=dhlpassword`).' if !config.password
22
+
23
+ config.account ||= options[:account]
24
+ raise 'Provide a DHL account number (e.g.: `export DHL_ACCOUNT=123456789`).' if !config.account
25
+
26
+ @requests_soap_client = Savon.client(client_options.merge(wsdl: "https://wsbuat.dhl.com:8300/amer/GEeuExpressRateBook?WSDL"))
27
+ @tracking_soap_client = Savon.client(client_options.merge(wsdl: "https://wsbuat.dhl.com:8300/gbl/glDHLExpressTrack?WSDL"))
28
+ end
29
+
30
+ def requests_soap_client
31
+ # SOAP Client operations:
32
+ # => [:get_rate_request, :create_shipment_request, :delete_shipment_request]
33
+ @requests_soap_client
34
+ end
35
+
36
+ def tracking_soap_client
37
+ # SOAP Client operations:
38
+ # => [:track_shipment_request]
39
+ @tracking_soap_client
40
+ end
41
+
42
+
43
+ def request_shipment(shipment_request)
44
+ response = requests_soap_client.call(:create_shipment_request, message: shipment_request.to_hash )
45
+
46
+ if response.body[:shipment_response][:notification][:@code] != '0'
47
+ raise "Error: #{response.body[:shipment_response][:notification][:message]}"
48
+ end
49
+
50
+ result = {}
51
+
52
+ image_format = response.body[:shipment_response][:label_image][:label_image_format]
53
+ shipment_identification_number = response.body[:shipment_response][:shipment_identification_number]
54
+ shipping_label_filename = "#{shipment_identification_number}.#{image_format.downcase}"
55
+ Dir.mkdir('labels') unless File.exists?('labels')
56
+ File.open("labels/#{shipping_label_filename}", 'wb') do |f|
57
+ f.write( Base64.decode64( response.body[:shipment_response][:label_image][:graphic_image]) )
58
+ result[:shipping_label] = File.absolute_path(f)
59
+ end
60
+
61
+ package_result = response.body[:shipment_response][:packages_result][:package_result]
62
+ result[:tracking_numbers] = package_result.is_a?(Array) ? package_result.map{|r| r[:tracking_number]} : package_result[:tracking_number]
63
+
64
+ result
65
+ end
66
+
67
+ def track(numbers)
68
+ request = Dhl::TrackingRequest.new(numbers)
69
+ response = tracking_soap_client.call(:track_shipment_request, message: request.to_hash)
70
+ response.body
71
+ end
72
+
73
+ # def request_rate
74
+ # response = @soap_client.call(:get_rate_request, message: request_rate_hash )
75
+ # end
76
+
77
+ end
78
+ end
@@ -0,0 +1,12 @@
1
+ module Dhl
2
+ class Configuration
3
+
4
+ attr_accessor :username, :password, :account
5
+ def initialize
6
+ @username = ENV['DHL_USERNAME']
7
+ @password = ENV['DHL_PASSWORD']
8
+ @account = ENV['DHL_ACCOUNT']
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ module Dhl
2
+ class Contact
3
+
4
+ attr_accessor :name, :company, :phone, :email, :address, :address2, :address3,
5
+ :street_name, :street_number, :state_name, :city, :postal_code, :country_code
6
+
7
+ def to_hash
8
+ {
9
+ contact: {
10
+ person_name: @name,
11
+ company_name: @company,
12
+ phone_number: @phone,
13
+ email_address: @email # Optional
14
+ }.remove_empty,
15
+ address: {
16
+ street_lines: @address,
17
+ street_lines_2: @address2, # Optional
18
+ street_lines_3: @address3, # Optional
19
+ city: @city,
20
+ postal_code: @postal_code,
21
+ country_code: @country_code,
22
+ street_name: @street_name, # Optional
23
+ street_number: @street_number, # Optional
24
+ state_or_province_code: @state_name # Optional
25
+ }.remove_empty
26
+ }
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,208 @@
1
+ request_rate_small_hash = {
2
+ requested_shipment: {
3
+ drop_off_type: "REGULAR_PICKUP",
4
+ ship: {
5
+ shipper: address_structure,
6
+ recipient: address_structure
7
+ },
8
+ packages: {
9
+ requested_packages: [
10
+ {
11
+ weight: {
12
+ value: '15'
13
+ },
14
+ dimensions: {
15
+ length: '3',
16
+ width: '3',
17
+ height: '3'
18
+ }
19
+ }
20
+ ]
21
+ },
22
+ ship_timestamp: Time.now.strftime('%Y-%m-%dT%H:%M:%SGMT+01:00'), # When is the shipment going to be ready for pickup?
23
+ account: ENV['DHL_CUSTOMER_CODE'],
24
+ unit_of_measurement: 'SI' # Or SU, UK, US,
25
+ }
26
+ }
27
+ response = client.call(:get_rate_request, message: request_rate_small_hash )
28
+
29
+ request_rate_hash = {
30
+ requested_shipment: {
31
+ drop_off_type: "REGULAR_PICKUP",
32
+ next_business_day: nil, # Optional, Y or N
33
+ ship: {
34
+ shipper: address_structure,
35
+ recipient: address_structure
36
+ },
37
+ packages: {
38
+ requested_packages: [
39
+ 1 => {
40
+ weight: '15',
41
+ dimensions: {
42
+ length: '3,0',
43
+ width: '3,0',
44
+ height: '3,0'
45
+ }
46
+ }
47
+ ]
48
+ },
49
+ ship_timestamp: Time.now.strftime('%Y-%m-%dT%H:%M:%SGMT%z'), # When is the shipment going to be ready for pickup?
50
+ unit_of_measurement: 'SI', # Or SU, UK, US
51
+ content: '', # Optional
52
+ payment_info: '', # Optional
53
+ account: '', # Optional
54
+ billing: {}, # Optional
55
+ special_services: {} # Optional
56
+ }
57
+ }
58
+
59
+
60
+ # request_shipment examples
61
+ request_shipment_small_hash = {
62
+ requested_shipment: {
63
+ shipment_info: {
64
+ drop_off_type: "REGULAR_PICKUP",
65
+ service_type: 'N',
66
+ currency: 'EUR',
67
+ unit_of_measurement: 'SI', # Or SU, UK, US
68
+ account: ENV['DHL_CUSTOMER_CODE'],
69
+
70
+ },
71
+ ship_timestamp: Time.now.+(5.days).strftime('%Y-%m-%dT19:%M:%SGMT+01:00'), # When is the shipment going to be ready for pickup?
72
+ payment_info: 'DDP',
73
+ international_detail: {
74
+ commodities: {
75
+ number_of_pieces: 1,
76
+ description: 'Goods',
77
+ }
78
+ },
79
+ ship: {
80
+ shipper: contact_structure,
81
+ recipient: recipient_contact_structure,
82
+ },
83
+ packages: [
84
+ requested_packages: {
85
+ weight: '15',
86
+ dimensions: {
87
+ length: '3',
88
+ width: '3',
89
+ height: '3'
90
+ },
91
+ customer_references: 'ewqqwe'
92
+ },
93
+ :attributes! => { requested_packages: { number: 1 } }
94
+ ]
95
+ }
96
+ }
97
+ response = client.call(:create_shipment_request, message: request_shipment_small_hash )
98
+
99
+ request_shipment_hash = {
100
+ requested_shipment: {
101
+
102
+ shipment_info: {
103
+ # REGULAR_PICKUP if regularly served, REQUEST_COURIER if a courier should specifically go
104
+ drop_off_type: "REGULAR_PICKUP",
105
+ service_type: '',
106
+ currency: 'EUR',
107
+ unit_of_measurement: 'SI', # Or SU, UK, US
108
+ account: '', # Optional, the customer account
109
+ billing: { # Optional
110
+ shipper_account_number: '', # DHL Account Number
111
+ shipping_payment_type: '', # S for ShipperAccountNumber, R for BillingAccountNumber, or T for BillingAccountNumber
112
+ billing_account_number: '', # Optional, if PaymentType is R or T
113
+ },
114
+ special_services: {}, # Optional
115
+
116
+ shipment_identification_number: nil, # Unused
117
+ packages_count: nil, # Unused
118
+ send_package: nil # Unused
119
+ },
120
+ ship_timestamp: Time.now.strftime('%Y-%m-%dT%H:%M:%SGMT%z'), # When is the shipment going to be ready for pickup?
121
+ payment_info: nil,
122
+ international_detail: {
123
+ commodities: {
124
+ number_of_pieces: 1,
125
+ description: 'Goods',
126
+ country_of_manufacture: 'IT', # Optional
127
+ quantity: '1', # Optional
128
+ unit_price: '100.00', # Optional
129
+ customs_value: '100.00' # Optional
130
+ },
131
+ content: 'NON_DOCUMENTS', # Optional, NON_DOCUMENTS or DOCUMENTS
132
+ export_reference: nil # Optional; e.g.: EEI/ITN reference information required for the US export
133
+ },
134
+ ship: {
135
+ shipper: contact_structure,
136
+ recipient: contact_structure,
137
+ pickup: contact_structure # Optional
138
+ },
139
+ packages: {
140
+ requested_packages: [
141
+ {
142
+ weight: '15.000',
143
+ dimensions: {
144
+ length: '3,0',
145
+ width: '3,0',
146
+ height: '3,0'
147
+ },
148
+ customer_references: 'ewqqwe',
149
+ insured_value: '100,00' # Optional
150
+ }
151
+ ]
152
+ }
153
+ }
154
+ }
155
+
156
+
157
+
158
+ def address_structure
159
+ {
160
+ street_lines: 'Loc Bellocchi 68B',
161
+ city: 'Fano',
162
+ postal_code: '61032',
163
+ country_code: 'IT',
164
+ street_name: 'Loc Bellocchi', # Optional
165
+ street_number: '68B', # Optional
166
+ # street_lines_2: '', # Optional
167
+ # street_lines_3: '', # Optional
168
+ state_or_province_code: 'PU' # Optional
169
+ }
170
+ end
171
+
172
+ def recipient_address_structure
173
+ {
174
+ street_lines: 'via Stephenson 48',
175
+ city: 'Milano',
176
+ postal_code: '20028',
177
+ country_code: 'IT',
178
+ street_name: 'via Stephenson', # Optional
179
+ street_number: '48', # Optional
180
+ # street_lines_2: '', # Optional
181
+ # street_lines_3: '', # Optional
182
+ state_or_province_code: 'MI' # Optional
183
+ }
184
+ end
185
+
186
+
187
+ def contact_structure
188
+ {
189
+ contact: {
190
+ person_name: 'Alessandro Mencarini',
191
+ company_name: 'freego',
192
+ phone_number: '+391234567890',
193
+ email_address: 'a.mencarini@freegoweb.it' # Optional
194
+ },
195
+ address: address_structure
196
+ }
197
+ end
198
+ def recipient_contact_structure
199
+ {
200
+ contact: {
201
+ person_name: 'Maurizio de Magnis',
202
+ company_name: 'Momit',
203
+ phone_number: '+390987654321',
204
+ email_address: 'maurizio.demagnis@momit.it' # Optional
205
+ },
206
+ address: recipient_address_structure
207
+ }
208
+ end