Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PAYSHIP-3125] Added new 3DS status in admin order page #1309

Open
wants to merge 7 commits into
base: prestashop/8.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ services:
public: true
arguments:
- "@ps_checkout.logger"
- '@PrestaShop\Module\PrestashopCheckout\Repository\PayPalOrderRepository'
- '@PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration'

PrestaShop\Module\PrestashopCheckout\PayPal\PaymentToken\PaymentMethodTokenService:
class: 'PrestaShop\Module\PrestashopCheckout\PayPal\PaymentToken\PaymentMethodTokenService'
Expand Down
9 changes: 9 additions & 0 deletions controllers/front/payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Query\GetPayPalOrderForCheckoutCompletedQuery;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Query\GetPayPalOrderForCheckoutCompletedQueryResult;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\ValueObject\PayPalOrderId;
use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration;
use PrestaShop\Module\PrestashopCheckout\Repository\PaymentTokenRepository;
use PrestaShop\Module\PrestashopCheckout\Repository\PayPalOrderRepository;

Expand Down Expand Up @@ -87,6 +88,8 @@ public function postProcess()

$this->commandBus = $this->module->getService('ps_checkout.bus.command');

/** @var PayPalConfiguration $payPalConfiguration */
$payPalConfiguration = $this->module->getService(PayPalConfiguration::class);
/** @var PayPalOrderRepository $payPalOrderRepository */
$payPalOrderRepository = $this->module->getService(PayPalOrderRepository::class);
/** @var Psr\SimpleCache\CacheInterface $payPalOrderCache */
Expand Down Expand Up @@ -136,6 +139,12 @@ public function postProcess()
$this->createOrder($payPalOrderFromCache, $payPalOrder);
break;
case Card3DSecure::NO_DECISION:
if ($payPalConfiguration->getHostedFieldsContingencies() === 'SCA_WHEN_REQUIRED') {
$this->commandBus->handle(new CapturePayPalOrderCommand($orderId, array_keys($payPalOrderFromCache['payment_source'])[0]));
$payPalOrderFromCache = $payPalOrderCache->get($orderId);
$this->createOrder($payPalOrderFromCache, $payPalOrder);
}
// no break
default:
break;
}
Expand Down
2 changes: 1 addition & 1 deletion ps_checkout.php
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ public function hookActionFrontControllerSetMedia()
'checkout.payment.token.delete.modal.confirm-button' => $this->l('Delete payment method'),
'checkout.payment.loader.processing-request' => $this->l('Please wait, we are processing your request'),
'APPLE_PAY_MERCHANT_SESSION_VALIDATION_ERROR' => $this->l('We’re unable to process your Apple Pay payment at the moment. This could be due to an issue verifying the payment setup for this website. Please try again later or choose a different payment method.'),
'APPROVE_APPLE_PAY_VALIDATION_ERROR' => $this->l('We encountered an issue while processing your Apple Pay payment. Please verify your order details and try again, or use a different payment method.')
'APPROVE_APPLE_PAY_VALIDATION_ERROR' => $this->l('We encountered an issue while processing your Apple Pay payment. Please verify your order details and try again, or use a different payment method.'),
],
]);

Expand Down
35 changes: 30 additions & 5 deletions src/Checkout/CheckoutChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
namespace PrestaShop\Module\PrestashopCheckout\Checkout;

use Cart;
use Configuration;
use Customer;
use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException;
use PrestaShop\Module\PrestashopCheckout\PayPal\Card3DSecure;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Entity\PayPalOrder;
use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration;
use PrestaShop\Module\PrestashopCheckout\Repository\PayPalOrderRepository;
use Psr\Log\LoggerInterface;
use Validate;

Expand All @@ -34,13 +36,26 @@ class CheckoutChecker
* @var LoggerInterface
*/
private $logger;
/**
* @var PayPalOrderRepository
*/
private $payPalOrderRepository;
/**
* @var PayPalConfiguration
*/
private $payPalConfiguration;

