Files
domokits/local/modules/Paypal/Controller/PaypalResponse.php
2019-11-21 12:25:31 +01:00

254 lines
10 KiB
PHP

<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* 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 3 of the License */
/* */
/* 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, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Paypal\Controller;
use Paypal\Classes\API\PaypalApiCredentials;
use Paypal\Classes\API\PaypalApiLogManager;
use Paypal\Classes\API\PaypalApiManager;
use Paypal\Classes\NVP\Operations\PaypalNvpOperationsDoExpressCheckoutPayment;
use Paypal\Classes\NVP\Operations\PaypalNvpOperationsGetExpressCheckoutDetails;
use Paypal\Classes\NVP\PaypalNvpMessageSender;
use Paypal\Paypal;
use Thelia\Core\Event\Order\OrderEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpKernel\Exception\RedirectException;
use Thelia\Model\Base\OrderQuery;
use Thelia\Model\OrderStatus;
use Thelia\Model\OrderStatusQuery;
use Thelia\Module\BasePaymentModuleController;
use Thelia\Tools\URL;
/**
* Class PaypalResponse
* @package Paypal\Controller
* @author Thelia <info@thelia.net>
*/
class PaypalResponse extends BasePaymentModuleController
{
/** @var PaypalApiLogManager */
private $logger;
public function __construct()
{
$this->logger = new PaypalApiLogManager();
}
/**
* @param $order_id
* @return \Thelia\Core\HttpFoundation\Response
*/
public function ok($order_id)
{
$token = null;
$message = '';
try {
$order = $this->checkorder($order_id, $token);
/*
* $payerid string value returned by paypal
* $logger PaypalApiLogManager used to log transctions with paypal
*/
$payerid = $this->getRequest()->get('PayerID');
if (! empty($payerid)) {
/*
* $config ConfigInterface Object that contains configuration
* $api PaypalApiCredentials Class used by the library to store and use 3T login(username, password, signature)
* $sandbox bool true if sandbox is enabled
*/
$api = new PaypalApiCredentials();
$sandbox = Paypal::isSandboxMode();
/*
* Send getExpressCheckout & doExpressCheckout
* empty cart
*/
$getExpressCheckout = new PaypalNvpOperationsGetExpressCheckoutDetails(
$api,
$token
);
$request = new PaypalNvpMessageSender($getExpressCheckout, $sandbox);
$response = PaypalApiManager::nvpToArray($request->send());
$this->logger->logTransaction($response);
if (isset($response['ACK']) && $response['ACK'] === 'Success' &&
isset($response['PAYERID']) && $response['PAYERID'] === $payerid &&
isset($response['TOKEN']) && $response['TOKEN'] === $token
) {
$doExpressCheckout = new PaypalNvpOperationsDoExpressCheckoutPayment(
$api,
round($order->getTotalAmount(), 2),
$order->getCurrency()->getCode(),
$payerid,
PaypalApiManager::PAYMENT_TYPE_SALE,
$token,
// FIXME This URL is not used in PaypalNvpOperationsDoExpressCheckoutPayment, and has no defined route
URL::getInstance()->absoluteUrl("/module/paypal/listen"),
PaypalApiManager::BUTTON_SOURCE
);
$request = new PaypalNvpMessageSender($doExpressCheckout, $token);
$response = PaypalApiManager::nvpToArray($request->send());
$this->logger->logTransaction($response);
// Store correlation ID in the order
if (isset($response['CORRELATIONID'])) {
$order
->setTransactionRef($response['CORRELATIONID'])
->save();
;
}
// In case of pending status, log the reason to get usefull information (multi-currency problem, ...)
if (isset($response['ACK']) && $response['ACK'] === "Success" &&
isset($response['PAYMENTINFO_0_PAYMENTSTATUS']) && $response['PAYMENTINFO_0_PAYMENTSTATUS'] === "Pending") {
$message = $this->getTranslator()->trans(
"Paypal transaction is pending. Reason: %reason",
[ 'reason' => $response['PAYMENTINFO_0_PENDINGREASON'] ],
Paypal::DOMAIN
);
}
/*
* In case of success, go to success page
* In case of error, show it
*/
if (isset($response['ACK']) && $response['ACK'] === "Success"
&& isset($response['PAYMENTINFO_0_PAYMENTSTATUS']) && $response['PAYMENTINFO_0_PAYMENTSTATUS'] === "Completed"
&& isset($response['TOKEN']) && $response['TOKEN'] === $token
) {
/*
* Set order status as paid
*/
$event = new OrderEvent($order);
$event->setStatus(OrderStatusQuery::getPaidStatus()->getId());
$this->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event);
$this->redirectToSuccessPage($order_id);
} else {
$message = $this->getTranslator()->trans("Failed to validate your payment", [], Paypal::DOMAIN);
}
} else {
$message = $this->getTranslator()->trans("Failed to validate payment parameters", [], Paypal::DOMAIN);
}
} else {
$message = $this->getTranslator()->trans("Failed to find PayerID", [], Paypal::DOMAIN);
}
$this->logger->getLogger()->info("Order [" . $order_id . "] : " . $message);
} catch (RedirectException $ex) {
throw $ex;
} catch (\Exception $ex) {
$this->logger->getLogger()->error("Error occured while processing express checkout : " . $ex->getMessage());
$message = $this->getTranslator()->trans(
"Unexpected error: %mesg",
[ '%mesg' => $ex->getMessage()],
Paypal::DOMAIN
);
}
$this->redirectToFailurePage($order_id, $message);
}
/*
* @param $order_id int
* @return \Thelia\Core\HttpFoundation\Response
*/
public function cancel($order_id)
{
$token = null;
try {
$order = $this->checkorder($order_id, $token);
$logger = new PaypalApiLogManager();
$logger->getLogger()->warning("User canceled payment of order ".$order->getRef());
$event = new OrderEvent($order);
$event->setStatus(OrderStatusQuery::create()->findOneByCode(OrderStatus::CODE_CANCELED)->getId());
$this->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event);
$message = $this->getTranslator()->trans("You canceled your payment", [], Paypal::DOMAIN);
} catch (\Exception $ex) {
$this->logger->getLogger()->error("Error occured while canceling express checkout : " . $ex->getMessage());
$message = $this->getTranslator()->trans(
"Unexpected error: %mesg",
[ '%mesg' => $ex->getMessage()],
Paypal::DOMAIN
);
}
$this->redirectToFailurePage($order_id, $message);
}
/*
* @param $order_id int
* @param &$token string|null
* @throws \Exception
* @return \Thelia\Model\Order
*/
public function checkorder($order_id, &$token)
{
$token = $this->getRequest()->getSession()->get('Paypal.token');
if ($token !== $this->getRequest()->get('token')) {
throw new \Exception(
$this->getTranslator()->trans(
"Invalid Paypal token. Please try again.",
[],
Paypal::DOMAIN
)
);
}
if (null === $order = OrderQuery::create()->findPk($order_id)) {
throw new \Exception(
$this->getTranslator()->trans(
"Invalid order ID. This order doesn't exists or doesn't belong to you.",
[],
Paypal::DOMAIN
)
);
}
return $order;
}
/**
* Return a module identifier used to calculate the name of the log file,
* and in the log messages.
*
* @return string the module code
*/
protected function getModuleCode()
{
return "Paypal";
}
}