First pass at adding key files
This commit is contained in:
@ -0,0 +1,317 @@
|
||||
# ====================================================================
|
||||
# Gossamer Threads Module Library - http://gossamer-threads.com/
|
||||
#
|
||||
# GT::Payment::Remote::2CheckOut
|
||||
# Author: Jason Rhinelander
|
||||
# CVS Info : 087,071,086,086,085
|
||||
# $Id: 2CheckOut.pm,v 1.5 2006/08/22 20:39:04 brewt Exp $
|
||||
#
|
||||
# Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved.
|
||||
# ====================================================================
|
||||
#
|
||||
# Description:
|
||||
# 2CheckOut payment processing.
|
||||
#
|
||||
|
||||
package GT::Payment::Remote::2CheckOut;
|
||||
use strict;
|
||||
use Carp;
|
||||
use GT::MD5 'md5_hex';
|
||||
require Exporter;
|
||||
use vars qw/@EXPORT_OK/;
|
||||
@EXPORT_OK = qw/process/;
|
||||
|
||||
sub process {
|
||||
# -----------------------------------------------------------------------------
|
||||
shift if $_[0] and UNIVERSAL::isa($_[0], __PACKAGE__);
|
||||
|
||||
my %opts = @_;
|
||||
$opts{param} and UNIVERSAL::isa($opts{param}, 'GT::CGI') or croak 'Usage: ->process(param => $gtcgi, ...)';
|
||||
my $in = $opts{param};
|
||||
|
||||
ref $opts{on_valid} eq 'CODE'
|
||||
or croak 'Usage: ->process(on_valid => \&CODEREF, ...)';
|
||||
|
||||
defined $opts{password} and length $opts{password} or croak 'Usage: ->process(password => "password", ...)';
|
||||
defined $opts{sellerid} and length $opts{sellerid} or croak 'Usage: ->process(sellerid => "sellerid", ...)';
|
||||
|
||||
$opts{password} eq 'tango' and croak 'Usage: ->process(password => "something other than \'tango\'", ...)';
|
||||
|
||||
my $order_number = $in->param('order_number');
|
||||
|
||||
# Check that the "secret word" (password) combined with the other information
|
||||
# actually checks out.
|
||||
my $str = $opts{password} . $opts{sellerid} . $order_number . $in->param('total');
|
||||
my $md5 = md5_hex($str);
|
||||
|
||||
if (lc $md5 eq lc $in->param('key')) {
|
||||
$opts{on_valid}->();
|
||||
}
|
||||
# If demo mode is enabled, then the order number is set to 1 in the md5:
|
||||
# https://www.2checkout.com/documentation/UsersGuide2/chapter6/md5-hash.html
|
||||
elsif ($opts{demo}) {
|
||||
$str = $opts{password} . $opts{sellerid} . 1 . $in->param('total');
|
||||
$md5 = md5_hex($str);
|
||||
|
||||
if (lc $md5 eq lc $in->param('key')) {
|
||||
$opts{on_valid}->();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
GT::Payment::Remote::2CheckOut - 2CheckOut payment handling
|
||||
|
||||
=head1 CAVEATS
|
||||
|
||||
2CheckOut has a pretty weak automated payment system - the security of the
|
||||
entire automated payment process hinges on your "Secret Word" (Admin -> Account
|
||||
Details -> Return -> Secret Word (near the bottom of the page)) - without it,
|
||||
there is no security at all. Another weakness in the system is that if your
|
||||
server is not reachable for whatever reason, the payment information would be
|
||||
lost. Payment providers like 2CheckOut and WorldPay would do well to learn
|
||||
from payment systems like that of PayPal - whatever can be said about other
|
||||
aspects of PayPal, they do have one of the nicest payment systems around - both
|
||||
from a developer and user's point of view.
|
||||
|
||||
Because of the security issue with not using the "Secret Word", this module
|
||||
requires that the secret word be used, even if other 2CheckOut systems may not.
|
||||
Additionally, the default secret word of "tango" is not allowed.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use GT::Payment::Remote::2CheckOut;
|
||||
use GT::CGI;
|
||||
|
||||
my $in = new GT::CGI;
|
||||
|
||||
GT::Payment::Remote::2CheckOut->process(
|
||||
param => $in,
|
||||
|
||||
on_valid => \&valid,
|
||||
|
||||
sellerid => "1234",
|
||||
password => "Some Good Secret Word"
|
||||
);
|
||||
|
||||
sub valid {
|
||||
# Update database - the payment has been made successfully.
|
||||
}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module is designed to handle 2CheckOut payment processing.
|
||||
|
||||
=head1 REQUIREMENTS
|
||||
|
||||
GT::CGI and GT::MD5.
|
||||
|
||||
=head1 FUNCTIONS
|
||||
|
||||
This module has only one function: process() does the work of actually
|
||||
figuring out what to do with a postback.
|
||||
|
||||
=head2 process
|
||||
|
||||
process() is the only function 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.
|
||||
|
||||
process() should be called for 2CheckOut initiated postbacks. This can be set
|
||||
up in your main .cgi by looking for 2CheckOut-specific CGI parameters
|
||||
('cart_order_id' is a good one to look for) or by making a seperate .cgi file
|
||||
exclusively for handling 2CheckOut postbacks.
|
||||
|
||||
Additionally, it is strongly advised that database connection, authenticate,
|
||||
etc. be performed before calling process() to ensure that the payment is
|
||||
recorded successfully. 2CheckOut will not attempt to repost the form data if
|
||||
your script produces an error, and the error will be shown to the customer.
|
||||
|
||||
=over 4
|
||||
|
||||
=item param
|
||||
|
||||
param takes a GT::CGI object from which 2CheckOut postback variables are read.
|
||||
|
||||
=item 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. The
|
||||
C<cart_order_id> CGI variable will have whatever cart_order_id you provided.
|
||||
|
||||
=item sellerid
|
||||
|
||||
This should be passed to seller number. This is needed, along with the
|
||||
password field below, to verify that the posted payment is a genuine 2CheckOut
|
||||
payment.
|
||||
|
||||
=item password
|
||||
|
||||
This is a "Secret Word" that the admin must set in the 2CheckOut admin area
|
||||
(under Look & Feel -> Secret Word). This field must be set in the admin, and
|
||||
passed in here. Note that the default value, "tango", is not allowed. Without
|
||||
this password, 2CheckOut postbacks should not be considered secure.
|
||||
|
||||
=item demo
|
||||
|
||||
Whether or not to initiate and accept demo transactions.
|
||||
|
||||
=back
|
||||
|
||||
=head1 INSTRUCTIONS
|
||||
|
||||
To implement 2CheckOut payment processing, there are a number of steps required
|
||||
in addition to this module. Basically, this module handles only the postback
|
||||
stage of the 2CheckOut payment process.
|
||||
|
||||
=head2 Directing customers to 2CheckOut
|
||||
|
||||
This is done by creating a web form containing the following variables. Your
|
||||
form, first of all, should post to
|
||||
C<https://www.2checkout.com/2co/buyer/purchase>. See
|
||||
C<https://www.2checkout.com/documentation/UsersGuide2/third_party_carts/2co-system-parameters.html>
|
||||
for a complete and up-to-date list of parameters that can be passed to 2CheckOut.
|
||||
|
||||
Required fields are as follows:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * sid
|
||||
|
||||
Your 2CheckOut account number
|
||||
|
||||
=item * total
|
||||
|
||||
The total amount to be billed, in DD.CC format.
|
||||
|
||||
=item * cart_order_id
|
||||
|
||||
A unique order id, which you should store to track the payment.
|
||||
|
||||
=back
|
||||
|
||||
The following parameters *may* be passed in, and will be available in the
|
||||
postback:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * card_holder_name
|
||||
|
||||
=item * street_address
|
||||
|
||||
=item * city
|
||||
|
||||
=item * state
|
||||
|
||||
=item * zip
|
||||
|
||||
=item * country
|
||||
|
||||
=item * phone
|
||||
|
||||
The card holder's details.
|
||||
|
||||
=item * email
|
||||
|
||||
The card holder's email address.
|
||||
|
||||
=item * ship_name
|
||||
|
||||
=item * ship_street_address
|
||||
|
||||
=item * ship_city
|
||||
|
||||
=item * ship_state
|
||||
|
||||
=item * ship_zip
|
||||
|
||||
=item * ship_country
|
||||
|
||||
Shipping info - however, according to 2CheckOut, you must indicate that you
|
||||
want to take that you want to take down a seperate shipping and billing address
|
||||
on the L<Shipping Details page|https://sellers.2checkout.com/cgi-bin/sellersarea/shipdetails.2c>.
|
||||
|
||||
=item * demo
|
||||
|
||||
Should be set to 'Y' if you want demo mode, omitted for regular transactions.
|
||||
|
||||
=back
|
||||
|
||||
In the postback CGI, you'll get back all of the billing and shipping variables
|
||||
listed above, plus:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * order_number
|
||||
|
||||
2CheckOut order number
|
||||
|
||||
=item * cart_order_id
|
||||
|
||||
=item * cart_id
|
||||
|
||||
Your order number, passed back. Both variables are the same.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Postback
|
||||
|
||||
Before 2CheckOut postback notification can occur, you must set up the postback
|
||||
(in 2CheckOut terminology, "Routine"). This can be set from the Admin ->
|
||||
Shopping Cart -> Cart Details. You need to enable the payment routine, and
|
||||
set it to a CGI that you manage.
|
||||
|
||||
=head2 Putting it all together
|
||||
|
||||
The typical way to implement all of this is as follows:
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1 Get necessary merchant information (sid and secret keyword)
|
||||
|
||||
=item 2 Once the customer has selected what to purchase, generate a
|
||||
cart_order_id (a random MD5 hex string works well), and store it somewhere
|
||||
(i.e. in the database).
|
||||
|
||||
=item 3 Make a form with all the necessary fields that
|
||||
L<submits to 2CheckOut|/"Directing customers to 2CheckOut">.
|
||||
|
||||
=item 4 Set up the L<C<on_valid>|/"on_valid"> callback. If using a dedicated
|
||||
CGI script for 2CheckOut callbacks, it should just call process(); otherwise,
|
||||
check for the CGI parameter 'cart_order_id' and if present, call process().
|
||||
|
||||
=item 5 For a valid payment, do whatever you need to do for a valid payment,
|
||||
and store some record of the payment having been made (storing at least the
|
||||
cart_order_id and the order_number is strongly recommended). Use the CGI
|
||||
parameter 'cart_order_id' to locate the order (i.e. in the database).
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<http://www.2checkout.com> - 2CheckOut website.
|
||||
|
||||
L<http://www.support.2checkout.com/deskpro/faq.php> - 2CheckOut knowledgebase
|
||||
|
||||
=head1 MAINTAINER
|
||||
|
||||
Jason Rhinelander
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved.
|
||||
http://www.gossamer-threads.com/
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
Revision: $Id: 2CheckOut.pm,v 1.5 2006/08/22 20:39:04 brewt Exp $
|
||||
|
||||
=cut
|
Reference in New Issue
Block a user