Skip to content

Commit

Permalink
Merge pull request #1234 from PrestaShopCorp/feat/PAYSHIP-2837
Browse files Browse the repository at this point in the history
PAYSHIP-2837 Added google pay to payment option list
  • Loading branch information
Matt75 authored Jul 10, 2024
2 parents d651e71 + 5f869c6 commit 72e2fb8
Show file tree
Hide file tree
Showing 24 changed files with 967 additions and 22 deletions.
8 changes: 8 additions & 0 deletions config/common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ services:
PrestaShop\Module\PrestashopCheckout\PayPal\Customer\Command\SavePayPalCustomerCommand: 'PrestaShop\Module\PrestashopCheckout\PayPal\Customer\CommandHandler\SavePayPalCustomerCommandHandler'
PrestaShop\Module\PrestashopCheckout\PayPal\OAuth\Query\GetPayPalGetUserIdTokenQuery: 'PrestaShop\Module\PrestashopCheckout\PayPal\OAuth\Query\GetPayPalGetUserIdTokenQueryHandler'
PrestaShop\Module\PrestashopCheckout\PayPal\Order\Command\SavePayPalOrderCommand: 'PrestaShop\Module\PrestashopCheckout\PayPal\Order\CommandHandler\SavePayPalOrderCommandHandler'
PrestaShop\Module\PrestashopCheckout\PayPal\GooglePay\Query\GetGooglePayTransactionInfoQuery: 'PrestaShop\Module\PrestashopCheckout\PayPal\GooglePay\Query\GetGooglePayTransactionInfoQueryHandler'

PrestaShop\Module\PrestashopCheckout\Event\SymfonyEventDispatcherFactory:
class: 'PrestaShop\Module\PrestashopCheckout\Event\SymfonyEventDispatcherFactory'
Expand Down Expand Up @@ -235,6 +236,7 @@ services:
- '@PrestaShop\Module\PrestashopCheckout\ShopContext'
- '@PrestaShop\Module\PrestashopCheckout\Context\PrestaShopContext'
- '@ps_checkout.logger'
- '@PrestaShop\Module\PrestashopCheckout\FundingSource\FundingSourceEligibilityConstraint'

PrestaShop\Module\PrestashopCheckout\Presenter\Store\Modules\PaypalModule:
class: 'PrestaShop\Module\PrestashopCheckout\Presenter\Store\Modules\PaypalModule'
Expand Down Expand Up @@ -471,3 +473,9 @@ services:
public: true
arguments:
- '@ps_checkout.module'

PrestaShop\Module\PrestashopCheckout\PayPal\GooglePay\Builder\GooglePayTransactionInfoBuilder:
class: 'PrestaShop\Module\PrestashopCheckout\PayPal\GooglePay\Builder\GooglePayTransactionInfoBuilder'
public: true
arguments:
- '@PrestaShop\Module\PrestashopCheckout\Translations\Translations'
6 changes: 6 additions & 0 deletions config/query-handlers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,9 @@ services:
- '@PrestaShop\Module\PrestashopCheckout\PayPal\OAuth\OAuthService'
- '@PrestaShop\Module\PrestashopCheckout\Repository\PayPalCustomerRepository'
- '@PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration'

PrestaShop\Module\PrestashopCheckout\PayPal\GooglePay\Query\GetGooglePayTransactionInfoQueryHandler:
class: 'PrestaShop\Module\PrestashopCheckout\PayPal\GooglePay\Query\GetGooglePayTransactionInfoQueryHandler'
public: true
arguments:
- '@PrestaShop\Module\PrestashopCheckout\PayPal\GooglePay\Builder\GooglePayTransactionInfoBuilder'
77 changes: 77 additions & 0 deletions controllers/front/googlepay.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?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
*/

use PrestaShop\Module\PrestashopCheckout\Cart\ValueObject\CartId;
use PrestaShop\Module\PrestashopCheckout\CommandBus\CommandBusInterface;
use PrestaShop\Module\PrestashopCheckout\Controller\AbstractFrontController;
use PrestaShop\Module\PrestashopCheckout\PayPal\GooglePay\Query\GetGooglePayTransactionInfoQuery;

