File Coverage

blib/lib/Business/FedEx/RateRequest.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Business::FedEx::RateRequest;
2              
3 1     1   22616 use 5.008008;
  1         4  
  1         37  
4 1     1   5 use strict;
  1         2  
  1         64  
5 1     1   6 use warnings;
  1         6  
  1         50  
6              
7             require Exporter;
8              
9 1     1   4539 use LWP::UserAgent;
  1         89736  
  1         34  
10 1     1   436 use XML::Simple;
  0            
  0            
11             use Data::Dumper;
12              
13             use Time::Piece;
14            
15             our @ISA = qw(Exporter);
16              
17             # Items to export into callers namespace by default. Note: do not export
18             # names by default without a very good reason. Use EXPORT_OK instead.
19             # Do not simply export all your public functions/methods/constants.
20              
21             # This allows declaration use Business::FedEx::RateRequest ':all';
22             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
23             # will save memory.
24             our %EXPORT_TAGS = ( 'all' => [ qw(
25            
26             ) ] );
27              
28             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
29              
30             our @EXPORT = qw();
31              
32             our $VERSION = '1.00';
33              
34             # FedEx Shipping notes
35             our %ship_note;
36             $ship_note{'FEDEX SAMEDAY'} = 'Fastest Delivery time based on flight availability';
37             $ship_note{'FIRST_OVERNIGHT'} = 'Overnight Delivery by 8:00 or 8:30 am';
38             $ship_note{'PRIORITY_OVERNIGHT'} = 'Overnight Delivery by 10:30 am';
39             $ship_note{'STANDARD_OVERNIGHT'} = 'Overnight Delivery by 3:00 pm';
40             $ship_note{'FEDEX_2_DAY'} = '2 Business Days Delivery by 4:30 pm';
41             $ship_note{'FEDEX_EXPRESS_SAVER'} = '3 Business Days Delivery by 4:30 pm';
42             $ship_note{'FEDEX_GROUND'} = '1-5 Business Days Delivery day based on distance to destination';
43             $ship_note{'FEDEX_HOME_DELIVERY'} = '1-5 Business Days Delivery day based on distance to destination';
44              
45             $ship_note{'INTERNATIONAL_NEXT_FLIGHT'} = 'Fastest Delivery time based on flight availability';
46             $ship_note{'INTERNATIONAL_FIRST'} = '2 Business Days Delivery by 8:00 or 8:30 am to select European cities';
47             $ship_note{'INTERNATIONAL_PRIORITY'}= '1-3 Business Days Delivery time based on country';
48             $ship_note{'INTERNATIONAL_ECONOMY'} = '2-5 Business Days Delivery time based on country';
49             $ship_note{'INTERNATIONAL_GROUND'} = '3-7 Business Days Delivery to Canada and Puerto Rico';
50              
51             # Preloaded methods go here.
52              
53             sub new {
54              
55             my $name = shift;
56             my $class = ref($name) || $name;
57              
58             my %args = @_;
59              
60             my $self = {
61             uri => $args{'uri'},
62             account => $args{'account'},
63             meter => $args{'meter'},
64             key => $args{'key'},
65             password => $args{'password'},
66             err_msg => "",
67             };
68              
69             my @rqd_lst = qw/uri meter account key password/;
70             foreach my $param (@rqd_lst) { unless ( $args{$param} ) { $self->{'err_msg'}="$param required"; return 0; } }
71              
72             $self->{UA} = LWP::UserAgent->new(agent => 'perlworks');
73             if ( $args{'timeout'} ) { $self->{UA}->timeout($args{'timeout'}); }
74            
75             #$self->{REQ} = HTTP::Request->new(POST=>$self->{uri}); # Create a request
76              
77             bless ($self, $class);
78             }
79              
80             # - - - - - - - - - - - - - - -
81             sub get_rates
82             {
83             my $self = shift @_;
84             my %args = @_;
85              
86             # As of Jan 2014 Fedex without warning changed the return xml document. The elements with versionized name spaces were changed to generic tags.
87             # so what was is now Sheessssh why would they change something like this....
88            
89             my $ver_prefix = ''; # Added a version namespace prefix in case they add it back in at a latter date.
90            
91             my @rqd_lst = qw/src_zip dst_zip weight/;
92             foreach my $param (@rqd_lst) { unless ( $args{$param} ) { $self->{'err_msg'}="$param required"; return 0; } }
93              
94             unless ( $args{'src_country'} ) { $args{'src_country'} = 'US' }
95             unless ( $args{'dst_country'} ) { $args{'dst_country'} = 'US' }
96             unless ( $args{'dst_residential'}) { $args{'dst_residential'} = 'false' }
97             unless ( $args{'weight_units'} ) { $args{'weight_units'} = 'LB'}
98             unless ( $args{'size_units'} ) { $args{'size_units'} = 'IN' }
99             unless ( $args{'length'} ) { $args{'length'} = '5' }
100             unless ( $args{'width'} ) { $args{'width'} = '5' }
101             unless ( $args{'height'} ) { $args{'height'} = '5' }
102             unless ( $args{'dropoff_type'} ) { $args{'dropoff_type'} = 'REGULAR_PICKUP' }
103             unless ( $args{'insured_value'} ) { $args{'insured_value'} = '0' }
104            
105             my $datetime = localtime;
106             $args{'timestamp'} = $datetime->datetime;
107            
108             my $xml_snd_doc = $self->gen_xml_v9(\%args);
109             #my $xml_snd_doc = $self->gen_xml_v10(\%args);
110              
111             #-#print $xml_snd_doc; exit; # debug line
112              
113             my $response = $self->{UA}->post($self->{'uri'}, Content_Type=>'text/xml', Content=>$xml_snd_doc);
114              
115             unless ($response->is_success)
116             {
117             $self->{'err_msg'} = "Error Request: " . $response->status_line;
118             return 0;
119             }
120            
121             # Must be success let's parse
122              
123             my $rtn = $response->as_string;
124             $rtn =~ /(.*)\n\n(.*)/s;
125            
126             my $hdr = $1; # Don't use for anything right now
127             my $xml_rtn_doc = $2; # The object of this all....
128              
129             my $xml_obj = new XML::Simple;
130              
131             my $data = $xml_obj->XMLin($xml_rtn_doc); # Time consuming operation. could use a regexp to speed up if necessary.
132            
133             #-#print $response->as_string; exit; # Debug line
134              
135             my $rate_lst_ref = $data->{"${ver_prefix}RateReplyDetails"};
136            
137             my @rtn_lst; # This will be returned
138              
139             unless ( defined $rate_lst_ref )
140             {
141             $self->{'err_msg'} = $data->{faultstring} || 'No rate data returned';
142             return 0;
143             } # Kyle's catch
144              
145             # If only one rate service
146             if ( ref $rate_lst_ref eq 'HASH' ) { $rate_lst_ref = [ $rate_lst_ref ] }
147            
148             my $i = 0;
149             foreach my $detail_ref ( @{$rate_lst_ref} )
150             {
151             my $ah_ref = $detail_ref->{"${ver_prefix}RatedShipmentDetails"};
152             my $ship_cost;
153            
154             if ( ref($ah_ref) eq 'ARRAY' )
155             {
156             $ship_cost = $ah_ref->[0]->{"${ver_prefix}ShipmentRateDetail"}->{"${ver_prefix}TotalNetCharge"}->{"${ver_prefix}Amount"};
157             }
158             else
159             {
160             $ship_cost = $ah_ref->{"${ver_prefix}ShipmentRateDetail"}->{"${ver_prefix}TotalNetCharge"}->{"${ver_prefix}Amount"};
161             }
162              
163             my $ServiceType = $detail_ref->{"${ver_prefix}ServiceType"};
164              
165             # Tags
166             my $tag = lc($ServiceType);
167             $tag =~ s/_/ /g;
168             $tag =~ s/\b(\w)/\U$1/g;
169              
170             # Notes
171             my $note = $ship_note{"$ServiceType"};
172              
173             $rtn_lst[$i] = {'ServiceType'=>$ServiceType, 'ship_cost'=>$ship_cost, 'ship_tag'=>$tag, 'ship_note'=>$note};
174             $i++;
175             }
176            
177             return wantarray ? @rtn_lst : \@rtn_lst;
178             }
179              
180             # - - - - - - - - - - - - - - -
181             sub gen_xml_v10
182             {
183             my $self = shift;
184             my $args = shift;
185              
186             my $rqst = qq(
187            
188            
189            
190            
191             $self->{'key'}
192             $self->{'password'}
193            
194            
195            
196             $self->{'account'}
197             $self->{'meter'}
198            
199            
200             Rate a Single Package V10
201            
202            
203             crs
204             10
205             0
206             0
207            
208             1
209             FDXE
210            
211             $args->{'timestamp'}
212             $args->{'dropoff_type'}
213             YOUR_PACKAGING
214            
215             $self->{'account'}
216            
217             PERSONAL_STATE
218             1057
219             ShipperTinsUsage
220            
221            
222             SY32030
223             Sunil Yadav
224             Syntel Inc
225             9545871684
226             020
227             sunil_yadav3\@syntelinc.com
228            
229            
230             SHIPPER ADDRESS LINE 1
231             SHIPPER ADDRESS LINE 2
232             COLORADO SPRINGS
233             CO
234             $args->{'src_zip'}
235             CO
236             $args->{'src_country'}
237             0
238            
239            
240            
241            
242             Receipient
243             Receiver Org
244             9982145555
245             011
246             receiver\@yahoo.com
247            
248            
249             RECIPIENT ADDRESS LINE 1
250             RECIPIENT ADDRESS LINE 2
251             DENVER
252             CO
253             $args->{'dst_zip'}
254             CO
255             $args->{'dst_country'}
256             0
257            
258            
259             DEN001
260            
261            
262             SY32030
263             Sunil Yadav
264             Syntel Inc
265             9545871684
266             020
267             sunil_yadav3\@syntelinc.com
268            
269            
270             SHIPPER ADDRESS LINE 1
271             SHIPPER ADDRESS LINE 2
272             COLORADO SPRINGS
273             CO
274             80915
275             CO
276             US
277             0
278            
279            
280            
281             SENDER
282            
283            
284             US
285            
286            
287             ACCOUNT
288             1
289            
290             1
291             1
292             1
293            
294             $args->{'weight_units'}
295             $args->{'weight'}
296            
297            
298             $args->{'length'}
299             $args->{'width'}
300             $args->{'height'}
301             $args->{'size_units'}
302            
303             BAG
304            
305             PRTNMBR007
306             ITMNMBR007
307             10
308             ContentDescription
309            
310            
311            
312            
313             );
314              
315             #$rqst =~ s/\n//g;
316             return $rqst;
317             }
318              
319             # - - - - - - - - - - - - - - -
320             sub gen_xml_v9
321             {
322             my $self = shift;
323             my $args = shift;
324              
325             my $rqst = <
326            
327            
328            
329            
330             $self->{'key'}
331             $self->{'password'}
332            
333            
334            
335             $self->{'account'}
336             $self->{'meter'}
337            
338            
339             Perlworks
340            
341            
342             crs
343             9
344             0
345             0
346            
347            
348             $args->{'timestamp'}
349             $args->{'dropoff_type'}
350             YOUR_PACKAGING
351            
352             USD
353             $args->{'insured_value'}
354            
355            
356             $self->{'account'}
357            
358             $args->{'src_zip'}
359             $args->{'src_country'}
360            
361            
362            
363            
364             $args->{'dst_zip'}
365             $args->{'dst_country'}
366             $args->{'dst_residential'}
367            
368            
369            
370             SENDER
371            
372             $self->{'account'}
373             USD
374            
375            
376             ACCOUNT
377             1
378             INDIVIDUAL_PACKAGES
379            
380             1
381            
382             $args->{'weight_units'}
383             $args->{'weight'}
384            
385            
386             $args->{'length'}
387             $args->{'width'}
388             $args->{'height'}
389             $args->{'size_units'}
390            
391            
392            
393            
394             END
395              
396             #$rqst =~ s/\n//g;
397             return $rqst;
398             }
399              
400             sub err_msg
401             {
402             my $self = shift @_;
403             return $self->{err_msg};
404             }
405              
406              
407             # Autoload methods go after =cut, and are processed by the autosplit program.
408              
409             1;
410             __END__