Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static function getCountries(string $fundingSourceName): array
'ideal' => ['NL'],
'mybank' => ['IT'],
'p24' => ['PL'],
'paylater' => ['FR', 'GB', 'US', 'ES', 'IT'],
'paylater' => ['AU', 'DE', 'ES', 'FR', 'GB', 'IT', 'US'],
'google_pay' => ['AU', 'AT', 'BE', 'BG', 'CA', 'CN', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HK', 'HU', 'IE', 'IT', 'JP', 'LV', 'LI', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SG', 'SK', 'SI', 'ES', 'SE', 'GB', 'US'],
'apple_pay' => ['AU', 'AT', 'BE', 'BG', 'CA', 'CN', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HK', 'HU', 'IE', 'IT', 'JP', 'LV', 'LI', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'SG', 'SK', 'SI', 'ES', 'SE', 'GB', 'US'],
];
Expand All @@ -58,6 +58,7 @@ public static function getCurrencies(string $fundingSourceName): array
$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'],
'apple_pay' => ['AUD', 'BRL', 'CAD', 'CHF', 'CZK', 'DKK', 'EUR', 'GBP', 'HKD', 'HUF', 'ILS', 'JPY', 'MXN', 'NOK', 'NZD', 'PHP', 'PLN', 'SEK', 'SGD', 'THB', 'TWD', 'USD'],
'paylater' => ['EUR', 'USD', 'AUD', 'GBP'],
];

return isset($currencies[$fundingSourceName]) ? $currencies[$fundingSourceName] : [];
Expand Down
1 change: 1 addition & 0 deletions core/src/Settings/Configuration/DefaultConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,6 @@ class DefaultConfiguration
'PS_CHECKOUT_DISPLAY_LOGO_CART' => '1',
'PS_CHECKOUT_HOSTED_FIELDS_CONTINGENCIES' => 'SCA_WHEN_REQUIRED',
'PS_CHECKOUT_PAYPAL_BUTTON' => '{"shape":"pill","label":"pay","color":"gold"}',
'PS_CHECKOUT_PAY_LATER_CONFIG' => '{"cart":{"placement":"cart","status":"enabled","layout":"text","logo-type":"inline","text-color":"black","text-size":"12"},"category":{"placement":"category","status":"disabled","color":"white","layout":"flex","ratio":"8x1"},"checkout":{"placement":"checkout","status":"enabled","layout":"text","logo-type":"inline","text-color":"black","text-size":"12"},"homepage":{"placement":"homepage","status":"disabled","color":"white","layout":"flex","ratio":"8x1"},"product":{"placement":"product","status":"enabled","layout":"text","logo-type":"inline","text-color":"black","text-size":"12"}}',
];
}
11 changes: 11 additions & 0 deletions core/src/Settings/Configuration/PayPalConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ class PayPalConfiguration

const PS_CHECKOUT_DOMAIN_REGISTERED_LIVE = 'PS_CHECKOUT_DOMAIN_REGISTERED_LIVE';

const PS_CHECKOUT_PAYPAL_COUNTRY_MERCHANT = 'PS_CHECKOUT_PAYPAL_COUNTRY_MERCHANT';

// NOT CONFIGURATION
const PS_CHECKOUT_CUSTOMER_INTENT_VAULT = 'VAULT';

const PS_CHECKOUT_CUSTOMER_INTENT_FAVORITE = 'FAVORITE';
Expand Down Expand Up @@ -116,4 +119,12 @@ public function is3dSecureEnabled(): bool
{
return $this->getCardFieldsContingencies() !== 'NONE';
}

/**
* @return string
*/
public function getMerchantCountry(): string
{
return $this->configuration->get(self::PS_CHECKOUT_PAYPAL_COUNTRY_MERCHANT);
}
}
79 changes: 75 additions & 4 deletions core/src/Settings/Configuration/PayPalPayLaterConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,94 @@

namespace PsCheckout\Core\Settings\Configuration;

use PsCheckout\Infrastructure\Adapter\ConfigurationInterface;

