Merge commit 'v7.10.17' into 8
Conflicts: docs/upgrades/upgrade_7.9.13-7.10.0.pl lib/WebGUI.pm lib/WebGUI/Asset/Template/TemplateToolkit.pm lib/WebGUI/Asset/Wobject/AssetReport.pm lib/WebGUI/Asset/Wobject/Thingy.pm lib/WebGUI/Form/Captcha.pm lib/WebGUI/Macro/AdminBar.pm lib/WebGUI/Shop/Cart.pm lib/WebGUI/Shop/PayDriver.pm lib/WebGUI/Shop/PayDriver/PayPal/ExpressCheckout.pm lib/WebGUI/Shop/PayDriver/PayPal/PayPalStd.pm lib/WebGUI/Shop/Transaction.pm lib/WebGUI/Workflow/Instance.pm lib/WebGUI/Workflow/Spectre.pm lib/WebGUI/i18n/English/PayDriver.pm t/Asset/Asset.t t/Asset/AssetExportHtml.t t/Asset/AssetLineage.t t/Asset/Wobject/Thingy.t
This commit is contained in:
commit
795d88e7e5
69 changed files with 972 additions and 170 deletions
|
|
@ -986,7 +986,7 @@ sub www_checkout {
|
|||
my $total = $self->calculateTotal;
|
||||
##Handle rounding errors, and checkout immediately if the amount is 0 since
|
||||
##at least the ITransact driver won't accept $0 checkout.
|
||||
if (sprintf('%.2f', $total + $self->calculateShopCreditDeduction($total)) eq '0.00') {
|
||||
if (sprintf('%.2f', abs($total + $self->calculateShopCreditDeduction($total))) eq '0.00') {
|
||||
my $transaction = WebGUI::Shop::Transaction->new({session => $session, cart => $self});
|
||||
$transaction->write;
|
||||
$transaction->completePurchase('zero', 'success', 'success');
|
||||
|
|
@ -1032,9 +1032,6 @@ sub www_lookupPosUser {
|
|||
Updates the cart totals, addresses, shipping driver and payment gateway. If requested, and the
|
||||
cart is ready, calls the www_getCredentials method from the selected payment gateway.
|
||||
|
||||
If the cart total, after taxes, shipping, coupons and shop credit is zero, does the checkout
|
||||
immediately without calling a payment gateway.
|
||||
|
||||
Otherwise, returns the user back to the cart.
|
||||
|
||||
=cut
|
||||
|
|
|
|||
|
|
@ -129,8 +129,13 @@ around BUILDARGS => sub {
|
|||
|
||||
=head2 appendCartVariables ( $var )
|
||||
|
||||
Append the subtotal, shipping, tax, and shop credeductions to a set of template
|
||||
variables.
|
||||
Append the subtotal, shipping, tax, and shop credit deductions to a set of template
|
||||
variables. Returns the modified hashreference of variables.
|
||||
|
||||
=head3 $var
|
||||
|
||||
A hashref. Template variables will be added to it. If $var is not passed, a new
|
||||
hashref is created, and that is returned.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -148,7 +153,7 @@ sub appendCartVariables {
|
|||
$var->{inShopCreditAvailable} = $credit->getSum;
|
||||
$var->{inShopCreditDeduction} = $credit->calculateDeduction($totalPrice);
|
||||
$var->{totalPrice } = $cart->formatCurrency($totalPrice + $var->{inShopCreditDeduction});
|
||||
return $self;
|
||||
return $var;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -259,10 +264,14 @@ sub displayPaymentError {
|
|||
my ($self, $transaction) = @_;
|
||||
my $i18n = WebGUI::International->new($self->session, "PayDriver");
|
||||
my $output = q{<h1>} . $i18n->get('error processing payment') . q{</h1>}
|
||||
. q{<p>} . $i18n->get('error processing payment message') . q{</p>}
|
||||
. q{<p>} . $transaction->get('statusMessage') . q{</p>}
|
||||
. q{<p><a href="?shop=cart;method=checkout">} . $i18n->get( 'try again' ) . q{</a></p>}
|
||||
;
|
||||
. q{<p>} . $i18n->get('error processing payment message') . q{</p>};
|
||||
if ($transaction) {
|
||||
$output .= q{<p>} . $transaction->get('statusMessage') . q{</p>};
|
||||
}
|
||||
else {
|
||||
$output .= q{<p>} . $i18n->get('unable to finish transaction') . q{</p>};
|
||||
}
|
||||
$output .= q{<p><a href="?shop=cart;method=checkout">} . $i18n->get( 'try again' ) . q{</a></p>};
|
||||
return $self->session->style->userStyle($output);
|
||||
}
|
||||
|
||||
|
|
@ -540,7 +549,7 @@ sub processTransaction {
|
|||
$transactionProperties->{ cart } = $cart;
|
||||
$transactionProperties->{ isRecurring } = $cart->requiresRecurringPayment;
|
||||
$transactionProperties->{ session } = $self->session;
|
||||
|
||||
|
||||
# Create a transaction...
|
||||
$transaction = WebGUI::Shop::Transaction->new( $transactionProperties );
|
||||
$transaction->write;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ sub processPayment {
|
|||
my $self = shift;
|
||||
# Since we'll have to create a transaction before doing the actual tranasction, we let it fail
|
||||
# initially with a message that it is pending.
|
||||
# Unless the transaction result with _setPaymentStatus the transaction will fail.
|
||||
# Unless the transaction result is updated via _setPaymentStatus the transaction will fail.
|
||||
|
||||
my $success = $self->{_transactionSuccessful} || 0;
|
||||
my $id = $self->{_ogoneId} || undef;
|
||||
|
|
@ -129,7 +129,6 @@ sub processPayment {
|
|||
my $message = $self->{_statusMessage} || 'Waiting for checkout';
|
||||
|
||||
return ( $success, $id, $status, $message );
|
||||
return (0, undef, 1, 'Pending');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ is a hashref, it will be modified in place.
|
|||
sub payPalForm {
|
||||
my $self = shift;
|
||||
my $args = ref $_[0] eq 'HASH' ? shift : {@_};
|
||||
$args->{VERSION} = '58.0';
|
||||
$args->{VERSION} = '2.3';
|
||||
$args->{USER} = $self->user;
|
||||
$args->{PWD} = $self->password;
|
||||
$args->{SIGNATURE} = $self->signature;
|
||||
|
|
@ -206,7 +206,6 @@ PayPal API spit back.
|
|||
|
||||
sub processPayment {
|
||||
my ( $self, $transaction ) = @_;
|
||||
my ( $isSuccess, $gatewayCode, $status, $message );
|
||||
|
||||
my $form = $self->payPalForm(
|
||||
METHOD => 'DoExpressCheckoutPayment',
|
||||
|
|
@ -317,6 +316,7 @@ sub www_sendToPayPal {
|
|||
if ($params) {
|
||||
unless ( $params->{ACK} =~ /^Success/ ) {
|
||||
my $log = sprintf "Paypal error: Request/response below: %s\n%s\n", Dumper($form), Dumper($params);
|
||||
$log .= $response->request->as_string;
|
||||
$session->log->error($log);
|
||||
$error = $i18n->get('internal paypal error');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ use URI;
|
|||
use URI::Escape;
|
||||
use LWP::UserAgent;
|
||||
use Readonly;
|
||||
use WebGUI::Shop::Transaction;
|
||||
|
||||
Readonly my $I18N => 'PayDriver_PayPalStd';
|
||||
|
||||
use Moose;
|
||||
|
|
@ -145,7 +147,9 @@ sub getButton {
|
|||
|
||||
# All the API stuff is done in paymentVariables; we'll just turn it into
|
||||
# hidden form fields here
|
||||
my $v = $self->paymentVariables;
|
||||
my $v = $self->paymentVariables;
|
||||
my $transaction = $self->processTransaction();
|
||||
$v->{custom} = $transaction->getId;
|
||||
my $fields = join "\n", map {
|
||||
WebGUI::Form::hidden( $session, { name => $_, value => $v->{$_} } )
|
||||
} (keys %$v);
|
||||
|
|
@ -177,6 +181,38 @@ sub getButton {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getPayPalParams
|
||||
|
||||
Using the tx form variable, dial up PayPal and ask them for details about the transaction.
|
||||
Return a hashreference of name/value pairs, along with PAYPAL_TX, the transactionId and
|
||||
PAYPAL_REQUEST_STATUS, the HTTP code from the response from PayPal.
|
||||
|
||||
=cut
|
||||
|
||||
sub getPayPalParams {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
# instead of relying on what was passed to us.
|
||||
return $self->{_params} if $self->{_params};
|
||||
my $tx = $session->form->process('tx');
|
||||
|
||||
my %form = (
|
||||
cmd => '_notify-synch',
|
||||
tx => $tx,
|
||||
at => $self->identityToken,
|
||||
);
|
||||
my $response = LWP::UserAgent->new->post($self->payPalUrl, \%form);
|
||||
my ($status, @lines) = split("\n", $response->content);
|
||||
my %params = map { split /=/ }
|
||||
map { uri_unescape($_) } @lines;
|
||||
$params{PAYPAL_REQUEST_STATUS} = $status;
|
||||
$params{PAYPAL_TX} = $tx;
|
||||
$self->{_params} = \%params;
|
||||
return $self->{_params};
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 paymentVariables
|
||||
|
||||
Returns a hashref of the payment variables to be used as hidden form fields
|
||||
|
|
@ -225,9 +261,9 @@ sub paymentVariables {
|
|||
foreach my $item (@{ $cart->getItems}) {
|
||||
my $n = ++$counter;
|
||||
$params{"amount_$n"} = $item->getSku->getPrice;
|
||||
$params{"quantity_$n"} = $item->get('quantity');
|
||||
$params{"item_name_$n"} = $item->get('configuredTitle');
|
||||
$params{"item_number_$n"} = $item->get('itemId');
|
||||
$params{"quantity_$n"} = $item->quantity;
|
||||
$params{"item_name_$n"} = $item->configuredTitle;
|
||||
$params{"item_number_$n"} = $item->itemId;
|
||||
}
|
||||
|
||||
return \%params;
|
||||
|
|
@ -258,49 +294,49 @@ passed to us.
|
|||
=cut
|
||||
|
||||
sub processPayment {
|
||||
my ( $self, $transaction ) = @_;
|
||||
my $session = $self->session;
|
||||
my ( $self ) = @_;
|
||||
|
||||
# To prevent a spoofed post to this url, we'll get the info from paypal
|
||||
# instead of relying on what was passed to us.
|
||||
my $tx = $session->form->process('tx');
|
||||
my $success = $self->{_transactionSuccessful} || 0;
|
||||
my $id = $self->{_tx} || undef;
|
||||
my $status = $self->{_statusCode} || undef;
|
||||
my $message = $self->{_statusMessage} || 'Waiting for checkout';
|
||||
|
||||
my %form = (
|
||||
cmd => '_notify-synch',
|
||||
tx => $tx,
|
||||
at => $self->identityToken,
|
||||
);
|
||||
my $response = LWP::UserAgent->new->post($self->payPalUrl, \%form);
|
||||
my ($status, @lines) = split("\n", $response->content);
|
||||
my %params = map { split /=/ }
|
||||
map { uri_unescape($_) } @lines;
|
||||
return ( $success, $id, $status, $message );
|
||||
}
|
||||
|
||||
if ($status =~ /FAIL/) {
|
||||
my $message = '<table><tr><th>Field</th><th>Value</th></tr>';
|
||||
foreach my $key ( keys %params ) {
|
||||
$message .= "<tr><td>$key</td><td>$params{$key}</td></tr>";
|
||||
}
|
||||
$message .= '</table>';
|
||||
return ( 0, $tx, $status, $message );
|
||||
}
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
# Make sure the transaction is for this cart to prevent spoofing
|
||||
my $cartId = $self->getCart->getId;
|
||||
if ($params{custom} ne $cartId) {
|
||||
my $user = $session->user;
|
||||
my $name = $user->username;
|
||||
my $id = $user->userId;
|
||||
$session->log->warn("SECURITY WARNING: $name (id: $id) tried to " .
|
||||
"checkout cart $cartId with PayPal transaction $tx, which " .
|
||||
"did not match the cart we passed ($params{custom})");
|
||||
=head2 _setPaymentStatus ( transactionSuccessful, ogoneId, statusCode, statusMessage )
|
||||
|
||||
my $i18n = WebGUI::International->new( $session, $I18N );
|
||||
return ( 0, $tx, 'FAIL', $i18n->get('cart transaction mismatch') );
|
||||
}
|
||||
Update the internal status of a payment, so that the next call to processPayment
|
||||
returns the correct data.
|
||||
|
||||
$status = $params{payment_status};
|
||||
return ( 1, $tx, $status, $status, $status );
|
||||
} ## end sub processPayment
|
||||
=head3 transactionSuccessful
|
||||
|
||||
A boolean indicating whether or not the payment was successful.
|
||||
|
||||
=head3 tx
|
||||
|
||||
The PayPal issued transaction ID.
|
||||
|
||||
=head3 statusCode
|
||||
|
||||
The PayPal issued status code.
|
||||
|
||||
=head3 statusMessage
|
||||
|
||||
An updates status message
|
||||
|
||||
=cut
|
||||
|
||||
sub _setPaymentStatus {
|
||||
my ( $self ) = @_;
|
||||
|
||||
$self->{_transactionSuccessful} = shift || 0;
|
||||
$self->{_tx} = shift || undef;
|
||||
$self->{_statusCode} = shift || undef;
|
||||
$self->{_statusMessage} = shift || undef;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -311,11 +347,26 @@ Where paypal comes back to when a transaction has been completed.
|
|||
=cut
|
||||
|
||||
sub www_completeTransaction {
|
||||
my $self = shift;
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
|
||||
my $transaction = $self->processTransaction;
|
||||
my $params = $self->getPayPalParams;
|
||||
if ($params->{PAYPAL_REQUEST_STATUS} =~ /FAIL/) {
|
||||
my $message = "<table><tr><th>Field</th><th>Value</th></tr>\n";
|
||||
foreach my $key ( keys %{ $params } ) {
|
||||
$message .= sprintf "<tr><td>%s</td><td>%s</td></tr>\n", $key, $params->{key};
|
||||
}
|
||||
$message .= "</table>\n";
|
||||
return ( 0, $params->{PAYPAL_TX}, $params->{PAYPAL_REQUEST_STATUS}, $message );
|
||||
}
|
||||
my $transaction = eval { WebGUI::Shop::Transaction->new($session, $params->{custom}); };
|
||||
if (my $e = Exception::Class->caught) {
|
||||
return $self->displayPaymentError();
|
||||
}
|
||||
$self->_setPaymentStatus(1, $params->{PAYPAL_TX}, $params->{payment_status}, 'Complete');
|
||||
$self->processTransaction($transaction);
|
||||
|
||||
return $transaction->get('isSuccessful')
|
||||
return $transaction->isSuccessful
|
||||
? $transaction->thankYou
|
||||
: $self->displayPaymentError($transaction);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -293,10 +293,16 @@ sub _mine_cart {
|
|||
$self->paymentDriverId($pay->getId);
|
||||
$self->paymentDriverLabel($pay->get('label'));
|
||||
|
||||
##Clear out current transaction items before adding new ones.
|
||||
foreach my $item (@{$self->getItems}) {
|
||||
$item->delete;
|
||||
}
|
||||
foreach my $item (@{$cart->getItems}) {
|
||||
$self->addItem({item=>$item});
|
||||
}
|
||||
|
||||
$self->isRecurring( $cart->requiresRecurringPayment );
|
||||
|
||||
$self->cashierUserId($cart->getPosUser->userId);
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue