Business-OnlinePayment-PayPal
view release on metacpan or search on metacpan
lib/Business/OnlinePayment/PayPal.pm view on Meta::CPAN
Returns the AVSCode returned from DoDirectPaymentRequest.
=item cvv2_code()
Returns the CVV2Code returned from DoDirectPaymentRequest.
=item is_success()
Returns 1 or 0 on success or failure of DoDirectPaymentRequest. This
method is part of the Business::OnlinePayment "standard" API.
=item error_message()
Returns a string containing an error message, if any. This method is
part of the Business::OnlinePayment "standard" API.
=back
=head2 set_defaults()
Creates accessor methods L</avs_code()>, L</correlationid()>,
L</cvv2_code()> and __map_fields_data (see L</get_request_data>).
=cut
sub set_defaults {
my $self = shift;
$self->build_subs(qw(avs_code correlationid cvv2_code __map_fields_data));
$self->__map_fields_data(
{
PaymentAction => "action",
OrderTotal => "amount", # Payment Detail
# Credit Card
CreditCardType => "type",
CreditCardNumber => "card_number",
CVV2 => undef,
# Card Owner / Payer Name
Payer => "email",
FirstName => "name",
LastName => undef,
# Payer Address
Street1 => "address",
Street2 => undef,
CityName => "city",
StateOrProvince => "state",
Country => "country",
PostalCode => "zip",
}
);
}
sub transactionid { shift()->authorization(@_); }
sub order_number { shift()->correlationid(@_); }
=head2 get_credentials()
Get the credential information for Business::PayPal::API that was
provided to Business::OnlinePayment::new(). The supported arguments
are:
=over 4
=item * Username Password PKCS12File PKCS12Password
=item * Username Password CertFile KeyFile
=item * Username Password Signature
=back
Business::OnlinePayment::PayPal does not currently map arguments to
new() from (standard?) names to the PayPal backend specific name. For
example, if the argument "login" were passed to new() the module could
potentially try to identify that and map that to "Username".
NOTE: This requirement/capability seems to be more of a
Business::OnlinePayment issue than a backend issue and it isn't clear
if behavior like this is needed in this module so I will wait for user
feedback to determine if we need/want to implement this.
=cut
sub get_credentials {
my $self = shift;
my %credentials;
my @cred_vars = (
[qw(PKCS12File PKCS12Password)],
[qw(CertFile KeyFile)], [qw(Signature)],
);
foreach my $aref (@cred_vars) {
my $need = 0;
my @vars = ( qw(Username Password), @$aref );
foreach my $var (@vars) {
# HACK: Business::OnlinePayment makes method lower case
my $method = lc($var);
if ( $self->can($method) ) {
$credentials{$var} = $self->$method;
}
else {
$need++;
}
}
if ($need) {
undef %credentials;
}
else {
last;
}
}
return %credentials;
}
=head2 get_request_data()
Return a hash %data with all the data from content() that we will try
to use in our request to PayPal. Tasks performed:
=over 4
=item *
Remove unsupported values from our hash (i.e. description fax login
password phone).
=item *
Translate the value in "action" if necessary, from
Business::OnlinePayment names to names used by PayPal. Translations
used are:
"normal authorization" => "Sale"
"authorization only" => "Authorization"
"void" => "None"
=item *
Translate the value in "type" if necessary, from
Business::OnlinePayment names to names used by PayPal. See
L</normalize_creditcardtype()> for details.
=item *
If necessary, separate ExpMonth and ExpYear values from the single
"standard" Business::OnlinePayment "expiration" field. See
L</parse_expiration()> for details.
=item *
Call get_remap_fields to map content() into the %data that we will
pass to PayPal. All fields not "mapped" will be passed AS-IS. The
mapping used is (map hashref stored in __map_fields_data()):
PaymentAction => "action"
# Payment Detail
OrderTotal => "amount"
# Credit Card
CreditCardType => "type"
CreditCardNumber => "card_number"
CVV2 => undef
# Card Owner / Payer Name
Payer => "email"
FirstName => "name"
LastName => undef
# Payer Address
Street1 => "address"
Street2 => undef
CityName => "city"
StateOrProvince => "state"
Country => "country"
PostalCode => "zip"
lib/Business/OnlinePayment/PayPal.pm view on Meta::CPAN
sub get_request_data {
my $self = shift;
my %content = $self->content;
return () unless (%content);
# remove some unsupported content
# others? description, invoice_number, customer_id
delete @content{qw(description fax login password phone)};
# action: map "standard" names to supported as needed
if ( $content{action} ) {
my $act = lc( $content{action} );
my %actions = (
"normal authorization" => "Sale",
"authorization only" => "Authorization",
"void" => "None",
);
$content{action} = $actions{$act} || $content{action};
}
# type: translate to supported CreditCardType values
if ( $content{type} ) {
my $type = $content{type};
$content{type} = $self->normalize_creditcardtype($type) || $type;
}
# expiration: need separate month and year values
if ( $content{expiration}
and ( !$content{ExpMonth} or !$content{ExpYear} ) )
{
my $exp = $content{expiration};
delete $content{expiration};
# we only set ExpMonth/ExpYear if they aren't already set
my ( $y, $m ) = $self->parse_expiration($exp);
if ( $m and !$content{ExpMonth} ) {
$content{ExpMonth} = $m;
}
if ( $y and !$content{ExpYear} ) {
$content{ExpYear} = $y;
}
}
my %data = $self->get_remap_fields(
content => \%content,
map => $self->__map_fields_data,
);
return %data;
}
=head2 submit()
Method that overrides the superclass stub. This method performs the
following tasks:
=over 4
=item *
Get credentials to be used for authentication with PayPal by calling
L</get_credentials()>.
=item *
Get request data to be passed to PayPal by calling
L</get_request_data()>.
=item *
Connect to PayPal and perform a DirectPaymentRequest. The request
will be run in test mode (i.e. go to PayPal's "sandbox") if
test_transaction() returns true. NOTE: I believe PayPal automatically
does AVS checking if possible.
=item *
Store the entire response in server_response().
=item *
Set result_code() to "" or the first ErrorCode in Errors (if present).
=item *
Set avs_code() to the response AVSCode.
=item *
Set cvv2_code() to the response CVV2Code.
=item *
Set is_success() to 1 or 0, indicating if the transaction was
successful or not.
=item *
On success, set authorization() with the value of TransactionID. On
failure, set error_message() with a string containing all ErrorCode
and LongMessage values joined together.
=back
=cut
sub submit {
my $self = shift;
my %credentials = $self->get_credentials;
my %request = $self->get_request_data;
my $pp =
Business::PayPal::API->new( %credentials,
sandbox => $self->test_transaction, );
my %resp = $pp->DoDirectPaymentRequest(%request);
$self->server_response( \%resp );
$self->result_code( $resp{Errors} ? $resp{Errors}->[0]->{ErrorCode} : "" );
$self->avs_code( $resp{AVSCode} );
$self->cvv2_code( $resp{CVV2Code} );
if ( $resp{Ack} and $resp{Ack} eq "Success" ) {
$self->is_success(1);
$self->authorization( $resp{TransactionID} );
$self->correlationid( $resp{CorrelationID} );
}
else {
$self->is_success(0);
}
if ( $resp{Errors} and @{ $resp{Errors} } ) {
my $error = join( "; ",
map { $_->{ErrorCode} . ": " . $_->{LongMessage} }
@{ $resp{Errors} } );
$self->error_message($error);
}
return $self->is_success;
}
=head2 get_remap_fields()
Options:
content => $href (default: { $self->content } )
map => $href (default: { } )
Combines some of the functionality of get_fields and remap_fields for
convenience and also extends/alters their behavior. Unlike
Business::OnlinePayment::remap_fields, this doesn't modify content(),
and can therefore be called more than once. Also, unlike
Business::OnlinePayment::get_fields in 3.x, this doesn't exclude
fields content with a value of undef.
=cut
sub get_remap_fields {
my ( $self, %opt ) = @_;
my $content = $opt{content} || { $self->content };
my $map = $opt{map} || {};
my %data;
while ( my ( $to, $from ) = each %$map ) {
my $tolc = lc($to);
my $v;
if ( defined $from ) {
$v = $content->{$from};
delete $content->{$from};
}
$v ||= $content->{$to} || $content->{$tolc};
delete @$content{ $to, $tolc };
( run in 3.008 seconds using v1.01-cache-2.11-cpan-364913b4093 )