class PayPalPayLaterConfiguration
{
/** @deprecated used only as fallback */
const PS_CHECKOUT_PAY_LATER_ORDER_PAGE = 'PS_CHECKOUT_PAY_IN_4X_ORDER_PAGE';

/** @deprecated used only as fallback */
const PS_CHECKOUT_PAY_LATER_PRODUCT_PAGE = 'PS_CHECKOUT_PAY_IN_4X_PRODUCT_PAGE';

const PS_CHECKOUT_PAY_LATER_ORDER_PAGE_BANNER = 'PS_CHECKOUT_PAY_LATER_ORDER_PAGE_BANNER';

/** @deprecated used only as fallback */
const PS_CHECKOUT_PAY_LATER_HOME_PAGE_BANNER = 'PS_CHECKOUT_PAY_LATER_HOME_PAGE_BANNER';

/** @deprecated used only as fallback */
const PS_CHECKOUT_PAY_LATER_CATEGORY_PAGE_BANNER = 'PS_CHECKOUT_PAY_LATER_CATEGORY_PAGE_BANNER';

const PS_CHECKOUT_PAY_LATER_PRODUCT_PAGE_BANNER = 'PS_CHECKOUT_PAY_LATER_PRODUCT_PAGE_BANNER';

const PS_CHECKOUT_PAY_LATER_ORDER_PAGE_BUTTON = 'PS_CHECKOUT_PAY_IN_4X_ORDER_PAGE_BUTTON';

const PS_CHECKOUT_PAY_LATER_CART_PAGE_BUTTON = 'PS_CHECKOUT_PAY_IN_4X_CART_PAGE_BUTTON';

const PS_CHECKOUT_PAY_LATER_PRODUCT_PAGE_BUTTON = 'PS_CHECKOUT_PAY_IN_4X_PRODUCT_PAGE_BUTTON';

const PS_CHECKOUT_PAY_LATER_CONFIG = 'PS_CHECKOUT_PAY_LATER_CONFIG';

/**
* @var ConfigurationInterface
*/
private $configuration;

/**
* @var array|null
*/
private $config;

public function __construct(ConfigurationInterface $configuration)
{
$this->configuration = $configuration;
$this->config = $this->configuration->getDeserializedRaw(self::PS_CHECKOUT_PAY_LATER_CONFIG);
}

/**
* Returns Pay Later customization, with fallback from old configuration values for banner and message statuses
*
* @return array[]
*/
public function getPayLaterMessagingConfiguration(): array
{
if (!$this->config) {
return $this->getPayLaterMessagingConfigurationLegacy();
}

return $this->config;
}

/**
* Returns the default Pay Later configuration
*
* @return array[]
*/
public function getPayLaterMessagingConfigurationDefault(): array
{
return [
'product' => ['status' => 'disabled'],
'homepage' => ['status' => 'disabled'],
'category' => ['status' => 'disabled'],
'checkout' => ['status' => 'disabled'],
'cart' => ['status' => 'disabled'],
];
}

public function isPayLaterMessagingEnabled($page): bool
{
return isset($this->config[$page]) && $this->config[$page]['status'] === 'enabled';
}

/**
* Returns Pay Later customization from legacy configuration values
*
* @return array[]
*/
private function getPayLaterMessagingConfigurationLegacy(): array
{
return [
'product' => ['status' => $this->configuration->getBoolean(self::PS_CHECKOUT_PAY_LATER_PRODUCT_PAGE) ? 'enabled': 'disabled'],
'homepage' => ['status' => $this->configuration->getBoolean(self::PS_CHECKOUT_PAY_LATER_HOME_PAGE_BANNER) ? 'enabled': 'disabled'],
'category' => ['status' => $this->configuration->getBoolean(self::PS_CHECKOUT_PAY_LATER_CATEGORY_PAGE_BANNER) ? 'enabled': 'disabled'],
'checkout' => ['status' => $this->configuration->getBoolean(self::PS_CHECKOUT_PAY_LATER_ORDER_PAGE) ? 'enabled': 'disabled'],
'cart' => ['status' => $this->configuration->getBoolean(self::PS_CHECKOUT_PAY_LATER_ORDER_PAGE) ? 'enabled': 'disabled'],
];
}
}
49 changes: 20 additions & 29 deletions core/src/Settings/Configuration/PayPalSdkConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ class PayPalSdkConfiguration
*/
private $logger;

