- NAME
- SYNOPSIS
- DESCRIPTION
- REQUIREMENTS
- process

- param
- on_valid
- on_pending
- on_failed
- on_denied
- on_invalid
- duplicate
- recurring
- recurring_signup
- recurring_cancel
- recurring_failed
- recurring_eot
- recurring_modify
- email
- on_error

- INSTRUCTIONS

- Directing customers to PayPal
- IPN

- SEE ALSO
- MAINTAINER
- COPYRIGHT
- VERSION

# NAME

GT::Payment::Remote::PayPal - PayPal payment handling

# SYNOPSIS

        use GT::Payment::Remote::PayPal;
        use GT::CGI;

        my $in = new GT::CGI;

        GT::Payment::Remote::PayPal->process(
            param => $in,
            on_valid => \&valid,
            on_pending => \&pending,
            on_failed => \&failed,
            on_denied => \&denied,
            on_invalid => \&invalid,
            on_recurring => \&recurring,
            on_recurring_signup => \&r_signup,
            on_recurring_cancel => \&r_cancel,
            on_recurring_failed => \&r_failed,
            on_recurring_eot => \&r_eot,
            on_recurring_modify => \&r_modify,
            duplicate => \&duplicate,
            email => \&email,
            on_error => \&error
        );

        sub valid {
            # Update database - the payment has been made successfully.
        }
        sub pending {
            # Optional; store a "payment pending" status if you wish.  This is optional
            # because another postback will be made with a completed, failed, or denied
            # status.
        }
        failed {
            # According to PayPal IPN documentation: "The payment has failed.  This
            # will only happen if the payment was made from your customer's bank
            # account."
            # Store a "payment failed" status for the order
        }
        sub denied {
            # According to PayPal IPN documentation: "You, the merchant, denied the
            # payment.  This will only happen if the payment was previously pending due
            # to one of the "pending reasons" [in pending_reason]"
        }
        sub invalid {
            # This means the request did NOT come from PayPal.  You should log the
            # request for follow up.
        }
        sub recurring {
            # This means a recurring payment has been made successfully.  Update
            # database.
        }
        sub r_signup {
            # This means a recurring signup has been made (NOT a payment, just a
            # signup).
        }
        sub r_cancel {
            # The user has cancelled their recurring payment
        }
        sub r_failed {
            # A recurring payment has failed (probably declined).
        }
        sub r_eot {
            # A recurring payment has come to its natural conclusion.  This only
            # applies to payments with a set number of payments.
        }
        sub r_modify {
            # Something has been modified regarding the recurring payment
        }
        sub duplicate {
            # Check to see if the payment has already been made.  If it _has_ been
            # made, you should return undef, otherwise return 1 to indicate that this
            # is not a duplicate postback.  The "txn_id" value is passed in, but is
            # also available through $in->param('txn_id').
        }
        sub email {
            # This will be called with an e-mail address.  You should check to make
            # sure that the e-mail address entered is the same as the one on the PayPal
            # account.  Return true (1) if everything checks out, undef otherwise.
        }
        sub error {
            # An error message is passed in here.  This is called when a error such as
            # a connection problem or HTTP problem occurs.
        }

# DESCRIPTION

This module is designed to handle PayPal payment processing using PayPal's IPN system. It does very little other than generating and sending a proper response to the PayPal server, and calling the provided code reference(s).

It is strongly recommended that you familiarize yourself with the PayPal ``Single Item Purchases Manual'' and ``IPN Manual'' listed in the SEE ALSO section of this document.

# REQUIREMENTS

GT::WWW with the https protocol, which in turn requires Net::SSLeay. PPM's are available from Gossamer Threads for the latest Windows releases of ActiveState Perl 5.6.1 and 5.8.0.

# process

`process()` is the only function/method provided by this module. It can be called as either a function or class method, and takes a hash (not hash reference) of arguments as described below. This module requires GT::WWW's https interface, which in turn requires Net::SSLeay.

`process()` should be called for PayPal initiated requests. This can be set up in your main CGI by looking for PayPal-specific CGI parameters ('txn_type' is a good one to look for) or by making a seperate .cgi file exclusively for handling IPN postbacks.

Additionally, it is strongly advised that database connection, authenticate, etc. be performed before calling `process()` to ensure that the payment is recorded successfully. If your CGI script has an error, PayPal will retry the postback again

Except where indicated, all arguments are required.

## param

param takes a GT::CGI object from which PayPal IPN variables are read.

## on_valid

on_valid takes a code reference as value. The code reference will be called when a successful payment has been made. Inside this code reference you are responsible for setting a ``paid'' status for the order in question.

See the PayPal IPN documentation listed below for information on how to identify an order.

## on_pending

on_pending is called when PayPal sends information on a ``Pending'' payment. This parameter is optional, due to the fact that a ``Pending'' status means that another notification (either ``Completed'', ``Failed'', or ``Denied'') will be made.

It is, however, recommended that when a Pending payment is encountered, a note be stored in your application that manual intervention is probably required.

According to PayPal documentation, there are a few cases where this will happen, which can be obtained from the ``pending_reason'' CGI input variable. The possible values and what each means follows (this comes straight from the PayPal documentation).

``echeck''

  The payment is pending because it was made by an eCheck, which has not yet cleared.

``multi_currency''

  You do not have a balance in the currency sent, and you do not have your Payment Receiving Preferences set to automatically convert and accept this payment. You must manually accept or deny this payment.