/**
* @param LoggerInterface $logger
*/
public function __construct(LoggerInterface $logger)
{
public function __construct(
LoggerInterface $logger,
PayPalOrderRepository $payPalOrderRepository,
PayPalConfiguration $payPalConfiguration
) {
$this->logger = $logger;
$this->payPalOrderRepository = $payPalOrderRepository;
$this->payPalConfiguration = $payPalConfiguration;
}

/**
Expand All @@ -57,6 +72,8 @@ public function continueWithAuthorization($cartId, $orderPayPal)
throw new PsCheckoutException(sprintf('PayPal Order %s is already captured', $orderPayPal['id']), PsCheckoutException::PAYPAL_ORDER_ALREADY_CAPTURED);
}

$contingencies = $this->payPalConfiguration->getHostedFieldsContingencies();

$paymentSource = isset($orderPayPal['payment_source']) ? key($orderPayPal['payment_source']) : '';

if (in_array($paymentSource, ['google_pay', 'card'], true)) {
Expand All @@ -74,7 +91,7 @@ public function continueWithAuthorization($cartId, $orderPayPal)
(string) Card3DSecure::RETRY,
],
[
Configuration::get('PS_CHECKOUT_LIABILITY_SHIFT_REQ') ? 'Rejected, no liability shift' : 'Proceed, without liability shift',
$contingencies === 'SCA_ALWAYS' ? 'Rejected, no liability shift' : 'Proceed, without liability shift',
'Proceed, liability shift is possible',
'Rejected',
'Retry, ask customer to retry',
Expand All @@ -90,9 +107,17 @@ public function continueWithAuthorization($cartId, $orderPayPal)
case Card3DSecure::RETRY:
throw new PsCheckoutException('Card Strong Customer Authentication must be retried.', PsCheckoutException::PAYPAL_PAYMENT_CARD_SCA_UNKNOWN);
case Card3DSecure::NO_DECISION:
if (Configuration::get('PS_CHECKOUT_LIABILITY_SHIFT_REQ')) {
if ($contingencies === 'SCA_ALWAYS') {
throw new PsCheckoutException('No liability shift to card issuer', PsCheckoutException::PAYPAL_PAYMENT_CARD_SCA_UNKNOWN);
}
if ($contingencies === 'SCA_WHEN_REQUIRED') {
$payPalOrder = $this->payPalOrderRepository->getPayPalOrderByCartId($cartId);
try {
$payPalOrder->addTag(PayPalOrder::THREE_D_SECURE_NOT_REQUIRED);
$this->payPalOrderRepository->savePayPalOrder($payPalOrder);
} catch (PsCheckoutException $e) {
}
}
break;
}
}
Expand Down
36 changes: 35 additions & 1 deletion src/PayPal/Order/Entity/PayPalOrder.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class PayPalOrder
const CUSTOMER_INTENT_VAULT = 'VAULT';
const CUSTOMER_INTENT_FAVORITE = 'FAVORITE';
const CUSTOMER_INTENT_USES_VAULTING = 'USES_VAULTING';
const THREE_D_SECURE_NOT_REQUIRED = '3DS_NOT_REQUIRED';

/**
* @var PayPalOrderId
Expand Down Expand Up @@ -74,8 +75,12 @@ class PayPalOrder
* @var PaymentTokenId|null
*/
private $paymentTokenId;
/**
* @var array
*/
private $tags;

public function __construct($id, $idCart, $intent, $fundingSource, $status, $paymentSource = [], $environment = 'LIVE', $isCardFields = false, $isExpressCheckout = false, $customerIntent = [], $paymentTokenId = null)
public function __construct($id, $idCart, $intent, $fundingSource, $status, $paymentSource = [], $environment = 'LIVE', $isCardFields = false, $isExpressCheckout = false, $customerIntent = [], $paymentTokenId = null, $tags = [])
L3RAZ marked this conversation as resolved.
Show resolved Hide resolved
{
$this->id = new PayPalOrderId($id);
$this->idCart = $idCart;
Expand All @@ -88,6 +93,7 @@ public function __construct($id, $idCart, $intent, $fundingSource, $status, $pay
$this->isExpressCheckout = (bool) $isExpressCheckout;
$this->customerIntent = $customerIntent;
$this->paymentTokenId = $paymentTokenId;
$this->tags = $tags;
}

/**
Expand Down Expand Up @@ -317,4 +323,32 @@ public function setPaymentTokenId($paymentTokenId)
{
$this->paymentTokenId = $paymentTokenId;
}

/**
* @return string[]
*/
public function getTags()
{
return $this->tags;
}

/**
* @param array $tags
*
* @return void
*/
public function setTags(array $tags)
{
$this->tags = $tags;
}

/**
* @param string $tag
*
* @return void
*/
public function addTag($tag)
{
$this->tags[] = $tag;
}
}
18 changes: 18 additions & 0 deletions src/Presenter/Order/OrderPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@

namespace PrestaShop\Module\PrestashopCheckout\Presenter\Order;

use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException;
use PrestaShop\Module\PrestashopCheckout\FundingSource\FundingSourceTranslationProvider;
use PrestaShop\Module\PrestashopCheckout\PayPal\Card3DSecure;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Entity\PayPalOrder;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\ValueObject\PayPalOrderId;
use PrestaShop\Module\PrestashopCheckout\Presenter\Date\DatePresenter;
use PrestaShop\Module\PrestashopCheckout\Provider\PaymentMethodLogoProvider;
use PrestaShop\Module\PrestashopCheckout\Repository\PayPalOrderRepository;
use Ps_checkout;
use PsCheckoutCart;

Expand All @@ -42,6 +46,10 @@ class OrderPresenter
* @var FundingSourceTranslationProvider
*/
private $fundingSourceTranslationProvider;
/**
* @var PayPalOrderRepository
*/
private $payPalOrderRepository;

/**
* @param Ps_checkout $module
Expand All @@ -54,6 +62,7 @@ public function __construct(Ps_checkout $module, array $orderPayPal)
/** @var FundingSourceTranslationProvider $fundingSourceTranslationProvider */
$fundingSourceTranslationProvider = $this->module->getService(FundingSourceTranslationProvider::class);
$this->fundingSourceTranslationProvider = $fundingSourceTranslationProvider;
$this->payPalOrderRepository = $this->module->getService(PayPalOrderRepository::class);
}

