Requested docs/scripts added for 11777

This commit is contained in:
Paul Driver 2009-07-13 22:12:03 +00:00
parent 0a3329d7be
commit 2adb08c79c
8 changed files with 407 additions and 974 deletions

View file

@ -3,6 +3,8 @@
- fixed #10626: Carriage returns stripped from Wiki comments
- fixed #10572: CDN / CloudFront breaks 7.7.11 upgrade
- fixed #10630: If macro says that 0 is true
- PayDriver::PayPal replaced. The old one fought the Shop API and
didn't work.
7.7.14
- fixed #10606: shelf selector

View file

@ -7,6 +7,12 @@ upgrading from one version to the next, or even between multiple
versions. Be sure to heed the warnings contained herein as they will
save you many hours of grief.
7.7.15
--------------------------------------------------------------------
* PayDriver::PayPal has been replaced with an entirely different
module. If you had the old one working, the new one very likely
will not work (the old one did some very un-Shop things, which
is why it was replaced). Please test the new one with your setup.
7.7.13
--------------------------------------------------------------------

View file

@ -33,6 +33,7 @@ my $session = start(); # this line required
# upgrade functions go here
replaceUsageOfOldTemplates($session);
replacePayPalDriver($session);
finish($session); # this line required
@ -46,6 +47,24 @@ finish($session); # this line required
# print "DONE!\n" unless $quiet;
#}
sub replacePayPalDriver {
my $session = shift;
my $config = $session->config;
my $prop = 'paymentDrivers';
my $old = 'WebGUI::Shop::PayDriver::PayPal::PayPalStd';
my $drivers = $config->get($prop);
foreach my $driver (@$drivers) {
# We'll do nothing if the old paypal driver isn't used
next unless $driver eq $old;
print "\tUpdating config to use new PayPal driver..." unless $quiet;
$config->deleteFromArray($prop, $old);
$config->addToArray($prop, 'WebGUI::Shop::PayDriver::PayPal');
print "DONE!\n" unless $quiet;
last;
}
}
#----------------------------------------------------------------------------
sub replaceUsageOfOldTemplates {
my $session = shift;

View file

@ -177,7 +177,7 @@
"paymentDrivers" : [
"WebGUI::Shop::PayDriver::Cash",
"WebGUI::Shop::PayDriver::ITransact",
"WebGUI::Shop::PayDriver::PayPal::PayPalStd",
"WebGUI::Shop::PayDriver::PayPal",
"WebGUI::Shop::PayDriver::Ogone"
],

View file

@ -1,363 +1,325 @@
package WebGUI::Shop::PayDriver::PayPal;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2009 Plain Black Corporation.
-------------------------------------------------------------------
Please read the legal notices (docs/legal.txt) and the license
(docs/license.txt) that came with this distribution before using
this software.
-------------------------------------------------------------------
http://www.plainblack.com info@plainblack.com
-------------------------------------------------------------------
=cut
## this holds some shared functionality, and MUST be overridden for a full payment driver
use strict;
use base qw/WebGUI::Shop::PayDriver/;
use warnings;
use LWP::UserAgent;
use Tie::IxHash;
use WebGUI::International;
use WebGUI::Form;
use URI::Escape;
use URI::Split;
use URI;
use Readonly;
use Data::Dumper;
=head1 NAME
WebGUI::Shop::PayDriver::PayPal
=head1 DESCRIPTION
=head1 DESCRIPTION
Super class for PayPal payment drivers
Payment driver that talks to PayPal
=head1 SYNOPSIS
# in webgui config file...
"paymentDrivers" : [
"WebGUI::Shop::PayDriver::Cash",
"WebGUI::Shop::PayDriver::PayPal",
...
],
=head1 METHODS
These methods are available from this class:
The following methods are available from this class:
=cut
=head2 getPayPalSandboxUrl
Readonly my $I18N => 'PayDriver_PayPal';
Returns the URL for the PayPal sandbox
#-------------------------------------------------------------------
=head2 apiUrl
Returns the URL for the PayPal API (or the sandbox, if we are configured to
use the sandbox)
=cut
sub getPayPalSandboxUrl {
return ('https://www.sandbox.paypal.com/cgi-bin/webscr');
sub apiUrl {
my $self = shift;
return $self->get( $self->get('testMode') ? 'apiSandbox' : 'api' );
}
=head2 getPayPalUrl
#-------------------------------------------------------------------
Returns the URL for PayPal.
=head2 definition
Standard definition method.
=cut
sub getPayPalUrl {
return ('https://www.paypal.com/cgi-bin/webscr');
}
sub definition {
my ( $class, $session, $definition ) = @_;
my $i18n = WebGUI::International->new( $session, $I18N );
=head2 getPaymentCurrencies
Returns a hash reference of currency codes and their full names.
=cut
sub getPaymentCurrencies {
return {
"AUD" => "Australian Dollar",
"CAD" => "Canadian Dollar",
"CHF" => "Swiss Franc",
"CZK" => "Czech Koruna",
"DKK" => "Danish Krone",
"EUR" => "Euro",
"GBP" => "Pound Sterling",
"HKD" => "Hong Kong Dollar",
"HUF" => "Hungarian Forint",
"JPY" => "Japanese Yen",
"NOK" => "Norwegian Krone",
"NZD" => "New Zealand Dollar",
"PLN" => "Polish Zloty",
"SEK" => "Swedish Krona",
"SGD" => "Singapore Dollar",
"USD" => "U.S. Dollar"
};
}
=head2 getCardTypes
Returns a hash of credit card types
=cut
sub getCardTypes {
return (
'Visa' => 'Visa',
'MasterCard' => 'MasterCard',
'Discover' => 'Discover',
'Amex' => 'Amex'
tie my %fields, 'Tie::IxHash';
my @fieldNames = qw(
paypal sandbox
api apiSandbox
user password
currency testMode
signature
);
}
my %paypalCountries = (
"AFGHANISTAN" => "AF",
"ÅLAND ISLANDS" => "AX",
"ALBANIA" => "AL",
"ALGERIA" => "DZ",
"AMERICAN SAMOA" => "AS",
"ANDORRA" => "AD",
"ANGOLA" => "AO",
"ANGUILLA" => "AI",
"ANTARCTICA" => "AQ",
"ANTIGUA AND BAR­BUDA" => "AG",
"ARGENTINA" => "AR",
"ARMENIA" => "AM",
"ARUBA" => "AW",
"AUSTRALIA" => "AU",
"AUSTRIA" => "AT",
"AZERBAIJAN" => "AZ",
"BAHAMAS" => "BS",
"BAHRAIN" => "BH",
"BANGLADESH" => "BD",
"BARBADOS" => "BB",
"BELARUS" => "BY",
"BELGIUM" => "BE",
"BELIZE" => "BZ",
"BENIN" => "BJ",
"BERMUDA" => "BM",
"BHUTAN" => "BT",
"BOLIVIA" => "BO",
"BOSNIA AND HERZE­GOVINA" => "BA",
"BOTSWANA" => "BW",
"BOUVET ISLAND" => "BV",
"BRAZIL" => "BR",
"BRITISH INDIAN OCEAN TERRITORY" => "IO",
"BRUNEI DARUSSALAM" => "BN",
"BULGARIA" => "BG",
"BURKINA FASO" => "BF",
"BURUNDI" => "BI",
"CAMBODIA" => "KH",
"CAMEROON" => "CM",
"CANADA" => "CA",
"CAPE VERDE" => "CV",
"CAYMAN ISLANDS" => "KY",
"CENTRAL AFRICAN REPUBLIC" => "CF",
"CHAD" => "TD",
"CHILE" => "CL",
"CHINA" => "CN",
"CHRISTMAS ISLAND" => "CX",
"COCOS (KEELING) ISLANDS" => "CC",
"COLOMBIA" => "CO",
"COMOROS" => "KM",
"CONGO" => "CG",
"CONGO, THE DEMO­CRATIC REPUBLIC OF THE" => "CD",
"COOK ISLANDS" => "CK",
"COSTA RICA" => "CR",
"COTE D'IVOIRE" => "CI",
"CROATIA" => "HR",
"CUBA" => "CU",
"CYPRUS" => "CY",
"CZECH REPUBLIC" => "CZ",
"DENMARK" => "DK",
"DJIBOUTI" => "DJ",
"DOMINICA" => "DM",
"DOMINICAN REPUBLIC" => "DO",
"ECUADOR" => "EC",
"EGYPT" => "EG",
"EL SALVADOR" => "SV",
"EQUATORIAL GUINEA" => "GQ",
"ERITREA" => "ER",
"ESTONIA" => "EE",
"ETHIOPIA" => "ET",
"FALKLAND ISLANDS (MALVINAS)" => "FK",
"FAROE ISLANDS" => "FO",
"FIJI" => "FJ",
"FINLAND" => "FI",
"FRANCE" => "FR",
"FRENCH GUIANA" => "GF",
"FRENCH POLYNESIA" => "PF",
"FRENCH SOUTHERN TERRITORIES" => "TF",
"GABON" => "GA",
"GAMBIA" => "GM",
"GEORGIA" => "GE",
"GERMANY" => "DE",
"GHANA" => "GH",
"GIBRALTAR" => "GI",
"GREECE" => "GR",
"GREENLAND" => "GL",
"GRENADA" => "GD",
"GUADELOUPE" => "GP",
"GUAM" => "GU",
"GUATEMALA" => "GT",
"GUERNSEY" => "GG",
"GUINEA" => "GN",
"GUINEA-BISSAU" => "GW",
"GUYANA" => "GY",
"HAITI" => "HT",
"HEARD ISLAND AND MCDONALD ISLANDS" => "HM",
"HOLY SEE (VATICAN CITY STATE)" => "VA",
"HONDURAS" => "HN",
"HONG KONG" => "HK",
"HUNGARY" => "HU",
"ICELAND" => "IS",
"INDIA" => "IN",
"INDONESIA" => "ID",
"IRAN, ISLAMIC REPUB­LIC OF" => "IR",
"IRAQ" => "IQ",
"IRELAND" => "IE",
"ISLE OF MAN" => "IM",
"ISRAEL" => "IL",
"ITALY" => "IT",
"JAMAICA" => "JM",
"JAPAN" => "JP",
"JERSEY" => "JE",
"JORDAN" => "JO",
"KAZAKHSTAN" => "KZ",
"KENYA" => "KE",
"KIRIBATI" => "KI",
"KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF" => "KP",
"KOREA, REPUBLIC OF" => "KR",
"KUWAIT" => "KW",
"KYRGYZSTAN" => "KG",
"LAO PEOPLE'S DEMO­CRATIC REPUBLIC" => "LA",
"LATVIA" => "LV",
"LEBANON" => "LB",
"LESOTHO" => "LS",
"LIBERIA" => "LR",
"LIBYAN ARAB JAMA­HIRIYA" => "LY",
"LIECHTENSTEIN" => "LI",
"LITHUANIA" => "LT",
"LUXEMBOURG" => "LU",
"MACAO" => "MO",
"MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF" => "MK",
"MADAGASCAR" => "MG",
"MALAWI" => "MW",
"MALAYSIA" => "MY",
"MALDIVES" => "MV",
"MALI" => "ML",
"MALTA" => "MT",
"MARSHALL ISLANDS" => "MH",
"MARTINIQUE" => "MQ",
"MAURITANIA" => "MR",
"MAURITIUS" => "MU",
"MAYOTTE" => "YT",
"MEXICO" => "MX",
"MICRONESIA, FEDER­ATED STATES OF" => "FM",
"MOLDOVA, REPUBLIC OF" => "MD",
"MONACO" => "MC",
"MONGOLIA" => "MN",
"MONTSERRAT" => "MS",
"MOROCCO" => "MA",
"MOZAMBIQUE" => "MZ",
"MYANMAR" => "MM",
"NAMIBIA" => "NA",
"NAURU" => "NR",
"NEPAL" => "NP",
"NETHERLANDS" => "NL",
"NETHERLANDS ANTI­LLES" => "AN",
"NEW CALEDONIA" => "NC",
"NEW ZEALAND" => "NZ",
"NICARAGUA" => "NI",
"NIGER" => "NE",
"NIGERIA" => "NG",
"NIUE" => "NU",
"NORFOLK ISLAND" => "NF",
"NORTHERN MARIANA ISLANDS" => "MP",
"NORWAY" => "NO",
"OMAN" => "OM",
"PAKISTAN" => "PK",
"PALAU" => "PW",
"PALESTINIAN TERRI­TORY, OCCUPIED" => "PS",
"PANAMA" => "PA",
"PAPUA NEW GUINEA" => "PG",
"PARAGUAY" => "PY",
"PERU" => "PE",
"PHILIPPINES" => "PH",
"PITCAIRN" => "PN",
"POLAND" => "PL",
"PORTUGAL" => "PT",
"PUERTO RICO" => "PR",
"QATAR" => "QA",
"REUNION" => "RE",
"ROMANIA" => "RO",
"RUSSIAN FEDERATION" => "RU",
"RWANDA" => "RW",
"SAINT HELENA" => "SH",
"SAINT KITTS AND NEVIS" => "KN",
"SAINT LUCIA" => "LC",
"SAINT PIERRE AND MIQUELON" => "PM",
"SAINT VINCENT AND THE GRENADINES" => "VC",
"SAMOA" => "WS",
"SAN MARINO" => "SM",
"SAO TOME AND PRINC­IPE" => "ST",
"SAUDI ARABIA" => "SA",
"SENEGAL" => "SN",
"SERBIA AND MON­TENEGRO" => "CS",
"SEYCHELLES" => "SC",
"SIERRA LEONE" => "SL",
"SINGAPORE" => "SG",
"SLOVAKIA" => "SK",
"SLOVENIA" => "SI",
"SOLOMON ISLANDS" => "SB",
"SOMALIA" => "SO",
"SOUTH AFRICA" => "ZA",
"SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS" => "GS",
"SPAIN" => "ES",
"SRI LANKA" => "LK",
"SUDAN" => "SD",
"SURINAME" => "SR",
"SVALBARD AND JAN MAYEN" => "SJ",
"SWAZILAND" => "SZ",
"SWEDEN" => "SE",
"SWITZERLAND" => "CH",
"SYRIAN ARAB REPUB­LIC" => "SY",
"TAIWAN, PROVINCE OF CHINA" => "TW",
"TAJIKISTAN" => "TJ",
"TANZANIA, UNITED REPUBLIC OF" => "TZ",
"THAILAND" => "TH",
"TIMOR-LESTE" => "TL",
"TOGO" => "TG",
"TOKELAU" => "TK",
"TONGA" => "TO",
"TRINIDAD AND TOBAGO" => "TT",
"TUNISIA" => "TN",
"TURKEY" => "TR",
"TURKMENISTAN" => "TM",
"TURKS AND CAICOS ISLANDS" => "TC",
"TUVALU" => "TV",
"UGANDA" => "UG",
"UKRAINE" => "UA",
"UNITED ARAB EMIR­ATES" => "AE",
"UNITED KINGDOM" => "GB",
"UNITED STATES" => "US",
"UNITED STATES MINOR OUTLYING ISLANDS" => "UM",
"URUGUAY" => "UY",
"UZBEKISTAN" => "UZ",
"VANUATU" => "VU",
"VENEZUELA" => "VE",
"VIET NAM" => "VN",
"VIRGIN ISLANDS, BRIT­ISH" => "VG",
"VIRGIN ISLANDS, U.S." => "VI",
"WALLIS AND FUTUNA" => "WF",
"WESTERN SAHARA" => "EH",
"YEMEN" => "YE",
"ZAMBIA" => "ZM",
"ZIMBABWE" => "ZW"
);
foreach my $f (@fieldNames) {
$fields{$f} = {
fieldType => 'text',
label => $i18n->get($f),
hoverHelp => $i18n->get("$f help"),
};
}
=head2 getPaypalCountry ( $country )
$fields{currency}{defaultValue} = 'USD';
Accepts a country name and returns the country code for it.
$fields{testMode}{fieldType} = 'YesNo';
=head3 $country
$fields{sandbox}{defaultValue} = 'https://www.sandbox.paypal.com/webscr';
$fields{apiSandbox}{defaultValue} = 'https://api-3t.sandbox.payPal.com/nvp';
The country to find the code for.
$fields{paypal}{defaultValue} = 'https://www.paypal.com/webscr';
$fields{api}{defaultValue} = 'https://api-3t.payPal.com/nvp';
push @{$definition}, {
name => $i18n->get('name'),
properties => \%fields,
};
return $class->SUPER::definition( $session, $definition );
} ## end sub definition
#-------------------------------------------------------------------
=head2 getButton
Overridden, submits to www_sendToPaypal with the proper parameters.
=cut
sub getPaypalCountry {
my $self = shift;
my $longCountry = shift;
sub getButton {
my $self = shift;
my $session = $self->session;
my $retcode = $paypalCountries{ uc $longCountry };
return $retcode;
my $payForm
= WebGUI::Form::formHeader($session)
. $self->getDoFormTags('sendToPayPal')
. WebGUI::Form::submit( $session, { value => $self->get('label') } )
. WebGUI::Form::formFooter($session);
return $payForm;
}
#-------------------------------------------------------------------
=head2 payPalForm ( %fields )
Returns a hashref representing a form (suitable for an LWP post) for talking
to the PayPal API. Fields can be either name value pairs or a hashref. If it
is a hashref, it will be modified in place.
=cut
sub payPalForm {
my $self = shift;
my $args = ref $_[0] eq 'HASH' ? shift : {@_};
$args->{VERSION} = '58.0';
$args->{USER} = $self->get('user');
$args->{PWD} = $self->get('password');
$args->{SIGNATURE} = $self->get('signature');
return $args;
}
#-------------------------------------------------------------------
=head2 payPalUrl
Returns the URL for the PayPal site (or the sandbox, if we are configured to
use the sandbox)
=cut
sub payPalUrl {
my $self = shift;
return $self->get( $self->get('testMode') ? 'sandbox' : 'paypal' );
}
#-------------------------------------------------------------------
=head2 processPayment ( transaction )
Implements the interface defined in WebGUI::Shop::PayDriver. Notably, on
error 'message' will be an HTML table representing the parameters that the
PayPal API spit back.
=cut
sub processPayment {
my ( $self, $transaction ) = @_;
my ( $isSuccess, $gatewayCode, $status, $message );
my $form = $self->payPalForm(
METHOD => 'DoExpressCheckoutPayment',
PAYERID => $self->session->form->process('PayerId'),
TOKEN => $self->session->form->process('token'),
AMT => $self->getCart->calculateTotal,
CURRENCYCODE => $self->get('currency'),
PAYMENTACTION => 'SALE',
);
my $response = LWP::UserAgent->new->post( $self->apiUrl, $form );
my $params = $self->responseHash($response);
if ($params) {
if ( $params->{ACK} !~ /^Success/ ) {
my $status = $params->{ACK};
my $message = '<table><tr><th>Field</th><th>Value</th></tr>';
foreach my $k ( keys %$params ) {
$message .= "<tr><td>$k</td><td>$params->{$k}</td></tr>";
}
$message .= '</table>';
return ( 0, undef, $status, $message );
}
my $status = $params->{PAYMENTSTATUS};
my $message = "Payment Status: $status";
return ( 1, $params->{TRANSACTIONID}, $status, $message );
}
return ( 0, undef, $response->status_code, $response->status_line );
} ## end sub processPayment
#-------------------------------------------------------------------
=head2 responseHash (response)
Chops up the body of a paypal response into a hashref (or undef if the request
failed)
=cut
sub responseHash {
my ( $self, $response ) = @_;
return undef unless $response->is_success;
local $_ = uri_unescape( $response->content );
return { map { split /=/ } split /[&;]/ };
}
#-------------------------------------------------------------------
=head2 www_payPalCallback
Handler that PayPal redirects to once payment has been confirmed on their end
=cut
sub www_payPalCallback {
my $self = shift;
my $transaction = $self->processTransaction;
return $transaction->get('isSuccessful')
? $transaction->thankYou
: $self->displayPaymentError($transaction);
}
#-------------------------------------------------------------------
=head2 www_sendToPayPal
Sets up payPal transaction and redirects the user off to payPal land
=cut
sub www_sendToPayPal {
my $self = shift;
my $session = $self->session;
my $url = $session->url;
my $base = $url->getSiteURL . $url->page;
my $returnUrl = URI->new($base);
$returnUrl->query_form( {
shop => 'pay',
method => 'do',
do => 'payPalCallback',
paymentGatewayId => $self->getId,
}
);
my $cancelUrl = URI->new($base);
$cancelUrl->query_form( { shop => 'cart' } );
my $form = $self->payPalForm(
METHOD => 'SetExpressCheckout',
AMT => $self->getCart->calculateTotal,
CURRENCYCODE => $self->get('currency'),
RETURNURL => $returnUrl->as_string,
CANCELURL => $cancelUrl->as_string,
PAYMENTACTION => 'SALE',
);
my $testMode = $self->get('testMode');
my $response = LWP::UserAgent->new->post( $self->apiUrl, $form );
my $params = $self->responseHash($response);
my $i18n = WebGUI::International->new( $self->session, $I18N );
my $error;
if ($params) {
unless ( $params->{ACK} =~ /^Success/ ) {
my $log = sprintf "Paypal error: Request/response below: %s\n%s\n", Dumper($form), Dumper($params);
$session->log->error($log);
$error = 'Internal Paypal Error';
}
}
else {
$error = $response->status_line;
}
if ($error) {
my $message = sprintf $i18n->get('api error'), $error;
return $session->style->userStyle($message);
}
my $dest = URI->new( $self->payPalUrl );
$dest->query_form( {
cmd => '_express-checkout',
token => $params->{TOKEN},
}
);
return $session->http->setRedirect($dest);
} ## end sub www_sendToPayPal
=head1 LIMITATIONS
=over 4
=item
Doesn't handle recurring payments, although Paypal can do that.
=item
There is no itemization of the cart for Paypal's records, just one total
(could do taxes, shipping, each item as separate things).
=item
Paypal's shipping information is ignored; this could be changed to accept new
shipping info from PayPal, but that's somewhat fragile. We're currently just
pretending PayPal is a payment gateway.
=cut
1;

View file

@ -1,475 +0,0 @@
package WebGUI::Shop::PayDriver::PayPal::PayPalStd;
=head1 LEGAL
-------------------------------------------------------------------
PayPal Standard payment driver for WebGUI.
Copyright (C) 2009 Invicta Services, LLC.
-------------------------------------------------------------------
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-------------------------------------------------------------------
=cut
use strict;
use LWP::UserAgent;
use Crypt::SSLeay;
use base qw/WebGUI::Shop::PayDriver::PayPal/;
=head1 NAME
PayPal Website payments standard
=head1 DESCRIPTION
A PayPal Website payments standard handler for WebGUI. Provides an interface to PayPal with cart contents
and transaction information on return.
=head1 SYNOPSIS
Add "WebGUI::Shop::PayDriver::PayPal::PayPalStd" to the paymentDrivers list in your WebGUI site config file.
Re-start the WebGUI modperl and modproxy web servers.
=cut
#-------------------------------------------------------------------
# local subs
#-------------------------------------------------------------------
=head2 handlesRecurring
Tells the commerce system that this payment plugin can handle recurring payments.
1 = yes, 0 = no. This module == no.
=cut
sub handlesRecurring {
return 0;
}
#-------------------------------------------------------------------
=head2 canCheckoutCart ( )
Returns whether the cart can be checked out by this plugin.
=cut
sub canCheckoutCart {
my $self = shift;
my $cart = $self->getCart;
return 0 unless $cart->readyForCheckout;
return 0 if $cart->requiresRecurringPayment;
return 1;
}
#-------------------------------------------------------------------
# Recurring TX stuff removed, for now.
#-------------------------------------------------------------------
sub definition {
my $class = shift;
my $session = shift;
WebGUI::Error::InvalidParam->throw( error => q{Must provide a session variable} )
unless ref $session eq 'WebGUI::Session';
my $definition = shift;
my $i18n = WebGUI::International->new( $session, 'PayDriver_PayPalStd' );
tie my %fields, 'Tie::IxHash';
%fields = (
vendorId => {
fieldType => 'text',
label => $i18n->get('vendorId'),
hoverHelp => $i18n->get('vendorId help'),
},
signature => {
fieldType => 'textarea',
label => $i18n->get('signature'),
hoverHelp => $i18n->get('signature help'),
},
currency => {
fieldType => 'selectBox',
label => $i18n->get('currency'),
hoverHelp => $i18n->get('currency help'),
defaultValue => 'USD',
options => $class->getPaymentCurrencies(),
},
useSandbox => {
fieldType => 'yesNo',
label => $i18n->get('use sandbox'),
hoverHelp => $i18n->get('use sandbox help'),
defaultValue => 1,
},
buttonImage => {
fieldType => 'text',
label => $i18n->get('button image'),
hoverHelp => $i18n->get('button image help'),
defaultValue => '',
},
emailMessage => {
fieldType => 'textarea',
label => $i18n->get('emailMessage'),
hoverHelp => $i18n->get('emailMessage help'),
},
);
push @{$definition},
{
name => $i18n->get('PayPal'),
properties => \%fields,
};
return $class->SUPER::definition( $session, $definition );
}
#-------------------------------------------------------------------
=head2 getButton
Extends the base class to add a user configurable button image.
=cut
sub getButton {
my $self = shift;
my $session = $self->session;
my $i18n = WebGUI::International->new( $session, 'PayDriver_PayPalStd' );
my $payForm = WebGUI::Form::formHeader($session) . $self->getDoFormTags('pay');
if ( $self->get('buttonImage') ) {
my $button = $self->get('buttonImage');
WebGUI::Macro::process( $session, \$button );
$payForm
.= '<input type="image" src="'
. $button
. '" border="0" name="submit" alt="'
. $i18n->get('PayPal') . '"> ';
}
else {
$payForm .= WebGUI::Form::submit( $session, { value => $i18n->get('PayPal') } );
}
$payForm .= WebGUI::Form::formFooter($session);
return $payForm;
}
#-------------------------------------------------------------------
=head2 processTransaction ( [ paymentAddress ] )
This method is responsible for handling success or failure from the payment processor, completing or denying the transaction, and sending out notification and receipt emails. Returns a WebGUI::Shop::Transaction object.
This method is overridden from the parent class to allow asynchronous completion / denial of PayPal payments.
=head3 paymentAddress
A reference to a WebGUI::Shop::Address object that should be attached as payment information. Not required.
=cut
sub processTransaction {
my ( $self, $paymentAddress ) = @_;
my $cart = $self->getCart;
# Setup tranasction properties
my $transactionProperties;
$transactionProperties->{paymentMethod} = $self;
$transactionProperties->{cart} = $cart;
$transactionProperties->{paymentAddress} = $paymentAddress if defined $paymentAddress;
$transactionProperties->{isRecurring} = $cart->requiresRecurringPayment;
# Create a transaction...
my $transaction = WebGUI::Shop::Transaction->create( $self->session, $transactionProperties );
# And handle the payment for it
my $session = $self->session;
my $config = $session->config;
my $f = WebGUI::HTMLForm->new(
$session,
action => ( $self->get('useSandbox') ? $self->getPayPalSandboxUrl() : $self->getPayPalUrl() ),
extras => 'name="paypal_form"'
);
$f->hidden( name => 'business', value => $self->get('vendorId') );
$f->hidden( name => 'cmd', value => '_cart' );
$f->hidden( name => 'site_url', value => $session->setting->get("companyURL") );
$f->hidden( name => 'image_url', value => '' );
$f->hidden(
name => 'return',
value =>
$session->url->page( "shop=pay;method=do;do=completeTransaction;paymentGatewayId=" . $self->getId, 1 )
); ## PayPal says OK for now
$f->hidden(
name => 'cancel_return',
value =>
$session->url->page( "shop=pay;method=do;do=cancelTransaction;paymentGatewayId=" . $self->getId, 1 )
); ## Error / user cancel
# $f->hidden(name=>'notify_url', value=>$session->url->page("shop=pay;method=do;do=IPNnotifyTransaction;paymentGatewayId=".$self->getId, 1));
$f->hidden( name => 'notify_url', value => '' ); ##no IPN for now, get OK from PDT auto-return
$f->hidden( name => 'rm', value => '2' ); ## use POST
$f->hidden( name => 'currency_code', value => $self->get('currency') );
$f->hidden( name => 'lc', value => 'US' );
$f->hidden( name => 'bn', value => 'toolkit-perl' );
$f->hidden( name => 'cbt', value => 'Continue >>' );
# <!-- Payment Page Information -->
$f->hidden( name => 'no_shipping', value => '1' ); # do not display shipping addr
$f->hidden( name => 'no_note', value => '0' );
$f->hidden( name => 'cn', value => 'Comments' );
$f->hidden( name => 'cs', value => '' );
# <!-- Cart Information -->
# does not get used for uploaded carts
$f->hidden( name => 'item_name', value => 'WebGUI cart' );
$f->hidden(
name => 'amount',
value => $transaction->get('amount') - $transaction->get('taxes') - $transaction->get('shippingPrice')
);
# <!-- Product Information for each item in our cart -->
$f->hidden( name => 'upload', value => '1' );
my $itemList = $transaction->getItems;
my $itemNum = 0;
foreach my $item ( @{$itemList} ) {
# items numbered 1++
$itemNum++;
# glue item number to WebGUI itemId
$f->hidden( name => 'item_number_' . $itemNum, value => $item->get('itemId') );
$f->hidden( name => 'item_name_' . $itemNum, value => $item->get('configuredTitle') );
$f->hidden( name => 'quantity_' . $itemNum, value => $item->get('quantity') );
$f->hidden( name => 'amount_' . $itemNum, value => $item->get('price') );
}
# <!-- Shipping and Misc Information -->
$f->hidden( name => 'shipping', value => $transaction->get('shippingPrice') );
$f->hidden( name => 'shipping2', value => '' ); # no individual shipping
$f->hidden( name => 'handling_cart', value => '0.00' ); # no separate handling
$f->hidden( name => 'tax_cart', value => $transaction->get('taxes') ); # no separate taxes
$f->hidden( name => 'custom', value => '' );
$f->hidden( name => 'invoice', value => $transaction->getId )
; # need to identify OUR TX so we can update it later
# <!-- Customer Information -->
$f->hidden( name => 'address_override', value => 1 );
$f->hidden(
name => 'first_name',
value => substr(
$transaction->get('shippingAddressName'), 0,
rindex( $transaction->get('shippingAddressName'), ' ' )
)
);
$f->hidden(
name => 'last_name',
value => substr(
$transaction->get('shippingAddressName'),
rindex( $transaction->get('shippingAddressName'), ' ' ) + 1
)
);
$f->hidden( name => 'address1', value => $transaction->get('shippingAddress1') );
$f->hidden( name => 'address2', value => $transaction->get('shippingAddress2') );
$f->hidden( name => 'city', value => $transaction->get('shippingCity') );
$f->hidden( name => 'state', value => $transaction->get('shippingState') );
$f->hidden( name => 'zip', value => $transaction->get('shippingCode') );
$f->hidden( name => 'country', value => $self->getPaypalCountry( $transaction->get('shippingCountry') ) );
if ( $session->user->profileField('email') ) {
$f->hidden( name => 'email', value => $session->user->profileField('email') );
}
$f->hidden( name => 'night_phone_a', value => $transaction->get('shippingPhoneNumber') );
$f->hidden( name => 'night_phone_b', value => '' );
$f->hidden( name => 'night_phone_c', value => '' );
return
$f->print
. '<center><font face="Verdana, Arial, Helvetica, sans-serif" size="2">Processing Transaction . . . </font></center>'
. '<script>document.paypal_form.submit();</script>';
}
#-------------------------------------------------------------------
=head2 www_cancelTransaction
Cancels the transaction defined by the C<invoice> form variable.
=cut
sub www_cancelTransaction {
my $self = shift;
my $session = $self->session;
my %pdt;
my $retstr = '';
foreach my $input_name ( $self->session->request->param ) {
$pdt{$input_name} = $self->session->request->param($input_name);
$retstr .= $input_name . ":" . $self->session->request->param($input_name) . "<br />";
}
my $transaction = eval { WebGUI::Shop::Transaction->newByGatewayId( $session, $pdt{invoice}, $self->getId ) };
# First check whether the original transaction actualy exists
if ( WebGUI::Error->caught || !( defined $transaction ) ) {
$session->errorHandler->warn("PayPal Standard: No transaction ID: $pdt{invoice}");
return;
}
$transaction->denyPurchase( $pdt{invoice}, 0, $pdt{payment_status} );
return $self->displayPaymentError($transaction);
}
#-------------------------------------------------------------------
=head2 www_completeTransaction
Finishes the transaction for this driver.
=cut
sub www_completeTransaction {
my $self = shift;
my $session = $self->session;
my $paypal_url;
my %paypal; ## return variables from PDT
## find TX key from PayPal PDT
my $tx = $self->session->form->get("tx");
if ($tx) {
# found a tx, re-present it for all the TX details
$paypal_url = $self->get('useSandbox') ? $self->getPayPalSandboxUrl() : $self->getPayPalUrl();
my $query = join( "&", "cmd=_notify-synch", "tx=" . $tx, "at=" . $self->get('signature') );
my $user_agent = new LWP::UserAgent;
my $request = new HTTP::Request( "POST", $paypal_url );
$request->content_type("application/x-www-form-urlencoded");
$request->content($query);
# Make the request
my $result = $user_agent->request($request);
if ( $result->is_error ) {
$session->errorHandler->warn("PayPal Standard: PayPal server seems offline.");
return;
}
# Decode the response into individual lines and unescape any HTML escapes
my @response = split( "\n", $self->session->url->unescape( $result->content ) );
# The status is always the first line of the response.
my $status = shift @response;
foreach my $response_line (@response) {
my ( $key, $value ) = split "=", $response_line;
$paypal{$key} = $value;
}
my $transaction = eval { WebGUI::Shop::Transaction->new( $session, $paypal{invoice} ) };
# First check whether the original transaction actualy exists
if ( WebGUI::Error->caught || !( defined $transaction ) ) {
$session->errorHandler->warn(
"PayPal Standard: No WebGUI transaction ID: $paypal{invoice}," . $self->getId );
return;
}
if ( $status eq "SUCCESS" ) {
$transaction->completePurchase( $paypal{invoice}, 1, $paypal{payment_status} );
my $cart = $self->getCart;
$cart->onCompletePurchase;
$self->sendNotifications($transaction);
}
elsif ( $status eq "FAIL" ) {
$transaction->denyPurchase( $paypal{invoice}, 0, $paypal{payment_status} );
}
if ( $transaction->get('isSuccessful') ) {
return $transaction->thankYou();
}
else {
return $self->displayPaymentError($transaction);
}
}
else { ## no tx from paypal
$session->errorHandler->warn("PayPal Standard: No transaction ID");
}
}
#-------------------------------------------------------------------
=head2 www_edit ( )
Generates an edit form.
=cut
sub www_edit {
my $self = shift;
my $session = $self->session;
my $admin = WebGUI::Shop::Admin->new($session);
my $i18n = WebGUI::International->new( $session, 'PayDriver_PayPalStd' );
return $session->privilege->insufficient() unless $admin->canManage;
my $form = $self->getEditForm;
$form->submit;
# adds instructions for IPN etc.
my $output = '<br />';
$output
.= $i18n->get('extra info')
. '<br /><br />'
. '<b>https://'
. $session->config->get("sitename")->[0]
. '/?shop=pay;method=do;do=completeTransaction;paymentGatewayId='
. $self->getId . '</b>';
return $admin->getAdminConsole->render( $form->print . $output, $i18n->get( 'payment methods', 'PayDriver' ) );
}
#-------------------------------------------------------------------
=head2 www_pay
Web facing wrapper method for C<processTransaction>.
=cut
sub www_pay {
my $self = shift;
my $session = $self->session;
# Payment time!
return $self->processTransaction();
}
1;

View file

@ -0,0 +1,95 @@
package WebGUI::i18n::English::PayDriver_PayPal;
use strict;
our $I18N = {
'api' => {
message => q{API URL},
lastUpdated => 1247254043,
},
'api error' => {
message => q{Error communicating with PayPal API: %s},
lastUpdated => 1247496228,
context => q{Error message to display on internal error talking to paypal},
},
'api help' => {
message => q{Base URL for PayPal's NVP api},
lastUpdated => 1247254068,
},
'apiSandbox' => {
message => q{API Sandbox URL},
lastUpdated => 1247499398,
},
'apiSandbox help' => {
message => q{URL for Paypal API in test mode},
lastUpdated => 1247499415,
},
'currency' => {
message => q{Currency Code},
lastUpdated => 1247253894,
},
'currency help' => {
message => q{Paypal currency code to use (e.g. USD)},
lastUpdated => 1247253924,
},
'label' => {
message => q{NewPal},
lastUpdated => 1247256659,
},
'name' => {
message => q{NewPal},
lastUpdated => 1247256412,
},
'password' => {
message => q{Password},
lastUpdated => 1247254156,
},
'password help' => {
message => q{Password from PayPal credentials},
lastUpdated => 1247254172,
},
'paypal' => {
message => q{Paypal URL},
lastUpdated => 1247498678,
},
'paypal help' => {
message => q{URL to use when redirecting to paypal},
lastUpdated => 1247498700,
},
'sandbox' => {
message => q{Sandbox URL},
lastUpdated => 1247498780,
},
'sandbox help' => {
message => q{URL to use for redirecting to paypal in test mode},
lastUpdated => 1247498766,
},
'signature' => {
message => q{Signature},
lastUpdated => 1247254180,
},
'signature help' => {
message => q{Signature from PayPal credentials},
lastUpdated => 1247254195,
},
'testMode' => {
message => q{Test Mode},
lastUpdated => 1247253942,
},
'testMode help' => {
message => q{Whether to use PayPal's sandbox},
lastUpdated => 1247253981,
},
'user' => {
message => q{Username},
lastUpdated => 1247254097,
},
'user help' => {
message => q{Username from Paypal credentials},
lastUpdated => 1247254128,
},
};
1;
#vim:ft=perl

View file

@ -1,176 +0,0 @@
package WebGUI::i18n::English::PayDriver_PayPalStd;
=head1 LEGAL
-------------------------------------------------------------------
PayPal Standard payment driver for WebGUI.
Copyright (C) 2009 Invicta Services, LLC.
-------------------------------------------------------------------
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-------------------------------------------------------------------
=cut
use strict;
our $I18N = {
'error occurred message' => {
message => q|The following errors occurred:|,
lastUpdated => 0,
context => q|The message that tell the user that there were some errors in their submitted credentials.|,
},
'PayPal' => {
message => q|PayPal|,
lastUpdated => 0,
context => q|The name of the PayPal Website Payments Standard plugin|,
},
'label' => {
message => q|PayPal|,
lastUpdated => 0,
context => q|Default PayPal payment gateway label|
},
'vendorId' => {
message => q|PayPal Account|,
lastUpdated => 0,
context => q|Form label in the configuration form of the PayPal module.|
},
'vendorId help' => {
message => q|Fill in the email address that identifies your PayPal account.|,
lastUpdated => 0,
context => q|Hover help for vendor id in the configuration form of the PayPal module.|
},
'emailMessage' => {
message => q|Email message|,
lastUpdated => 0,
context => q|Form label in the configuration form of the PayPal module.|
},
'emailMessage help' => {
message => q|The message that will be appended to the email user will receive from PayPal.|,
lastUpdated => 0,
context => q|Hover help for the email message field in the configuration form of the PayPal module.|
},
'password' => {
message => q|Password|,
lastUpdated => 0,
context => q|Form label in the configuration form of the PayPal module.|
},
'password help' => {
message => q|The password for your PayPal account.|,
lastUpdated => 0,
context => q|Hover help for the password field in the configuration form of the PayPal module.|
},
'signature' => {
message => q|Signature|,
lastUpdated => 0,
context => q|Form label in the configuration form of the PayPal module.|
},
'signature help' => {
message => q|The account signature for your PayPal account.|,
lastUpdated => 0,
context => q|Hover help for the signature field in the configuration form of the PayPal module.|
},
'currency' => {
message => q|Currency|,
lastUpdated => 0,
context => q|Form label in the configuration form of the PayPal module.|
},
'currency help' => {
message => q|The currency for your transactions with your PayPal account.|,
lastUpdated => 0,
context => q|Hover help for the signature field in the configuration form of the PayPal module.|
},
'use sandbox' => {
message => q|Use Sandbox|,
lastUpdated => 0,
context => q|Form label in the configuration form of the PayPal module.|
},
'use sandbox help' => {
message =>
q|Set this option to yes if you want to use the PayPal SANDBOX development (i.e. NOT production) environment. Recommended for testing.|,
lastUpdated => 0,
context => q|Form label in the configuration form of the PayPal module.|
},
'button image' => {
message => q|PayPal Button image URL|,
lastUpdated => 1241986933,
context => q|Form label in the configuration form of the PayPal module.|
},
'button image help' => {
message => q|Set this option to use PayPal images for checkout buttons.|,
lastUpdated => 1241986933,
context => q|Form label in the configuration form of the PayPal module.|
},
'module name' => {
message => q|PayPal|,
lastUpdated => 0,
context => q|The displayed name of the payment module.|
},
'invalid firstName' => {
message => q|You have to enter a valid first name.|,
lastUpdated => 0,
context => q|An error indicating that an invalid first name has been entered.|
},
'invalid lastName' => {
message => q|You have to enter a valid last name.|,
lastUpdated => 0,
context => q|An error indicating that an invalid last name has been entered.|
},
'invalid address' => {
message => q|You have to enter a valid address.|,
lastUpdated => 0,
context => q|An error indicating that an invalid street has been entered.|
},
'invalid city' => {
message => q|You have to enter a valid city.|,
lastUpdated => 0,
context => q|An error indicating that an invalid city has been entered.|
},
'invalid zip' => {
message => q|You have to enter a valid zipcode.|,
lastUpdated => 0,
context => q|An error indicating that an invalid zipcode has been entered.|
},
'invalid email' => {
message => q|You have to enter a valid email address.|,
lastUpdated => 0,
context => q|An error indicating that an invalid email address has been entered.|
},
'PayPal' => {
message => q|PayPal|,
lastUpdated => 0,
context => q|Name of the gateway from the definition|
},
'no description' => {
message => q|No description|,
lastUpdated => 0,
context => q|The default description of purchase of users.|
},
'extra info' => {
message =>
q|Remember to set both &quot;Payment Data Transfer&quot; and &quot;Auto Return&quot; <b>ON</b> in the <a href="https://www.paypal.com/us/cgi-bin/webscr?cmd=_profile-website-payments">Website Payments</a> section of your PayPal Profile.<br />
Additionally, set the &quot;Return URL&quot; to:|,
lastUpdated => 1245364211,
context => q|An informational message that's shown in the configuration form of this plugin.|
},
};
1;