Files
outil-82/local/modules/PayPal/PayPal.php

374 lines
15 KiB
PHP

<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace PayPal;
use Monolog\Logger;
use PayPal\Exception\PayPalConnectionException;
use PayPal\Model\PaypalCartQuery;
use PayPal\Model\PaypalPlanifiedPaymentQuery;
use PayPal\Service\Base\PayPalBaseService;
use PayPal\Service\PayPalAgreementService;
use PayPal\Service\PayPalLoggerService;
use PayPal\Service\PayPalPaymentService;
use Propel\Runtime\Connection\ConnectionInterface;
use Propel\Runtime\Propel;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Thelia\Core\Event\Order\OrderEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Translation\Translator;
use Thelia\Install\Database;
use Thelia\Model\Message;
use Thelia\Model\MessageQuery;
use Thelia\Model\ModuleImageQuery;
use Thelia\Model\Order;
use Thelia\Model\OrderStatusQuery;
use Thelia\Module\AbstractPaymentModule;
use Thelia\Tools\URL;
class PayPal extends AbstractPaymentModule
{
/** @var string */
const DOMAIN_NAME = 'paypal';
const ROUTER = 'router.paypal';
/**
* The confirmation message identifier
*/
const CONFIRMATION_MESSAGE_NAME = 'paypal_payment_confirmation';
const RECURSIVE_MESSAGE_NAME = 'paypal_recursive_payment_confirmation';
const CREDIT_CARD_TYPE_VISA = 'visa';
const CREDIT_CARD_TYPE_MASTERCARD = 'mastercard';
const CREDIT_CARD_TYPE_DISCOVER = 'discover';
const CREDIT_CARD_TYPE_AMEX = 'amex';
const PAYPAL_METHOD_PAYPAL = 'paypal';
const PAYPAL_METHOD_EXPRESS_CHECKOUT = 'express_checkout';
const PAYPAL_METHOD_CREDIT_CARD = 'credit_card';
const PAYPAL_METHOD_PLANIFIED_PAYMENT = 'planified_payment';
const PAYPAL_PAYMENT_SERVICE_ID = 'paypal_payment_service';
const PAYPAL_CUSTOMER_SERVICE_ID = 'paypal_customer_service';
const PAYPAL_AGREEMENT_SERVICE_ID = 'paypal_agreement_service';
const PAYMENT_STATE_APPROVED = 'approved';
const PAYMENT_STATE_CREATED = 'created';
const PAYMENT_STATE_REFUSED = 'refused';
/**
* Method used by payment gateway.
*
* If this method return a \Thelia\Core\HttpFoundation\Response instance, this response is send to the
* browser.
*
* In many cases, it's necessary to send a form to the payment gateway. On your response you can return this form already
* completed, ready to be sent
*
* @param Order $order
* @return RedirectResponse
* @throws \Exception
*/
public function pay(Order $order)
{
$con = Propel::getConnection();
$con->beginTransaction();
try {
/** @var PayPalPaymentService $payPalService */
$payPalService = $this->getContainer()->get(self::PAYPAL_PAYMENT_SERVICE_ID);
/** @var PayPalAgreementService $payPalAgreementService */
$payPalAgreementService = $this->getContainer()->get(self::PAYPAL_AGREEMENT_SERVICE_ID);
if (null !== $payPalCart = PaypalCartQuery::create()->findOneById($order->getCartId())) {
if (null !== $payPalCart->getCreditCardId()) {
$payment = $payPalService->makePayment($order, $payPalCart->getCreditCardId());
//This payment method does not have a callback URL... So we have to check the payment status
if ($payment->getState() === PayPal::PAYMENT_STATE_APPROVED) {
$event = new OrderEvent($order);
$event->setStatus(OrderStatusQuery::getPaidStatus()->getId());
$this->getDispatcher()->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event);
$response = new RedirectResponse(URL::getInstance()->absoluteUrl('/order/placed/' . $order->getId()));
PayPalLoggerService::log(
Translator::getInstance()->trans(
'Order payed with success with method : %method',
[
'%method' => self::PAYPAL_METHOD_CREDIT_CARD
],
self::DOMAIN_NAME
),
[
'order_id' => $order->getId(),
'customer_id' => $order->getCustomerId()
],
Logger::INFO
);
} else {
$response = new RedirectResponse(URL::getInstance()->absoluteUrl('/module/paypal/cancel/' . $order->getId()));
PayPalLoggerService::log(
Translator::getInstance()->trans(
'Order failed with method : %method',
[
'%method' => self::PAYPAL_METHOD_CREDIT_CARD
],
self::DOMAIN_NAME
),
[
'order_id' => $order->getId(),
'customer_id' => $order->getCustomerId()
],
Logger::CRITICAL
);
}
} elseif (null !== $planifiedPayment = PaypalPlanifiedPaymentQuery::create()->findOneById($payPalCart->getPlanifiedPaymentId())) {
//Agreement Payment
$agreement = $payPalAgreementService->makeAgreement($order, $planifiedPayment);
$response = new RedirectResponse($agreement->getApprovalLink());
PayPalLoggerService::log(
Translator::getInstance()->trans(
'Order created with success in PayPal with method : %method',
[
'%method' => self::PAYPAL_METHOD_PLANIFIED_PAYMENT
],
self::DOMAIN_NAME
),
[
'order_id' => $order->getId(),
'customer_id' => $order->getCustomerId()
],
Logger::INFO
);
} else {
//Classic Payment
$payment = $payPalService->makePayment($order);
$response = new RedirectResponse($payment->getApprovalLink());
PayPalLoggerService::log(
Translator::getInstance()->trans(
'Order created with success in PayPal with method : %method',
[
'%method' => self::PAYPAL_METHOD_PAYPAL
],
self::DOMAIN_NAME
),
[
'order_id' => $order->getId(),
'customer_id' => $order->getCustomerId()
],
Logger::INFO
);
}
} else {
//Classic Payment
$payment = $payPalService->makePayment($order);
$response = new RedirectResponse($payment->getApprovalLink());
PayPalLoggerService::log(
Translator::getInstance()->trans(
'Order created with success in PayPal with method : %method',
[
'%method' => self::PAYPAL_METHOD_PAYPAL
],
self::DOMAIN_NAME
),
[
'order_id' => $order->getId(),
'customer_id' => $order->getCustomerId()
],
Logger::INFO
);
//Future Payment NOT OPERATIONNEL IN PAYPAL API REST YET !
//$payment = $payPalService->makePayment($order, null, null, true);
//$response = new RedirectResponse($payment->getApprovalLink());
}
$con->commit();
return $response;
} catch (PayPalConnectionException $e) {
$con->rollBack();
$message = sprintf('url : %s. data : %s. message : %s', $e->getUrl(), $e->getData(), $e->getMessage());
PayPalLoggerService::log(
$message,
[
'customer_id' => $order->getCustomerId(),
'order_id' => $order->getId()
],
Logger::CRITICAL
);
throw $e;
} catch(\Exception $e) {
$con->rollBack();
PayPalLoggerService::log(
$e->getMessage(),
[
'customer_id' => $order->getCustomerId(),
'order_id' => $order->getId()
],
Logger::CRITICAL
);
throw $e;
}
}
/**
*
* This method is call on Payment loop.
*
* If you return true, the payment method will de display
* If you return false, the payment method will not be display
*
* @return boolean
*/
public function isValidPayment()
{
$isValid = false;
// Check if total order amount is within the module's limits
$order_total = $this->getCurrentOrderTotalAmount();
$min_amount = Paypal::getConfigValue('minimum_amount', 0);
$max_amount = Paypal::getConfigValue('maximum_amount', 0);
if (
($order_total > 0)
&&
($min_amount <= 0 || $order_total >= $min_amount)
&&
($max_amount <= 0 || $order_total <= $max_amount)
) {
// Check cart item count
$cartItemCount = $this->getRequest()->getSession()->getSessionCart($this->getDispatcher())->countCartItems();
if ($cartItemCount <= Paypal::getConfigValue('cart_item_count', 9)) {
$isValid = true;
if (PayPalBaseService::isSandboxMode()) {
// In sandbox mode, check the current IP
$raw_ips = explode("\n", Paypal::getConfigValue('allowed_ip_list', ''));
$allowed_client_ips = array();
foreach ($raw_ips as $ip) {
$allowed_client_ips[] = trim($ip);
}
$client_ip = $this->getRequest()->getClientIp();
$isValid = in_array($client_ip, $allowed_client_ips);
}
}
}
return $isValid;
}
/**
* if you want, you can manage stock in your module instead of order process.
* Return false to decrease the stock when order status switch to pay
*
* @return bool
*/
public function manageStockOnCreation()
{
return false;
}
/**
* @param \Propel\Runtime\Connection\ConnectionInterface $con
*/
public function postActivation(ConnectionInterface $con = null)
{
$database = new Database($con);
$database->insertSql(null, array(__DIR__ . "/Config/create.sql"));
// Setup some default values at first install
if (null === self::getConfigValue('minimum_amount', null)) {
self::setConfigValue('minimum_amount', 0);
self::setConfigValue('maximum_amount', 0);
self::setConfigValue('send_payment_confirmation_message', 1);
self::setConfigValue('cart_item_count', 999);
}
if (null === MessageQuery::create()->findOneByName(self::CONFIRMATION_MESSAGE_NAME)) {
$message = new Message();
$message
->setName(self::CONFIRMATION_MESSAGE_NAME)
->setHtmlTemplateFileName('paypal-payment-confirmation.html')
->setTextTemplateFileName('paypal-payment-confirmation.txt')
->setLocale('en_US')
->setTitle('Paypal payment confirmation')
->setSubject('Payment of order {$order_ref}')
->setLocale('fr_FR')
->setTitle('Confirmation de paiement par Paypal')
->setSubject('Confirmation du paiement de votre commande {$order_ref}')
->save()
;
}
if (null === MessageQuery::create()->findOneByName(self::RECURSIVE_MESSAGE_NAME)) {
$message = new Message();
$message
->setName(self::RECURSIVE_MESSAGE_NAME)
->setHtmlTemplateFileName('paypal-recursive-payment-confirmation.html')
->setTextTemplateFileName('paypal-recursive-payment-confirmation.txt')
->setLocale('en_US')
->setTitle('Paypal payment confirmation')
->setSubject('Payment of order {$order_ref}')
->setLocale('fr_FR')
->setTitle('Confirmation de paiement par Paypal')
->setSubject('Confirmation du paiement de votre commande {$order_ref}')
->save()
;
}
/* Deploy the module's image */
$module = $this->getModuleModel();
if (ModuleImageQuery::create()->filterByModule($module)->count() == 0) {
$this->deployImageFolder($module, sprintf('%s/images', __DIR__), $con);
}
}
public function update($currentVersion, $newVersion, ConnectionInterface $con = null)
{
$finder = (new Finder())
->files()
->name('#.*?\.sql#')
->sortByName()
->in(__DIR__ . DS . 'Config' . DS . 'Update')
;
$database = new Database($con);
/** @var \Symfony\Component\Finder\SplFileInfo $updateSQLFile */
foreach ($finder as $updateSQLFile) {
if (version_compare($currentVersion, str_replace('.sql', '', $updateSQLFile->getFilename()), '<')) {
$database->insertSql(
null,
[
$updateSQLFile->getPathname()
]
);
}
}
}
}