File Coverage

blib/lib/Business/PayPal/SDK.pm
Criterion Covered Total %
statement 12 481 2.4
branch 0 164 0.0
condition 0 15 0.0
subroutine 4 23 17.3
pod 8 11 72.7
total 24 694 3.4


line stmt bran cond sub pod time code
1             package Business::PayPal::SDK;
2              
3             #$Id: SDK.pm,v 1.7 2005/12/08 18:18:31 jacob Exp $
4             #
5             =head1 NAME
6              
7             Business::PayPal::SDK - An interface to paypals SDK's.
8              
9             =head1 SYNOPSIS
10              
11             use Business::PayPal::SDK;
12             my $pp = new Business::PayPal::SDK(
13             {
14             paypal_apiid => "sdk-seller_api1.sdk.com",
15             paypal_apipw => "12345678",
16             paypal_cert => "paypal_java_sdk/samples/Cert/sdk-seller.p12",
17             paypal_certpw => "password",
18             paypal_env => "sandbox",
19             java_sdk_dir => "/path/to/paypals/java/sdk",
20             }
21             );
22              
23             my $res = $pp->SetExpressCheckout(
24             {
25             OrderTotal => '10.00',
26             ReturnURL => 'http:://mydomain.com/myreturn',
27             CancelURL => 'http:://mydomain.com/mycancel',
28             }
29             );
30              
31             print $res->{token};
32              
33             =head1 DESCRIPTION
34              
35             Business::PayPal::SDK is a perl interface to the SDK provided by paypal (http://www.paypal.com/sdk). You can use this module to implement paypal pro and paypal express transactions in perl. On the back end this modules uses Inline::Java to interface directly with the paypals java sdk. Consequently you will need to get a J2SDK and Inline::Java installed. This was done for 2 reasons. 1) Speed of development, didnt have to deal with all the SOAP stuff. 2) Easier maintanance regarding future changes. That is to say, I only have to make sure I keep this compatiable with paypals SDK, not thier underlying protocol changes.
36              
37             This document assumes you have an understanding of the java SDK and API provided by PayPal.
38              
39             All methods take a single hashref as an argument.
40             All methods return a hashref, or undef if there is an internal failure of some sort. Check $ret->{ack} to see if the call to PayPal was successful. If $ret->{ack} is not 'Success' than you can check the $res->{ErrorCodes}, this will be an hashref with the key being the error code from paypal and the value is the 'getLongMessage' from the error. Check $obj->error for description of failure.
41              
42             =cut
43              
44 1     1   20633 use strict;
  1         2  
  1         37  
45 1     1   4 use warnings;
  1         2  
  1         29  
46              
47 1     1   4 use base qw/Class::Accessor/;
  1         5  
  1         885  
48             my @REQUIRED = qw/
49             paypal_apiid
50             paypal_apipw
51             paypal_cert
52             paypal_certpw
53             paypal_env
54             java_sdk_dir
55             /;
56             my @OTHER = qw/
57             jni
58             shared_jvm
59             paypal
60             /;
61 1     1   2823 use Data::Dumper;
  1         9730  
  1         5756  
62              
63             __PACKAGE__->mk_accessors (@REQUIRED, @OTHER);
64              
65             our $ERROR = '';
66             our $VERSION = '0.14';
67             our $PPCONINFO = undef;
68              
69             =head1 Public Methods
70              
71             =head2 new()
72              
73             All args are pass in as a hash ref.
74             All the other functions require paypal_apiid, paypal_apipw, payapl_cert, paypal_certpw, paypal_env and java_sdk_dir to be defined. You can pass them all in the new call, or you can use there accessors. $obj->paypal_apiid.
75              
76             Additionally, you can use pass jni => 1, or shared_jvm => 1 to have these values passed to Inline::Java. See Inline::Javas docs for more details on JNI and SHARED_JVM.
77              
78             =cut
79              
80             sub new {
81 0     0 1   my $pkg = shift;
82 0           my $args = shift;
83              
84 0           my $self = {
85             };
86              
87 0           my $s = SUPER::new $pkg $self;
88              
89 0           foreach my $ac (@REQUIRED, @OTHER) {
90 0 0         $s->$ac($args->{$ac}) if ($args->{$ac});
91             }
92              
93 0 0         unless ($s->java_sdk_dir) {
94 0           $s->error("WARNING: java_sdk_dir must be set.");
95 0           return undef;
96             }
97 0           return $s;
98             }
99              
100             =head2 init_java()
101              
102             This will 'require' Inline::Java and get the jvm fired up.
103              
104             Does not take any arguments. However, if you want to use the authentication information and cert that is used in the paypal API docs you can set the $Business::PayPal::SDK::PPCONINFO variable to true and it will use those instead of whatever you may have set.
105              
106             =cut
107             sub init_java {
108 0     0 1   my $s = shift;
109              
110 0           my @study = qw(
111             java.util.HashMap
112             com.paypal.sdk.profiles.APIProfile
113             com.paypal.sdk.profiles.ProfileFactory
114             com.paypal.sdk.services.CallerServices
115             com.paypal.sdk.exceptions.PayPalException
116             com.paypal.soap.api.AckCodeType
117             com.paypal.soap.api.ErrorType
118             org.apache.axis.types.Token
119             com.paypal.soap.api.CurrencyCodeType
120             );
121              
122 0           $ENV{CLASSPATH} = $s->get_classpath;
123              
124             ## Terrible hack to make Inline work in a module
125             package main;
126 0           require Inline;
127 0           import Inline (
128             Java => 'STUDY',
129             STUDY => [],
130             CLASSPATH => $ENV{CLASSPATH},
131             JNI => $s->jni,
132             SHARED_JVM => $s->shared_jvm,
133             DIRECTORY => "/tmp",
134             );
135 0           Inline::Java::study_classes(\@study);
136             package Business::PayPal::SDK;
137              
138 0           foreach my $ac (@REQUIRED) {
139 0 0 0       if (!$s->$ac and !$PPCONINFO) {
140 0           $s->error("$ac not set.");
141             }
142 0 0         return undef if $s->error;
143             }
144 0           my $prof = Inline::Java::cast('com.paypal.sdk.profiles.APIProfile', com::paypal::sdk::profiles::ProfileFactory->createAPIProfile());
145              
146             ## Test values from sdk
147 0 0         if ($PPCONINFO) {
148 0           $prof->setAPIUsername("sdk-seller_api1.sdk.com");
149 0           $prof->setAPIPassword("12345678");
150 0           $prof->setCertificateFile($s->java_sdk_dir . "/samples/Cert/sdk-seller.p12");
151 0           $prof->setPrivateKeyPassword("password");
152 0           $prof->setEnvironment("sandbox");
153             } else {
154 0           $prof->setAPIUsername($s->paypal_apiid);
155 0           $prof->setAPIPassword($s->paypal_apipw);
156 0           $prof->setCertificateFile($s->paypal_cert);
157 0           $prof->setPrivateKeyPassword($s->paypal_certpw);
158 0           $prof->setEnvironment($s->paypal_env);
159             }
160              
161 0           my $caller = com::paypal::sdk::services::CallerServices->new();
162              
163 0           eval {
164 0           $caller->setAPIProfile($prof);
165             };
166              
167 0 0         if ($@) {
168 0 0         if (ref $@) {
169 0           $s->error("setAPIProfile failed: [" . $@->getMessage() . '] [' . $@ . ']');
170             } else {
171 0           $s->error("setAPIProfile failed: [$@]");
172             }
173 0           return undef;
174             }
175              
176 0           $s->paypal($caller);
177 0           return 1;
178             }
179              
180             =head2 DoDirectPayment()
181              
182             DoDirectPayment charges a card. Returns a hasref very similar in structure to the object returned by the java jdk
183              
184             =cut
185             sub DoDirectPayment {
186 0     0 1   my $s = shift;
187 0           my $args = shift;
188              
189 0 0         unless ($s->paypal) {
190 0 0         unless ($s->init_java) {
191 0           $s->error("could not init_java.");
192 0           return undef;
193             }
194             }
195              
196 0           my $reqs = [
197             qw/
198             OrderTotal
199             FirstName
200             LastName
201             CreditCardNumber
202             ExpMonth
203             ExpYear
204             Street1
205             CityName
206             IPAddress
207             /
208             ];
209              
210 0 0         return undef unless ($s->_checkRequires($reqs, $args));
211              
212             package main;
213 0           Inline::Java::study_classes(
214             [
215             qw(
216             com.paypal.soap.api.DoDirectPaymentRequestDetailsType
217             com.paypal.soap.api.DoDirectPaymentRequestType
218             com.paypal.soap.api.DoDirectPaymentResponseType
219             com.paypal.soap.api.PaymentActionCodeType
220             com.paypal.soap.api.PaymentDetailsType
221             com.paypal.soap.api.PaymentCodeType
222             com.paypal.soap.api.BasicAmountType
223             com.paypal.soap.api.PayerInfoType
224             )
225             ]
226             );
227             package Business::PayPal::SDK;
228              
229 0           my $resp;
230 0           eval {
231 0           my $requestDetails = com::paypal::soap::api::DoDirectPaymentRequestDetailsType->new();
232 0           $requestDetails->setPaymentAction($com::paypal::soap::api::PaymentActionCodeType::Sale);
233            
234 0           my $paymentDetails = com::paypal::soap::api::PaymentDetailsType->new();
235 0           my $totalAmount = com::paypal::soap::api::BasicAmountType->new();
236 0           $totalAmount->set_value($args->{OrderTotal});
237 0           $totalAmount->setCurrencyID($com::paypal::soap::api::CurrencyCodeType::USD);
238            
239 0           $paymentDetails->setOrderTotal($totalAmount);
240            
241 0           my $creditCard = $s->_getCreditCard($args);
242 0           my $payerName = $s->_getPersonName($args);
243            
244 0           my $payerInfo = com::paypal::soap::api::PayerInfoType->new();
245 0           $payerInfo->setPayerName($payerName);
246            
247 0           my $payerAddress = $s->_getAddress($args);
248 0           $payerInfo->setAddress($payerAddress);
249 0           $creditCard->setCardOwner($payerInfo);
250            
251 0           $requestDetails->setCreditCard($creditCard);
252 0           $requestDetails->setPaymentDetails($paymentDetails);
253 0           $requestDetails->setIPAddress($args->{IPAddress});
254            
255 0           my $paymentRequest = com::paypal::soap::api::DoDirectPaymentRequestType->new();
256 0           $paymentRequest->setDoDirectPaymentRequestDetails($requestDetails);
257            
258 0           $resp = $s->paypal->call("DoDirectPayment", $paymentRequest);
259             };
260            
261 0           my $ret = {};
262 0 0         if ($@) {
263 0 0         if (Inline::Java::caught('java.lang.Exception')) {
264 0 0         if (ref $@) {
265 0           $s->error("DoDirectPayment failed: [" . $@->getMessage() . '] [' . $@ . ']');
266             } else {
267 0           $s->error("DoDirectPayment failed: [" . $@ . ']');
268             }
269 0           return undef;
270             } else {
271 0           $s->error($@);
272 0           return undef;
273             }
274             }
275              
276 0           my $ack = $resp->getAck();
277 0           $ret->{ack} = $ack->toString;
278              
279 0 0         if ($ret->{ack} eq 'Success') {
280 0           my $Amount = $resp->getAmount;
281 0           $ret->{Amount}->{value} = $Amount->get_value;
282 0           $ret->{Amount}->{Currency} = $Amount->getCurrencyID->toString;
283 0           $ret->{TransactionID} = $resp->getTransactionID;
284 0           $ret->{AVSCode} = $resp->getAVSCode;
285 0           $ret->{CVV2Code} = $resp->getCVV2Code;
286 0           $ret->{ErrorCodes} = $s->_getErrorHash($resp->getErrors);
287             } else {
288 0           $ret->{ErrorCodes} = $s->_getErrorHash($resp->getErrors);
289             }
290              
291 0           return $ret;
292             }
293              
294             sub _getCreditCard {
295 0     0     my $s = shift;
296 0           my $args = shift;
297              
298 0           my $reqs = [
299             qw/
300             CreditCardNumber
301             ExpMonth
302             ExpYear
303             CardType
304             /
305             ];
306              
307 0 0         return undef unless $s->_checkRequires($reqs, $args);
308              
309 0   0       $args->{CVV2} ||= 000;
310             package main;
311 0           require Inline::Java;
312 0           Inline::Java::study_classes(
313             [
314             qw(
315             com.paypal.soap.api.CreditCardDetailsType
316             )
317             ]
318             );
319             package Business::PayPal::SDK;
320              
321 0           my $creditCard;
322 0           eval {
323 0           $creditCard = com::paypal::soap::api::CreditCardDetailsType->new();
324 0           $creditCard->setCreditCardNumber($args->{CreditCardNumber});
325 0           $creditCard->setExpMonth($args->{ExpMonth});
326 0           $creditCard->setExpYear($args->{ExpYear});
327 0           $creditCard->setCVV2($args->{CVV2});
328 0           $creditCard->setCreditCardType($s->_getCardType($args->{CardType}));
329             };
330              
331 0 0         if ($@) {
332 0           $s->error("getCreditCard failed: " . $@->getMessage());
333 0           return undef;
334             } else {
335 0           return $creditCard;
336             }
337             }
338              
339             sub _getPersonName {
340 0     0     my $s = shift;
341 0           my $args = shift;
342              
343 0           my $reqs = [
344             qw/
345             FirstName
346             LastName
347             /
348             ];
349              
350 0 0         return undef unless ($s->_checkRequires($reqs, $args));
351              
352              
353             package main;
354 0           require Inline::Java;
355 0           Inline::Java::study_classes(
356             [
357             qw(
358             com.paypal.soap.api.PersonNameType
359             )
360             ]
361             );
362             package Business::PayPal::SDK;
363              
364 0           my $payerName;
365 0           eval {
366 0           $payerName = com::paypal::soap::api::PersonNameType->new();
367 0           $payerName->setFirstName($args->{FirstName});
368 0           $payerName->setLastName($args->{LastName});
369 0 0         $payerName->setMiddleName($args->{MiddleName}) if $args->{MiddleName};
370 0 0         $payerName->setSalutation($args->{Salutation}) if $args->{Salutation};
371 0 0         $payerName->setSuffix($args->{Suffix}) if $args->{Suffix};
372             };
373              
374 0 0         if ($@) {
375 0           $s->error("getPersonName failed: [" . $@->getMessage() . ']' . ' [' . $@->toString() . ']');
376 0           return undef;
377             } else {
378 0           return $payerName;
379             }
380             }
381              
382             sub _getCardType {
383 0     0     my $s = shift;
384 0           my $type = shift;
385              
386 0 0         unless ($type) {
387 0           $s->error("You must pass a card type to _getCardType");
388 0           return undef;
389             }
390              
391             package main;
392 0           require Inline::Java;
393 0           Inline::Java::study_classes(
394             [
395             qw(
396             com.paypal.soap.api.CreditCardTypeType
397             )
398             ]
399             );
400             package Business::PayPal::SDK;
401              
402 0           my $ccType;
403 0           eval {
404 0           $ccType = com::paypal::soap::api::CreditCardTypeType->fromString($type);
405             };
406              
407 0 0         if ($@) {
408 0           $s->error("getCreditCardType failes: [" . $@->getMessage() . "] [" . $@->toString() . ']');
409 0           return undef;
410             } else {
411 0           return $ccType;
412             }
413             }
414              
415             =head2 DoExpressCheckoutPayment()
416              
417             DoExpressCheckoutPayment after getting a token
418              
419             =cut
420             sub DoExpressCheckoutPayment {
421 0     0 1   my $s = shift;
422 0           my $args = shift;
423              
424 0 0         unless ($s->paypal) {
425 0 0         unless ($s->init_java) {
426 0           $s->error("could not init_java.");
427 0           return undef;
428             }
429             }
430              
431 0           my $reqs = [
432             qw/
433             token
434             PayerID
435             OrderTotal
436             /
437             ];
438              
439 0 0         return undef unless ($s->_checkRequires($reqs, $args));
440              
441             package main;
442 0           Inline::Java::study_classes(
443             [
444             qw(
445             com.paypal.soap.api.BasicAmountType
446             com.paypal.soap.api.DoExpressCheckoutPaymentRequestDetailsType
447             com.paypal.soap.api.DoExpressCheckoutPaymentRequestType
448             com.paypal.soap.api.DoExpressCheckoutPaymentResponseDetailsType
449             com.paypal.soap.api.DoExpressCheckoutPaymentResponseType
450             com.paypal.soap.api.PaymentActionCodeType
451             com.paypal.soap.api.PaymentCodeType
452             com.paypal.soap.api.PaymentDetailsType
453             com.paypal.soap.api.PaymentInfoType
454             com.paypal.soap.api.PaymentStatusCodeType
455             com.paypal.soap.api.PaymentTransactionCodeType
456             java.util.Calendar
457             )
458             ]
459             );
460             package Business::PayPal::SDK;
461              
462 0           my $resp;
463             my $responseDetails;
464 0           eval {
465 0           my $request = com::paypal::soap::api::DoExpressCheckoutPaymentRequestType->new();
466 0           my $requestDetails = com::paypal::soap::api::DoExpressCheckoutPaymentRequestDetailsType->new();
467 0           $requestDetails->setToken($args->{token});
468 0           $requestDetails->setPayerID($args->{PayerID});
469 0           $requestDetails->setPaymentAction($com::paypal::soap::api::PaymentActionCodeType::Sale);
470            
471 0           my $paymentDetails = com::paypal::soap::api::PaymentDetailsType->new();
472 0           my $orderTotal = com::paypal::soap::api::BasicAmountType->new();
473              
474 0           $orderTotal->set_value($args->{OrderTotal});
475 0           $orderTotal->setCurrencyID($com::paypal::soap::api::CurrencyCodeType::USD);
476              
477 0           $paymentDetails->setOrderTotal($orderTotal);
478              
479 0           $requestDetails->setPaymentDetails($paymentDetails);
480              
481 0           $request->setDoExpressCheckoutPaymentRequestDetails($requestDetails);
482              
483 0           $resp = $s->paypal->call('DoExpressCheckoutPayment', $request);
484              
485 0           $responseDetails = $resp->getDoExpressCheckoutPaymentResponseDetails();
486             };
487              
488 0 0         if ($@) {
489 0 0         if (Inline::Java::caught('java.lang.Exception')) {
490 0 0         if (ref $@) {
491 0           $s->error("DoExpressCheckoutPayment failed: [" . $@->getMessage() . '] [' . $@ . ']');
492             } else {
493 0           $s->error("DoExpressCheckoutPayment failed: [" . $@ . ']');
494             }
495 0           return undef;
496             } else {
497 0           $s->error($@);
498 0           return undef;
499             }
500             }
501              
502 0           my $ret= {};
503              
504 0           my $ack = $resp->getAck();
505 0           $ret->{ack} = $ack->toString;
506              
507 0           $ret->{Token} = $responseDetails->getToken;
508              
509 0           my $paymentInfo = $responseDetails->getPaymentInfo();
510              
511            
512 0 0         if ($ret->{ack} eq 'Success') {
513 0           my $feeAmount = $paymentInfo->getFeeAmount();
514            
515 0           my $settleAmount = $paymentInfo->getSettleAmount();
516            
517 0           my $taxAmount = $paymentInfo->getTaxAmount();
518            
519 0           my $grossAmount = $paymentInfo->getGrossAmount();
520            
521 0           my $paymentStatus = $paymentInfo->getPaymentStatus();
522            
523 0           my $paymentType = $paymentInfo->getPaymentType();
524            
525 0           my $transactionType = $paymentInfo->getTransactionType();
526            
527 0           my $paymentDate = Inline::Java::cast('java.util.Calendar', $paymentInfo->getPaymentDate());
528              
529 0           $ret->{PaymentInfo} = {};
530            
531 0           $ret->{PaymentInfo}->{PaymentStatus} = $paymentStatus->toString;
532 0           $ret->{PaymentInfo}->{PaymentType} = $paymentType->toString;
533 0           $ret->{PaymentInfo}->{ExchangeRate} = $paymentInfo->getExchangeRate();
534 0           $ret->{PaymentInfo}->{ParentTransactionID} = $paymentInfo->getParentTransactionID();
535 0           $ret->{PaymentInfo}->{TransactionID} = $paymentInfo->getTransactionID();
536 0           $ret->{PaymentInfo}->{TransactionType} = $transactionType->toString();
537 0           $ret->{PaymentInfo}->{ReceiptID} = $paymentInfo->getReceiptID();
538            
539 0           $ret->{PaymentInfo}->{PaymentDate} = $s->_getDateString($paymentDate);
540            
541 0           $ret->{PaymentInfo}->{GrossAmount} = {};
542 0 0         if ($grossAmount) {
543 0           $ret->{PaymentInfo}->{GrossAmount}->{value} = $grossAmount->get_value;
544 0           $ret->{PaymentInfo}->{GrossAmount}->{CurrencyCode} = "USD";
545             }
546            
547 0           $ret->{PaymentInfo}->{FeeAmount} = {};
548 0 0         if ($feeAmount) {
549 0           $ret->{PaymentInfo}->{FeeAmount}->{value} = $feeAmount->get_value;
550 0           $ret->{PaymentInfo}->{FeeAmount}->{CurrencyCode} = "USD";
551             }
552            
553 0           $ret->{PaymentInfo}->{SettleAmount} = {};
554 0 0         if ($settleAmount) {
555 0           $ret->{PaymentInfo}->{SettleAmount}->{value} = $settleAmount->get_value;
556 0           $ret->{PaymentInfo}->{SettleAmount}->{CurrencyCode} = "USD";
557             }
558            
559 0           $ret->{PaymentInfo}->{TaxAmount} = {};
560 0 0         if ($taxAmount) {
561 0           $ret->{PaymentInfo}->{TaxAmount}->{value} = $taxAmount->get_value;
562 0           $ret->{PaymentInfo}->{TaxAmount}->{CurrencyCode} = "USD";
563             }
564             } else {
565 0           $ret->{ErrorCodes} = $s->_getErrorHash($resp->getErrors);
566             }
567              
568 0           return $ret;
569             }
570              
571             =head2 GetExpressCheckoutDetails()
572              
573             GetExpressCheckoutDetails to get customer details.
574              
575             =cut
576             sub GetExpressCheckoutDetails {
577 0     0 1   my $s = shift;
578 0           my $args = shift;
579              
580 0 0         unless ($s->paypal) {
581 0 0         unless ($s->init_java) {
582 0           $s->error("could not init_java.");
583 0           return undef;
584             }
585             }
586              
587 0           my $reqs = [
588             qw/
589             token
590             /
591             ];
592              
593 0 0         return undef unless ($s->_checkRequires($reqs, $args));
594              
595             package main;
596 0           Inline::Java::study_classes(
597             [
598             qw(
599             com.paypal.soap.api.GetExpressCheckoutDetailsRequestType
600             com.paypal.soap.api.GetExpressCheckoutDetailsResponseType
601             com.paypal.soap.api.GetExpressCheckoutDetailsResponseDetailsType
602             com.paypal.soap.api.PersonNameType
603             com.paypal.soap.api.PayerInfoType
604             com.paypal.soap.api.AddressType
605             com.paypal.soap.api.CountryCodeType
606             com.paypal.soap.api.PayPalUserStatusCodeType
607             )
608             ]
609             );
610             package Business::PayPal::SDK;
611              
612 0           my $resp;
613             my $respDetails;
614 0           my $payerInfo;
615 0           eval {
616 0           my $request = com::paypal::soap::api::GetExpressCheckoutDetailsRequestType->new();
617 0           $request->setToken($args->{token});
618              
619 0           $resp = $s->paypal->call("GetExpressCheckoutDetails", $request);
620 0           $respDetails = $resp->getGetExpressCheckoutDetailsResponseDetails();
621 0           $payerInfo = $respDetails->getPayerInfo();
622             };
623              
624 0 0         if ($@) {
625 0 0         if (Inline::Java::caught('java.lang.Exception')) {
626 0 0         if (ref $@) {
627 0           $s->error("GetExpressCheckoutDetails failed: [" . $@->getMessage() . '] [' . $@ . ']');
628             } else {
629 0           $s->error("GetExpressCheckoutDetails failed: [" . $@ . ']');
630             }
631 0           return undef;
632             } else {
633 0           $s->error($@);
634 0           return undef;
635             }
636             }
637            
638 0           my $ret = {};
639 0           my $ack = $resp->getAck();
640 0           $ret->{ack} = $ack->toString;
641 0 0         if ($ret->{ack} eq 'Success') {
642 0           $ret->{Custom} = $respDetails->getCustom;
643 0           $ret->{InvoiceID} = $respDetails->getInvoiceID;
644 0           $ret->{Token} = $respDetails->getToken;
645            
646 0           $ret->{PayerInfo}->{Payer} = $payerInfo->getPayer;
647 0           $ret->{PayerInfo}->{PayerID} = $payerInfo->getPayerID;
648 0           $ret->{PayerInfo}->{PayerBusiness} = $payerInfo->getPayerBusiness;
649 0 0         if ($payerInfo->getPayerCountry) {
650 0           my $CountryCodeType = $payerInfo->getPayerCountry;
651 0           $ret->{PayerInfo}->{PayerCountry} = $CountryCodeType->toString;
652             }
653            
654 0           my $PayerStatus = $payerInfo->getPayerStatus;
655 0           $ret->{PayerInfo}->{PayerStatus} = $PayerStatus->toString;
656            
657 0           my $payerName = $payerInfo->getPayerName();
658            
659 0           $ret->{PayerInfo}->{PayerName}->{FirstName} = $payerName->getFirstName();
660 0           $ret->{PayerInfo}->{PayerName}->{LastName} = $payerName->getLastName();
661            
662 0           my $payerAddress = $payerInfo->getAddress();
663            
664 0           $ret->{PayerInfo}->{PayerAddress}->{AddressID} = $payerAddress->getAddressID();
665 0           $ret->{PayerInfo}->{PayerAddress}->{CityName} = $payerAddress->getCityName();
666 0           my $CountryCodeType = $payerAddress->getCountry;
667 0 0         $ret->{PayerInfo}->{PayerAddress}->{Country} = $CountryCodeType->toString() if $CountryCodeType;
668 0           $ret->{PayerInfo}->{PayerAddress}->{CountryName} = $payerAddress->getCountryName();
669 0           $ret->{PayerInfo}->{PayerAddress}->{Phone} = $payerAddress->getPhone();
670 0           $ret->{PayerInfo}->{PayerAddress}->{Name} = $payerAddress->getName();
671 0           $ret->{PayerInfo}->{PayerAddress}->{PostalCode} = $payerAddress->getPostalCode();
672 0           $ret->{PayerInfo}->{PayerAddress}->{StateOrProvince} = $payerAddress->getStateOrProvince();
673 0           $ret->{PayerInfo}->{PayerAddress}->{Street1} = $payerAddress->getStreet1();
674 0           $ret->{PayerInfo}->{PayerAddress}->{Street2} = $payerAddress->getStreet2();
675             } else {
676 0           $ret->{ErrorCodes} = $s->_getErrorHash($resp->getErrors);
677             }
678 0           return $ret;
679             }
680              
681             =head2 SetExpressCheckout()
682              
683             SetExpressCheckout to get token
684              
685             =cut
686             sub SetExpressCheckout {
687 0     0 1   my $s = shift;
688 0           my $args = shift;
689              
690 0 0         unless ($s->paypal) {
691 0 0         unless ($s->init_java) {
692 0           $s->error("could not init_java.");
693 0           return undef;
694             }
695             }
696              
697 0           my $reqs = [
698             qw/
699             OrderTotal
700             ReturnURL
701             CancelURL
702             /
703             ];
704              
705 0 0         return undef unless $s->_checkRequires($reqs, $args);
706            
707             package main;
708 0           Inline::Java::study_classes(
709             [
710             qw(
711             com.paypal.soap.api.SetExpressCheckoutRequestType
712             com.paypal.soap.api.SetExpressCheckoutResponseType
713             com.paypal.soap.api.SetExpressCheckoutRequestDetailsType
714             com.paypal.soap.api.BasicAmountType
715             com.paypal.soap.api.CountryCodeType
716             )
717             ]
718             );
719             package Business::PayPal::SDK;
720              
721 0           my $resp;
722 0           eval {
723 0           my $OrderTotalObj = com::paypal::soap::api::BasicAmountType->new($args->{OrderTotal});
724 0           $OrderTotalObj->setCurrencyID($com::paypal::soap::api::CurrencyCodeType::USD);
725 0           my $MaxAmountObj;
726 0 0         if ($args->{MaxAmount}) {
727 0           $MaxAmountObj = com::paypal::soap::api::BasicAmountType->new($args->{MaxAmount});
728 0           $MaxAmountObj->setCurrencyID($com::paypal::soap::api::CurrencyCodeType::USD);
729             }
730            
731 0           my $ReqDetails = com::paypal::soap::api::SetExpressCheckoutRequestDetailsType->new();
732 0           $ReqDetails->setReturnURL($args->{ReturnURL});
733 0           $ReqDetails->setCancelURL($args->{CancelURL});
734 0           $ReqDetails->setOrderTotal($OrderTotalObj);
735            
736 0 0         $ReqDetails->setCustom($args->{Custom}) if $args->{Custom};
737 0 0         $ReqDetails->setInvoiceID($args->{InvoiceID}) if $args->{InvoiceID};
738              
739 0           my $request = com::paypal::soap::api::SetExpressCheckoutRequestType->new();
740 0           $request->setSetExpressCheckoutRequestDetails($ReqDetails);
741 0           $resp = $s->paypal->call("SetExpressCheckout", $request);
742             };
743 0           my $ret = {};
744              
745 0 0         if ($@) {
746 0 0         if (ref $@) {
747 0           $s->error("SetExpressCheckout failed: [" . $@->getMessage() . '] [' . $@ . ']');
748             } else {
749 0           $s->error("SetExpressCheckout failed: [$@]");
750             }
751 0           return undef;
752             }
753              
754 0           my $ack = $resp->getAck();
755 0           $ret->{ack} = $ack->toString;
756              
757 0 0         if ($ret->{ack} eq 'Success') {
758 0           $ret->{token} = $resp->getToken();
759 0           $ret->{ErrorCodes} = $s->_getErrorHash($resp->getErrors);
760             } else {
761 0           $ret->{ErrorCodes} = $s->_getErrorHash($resp->getErrors);
762             }
763 0           return $ret;
764             }
765              
766             =head2 RefundTransaction()
767              
768             RefundTransaction to do refund. RefundType is defaulted to 'Full'
769              
770             =cut
771             sub RefundTransaction {
772 0     0 1   my $s = shift;
773 0           my $args = shift;
774              
775 0 0         unless ($s->paypal) {
776 0 0         unless ($s->init_java) {
777 0           $s->error("could not init_java.");
778 0           return undef;
779             }
780             }
781              
782 0   0       $args->{RefundType} ||= 'Full';
783              
784 0           my $reqs = [
785             qw/
786             TransactionID
787             RefundType
788             /
789             ];
790              
791 0 0         if ($args->{RefundType} ne 'Full') {
792 0           push @$reqs, 'Amount';
793             }
794              
795 0 0         return undef unless $s->_checkRequires($reqs, $args);
796              
797 0 0         unless ($args->{RefundType} =~ /^(Full|Partial|Other)$/) {
798 0           $s->error("[$args->{RefundType}] is not a valid RefundType");
799 0           return undef;
800             }
801              
802             package main;
803 0           Inline::Java::study_classes(
804             [
805             qw(
806             com.paypal.soap.api.RefundTransactionRequestType
807             com.paypal.soap.api.RefundTransactionResponseType
808             com.paypal.soap.api.RefundPurposeTypeCodeType
809             com.paypal.soap.api.BasicAmountType
810             )
811             ]
812             );
813             package Business::PayPal::SDK;
814              
815 0           my $resp;
816 0           eval {
817            
818 0           my $request = com::paypal::soap::api::RefundTransactionRequestType->new();
819              
820 0           $request->setTransactionID($args->{TransactionID});
821            
822 0           my $RefundType = com::paypal::soap::api::RefundPurposeTypeCodeType->fromString($args->{RefundType});
823 0           $request->setRefundType($RefundType);
824 0 0         if ($args->{Amount}) {
825 0           my $Amount = com::paypal::soap::api::BasicAmountType->new($args->{Amount});
826 0           $Amount->setCurrencyID($com::paypal::soap::api::CurrencyCodeType::USD);
827 0           $request->setAmount($Amount);
828             }
829 0 0         $request->setMemo($args->{Memo}) if $args->{Memo};
830 0           $resp = $s->paypal->call("RefundTransaction", $request);
831             };
832 0           my $ret = {};
833              
834 0 0         if ($@) {
835 0           my $var = $@;
836 0 0         if (ref $@) {
837 0           $s->error("RefundTransaction failed: [" . $var->getMessage() . '] [' . $var . ']');
838             } else {
839 0           $s->error("RefundTransaction failed: [$var]");
840             }
841 0           return undef;
842             }
843            
844 0           my $ack = $resp->getAck();
845 0           $ret->{ack} = $ack->toString;
846              
847 0 0         if ($ret->{ack} eq "Success") {
848 0           my $FeeRefundAmount = $resp->getFeeRefundAmount();
849 0           my $GrossRefundAmount = $resp->getGrossRefundAmount();
850 0           my $NetRefundAmount = $resp->getNetRefundAmount();
851 0           $ret->{RefundTransactionID} = $resp->getRefundTransactionID();
852 0 0         $ret->{FeeRefundAmount}->{value} = $FeeRefundAmount->get_value() if $FeeRefundAmount;
853 0 0         $ret->{GrossRefundAmount}->{value} = $GrossRefundAmount->get_value() if $GrossRefundAmount;
854 0 0         $ret->{NetRefundAmount}->{value} = $NetRefundAmount->get_value() if $NetRefundAmount;
855 0           $ret->{ErrorCodes} = $s->_getErrorHash($resp->getErrors);
856             } else {
857 0           $ret->{ErrorCodes} = $s->_getErrorHash($resp->getErrors);
858             }
859 0           return $ret;
860             }
861              
862              
863              
864             sub _getAddress {
865 0     0     my $s = shift;
866 0           my $args = shift;
867              
868 0           my @requires = qw/
869             Street1
870             CityName
871             PostalCode
872             Country
873             /;
874 0 0         return undef unless $s->_checkRequires(\@requires, $args);
875             package main;
876 0           require Inline::Java;
877 0           Inline::Java::study_classes(
878             [
879             qw(
880             com.paypal.soap.api.AddressType
881             )
882             ]
883             );
884             package Business::PayPal::SDK;
885            
886 0           my $AddressObj;
887 0           eval {
888 0           $AddressObj = com::paypal::soap::api::AddressType->new();
889 0           $AddressObj->setStreet1($args->{Street1});
890 0 0         $AddressObj->setStreet2($args->{Street2}) if $args->{Street2};
891 0           $AddressObj->setCityName($args->{CityName});
892 0           $AddressObj->setStateOrProvince($args->{StateOrProvince});
893 0           $AddressObj->setPostalCode($args->{PostalCode});
894 0           $AddressObj->setCountry($s->_getCountryCode($args->{Country}));
895             };
896              
897 0 0         if ($@) {
898 0           $s->error("getAddress failed: [" . $@->getMessage() . '] [' . $@->toString() . ']');
899 0           return undef;
900             } else {
901 0           return $AddressObj;
902             }
903             }
904              
905             sub _getCountryCode {
906 0     0     my $s = shift;
907 0           my $cc = shift;
908              
909 0   0       $cc ||= '';
910 0 0 0       unless ($cc && $cc =~ /^[A-Z]{2}$/) {
911 0           $s->error("You must pass a valid code to _getCountryCode. [$cc]");
912             return
913 0           }
914             package main;
915 0           require Inline::Java;
916 0           Inline::Java::study_classes(
917             [
918             qw(
919             com.paypal.soap.api.CountryCodeType
920             )
921             ]
922             );
923             package Business::PayPal::SDK;
924            
925 0           my $code;
926 0           eval {
927 0           $code = com::paypal::soap::api::CountryCodeType->fromString($cc);
928             };
929              
930 0 0         if ($@) {
931 0 0         if ((ref $@) eq 'main::java::lang::IllegalArgumentException') {
    0          
932 0           $s->error("getCountryCode failed: [$cc] is not a valid country code.");
933             } elsif (ref $@) {
934 0           $s->error("getCountryCode failed: [" . $@->getMessage() . '] [' . $@ . ']');
935             } else {
936 0           $s->error("getCountryCode failed: [$@]");
937             }
938 0           return undef;
939             } else {
940 0           return $code;
941             }
942             }
943              
944             sub _checkRequires {
945 0     0     my $s = shift;
946 0           my $reqs = shift;
947 0           my $args = shift;
948              
949 0 0         unless (ref $reqs) {
950 0           $s->error('You must pass an arrayref to check_requires.');
951 0           return undef;
952             }
953              
954 0           foreach my $req (@$reqs) {
955 0 0         unless ($args->{$req}) {
956 0           my @stack = caller(1);
957 0           $s->error("$req is required for method $stack[3]");
958 0           return undef;
959             }
960             }
961 0           return 1;
962             }
963              
964             =head2 TransactionSearch()
965              
966             This is not really completed yet.
967              
968             =cut
969             sub TransactionSearch {
970 0     0 1   my $s = shift;
971 0           my $args = shift;
972              
973 0 0         unless ($s->paypal) {
974 0 0         unless ($s->init_java) {
975 0           $s->error("could not init_java.");
976 0           return undef;
977             }
978             }
979              
980             package main;
981 0           Inline::Java::study_classes(
982             [
983             qw(
984             com.paypal.soap.api.TransactionSearchRequestType
985             com.paypal.soap.api.TransactionSearchResponseType
986             com.paypal.sdk.exceptions.TransactionException
987             java.util.Calendar
988             java.lang.String
989             )
990             ]
991             );
992             package Business::PayPal::SDK;
993            
994 0           my $resp;
995 0           eval {
996 0           my $request = com::paypal::soap::api::TransactionSearchRequestType->new();
997 0           my $jcal = Inline::Java::cast('java.util.Calendar', java::util::Calendar->getInstance());
998 0           $jcal->set(@{$args->{date}});
  0            
999 0           $request->setStartDate($jcal);
1000              
1001 0           my $resp = $s->paypal->call("TransactionSearch", $request);
1002             };
1003              
1004 0           my $ackcode = $resp->getAck();
1005              
1006 0 0         if ($@) {
1007 0           my $var = $@;
1008 0 0         if (ref $@) {
1009 0           $s->error("RefundTransaction failed: [" . $var->getMessage() . '] [' . $var . ']');
1010             } else {
1011 0           $s->error("RefundTransaction failed: [$var]");
1012             }
1013 0           return undef;
1014             }
1015              
1016 0           my $ret = {};
1017 0           $ret->{ack} = $ackcode->toString;
1018 0 0         if ($args->{ack} eq 'Success') {
1019 0           1;
1020             } else {
1021 0           1;
1022             }
1023 0           $ret->{ErrorCodes} = $s->_getErrorHash($resp->getErrors);
1024 0           return $ret;
1025             }
1026              
1027             sub _getDateString {
1028 0     0     my $s = shift;
1029 0           my $dateObj = shift;
1030              
1031 0           return sprintf(
1032             "%04d-%02d-%02d %02d:%02d:%02d",
1033             $dateObj->get($dateObj->{YEAR}),
1034             $dateObj->get($dateObj->{MONTH}),
1035             $dateObj->get($dateObj->{DAY_OF_MONTH}),
1036             $dateObj->get($dateObj->{HOUR}),
1037             $dateObj->get($dateObj->{MINUTE}),
1038             $dateObj->get($dateObj->{SECOND}),
1039             );
1040             }
1041              
1042             sub error {
1043 0     0 0   my $s = shift;
1044 0           my $msg = shift;
1045              
1046 0 0         if ($msg) {
1047 0           $ERROR .= "$msg\n";
1048             }
1049              
1050 0           return $ERROR;
1051             }
1052              
1053             sub _getErrorHash {
1054 0     0     my $s = shift;
1055 0           my $errors = shift;
1056              
1057 0           my $ErrorCodes = {};
1058 0           foreach my $err (@$errors) {
1059 0           my $token = $err->getErrorCode;
1060 0 0         $s->error($err->getLongMessage) if $err;
1061 0 0 0       $ErrorCodes->{$token->toString} = $err->getLongMessage if ($err && $token);
1062             }
1063 0           return $ErrorCodes;
1064             }
1065              
1066             sub get_classpath {
1067 0     0 0   my $s = shift;
1068              
1069 0           my $pplibdir = $s->java_sdk_dir . "/lib";
1070              
1071 0           opendir DIR, "$pplibdir";
1072 0           my @jars;
1073 0           foreach my $jar (grep { /\.jar$/ } readdir(DIR)) {
  0            
1074 0           push @jars, "$pplibdir/$jar";
1075             }
1076 0           closedir DIR;
1077 0           return join ":", @jars;
1078             }
1079              
1080             sub dumper {
1081 0     0 0   my $s = shift;
1082 0           my $thing = shift;
1083              
1084 0           require Data::Dumper;
1085 0           return Data::Dumper::Dumper($thing);
1086             }
1087              
1088             1;
1089              
1090             __END__