deliveries 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/main.yml +19 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +34 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +127 -0
- data/LICENSE.txt +21 -0
- data/README.md +207 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/deliveries.gemspec +36 -0
- data/lib/deliveries/address.rb +71 -0
- data/lib/deliveries/checkpoint.rb +12 -0
- data/lib/deliveries/collection_point.rb +45 -0
- data/lib/deliveries/courier.rb +69 -0
- data/lib/deliveries/couriers/correos_express/address.rb +31 -0
- data/lib/deliveries/couriers/correos_express/collection_points/search/format_response.rb +82 -0
- data/lib/deliveries/couriers/correos_express/collection_points/search.rb +56 -0
- data/lib/deliveries/couriers/correos_express/labels/generate.rb +68 -0
- data/lib/deliveries/couriers/correos_express/pickups/create/defaults.rb +60 -0
- data/lib/deliveries/couriers/correos_express/pickups/create/format_params.rb +95 -0
- data/lib/deliveries/couriers/correos_express/pickups/create.rb +66 -0
- data/lib/deliveries/couriers/correos_express/pickups/cutoff_time/format_params.rb +40 -0
- data/lib/deliveries/couriers/correos_express/pickups/cutoff_time.rb +61 -0
- data/lib/deliveries/couriers/correos_express/pickups/trace/correos.test.wsdl +163 -0
- data/lib/deliveries/couriers/correos_express/pickups/trace/correos.wsdl +163 -0
- data/lib/deliveries/couriers/correos_express/pickups/trace/format_response.rb +71 -0
- data/lib/deliveries/couriers/correos_express/pickups/trace.rb +49 -0
- data/lib/deliveries/couriers/correos_express/shipments/create/defaults.rb +80 -0
- data/lib/deliveries/couriers/correos_express/shipments/create/format_params.rb +99 -0
- data/lib/deliveries/couriers/correos_express/shipments/create.rb +101 -0
- data/lib/deliveries/couriers/correos_express/shipments/trace/format_response.rb +67 -0
- data/lib/deliveries/couriers/correos_express/shipments/trace.rb +65 -0
- data/lib/deliveries/couriers/correos_express.rb +162 -0
- data/lib/deliveries/couriers/dummy.rb +106 -0
- data/lib/deliveries/couriers/mondial_relay/address.rb +31 -0
- data/lib/deliveries/couriers/mondial_relay/collection_points/search/format_response.rb +103 -0
- data/lib/deliveries/couriers/mondial_relay/labels/generate.rb +40 -0
- data/lib/deliveries/couriers/mondial_relay/pickups/create/format_params.rb +57 -0
- data/lib/deliveries/couriers/mondial_relay/shipments/create/defaults.rb +96 -0
- data/lib/deliveries/couriers/mondial_relay/shipments/create/format_params.rb +68 -0
- data/lib/deliveries/couriers/mondial_relay/shipments/create.rb +36 -0
- data/lib/deliveries/couriers/mondial_relay/shipments/trace/format_response.rb +94 -0
- data/lib/deliveries/couriers/mondial_relay/shipments/trace.rb +47 -0
- data/lib/deliveries/couriers/mondial_relay/status_codes.rb +105 -0
- data/lib/deliveries/couriers/mondial_relay.rb +189 -0
- data/lib/deliveries/couriers/mondial_relay_dual/address.rb +31 -0
- data/lib/deliveries/couriers/mondial_relay_dual/pickups/create/format_params.rb +39 -0
- data/lib/deliveries/couriers/mondial_relay_dual/shipments/create/format_params.rb +101 -0
- data/lib/deliveries/couriers/mondial_relay_dual/shipments/create.rb +133 -0
- data/lib/deliveries/couriers/mondial_relay_dual.rb +105 -0
- data/lib/deliveries/couriers/spring/address.rb +23 -0
- data/lib/deliveries/couriers/spring/labels/generate.rb +33 -0
- data/lib/deliveries/couriers/spring/request.rb +43 -0
- data/lib/deliveries/couriers/spring/shipments/create/defaults.rb +73 -0
- data/lib/deliveries/couriers/spring/shipments/create/format_params.rb +77 -0
- data/lib/deliveries/couriers/spring/shipments/create.rb +45 -0
- data/lib/deliveries/couriers/spring/shipments/trace/format_response.rb +79 -0
- data/lib/deliveries/couriers/spring/shipments/trace.rb +29 -0
- data/lib/deliveries/couriers/spring.rb +84 -0
- data/lib/deliveries/couriers/ups/collection_points/search.rb +142 -0
- data/lib/deliveries/couriers/ups/json_request.rb +40 -0
- data/lib/deliveries/couriers/ups/labels/generate.rb +72 -0
- data/lib/deliveries/couriers/ups/shipments/create.rb +210 -0
- data/lib/deliveries/couriers/ups/shipments/trace.rb +79 -0
- data/lib/deliveries/couriers/ups.rb +122 -0
- data/lib/deliveries/couriers.rb +14 -0
- data/lib/deliveries/delivery.rb +20 -0
- data/lib/deliveries/errors.rb +22 -0
- data/lib/deliveries/label.rb +20 -0
- data/lib/deliveries/label_utils.rb +67 -0
- data/lib/deliveries/labels.rb +40 -0
- data/lib/deliveries/pickup.rb +15 -0
- data/lib/deliveries/shipment.rb +15 -0
- data/lib/deliveries/tracking_info.rb +29 -0
- data/lib/deliveries/version.rb +5 -0
- data/lib/deliveries.rb +63 -0
- metadata +240 -0
@@ -0,0 +1,189 @@
|
|
1
|
+
require_relative 'mondial_relay/collection_points/search/format_response'
|
2
|
+
require_relative 'mondial_relay/shipments/create'
|
3
|
+
require_relative 'mondial_relay/shipments/create/defaults'
|
4
|
+
require_relative 'mondial_relay/shipments/create/format_params'
|
5
|
+
require_relative 'mondial_relay/shipments/trace'
|
6
|
+
require_relative 'mondial_relay/shipments/trace/format_response'
|
7
|
+
require_relative 'mondial_relay/pickups/create/format_params'
|
8
|
+
require_relative 'mondial_relay/labels/generate'
|
9
|
+
require_relative 'mondial_relay/status_codes'
|
10
|
+
require_relative 'mondial_relay/address'
|
11
|
+
require 'savon'
|
12
|
+
|
13
|
+
module Deliveries
|
14
|
+
module Couriers
|
15
|
+
module MondialRelay
|
16
|
+
extend Courier
|
17
|
+
|
18
|
+
Config = Struct.new(
|
19
|
+
:mondial_relay_merchant,
|
20
|
+
:mondial_relay_key
|
21
|
+
)
|
22
|
+
|
23
|
+
WSDL_ENDPOINT = 'http://api.mondialrelay.com/Web_Services.asmx?WSDL'.freeze
|
24
|
+
|
25
|
+
module_function
|
26
|
+
|
27
|
+
def api_client
|
28
|
+
Savon.client wsdl: WSDL_ENDPOINT,
|
29
|
+
logger: Deliveries.logger,
|
30
|
+
log: Deliveries.debug
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_collection_points(country:, postcode:)
|
34
|
+
# Build params needed by web service.
|
35
|
+
params = { 'Enseigne' => Deliveries::Couriers::MondialRelay.config(:mondial_relay_merchant),
|
36
|
+
'Pays' => country, 'NumPointRelais' => '', 'Ville' => '',
|
37
|
+
'CP' => postcode, 'Latitude' => '', 'Longitude' => '',
|
38
|
+
'Taille' => '', 'Poids' => '', 'Action' => '',
|
39
|
+
'DelaiEnvoi' => '0', 'RayonRecherche' => '', 'TypeActivite' => '', 'NACE' => '' }
|
40
|
+
# Calculate security parameters.
|
41
|
+
params['Security'] = calculate_security_param params
|
42
|
+
|
43
|
+
response = api_client.call :wsi3_point_relais_recherche, message: params
|
44
|
+
# If response returns OK stat code.
|
45
|
+
if (response_result = response.body[:wsi3_point_relais_recherche_response][:wsi3_point_relais_recherche_result]) &&
|
46
|
+
response_result[:stat] == '0'
|
47
|
+
|
48
|
+
collection_points = []
|
49
|
+
[response_result.dig(:points_relais, :point_relais_details)].flatten.compact.each do |point_params|
|
50
|
+
collection_point_params = CollectionPoints::Search::FormatResponse.new(response: point_params).execute
|
51
|
+
collection_points << Deliveries::CollectionPoint.new(collection_point_params)
|
52
|
+
end
|
53
|
+
|
54
|
+
collection_points
|
55
|
+
else
|
56
|
+
raise Deliveries::APIError.new(
|
57
|
+
StatusCodes.message_for(response_result[:stat].to_i),
|
58
|
+
response_result[:stat]
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_collection_point(global_point_id:)
|
64
|
+
global_point = Deliveries::CollectionPoint.parse_global_point_id(global_point_id: global_point_id)
|
65
|
+
|
66
|
+
params = { 'Enseigne' => Deliveries::Couriers::MondialRelay.config(:mondial_relay_merchant),
|
67
|
+
'Pays' => global_point.country, 'NumPointRelais' => global_point.point_id, 'Ville' => '',
|
68
|
+
'CP' => '', 'Latitude' => '', 'Longitude' => '',
|
69
|
+
'Taille' => '', 'Poids' => '', 'Action' => '',
|
70
|
+
'DelaiEnvoi' => '0', 'RayonRecherche' => '', 'TypeActivite' => '', 'NACE' => '' }
|
71
|
+
|
72
|
+
# Calculate security parameters.
|
73
|
+
params['Security'] = calculate_security_param params
|
74
|
+
|
75
|
+
response = api_client.call :wsi3_point_relais_recherche, message: params
|
76
|
+
|
77
|
+
response_result = response.body.dig(:wsi3_point_relais_recherche_response,
|
78
|
+
:wsi3_point_relais_recherche_result)
|
79
|
+
|
80
|
+
point_relais_details = response_result.dig(:points_relais, :point_relais_details)
|
81
|
+
|
82
|
+
if response_result[:stat] == '0' && point_relais_details.present?
|
83
|
+
collection_point_params = CollectionPoints::Search::FormatResponse.new(response: point_relais_details).execute
|
84
|
+
Deliveries::CollectionPoint.new(collection_point_params)
|
85
|
+
else
|
86
|
+
raise Deliveries::APIError.new(
|
87
|
+
StatusCodes.message_for(response_result[:stat].to_i),
|
88
|
+
response_result[:stat]
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def create_shipment(sender:, receiver:, parcels:, reference_code:, collection_point: nil, shipment_date: nil, remarks: nil, language: 'FR')
|
94
|
+
params = Shipments::Create::FormatParams.new(
|
95
|
+
sender: sender.courierize(:mondial_relay),
|
96
|
+
receiver: receiver.courierize(:mondial_relay),
|
97
|
+
parcels: parcels,
|
98
|
+
collection_point: collection_point,
|
99
|
+
reference_code: reference_code,
|
100
|
+
remarks: remarks,
|
101
|
+
language: language
|
102
|
+
).execute
|
103
|
+
|
104
|
+
tracking_code, label_url = Shipments::Create.new(
|
105
|
+
params: params
|
106
|
+
).execute.values_at(:tracking_code, :label_url)
|
107
|
+
|
108
|
+
Deliveries::Shipment.new(
|
109
|
+
courier_id: 'mondial_relay',
|
110
|
+
sender: sender,
|
111
|
+
receiver: receiver,
|
112
|
+
parcels: parcels,
|
113
|
+
reference_code: reference_code,
|
114
|
+
tracking_code: tracking_code,
|
115
|
+
shipment_date: shipment_date,
|
116
|
+
label: Label.new(url: label_url)
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
def create_pickup(sender:, receiver:, parcels:, reference_code:,
|
121
|
+
pickup_date: nil, remarks: nil, language: 'FR')
|
122
|
+
params = Pickups::Create::FormatParams.new(
|
123
|
+
sender: sender.courierize(:mondial_relay),
|
124
|
+
receiver: receiver.courierize(:mondial_relay),
|
125
|
+
parcels: parcels,
|
126
|
+
reference_code: reference_code,
|
127
|
+
pickup_date: pickup_date,
|
128
|
+
remarks: remarks,
|
129
|
+
language: language
|
130
|
+
).execute
|
131
|
+
|
132
|
+
tracking_code, label_url = Shipments::Create.new(
|
133
|
+
params: params
|
134
|
+
).execute.values_at(:tracking_code, :label_url)
|
135
|
+
|
136
|
+
Deliveries::Pickup.new(
|
137
|
+
courier_id: 'mondial_relay',
|
138
|
+
sender: sender,
|
139
|
+
receiver: receiver,
|
140
|
+
parcels: parcels,
|
141
|
+
reference_code: reference_code,
|
142
|
+
tracking_code: tracking_code,
|
143
|
+
pickup_date: pickup_date,
|
144
|
+
label: Label.new(url: label_url)
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
def shipment_info(tracking_code:, language: 'FR')
|
149
|
+
response = Shipments::Trace.new(
|
150
|
+
tracking_code: tracking_code,
|
151
|
+
language: language
|
152
|
+
).execute
|
153
|
+
|
154
|
+
tracking_info_params = Shipments::Trace::FormatResponse.new(response: response).execute
|
155
|
+
|
156
|
+
tracking_info_params = tracking_info_params.merge(tracking_code: tracking_code)
|
157
|
+
Deliveries::TrackingInfo.new(tracking_info_params)
|
158
|
+
end
|
159
|
+
|
160
|
+
def pickup_info(tracking_code:, language: 'FR')
|
161
|
+
shipment_info(tracking_code: tracking_code, language: language)
|
162
|
+
end
|
163
|
+
|
164
|
+
def get_label(tracking_code:, language: 'FR')
|
165
|
+
label_url = Labels::Generate.new(
|
166
|
+
tracking_codes: tracking_code,
|
167
|
+
language: language
|
168
|
+
).execute
|
169
|
+
|
170
|
+
Deliveries::Label.new(url: label_url)
|
171
|
+
end
|
172
|
+
|
173
|
+
def get_labels(tracking_codes:, language: 'FR')
|
174
|
+
labels_url = Labels::Generate.new(
|
175
|
+
tracking_codes: tracking_codes,
|
176
|
+
language: language
|
177
|
+
).execute
|
178
|
+
|
179
|
+
Deliveries::Labels.new(url: labels_url)
|
180
|
+
end
|
181
|
+
|
182
|
+
def calculate_security_param(params)
|
183
|
+
Digest::MD5.hexdigest(params.map do |_, v|
|
184
|
+
v
|
185
|
+
end.join + Deliveries::Couriers::MondialRelay.config(:mondial_relay_key)).upcase
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Deliveries
|
2
|
+
module Couriers
|
3
|
+
module MondialRelayDual
|
4
|
+
class Address < Deliveries::Address
|
5
|
+
def name
|
6
|
+
I18n.transliterate(@name.to_s).gsub(%r{[^0-9A-Z_\-'., /]}i, '').upcase.truncate(30, omission: '')
|
7
|
+
end
|
8
|
+
|
9
|
+
def street
|
10
|
+
I18n.transliterate(@street.to_s).gsub(%r{[^0-9A-Z_\-'., /]}i, '').upcase.truncate(30, omission: '')
|
11
|
+
end
|
12
|
+
|
13
|
+
def city
|
14
|
+
I18n.transliterate(@city.to_s).gsub(/[^A-Z_\-' ]/i, '').upcase.truncate(30, omission: '')
|
15
|
+
end
|
16
|
+
|
17
|
+
def country
|
18
|
+
@country.to_s.upcase
|
19
|
+
end
|
20
|
+
|
21
|
+
def phone
|
22
|
+
format_international_phone
|
23
|
+
end
|
24
|
+
|
25
|
+
def email
|
26
|
+
format_email
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Deliveries
|
2
|
+
module Couriers
|
3
|
+
module MondialRelayDual
|
4
|
+
module Pickups
|
5
|
+
class Create
|
6
|
+
class FormatParams < Shipments::Create::FormatParams
|
7
|
+
def initialize(sender:, receiver:, parcels:, reference_code:, remarks:, language:)
|
8
|
+
super(
|
9
|
+
sender: sender,
|
10
|
+
receiver: receiver,
|
11
|
+
parcels: parcels,
|
12
|
+
reference_code: reference_code,
|
13
|
+
remarks: remarks,
|
14
|
+
language: language,
|
15
|
+
collection_point: nil
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def delivery_mode
|
22
|
+
{
|
23
|
+
mode: 'LCC',
|
24
|
+
location: ''
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def collection_mode
|
29
|
+
{
|
30
|
+
mode: 'REL',
|
31
|
+
location: ''
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Deliveries
|
2
|
+
module Couriers
|
3
|
+
module MondialRelayDual
|
4
|
+
module Shipments
|
5
|
+
class Create
|
6
|
+
class FormatParams
|
7
|
+
attr_accessor :sender, :receiver, :parcels, :reference_code, :collection_point, :remarks, :language
|
8
|
+
|
9
|
+
def initialize(sender:, receiver:, parcels:, reference_code:, collection_point:, remarks:, language:)
|
10
|
+
self.sender = sender.courierize(:mondial_relay_dual)
|
11
|
+
self.receiver = receiver.courierize(:mondial_relay_dual)
|
12
|
+
self.parcels = parcels
|
13
|
+
self.reference_code = reference_code
|
14
|
+
self.collection_point = collection_point
|
15
|
+
self.remarks = remarks
|
16
|
+
self.language = language
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute
|
20
|
+
{
|
21
|
+
culture: culture,
|
22
|
+
order_no: reference_code,
|
23
|
+
parcel_count: parcels.to_i,
|
24
|
+
delivery_mode: delivery_mode,
|
25
|
+
collection_mode: collection_mode,
|
26
|
+
deliver_instruction: remarks,
|
27
|
+
parcels: parcel_list,
|
28
|
+
sender: {
|
29
|
+
streetname: sender.street,
|
30
|
+
country_code: sender.country,
|
31
|
+
post_code: sender.postcode,
|
32
|
+
city: sender.city,
|
33
|
+
address_add_1: sender.name,
|
34
|
+
phone_no: sender.phone,
|
35
|
+
email: sender.email
|
36
|
+
},
|
37
|
+
recipient: {
|
38
|
+
streetname: receiver.street,
|
39
|
+
country_code: receiver.country,
|
40
|
+
post_code: receiver.postcode,
|
41
|
+
city: receiver.city,
|
42
|
+
address_add_1: receiver.name,
|
43
|
+
phone_no: receiver.phone,
|
44
|
+
email: receiver.email
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def culture
|
52
|
+
case language.to_s.downcase
|
53
|
+
when 'es' then 'es-ES'
|
54
|
+
when 'de' then 'de-DE'
|
55
|
+
when 'en' then 'en-GB'
|
56
|
+
else 'fr-FR'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def delivery_mode
|
61
|
+
if collection_point
|
62
|
+
{
|
63
|
+
mode: '24R',
|
64
|
+
location: collection_point.point_id
|
65
|
+
}
|
66
|
+
else
|
67
|
+
home_delivery_mode = MondialRelayDual.config("countries.#{receiver.country.downcase}.home_delivery_mode") || 'HOM'
|
68
|
+
{
|
69
|
+
mode: home_delivery_mode,
|
70
|
+
location: ''
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def collection_mode
|
76
|
+
{
|
77
|
+
mode: 'CCC',
|
78
|
+
location: ''
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def parcel_list
|
83
|
+
list = []
|
84
|
+
parcels.times do
|
85
|
+
list << {
|
86
|
+
content: 'Vêtements',
|
87
|
+
weight: {
|
88
|
+
value: '1000',
|
89
|
+
unit: 'gr'
|
90
|
+
}
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
list
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Deliveries
|
4
|
+
module Couriers
|
5
|
+
module MondialRelayDual
|
6
|
+
module Shipments
|
7
|
+
class Create
|
8
|
+
attr_accessor :params
|
9
|
+
|
10
|
+
def initialize(params:)
|
11
|
+
self.params = params
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute
|
15
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'utf-8') do |xml|
|
16
|
+
xml.ShipmentCreationRequest('xmlns:xsi0' => 'http://www.w3.org/2001/XMLSchema-instance',
|
17
|
+
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', 'xmlns' => 'http://www.example.org/Request') do
|
18
|
+
xml.Context do
|
19
|
+
xml.Login Deliveries::Couriers::MondialRelayDual.config(:dual_carrier_login)
|
20
|
+
xml.Password Deliveries::Couriers::MondialRelayDual.config(:dual_carrier_password)
|
21
|
+
xml.CustomerId Deliveries::Couriers::MondialRelayDual.config(:dual_carrier_customer_id)
|
22
|
+
xml.Culture params[:culture]
|
23
|
+
xml.VersionAPI '1.0'
|
24
|
+
end
|
25
|
+
|
26
|
+
xml.OutputOptions do
|
27
|
+
xml.OutputFormat '10x15'
|
28
|
+
xml.OutputType 'PdfUrl'
|
29
|
+
end
|
30
|
+
|
31
|
+
xml.ShipmentsList do
|
32
|
+
xml.Shipment do
|
33
|
+
xml.OrderNo params[:order_no]
|
34
|
+
xml.CustomerNo
|
35
|
+
xml.ParcelCount params[:parcel_count]
|
36
|
+
xml.DeliveryMode(Mode: params.dig(:delivery_mode, :mode),
|
37
|
+
Location: params.dig(:delivery_mode,
|
38
|
+
:location))
|
39
|
+
xml.CollectionMode(Mode: params.dig(:collection_mode, :mode),
|
40
|
+
Location: params.dig(:collection_mode,
|
41
|
+
:location))
|
42
|
+
xml.Parcels do
|
43
|
+
params[:parcels].each do |parcel|
|
44
|
+
xml.Parcel do
|
45
|
+
xml.Content parcel[:content]
|
46
|
+
xml.Weight(Value: parcel.dig(:weight, :value), Unit: parcel.dig(:weight, :unit))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
xml.DeliveryInstruction params[:deliver_instruction]
|
51
|
+
xml.Sender do
|
52
|
+
xml.Address do
|
53
|
+
xml.Title
|
54
|
+
xml.Firstname
|
55
|
+
xml.Lastname
|
56
|
+
xml.Streetname params.dig(:sender, :streetname)
|
57
|
+
xml.HouseNo
|
58
|
+
xml.CountryCode params.dig(:sender, :country_code)
|
59
|
+
xml.PostCode params.dig(:sender, :post_code)
|
60
|
+
xml.City params.dig(:sender, :city)
|
61
|
+
xml.AddressAdd1 params.dig(:sender, :address_add_1)
|
62
|
+
xml.AddressAdd2
|
63
|
+
xml.AddressAdd3
|
64
|
+
xml.PhoneNo params.dig(:sender, :phone_no)
|
65
|
+
xml.MobileNo
|
66
|
+
xml.Email params.dig(:sender, :email)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
xml.Recipient do
|
70
|
+
xml.Address do
|
71
|
+
xml.Title
|
72
|
+
xml.Firstname
|
73
|
+
xml.Lastname
|
74
|
+
xml.Streetname params.dig(:recipient, :streetname)
|
75
|
+
xml.HouseNo
|
76
|
+
xml.CountryCode params.dig(:recipient, :country_code)
|
77
|
+
xml.PostCode params.dig(:recipient, :post_code)
|
78
|
+
xml.City params.dig(:recipient, :city)
|
79
|
+
xml.AddressAdd1 params.dig(:recipient, :address_add_1)
|
80
|
+
xml.AddressAdd2
|
81
|
+
xml.AddressAdd3
|
82
|
+
xml.PhoneNo params.dig(:recipient, :phone_no)
|
83
|
+
xml.MobileNo
|
84
|
+
xml.Email params.dig(:recipient, :email)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
response = HTTParty.post(
|
93
|
+
api_endpoint,
|
94
|
+
body: builder.to_xml,
|
95
|
+
headers: { 'Content-Type': 'application/xml', Accept: 'application/xml' },
|
96
|
+
debug_output: Deliveries.debug ? Deliveries.logger : nil
|
97
|
+
)
|
98
|
+
|
99
|
+
xml_doc = Nokogiri::XML(response.body, &:strict)
|
100
|
+
xml_doc.remove_namespaces!
|
101
|
+
|
102
|
+
shipment_number = xml_doc.xpath('//ShipmentCreationResponse/ShipmentsList/Shipment/@ShipmentNumber').first&.content
|
103
|
+
pdf_url = xml_doc.xpath('//ShipmentCreationResponse/ShipmentsList/Shipment/LabelList/Label/Output').first&.content
|
104
|
+
|
105
|
+
unless shipment_number && pdf_url
|
106
|
+
error_node = xml_doc.xpath('//ShipmentCreationResponse/StatusList/Status').find do |n|
|
107
|
+
%w[Critical\ Error Error].include?(n[:Level])
|
108
|
+
end
|
109
|
+
raise Deliveries::APIError.new(error_node[:Message], error_node[:Code]) if error_node
|
110
|
+
|
111
|
+
raise Deliveries::ClientError, 'Cannot obtain error code from the API response'
|
112
|
+
end
|
113
|
+
|
114
|
+
{
|
115
|
+
tracking_code: shipment_number,
|
116
|
+
pdf_url: pdf_url
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def api_endpoint
|
123
|
+
if MondialRelayDual.live?
|
124
|
+
MondialRelayDual::API_ENDPOINT_LIVE
|
125
|
+
else
|
126
|
+
MondialRelayDual::API_ENDPOINT_TEST
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require_relative 'mondial_relay_dual/shipments/create'
|
2
|
+
require_relative 'mondial_relay_dual/shipments/create/format_params'
|
3
|
+
require_relative 'mondial_relay_dual/pickups/create/format_params'
|
4
|
+
require_relative 'mondial_relay_dual/address'
|
5
|
+
|
6
|
+
module Deliveries
|
7
|
+
module Couriers
|
8
|
+
module MondialRelayDual
|
9
|
+
extend Courier
|
10
|
+
|
11
|
+
Config = Struct.new(
|
12
|
+
:dual_carrier_login,
|
13
|
+
:dual_carrier_password,
|
14
|
+
:dual_carrier_customer_id,
|
15
|
+
:countries
|
16
|
+
)
|
17
|
+
|
18
|
+
API_ENDPOINT_LIVE = 'https://connect-api.mondialrelay.com/api/shipment'.freeze
|
19
|
+
API_ENDPOINT_TEST = 'https://connect-api-sandbox.mondialrelay.com/api/shipment'.freeze
|
20
|
+
|
21
|
+
module_function
|
22
|
+
|
23
|
+
def get_collection_points(country:, postcode:)
|
24
|
+
MondialRelay.get_collection_points(
|
25
|
+
country: country,
|
26
|
+
postcode: postcode
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_collection_point(global_point_id:)
|
31
|
+
MondialRelay.get_collection_point(global_point_id: global_point_id)
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_shipment(sender:, receiver:, parcels:, reference_code:, collection_point: nil, shipment_date: nil, remarks: nil, language: nil)
|
35
|
+
params = Shipments::Create::FormatParams.new(
|
36
|
+
sender: sender,
|
37
|
+
receiver: receiver,
|
38
|
+
parcels: parcels,
|
39
|
+
collection_point: collection_point,
|
40
|
+
reference_code: reference_code,
|
41
|
+
remarks: remarks,
|
42
|
+
language: language
|
43
|
+
).execute
|
44
|
+
|
45
|
+
tracking_code, pdf_url = Shipments::Create.new(
|
46
|
+
params: params
|
47
|
+
).execute.values_at(:tracking_code, :pdf_url)
|
48
|
+
|
49
|
+
Deliveries::Shipment.new(
|
50
|
+
courier_id: 'mondial_relay_dual',
|
51
|
+
sender: sender,
|
52
|
+
receiver: receiver,
|
53
|
+
parcels: parcels,
|
54
|
+
reference_code: reference_code,
|
55
|
+
tracking_code: tracking_code,
|
56
|
+
shipment_date: shipment_date,
|
57
|
+
label: Label.new(url: pdf_url)
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_pickup(sender:, receiver:, parcels:, reference_code:,
|
62
|
+
pickup_date: nil, remarks: nil, language: nil)
|
63
|
+
params = Pickups::Create::FormatParams.new(
|
64
|
+
sender: sender,
|
65
|
+
receiver: receiver,
|
66
|
+
parcels: parcels,
|
67
|
+
reference_code: reference_code,
|
68
|
+
remarks: remarks,
|
69
|
+
language: language
|
70
|
+
).execute
|
71
|
+
|
72
|
+
tracking_code, pdf_url = Shipments::Create.new(
|
73
|
+
params: params
|
74
|
+
).execute.values_at(:tracking_code, :pdf_url)
|
75
|
+
|
76
|
+
Deliveries::Pickup.new(
|
77
|
+
courier_id: 'mondial_relay_dual',
|
78
|
+
sender: sender,
|
79
|
+
receiver: receiver,
|
80
|
+
parcels: parcels,
|
81
|
+
reference_code: reference_code,
|
82
|
+
tracking_code: tracking_code,
|
83
|
+
pickup_date: pickup_date,
|
84
|
+
label: Label.new(url: pdf_url)
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
def shipment_info(tracking_code:, language: nil)
|
89
|
+
MondialRelay.shipment_info(tracking_code: tracking_code, language: language)
|
90
|
+
end
|
91
|
+
|
92
|
+
def pickup_info(tracking_code:, language: nil)
|
93
|
+
MondialRelay.pickup_info(tracking_code: tracking_code, language: language)
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_label(**)
|
97
|
+
raise NotImplementedError, 'This courier does not support get_label operation'
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_labels(**)
|
101
|
+
raise NotImplementedError, 'This courier does not support get_labels operation'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Deliveries
|
2
|
+
module Couriers
|
3
|
+
module Spring
|
4
|
+
class Address < Deliveries::Address
|
5
|
+
def name
|
6
|
+
@name.to_s[0, 35]
|
7
|
+
end
|
8
|
+
|
9
|
+
def street
|
10
|
+
@street.to_s[0, 35]
|
11
|
+
end
|
12
|
+
|
13
|
+
def street2
|
14
|
+
@street.to_s[35, 35].to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def street3
|
18
|
+
@street.to_s[70, 35].to_s
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Deliveries
|
2
|
+
module Couriers
|
3
|
+
module Spring
|
4
|
+
module Labels
|
5
|
+
class Generate
|
6
|
+
attr_accessor :tracking_code
|
7
|
+
|
8
|
+
def initialize(tracking_code:)
|
9
|
+
self.tracking_code = tracking_code
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute
|
13
|
+
params = {
|
14
|
+
Apikey: Deliveries::Couriers::Spring.config(:api_key),
|
15
|
+
Command: 'GetShipmentLabel',
|
16
|
+
Shipment: {
|
17
|
+
LabelFormat: 'PDF',
|
18
|
+
TrackingNumber: tracking_code
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
response = Deliveries::Couriers::Spring::Request.execute(params: params)
|
23
|
+
|
24
|
+
{
|
25
|
+
url: response[:Shipment][:CarrierTrackingUrl],
|
26
|
+
decoded_label: Base64.decode64(response[:Shipment][:LabelImage]).force_encoding('binary')
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|