412 lines
14 KiB
PHP
412 lines
14 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\Service;
|
|
|
|
use Monolog\Logger;
|
|
use PayPal\Api\Amount;
|
|
use PayPal\Api\CreditCard;
|
|
use PayPal\Api\CreditCardToken;
|
|
use PayPal\Api\Details;
|
|
use PayPal\Api\FundingInstrument;
|
|
use PayPal\Api\FuturePayment;
|
|
use PayPal\Api\OpenIdTokeninfo;
|
|
use PayPal\Api\Payer;
|
|
use PayPal\Api\Payment;
|
|
use PayPal\Api\PaymentExecution;
|
|
use PayPal\Api\RedirectUrls;
|
|
use PayPal\Api\Transaction;
|
|
use PayPal\Exception\PayPalConnectionException;
|
|
use PayPal\PayPal;
|
|
use PayPal\Service\Base\PayPalBaseService;
|
|
use Thelia\Core\Translation\Translator;
|
|
use Thelia\Model\Cart;
|
|
use Thelia\Model\Currency;
|
|
use Thelia\Model\CurrencyQuery;
|
|
use Thelia\Model\Order;
|
|
use Thelia\Tools\URL;
|
|
|
|
|
|
/**
|
|
* Class PayPalPaymentService
|
|
* @package PayPal\Service
|
|
*/
|
|
class PayPalPaymentService extends PayPalBaseService
|
|
{
|
|
/**
|
|
* Create a payment using a previously obtained
|
|
* credit card id. The corresponding credit
|
|
* card is used as the funding instrument.
|
|
*
|
|
* @param Order $order
|
|
* @param bool $future
|
|
* @param string|null $creditCardId
|
|
* @param string|null $description
|
|
* @return Payment
|
|
*/
|
|
public function makePayment(Order $order, $creditCardId = null, $description = null, $future = false)
|
|
{
|
|
$payPalOrderEvent = $this->generatePayPalOrder($order);
|
|
|
|
if (null !== $creditCardId) {
|
|
$creditCardToken = new CreditCardToken();
|
|
$creditCardToken->setCreditCardId($creditCardId);
|
|
|
|
$fundingInstrument = new FundingInstrument();
|
|
$fundingInstrument->setCreditCardToken($creditCardToken);
|
|
|
|
$payer = self::generatePayer(PayPal::PAYPAL_METHOD_CREDIT_CARD, [$fundingInstrument]);
|
|
} else {
|
|
$payer = self::generatePayer();
|
|
}
|
|
|
|
// Specify the payment amount.
|
|
if (null === $currency = CurrencyQuery::create()->findOneById($order->getCurrencyId())) {
|
|
$currency = Currency::getDefaultCurrency();
|
|
}
|
|
|
|
$amount = $this->generateAmount($order, $currency);
|
|
|
|
$transaction = $this->generateTransaction($amount, $description);
|
|
|
|
$payment = $this->generatePayment($order, $payer, $transaction, $future);
|
|
|
|
$this->updatePayPalOrder($payPalOrderEvent->getPayPalOrder(), $payment->getState(), $payment->getId());
|
|
|
|
return $payment;
|
|
}
|
|
|
|
public function makePaymentFromCart(Cart $cart, $description = null, $future = false, $fromCartView = true)
|
|
{
|
|
$payer = self::generatePayer();
|
|
|
|
// Specify the payment amount.
|
|
if (null === $currency = CurrencyQuery::create()->findOneById($cart->getCurrencyId())) {
|
|
$currency = Currency::getDefaultCurrency();
|
|
}
|
|
|
|
$amount = $this->generateAmountFromCart($cart, $currency);
|
|
|
|
$transaction = $this->generateTransaction($amount, $description);
|
|
|
|
$payment = $this->generatePaymentFromCart($cart, $payer, $transaction, $future, $fromCartView);
|
|
|
|
//$this->updatePayPalOrder($payPalOrderEvent->getPayPalOrder(), $payment->getState(), $payment->getId());
|
|
|
|
return $payment;
|
|
}
|
|
|
|
/**
|
|
* Completes the payment once buyer approval has been
|
|
* obtained. Used only when the payment method is 'paypal'
|
|
*
|
|
* @param string $paymentId id of a previously created
|
|
* payment that has its payment method set to 'paypal'
|
|
* and has been approved by the buyer.
|
|
*
|
|
* @param string $payerId PayerId as returned by PayPal post
|
|
* buyer approval.
|
|
*
|
|
* @return Payment
|
|
*/
|
|
public function executePayment($paymentId, $payerId, Details $details = null)
|
|
{
|
|
$payment = $this->getPaymentDetails($paymentId);
|
|
$paymentExecution = new PaymentExecution();
|
|
$paymentExecution->setPayerId($payerId);
|
|
|
|
if (null !== $details) {
|
|
$amount = new Amount();
|
|
$totalDetails = (float)$details->getShipping() + (float)$details->getTax() + (float)$details->getSubtotal();
|
|
$amount
|
|
->setCurrency('EUR')
|
|
->setTotal($totalDetails)
|
|
->setDetails($details)
|
|
;
|
|
|
|
$transaction = new Transaction();
|
|
$transaction->setAmount($amount);
|
|
|
|
$paymentExecution->addTransaction($transaction);
|
|
}
|
|
|
|
$payment = $payment->execute($paymentExecution, self::getApiContext());
|
|
|
|
return $payment;
|
|
}
|
|
|
|
public function createDetails($shipping = 0, $shippingTax = 0, $subTotal = 0)
|
|
{
|
|
$details = new Details();
|
|
$details
|
|
->setShipping($shipping)
|
|
->setTax($shippingTax)
|
|
->setSubtotal($subTotal)
|
|
;
|
|
|
|
return $details;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the payment information based on PaymentID from Paypal APIs
|
|
*
|
|
* @param $paymentId
|
|
*
|
|
* @return Payment
|
|
*/
|
|
public function getPaymentDetails($paymentId)
|
|
{
|
|
$payment = Payment::get($paymentId, self::getApiContext());
|
|
|
|
return $payment;
|
|
}
|
|
|
|
/**
|
|
* @param $authorizationCode
|
|
* @return OpenIdTokeninfo
|
|
* @throws PayPalConnectionException
|
|
*/
|
|
public function generateAccessToken($authorizationCode)
|
|
{
|
|
try {
|
|
// Obtain Authorization Code from Code, Client ID and Client Secret
|
|
$accessToken = OpenIdTokeninfo::createFromAuthorizationCode(
|
|
['code' => $authorizationCode],
|
|
null,
|
|
null,
|
|
self::getApiContext()
|
|
);
|
|
|
|
return $accessToken;
|
|
} catch (PayPalConnectionException $ex) {
|
|
PayPalLoggerService::log($ex->getMessage(), [], Logger::ERROR);
|
|
throw $ex;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $type
|
|
* @param $number
|
|
* @param $expireMonth
|
|
* @param $expireYear
|
|
* @param $cvv2
|
|
* @return string
|
|
* @throws \Exception
|
|
*/
|
|
public function getPayPalCreditCardId($type, $number, $expireMonth, $expireYear, $cvv2)
|
|
{
|
|
try {
|
|
$card = new CreditCard();
|
|
$card->setType($type);
|
|
$card->setNumber((int)$number);
|
|
$card->setExpireMonth((int)$expireMonth);
|
|
$card->setExpireYear((int)$expireYear);
|
|
$card->setCvv2($cvv2);
|
|
|
|
$card->create(self::getApiContext());
|
|
|
|
return $card->getId();
|
|
} catch (\Exception $e) {
|
|
PayPalLoggerService::log($e->getMessage(), [], Logger::ERROR);
|
|
throw new \Exception(Translator::getInstance()->trans('Credit card is invalid', [], PayPal::DOMAIN_NAME));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Order $order
|
|
* @param Payer $payer
|
|
* @param Transaction $transaction
|
|
* @param bool $future
|
|
* @return FuturePayment|Payment
|
|
* @throws PayPalConnectionException
|
|
* @throws \Exception
|
|
*/
|
|
public function generatePayment(Order $order, Payer $payer, Transaction $transaction, $future = false)
|
|
{
|
|
if ($future) {
|
|
$payment = new FuturePayment();
|
|
$payment->setIntent('authorize');
|
|
} else {
|
|
$payment = new Payment();
|
|
$payment->setIntent('sale');
|
|
}
|
|
|
|
$payment
|
|
->setRedirectUrls($this->getRedirectUrls($order))
|
|
->setPayer($payer)
|
|
->setTransactions([$transaction])
|
|
;
|
|
|
|
$clientMetadataId = '123123456';
|
|
|
|
try {
|
|
|
|
if ($future) {
|
|
|
|
//$authorizationCode = self::getAuthorizationCode();
|
|
$refreshToken = $this->getRefreshToken();
|
|
//$refreshToken = FuturePayment::getRefreshToken($this->getAuthorizationCode(), self::getApiContext());
|
|
$payment->updateAccessToken($refreshToken, self::getApiContext());
|
|
$payment->create(self::getApiContext(), $clientMetadataId);
|
|
|
|
} else {
|
|
$payment->create(self::getApiContext());
|
|
}
|
|
|
|
return $payment;
|
|
|
|
} catch (PayPalConnectionException $e) {
|
|
$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) {
|
|
PayPalLoggerService::log(
|
|
$e->getMessage(),
|
|
[
|
|
'customer_id' => $order->getCustomerId(),
|
|
'order_id' => $order->getId()
|
|
],
|
|
Logger::CRITICAL
|
|
);
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Cart $cart
|
|
* @param Payer $payer
|
|
* @param Transaction $transaction
|
|
* @param bool $future
|
|
* @return FuturePayment|Payment
|
|
* @throws PayPalConnectionException
|
|
* @throws \Exception
|
|
*/
|
|
public function generatePaymentFromCart(Cart $cart, Payer $payer, Transaction $transaction, $future = false, $fromCartView = true)
|
|
{
|
|
if ($future) {
|
|
$payment = new FuturePayment();
|
|
$payment->setIntent('authorize');
|
|
} else {
|
|
$payment = new Payment();
|
|
$payment->setIntent('sale');
|
|
}
|
|
|
|
if ($fromCartView) {
|
|
$payment->setRedirectUrls($this->getRedirectCartUrls($cart));
|
|
} else {
|
|
$payment->setRedirectUrls($this->getRedirectInvoiceUrls($cart));
|
|
}
|
|
$payment
|
|
->setPayer($payer)
|
|
->setTransactions([$transaction])
|
|
;
|
|
|
|
$clientMetadataId = '123123456';
|
|
|
|
try {
|
|
|
|
if ($future) {
|
|
|
|
//$authorizationCode = self::getAuthorizationCode();
|
|
$refreshToken = $this->getRefreshToken();
|
|
//$refreshToken = FuturePayment::getRefreshToken($this->getAuthorizationCode(), self::getApiContext());
|
|
$payment->updateAccessToken($refreshToken, self::getApiContext());
|
|
$payment->create(self::getApiContext(), $clientMetadataId);
|
|
|
|
} else {
|
|
$payment->create(self::getApiContext());
|
|
}
|
|
|
|
return $payment;
|
|
|
|
} catch (PayPalConnectionException $e) {
|
|
$message = sprintf('url : %s. data : %s. message : %s', $e->getUrl(), $e->getData(), $e->getMessage());
|
|
PayPalLoggerService::log(
|
|
$message,
|
|
[],
|
|
Logger::CRITICAL
|
|
);
|
|
throw $e;
|
|
} catch (\Exception $e) {
|
|
PayPalLoggerService::log(
|
|
$e->getMessage(),
|
|
[],
|
|
Logger::CRITICAL
|
|
);
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Order $order
|
|
* @return RedirectUrls
|
|
*/
|
|
public function getRedirectUrls(Order $order)
|
|
{
|
|
$redirectUrls = new RedirectUrls();
|
|
$urlOk = URL::getInstance()->absoluteUrl('/module/paypal/ok/' . $order->getId());
|
|
$urlCancel = URL::getInstance()->absoluteUrl('/module/paypal/cancel/' . $order->getId());
|
|
$redirectUrls->setReturnUrl($urlOk);
|
|
$redirectUrls->setCancelUrl($urlCancel);
|
|
|
|
return $redirectUrls;
|
|
}
|
|
|
|
/**
|
|
* @param Cart $cart
|
|
* @return RedirectUrls
|
|
*/
|
|
public function getRedirectCartUrls(Cart $cart)
|
|
{
|
|
$redirectUrls = new RedirectUrls();
|
|
$urlOk = URL::getInstance()->absoluteUrl('/module/paypal/express/checkout/ok/' . $cart->getId());
|
|
$urlCancel = URL::getInstance()->absoluteUrl('/module/paypal/express/checkout/ko/' . $cart->getId());
|
|
$redirectUrls->setReturnUrl($urlOk);
|
|
$redirectUrls->setCancelUrl($urlCancel);
|
|
|
|
return $redirectUrls;
|
|
}
|
|
|
|
/**
|
|
* @param Cart $cart
|
|
* @return RedirectUrls
|
|
*/
|
|
public function getRedirectInvoiceUrls(Cart $cart)
|
|
{
|
|
$redirectUrls = new RedirectUrls();
|
|
$urlOk = URL::getInstance()->absoluteUrl('/module/paypal/invoice/express/checkout/ok/' . $cart->getId());
|
|
$urlCancel = URL::getInstance()->absoluteUrl('/module/paypal/invoice/express/checkout/ko/' . $cart->getId());
|
|
$redirectUrls->setReturnUrl($urlOk);
|
|
$redirectUrls->setCancelUrl($urlCancel);
|
|
|
|
return $redirectUrls;
|
|
}
|
|
}
|