File Coverage

lib/WebService/Shippo.pm
Criterion Covered Total %
statement 28 28 100.0
branch 2 4 50.0
condition 1 3 33.3
subroutine 8 8 100.0
pod n/a
total 39 43 90.7


line stmt bran cond sub pod time code
1 7     7   318833 use strict;
  7         15  
  7         178  
2 7     7   34 use warnings;
  7         11  
  7         481  
3              
4             package WebService::Shippo;
5             # ABSTRACT: A Shippo Perl API wrapper
6             our $VERSION = '0.0.19';
7             require WebService::Shippo::Entities;
8 7     7   34 use boolean ':all';
  7         11  
  7         39  
9 7     7   6113 use Params::Callbacks ( 'callbacks', 'callback' );
  7         1319415  
  7         563  
10 7     7   66 use base ( 'Exporter' );
  7         16  
  7         1435  
11              
12             our @EXPORT = qw(
13             true
14             false
15             boolean
16             callback
17             );
18              
19             sub import
20             {
21 7     7   81 my ( $class ) = @_;
22             # Configure Shippo client on import
23 7         36 WebService::Shippo::Config->config;
24             # The API key is overridden with the environment's value if defined.
25             WebService::Shippo::Resource->api_credentials(
26             @ENV{ 'SHIPPO_USER', 'SHIPPO_PASS' } )
27 7 50 33     44 if $ENV{SHIPPO_USER} && !$ENV{SHIPPO_TOKEN};
28             WebService::Shippo::Resource->api_key( $ENV{SHIPPO_TOKEN} )
29 7 50       38 if $ENV{SHIPPO_TOKEN};
30             # Pass call frame to Exporter's import for further processing
31 7         24662 goto &Exporter::import;
32             }
33              
34             BEGIN {
35 7     7   39 no warnings 'once';
  7         12  
  7         690  
36             # There are some useful symbols defined elsewhere that I'd like to
37             # make available (alias) via the root namespace.
38 7     7   21 *api_key = *WebService::Shippo::Resource::api_key;
39 7         15 *api_credentials = *WebService::Shippo::Resource::api_credentials;
40 7         13 *pretty = *WebService::Shippo::Object::pretty;
41 7         15 *response = *WebService::Shippo::Request::response;
42 7         930 *Shippo:: = *WebService::Shippo::;
43             }
44              
45             1;
46              
47             =pod
48              
49             =encoding utf8
50              
51             =head1 UNDER CONSTRUCTION
52              
53             B
54             documented and should, therefore, be considered a work in progress.>
55              
56             =head1 NAME
57              
58             WebService::Shippo - Shippo API Client
59              
60             =head1 VERSION
61              
62             version 0.0.19
63              
64             =head1 SYNOPIS
65              
66             B: though scripts and modules must always C
67             to import the client software, the C portion of that package
68             namespace may be dropped when subsequently referring to the main package
69             or any of its resource classes. For example, C
70             and C refer to the same class.
71              
72             To compel the developer to continue using the C prefix does
73             seem like an unreasonable form of torture, besides which, it probably
74             doesn't leave much scope for indenting code as some class names would be
75             very long. Use it, or don't use it. It's entirely up to you.
76              
77             use strict;
78             use LWP::UserAgent;
79             use WebService::Shippo;
80            
81             # If you aren't using a config file or the environment (SHIPPO_TOKEN=...)
82             # to supply your API key, you can do so here:
83            
84             Shippo->api_key('PASTE YOUR AUTH TOKEN HERE')
85             unless Shippo->api_key;
86            
87             # Complete example illustrating the the process of Shipment creation
88             # through to label generation.
89             #
90             # Create a Shipment object:
91            
92             my $shipment = Shippo::Shipment->create(
93             object_purpose => 'PURCHASE',
94             address_from => {
95             object_purpose => 'PURCHASE',
96             name => 'Shawn Ippotle',
97             company => 'Shippo',
98             street1 => '215 Clayton St.',
99             city => 'San Francisco',
100             state => 'CA',
101             zip => '94117',
102             country => 'US',
103             phone => '+1 555 341 9393',
104             email => 'shippotle@goshippo.com'
105             },
106             address_to => {
107             object_purpose => 'PURCHASE',
108             name => 'Mr Hippo',
109             company => '',
110             street1 => 'Broadway 1',
111             street2 => '',
112             city => 'New York',
113             state => 'NY',
114             zip => '10007',
115             country => 'US',
116             phone => '+1 555 341 9393',
117             email => 'mrhippo@goshippo.com'
118             },
119             parcel => {
120             length => '5',
121             width => '5',
122             height => '5',
123             distance_unit => 'in',
124             weight => '2',
125             mass_unit => 'lb'
126             }
127             );
128            
129             # Retrieve shipping rates and select preferred rate:
130            
131             my $rates = Shippo::Shipment->get_shipping_rates( $shipment->object_id );
132             my $preferred_rate = $rates->item(2);
133            
134             # Purchase label at the preferred rate:
135            
136             my $transaction = Shippo::Transaction->create(
137             rate => $preferred_rate->object_id,
138             label_file_type => 'PNG',
139             );
140            
141             # Get the shipping label:
142            
143             my $label_url = Shippo::Transaction->get_shipping_label( $transaction->object_id );
144             my $browser = LWP::UserAgent->new;
145             $browser->get( $transaction->label_url, ':content_file' => './sample.png' );
146            
147             # Print the transaction object...
148            
149             print "Transaction:\n", $transaction->to_json(1); # '1' makes the JSON readable
150              
151             --[content dumped to console]--
152             Transaction:
153             {
154             "commercial_invoice_url" : null,
155             "customs_note" : "",
156             "label_url" : "https://shippo-delivery-east.s3.amazonaws.com/da2e68fe85f94a9ebca458d9f9d
157             2446b.PNG?Signature=BjD2JMQt0ATd5jUWAKm%2B6FHcBPM%3D&Expires=1477323662&AWSAccessKeyId=AKIA
158             JGLCC5MYLLWIG42A",
159             "messages" : [],
160             "metadata" : "",
161             "notification_email_from" : false,
162             "notification_email_other" : "",
163             "notification_email_to" : false,
164             "object_created" : "2015-10-25T15:41:01.182Z",
165             "object_id" : "da2e68fe85f94a9ebca458d9f9d2446b",
166             "object_owner" : "******@*********.***",
167             "object_state" : "VALID",
168             "object_status" : "SUCCESS",
169             "object_updated" : "2015-10-25T15:41:02.494Z",
170             "order" : null,
171             "pickup_date" : null,
172             "rate" : "3c76e81733d7417b9a801ce957f4219d",
173             "submission_note" : "",
174             "tracking_history" : [],
175             "tracking_number" : "9499907123456123456781",
176             "tracking_status" : {
177             "object_created" : "2015-10-25T15:41:02.451Z",
178             "object_id" : "02ce6dbd6d5a48cfb764fdeb0cb6e404",
179             "object_updated" : "2015-10-25T15:41:02.451Z",
180             "status" : "UNKNOWN",
181             "status_date" : null,
182             "status_details" : ""
183             },
184             "tracking_url_provider" : "https://tools.usps.com/go/TrackConfirmAction_input?origTrackN
185             um=9499907123456123456781",
186             "was_test" : true
187             }
188             --[end of content]--
189              
190             The sample code in this synopsis produced the following label (at a much
191             larger size, of course), which was then saved as a PNG file using the
192             C package:
193              
194             =over 2
195              
196             =item * L
197              
198             =back
199              
200             =head1 DESCRIPTION
201              
202             Shippo connects you with multiple shipping providers (USPS, UPS and Fedex,
203             for example) through one interface, offering you great discounts on a
204             selection of shipping rates. You can sign-up for an account at
205             L.
206              
207             The Shippo API can be used to automate and customize shipping capabilities
208             for your e-commerce store or marketplace, enabling you to retrieve shipping
209             rates, create and purchase shipping labels, track packages, and much more.
210              
211             Though Shippo I offer official API clients for a bevy of major languages,
212             the venerable Perl 5 was not included in that list. This community offering
213             attempts to correct that omission ;-)
214              
215             =head2 API Resources
216              
217             Access to all Shippo API resources is via URLs relative to the same encrypted
218             API endpoint (https://api.goshippo.com/v1/).
219              
220             There are resource item classes to help with the nitty-gritty of interacting
221             each type of resource:
222              
223             =over 2
224              
225             =item * Addresses
226              
227             =item * Parcels
228              
229             =item * Shipments
230              
231             =item * Rates
232              
233             =item * Transactions
234              
235             =item * Customs Items
236              
237             =item * Customs Declarations
238              
239             =item * Refunds
240              
241             =item * Manifests
242              
243             =item * Carrier Accounts
244              
245             =back
246              
247             Each item class has a related collection class with a similar name I
248             plural form>. The rationale behind this is that the Shippo API can be used
249             to retrieve single objects with the C method, and collections of
250             objects with the C method, and different behaviours may be applied
251             to collections, which is why both forms exist.
252              
253             =head2 Request & Response Data
254              
255             The Perl client ensures that requests are properly encoded and passed to the
256             correct API endpoints using appropriate HTTP methods. There is documentation
257             for each API resource, containing more details on the values accepted by and
258             returned for a given resource (see L).
259              
260             All API requests return responses encoded as JSON strings, which the client
261             converts into Perl blessed object references of the correct type. As a rule,
262             any resource attribute documented in the API specification will have an
263             accessor of the same same in a Perl instance of that object.
264              
265             =head2 REST & Disposable Objects
266              
267             The Shippo API is built with simplicity and RESTful principles in mind:
268             B requests are used to create objects, B requests to fetch and
269             list objects, and B requests to update objects. The Perl client provides
270             C, C, C and C methods for use with resource
271             objects that permit such operations.
272              
273             Addresses, Parcels, Shipments, Rates, Transactions, Refunds, Customs Items and
274             Customs Declarations are disposable objects. This means that once you create
275             an object, you cannot change it. Instead, create a new one with the desired
276             values. Carrier Accounts are the exception and may be updated via B
277             requests.
278              
279             =head1 METHODS
280              
281             =head2 api_key
282              
283             Get or set the key used by API requests for Shippo's token-based
284             authentication. This is Shippo's preferred method of authentication.
285              
286             =over 2
287              
288             =item * Return the token currently being used for authentication.
289              
290             my $api_key = Shippo->api_key;
291              
292             =item * Set the token to be used for authentication.
293            
294             Shippo->api_key($auth_token);
295              
296             The C method is chainable when used as a setter.
297              
298             =back
299              
300             =head2 api_credentials
301              
302             Get or set the login credentials used by API requests for Shippo's legacy
303             authentication. Legacy authentication means encoding the HTTP Authorization
304             header for Basic Authentication so, even though requests and repsonses are
305             encrypted, you should still consider using the token-based authentication
306             instead (see C).
307              
308             =over 2
309              
310             =item * Return the login credentials currently being used for authentication.
311              
312             my ($username, $password) = Shippo->api_credentials;
313              
314             =item * Set the credentials to be used for authentication.
315              
316             Shippo->api_credentials($username, $password);
317              
318             The C method is chainable when used as a setter.
319              
320             =back
321              
322             Whenever a configuration specifies both token and login credentials, the
323             client will always favour token-based authentication. If C and
324             C are both set manually then it is the most recently
325             set mechanism that defines the HTTP Authorization header.
326              
327             =head2 pretty
328              
329             Get or set the state of the attribute influencing the default readability
330             of objects serialized as JSON using the C method or automatic
331             stringification.
332              
333             =over 2
334              
335             =item * Return the current state of the C attribute.
336            
337              
338             my $boolean = Shippo->pretty;
339              
340             =item * Set the state of the C attribute.
341              
342             Shippo->pretty($boolean);
343              
344             =back
345              
346             B: the C method also takes optional boolean argument that
347             may be set to C or C to achieve the same effect for a single
348             serialization, regardless of the default currently in force.
349            
350             =head2 response
351              
352             my $last_response = Shippo->response;
353              
354             Returns a copy of the C> resulting from the most recent request.
355              
356             =head1 EXPORTS
357              
358             The C package exports a number of helpful subroutines by
359             default:
360              
361             =head2 true
362              
363             my $fedex_account = Shippo::CarrierAccount->create(
364             carrier => 'fedex',
365             account_id => '',
366             parameters => { meter => '' },
367             test => true,
368             active => true
369             );
370              
371             Returns a scalar value which will evaluate to true.
372              
373             Since the I connecting Shippo's API and the Perl client is
374             JSON, it can feel more natural to think in those terms. Thus, C may be
375             used in place of C<1>. Now, when creating a new object from a JSON example,
376             any literal and accidental use of C or C is much less likely
377             to result in misery.
378              
379             See Ingy's L package for more guidance.
380              
381             =head2 false
382              
383             my $fedex_account = Shippo::CarrierAccount->create(
384             carrier => 'fedex',
385             account_id => '',
386             parameters => { meter => '' },
387             test => false,
388             active => false
389             );
390              
391             Returns a scalar value which will evaluate to false.
392              
393             Since the I connecting Shippo's API and the Perl client is
394             JSON, it can feel more natural to think in those terms. Thus, C may be
395             used in place of C<0>. Now, when creating a new object from a JSON example,
396             any literal and accidental use of C or C is much less likely
397             to result in misery.
398              
399             See Ingy's L package for more guidance.
400              
401             =head2 boolean
402              
403             my $bool = boolean($value);
404              
405             Casts a scalar value to a boolean value (C or C).
406              
407             See Ingy's L package for more guidance.
408              
409             =head2 callback
410              
411             Shippo::CarrierAccounts->all(callback {
412             $_->enable_test_mode;
413             });
414            
415             Returns a blessed C suitable for use as a callback. Some methods accept
416             optional blocking callbacks in order to facilitate list transformations, so
417             this package makes C<&Params::Callbacks::callback> available for use.
418              
419             See L for more guidance.
420              
421             =head1 CONFIGURATION
422              
423             While the client does provide C and C methods to
424             help with authentication, hard-coding such calls in anything more mission
425             critical than a simple test script may I be the best way to go.
426              
427             As soon as it is imported, one of the first things the client does is search
428             a number of locations for a L
429             configuration file. The first one it finds is loaded.
430              
431             In order, the locations searched are as follows:
432              
433             =over 2
434              
435             =item * C<./.shipporc>
436              
437             =item * C/I/I/.shipporc>
438              
439             =item * C/shipporc>
440              
441             =item * C/I/I/I/I/I/WebService/Shippo/Config.yml>
442              
443             =back
444              
445             The configuration file is very simple and needs to have the following
446             structure, though not all elements are mandatory:
447              
448             ---
449             username: martymcfly@pinheads.org
450             password: yadayada
451             private_token: f0e1d2c3b4a5968778695a4b3c2d1e0f96877869
452             public_token: 96877869f0e1d2c3b4a5968778695a4b3c2d1e0f
453             default_token: private_token
454              
455             At a minimum, your configuration should define values for C and
456             C. These are your Shippo Private and Publishable Auth tokens,
457             which are found on your L.
458              
459             =head1 FULL API DOCUMENTATION
460              
461             =over 2
462              
463             =item * For API documentation, go to L
464              
465             =item * For API support, contact L with any
466             questions.
467              
468             =back
469              
470             =head1 SEE ALSO
471              
472             =head2 Shippo Objects
473              
474             =over 2
475              
476             =item * L
477              
478             =item * L
479              
480             =item * L
481              
482             =item * L
483              
484             =item * L
485              
486             =item * L
487              
488             =item * L
489              
490             =item * L
491              
492             =item * L
493              
494             =item * L
495              
496             =back
497              
498             =head2 Shippo Collections
499              
500             =over 2
501              
502             =item * L
503              
504             =item * L
505              
506             =item * L
507              
508             =item * L
509              
510             =item * L
511              
512             =item * L
513              
514             =item * L
515              
516             =item * L
517              
518             =item * L
519              
520             =item * L
521              
522             =back
523              
524             =head1 REPOSITORY
525              
526             =over 2
527              
528             =item * L
529              
530             =item * L
531              
532             =back
533              
534             =head1 AUTHOR
535              
536             Iain Campbell
537              
538             =head1 COPYRIGHT AND LICENSE
539              
540             This software is copyright E 2015 by Iain Campbell.
541              
542             You may distribute this software under the terms of either the GNU General
543             Public License or the Artistic License, as specified in the Perl README
544             file.
545              
546              
547             =cut