NAME

Net::PayPal::Lite - unofficial Perl extension for PayPal's REST API (Lite version)

SYNOPSIS

use Net::PayPal::Lite

my $p = Net::PayPal::Lite->new(
    client_id => $client_id,
    secret    => $secret,
);

my $payment = $p->cc_payment({
    cc_number       => '4111111111111111',
    cc_type         => 'visa',
    cc_expire_month => 3,
    cc_expire_year  => 2099,
    amount          => 19.95,
});

unless ( $payment ) {
    die $p->error;
}

unless ( $payment->{state} eq "approved" ) {
    printf("Your payment was not approved");
}

DESCRIPTION

Net::PayPal::Lite implements PayPal's REST API. Visit http://developer.paypal.com for further information.

This is a "lite" fork of Net::PayPal that does not store secrets in encrypted files.

To start using Net::PayPal::Lite the following actions must be completed to gain access to API endpoints:

1 Sign up for a (free) developer account.
2 Under "Applications" tab (after signing into developer.paypal.com) make note of secret and client_id. You will need these two identifiers to interact with PayPal's API server
3 Create Net::PayPal::Lite instance using secret and client_id identifiers.

METHODS

Following methods are available

new( %ARGS );

my $paypal = Net::PayPal::Lite->new(
    client_id => '1234',
    secret    => 'abcd',
);

Creates and returns an instance of Net::PayPal::Lite class.

Accepts the following arguments in a hash or hashref:

  • client_id - The client id for your app, as provided by PayPal. Mandatory.

  • secret - The secret for your app, as provided by PayPal. Mandatory.

  • sandbox - Set the target url

Safekeeping your cached access token

PayPal's REST API forces you to provide an access token on every query. That token comes with a (sometimes very short) expiration date, rendering requests very expensive - imagine having to ask for a new acces token every time you make a request to the API!

To prevent that while also allowing different processes to share the same access token, we store it in cache, using Cache::Cache's FileCache engine.

Problem is, caching to the filesystem defaults to a public directory, which might be readable by others. While that's kind of the point, it is worth noticing that anyone whith read access to the temporary directory in your filesystem will be able to read it (and perform operations on the REST API on your behalf!).

There are several ways to make this safe:

  • use the cache_dir argument to save the cache file in a protected directory of your choosing - probably the same place where you store your client_id and secret, which are even more sensitive.

  • use the cache argument to set a different, safer, cache of your choosing.

  • use the cache_transform argument to encrypt/decrypt your access key. The example below encrypts your key using the Blowfish cipher, with the paypal secret as key:

    use Net::PayPal::Lite;
    use Crypt::CBC;
    
    my ($client_id, $secret) = fetch_my_paypal_data();
    
    my $cipher = Crypt::CBC->new( -key => $secret, -cipher => 'Blowfish' );
    
    my $paypal = Net::PayPal::Lite->new({
        client_id       => $client_id,
        secret          => $secret,
        cache_transform => {
            in  => sub { $cipher->encrypt(@_) },
            out => sub { $cipher->decrypt(@_) },
        }

cc_payment(\%data)

Charges a credit card:

my $payment = $p->cc_payment({
    cc_number       => '4111111111111111',
    cc_type         => 'visa',
    cc_expire_month => 3,
    cc_expire_year  => 2099,
    first_name      => 'Jane',
    last_name       => 'Doe',
    amount          => 19.95,
}) or die $p->error;

You may choose to store id payment attribute should you wish to lookup payment details in the future. The state of the payment is stored in 'state' attribute:

unless ( $payment->{state} eq 'approved' ) {
    die "Your payment wasn't approved";
}

On error returns undef. Last error message can be queried through error() class method.

stored_cc_payment(\%data)

The same as cc_payment(), except using a credit card stored in vault

my $payment = $p->cc_payment({
    id      => 'CARD-ADFA13413241241324'
    amount  => '19.95',
    currency=> 'USD'
});

id is the result of previously invoked store_cc().

On error returns undef. Last error message can be queried through error() class method.

get_payment( $id )

Returns previously processed payment information, given the payment ID.

my $payment = $p->get_payment( 'PAY-9D023728F47376036KE5OTKY' );

On error returns undef. Last error message can be queried through error() class method.

get_payments()

Returns list of previously processed payments.

my @payments = $p->get_payments;

On error returns undef. Last error message can be queried through error() class method.

store_cc(\%credit_card);

Stores a credit card profile in the vault:

my $cc = $p->store_cc({
    cc_number       => '4111111111111111',
    cc_type         => 'visa',
    cc_expire_month => '3',
    cc_expire_year  => '2099',
    cvv2            => '420',
    first_name      => 'Jane',
    last_name       => 'Doe'
});

id is probably the most important attribute of the response data. To make a payment using the stored CC see stored_cc_payment() method.

get_cc( $id )

Retrieves stored CC information from the database. Usual, in real world applications there is rarely a need for this method. Since once can already charge a credit card without retrieving it completely.

my $cc = get_cc( $id );

On error returns undef. Last error message can be queried through error() class method.

rest($method, $path)

rest($method, $path, $json_or_hashref);

To make up for missing API methods and PayPal's future upgrades to its REST API I decided to provide this convenience method. Basically all other methods of Net::PayPal::Lite rely on this method to make things happen. It takes care of all OAuth2 specific authentication that PayPal requires.

For example:

my $r = $pp->cc_payment({
    cc_number   => '...',
    cc_type     => 'visa',
    cc_expire_month => '...',
    cc_expire_year  => '...',
    cvv2    => '...',
    amount  => '19.95',
    currency => 'USD'
});

Is equivalent to:

my $r = $pp->rest('POST', '/v1/payments/payment', {
    intent => 'sale',
    payer  => {
        payment_method      => "credit_card",
        funding_instruments => [{credit_card => {
            number  => '...',
            type    => 'visa',
            expire_month => '...',
            expire_year => ''',
            cvv2 => ''
        }}
    ],
    transactions => [{
        amount => {
            total    => 19.95,
            currency => "USD"
        },
    }]
});

To learn more about the contents of REST request refer to PayPal's REST API documentation located on https://developer.paypal.com/webapps/developer/docs/api/

rest() really shines if you decided to subclass Net::PayPal::Lite.

GOING LIVE

All the above methods invoke the sandbox API hosted at api.sandbox.paypal.com. Once you're done developing your tool you must go live by calling live(1) BEFORE calling new():

Net::PayPal::Lite->live( 1 );
my $pp = Net::PayPal::Lite->new($client_id, $secret);

SEE ALSO

Net::PayPal (this module is a fork of it)
Business::Net::PayPal::Lite
Business::PayPal::IPN
Business::OnlinePayment::PayPal

CREDITS

Net::PayPal::Lite is an immediate fork of Sherzod B. Ruzmetov's excellent Net::PayPal, which sadly hasn't been updated in a while.

Net::PayPal::Lite is NOT affiliated with PayPal nor PayPal, Inc. in any way.

PayPal is a trademark of PayPal, Inc.

AUTHOR

Sherzod B. Ruzmetov <sherzodr@cpan.org> (original source code author) Breno G. de Oliveira <garu@cpan.org> (fork maintainer)

COPYRIGHT AND LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 425:

'=item' outside of any '=over'