/**
* This controller receive ajax call on customer click on a payment button
*/
class Ps_CheckoutGooglepayModuleFrontController extends AbstractFrontController
{
/**
* @var Ps_checkout
*/
public $module;

/**
* @var CommandBusInterface
*/
private $commandBus;

/**
* @see FrontController::postProcess()
*/
public function postProcess()
{
try {
$bodyValues = [];
$bodyContent = file_get_contents('php://input');

if (!empty($bodyContent)) {
$bodyValues = json_decode($bodyContent, true);
}

$action = $bodyValues['action'];

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

if ($action === 'getTransactionInfo') {
$this->getTransactionInfo($bodyValues);
} else {
$this->exitWithExceptionMessage(new Exception('Invalid request', 400));
}
} catch (Exception $exception) {
$this->exitWithExceptionMessage($exception);
}
}

private function getTransactionInfo(array $bodyValues)
{
$transactionInfo = $this->commandBus->handle(new GetGooglePayTransactionInfoQuery(new CartId($this->context->cart->id)));

$this->exitWithResponse([
'httpCode' => 200,
'body' => $transactionInfo->getPayload()->toArray(),
]);
}
}
12 changes: 9 additions & 3 deletions ps_checkout.php
Original file line number Diff line number Diff line change
Expand Up @@ -970,18 +970,22 @@ public function hookActionFrontControllerSetMedia()
$fundingSourcesSorted = [];
$payWithTranslations = [];
$isCardAvailable = false;
$vaultedPaymentMarks = [];
$customMarks = [];

foreach ($fundingSourceProvider->getSavedTokens($this->context->customer->id) as $fundingSource) {
$fundingSourcesSorted[] = $fundingSource->name;
$payWithTranslations[$fundingSource->name] = $fundingSource->label;
$vaultedPaymentMarks[$fundingSource->name] = $fundingSource->customMark;
$customMarks[$fundingSource->name] = $fundingSource->customMark;
}

foreach ($fundingSourceProvider->getAll() as $fundingSource) {
$fundingSourcesSorted[] = $fundingSource->name;
$payWithTranslations[$fundingSource->name] = $fundingSource->label;

if ($fundingSource->customMark !== null) {
$customMarks[$fundingSource->name] = $fundingSource->customMark;
}

if ('card' === $fundingSource->name) {
$isCardAvailable = $fundingSource->isEnabled;
}
Expand Down Expand Up @@ -1015,7 +1019,7 @@ public function hookActionFrontControllerSetMedia()
$this->name . 'LoaderImage' => $this->getPathUri() . 'views/img/loader.svg',
$this->name . 'PayPalButtonConfiguration' => $payPalConfiguration->getButtonConfiguration(),
$this->name . 'CardFundingSourceImg' => Media::getMediaPath(_PS_MODULE_DIR_ . $this->name . '/views/img/payment-cards.png'),
$this->name . 'VaultedPaymentMarks' => $vaultedPaymentMarks,
$this->name . 'CustomMarks' => $customMarks,
$this->name . 'CardLogos' => [
'AMEX' => Media::getMediaPath(_PS_MODULE_DIR_ . $this->name . '/views/img/amex.svg'),
'CB_NATIONALE' => Media::getMediaPath(_PS_MODULE_DIR_ . $this->name . '/views/img/cb.svg'),
Expand All @@ -1037,6 +1041,7 @@ public function hookActionFrontControllerSetMedia()
$this->name . 'ExpressCheckoutUrl' => $this->context->link->getModuleLink($this->name, 'ExpressCheckout', [], true),
$this->name . 'VaultUrl' => $this->context->link->getModuleLink($this->name, 'vault', [], true),
$this->name . 'PaymentUrl' => $this->context->link->getModuleLink($this->name, 'payment', [], true),
$this->name . 'GooglePayUrl' => $this->context->link->getModuleLink($this->name, 'googlepay', [], true),
$this->name . 'CheckoutUrl' => $this->getCheckoutPageUrl(),
$this->name . 'ConfirmUrl' => $this->context->link->getPageLink('order-confirmation', true, (int) $this->context->language->id),
$this->name . 'PayPalSdkConfig' => $payPalSdkConfigurationBuilder->buildConfiguration(),
Expand Down Expand Up @@ -1091,6 +1096,7 @@ public function hookActionFrontControllerSetMedia()
'express-button.cart.separator' => $this->l('or'),
'express-button.checkout.express-checkout' => $this->l('Express Checkout'),
'error.paypal-sdk' => $this->l('No PayPal Javascript SDK Instance'),
'error.google-pay-sdk' => $this->l('No Google Pay Javascript SDK Instance'),
'checkout.payment.others.link.label' => $this->l('Other payment methods'),
'checkout.payment.others.confirm.button.label' => $this->l('I confirm my order'),
'checkout.form.error.label' => $this->l('There was an error during the payment. Please try again or contact the support.'),
Expand Down
37 changes: 35 additions & 2 deletions src/Builder/Payload/OrderPayloadBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,15 @@ public function buildFullPayload()
$this->buildSupplementaryDataNode();
}

if ($this->fundingSource === 'paypal') {
$this->buildPayPalPaymentSourceNode();
switch ($this->fundingSource) {
case 'paypal':
$this->buildPayPalPaymentSourceNode();
break;
case 'google_pay':
$this->buildGooglePayPaymentSourceNode();
break;
default:
break;
}
}

Expand Down Expand Up @@ -731,4 +738,30 @@ private function buildPayPalPaymentSourceNode()

$this->getPayload()->addAndMergeItems($node);
}

