Skip to content

Commit

Permalink
Replace client token by user id token
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt75 committed Jan 15, 2024
1 parent 0a792c9 commit d073645
Show file tree
Hide file tree
Showing 9 changed files with 438 additions and 41 deletions.
51 changes: 11 additions & 40 deletions controllers/front/token.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,66 +18,37 @@
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/

use PrestaShop\Module\PrestashopCheckout\CommandBus\CommandBusInterface;
use PrestaShop\Module\PrestashopCheckout\Controller\AbstractFrontController;
use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalClientTokenProvider;
use PrestaShop\Module\PrestashopCheckout\PayPal\OAuth\Query\GetPayPalGetUserIdTokenQuery;
use PrestaShop\Module\PrestashopCheckout\PayPal\OAuth\Query\GetPayPalGetUserIdTokenQueryResult;
use Psr\Log\LoggerInterface;

/**
* This controller receive ajax call to retrieve a PayPal Client Token
* This controller receive ajax call to retrieve a PayPal User Id Token
*/
class Ps_CheckoutTokenModuleFrontController extends AbstractFrontController
{
/**
* @var Ps_checkout
*/
public $module;

/**
* @see FrontController::postProcess()
*
* @todo Move logic to a Service and refactor
*/
public function postProcess()
{
try {
if (false === Validate::isLoadedObject($this->context->cart)) {
$this->exitWithResponse([
'httpCode' => 400,
'body' => 'No cart found.',
]);
}

/** @var PayPalClientTokenProvider $clientTokenProvider */
$clientTokenProvider = $this->module->getService('ps_checkout.paypal.provider.client_token');

/** @var \PrestaShop\Module\PrestashopCheckout\Repository\PsCheckoutCartRepository $psCheckoutCartRepository */
$psCheckoutCartRepository = $this->module->getService('ps_checkout.repository.pscheckoutcart');

/** @var PsCheckoutCart|false $psCheckoutCart */
$psCheckoutCart = $psCheckoutCartRepository->findOneByCartId((int) $this->context->cart->id);

if (false === $psCheckoutCart) {
$psCheckoutCart = new PsCheckoutCart();
$psCheckoutCart->id_cart = (int) $this->context->cart->id;
}

if ($psCheckoutCart->isPaypalClientTokenExpired()) {
$psCheckoutCart->paypal_order = '';
$psCheckoutCart->paypal_token = $clientTokenProvider->getPayPalClientToken();
$psCheckoutCart->paypal_token_expire = (new DateTime())->modify('+3550 seconds')->format('Y-m-d H:i:s');
$psCheckoutCartRepository->save($psCheckoutCart);
}
/** @var CommandBusInterface $commandBus */
$commandBus = $this->module->getService('ps_checkout.bus.command');
/** @var GetPayPalGetUserIdTokenQueryResult $getPayPalGetUserIdTokenQueryResult */
$getPayPalGetUserIdTokenQueryResult = $commandBus->handle(new GetPayPalGetUserIdTokenQuery($this->getCustomerId()));

$this->exitWithResponse([
'status' => true,
'httpCode' => 200,
'body' => [
'token' => $psCheckoutCart->paypal_token,
'token' => $getPayPalGetUserIdTokenQueryResult->getUserIdToken(),
],
'exceptionCode' => null,
'exceptionMessage' => null,
]);
} catch (Exception $exception) {
/* @var \Psr\Log\LoggerInterface logger */
/** @var LoggerInterface $logger */
$logger = $this->module->getService('ps_checkout.logger');
$logger->error(
sprintf(
Expand Down
32 changes: 31 additions & 1 deletion src/Controller/AbstractFrontController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@

use Exception;
use ModuleFrontController;
use PrestaShop\Module\PrestashopCheckout\Customer\Exception\CustomerException;
use PrestaShop\Module\PrestashopCheckout\Customer\ValueObject\CustomerId;
use Ps_checkout;
use Tools;

class AbstractFrontController extends ModuleFrontController
{
/**
* @var \Ps_checkout
* @var Ps_checkout
*/
public $module;

Expand Down Expand Up @@ -68,4 +72,30 @@ protected function exitWithResponse(array $response = [])

exit;
}

/**
* @return CustomerId|null
*
* @throws CustomerException
*/
protected function getCustomerId()
{
return $this->context->customer->isLogged() ? new CustomerId($this->context->customer->id) : null;
}

/**
* @return int
*/
protected function getPageSize()
{
return (int) Tools::getValue('pageSize', 10);
}

/**
* @return int
*/
protected function getPageNumber()
{
return (int) Tools::getValue('pageNumber', 1);
}
}
14 changes: 14 additions & 0 deletions src/Database/TableManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ public function createTable()
PRIMARY KEY (`name`, `id_shop`),
INDEX (`id_shop`)
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=UTF8;
') && $this->db->execute('
CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'pscheckout_customer` (
`id_customer` int unsigned NOT NULL,
`paypal_customer_id` varchar(50) NOT NULL,
PRIMARY KEY (`id_customer`, `paypal_customer_id`)
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=UTF8;
') && $this->db->execute('
CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'pscheckout_payment_token` (
`id` varchar(50) NOT NULL,
`paypal_customer_id` varchar(50) NOT NULL,
`payment_source` varchar(50) NOT NULL,
`data` text NOT NULL,
PRIMARY KEY (`id_customer`, `paypal_customer_id`)
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=UTF8;
');

$this->checkTable();
Expand Down
88 changes: 88 additions & 0 deletions src/PayPal/Customer/PayPalCustomerRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/

namespace PrestaShop\Module\PrestashopCheckout\PayPal\Customer;

use Db;
use DbQuery;
use Exception;
use PrestaShop\Module\PrestashopCheckout\Customer\ValueObject\CustomerId;
use PrestaShop\Module\PrestashopCheckout\PayPal\Customer\ValueObject\PayPalCustomerId;

class PayPalCustomerRepository
{
/**
* @var Db
*/
private $db;

/**
* @param Db $db
*/
public function __construct(Db $db)
{
$this->db = $db;
}

/**
* @param CustomerId $customerId
*
* @return PayPalCustomerId|null
*
* @throws Exception
*/
public function findPayPalCustomerIdByCustomerId(CustomerId $customerId)
{
try {
$query = new DbQuery();
$query->select('`paypal_customer_id`');
$query->from('pscheckout_customer');
$query->where('`id_customer` = ' . (int) $customerId->getValue());
$customerIdPayPal = $this->db->getValue($query);

return $customerIdPayPal ? new PayPalCustomerId($customerIdPayPal) : null;
} catch (Exception $exception) {
throw new Exception('Failed to find PayPal Customer ID', 0, $exception);
}
}

/**
* @param CustomerId $customerId
* @param PayPalCustomerId $paypalCustomerId
*
* @return void
*
* @throws Exception
*/
public function save(CustomerId $customerId, PayPalCustomerId $paypalCustomerId)
{
try {
$this->db->insert(
'pscheckout_customer',
[
'id_customer' => (int) $customerId->getValue(),
'paypal_customer_id' => pSQL($paypalCustomerId->getValue()),
]
);
} catch (Exception $exception) {
throw new Exception('Failed to save PayPal Customer ID', 0, $exception);
}
}
}
74 changes: 74 additions & 0 deletions src/PayPal/Customer/ValueObject/PayPalCustomerId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/

namespace PrestaShop\Module\PrestashopCheckout\PayPal\Customer\ValueObject;

use InvalidArgumentException;

class PayPalCustomerId
{
/**
* @var string
*/
private $customerId;

/**
* @param string $customerId
*
* @throws InvalidArgumentException
*/
public function __construct($customerId)
{
$this->assertIsValid($customerId);
$this->customerId = $customerId;
}

/**
* @return string
*/
public function getValue()
{
return $this->customerId;
}

/**
* @param string $customerId
*
* @return void
*
* @throws InvalidArgumentException
*/
private function assertIsValid($customerId)
{
if (!is_string($customerId)) {
throw new InvalidArgumentException('PayPal Customer ID must be a string.');
}

$length = strlen($customerId);

if ($length < 1 || $length > 22) {
throw new InvalidArgumentException('PayPal Customer ID must be between 1 and 22 characters long.');
}

if (preg_match('/^[0-9a-zA-Z_-]+$/', $customerId) !== 1) {
throw new InvalidArgumentException('PayPal Customer ID must be alphanumeric.');
}
}
}
66 changes: 66 additions & 0 deletions src/PayPal/OAuth/OAuthService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/

namespace PrestaShop\Module\PrestashopCheckout\PayPal\OAuth;

use Exception;
use GuzzleHttp\Psr7\Request;
use PrestaShop\Module\PrestashopCheckout\PayPal\Customer\ValueObject\PayPalCustomerId;

class OAuthService
{
private $httpClient;

public function __construct($httpClient)
{
$this->httpClient = $httpClient;
}

/**
* @param PayPalCustomerId|null $customerId
*
* @return string
*
* @throws Exception
*/
public function getUserIdToken(PayPalCustomerId $customerId = null)
{
try {
$body = 'grant_type=client_credentials&response_type=id_token';

if ($customerId) {
$body .= '&target_customer_id=' . $customerId->getValue();
}

$request = new Request('POST', '', [], $body);
$response = $this->httpClient->sendRequest($request);

$data = json_decode($response->getBody()->getContents(), true);

if (empty($data['id_token'])) {
throw new Exception('Failed to get PayPal User ID token from response.');
}

return $data['id_token'];
} catch (Exception $exception) {
throw new Exception('Failed to get PayPal User ID token.', 0, $exception);
}
}
}
Loading

0 comments on commit d073645

Please sign in to comment.