File Coverage

blib/lib/Net/Stripe/Simple.pm
Criterion Covered Total %
statement 120 476 25.2
branch 20 146 13.7
condition 7 47 14.8
subroutine 25 124 20.1
pod 23 23 100.0
total 195 816 23.9


line stmt bran cond sub pod time code
1             package Net::Stripe::Simple;
2             $Net::Stripe::Simple::VERSION = '0.003';
3             # ABSTRACT: simple, non-Moose interface to the Stripe API
4              
5 3     3   227043 use v5.10;
  3         12  
6 3     3   14 use strict;
  3         5  
  3         212  
7 3     3   17 use warnings;
  3         5  
  3         144  
8              
9 3     3   16 use Exporter qw(import);
  3         5  
  3         104  
10 3     3   2127 use LWP::UserAgent;
  3         125159  
  3         183  
11 3     3   1863 use HTTP::Request::Common qw(GET POST DELETE);
  3         5278  
  3         216  
12 3     3   1392 use MIME::Base64 qw(encode_base64);
  3         1952  
  3         179  
13 3     3   17 use URI::Escape qw(uri_escape);
  3         6  
  3         156  
14 3     3   14 use Scalar::Util qw(reftype blessed);
  3         4  
  3         176  
15 3     3   2104 use JSON ();
  3         33282  
  3         132  
16 3     3   1724 use Devel::StackTrace;
  3         8745  
  3         93  
17              
18 3     3   1710 use Net::Stripe::Simple::Data;
  3         6  
  3         76  
19 3     3   1347 use Net::Stripe::Simple::Error;
  3         8  
  3         219  
20              
21             our @EXPORT_OK = qw(true false null data_object);
22             our %EXPORT_TAGS = ( const => [qw(true false null)], all => \@EXPORT_OK );
23              
24 3     3   16 use constant API_BASE => 'https://api.stripe.com/v1';
  3         7  
  3         17420  