/**
* @var PayPalPayLaterConfiguration
*/
private $payPalPayLaterConfiguration;

/**
* @param ContextInterface $context
* @param ConfigurationInterface $configuration
Expand All @@ -91,6 +96,7 @@ class PayPalSdkConfiguration
* @param PayPalCustomerRepositoryInterface $payPalCustomerRepository
* @param OAuthServiceInterface $oAuthService
* @param LoggerInterface $logger
* @param PayPalPayLaterConfiguration $payPalPayLaterConfiguration
*/
public function __construct(
ContextInterface $context,
Expand All @@ -100,7 +106,8 @@ public function __construct(
FundingSourcePresenterInterface $fundingSourcePresenter,
PayPalCustomerRepositoryInterface $payPalCustomerRepository,
OAuthServiceInterface $oAuthService,
LoggerInterface $logger
LoggerInterface $logger,
PayPalPayLaterConfiguration $payPalPayLaterConfiguration
) {
$this->context = $context;
$this->configuration = $configuration;
Expand All @@ -110,6 +117,7 @@ public function __construct(
$this->payPalCustomerRepository = $payPalCustomerRepository;
$this->oAuthService = $oAuthService;
$this->logger = $logger;
$this->payPalPayLaterConfiguration = $payPalPayLaterConfiguration;
}

/**
Expand Down Expand Up @@ -261,35 +269,18 @@ private function shouldIncludeMessagesComponent(): bool
{
$pageName = $this->getPageName();

if ('index' === $pageName && $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_HOME_PAGE_BANNER)) {
return true;
}

if ('category' === $pageName && $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_CATEGORY_PAGE_BANNER)) {
return true;
}

if (
in_array($pageName, ['cart', 'order']) &&
(
$this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_ORDER_PAGE) ||
$this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_ORDER_PAGE_BANNER)
)
) {
return true;
}

if (
'product' === $pageName &&
(
$this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_PRODUCT_PAGE) ||
$this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_PRODUCT_PAGE_BANNER)
)
) {
return true;
switch ($pageName) {
case 'cart':
case 'category':
case 'product':
return $this->payPalPayLaterConfiguration->isPayLaterMessagingEnabled($pageName);
case 'order':
return $this->payPalPayLaterConfiguration->isPayLaterMessagingEnabled('checkout');
case 'index':
return $this->payPalPayLaterConfiguration->isPayLaterMessagingEnabled('homepage');
default:
return false;
}

return false;
}

private function shouldIncludeGooglePayComponent(): bool
Expand Down
4 changes: 2 additions & 2 deletions infrastructure/src/Adapter/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ public function getDeserializedRaw(string $key)
$configuration = $this->get($key);

if (!$configuration) {
return '';
return [];
}

return json_decode($configuration);
return json_decode($configuration, true);
}

/**
Expand Down
24 changes: 15 additions & 9 deletions infrastructure/src/Validator/FrontControllerValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,17 @@ class FrontControllerValidator implements FrontControllerValidatorInterface
*/
private $configuration;

/**
* @var PayPalPayLaterConfiguration
*/
private $payPalPayLaterConfiguration;

public function __construct(
ConfigurationInterface $configuration
ConfigurationInterface $configuration,
PayPalPayLaterConfiguration $payPalPayLaterConfiguration
) {
$this->configuration = $configuration;
$this->payPalPayLaterConfiguration = $payPalPayLaterConfiguration;
}

/**
Expand All @@ -46,10 +53,10 @@ public function shouldLoadFrontCss(string $controller): bool
switch ($controller) {
// Homepage
case 'index':
return $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_HOME_PAGE_BANNER);
return $this->payPalPayLaterConfiguration->isPayLaterMessagingEnabled('homepage');
// Category
case 'category':
return $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_CATEGORY_PAGE_BANNER);
return $this->payPalPayLaterConfiguration->isPayLaterMessagingEnabled('category');
// Payment step
case 'orderopc':
case 'order':
Expand All @@ -74,22 +81,21 @@ public function shouldLoadFrontJS(string $controller): bool
switch ($controller) {
// Homepage
case 'index':
return $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_HOME_PAGE_BANNER);
return $this->payPalPayLaterConfiguration->isPayLaterMessagingEnabled('homepage');
// Category
case 'category':
return $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_CATEGORY_PAGE_BANNER);
return $this->payPalPayLaterConfiguration->isPayLaterMessagingEnabled('category');
case 'orderopc':
case 'order':
return true;
case 'product':
return $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_PRODUCT_PAGE)
|| $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_PRODUCT_PAGE_BANNER)
return
$this->payPalPayLaterConfiguration->isPayLaterMessagingEnabled('product')
|| $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_PRODUCT_PAGE_BUTTON)
|| $this->configuration->getBoolean(PayPalExpressCheckoutConfiguration::PS_CHECKOUT_EC_PRODUCT_PAGE)
|| $this->configuration->getBoolean(PayPalConfiguration::PS_CHECKOUT_DISPLAY_LOGO_PRODUCT);
case 'cart':
return $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_ORDER_PAGE)
|| $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_ORDER_PAGE_BANNER)
return $this->payPalPayLaterConfiguration->isPayLaterMessagingEnabled('cart')
|| $this->configuration->getBoolean(PayPalPayLaterConfiguration::PS_CHECKOUT_PAY_LATER_CART_PAGE_BUTTON)
|| $this->configuration->getBoolean(PayPalExpressCheckoutConfiguration::PS_CHECKOUT_EC_ORDER_PAGE)
|| $this->configuration->getBoolean(PayPalConfiguration::PS_CHECKOUT_DISPLAY_LOGO_CART);
Expand Down
64 changes: 64 additions & 0 deletions infrastructure/src/Validator/PayLaterValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace PsCheckout\Infrastructure\Validator;

use PsCheckout\Core\FundingSource\Constraint\FundingSourceConstraint;
use PsCheckout\Core\Settings\Configuration\PayPalConfiguration;
use PsCheckout\Infrastructure\Adapter\ContextInterface;

class PayLaterValidator implements PayLaterValidatorInterface
{
/**
* @var ContextInterface
*/
private $context;

/**
* @var PayPalConfiguration
*/
private $payPalConfiguration;

public function __construct(ContextInterface $context, PayPalConfiguration $payPalConfiguration)
{
$this->context = $context;
$this->payPalConfiguration = $payPalConfiguration;
}

public function isPayLaterAvailable(): bool
{
$merchantCountry = $this->payPalConfiguration->getMerchantCountry();
$countries = FundingSourceConstraint::getCountries('paylater');
$currency = $this->context->getCurrency()->iso_code;
$locale = $this->context->getLanguage()->locale;
$customerCountry = $this->context->getCountry()->iso_code;

// Define supported country-currency combinations for Pay Later messaging
$supportedCountryCurrencyMap = [
'AU' => 'AUD', // Australia
'FR' => 'EUR', // France
'DE' => 'EUR', // Germany
'IT' => 'EUR', // Italy
'ES' => 'EUR', // Spain
'GB' => 'GBP', // United Kingdom
'US' => 'USD', // United States
];

// Define locale to country mapping for website locale validation
$localeCountryMap = [
'en-AU' => 'AU', // Australia
'fr-FR' => 'FR', // France
'de-DE' => 'DE', // Germany
'it-IT' => 'IT', // Italy
'es-ES' => 'ES', // Spain
'en-GB' => 'GB', // United Kingdom
'en-US' => 'US', // United States
];

return in_array($merchantCountry, $countries, true)
&& $merchantCountry === $customerCountry
&& isset($supportedCountryCurrencyMap[$customerCountry])
&& $supportedCountryCurrencyMap[$customerCountry] === $currency
&& isset($localeCountryMap[$locale])
&& $localeCountryMap[$locale] === $merchantCountry;
}
}
29 changes: 29 additions & 0 deletions infrastructure/src/Validator/PayLaterValidatorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?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 PsCheckout\Infrastructure\Validator;

interface PayLaterValidatorInterface
{
/**
* @return bool
*/
public function isPayLaterAvailable(): bool;
}
Loading