``intl''

  The payment is pending because you, the merchant, hold an international account and do not have a withdrawal mechanism. You must manually accept or deny this payment from your Account Overview.

``verify''

  The payment is pending because you, the merchant, are not yet verified. You must verify your account before you can accept this payment.

``address''

  The payment is pending because your customer did not include a confirmed shipping address and you, the merchant, have your Payment Receiving Preferences set such that you want to manually accept or deny each of these payments. To change your preference, go to the ``Preferences'' section of your ``Profile.''

``upgrade''

  The payment is pending because it was made via credit card and you, the merchant, must upgrade your account to Business or Premier status in order to receive the funds.

``unilateral''

  The payment is pending because it was made to an email address that is not yet registered or confirmed.

``other''

  The payment is pending for an ``other'' reason. For more information, contact customer service.

## on_failed

Takes a code reference to call in the event of a failed payment notification. A failed payment ``will only happen if the payment was made from your customer's bank account.''

You should record a failed payment in your application.

## on_denied

This code reference is called when a ``Denied'' payment notification is received. ``This will only happen if the payment was previously pending due to one of the 'pending reasons''' above.

You should record a failed or denied payment in your application.

## on_invalid

This code reference will be called when an invalid request is made. This usually means that the request did not come from PayPal. According to PayPal, ``if you receive an 'INVALID' notification, it should be treated as suspicious and investigated.'' Thus it is strongly recommended that a record of the invalid request be made.

## duplicate

This code reference is required to prevent duplicate payments. It is called for potentially successful requests to ensure that it is not a duplicate postback. It is passed the ``txn_id'' CGI parameter, which is the PayPal-generated transaction ID. You should check this parameter against your order database. If you have already recorded this payment as successfully made, should should return `undef` from this function, to indicate that the duplicate check failed. If the transaction ID is okay (i.e. is not a duplicate) return 1 to continue.

## recurring

A successful recurring payment has been made. You should set a ``paid'' status for the item in question.

## recurring_signup

## recurring_cancel

## recurring_failed

## recurring_eot

## recurring_modify

These are called when various things have happened to the subscription. In particular, signup refers to a new subscription, cancel refers to a cancelled subscription, failed refers to a failed payment, eot refers to a subscription that ended naturally (i.e. an end was set when the subscription was initially made), and modify is called when a payment has been modified.

## email

This code reference, like duplicate, is called to ensure that the payment was sent to the correct account. An e-mail address is passed in which must be the same as the primary account's e-mail address. If it is the same, return `1`. If it is not the same, you should return `undef` and store a note asking the user to check that the PayPal e-mail address they have provided is the correct, primary, PayPal e-mail address.

## on_error

This code reference is optional, but recommended. It is called when a non-PayPal generated error occurs - such as a failure to connect to PayPal. It is recommended that you provide this code reference and log any errors that occur. The error message is passed in.

# INSTRUCTIONS

To implement PayPal payment processing, there are a number of steps required in addition to this module. Basically, this module handles only the postback stage of the PayPal IPN process.

Full PayPal single item, subscription, and IPN documentation is available at the URL's listed in the SEE ALSO section.

## Directing customers to PayPal

This is done by creating a web form containing the following variables. Your form, first of all, must post to `https://www.paypal.com/cgi-bin/webscr`.

Your form should contains various PayPal parameters, as outlined in the PayPal manuals linked to in the SEE ALSO section.

Of particular note is the ``notify_url'' option, which should be used to specify a postback URL for PayPal IPN postbacks. The below is simply a list of the required fields, and only those fields that are absolutely required are described. For descriptions of each field, check the PayPal Single Item Purchases Manual.

cmd

  Must be set to ``_xclick''.

business

  Your PayPal ID (e-mail address). Must be confirmed and linked to your Verified Business or Premier account.

item_name
item_number
image_url
no_shipping
return

  Although optional, this is highly recommend - takes a URL to bring the buyer back to after purchasing. If not specified, they'll remain at PayPal.

rm

  Return method for the return option. If ``1'', a GET request without the transaction variables will be made, if ``2'' a POST request WITH the transaction variables will be made.

cancel_return
no_note
cn
cs
on0
on1
os0
os1
quantity

  The quantity of items being purchased. If omitted, defaults to 1 and will not be shown in the payment flow.

undefined_quantity

  ``If set to ''1``, the user will be able to edit the quantity. This means your customer will see a field next to quantity which they must complete. This is optional; if omitted or set to ''0``, the quantity will not be editable by the user. Instead, it will default to 1''

shipping

## IPN

Before PayPal payment notification can occur, you must instruct the user to enable Instant Payment Notification (IPN) on their PayPal account. The postback URL should be provided and handled by you either by detecting a PayPal request in your main .cgi script (recommended), or through the use of an additional .cgi script exclusively for PayPal IPN.

If adding to your existing script, it is recommended to look for the 'txn_type' CGI parameter, which will be set for PayPal IPN postbacks.

Once IPN has been set up, you have to set up your application to direct users to PayPal in order to initiate a PayPal payment.

# SEE ALSO

https://www.paypal.com/html/single_item.pdf - Single Item Purchases Manual

https://www.paypal.com/html/subscriptions.pdf - Subscriptions and Recurring Payments Manual

https://www.paypal.com/html/ipn.pdf - IPN Manual

# MAINTAINER

Jason Rhinelander

# COPYRIGHT

Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved. http://www.gossamer-threads.com/

# VERSION

Revision: $Id: PayPal.pm,v 1.8 2006/04/08 03:42:05 brewt Exp $