25              
26             # version of stripe's API to use
27             our $STRIPE_VERSION = '2014-06-17';
28              
29              
30             sub new {
31 1     1 1 2103 my ( $class, $api, $version ) = @_;
32 1   33     11 $class = ref($class) || $class;
33 1 50       4 die 'API key required' unless $api;
34 1   33     9 $version //= $STRIPE_VERSION;
35              
36 1   50     7 my $pkg_version = $Net::Stripe::Simple::VERSION // '0.01';
37              
38 1         13 my $ua = LWP::UserAgent->new;
39 1         4061 $ua->agent("$class/$pkg_version");
40 1         134 my $auth = 'Basic ' . encode_base64( $api . ':' );
41 1         22 bless { ua => $ua, auth => $auth, version => $version }, $class;
42             }
43              
44             # API
45              
46             # generic argument validation
47             sub _validate {
48 1     1   3 my $self = shift;
49 1         3 my $name = shift;
50 1         2 my $actions = shift;
51 1         3 my $action = shift;
52 1         5 ( my $err_name = $name ) =~ tr/_/ /;
53 1 0       8 my $args = ref $_[0] eq 'HASH' ? $_[0] : { @_ == 1 ? ( id => $_[0] ) : @_ };
    50          
54 1 50       6 die "$err_name action required" unless $action;
55 1 50       4 die "unknown $err_name action: $action" unless exists $actions->{$action};
56 1   33     22 my $method = $actions->{$action} //= $self->can("_${action}_$name");
57 1 50       5 die "logic error: $action $err_name action not implemented" unless $method;
58 1         4 return $args, $method;
59             }
60              
61             # removes private keys from args
62             sub _clean {
63 1     1   3 my $args = shift;
64 1         8 delete @$args{ grep /^_/, keys %$args };
65             }
66              
67             # generic implementations of these operations
68              
69             sub _retrieve {
70 0     0   0 my ( $self, $args ) = @_;
71 0         0 my ( $base, $id ) = @$args{qw(_base id)};
72 0 0       0 _invalid('No id provided.') unless defined $id;
73 0         0 return $self->_get( $base . '/' . uri_escape($id) );
74             }
75              
76             sub _update {
77 0     0   0 my ( $self, $args ) = @_;
78 0         0 my ( $base, $id ) = delete @$args{qw(_base id)};
79 0 0       0 _invalid('No id provided.') unless defined $id;
80 0         0 _clean($args);
81 0         0 return $self->_post( $base . '/' . uri_escape($id), $args );
82             }
83              
84             sub _create {
85 1     1   4 my ( $self, $args ) = @_;
86 1         4 my $base = delete $args->{_base};
87 1         4 _clean($args);
88 1         7 return $self->_post( $base, $args );
89             }
90              
91             sub _list {
92 0     0   0 my ( $self, $args ) = @_;
93 0         0 my $base = delete $args->{_base};
94 0         0 _clean($args);
95 0         0 return $self->_get( $base, $args );
96             }
97              
98             sub _del {
99 0     0   0 my ( $self, $args ) = @_;
100 0         0 my ( $base, $id ) = @$args{qw(_base id)};
101 0 0       0 _invalid('No id provided.') unless defined $id;
102 0         0 return $self->_delete( $base . '/' . uri_escape($id) );
103             }
104              
105             # create a common uri base; expects customer id and sub-base
106             sub _customer_base {
107 0     0   0 my $customer = shift;
108 0 0       0 _invalid('No customer id provided.') unless defined $customer;
109 0         0 return 'customers/' . uri_escape($customer) . '/' . shift;
110             }
111              
112              
113             sub charges {
114 0     0 1 0 my $self = shift;
115             state $actions =
116 0         0 { map { $_ => undef } qw(create retrieve update refund capture list) };
  0         0  
117 0         0 my ( $args, $method ) = $self->_validate( 'charge', $actions, @_ );
118 0         0 $args->{_base} = 'charges';
119 0         0 return $self->$method($args);
120             }
121 0     0   0 sub _create_charge { goto &_create }
122 0     0   0 sub _retrieve_charge { goto &_retrieve }
123 0     0   0 sub _update_charge { goto &_update }
124              
125             sub _capture_charge {
126 0     0   0 my ( $self, $args ) = @_;
127 0         0 my ( $base, $id ) = delete @$args{qw(_base id)};
128 0 0       0 _invalid('No id provided.') unless defined $id;
129 0         0 _clean($args);
130 0         0 return $self->_post( $base . '/' . uri_escape($id) . '/capture', $args );
131             }
132 0     0   0 sub _list_charge { goto &_list }
133              
134             sub _refund_charge {
135 0     0   0 my ( $self, $args ) = @_;
136 0         0 my ( $base, $id ) = delete @$args{qw(_base id)};
137 0 0       0 _invalid('No id provided.') unless defined $id;
138 0         0 _clean($args);
139 0         0 return $self->_post( $base . '/' . uri_escape($id) . '/refund', $args );
140             }
141              
142              
143             sub refunds {
144 0     0 1 0 my $self = shift;
145 0         0 state $actions = { map { $_ => undef } qw(create retrieve update list) };
  0         0  
146 0         0 my ( $args, $method ) = $self->_validate( 'refund', $actions, @_ );
147 0         0 $args->{_base} = 'charges';
148 0         0 return $self->$method($args);
149             }
150              
151             sub _create_refund {
152 0     0   0 my ( $self, $args ) = @_;
153 0         0 my ( $base, $id ) = delete @$args{qw(_base id)};
154 0 0       0 _invalid('No id provided.') unless defined $id;
155 0         0 _clean($args);
156 0         0 return $self->_post( $base . '/' . uri_escape($id) . '/refunds', $args );
157             }
158              
159             sub _retrieve_refund {
160 0     0   0 my ( $self, $args ) = @_;
161 0         0 my ( $base, $id, $charge ) = delete @$args{qw(_base id charge)};
162 0         0 my @errors;
163 0 0       0 push @errors, 'No id provided.' unless defined $id;
164 0 0       0 push @errors, 'No charge provided.' unless defined $charge;
165 0 0       0 _invalid( join ' ', @errors ) if @errors;
166 0         0 _clean($args);
167 0         0 return $self->_get(
168             $base . '/' . uri_escape($charge) . '/refunds/' . uri_escape($id),
169             $args );
170             }
171              
172             sub _update_refund {
173 0     0   0 my ( $self, $args ) = @_;
174 0         0 my ( $base, $id, $charge ) = delete @$args{qw(_base id charge)};
175 0         0 my @errors;
176 0 0       0 push @errors, 'No id provided.' unless defined $id;
177 0 0       0 push @errors, 'No charge provided.' unless defined $charge;
178 0 0       0 _invalid( join ' ', @errors ) if @errors;
179 0         0 _clean($args);
180 0         0 return $self->_post(
181             $base . '/' . uri_escape($charge) . '/refunds/' . uri_escape($id),
182             $args );
183             }
184              
185             sub _list_refund {
186 0     0   0 my ( $self, $args ) = @_;
187 0         0 my ( $base, $id ) = delete @$args{qw(_base id)};
188 0 0       0 _invalid('No id provided.') unless defined $id;
189 0         0 _clean($args);
190 0         0 return $self->_get( $base . '/' . uri_escape($id) . '/refunds', $args );
191             }
192              
193              
194             sub customers {
195 1     1 1 3288 my $self = shift;
196             state $actions =
197 1         6 { map { $_ => undef } qw(create retrieve update delete list) };
  5         14  
198 1         8 my ( $args, $method ) = $self->_validate( 'customer', $actions, @_ );
199 1         5 $args->{_base} = 'customers';
200 1         4 return $self->$method($args);
201             }
202 1     1   6 sub _create_customer { goto &_create }
203 0     0   0 sub _retrieve_customer { goto &_retrieve }
204 0     0   0 sub _update_customer { goto &_update }
205 0     0   0 sub _delete_customer { goto &_del }
206 0     0   0 sub _list_customer { goto &_list }
207              
208              
209             sub cards {
210 0     0 1 0 my $self = shift;
211             state $actions =
212 0         0 { map { $_ => undef } qw(create retrieve update delete list) };
  0         0  
213 0         0 my ( $args, $method ) = $self->_validate( 'card', $actions, @_ );
214 0         0 $args->{_base} = 'cards';
215 0         0 return $self->$method($args);
216             }
217              
218             sub _create_card {
219 0     0   0 my ( $self, $args ) = @_;
220 0         0 my ( $base, $id, $customer ) = delete @$args{qw(_base id customer)};
221 0   0     0 $id //= $customer;
222 0         0 _clean($args);
223 0         0 return $self->_post( _customer_base( $id, $base ), $args );
224             }
225              
226             sub _retrieve_card {
227 0     0   0 my ( $self, $args ) = @_;
228 0         0 my ( $base, $id, $customer ) = @$args{qw(_base id customer)};
229 0         0 my @errors;
230 0 0       0 push @errors, 'No id provided.' unless defined $id;
231 0 0       0 push @errors, 'No customer id provided.' unless defined $customer;
232 0 0       0 _invalid( join ' ', @errors ) if @errors;
233 0         0 return $self->_get(
234             _customer_base( $customer, $base ) . '/' . uri_escape($id) );
235             }
236              
237             sub _update_card {
238 0     0   0 my ( $self, $args ) = @_;
239 0         0 my ( $base, $id, $customer ) = delete @$args{qw(_base id customer)};
240 0         0 my @errors;
241 0 0       0 push @errors, 'No id provided.' unless defined $id;
242 0 0       0 push @errors, 'No customer id provided.' unless defined $customer;
243 0 0       0 _invalid( join ' ', @errors ) if @errors;
244 0         0 _clean($args);
245 0         0 return $self->_post(
246             _customer_base( $customer, $base ) . '/' . uri_escape($id), $args );
247             }
248              
249             sub _delete_card {
250 0     0   0 my ( $self, $args ) = @_;
251 0         0 my ( $base, $id, $customer ) = @$args{qw(_base id customer)};
252 0         0 my @errors;
253 0 0       0 push @errors, 'No id provided.' unless defined $id;
254 0 0       0 push @errors, 'No customer id provided.' unless defined $customer;
255 0 0       0 _invalid( join ' ', @errors ) if @errors;
256 0         0 return $self->_delete(
257             _customer_base( $customer, $base ) . '/' . uri_escape($id) );
258             }
259              
260             sub _list_card {
261 0     0   0 my ( $self, $args ) = @_;
262 0         0 my ( $base, $id, $customer ) = delete @$args{qw(_base id customer)};
263 0   0     0 $id //= $customer;
264 0         0 _clean($args);
265 0         0 return $self->_get( _customer_base( $id, $base ), $args );
266             }
267              
268              
269             sub subscriptions {
270 0     0 1 0 my $self = shift;
271             state $actions =
272 0         0 { map { $_ => undef } qw(create retrieve update cancel list) };
  0         0  
273 0         0 my ( $args, $method ) = $self->_validate( 'subscription', $actions, @_ );
274 0         0 $args->{_base} = 'subscriptions';
275 0         0 return $self->$method($args);
276             }
277              
278             sub _create_subscription {
279 0     0   0 my ( $self, $args ) = @_;
280 0         0 my ( $base, $id, $customer ) = delete @$args{qw(_base id customer)};
281 0   0     0 $id //= $customer;
282 0         0 _clean($args);
283 0         0 return $self->_post( _customer_base( $id, $base ), $args );
284             }
285              
286             sub _retrieve_subscription {
287 0     0   0 my ( $self, $args ) = @_;
288 0         0 my ( $base, $id, $customer ) = @$args{qw(_base id customer)};
289 0         0 my @errors;
290 0 0       0 push @errors, 'No id provided.' unless defined $id;
291 0 0       0 push @errors, 'No customer id provided.' unless defined $customer;
292 0 0       0 _invalid( join ' ', @errors ) if @errors;
293 0         0 return $self->_get(
294             _customer_base( $customer, $base ) . '/' . uri_escape($id) );
295             }
296              
297             sub _update_subscription {
298 0     0   0 my ( $self, $args ) = @_;
299 0         0 my ( $base, $id, $customer ) = delete @$args{qw(_base id customer)};
300 0         0 my @errors;
301 0 0       0 push @errors, 'No id provided.' unless defined $id;
302 0 0       0 push @errors, 'No customer id provided.' unless defined $customer;
303 0 0       0 _invalid( join ' ', @errors ) if @errors;
304 0         0 _clean($args);
305 0         0 return $self->_post(
306             _customer_base( $customer, $base ) . '/' . uri_escape($id), $args );
307             }
308              
309             sub _cancel_subscription {
310 0     0   0 my ( $self, $args ) = @_;
311 0         0 my ( $base, $id, $customer ) = @$args{qw(_base id customer)};
312 0         0 my @errors;
313 0 0       0 push @errors, 'No id provided.' unless defined $id;
314 0 0       0 push @errors, 'No customer id provided.' unless defined $customer;
315 0 0       0 _invalid( join ' ', @errors ) if @errors;
316 0         0 return $self->_delete(
317             _customer_base( $customer, $base ) . '/' . uri_escape($id) );
318             }
319              
320             sub _list_subscription {
321 0     0   0 my ( $self, $args ) = @_;
322 0         0 my ( $base, $id, $customer ) = delete @$args{qw(_base id customer)};
323 0   0     0 $id //= $customer;
324 0         0 _clean($args);
325 0         0 return $self->_get( _customer_base( $id, $base ), $args );
326             }
327              
328              
329             sub plans {
330 0     0 1 0 my $self = shift;
331             state $actions =
332 0         0 { map { $_ => undef } qw(create retrieve update delete list) };
  0         0  
333 0         0 my ( $args, $method ) = $self->_validate( 'plan', $actions, @_ );
334 0         0 $args->{_base} = 'plans';
335 0         0 return $self->$method($args);
336             }
337 0     0   0 sub _create_plan { goto &_create }
338 0     0   0 sub _retrieve_plan { goto &_retrieve }
339 0     0   0 sub _update_plan { goto &_update }
340 0     0   0 sub _delete_plan { goto &_del }
341 0     0   0 sub _list_plan { goto &_list }
342              
343              
344             sub coupons {
345 0     0 1 0 my $self = shift;
346 0         0 state $actions = { map { $_ => undef } qw(create retrieve delete list) };
  0         0  
347 0         0 my ( $args, $method ) = $self->_validate( 'coupon', $actions, @_ );
348 0         0 $args->{_base} = 'coupons';
349 0         0 return $self->$method($args);
350             }
351 0     0   0 sub _create_coupon { goto &_create }
352 0     0   0 sub _retrieve_coupon { goto &_retrieve }
353 0     0   0 sub _delete_coupon { goto &_del }
354 0     0   0 sub _list_coupon { goto &_list }
355              
356              
357             sub discounts {
358 0     0 1 0 my $self = shift;
359 0         0 state $actions = { map { $_ => undef } qw(customer subscription) };
  0         0  
360 0         0 my ( $args, $method ) = $self->_validate( 'discount', $actions, @_ );
361 0         0 return $self->$method($args);
362             }
363              
364             sub _customer_discount {
365 0     0   0 my ( $self, $args ) = @_;
366 0         0 my ( $id, $customer ) = @$args{qw(id customer)};
367 0   0     0 $id //= $customer;
368 0         0 return $self->_delete( _customer_base( $id, 'discount' ) );
369             }
370              
371             sub _subscription_discount {
372 0     0   0 my ( $self, $args ) = @_;
373 0         0 my ( $id, $customer ) = @$args{qw(subscription customer)};
374 0         0 my @errors;
375 0 0       0 push @errors, 'No id provided.' unless defined $id;
376 0 0       0 push @errors, 'No customer id provided.' unless defined $customer;
377 0 0       0 _invalid( join ' ', @errors ) if @errors;
378 0         0 my $path =
379             _customer_base( $customer, 'subscriptions' ) . '/'
380             . uri_escape($id)
381             . '/discount';
382 0         0 return $self->_delete($path);
383             }
384              
385              
386             sub invoices {
387 0     0 1 0 my $self = shift;
388             state $actions =
389 0         0 { map { $_ => undef }
  0         0  
390             qw(create retrieve lines update pay list upcoming) };
391 0         0 my ( $args, $method ) = $self->_validate( 'invoice', $actions, @_ );
392 0         0 $args->{_base} = 'invoices';
393 0         0 return $self->$method($args);
394             }
395 0     0   0 sub _create_invoice { goto &_create }
396 0     0   0 sub _retrieve_invoice { goto &_retrieve }
397              
398             sub _lines_invoice {
399 0     0   0 my ( $self, $args ) = @_;
400 0         0 my ( $base, $id ) = delete @$args{qw(_base id)};
401 0 0       0 _invalid('No id provided.') unless defined $id;
402 0         0 _clean($args);
403 0         0 return $self->_get( $base . '/' . uri_escape($id) . '/lines', $args );
404             }
405 0     0   0 sub _update_invoice { goto &_update }
406              
407             sub _pay_invoice {
408 0     0   0 my ( $self, $args ) = @_;
409 0         0 my ( $base, $id ) = @$args{qw(_base id)};
410 0 0       0 _invalid('No id provided.') unless defined $id;
411 0         0 return $self->_post( $base . '/' . uri_escape($id) . '/pay' );
412             }
413 0     0   0 sub _list_invoice { goto &_list }
414              
415             sub _upcoming_invoice {
416 0     0   0 my ( $self, $args ) = @_;
417 0         0 my ( $base, $id, $customer ) = @$args{qw(_base id customer)};
418 0   0     0 $id //= $customer;
419 0 0       0 _invalid('No id provided.') unless defined $id;
420 0         0 return $self->_get( $base . '/upcoming', { customer => $id } );
421             }
422              
423              
424             sub invoice_items {
425 0     0 1 0 my $self = shift;
426             state $actions =
427 0         0 { map { $_ => undef } qw(create retrieve update delete list) };
  0         0  
428 0         0 my ( $args, $method ) = $self->_validate( 'invoice_item', $actions, @_ );
429 0         0 $args->{_base} = 'invoiceitems';
430 0         0 return $self->$method($args);
431             }
432 0     0   0 sub _create_invoice_item { goto &_create }
433 0     0   0 sub _retrieve_invoice_item { goto &_retrieve }
434 0     0   0 sub _update_invoice_item { goto &_update }
435 0     0   0 sub _delete_invoice_item { goto &_del }
436 0     0   0 sub _list_invoice_item { goto &_list }
437              
438              
439             sub disputes {
440 0     0 1 0 my $self = shift;
441 0         0 state $actions = { map { $_ => undef } qw(update close) };
  0         0  
442 0         0 my ( $args, $method ) = $self->_validate( 'dispute', $actions, @_ );
443 0         0 return $self->$method($args);
444             }
445              
446             sub _update_dispute {
447 0     0   0 my ( $self, $args ) = @_;
448 0         0 my $id = delete $args->{id};
449 0 0       0 _invalid('No id provided.') unless defined $id;
450 0         0 _clean($args);
451 0         0 my $path = 'charges/' . uri_escape($id) . '/dispute';
452 0         0 return $self->_post( $path, $args );
453             }
454              
455             sub _close_dispute {
456 0     0   0 my ( $self, $args ) = @_;
457 0         0 my $id = delete $args->{id};
458 0 0       0 _invalid('No id provided.') unless defined $id;
459 0         0 _clean($args);
460 0         0 my $path = 'charges/' . uri_escape($id) . '/dispute/close';
461 0         0 return $self->_post( $path, $args );
462             }
463              
464              
465             sub transfers {
466 0     0 1 0 my $self = shift;
467             state $actions =
468 0         0 { map { $_ => undef } qw(create retrieve update cancel list) };
  0         0  
469 0         0 my ( $args, $method ) = $self->_validate( 'transfer', $actions, @_ );
470 0         0 $args->{_base} = 'transfers';
471 0         0 return $self->$method($args);
472             }
473 0     0   0 sub _create_transfer { goto &_create }
474 0     0   0 sub _retrieve_transfer { goto &_retrieve }
475 0     0   0 sub _update_transfer { goto &_update }
476              
477             sub _cancel_transfer {
478 0     0   0 my ( $self, $args ) = @_;
479 0         0 my ( $base, $id ) = @$args{qw(_base id)};
480 0 0       0 _invalid('No id provided.') unless defined $id;
481 0         0 my $path = $base . '/' . uri_escape($id) . '/cancel';
482 0         0 return $self->_post($path);
483             }
484 0     0   0 sub _list_transfer { goto &_list }
485              
486              
487             sub recipients {
488 0     0 1 0 my $self = shift;
489             state $actions =
490 0         0 { map { $_ => undef } qw(create retrieve update delete list) };
  0         0  
491 0         0 my ( $args, $method ) = $self->_validate( 'recipient', $actions, @_ );
492 0         0 $args->{_base} = 'recipients';
493 0         0 return $self->$method($args);
494             }
495 0     0   0 sub _create_recipient { goto &_create }
496 0     0   0 sub _retrieve_recipient { goto &_retrieve }
497 0     0   0 sub _update_recipient { goto &_update }
498 0     0   0 sub _delete_recipient { goto &_del }
499 0     0   0 sub _list_recipient { goto &_list }
500              
501              
502             sub application_fees {
503 0     0 1 0 my $self = shift;
504 0         0 state $actions = { map { $_ => undef } qw(retrieve refund list) };
  0         0  
505 0         0 my ( $args, $method ) = $self->_validate( 'application_fee', $actions, @_ );
506 0         0 $args->{_base} = 'application_fees';
507 0         0 return $self->$method($args);
508             }
509              
510 0     0   0 sub _retrieve_application_fee { goto &_retrieve }
511 0     0   0 sub _list_application_fee { goto &_list }
512              
513             sub _refund_application_fee {
514 0     0   0 my ( $self, $args ) = @_;
515 0         0 my ( $base, $id ) = delete @$args{qw(_base id)};
516 0 0       0 _invalid('No id provided.') unless defined $id;
517 0         0 _clean($args);
518 0         0 my $path = $base . '/' . uri_escape($id) . '/refund';
519 0         0 return $self->_post( $path, $args );
520             }
521              
522              
523             sub account {
524 0     0 1 0 my $self = shift;
525 0 0       0 unshift @_, 'retrieve' unless @_;
526 0         0 state $actions = { map { $_ => undef } qw(retrieve) };
  0         0  
527 0         0 my ( $args, $method ) = $self->_validate( 'account', $actions, @_ );
528 0         0 $args->{_base} = 'account';
529 0         0 return $self->$method($args);
530             }
531              
532             sub _retrieve_account {
533 0     0   0 my ( $self, $args ) = @_;
534 0         0 my $base = $args->{_base};
535 0         0 return $self->_get($base);
536             }
537              
538              
539             sub balance {
540 0     0 1 0 my $self = shift;
541 0         0 state $actions = { map { $_ => undef } qw(retrieve history transaction) };
  0         0  
542 0         0 my ( $args, $method ) = $self->_validate( 'balance', $actions, @_ );
543 0         0 $args->{_base} = 'balance';
544 0         0 return $self->$method($args);
545             }
546             sub _retrieve_balance {
547 0     0   0 my ( $self, $args ) = @_;
548 0         0 return $self->_get( $args->{_base} );
549             }
550              
551             sub _transaction_balance {
552 0     0   0 my ( $self, $args ) = @_;
553 0         0 my ( $base, $id ) = @$args{qw(_base id)};
554 0 0       0 _invalid('No id provided.') unless defined $id;
555 0         0 my $path = $base . '/history/' . uri_escape($id);
556 0         0 return $self->_get($path);
557             }
558              
559             sub _history_balance {
560 0     0   0 my ( $self, $args ) = @_;
561 0         0 my $base = delete $args->{_base};
562 0         0 _clean($args);
563 0         0 my $path = $base . '/history';
564 0         0 return $self->_get( $path, $args );
565             }
566              
567              
568             sub events {
569 0     0 1 0 my $self = shift;
570 0         0 state $actions = { map { $_ => undef } qw(retrieve list) };
  0         0  
571 0         0 my ( $args, $method ) = $self->_validate( 'event', $actions, @_ );
572 0         0 $args->{_base} = 'events';
573 0         0 return $self->$method($args);
574             }
575 0     0   0 sub _retrieve_event { goto &_retrieve }
576 0     0   0 sub _list_event { goto &_list }
577              
578              
579             sub tokens {
580 0     0 1 0 my $self = shift;
581 0         0 state $actions = { map { $_ => undef } qw(create retrieve bank) };
  0         0  
582 0         0 my ( $args, $method ) = $self->_validate( 'token', $actions, @_ );
583 0         0 $args->{_base} = 'tokens';
584 0         0 return $self->$method($args);
585             }
586 0     0   0 sub _create_token { goto &_create }
587 0     0   0 sub _retrieve_token { goto &_retrieve }
588 0     0   0 sub _bank_token { goto &_create }
589              
590             # Helper methods copied with modification from Net::Stripe
591              
592             sub _get {
593 0     0   0 my ( $self, $path, $args ) = @_;
594 0 0 0     0 $path .= '?' . _encode_params($args) if $args && %$args;
595 0         0 my $req = GET API_BASE . '/' . $path;
596 0         0 return $self->_make_request($req);
597             }
598              
599             # implements PHP convention for encoding "dictionaries" (why don't they accept
600             # json bodies in posts?)
601             sub _encode_params {
602 1     1   4 my $args = shift;
603 1         3 my @components;
604 1         5 for my $key ( keys %$args ) {
605 1         9 my $ek = uri_escape($key);
606 1         57 my $value = $args->{$key};
607 1 0 33     9 if ( blessed $value
      33        
608             && $value->isa('Net::Stripe::Simple::Data')
609             && exists $value->{id} )
610             {
611 0         0 push @components, $ek . '=' . $value->{id};
612 0         0 next;
613             }
614              
615 1         3 my $ref = ref($value);
616 1 50       5 if ($ref eq 'HASH') {
    0          
617 1         5 for my $sk ( keys %$value ) {
618 1         3 my $sv = $value->{$sk};
619             next
620 1 50       5 if ref $sv; # don't think this PHP convention goes deeper
621 1         7 push @components,
622             $ek . '[' . uri_escape($sk) . ']=' . uri_escape($sv);
623             }
624             } elsif ($ref eq 'ARRAY') {
625 0         0 for my $sv (@$value) {
626 0 0       0 next if ref $sv; # again, I think we can't go deeper
627 0         0 push @components, $ek . '[]=' . uri_escape($sv);
628             }
629             } else {
630 0 0       0 $value = # JSON boolean stringification magic has been erased
    0          
631             ref $value eq 'JSON::PP::Boolean'
632             ? $value
633             ? 'true'
634             : 'false'
635             : uri_escape($value);
636 0         0 push @components, "$ek=$value"
637             }
638             }
639 1         31 return join( '&', @components );
640             }
641              
642             sub _delete {
643 0     0   0 my ( $self, $path, $args ) = @_;
644 0 0 0     0 $path .= '?' . _encode_params($args) if $args && %$args;
645 0         0 my $req = DELETE API_BASE . '/' . $path;
646 0         0 return $self->_make_request($req);
647             }
648              
649             sub _post {
650 1     1   2 my ( $self, $path, $obj ) = @_;
651              
652 1 50       11 my $req = POST API_BASE . '/' . $path,
653             ( $obj ? ( Content => _encode_params($obj) ) : () );
654 1         8048 return $self->_make_request($req);
655             }
656              
657             sub _make_request {
658 1     1   2 my ( $self, $req ) = @_;
659 1         1 my ( $e, $resp, $ret );
660 1         2 state $json = do {
661 1         16 my $j = JSON->new;
662 1         8 $j->utf8(1);
663 1         2 $j;
664             };
665 1         1 eval {
666 1         9 $req->header( Authorization => $self->{auth} );
667 1         30 $req->header( Stripe_Version => $self->{version} );
668              
669 1         46 $resp = $self->{ua}->request($req);
670 1 50       1416 if ( $resp->code == 200 ) {
671 0         0 my $hash = $json->decode( $resp->content );
672 0         0 $ret = data_object($hash);
673             }
674             else {
675 1 50       10 if ( $resp->header('Content_Type') =~ m{text/html} ) {
676 0         0 $e = _hash_to_error(
677             code => $resp->code,
678             type => $resp->message,
679             message => $resp->message
680             );
681             }
682             else {
683 1         30 my $hash = $json->decode( $resp->content );
684 0   0     0 $e = _hash_to_error( $hash->{error} // $hash );
685             }
686             }
687             };
688 1 50       49 if ($@) {
689 1 50       13 $e = _hash_to_error(
690             {
691             type => "Could not decode HTTP response: $@",
692             $resp
693             ? ( message => $resp->status_line . " - " . $resp->content )
694             : (),
695             }
696             );
697             }
698 1 50       30 die $e if $e;
699 0 0       0 return $ret if $ret;
700 0         0 die _hash_to_error();
701             }
702              
703             # generates validation error when parameters required to construct the URL
704             # have not been provided
705             sub _invalid {
706 0     0   0 my $message = shift;
707 0         0 my %params = ( type => 'Required parameter missing' );
708 0 0       0 $params{message} = $message if defined $message;
709 0         0 die _hash_to_error(%params);
710             }
711              
712              
713             sub data_object {
714 18     18 1 519 my $ref = shift;
715 18         29 my $rr = ref $ref;
716 18 100       51 return unless $rr;
717 9 50 33     44 die "forbidden class: $rr" if blessed($ref) and $rr !~ /^JSON::/;
718 9 50       48 bless $ref, 'Net::Stripe::Simple::Data' if $rr eq 'HASH';
719              
720 9 50       21 if ($rr eq 'HASH') {
    0          
721 9         126 data_object($_) for values %$ref
722             } elsif ($rr eq 'ARRAY') {
723 0         0 data_object($_) for @$ref
724             }
725              
726 9         17 return $ref;
727             }
728              
729             sub _hash_to_error {
730 5 100   5   816 my %args = ( ref $_[0] ? %{ $_[0] } : @_ );
  2         13  
731 5         14 my $o = data_object( \%args );
732 5         30 my $trace = Devel::StackTrace->new( ignore_package => __PACKAGE__ );
733 5         897 $o->{_trace} = $trace;
734 5         19 bless $o, 'Net::Stripe::Simple::Error';
735             }
736              
737              
738 0     0 1   sub true() { JSON::true }
739 0     0 1   sub false() { JSON::false }
740 0     0 1   sub null() { JSON::null }
741              
742             1;
743              
744             __END__
745              
746             =pod
747              
748             =encoding UTF-8
749              
750             =head1 NAME
751              
752             Net::Stripe::Simple - simple, non-Moose interface to the Stripe API
753              
754             =head1 VERSION
755              
756             version 0.003
757              
758             =head1 SYNOPSIS
759              
760             use Net::Stripe::Simple;
761              
762             my $stripe = Net::Stripe::Simple->new('sk_test_00000000000000000000000000');
763              
764             # when the only argument is an id, that's all you need
765             my $c1 = $stripe->customers( retrieve => 'cus_meFAKEfakeFAKE' );
766              
767             # you can provide arguments as a hash reference
768             my $c2 = $stripe->customers( retrieve => { id => 'cus_ImFAKEfakeFAKE' } );
769              
770             # or as key-value list
771             my $c3 = $stripe->customers( 'retrieve', id => 'cus_I2FAKEfakeFAKE', expand => 1 );
772              
773             =head1 DESCRIPTION
774              
775             A lightweight, limited-dependency client to the stripe.com API. This is just
776             a thin wrapper around stripe's RESTful API. It is "simple" in the sense that it
777             is simple to write and maintain and it maps simply onto Stripe's web
778             documentation, so it is simple to use. When you get a response back, it's just
779             the raw JSON blessed with some convenience methods: stringification to ids and
780             autoloaded attributes (L<Net::Stripe::Simple::Data>). If there is an error, the
781             error that is thrown is again just Stripe's JSON with a little blessing
782             (L<Net::Stripe::Simple::Error>).
783              
784             This simplicity comes at a cost: L<Net::Stripe::Simple> does not
785             validate your parameters aside from those required to construct the URL before
786             constructing a request and sending it off to Stripe. This means that if you've
787             done it wrong it takes a round trip to find out.
788              
789             For the full details of stripe's API, see L<https://stripe.com/docs/api>.
790              
791             =head2 Method Invocation
792              
793             Following the organization scheme of Stripe's API, actions are grouped by entity
794             type, each entity corresponding to a method. For a given method there are
795             generally a number of actions, which are treated as the primary key in a
796             parameter hash. Parameters for these actions are provided by a parameter hash
797             which is the value of the primary key. However, there is some flexibility.
798              
799             Methods that require only an id are flexible. All the following will work:
800              
801             $stripe->plans( retrieve => { id => $id } );
802             $stripe->plans( 'retrieve', id => $id );
803             $stripe->plans( retrieve => $id );
804              
805             Methods that require no arguments are also flexible:
806              
807             $stripe->plans( list => { } );
808             $stripe->plans('list');
809              
810             =head2 Export Tags
811              
812             L<Net::Stripe::Simple> exports nothing by default. It has four exportable
813             constants and one exportable function:
814              
815             =over 4
816              
817             =item true
818              
819             =item false
820              
821             =item null
822              
823             =item data_object
824              
825             =back
826              
827             To facilitate their export, it has two tags:
828              
829             =over 4
830              
831             =item :const
832              
833             The three constants.
834              
835             =item :all
836              
837             The three constants plus C<data_object>.
838              
839             =back
840              
841             =head1 NAME
842              
843             Net::Stripe::Simple - simple, non-Moose interface to the Stripe API
844              
845             =head1 VERSION
846              
847             version 0.002
848              
849             =head1 METHODS
850              
851             =head2 new
852              
853             Net::Stripe::Simple->('sk_test_00000000000000000000000000', '2014-01-31')
854              
855             The class constructor method. The API key is required. The version date is
856             optional. If not supplied, the value of C<$Net::Stripe::Simple::STRIPE_VERSION>
857             will be supplied. L<Net::Stripe::Simple> was implemented or has been updated
858             for the following versions:
859              
860             =over 4
861              
862             =item 2014-01-31
863              
864             =item 2014-06-17
865              
866             =back
867              
868             The default version will always be the most recent version whose handling
869             required an update to L<Net::Stripe::Simple>.
870              
871             =head2 charges
872              
873             See L<https://stripe.com/docs/api#charges>.
874              
875             B<Available Actions>
876              
877             =over 4
878              
879             =item create
880              
881             $charge = $stripe->charges(
882             create => {
883             customer => $customer,
884             amount => 100,
885             currency => 'usd',
886             capture => 'false',
887             }
888             );
889              
890             =item retrieve
891              
892             $charge = $stripe->charges( retrieve => $id );
893              
894             =item update
895              
896             $charge = $stripe->charges(
897             update => {
898             id => $charge,
899             description => 'foo',
900             }
901             );
902              
903             =item refund
904              
905             Availability may depend on version of API.
906             $charge = $stripe->charges( refund => $id );
907              
908             =item capture
909              
910             $charge = $stripe->charges( capture => $id );
911              
912             =item list
913              
914             my $charges = $stripe->charges('list');
915              
916             =back
917              
918             =head2 refunds
919              
920             See L<https://stripe.com/docs/api#refunds>.
921              
922             B<Available Actions>
923              
924             =over 4
925              
926             =item create
927              
928             my $refund = $stripe->refunds(
929             create => {
930             id => $charge,
931             amount => 50
932             }
933             );
934              
935             =item retrieve
936              
937             $refund = $stripe->refunds(
938             retrieve => {
939             id => $refund,
940             charge => $charge
941             }
942             );
943              
944             =item update
945              
946             $refund = $stripe->refunds(
947             update => {
948             id => $refund,
949             charge => $charge,
950             metadata => { foo => 'bar' }
951             }
952             );
953              
954             =item list
955              
956             my $refunds = $stripe->refunds( list => $charge );
957              
958             =back
959              
960             =head2 customers
961              
962             See L<https://stripe.com/docs/api#customers>.
963              
964             B<Available Actions>
965              
966             =over 4
967              
968             =item create
969              
970             $customer = $stripe->customers(
971             create => {
972             metadata => { foo => 'bar' }
973             }
974             );
975              
976             =item retrieve
977              
978             $customer = $stripe->customers( retrieve => $id );
979              
980             =item update
981              
982             $customer = $stripe->customers(
983             update => {
984             id => $customer,
985             metadata => { foo => 'baz' }
986             }
987             );
988              
989             =item delete
990              
991             $customer = $stripe->customers( delete => $id );
992              
993             =item list
994              
995             my $customers = $stripe->customers(
996             list => {
997             created => { gte => $time - 100 }
998             }
999             );
1000              
1001             =back
1002              
1003             =head2 cards
1004              
1005             See L<https://stripe.com/docs/api#cards>.
1006              
1007             B<Available Actions>
1008              
1009             =over 4
1010              
1011             =item create
1012              
1013             $card = $stripe->cards(
1014             create => {
1015             customer => $customer,
1016             card => {
1017             number => '4242424242424242',
1018             exp_month => $expiry->month,
1019             exp_year => $expiry->year,
1020             cvc => 123
1021             }
1022             }
1023             );
1024              
1025             =item retrieve
1026              
1027             $card = $stripe->cards(
1028             retrieve => {
1029             customer => $customer,
1030             id => $id
1031             }
1032             );
1033              
1034             =item update
1035              
1036             $card = $stripe->cards(
1037             update => {
1038             customer => $customer,
1039             id => $card,
1040             name => 'foo',
1041             }
1042             );
1043              
1044             =item delete
1045              
1046             $card = $stripe->cards(
1047             delete => {
1048             customer => $customer,
1049             id => $id
1050             }
1051             );
1052              
1053             =item list
1054              
1055             my $cards = $stripe->cards( list => $customer );
1056              
1057             =back
1058              
1059             =head2 subscriptions
1060              
1061             See L<https://stripe.com/docs/api#subscriptions>.
1062              
1063             B<Available Actions>
1064              
1065             =over 4
1066              
1067             =item create
1068              
1069             $subscription = $stripe->subscriptions(
1070             create => {
1071             customer => $customer,
1072             plan => $plan,
1073             }
1074             );
1075              
1076             =item retrieve
1077              
1078             $subscription = $stripe->subscriptions(
1079             retrieve => {
1080             id => $id,
1081             customer => $customer,
1082             }
1083             );
1084              
1085             =item update
1086              
1087             $subscription = $stripe->subscriptions(
1088             update => {
1089             id => $id,
1090             customer => $customer,
1091             metadata => { foo => 'bar' }
1092             }
1093             );
1094              
1095             =item cancel
1096              
1097             $subscription = $stripe->subscriptions(
1098             cancel => {
1099             id => $id,
1100             customer => $customer,
1101             }
1102             );
1103              
1104             =item list
1105              
1106             my $subscriptions = $stripe->subscriptions( list => $customer );
1107              
1108             =back
1109              
1110             =head2 plans
1111              
1112             See L<https://stripe.com/docs/api#plans>.
1113              
1114             B<Available Actions>
1115              
1116             =over 4
1117              
1118             =item create
1119              
1120             $plan = $stripe->plans(
1121             create => {
1122             id => $id,
1123             amount => 100,
1124             currency => 'usd',
1125             interval => 'week',
1126             name => 'Foo',
1127             }
1128             );
1129              
1130             =item retrieve
1131              
1132             $plan = $stripe->plans( retrieve => $id );
1133              
1134             =item update
1135              
1136             $plan = $stripe->plans(
1137             update => {
1138             id => $id,
1139             metadata => { bar => 'baz' }
1140             }
1141             );
1142              
1143             =item delete
1144              
1145             $plan = $stripe->plans( delete => $id );
1146              
1147             =item list
1148              
1149             my $plans = $stripe->plans('list');
1150              
1151             =back
1152              
1153             =head2 coupons
1154              
1155             B<Available Actions>
1156              
1157             See L<https://stripe.com/docs/api#coupons>.
1158              
1159             =over 4
1160              
1161             =item create
1162              
1163             $coupon = $stripe->coupons(
1164             create => {
1165             percent_off => 1,
1166             duration => 'forever',
1167             }
1168             );
1169              
1170             =item retrieve
1171              
1172             $coupon = $stripe->coupons( retrieve => $id );
1173              
1174             =item delete
1175              
1176             $coupon = $stripe->coupons( delete => $coupon );
1177              
1178             =item list
1179              
1180             my $coupons = $stripe->coupons('list');
1181              
1182             =back
1183              
1184             =head2 discounts
1185              
1186             See L<https://stripe.com/docs/api#discounts>.
1187              
1188             B<Available Actions>
1189              
1190             =over 4
1191              
1192             =item customer
1193              
1194             my $deleted = $stripe->discounts( customer => $c );
1195              
1196             =item subscription
1197              
1198             $deleted = $stripe->discounts(
1199             subscription => {
1200             customer => $c,
1201             subscription => $s,
1202             }
1203             );
1204              
1205             =back
1206              
1207             =head2 invoices
1208              
1209             See L<https://stripe.com/docs/api#invoices>.
1210              
1211             B<Available Actions>
1212              
1213             =over 4
1214              
1215             =item create
1216              
1217             my $new_invoice = $stripe->invoices(
1218             create => {
1219             customer => $customer,
1220             }
1221             );
1222              
1223             =item retrieve
1224              
1225             $invoice = $stripe->invoices( retrieve => $id );
1226              
1227             =item lines
1228              
1229             my $lines = $stripe->invoices( lines => $invoice );
1230              
1231             =item update
1232              
1233             $stripe->subscriptions(
1234             update => {
1235             customer => $customer,
1236             id => $subscription,
1237             plan => $spare_plan,
1238             }
1239             );
1240              
1241             =item pay
1242              
1243             $new_invoice = $stripe->invoices( pay => $new_invoice );
1244              
1245             =item list
1246              
1247             my $invoices = $stripe->invoices( list => { customer => $customer } );
1248              
1249             =item upcoming
1250              
1251             $new_invoice = $stripe->invoices( upcoming => $customer );
1252              
1253             =back
1254              
1255             =head2 invoice_items
1256              
1257             See L<https://stripe.com/docs/api#invoiceitems>.
1258              
1259             B<Available Actions>
1260              
1261             =over 4
1262              
1263             =item create
1264              
1265             my $item = $stripe->invoice_items(
1266             create => {
1267             customer => $customer,
1268             amount => 100,
1269             currency => 'usd',
1270             metadata => { foo => 'bar' }
1271             }
1272             );
1273              
1274             =item retrieve
1275              
1276             $item = $stripe->invoice_items( retrieve => $id );
1277              
1278             =item update
1279              
1280             $item = $stripe->invoice_items(
1281             update => {
1282             id => $item,
1283             metadata => { foo => 'baz' }
1284             }
1285             );
1286              
1287             =item delete
1288              
1289             $item = $stripe->invoice_items( delete => $item );
1290              
1291             =item list
1292              
1293             my $items = $stripe->invoice_items( list => { customer => $customer } );
1294              
1295             =back
1296              
1297             =head2 disputes
1298              
1299             See L<https://stripe.com/docs/api#disputes>.
1300              
1301             B<Available Actions>
1302              
1303             =over 4
1304              
1305             =item update
1306              
1307             $stripe->disputes(
1308             update => {
1309             id => $charge,
1310             metadata => { foo => 'bar' }
1311             }
1312             );
1313              
1314             =item close
1315              
1316             $stripe->disputes( close => $charge );
1317              
1318             =back
1319              
1320             =head2 transfers
1321              
1322             See L<https://stripe.com/docs/api#transfers>.
1323              
1324             B<Available Actions>
1325              
1326             =over 4
1327              
1328             =item create
1329              
1330             my $transfer = $stripe->transfers(
1331             create => {
1332             amount => 1,
1333             currency => 'usd',
1334             recipient => $recipient,
1335             }
1336             );
1337              
1338             =item retrieve
1339              
1340             $transfer = $stripe->transfers( retrieve => $id );
1341              
1342             =item update
1343              
1344             $transfer = $stripe->transfers(
1345             update => {
1346             id => $transfer,
1347             metadata => { foo => 'bar' }
1348             }
1349             );
1350              
1351             =item cancel
1352              
1353             $transfer = $stripe->transfers( cancel => $transfer );
1354              
1355             =item list
1356              
1357             my $transfers = $stripe->transfers(
1358             list => {
1359             created => { gt => $time }
1360             }
1361             );
1362              
1363             =back
1364              
1365             =head2 recipients
1366              
1367             See L<https://stripe.com/docs/api#recipients>.
1368              
1369             B<Available Actions>
1370              
1371             =over 4
1372              
1373             =item create
1374              
1375             $recipient = $stripe->recipients(
1376             create => {
1377             name => 'I Am An Example',
1378             type => 'individual',
1379             }
1380             );
1381              
1382             =item retrieve
1383              
1384             $recipient = $stripe->recipients( retrieve => $id );
1385              
1386             =item update
1387              
1388             $recipient = $stripe->recipients(
1389             update => {
1390             id => $recipient,
1391             metadata => { foo => 'bar' },
1392             }
1393             );
1394              
1395             =item delete
1396              
1397             $recipient = $stripe->recipients( delete => $id );
1398              
1399             =item list
1400              
1401             my $recipients = $stripe->recipients('list');
1402              
1403             =back
1404              
1405             =head2 application_fees
1406              
1407             See L<https://stripe.com/docs/api#application_fees>.
1408              
1409             B<Available Actions>
1410              
1411             =over 4
1412              
1413             =item retrieve
1414              
1415             my $fee = $stripe->application_fees( retrieve => $id );
1416              
1417             =item refund
1418              
1419             my $fee = $stripe->application_fees( refund => $id );
1420              
1421             =item list
1422              
1423             my $fees = $stripe->application_fees('list');
1424              
1425             =back
1426              
1427             =head2 account
1428              
1429             See L<https://stripe.com/docs/api#account>.
1430              
1431             B<Available Actions>
1432              
1433             =over 4
1434              
1435             =item retrieve
1436              
1437             my $account = $stripe->account('retrieve'); # or
1438             $account = $stripe->account;
1439              
1440             =back
1441              
1442             =head2 balance
1443              
1444             See L<https://stripe.com/docs/api#balance>.
1445              
1446             B<Available Actions>
1447              
1448             =over 4
1449              
1450             =item retrieve
1451              
1452             my $balance = $stripe->balance('retrieve');
1453              
1454             =item history
1455              
1456             my $history = $stripe->balance('history');
1457              
1458             =item transaction
1459              
1460             $balance = $stripe->balance( transaction => $charge );
1461              
1462             =back
1463              
1464             =head2 events
1465              
1466             See L<https://stripe.com/docs/api#events>.
1467              
1468             B<Available Actions>
1469              
1470             =over 4
1471              
1472             =item retrieve
1473              
1474             $event = $stripe->events( retrieve => $id );
1475              
1476             =item list
1477              
1478             my $events = $stripe->events( list => { created => { gt => $time } } );
1479              
1480             =back
1481              
1482             =head2 tokens
1483              
1484             See L<https://stripe.com/docs/api#tokens>.
1485              
1486             B<Available Actions>
1487              
1488             =over 4
1489              
1490             =item create
1491              
1492             $token = $stripe->tokens(
1493             create => {
1494             card => {
1495             number => '4242424242424242',
1496             exp_month => $expiry->month,
1497             exp_year => $expiry->year,
1498             cvc => 123
1499             }
1500             }
1501             );
1502             $token = $stripe->tokens(
1503             create => {
1504             bank_account => {
1505             country => 'US',
1506             routing_number => '110000000',
1507             account_number => '000123456789',
1508             }
1509             }
1510             );
1511              
1512             =item retrieve
1513              
1514             $token = $stripe->tokens( retrieve => $id );
1515              
1516             =item bank
1517              
1518             To preserve the parallel with the Stripe's API documentation, there is a
1519             special "bank" action, but it is simply a synonym for the code above.
1520             $token = $stripe->tokens(
1521             bank => {
1522             bank_account => {
1523             country => 'US',
1524             routing_number => '110000000',
1525             account_number => '000123456789',
1526             }
1527             }
1528             );
1529              
1530             =back
1531              
1532             =head1 FUNCTIONS
1533              
1534             =head2 data_object($hash_ref)
1535              
1536             This function recursively converts a hash ref into a data object. This is just
1537             L<Net::Stripe::Simple::Data>, whose only function is to autoload accessors for
1538             all the keys in the hash. It is made for adding magic to JSON objects. If you
1539             try to give it something that contains blessed references whose class is
1540             outside the JSON namespace it will die.
1541              
1542             =head1 SEE ALSO
1543              
1544             L<Net::Stripe>, L<Business::Stripe>
1545              
1546             =head1 EXPORTED CONSTANTS
1547              
1548             These are just the corresponding L<JSON> constants. They are exported by
1549             L<Net::Stripe::Simple> for convenience.
1550              
1551             use Net::Stripe::Simple qw(:const);
1552             ...
1553             my $subscription = $stripe->subscriptions(
1554             update => {
1555             id => $id,
1556             customer => $customer_id,
1557             plan => $plan_id,
1558             prorate => true,
1559             }
1560             );
1561              
1562             You can import the constants individually or all together with C<:const>.
1563              
1564             =over 4
1565              
1566             =item true
1567              
1568             =item false
1569              
1570             =item null
1571              
1572             =back
1573              
1574             =head1 AUTHORS
1575              
1576             =over 4
1577              
1578             =item *
1579              
1580             Grant Street Group <developers@grantstreet.com>
1581              
1582             =item *
1583              
1584             David F. Houghton <dfhoughton@gmail.com>
1585              
1586             =back
1587              
1588             =head1 COPYRIGHT AND LICENSE
1589              
1590             This software is copyright (c) 2014 by Grant Street Group.
1591              
1592             This is free software; you can redistribute it and/or modify it under
1593             the same terms as the Perl 5 programming language system itself.
1594              
1595             =head1 AUTHORS
1596              
1597             =over 4
1598              
1599             =item *
1600              
1601             Grant Street Group <developers@grantstreet.com>
1602              
1603             =item *
1604              
1605             David F. Houghton <dfhoughton@gmail.com>
1606              
1607             =back
1608              
1609             =head1 COPYRIGHT AND LICENSE
1610              
1611             This software is copyright (c) 2014 by Grant Street Group.
1612              
1613             This is free software; you can redistribute it and/or modify it under
1614             the same terms as the Perl 5 programming language system itself.
1615              
1616             =cut