private function buildGooglePayPaymentSourceNode()
{
/** @var \Ps_checkout $module */
$module = \Module::getInstanceByName('ps_checkout');
/** @var PayPalConfiguration $paypalConfiguration */
$paypalConfiguration = $module->getService(PayPalConfiguration::class);

if (!$paypalConfiguration->is3dSecureEnabled()) {
return;
}

$node = [
'payment_source' => [
'google_pay' => [
'attributes' => [
'verification' => [
'method' => $paypalConfiguration->getHostedFieldsContingencies(),
],
],
],
],
];

$this->getPayload()->addAndMergeItems($node);
}
}
6 changes: 4 additions & 2 deletions src/Checkout/CheckoutChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@ public function continueWithAuthorization($cartId, $orderPayPal)
throw new PsCheckoutException(sprintf('PayPal Order %s is already captured', $orderPayPal['id']));
}

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

if (in_array($paymentSource, ['google_pay', 'card'], true)) {
$card3DSecure = (new Card3DSecure())->continueWithAuthorization($orderPayPal);

$this->logger->info(
'3D Secure authentication result',
[
'authentication_result' => isset($orderPayPal['payment_source']['card']['authentication_result']) ? $orderPayPal['payment_source']['card']['authentication_result'] : null,
'authentication_result' => isset($orderPayPal['payment_source'][$paymentSource]['authentication_result']) ? $orderPayPal['payment_source'][$paymentSource]['authentication_result'] : null,
'decision' => str_replace(
[
(string) Card3DSecure::NO_DECISION,
Expand Down
8 changes: 7 additions & 1 deletion src/FundingSource/FundingSourceCollectionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ public function create()
$blik->setIsEnabled($this->configuration->isEnabled('blik'));
$blik->setCountries($this->eligibilityConstraint->getCountries('blik'));

return [$paypal, $paylater, $card, $bancontact, $eps, $giropay, $ideal, $mybank, $p24, $blik];
// Google pay
$googlePay = new FundingSourceEntity('google_pay');
$googlePay->setPosition($this->configuration->getPosition('google_pay', 11));
$googlePay->setIsEnabled($this->configuration->isEnabled('google_pay'));
$googlePay->setCountries($this->eligibilityConstraint->getCountries('google_pay'));

return [$paypal, $paylater, $card, $bancontact, $eps, $giropay, $ideal, $mybank, $p24, $blik, $googlePay];
}
}
17 changes: 17 additions & 0 deletions src/FundingSource/FundingSourceEligibilityConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,25 @@ public function getCountries($fundingSourceName)
'mybank' => ['IT'],
'p24' => ['PL'],
'paylater' => ['FR', 'GB', 'US', 'ES', 'IT'],
'google_pay' => ['AU', 'AT', 'BE', 'BG', 'CA', 'CN', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LI', 'LT', 'LU', 'MK', 'MT', 'NL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB', 'US'],
];

return $countries[$fundingSourceName];
}

/**
* Get eligible currencies for PayPal funding sources
*
* @param string $fundingSourceName
*
* @return array
*/
public function getCurrencies($fundingSourceName)
{
$currencies = [
'google_pay' => ['AUD', 'BRL', 'CAD', 'CHF', 'CZK', 'DKK', 'EUR', 'GBP', 'HKD', 'HUF', 'ILS', 'JPY', 'MXN', 'NOK', 'NZD', 'PHP', 'PLN', 'SEK', 'SGD', 'THB', 'TWD', 'USD'],
];

return $currencies[$fundingSourceName];
}
}
12 changes: 9 additions & 3 deletions src/FundingSource/FundingSourcePresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ class FundingSourcePresenter
* @param FundingSourceTranslationProvider $translation
* @param CountryRepository $country
*/
public function __construct(FundingSourceTranslationProvider $translation, CountryRepository $country, PaymentMethodLogoProvider $paymentMethodLogoProvider)
{
public function __construct(
FundingSourceTranslationProvider $translation,
CountryRepository $country,
PaymentMethodLogoProvider $paymentMethodLogoProvider
) {
$this->translation = $translation;
$this->country = $country;
$this->paymentMethodLogoProvider = $paymentMethodLogoProvider;
Expand All @@ -67,7 +70,10 @@ public function present($entity, $isAdmin)
$entity->getPosition(),
$isAdmin ? $this->country->getCountryNames($entity->getCountries()) : $entity->getCountries(),
$entity->getIsEnabled(),
$entity->getIsToggleable()
$entity->getIsToggleable(),
null,
null,
$name === 'google_pay' ? $this->paymentMethodLogoProvider->getLogoByPaymentSource([$name => []]) : null
);
}

Expand Down
1 change: 1 addition & 0 deletions src/FundingSource/FundingSourceTranslationProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public function __construct(Module $module)
'maxima' => 'Maxima',
'mercadopago' => 'Mercado Pago',
'sepa' => 'SEPA',
'google_pay' => 'Google Pay',
'token' => $module->l('Pay with %s', 'fundingsourcetranslationprovider'),
];