/**
Expand All @@ -65,6 +74,14 @@ public function present()
return [];
}

$threeDSNotRequired = false;

try {
$payPalOrder = $this->payPalOrderRepository->getPayPalOrderById(new PayPalOrderId($this->orderPayPal['id']));
L3RAZ marked this conversation as resolved.
Show resolved Hide resolved
$threeDSNotRequired = in_array(PayPalOrder::THREE_D_SECURE_NOT_REQUIRED, $payPalOrder->getTags());
} catch (PsCheckoutException $e) {
}

$card3DSecure = new Card3DSecure();

return array_merge(
Expand All @@ -73,6 +90,7 @@ public function present()
'intent' => $this->orderPayPal['intent'],
'status' => $this->getOrderStatus(),
'transactions' => $this->getTransactions(),
'is3DSNotRequired' => $threeDSNotRequired,
'is3DSecureAvailable' => $card3DSecure->is3DSecureAvailable($this->orderPayPal),
'isLiabilityShifted' => $card3DSecure->isLiabilityShifted($this->orderPayPal),
'paymentSource' => $this->getPaymentSourceName($this->orderPayPal),
Expand Down
7 changes: 5 additions & 2 deletions src/Repository/PayPalOrderRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public function savePayPalOrder(PayPalOrder $payPalOrder)
'is_express_checkout' => (int) $payPalOrder->isExpressCheckout(),
'customer_intent' => pSQL(implode(',', $payPalOrder->getCustomerIntent())),
'payment_token_id' => $payPalOrder->getPaymentTokenId() ? pSQL($payPalOrder->getPaymentTokenId()->getValue()) : null,
'tags' => pSQL(implode(',', $payPalOrder->getTags())),
],
false,
true,
Expand Down Expand Up @@ -112,7 +113,8 @@ public function getPayPalOrderById(PayPalOrderId $payPalOrderId)
$queryResult['is_card_fields'],
$queryResult['is_express_checkout'],
explode(',', $queryResult['customer_intent']),
$queryResult['payment_token_id'] ? new PaymentTokenId($queryResult['payment_token_id']) : null
$queryResult['payment_token_id'] ? new PaymentTokenId($queryResult['payment_token_id']) : null,
Matt75 marked this conversation as resolved.
Show resolved Hide resolved
explode(',', $queryResult['tags'])
);
}

Expand Down Expand Up @@ -150,7 +152,8 @@ public function getPayPalOrderByCartId($cartId)
$queryResult['is_card_fields'],
$queryResult['is_express_checkout'],
explode(',', $queryResult['customer_intent']),
$queryResult['payment_token_id'] ? new PaymentTokenId($queryResult['payment_token_id']) : null
$queryResult['payment_token_id'] ? new PaymentTokenId($queryResult['payment_token_id']) : null,
explode(',', $queryResult['tags'])
);
}

Expand Down
2 changes: 1 addition & 1 deletion translations/en.php
Original file line number Diff line number Diff line change
Expand Up @@ -674,4 +674,4 @@
$_MODULE['<{ps_checkout}prestashop>vaulttokenform_0db443e338b016aae2b24ce0be40beda'] = 'Make this my preferred payment method';
$_MODULE['<{ps_checkout}prestashop>vaulttokenform_6c493105989f12b2da5d1f770ac779f9'] = 'This payment method has been saved to your account.';
$_MODULE['<{ps_checkout}prestashop>vaulttokenform_ca3e15a8a9c7a796a1893277bf48b8ef'] = 'This payment method has been saved to your account and defined as favorite for future purchases.';
$_MODULE['<{ps_checkout}prestashop>vaulttokenform_f2a6c498fb90ee345d997f888fce3b18'] = 'Delete';
$_MODULE['<{ps_checkout}prestashop>vaulttokenform_f2a6c498fb90ee345d997f888fce3b18'] = 'Delete';
2 changes: 1 addition & 1 deletion translations/it.php
Original file line number Diff line number Diff line change
Expand Up @@ -593,4 +593,4 @@
$_MODULE['<{ps_checkout}prestashop>validate_ee02bd0a1dffdbc6ee993d07fa3997b7'] = 'Un cliente ha riscontrato un errore durante il pagamento';
$_MODULE['<{ps_checkout}prestashop>validate_fb970bdd962fa85ffc3459b4d5312b10'] = 'Transazione non riuscita. Riprova con un\'altra carta.';
$_MODULE['<{ps_checkout}prestashop>validate_fdef7819688bef617b84868f7713f883'] = 'Questo messaggio viene inviato automaticamente dal modulo PrestaShop Checkout';
$_MODULE['<{ps_checkout}prestashop>validate_ff74fb308795919496b905a116ae1da6'] = 'Questo metodo di pagamento non è disponibile';
$_MODULE['<{ps_checkout}prestashop>validate_ff74fb308795919496b905a116ae1da6'] = 'Questo metodo di pagamento non è disponibile';
44 changes: 44 additions & 0 deletions upgrade/upgrade-8.4.3.1.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?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
*/
if (!defined('_PS_VERSION_')) {
exit;
}

