diff --git a/lib/WebGUI/Shop/PayDriver/PayPal.pm b/lib/WebGUI/Shop/PayDriver/PayPal.pm index 57d1cd561..b4ae8480b 100644 --- a/lib/WebGUI/Shop/PayDriver/PayPal.pm +++ b/lib/WebGUI/Shop/PayDriver/PayPal.pm @@ -1,363 +1,259 @@ 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; -=head1 NAME +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; -WebGUI::Shop::PayDriver::PayPal +Readonly my $I18N => 'PayDriver_PayPal'; -=head1 DESCRIPTION +#------------------------------------------------------------------- -Super class for PayPal payment drivers +=head2 apiUrl -=head1 METHODS - -These methods are available from this class: +Returns the URL for the PayPal API (or the sandbox, if we are configured to +use the sandbox) =cut -=head2 getPayPalSandboxUrl - -Returns the URL for the PayPal 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 +#------------------------------------------------------------------- +sub definition { + my ( $class, $session, $definition ) = @_; + my $i18n = WebGUI::International->new( $session, $I18N ); -Returns the URL for PayPal. - -=cut - -sub getPayPalUrl { - return ('https://www.paypal.com/cgi-bin/webscr'); -} - -=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 ); + + foreach my $f (@fieldNames) { + $fields{$f} = { + fieldType => 'text', + label => $i18n->get($f), + hoverHelp => $i18n->get("$f help"), + }; + } + + $fields{currency}{defaultValue} = 'USD'; + + $fields{testMode}{fieldType} = 'YesNo'; + + $fields{sandbox}{defaultValue} = 'https://www.sandbox.paypal.com/webscr'; + $fields{apiSandbox}{defaultValue} = 'https://api-3t.sandbox.payPal.com/nvp'; + + $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 + +#------------------------------------------------------------------- + +sub getButton { + my $self = shift; + my $session = $self->session; + + my $payForm + = WebGUI::Form::formHeader($session) + . $self->getDoFormTags('sendToPayPal') + . WebGUI::Form::submit( $session, { value => $self->get('label') } ) + . WebGUI::Form::formFooter($session); + + return $payForm; } -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" -); +#------------------------------------------------------------------- -=head2 getPaypalCountry ( $country ) +=head2 payPalForm ( %fields ) -Accepts a country name and returns the country code for it. - -=head3 $country - -The country to find the code for. +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 getPaypalCountry { - my $self = shift; - my $longCountry = shift; +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'); - my $retcode = $paypalCountries{ uc $longCountry }; - return $retcode; + return $args; } +#------------------------------------------------------------------- + +=head2 papPalUrl + +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' ); +} + +#------------------------------------------------------------------- + +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 = ''; + foreach my $k ( keys %$params ) { + $message .= ""; + } + $message .= '
FieldValue
$k$params->{$k}
'; + 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 + 1; diff --git a/lib/WebGUI/Shop/PayDriver/PayPal/PayPalStd.pm b/lib/WebGUI/Shop/PayDriver/PayPal/PayPalStd.pm deleted file mode 100644 index a37f6946c..000000000 --- a/lib/WebGUI/Shop/PayDriver/PayPal/PayPalStd.pm +++ /dev/null @@ -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 - .= ' '; - } - 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 >>' ); - - # - $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 => '' ); - - # - # 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') - ); - - # - $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') ); - } - - # - $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 - - # - $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 - . '
Processing Transaction . . .
' - . ''; - -} - -#------------------------------------------------------------------- - -=head2 www_cancelTransaction - -Cancels the transaction defined by the C 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) . "
"; - } - - 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 = '
'; - $output - .= $i18n->get('extra info') - . '

' - . 'https://' - . $session->config->get("sitename")->[0] - . '/?shop=pay;method=do;do=completeTransaction;paymentGatewayId=' - . $self->getId . ''; - - return $admin->getAdminConsole->render( $form->print . $output, $i18n->get( 'payment methods', 'PayDriver' ) ); -} - -#------------------------------------------------------------------- - -=head2 www_pay - -Web facing wrapper method for C. - -=cut - -sub www_pay { - my $self = shift; - my $session = $self->session; - - # Payment time! - return $self->processTransaction(); -} - -1; - diff --git a/lib/WebGUI/i18n/English/PayDriver_PayPal.pm b/lib/WebGUI/i18n/English/PayDriver_PayPal.pm new file mode 100644 index 000000000..7535233c8 --- /dev/null +++ b/lib/WebGUI/i18n/English/PayDriver_PayPal.pm @@ -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 diff --git a/lib/WebGUI/i18n/English/PayDriver_PayPalStd.pm b/lib/WebGUI/i18n/English/PayDriver_PayPalStd.pm deleted file mode 100644 index b8eba0f47..000000000 --- a/lib/WebGUI/i18n/English/PayDriver_PayPalStd.pm +++ /dev/null @@ -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 "Payment Data Transfer" and "Auto Return" ON in the Website Payments section of your PayPal Profile.
-Additionally, set the "Return URL" to:|, - lastUpdated => 1245364211, - context => q|An informational message that's shown in the configuration form of this plugin.| - }, -}; - -1; -