Expand Down
22 changes: 12 additions & 10 deletions src/PayPal/Card3DSecure.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ public function is3DSecureAvailable(array $order)
*/
public function isLiabilityShifted(array $order)
{
$cardAuthenticationResult = $this->getAuthenticationResult($order);
$liabilityShift = $this->getLiabilityShift($cardAuthenticationResult);
$threeDSecure = $this->get3DSecure($cardAuthenticationResult);
$authenticationResult = $this->getAuthenticationResult($order);
$liabilityShift = $this->getLiabilityShift($authenticationResult);
$threeDSecure = $this->get3DSecure($authenticationResult);
$authenticationStatus = $this->getAuthenticationStatus($threeDSecure);

return ($liabilityShift === self::LIABILITY_SHIFT_POSSIBLE || $liabilityShift === self::LIABILITY_SHIFT_YES)
Expand Down Expand Up @@ -188,27 +188,29 @@ private function noLiabilityShift(array $cardAuthenticationResult)
*/
private function getAuthenticationResult(array $order)
{
return isset($order['payment_source']['card']['authentication_result']) ? $order['payment_source']['card']['authentication_result'] : null;
$fundingSource = isset($order['payment_source']) ? key($order['payment_source']) : '';

return isset($order['payment_source'][$fundingSource]['authentication_result']) ? $order['payment_source'][$fundingSource]['authentication_result'] : null;
}

/**
* @param array|null $cardAuthenticationResult
* @param array|null $authenticationResult
*
* @return string|null
*/
private function getLiabilityShift($cardAuthenticationResult)
private function getLiabilityShift($authenticationResult)
{
return isset($cardAuthenticationResult['liability_shift']) ? $cardAuthenticationResult['liability_shift'] : null;
return isset($authenticationResult['liability_shift']) ? $authenticationResult['liability_shift'] : null;
}

/**
* @param array|null $cardAuthenticationResult
* @param array|null $authenticationResult
*
* @return array|null
*/
private function get3DSecure($cardAuthenticationResult)
private function get3DSecure($authenticationResult)
{
return isset($cardAuthenticationResult['three_d_secure']) ? $cardAuthenticationResult['three_d_secure'] : null;
return isset($authenticationResult['three_d_secure']) ? $authenticationResult['three_d_secure'] : null;
}

/**
Expand Down
Loading

0 comments on commit 72e2fb8

Please sign in to comment.