/**
* Update main function for module version 8.4.2.0
*
* @param Ps_checkout $module
*
* @return bool
*/
function upgrade_module_8_4_2_0($module)
{
try {
$db = Db::getInstance();

$db->execute('ALTER TABLE `' . _DB_PREFIX_ . 'pscheckout_order` ADD COLUMN `tags` varchar(255) DEFAULT NULL;');
} catch (Exception $exception) {
PrestaShopLogger::addLog($exception->getMessage(), 4, 1, 'Module', $module->id);

return false;
}

return true;
}
9 changes: 8 additions & 1 deletion views/templates/admin/ajaxPayPalOrder.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@
{if $psCheckoutCart->paypal_funding === 'card'}
<dt data-grid-area="card-sca">{l s='3D Secure' mod='ps_checkout'}</dt>
<dd data-grid-area="card-sca-value">
{if $orderPayPal.is3DSecureAvailable && $orderPayPal.isLiabilityShifted}
{if $orderPayPal.is3DSNotRequired}
<span class="badge rounded badge-warning">
{l s='Not required' mod='ps_checkout'}
</span>
{elseif $orderPayPal.is3DSecureAvailable && $orderPayPal.isLiabilityShifted}
<span class="badge rounded badge-success">
{l s='Success' mod='ps_checkout'}
</span>
Expand Down Expand Up @@ -112,6 +116,9 @@
</dl>
{if $psCheckoutCart->paypal_funding === 'card' && !$orderPayPal.isLiabilityShifted}
<div class="liability-explanation">
{if $orderPayPal.is3DSNotRequired}
{l s='Your 3D Secure settings for this transaction was SCA_WHEN_REQUIRED and the current transaction doesn’t require it.' mod='ps_checkout'}
L3RAZ marked this conversation as resolved.
Show resolved Hide resolved
{/if}
{l s='The bank issuer declined the liability shift. We advice you not to honor the order immediately, wait a few days in case of chargeback and contact the consumer to ensure authenticity of the transaction. For this type of cases we also recommend to consider Chargeback protection.' mod='ps_checkout'}
</div>
{/if}
Expand Down
Loading