From f279694a046bfe03d75376ca5a94769f1aa52b57 Mon Sep 17 00:00:00 2001 From: Henning Kuntzschmann Date: Wed, 5 Oct 2022 12:50:35 +0200 Subject: [PATCH 1/5] GH-1141 - Catch render errors on Amazon Sign In buttons to allow multiple buttons on the same page --- view/frontend/web/js/amazon-login-button.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/view/frontend/web/js/amazon-login-button.js b/view/frontend/web/js/amazon-login-button.js index 3ce150611..7eab11826 100755 --- a/view/frontend/web/js/amazon-login-button.js +++ b/view/frontend/web/js/amazon-login-button.js @@ -72,7 +72,12 @@ define([ $buttonRoot.html(''); $buttonContainer.empty().append($buttonRoot); this._loadButtonConfig(config, function (buttonConfig) { - amazon.Pay.renderButton('#' + $buttonRoot.empty().uniqueId().attr('id'), buttonConfig); + try { + amazon.Pay.renderButton('#' + $buttonRoot.empty().uniqueId().attr('id'), buttonConfig); + } catch (e) { + console.log('Amazon Login button render error: ' + e); + return; + } $('.amazon-sign-in-button-container .field-tooltip').fadeIn(); $('.login-with-amazon').click(function() { customerData.invalidate('*'); }); }); From 0f3a132e91405b080df8b37a5a64de1cf8a06065 Mon Sep 17 00:00:00 2001 From: Spencer Gabhart Date: Mon, 9 Jan 2023 11:02:27 -0500 Subject: [PATCH 2/5] ASD-916 - Key Upgrade API integration --- Api/KeyUpgradeInterface.php | 59 +++ .../System/Config/AutoKeyExchangeAdmin.php | 30 +- Controller/Adminhtml/Pay/ManualKeyUpgrade.php | 103 +++++ Model/Config/AutoKeyExchange.php | 87 +---- Model/Config/KeyManagement.php | 120 ++++++ Model/Config/KeyUpgrade.php | 363 ++++++++++++++++++ Setup/Patch/Data/PerformKeyUpgrade.php | 175 +++++++++ etc/di.xml | 1 + i18n/de_AT.csv | 3 + i18n/de_CH.csv | 3 + i18n/de_DE.csv | 3 + i18n/en_GB.csv | 3 + i18n/en_US.csv | 3 + i18n/es_AR.csv | 3 + i18n/es_CL.csv | 3 + i18n/es_CO.csv | 3 + i18n/es_CR.csv | 3 + i18n/es_ES.csv | 3 + i18n/es_MX.csv | 3 + i18n/es_PA.csv | 3 + i18n/es_PE.csv | 3 + i18n/es_VE.csv | 3 + i18n/fr_CA.csv | 3 + i18n/fr_FR.csv | 3 + i18n/it_CH.csv | 3 + i18n/it_IT.csv | 3 + .../system/config/autokeyexchange_admin.phtml | 137 ++++--- view/adminhtml/web/js/keyupgrade.js | 103 +++++ view/adminhtml/web/styles.css | 6 +- 29 files changed, 1095 insertions(+), 143 deletions(-) create mode 100644 Api/KeyUpgradeInterface.php create mode 100644 Controller/Adminhtml/Pay/ManualKeyUpgrade.php create mode 100644 Model/Config/KeyManagement.php create mode 100644 Model/Config/KeyUpgrade.php create mode 100644 Setup/Patch/Data/PerformKeyUpgrade.php create mode 100644 view/adminhtml/web/js/keyupgrade.js diff --git a/Api/KeyUpgradeInterface.php b/Api/KeyUpgradeInterface.php new file mode 100644 index 000000000..c0a2029d0 --- /dev/null +++ b/Api/KeyUpgradeInterface.php @@ -0,0 +1,59 @@ +autokeyexchange = $autokeyexchange; + $this->keyUpgrade = $keyUpgrade; } /** @@ -64,4 +72,20 @@ public function getCurrency() } return $currency; } + + /** + * Whether to display Key Upgrade or AKE + */ + public function canUpgrade() + { + return $this->keyUpgrade->getMwsKeyForScope(); + } + + /** + * Return Key Upgrade info + */ + public function getKeyUpgradeConfig() + { + return json_encode($this->keyUpgrade->getJsonAmazonKeyUpgradeConfig()); + } } diff --git a/Controller/Adminhtml/Pay/ManualKeyUpgrade.php b/Controller/Adminhtml/Pay/ManualKeyUpgrade.php new file mode 100644 index 000000000..90cdc4153 --- /dev/null +++ b/Controller/Adminhtml/Pay/ManualKeyUpgrade.php @@ -0,0 +1,103 @@ +config = $config; + $this->jsonResultFactory = $jsonResultFactory; + $this->cacheManager = $cacheManager; + $this->keyUpgrade = $keyUpgrade; + } + + public function execute() + { + $scopeType = $this->_request->getParam('scope'); + $scopeCode = (int) $this->_request->getParam('scopeCode'); + + $publicKeyId = $this->keyUpgrade->getPublicKeyId( + $scopeType, + $scopeCode, + $this->_request->getParam('accessKey') + ); + + $result = $this->jsonResultFactory->create(); + if (!empty($publicKeyId)) { + $this->keyUpgrade->updateKeysInConfig( + $publicKeyId, + $scopeType, + $scopeCode + ); + + $this->cacheManager->clean([CacheTypeConfig::TYPE_IDENTIFIER]); + $result->setData(['result' => 'success']); + $this->messageManager->addSuccessMessage('Amazon Pay keys upgraded successfully.'); + } else { + $result->setData(['result' => 'error']); + $this->messageManager->addErrorMessage('Amazon Pay keys could not be upgraded. ' + . 'See the paywithamazon.log for more details'); + } + + return $result; + } +} diff --git a/Model/Config/AutoKeyExchange.php b/Model/Config/AutoKeyExchange.php index 5754e9b5c..08ebf27b3 100755 --- a/Model/Config/AutoKeyExchange.php +++ b/Model/Config/AutoKeyExchange.php @@ -23,7 +23,7 @@ use Magento\Framework\App\Cache\Type\Config as CacheTypeConfig; use Magento\Backend\Model\UrlInterface; -class AutoKeyExchange +class AutoKeyExchange extends KeyManagement { const CONFIG_XML_PATH_PRIVATE_KEY = 'payment/amazon_payment/autokeyexchange/privatekey'; @@ -44,26 +44,6 @@ class AutoKeyExchange 'JPY' => 'ja', ]; - /** - * @var - */ - private $_storeId; - - /** - * @var - */ - private $_websiteId; - - /** - * @var string - */ - private $_scope; - - /** - * @var int - */ - private $_scopeId; - /** * @var AmazonHelper */ @@ -114,16 +94,6 @@ class AutoKeyExchange */ private $state; - /** - * @var \Magento\Framework\App\Request\Http - */ - private $request; - - /** - * @var \Magento\Store\Model\StoreManagerInterface - */ - private $storeManager; - /** * @var \Psr\Log\LoggerInterface */ @@ -185,46 +155,12 @@ public function __construct( $this->cacheManager = $cacheManager; $this->connection = $connection; $this->state = $state; - $this->request = $request; - $this->storeManager = $storeManager; $this->mathRandom = $mathRandom; $this->logger = $logger; $this->messageManager = $messageManager; - // Find store ID and scope - $this->_websiteId = $request->getParam('website', 0); - $this->_storeId = $request->getParam('store', 0); - $this->_scope = $request->getParam('scope'); - - // Website scope - if ($this->_websiteId) { - $this->_scope = !$this->_scope ? 'websites' : $this->_scope; - } else { - $this->_websiteId = $storeManager->getWebsite()->getId(); - } - - // Store scope - if ($this->_storeId) { - $this->_websiteId = $this->storeManager->getStore($this->_storeId)->getWebsite()->getId(); - $this->_scope = !$this->_scope ? 'stores' : $this->_scope; - } else { - $this->_storeId = $storeManager->getWebsite($this->_websiteId)->getDefaultStore()->getId(); - } - - // Set scope ID - switch ($this->_scope) { - case 'websites': - $this->_scopeId = $this->_websiteId; - break; - case 'stores': - $this->_scopeId = $this->_storeId; - break; - default: - $this->_scope = 'default'; - $this->_scopeId = 0; - break; - } + parent::__construct($request, $storeManager); } /** @@ -269,20 +205,9 @@ public function getListenerOrigins() /** * Generate and save RSA keys */ - public function generateKeys() + protected function generateKeys() { - // Magento 2.4.4 switches to phpseclib3, use that if it exists - if (class_exists(\phpseclib3\Crypt\RSA::class, true)) { - $keypair = \phpseclib3\Crypt\RSA::createKey(2048); - $keys = [ - "publickey" => $keypair->getPublicKey()->__toString(), - "privatekey" => $keypair->__toString() - ]; - } else { - $rsa = new \phpseclib\Crypt\RSA(); - $keys = $rsa->createKey(2048); - } - + $keys = parent::generateKeys(); $encrypt = $this->encryptor->encrypt($keys['privatekey']); $this->config @@ -363,9 +288,9 @@ public function getPrivateKey() public function decryptPayload($payloadJson, $autoEnable = true, $autoSave = true) { try { - $payload = (object) json_decode($payloadJson); + $payload = json_decode($payloadJson); - $publicKeyId = urldecode($payload->publicKeyId); + $publicKeyId = urldecode($payload['publicKeyId'] ?? ''); $decryptedKey = null; $success = openssl_private_decrypt( diff --git a/Model/Config/KeyManagement.php b/Model/Config/KeyManagement.php new file mode 100644 index 000000000..6deda3910 --- /dev/null +++ b/Model/Config/KeyManagement.php @@ -0,0 +1,120 @@ +request = $request; + $this->storeManager = $storeManager; + + // Find store ID and scope + $this->_websiteId = $request->getParam('website', 0); + $this->_storeId = $request->getParam('store', 0); + $this->_scope = $request->getParam('scope'); + + // Website scope + if ($this->_websiteId) { + $this->_scope = !$this->_scope ? 'websites' : $this->_scope; + } else { + $this->_websiteId = $storeManager->getWebsite()->getId(); + } + + // Store scope + if ($this->_storeId) { + $this->_websiteId = $this->storeManager->getStore($this->_storeId)->getWebsite()->getId(); + $this->_scope = !$this->_scope ? 'stores' : $this->_scope; + } else { + $this->_storeId = $storeManager->getWebsite($this->_websiteId)->getDefaultStore()->getId(); + } + + // Set scope ID + switch ($this->_scope) { + case 'websites': + $this->_scopeId = $this->_websiteId; + break; + case 'stores': + $this->_scopeId = $this->_storeId; + break; + default: + $this->_scope = 'default'; + $this->_scopeId = 0; + break; + } + } + + /** + * Generate and save RSA keys + * + * @return array + */ + protected function generateKeys() + { + // Magento 2.4.4 switches to phpseclib3, use that if it exists + if (class_exists(\phpseclib3\Crypt\RSA::class, true)) { + $keypair = \phpseclib3\Crypt\RSA::createKey(2048); + $keys = [ + "publickey" => $keypair->getPublicKey()->__toString(), + "privatekey" => $keypair->__toString() + ]; + } else { + $rsa = new \phpseclib\Crypt\RSA(); + $keys = $rsa->createKey(2048); + } + + return $keys; + } +} diff --git a/Model/Config/KeyUpgrade.php b/Model/Config/KeyUpgrade.php new file mode 100644 index 000000000..30ab84c89 --- /dev/null +++ b/Model/Config/KeyUpgrade.php @@ -0,0 +1,363 @@ +scopeConfig = $scopeConfig; + $this->amazonConfig = $amazonConfig; + $this->backendUrl = $backendUrl; + $this->curl = $curl; + $this->encryptor = $encryptor; + $this->config = $config; + $this->logger = $logger; + + parent::__construct($request, $storeManager); + } + + /** + * {@inheritDoc} + */ + public function getPublicKeyId( + string $scopeType, + int $scopeCode, + string $accessKey + ) { + if (isset($this->keys) && !empty($this->keys)) { + $this->resetKeys(); + } + + $sellerId = $this->scopeConfig->getValue( + 'payment/amazon_payment/merchant_id', + $scopeType, + $scopeCode + ); + + $secretKey = $this->encryptor->decrypt($this->scopeConfig->getValue( + 'payment/amazon_payment/secret_key', + $scopeType, + $scopeCode + )); + + $serviceUrl = $this->getServiceUrl($scopeType, $scopeCode); + if (empty($serviceUrl)) { + return ''; + } + + $resourcePathPrefix = $this->getReleaseMode(); + $resourcePath = $resourcePathPrefix . '/v2/publicKeyId'; + + $timestamp = gmdate("Y-m-d\TH:i:s\\Z", time()); + $params = [ + 'AWSAccessKeyId' => $accessKey, + 'Action' => self::ACTION, + 'SellerId' => $sellerId, + 'SignatureMethod' => self::SIGNATURE_METHOD, + 'SignatureVersion' =>self::SIGNATURE_VERSION, + 'Timestamp' => $timestamp + ]; + + $stringToSign = $this->generateStringToSign($params, $serviceUrl, $resourcePath); + $signature = base64_encode(hash_hmac('sha256', $stringToSign, $secretKey, true)); + $publicKey = str_replace("\r", '', $this->getKeyPair()['publickey']); + + $request = $this->createCurlRequest($serviceUrl, $resourcePath, $params, $signature, $publicKey); + + $this->curl->setOption(CURLOPT_RETURNTRANSFER, 1); + $this->curl->get($request); + $output = $this->curl->getBody(); + + $responseObj = json_decode($output); + $publicKeyId = $responseObj->publicKeyId ?? ''; + if (empty($publicKeyId)) { + $this->logger->debug('Unable to automatically upgrade public key for Merchant ID ' . $sellerId . + ', Access Key ' . $accessKey . ': ' . json_encode($responseObj)); + } + + return $publicKeyId; + } + + /** + * {@inheritDoc} + */ + public function getKeyPair() + { + if (empty($this->keys)) { + $this->generateKeys(); + } + + return $this->keys; + } + + /** + * Return true if this scope still has a CV1 access key set + * + * @return mixed + */ + public function getMwsKeyForScope() + { + $accessKey = $this->scopeConfig->getValue( + 'payment/amazon_payment/access_key', + $this->_scope, + $this->_scopeId + ); + + return $accessKey; + } + + /** + * Check if V2 public key ID already exists + * + * @return mixed + */ + public function getExistingPublicKeyId() + { + return $this->amazonConfig->getPublicKeyId($this->_scope, $this->_scopeId); + } + + /** + * {@inheritDoc} + */ + public function updateKeysInConfig( + $publicKeyId, + $scopeType, + $scopeId + ) { + //Save new public key and remove old access key + $this->config->saveConfig( + 'payment/amazon_payment_v2/public_key_id', + $publicKeyId, + $scopeType, + $scopeId + ); + + $this->config->deleteConfig( + 'payment/amazon_payment/access_key', + $scopeType, + $scopeId + ); + + // Save private key + $keyPair = $this->getKeyPair(); + $privateKeyValue = $this->encryptor->encrypt($keyPair['privatekey']); + $this->config->saveConfig( + 'payment/amazon_payment_v2/private_key', + $privateKeyValue, + $scopeType, + $scopeId + ); + } + + /** + * Generate config object for manual upgrade from admin section + * + * @return array + */ + public function getJsonAmazonKeyUpgradeConfig() + { + return [ + 'scope' => $this->_scope, + 'scopeCode' => $this->_scopeId, + 'accessKey' => $this->getMwsKeyForScope(), + 'keyUpgradeUrl' => $this->backendUrl->getUrl('amazon_pay/pay/manualKeyUpgrade') + ]; + } + + /** + * Generate RSA keypair + * + * @return void + */ + protected function generateKeys() + { + $keys = parent::generateKeys(); + $this->keys = $keys; + } + + /** + * Empty keypair for new public key ID request + * + * @return void + */ + private function resetKeys() + { + $this->keys = []; + } + + /** + * Get request domain based on AP region, e.g. 'pay-api.amazon.eu' + * + * @param string $scopeType + * @param int $scopeCode + * @return string + */ + private function getServiceUrl(string $scopeType, int $scopeCode) + { + $urlMap = [ + 'us' => 'pay-api.amazon.com', + 'de' => 'pay-api.amazon.eu', + 'uk' => 'pay-api.amazon.eu', + 'jp' => 'pay-api.amazon.jp' + ]; + $region = $this->amazonConfig->getRegion($scopeType, $scopeCode); + + return $urlMap[$region]; + } + + /** + * Get resource path prefix based on release mode (live or sandbox) + * + * @return string + */ + private function getReleaseMode() + { + // Live is currently the only available path + return '/live'; + } + + /** + * Create the request string from which a signature will be calculated + * + * @param array $params + * @param string $serviceUrl + * @param string $resourcePath + * @return string + */ + private function generateStringToSign(array &$params, string $serviceUrl, string $resourcePath) + { + ksort($params, SORT_NUMERIC); + + $uri = new Uri($serviceUrl); + $stringToSign = 'GET' . PHP_EOL + . $uri->getPath() . PHP_EOL + . $resourcePath . PHP_EOL + . http_build_query($params, "", "&", PHP_QUERY_RFC3986); + + return $stringToSign; + } + + /** + * Create a request executable by a CurlHandle + * + * @param string $domain + * @param string $resourcePath + * @param array $params + * @param string $signature + * @param string $publicKey + * @return string + */ + private function createCurlRequest( + string $domain, + string $resourcePath, + array $params, + string $signature, + string $publicKey + ) { + $params['PublicKey'] = $publicKey; + $params['Signature'] = $signature; + + $queryString = http_build_query($params, '', '&', PHP_QUERY_RFC3986); + + $request = $domain + . $resourcePath + . '?' . str_replace('SellerId', 'MerchantId', $queryString); + + return 'https://' . $request; + } +} diff --git a/Setup/Patch/Data/PerformKeyUpgrade.php b/Setup/Patch/Data/PerformKeyUpgrade.php new file mode 100644 index 000000000..4df74ed88 --- /dev/null +++ b/Setup/Patch/Data/PerformKeyUpgrade.php @@ -0,0 +1,175 @@ + 'payment/amazon_payment_v2/active', + 'payment/amazon_payment/merchant_id' => 'payment/amazon_payment_v2/merchant_id', + 'payment/amazon_payment/client_id' => 'payment/amazon_payment_v2/store_id', + 'payment/amazon_payment/lwa_enabled' => 'payment/amazon_payment_v2/lwa_enabled', + 'payment/amazon_payment/payment_action' => 'payment/amazon_payment_v2/payment_action', + 'payment/amazon_payment/button_color' => 'payment/amazon_payment_v2/button_color', + 'payment/amazon_payment/allowed_ips' => 'payment/amazon_payment_v2/allowed_ips' + ]; + + /** + * @var KeyUpgradeInterface + */ + private $keyUpgrade; + + /** + * @var ConfigInterface + */ + private $config; + + /** + * @var EncryptorInterface + */ + private $encryptor; + + /** + * @var ModuleDataSetupInterface + */ + private $moduleDataSetup; + + /** + * @param KeyUpgradeInterface $keyUpgrade + * @param ConfigInterface $config + * @param EncryptorInterface $encryptor + * @param ModuleDataSetupInterface $moduleDataSetup + */ + public function __construct( + KeyUpgradeInterface $keyUpgrade, + ConfigInterface $config, + EncryptorInterface $encryptor, + ModuleDataSetupInterface $moduleDataSetup + ) { + $this->keyUpgrade = $keyUpgrade; + $this->config = $config; + $this->encryptor = $encryptor; + $this->moduleDataSetup = $moduleDataSetup; + } + + /** + * {@inheritDoc} + */ + public function apply() + { + $accessKeys = $this->getAccessKeysByScope(); + foreach ($accessKeys as [ + 'scope' => $scopeType, + 'scope_id' => $scopeId, + 'value' => $accessKey + ]) { + $publicKeyId = $this->keyUpgrade->getPublicKeyId( + $scopeType, + $scopeId, + $accessKey + ); + + if (!empty($publicKeyId)) { + $this->keyUpgrade->updateKeysInConfig( + $publicKeyId, + $scopeType, + $scopeId + ); + } + } + + // Upgrade all other configs + $savedConfigs = $this->getSavedV1Configs(); + foreach ($savedConfigs as [ + 'scope_id' => $scopeId, + 'scope' => $scopeType, + 'path' => $path, + 'value' => $value + ]) { + $this->config->saveConfig( + self::PATH_TRANSLATION_MAP[$path], + $value, + $scopeType, + $scopeId + ); + } + } + + /** + * Return a list of scopes with unique access key IDs + * + * @return array + */ + private function getAccessKeysByScope() + { + $conn = $this->moduleDataSetup->getConnection(); + $select = $conn->select() + ->from('core_config_data', ['scope_id', 'scope', 'value']) + ->where('path = ?', 'payment/amazon_payment/access_key') + ->order('scope_id'); + + return $conn->fetchAll($select); + } + + /** + * Return all explicitly saved Amazon Pay CV1 config values that need to have + * their paths updated + * + * @return array + */ + private function getSavedV1Configs() + { + $conn = $this->moduleDataSetup->getConnection(); + $select = $conn->select() + ->from('core_config_data', ['scope_id', 'scope', 'path', 'value']) + ->where('path in (?)', array_keys(self::PATH_TRANSLATION_MAP)) + ->order('scope_id'); + + return $conn->fetchAll($select); + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + + /** + * {@inheritdoc} + */ + public static function getVersion() + { + return '5.0.0'; + } +} diff --git a/etc/di.xml b/etc/di.xml index 258c6658a..e4e0f7945 100755 --- a/etc/di.xml +++ b/etc/di.xml @@ -21,6 +21,7 @@ + diff --git a/i18n/de_AT.csv b/i18n/de_AT.csv index 2847344df..d8492cbeb 100644 --- a/i18n/de_AT.csv +++ b/i18n/de_AT.csv @@ -193,3 +193,6 @@ "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Unsachgemäße Änderungen können zu einer fehlerhaften Integration führen. Ändern Sie diesen Wert nur bei Bedarf.
Ihre Kunden werden zu dieser URL weitergeleitet, wenn sie während des Bezahlvorgangs auf „Amazon Pay-Bezahlvorgang abbrechen und zu [Händlername] zurückkehren“ klicken. Standardmäßig werden Ihre Kunden auf die Warenkorbseite geleitet." "Amazon Sign In cancel URL Path","URL-Pfad bei Abbruch der Anmeldung mit Amazon (nur für die Regionen EU/UK)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Unsachgemäße Änderungen können zu einer fehlerhaften Integration führen. Ändern Sie diesen Wert nur bei Bedarf.
Ihre Kunden werden zu dieser URL weitergeleitet, wenn sie auf der Seite „Mit Amazon anmelden“ auf „Abbrechen“ klicken. Tragen Sie keinen vorangestellten Schrägstrich ein. Standardmäßig werden Ihre Kunden zur vorherigen Seite zurückgeleitet." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay funktioniert erst, wenn die mit Ihrer Konfiguration verknüpften Legacy-Schlüssel aktualisiert wurden. Klicken Sie auf die Schaltfläche unten, um Ihre Anmeldeinformationen zu aktualisieren." +"Upgrade your legacy Amazon Pay credentials","Aktualisieren Sie Ihre alten Amazon Pay-Anmeldeinformationen" +"Updating your config with new keys, please wait...","Aktualisieren Ihrer Konfiguration mit neuen Schlüsseln, bitte warten..." diff --git a/i18n/de_CH.csv b/i18n/de_CH.csv index 2847344df..d8492cbeb 100644 --- a/i18n/de_CH.csv +++ b/i18n/de_CH.csv @@ -193,3 +193,6 @@ "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Unsachgemäße Änderungen können zu einer fehlerhaften Integration führen. Ändern Sie diesen Wert nur bei Bedarf.
Ihre Kunden werden zu dieser URL weitergeleitet, wenn sie während des Bezahlvorgangs auf „Amazon Pay-Bezahlvorgang abbrechen und zu [Händlername] zurückkehren“ klicken. Standardmäßig werden Ihre Kunden auf die Warenkorbseite geleitet." "Amazon Sign In cancel URL Path","URL-Pfad bei Abbruch der Anmeldung mit Amazon (nur für die Regionen EU/UK)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Unsachgemäße Änderungen können zu einer fehlerhaften Integration führen. Ändern Sie diesen Wert nur bei Bedarf.
Ihre Kunden werden zu dieser URL weitergeleitet, wenn sie auf der Seite „Mit Amazon anmelden“ auf „Abbrechen“ klicken. Tragen Sie keinen vorangestellten Schrägstrich ein. Standardmäßig werden Ihre Kunden zur vorherigen Seite zurückgeleitet." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay funktioniert erst, wenn die mit Ihrer Konfiguration verknüpften Legacy-Schlüssel aktualisiert wurden. Klicken Sie auf die Schaltfläche unten, um Ihre Anmeldeinformationen zu aktualisieren." +"Upgrade your legacy Amazon Pay credentials","Aktualisieren Sie Ihre alten Amazon Pay-Anmeldeinformationen" +"Updating your config with new keys, please wait...","Aktualisieren Ihrer Konfiguration mit neuen Schlüsseln, bitte warten..." diff --git a/i18n/de_DE.csv b/i18n/de_DE.csv index 2847344df..d8492cbeb 100644 --- a/i18n/de_DE.csv +++ b/i18n/de_DE.csv @@ -193,3 +193,6 @@ "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Unsachgemäße Änderungen können zu einer fehlerhaften Integration führen. Ändern Sie diesen Wert nur bei Bedarf.
Ihre Kunden werden zu dieser URL weitergeleitet, wenn sie während des Bezahlvorgangs auf „Amazon Pay-Bezahlvorgang abbrechen und zu [Händlername] zurückkehren“ klicken. Standardmäßig werden Ihre Kunden auf die Warenkorbseite geleitet." "Amazon Sign In cancel URL Path","URL-Pfad bei Abbruch der Anmeldung mit Amazon (nur für die Regionen EU/UK)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Unsachgemäße Änderungen können zu einer fehlerhaften Integration führen. Ändern Sie diesen Wert nur bei Bedarf.
Ihre Kunden werden zu dieser URL weitergeleitet, wenn sie auf der Seite „Mit Amazon anmelden“ auf „Abbrechen“ klicken. Tragen Sie keinen vorangestellten Schrägstrich ein. Standardmäßig werden Ihre Kunden zur vorherigen Seite zurückgeleitet." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay funktioniert erst, wenn die mit Ihrer Konfiguration verknüpften Legacy-Schlüssel aktualisiert wurden. Klicken Sie auf die Schaltfläche unten, um Ihre Anmeldeinformationen zu aktualisieren." +"Upgrade your legacy Amazon Pay credentials","Aktualisieren Sie Ihre alten Amazon Pay-Anmeldeinformationen" +"Updating your config with new keys, please wait...","Aktualisieren Ihrer Konfiguration mit neuen Schlüsseln, bitte warten..." diff --git a/i18n/en_GB.csv b/i18n/en_GB.csv index a9716cfb5..5f85db408 100644 --- a/i18n/en_GB.csv +++ b/i18n/en_GB.csv @@ -134,3 +134,6 @@ Logging,Logging "Valued customer","Valued customer" "Unfortunately Amazon Pay declined the payment for your order in our online shop %storeName, please try placing the order again with another payment method.","Unfortunately Amazon Pay declined the payment for your order in our online shop %storeName, please try placing the order again with another payment method." "Kind regards","Kind regards" +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials." +"Upgrade your legacy Amazon Pay credentials","Upgrade your legacy Amazon Pay credentials" +"Updating your config with new keys, please wait...","Updating your config with new keys, please wait..." diff --git a/i18n/en_US.csv b/i18n/en_US.csv index d3ab486a1..37a27b7ce 100644 --- a/i18n/en_US.csv +++ b/i18n/en_US.csv @@ -136,3 +136,6 @@ "Kind regards","Kind regards" "Yes","Enabled" "No","Disabled" +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials." +"Upgrade your legacy Amazon Pay credentials","Upgrade your legacy Amazon Pay credentials" +"Updating your config with new keys, please wait...","Updating your config with new keys, please wait..." diff --git a/i18n/es_AR.csv b/i18n/es_AR.csv index bfd8c6756..d715d6001 100644 --- a/i18n/es_AR.csv +++ b/i18n/es_AR.csv @@ -198,3 +198,6 @@ Nota: El botón de Amazon Pay solo podrán verlo los clientes con las direccione "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se dirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar pago de Amazon Pay y volver a [nombre del vendedor]” durante el proceso de pago. De forma predeterminada, tus clientes volverán a la página previa al pago." "Amazon Sign In cancel URL Path","Ruta de URL de cancelación de inicio de sesión de Amazon (solo regiones de Reino Unido/UE)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se redirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar” en la página de Iniciar sesión con Amazon. No incluyas una barra diagonal al principio. De forma predeterminada, los clientes volverán a la página anterior." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay no funcionará hasta que se actualicen las claves heredadas asociadas con su configuración. Haga clic en el botón de abajo para actualizar sus credenciales." +"Upgrade your legacy Amazon Pay credentials","Actualice sus credenciales heredadas de Amazon Pay" +"Updating your config with new keys, please wait...","Actualizando su configuración con claves nuevas, por favor espere..." diff --git a/i18n/es_CL.csv b/i18n/es_CL.csv index bfd8c6756..d715d6001 100644 --- a/i18n/es_CL.csv +++ b/i18n/es_CL.csv @@ -198,3 +198,6 @@ Nota: El botón de Amazon Pay solo podrán verlo los clientes con las direccione "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se dirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar pago de Amazon Pay y volver a [nombre del vendedor]” durante el proceso de pago. De forma predeterminada, tus clientes volverán a la página previa al pago." "Amazon Sign In cancel URL Path","Ruta de URL de cancelación de inicio de sesión de Amazon (solo regiones de Reino Unido/UE)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se redirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar” en la página de Iniciar sesión con Amazon. No incluyas una barra diagonal al principio. De forma predeterminada, los clientes volverán a la página anterior." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay no funcionará hasta que se actualicen las claves heredadas asociadas con su configuración. Haga clic en el botón de abajo para actualizar sus credenciales." +"Upgrade your legacy Amazon Pay credentials","Actualice sus credenciales heredadas de Amazon Pay" +"Updating your config with new keys, please wait...","Actualizando su configuración con claves nuevas, por favor espere..." diff --git a/i18n/es_CO.csv b/i18n/es_CO.csv index bfd8c6756..d715d6001 100644 --- a/i18n/es_CO.csv +++ b/i18n/es_CO.csv @@ -198,3 +198,6 @@ Nota: El botón de Amazon Pay solo podrán verlo los clientes con las direccione "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se dirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar pago de Amazon Pay y volver a [nombre del vendedor]” durante el proceso de pago. De forma predeterminada, tus clientes volverán a la página previa al pago." "Amazon Sign In cancel URL Path","Ruta de URL de cancelación de inicio de sesión de Amazon (solo regiones de Reino Unido/UE)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se redirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar” en la página de Iniciar sesión con Amazon. No incluyas una barra diagonal al principio. De forma predeterminada, los clientes volverán a la página anterior." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay no funcionará hasta que se actualicen las claves heredadas asociadas con su configuración. Haga clic en el botón de abajo para actualizar sus credenciales." +"Upgrade your legacy Amazon Pay credentials","Actualice sus credenciales heredadas de Amazon Pay" +"Updating your config with new keys, please wait...","Actualizando su configuración con claves nuevas, por favor espere..." diff --git a/i18n/es_CR.csv b/i18n/es_CR.csv index bfd8c6756..d715d6001 100644 --- a/i18n/es_CR.csv +++ b/i18n/es_CR.csv @@ -198,3 +198,6 @@ Nota: El botón de Amazon Pay solo podrán verlo los clientes con las direccione "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se dirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar pago de Amazon Pay y volver a [nombre del vendedor]” durante el proceso de pago. De forma predeterminada, tus clientes volverán a la página previa al pago." "Amazon Sign In cancel URL Path","Ruta de URL de cancelación de inicio de sesión de Amazon (solo regiones de Reino Unido/UE)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se redirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar” en la página de Iniciar sesión con Amazon. No incluyas una barra diagonal al principio. De forma predeterminada, los clientes volverán a la página anterior." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay no funcionará hasta que se actualicen las claves heredadas asociadas con su configuración. Haga clic en el botón de abajo para actualizar sus credenciales." +"Upgrade your legacy Amazon Pay credentials","Actualice sus credenciales heredadas de Amazon Pay" +"Updating your config with new keys, please wait...","Actualizando su configuración con claves nuevas, por favor espere..." diff --git a/i18n/es_ES.csv b/i18n/es_ES.csv index bfd8c6756..d715d6001 100644 --- a/i18n/es_ES.csv +++ b/i18n/es_ES.csv @@ -198,3 +198,6 @@ Nota: El botón de Amazon Pay solo podrán verlo los clientes con las direccione "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se dirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar pago de Amazon Pay y volver a [nombre del vendedor]” durante el proceso de pago. De forma predeterminada, tus clientes volverán a la página previa al pago." "Amazon Sign In cancel URL Path","Ruta de URL de cancelación de inicio de sesión de Amazon (solo regiones de Reino Unido/UE)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se redirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar” en la página de Iniciar sesión con Amazon. No incluyas una barra diagonal al principio. De forma predeterminada, los clientes volverán a la página anterior." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay no funcionará hasta que se actualicen las claves heredadas asociadas con su configuración. Haga clic en el botón de abajo para actualizar sus credenciales." +"Upgrade your legacy Amazon Pay credentials","Actualice sus credenciales heredadas de Amazon Pay" +"Updating your config with new keys, please wait...","Actualizando su configuración con claves nuevas, por favor espere..." diff --git a/i18n/es_MX.csv b/i18n/es_MX.csv index bfd8c6756..d715d6001 100644 --- a/i18n/es_MX.csv +++ b/i18n/es_MX.csv @@ -198,3 +198,6 @@ Nota: El botón de Amazon Pay solo podrán verlo los clientes con las direccione "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se dirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar pago de Amazon Pay y volver a [nombre del vendedor]” durante el proceso de pago. De forma predeterminada, tus clientes volverán a la página previa al pago." "Amazon Sign In cancel URL Path","Ruta de URL de cancelación de inicio de sesión de Amazon (solo regiones de Reino Unido/UE)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se redirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar” en la página de Iniciar sesión con Amazon. No incluyas una barra diagonal al principio. De forma predeterminada, los clientes volverán a la página anterior." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay no funcionará hasta que se actualicen las claves heredadas asociadas con su configuración. Haga clic en el botón de abajo para actualizar sus credenciales." +"Upgrade your legacy Amazon Pay credentials","Actualice sus credenciales heredadas de Amazon Pay" +"Updating your config with new keys, please wait...","Actualizando su configuración con claves nuevas, por favor espere..." diff --git a/i18n/es_PA.csv b/i18n/es_PA.csv index bfd8c6756..d715d6001 100644 --- a/i18n/es_PA.csv +++ b/i18n/es_PA.csv @@ -198,3 +198,6 @@ Nota: El botón de Amazon Pay solo podrán verlo los clientes con las direccione "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se dirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar pago de Amazon Pay y volver a [nombre del vendedor]” durante el proceso de pago. De forma predeterminada, tus clientes volverán a la página previa al pago." "Amazon Sign In cancel URL Path","Ruta de URL de cancelación de inicio de sesión de Amazon (solo regiones de Reino Unido/UE)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se redirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar” en la página de Iniciar sesión con Amazon. No incluyas una barra diagonal al principio. De forma predeterminada, los clientes volverán a la página anterior." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay no funcionará hasta que se actualicen las claves heredadas asociadas con su configuración. Haga clic en el botón de abajo para actualizar sus credenciales." +"Upgrade your legacy Amazon Pay credentials","Actualice sus credenciales heredadas de Amazon Pay" +"Updating your config with new keys, please wait...","Actualizando su configuración con claves nuevas, por favor espere..." diff --git a/i18n/es_PE.csv b/i18n/es_PE.csv index bfd8c6756..d715d6001 100644 --- a/i18n/es_PE.csv +++ b/i18n/es_PE.csv @@ -198,3 +198,6 @@ Nota: El botón de Amazon Pay solo podrán verlo los clientes con las direccione "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se dirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar pago de Amazon Pay y volver a [nombre del vendedor]” durante el proceso de pago. De forma predeterminada, tus clientes volverán a la página previa al pago." "Amazon Sign In cancel URL Path","Ruta de URL de cancelación de inicio de sesión de Amazon (solo regiones de Reino Unido/UE)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se redirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar” en la página de Iniciar sesión con Amazon. No incluyas una barra diagonal al principio. De forma predeterminada, los clientes volverán a la página anterior." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay no funcionará hasta que se actualicen las claves heredadas asociadas con su configuración. Haga clic en el botón de abajo para actualizar sus credenciales." +"Upgrade your legacy Amazon Pay credentials","Actualice sus credenciales heredadas de Amazon Pay" +"Updating your config with new keys, please wait...","Actualizando su configuración con claves nuevas, por favor espere..." diff --git a/i18n/es_VE.csv b/i18n/es_VE.csv index bfd8c6756..d715d6001 100644 --- a/i18n/es_VE.csv +++ b/i18n/es_VE.csv @@ -198,3 +198,6 @@ Nota: El botón de Amazon Pay solo podrán verlo los clientes con las direccione "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se dirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar pago de Amazon Pay y volver a [nombre del vendedor]” durante el proceso de pago. De forma predeterminada, tus clientes volverán a la página previa al pago." "Amazon Sign In cancel URL Path","Ruta de URL de cancelación de inicio de sesión de Amazon (solo regiones de Reino Unido/UE)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Las modificaciones inadecuadas pueden interrumpir la integración. Solo debes cambiar este valor si es necesario.
Se redirigirá a tus clientes a esta URL cuando hagan clic en “Cancelar” en la página de Iniciar sesión con Amazon. No incluyas una barra diagonal al principio. De forma predeterminada, los clientes volverán a la página anterior." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay no funcionará hasta que se actualicen las claves heredadas asociadas con su configuración. Haga clic en el botón de abajo para actualizar sus credenciales." +"Upgrade your legacy Amazon Pay credentials","Actualice sus credenciales heredadas de Amazon Pay" +"Updating your config with new keys, please wait...","Actualizando su configuración con claves nuevas, por favor espere..." diff --git a/i18n/fr_CA.csv b/i18n/fr_CA.csv index 768ac7599..23adf8d79 100644 --- a/i18n/fr_CA.csv +++ b/i18n/fr_CA.csv @@ -195,3 +195,6 @@ "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Des modifications incorrectes peuvent casser l'intégration. Modifiez cette valeur uniquement si nécessaire.
Vos clients seront redirigés vers cette URL lorsqu'ils cliqueront sur « Annuler le paiement Amazon Pay et retourner à [nom du marchand] » lors du paiement. Par défaut, vos clients seront renvoyés vers votre page de pré-paiement." "Amazon Sign In cancel URL Path","Chemin de l'URL d'annulation de connexion Amazon (régions UE/Royaume-Uni uniquement)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Des modifications incorrectes peuvent casser l'intégration. Modifiez cette valeur uniquement si nécessaire.
Vos clients seront redirigés vers cette URL lorsqu'ils cliqueront sur « Annuler » sur la page Se connecter avec Amazon. N'entrez pas de barre oblique. Par défaut, vos clients seront renvoyés à la page précédente." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay ne sera pas fonctionnel tant que les anciennes clés associées à votre configuration ne seront pas mises à jour. Cliquez sur le bouton ci-dessous pour mettre à jour vos informations d'identification." +"Upgrade your legacy Amazon Pay credentials","Mettez à niveau vos anciennes informations d'identification Amazon Pay" +"Updating your config with new keys, please wait...","Mise à jour de votre configuration avec de nouvelles clés, veuillez patienter..." diff --git a/i18n/fr_FR.csv b/i18n/fr_FR.csv index 768ac7599..23adf8d79 100644 --- a/i18n/fr_FR.csv +++ b/i18n/fr_FR.csv @@ -195,3 +195,6 @@ "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Des modifications incorrectes peuvent casser l'intégration. Modifiez cette valeur uniquement si nécessaire.
Vos clients seront redirigés vers cette URL lorsqu'ils cliqueront sur « Annuler le paiement Amazon Pay et retourner à [nom du marchand] » lors du paiement. Par défaut, vos clients seront renvoyés vers votre page de pré-paiement." "Amazon Sign In cancel URL Path","Chemin de l'URL d'annulation de connexion Amazon (régions UE/Royaume-Uni uniquement)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Des modifications incorrectes peuvent casser l'intégration. Modifiez cette valeur uniquement si nécessaire.
Vos clients seront redirigés vers cette URL lorsqu'ils cliqueront sur « Annuler » sur la page Se connecter avec Amazon. N'entrez pas de barre oblique. Par défaut, vos clients seront renvoyés à la page précédente." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay ne sera pas fonctionnel tant que les anciennes clés associées à votre configuration ne seront pas mises à jour. Cliquez sur le bouton ci-dessous pour mettre à jour vos informations d'identification." +"Upgrade your legacy Amazon Pay credentials","Mettez à niveau vos anciennes informations d'identification Amazon Pay" +"Updating your config with new keys, please wait...","Mise à jour de votre configuration avec de nouvelles clés, veuillez patienter..." diff --git a/i18n/it_CH.csv b/i18n/it_CH.csv index 5f9048952..9ebc3a9e1 100644 --- a/i18n/it_CH.csv +++ b/i18n/it_CH.csv @@ -194,3 +194,6 @@ "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Le modifiche improprie possono danneggiare l'integrazione. Modifica questo valore solo se necessario.
I tuoi clienti verranno indirizzati a questo URL quando cliccheranno su “Annulla il checkout di Amazon Pay e torna a [nome venditore]” durante il pagamento. Per impostazione predefinita, i clienti verranno reindirizzati alla pagina di pre-pagamento." "Amazon Sign In cancel URL Path","Percorso URL di annullamento accesso ad Amazon (solo UE/Regno Unito)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Le modifiche improprie possono danneggiare l'integrazione. Modifica questo valore solo se necessario.
I tuoi clienti verranno reindirizzati a questo URL quando cliccheranno su “Annulla” nella pagina Accedi con Amazon. Non inserire una barra iniziale. Per impostazione predefinita, i clienti verranno reindirizzati alla pagina precedente." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay non funzionerà fino a quando le chiavi legacy associate alla tua configurazione non saranno aggiornate. Fai clic sul pulsante in basso per aggiornare le tue credenziali." +"Upgrade your legacy Amazon Pay credentials","Aggiorna le tue credenziali Amazon Pay legacy" +"Updating your config with new keys, please wait...","Aggiornamento della configurazione con nuove chiavi, attendere..." diff --git a/i18n/it_IT.csv b/i18n/it_IT.csv index 5f9048952..9ebc3a9e1 100644 --- a/i18n/it_IT.csv +++ b/i18n/it_IT.csv @@ -194,3 +194,6 @@ "Amazon Pay Checkout could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel Amazon Pay checkout and return to [merchant site]"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before checkout (EU/UK regions only).","Le modifiche improprie possono danneggiare l'integrazione. Modifica questo valore solo se necessario.
I tuoi clienti verranno indirizzati a questo URL quando cliccheranno su “Annulla il checkout di Amazon Pay e torna a [nome venditore]” durante il pagamento. Per impostazione predefinita, i clienti verranno reindirizzati alla pagina di pre-pagamento." "Amazon Sign In cancel URL Path","Percorso URL di annullamento accesso ad Amazon (solo UE/Regno Unito)" "Amazon Pay Sign In could potentially break if this value is modified. Do it only if it is needed by your website.
Amazon Pay will redirect to this URL if the customer clicks ""Cancel"" from the Amazon-hosted page. Do not use a leading slash. Leave blank to return the customer to the last page visited before sign in (EU/UK regions only).","Le modifiche improprie possono danneggiare l'integrazione. Modifica questo valore solo se necessario.
I tuoi clienti verranno reindirizzati a questo URL quando cliccheranno su “Annulla” nella pagina Accedi con Amazon. Non inserire una barra iniziale. Per impostazione predefinita, i clienti verranno reindirizzati alla pagina precedente." +"Amazon Pay will not be functional until the legacy keys associated with your configuration are updated. Click the button below to upgrade your credentials.","Amazon Pay non funzionerà fino a quando le chiavi legacy associate alla tua configurazione non saranno aggiornate. Fai clic sul pulsante in basso per aggiornare le tue credenziali." +"Upgrade your legacy Amazon Pay credentials","Aggiorna le tue credenziali Amazon Pay legacy" +"Updating your config with new keys, please wait...","Aggiornamento della configurazione con nuove chiavi, attendere..." diff --git a/view/adminhtml/templates/system/config/autokeyexchange_admin.phtml b/view/adminhtml/templates/system/config/autokeyexchange_admin.phtml index b5a73e8ef..cbdb2f504 100644 --- a/view/adminhtml/templates/system/config/autokeyexchange_admin.phtml +++ b/view/adminhtml/templates/system/config/autokeyexchange_admin.phtml @@ -20,70 +20,95 @@ $currency = $block->getCurrency();
- -
- -
- escapeHtml(__('An unsupported currency is currently selected. ' . - 'Please review our configuration guide.')); ?> - - - (escapeHtml(__('More Information')); ?>) - - -
- -
- -
+canUpgrade()): ?> +
+
escapeHtml( __( - "You'll be connecting/registering a %1 account based on your display currency of your store " . - "scope. For more information, see Amazon Pay for Magento 2.", - $block->getRegion() + "Amazon Pay will not be functional until the legacy keys associated with your configuration " . + "are updated. Click the button below to upgrade your credentials." ) ); ?> - - - (escapeHtml(__('More Information')); ?>) - -
- - + + - -   escapeHtml(__('or')); ?>   - - escapeHtml(__("I've already set up Amazon Pay with Magento and I want to edit " . - "my configuration.")); ?> - +
+ + -

- escapeHtml(__("In order to enable automatic account configuration using Amazon's secure key " . - 'exchange, please turn on secure admin pages in General > Web > Use secure URLs in Admin.')); ?> -

-

- escapeHtml(__('Updating your config with new keys, please wait...')); ?> -

-
-
+ +
+ +
+ escapeHtml(__('An unsupported currency is currently selected. ' . + 'Please review our configuration guide.')); ?> + + + (escapeHtml(__('More Information')); ?>) + + +
+ +
+ +
+ escapeHtml( + __( + "You'll be connecting/registering a %1 account based on your display currency of your store " . + "scope. For more information, see Amazon Pay for Magento 2.", + $block->getRegion() + ) + ); ?> + + + (escapeHtml(__('More Information')); ?>) + + +
+ + + -
- - -
- -
+ +   escapeHtml(__('or')); ?>   + + escapeHtml(__("I've already set up Amazon Pay with Magento and I want to edit " . + "my configuration.")); ?> + + +

+ escapeHtml(__("In order to enable automatic account configuration using Amazon's secure " . + 'key exchange, please turn on secure admin pages in General > Web > Use secure URLs in Admin.')); ?> +

+

+ escapeHtml(__('Updating your config with new keys, please wait...')); ?> +

+
+ +
+ + + +
+ +
- + + \ No newline at end of file diff --git a/view/adminhtml/web/js/keyupgrade.js b/view/adminhtml/web/js/keyupgrade.js new file mode 100644 index 000000000..8e18649b4 --- /dev/null +++ b/view/adminhtml/web/js/keyupgrade.js @@ -0,0 +1,103 @@ +/** + * Copyright © Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'jquery', + 'uiComponent', + 'mage/translate', + 'jquery/ui', + 'jquery/validate' + ], + function ($, Component, $t) { + 'use strict'; + + return Component.extend({ + + defaults: { + apKeyUpgradeSelector: '#amazon_keyupgrade_start' + }, + + /** + * Set list of observable attributes + * @returns {exports.initObservable} + */ + initObservable: function () { + var self = this; + + self._super(); + self.initEventHandlers(); + + return self; + }, + + /** + * Init event handlers + */ + initEventHandlers: function () { + var self = this; + + $(self.apKeyUpgradeSelector).click(function () { + $('#keyupgrade_message ').show(); + $.ajax({ + url: self.keyUpgradeUrl, + data: { + scope: self.scope, + scopeCode: self.scopeCode, + accessKey: self.accessKey + }, + type: 'GET', + cache: true, + dataType: 'json', + context: this, + + /** + * Response handler + * @param {Object} response + */ + success: function (response) { + document.location.replace(document.location + '#payment_amazon_payments-head'); + location.reload(); + } + }); + }); + }, + + /** + * display amazon simple path config section + */ + showAmazonConfig: function () { + this.$amazonAutoKeyExchange.show(); + this.$amazonAutoKeyExchangeBack.hide(); + if (this.$amazonCredentialsHeader.hasClass('open')) { + this.$amazonCredentialsHeader.click(); + } + }, + + /** + * hide amazon simple path config. + */ + hideAmazonConfig: function () { + this.$amazonAutoKeyExchange.hide(); + this.$amazonAutoKeyExchangeBack.show(); + if (!this.$amazonCredentialsHeader.hasClass('open')) { + this.$amazonCredentialsHeader.click(); + } + }, + } + ); + } +); diff --git a/view/adminhtml/web/styles.css b/view/adminhtml/web/styles.css index d9f5963a7..897e79c3e 100644 --- a/view/adminhtml/web/styles.css +++ b/view/adminhtml/web/styles.css @@ -1,4 +1,4 @@ -#amazon_https_required, #amazon_reload { color:red; display:none; } +#amazon_https_required, #amazon_reload, #keyupgrade_message, #reset-auto-key-exchange-message { color:red; display:none; } .complex.amazon-pay-section .amazon-pay-logo { display:inline-block; vertical-align: middle; margin: 0 20px 0 0px; width: 180px; height:60px; background-repeat: no-repeat, no-repeat, no-repeat; background-image: url('data:image/jpeg;base64,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bAAAAAAATmd0dmJvb2wAAAAAAEVtbERib29sAAAAAABJbnRyYm9vbAAAAAAAQmNrZ09iamMAAAABAAAAAAAAUkdCQwAAAAMAAAAAUmQgIGRvdWJAb+AAAAAAAAAAAABHcm4gZG91YkBv4AAAAAAAAAAAAEJsICBkb3ViQG/gAAAAAAAAAAAAQnJkVFVudEYjUmx0AAAAAAAAAAAAAAAAQmxkIFVudEYjUmx0AAAAAAAAAAAAAAAAUnNsdFVudEYjUHhsQFIAAAAAAAAAAAAKdmVjdG9yRGF0YWJvb2wBAAAAAFBnUHNlbnVtAAAAAFBnUHMAAAAAUGdQQwAAAABMZWZ0VW50RiNSbHQAAAAAAAAAAAAAAABUb3AgVW50RiNSbHQAAAAAAAAAAAAAAABTY2wgVW50RiNQcmNAWQAAAAAAAAAAABBjcm9wV2hlblByaW50aW5nYm9vbAAAAAAOY3JvcFJlY3RCb3R0b21sb25nAAAAAAAAAAxjcm9wUmVjdExlZnRsb25nAAAAAAAAAA1jcm9wUmVjdFJpZ2h0bG9uZwAAAAAAAAALY3JvcFJlY3RUb3Bsb25nAAAAAAA4QklNA+0AAAAAABAASAAAAAEAAQBIAAAAAQABOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD+AAAA4QklNBA0AAAAAAAQAAABaOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNJxAAAAAAAAoAAQAAAAAAAAABOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0EAAAAAAAAAgABOEJJTQQCAAAAAAAEAAAAADhCSU0EMAAAAAAAAgEBOEJJTQQtAAAAAAAGAAEAAAACOEJJTQQIAAAAAAAQAAAAAQAAAkAAAAJAAAAAADhCSU0EHgAAAAAABAAAAAA4QklNBBoAAAAAA0kAAAAGAAAAAAAAAAAAAAA8AAAAtAAAAAoAVQBuAHQAaQB0AGwAZQBkAC0AMwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAtAAAADwAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAG51bGwAAAACAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAADwAAAAAUmdodGxvbmcAAAC0AAAABnNsaWNlc1ZsTHMAAAABT2JqYwAAAAEAAAAAAAVzbGljZQAAABIAAAAHc2xpY2VJRGxvbmcAAAAAAAAAB2dyb3VwSURsb25nAAAAAAAAAAZvcmlnaW5lbnVtAAAADEVTbGljZU9yaWdpbgAAAA1hdXRvR2VuZXJhdGVkAAAAAFR5cGVlbnVtAAAACkVTbGljZVR5cGUAAAAASW1nIAAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAAA8AAAAAFJnaHRsb25nAAAAtAAAAAN1cmxURVhUAAAAAQAAAAAAAG51bGxURVhUAAAAAQAAAAAAAE1zZ2VURVhUAAAAAQAAAAAABmFsdFRhZ1RFWFQAAAABAAAAAAAOY2VsbFRleHRJc0hUTUxib29sAQAAAAhjZWxsVGV4dFRFWFQAAAABAAAAAAAJaG9yekFsaWduZW51bQAAAA9FU2xpY2VIb3J6QWxpZ24AAAAHZGVmYXVsdAAAAAl2ZXJ0QWxpZ25lbnVtAAAAD0VTbGljZVZlcnRBbGlnbgAAAAdkZWZhdWx0AAAAC2JnQ29sb3JUeXBlZW51bQAAABFFU2xpY2VCR0NvbG9yVHlwZQAAAABOb25lAAAACXRvcE91dHNldGxvbmcAAAAAAAAACmxlZnRPdXRzZXRsb25nAAAAAAAAAAxib3R0b21PdXRzZXRsb25nAAAAAAAAAAtyaWdodE91dHNldGxvbmcAAAAAADhCSU0EKAAAAAAADAAAAAI/8AAAAAAAADhCSU0EEQAAAAAAAQEAOEJJTQQUAAAAAAAEAAAAAjhCSU0EDAAAAAALTgAAAAEAAACfAAAANQAAAeAAAGNgAAALMgAYAAH/2P/tAAxBZG9iZV9DTQAC/+4ADkFkb2JlAGSAAAAAAf/bAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgANQCfAwEiAAIRAQMRAf/dAAQACv/EAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5/cRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//aAAwDAQACEQMRAD8A9VSSSSUpJJJJSkkkklKSSSSUpJJJJSkkkklKSSSSUpJJJJSkkkklKSSSSU//0NDrX1dy+pdbyL/rf1SnA6TLjhVjIa1pbO2pjKslramObX78m70/Vst/4NVf8X+Zfg/Wq/ouNlnL6W5twrIduqd6Ra6nKxxLq699bnMt9D9Fd/22s7oOR0TI+s2fnfW9zXPG8j1wXMFzHltlNjdf6PUz0sWh36P/AK8ifVbqWEz6+symVnHxc2y6vEqDI2tuE4h9Jv0KrW1/meyv1P8AR+9P6Ut6pK8TqHUvr31XpuJmWYf2uzIryL2kuc2gGqy1lTS72vscymr/AINirdK6b1fC+seV9Uun5xxW5LzRk31gtBrYz7Z69dTX/osh9H6Dcx/+E/nP8IzW+rpH/jo9QE678v8A9EpYJH/jt3if8NZ/7aNS/gr+LW+rmJl/Vv6/s6JReX02ucy8NG1trHUPy632U/Q9enZ/O/8AGf6bYtj609D6t1Trhd1rqFXT/q02BX+nDPotBO+q4MpfkXWF/wCks9X0KfoKlkkf+O3WJH02af8AoK9ZuTd0/M/xhZR+tDt2JRdZS1ts+mxjW/qbHD/B4759f9y21/6ZDx8FfxZ/V65vQ/rrT07ouf8AbOlX2Cslr2uqsbYzf/gv1f18e3/D0+//AAf+kXRfXT6q9OsuyfrF1DqeTiUsrY11NIaSS32V10b/APC3vdtYz/SLkrOrdGb9d8fqeDX6PSWZFIq9OvYC1o+z2X00sbucx137jPUV3/GJ1fN6l193R6g84/T9u2mqXOfa9oe+97GB3urqf6VH+j/S2f4RHWwrol/xbdJy8jqZ65a99eFgtsYNzi71LHt2vr/lV49f887/AE/pbP5u1D6VhXf4wutZl/VMm1mBjjfTRWRDGvLmYrKmWNspa706vUvu9L1LbP8Ag1s/VT64Ydt+P9Vj0t/TK31vqxgHF0Q11kWttZVbve31Hvu/Sb7fp/vrG+pPU8b6qda6j03rTjikMbWXOa53uqLnU6VNf7Mii71arPoJa6q7Oj9Qeq52B1/L+q+ZkOyKKja3HLySWvodsc2reTsotp/Sej/gn/zX01g/VPpXUOv29Q6SzNfi4dsW5r9bHP2Ptbj0e94/RufY+y//AEnprV+o9D+r/XPO69UxzcOqy+xr3DTfedtdB/4X0HerYz/B+z/SKX+Kgg9T6nB/wbf/AD5Yl3V2Zf4sLsvF611DozrJxqq3ONQJ2NtqtFDn0tP836m/37V0P+Mi22n6qZD6rH1O9WkF1bix0Gxm5u9ha5c79QCD9d+rwfzMj/24Yug/xmCfqlkD/haP/PrEDuobNWj6j43XunY3UOt9QzMzMyaa7Q4WbK6t7GENx8ZrfRZs/lfzv85am+ovUOpY3Vep/VfqN7ss9OO/GvsJLvTnbsc5xc/a5r6bq2O/mfU9Hf6bK1b6F9dPqxX0TGrvz68e7DorrvoullocxjQ7ZS79Jf8AyPQ9Xesn6ovzOp9Y+sH1qxKiKr2OpwWvH849obs7/u0Uep7v5yz00u9p7N7N+o31etuL+tdUy8jJtc54ORlbNC4nbVV7WsrZOxuxVPqpRfj9d699UbMq6/ptNQ9AvefUrFjW7hTaP5r9Hkf4P/C1eqzYsj6oVfUjMwMnO+tF+Pd1Wy1xvdn2gPLQBt9Ntjmb/wCx7/8ABf6Niv8A1CPTP+efVv2Qz0unHGY7ErLXMismqXCu39K1ll3q2M3pd0dnS/xd5uZV+0vq91K112Z0q8w+xznOdW/Tc02bnenvZ6lf/B3VqLrsnrf+Mb7PVdY3p/QaQ+5jHvax97x7GPawta/3Pb9L/uLZWofWVzfq39cMH6zEOGFm1PxOoBgklzWF+O6Pa3e/06f7GOm+q+Pm9N+pHVOv2QOqdSqyeouefHZZZjf2P8Kz/jUvFPg//9H0HL+q/wBXs3M+3ZXT6LsmQTY5gJcR3sH0bP8ArisWdNxm3/bsailueyn0KrnM4rB3tolkObVu/dVxJI6giyoaG3Exv2HR1F+Rdh1YHU7Nxfa9jQX7o3ublAbXtfsV9nSekjOPU68Wn7a+ScoMbvMtFc+p9L+bbsR8jFx8qv08isWN8D2/qn81ZT/q/ZSS7p2U+j/gyTH+cz/vzLFVlPmsf6A5iPeJ9vN/hR/m5/4HA2IxwT/SOGXYj3Mf+DL54t49I6Wc8dSOLUc4cZOwepo30v5z6X837EDqP1b6D1S9uR1DBpyLmiBa5vuIHDXPbDntb/LVT0frRT7W2C0eMsP/AJ8bW5OB9aX6EtZ5n0/++70z7+djy3MX4Y7H+NxLvug/z+Gv7/7OF0h0npgtxrRi1NfghzcQhjR6QeNr20wP0e6PzVUyXelmOZRlUYlmS9o2sq9S17oDGvvhw/d2b3s+ght6N1O/+m5ztvdlROv9r9G3/wACV/E6ZiYTHDFYGWOEG0+5xP8AKKdxZ8wr2jhhd3KfDkl4cGGX/qVAjhxa8Yyy2qMLh/jZf/VbW6Ybsmy45vp3vw7iyi7YAQ7btscz9z2PROpdB6N1Ytd1HDqyXsENe9oLgP3d/wBPZ7voKzh4rMTHbQwl0SXPPLnOO573f13I6mwQlDFGMyZSA1JPEdda4v6rFmlGWSRiAI9KHDt+lw/1kOJh4uFQ3GxKWY9DPo11tDWj+y1BwukdL6e+yzBxKsZ9v846pgaXQS73bf5TlcSUrG08XpHS8PJsy8XEqoyLp9W2tga524+o/c5v7z/csH/GY17vqjkhrS4iykkNBcYFjJMNXVJJWpw+n9B6RndJ6dbn4NN17cWgF9tYL5FbPa9zhv8Ab/LWzVVVTW2qlja62ANYxgDWtA4a1rfa1TSSU5tv1c6BdlHMu6djWZDiS6x1TSSTq5z9Pe7+U5XG4mJXkWZbKK25NjQ2y9rALHNb9Fj7AN72tRkklPnXXOuVfXmzB6B0am70X3Nvz8iyvZ6VTNHRu/P97v8ArvpV1/4RegfZcf7N9k9Nv2bZ6XpR7dkbPT2/ubPaipI2p//S9VSXyqkkp+qkl8qpJKfqpJfKqSSn6qSXyqkkp+qkl8qpJKfqpJfKqSSn6qSXyqkkp+qkl8qpJKfqpJfKqSSn6qSXyqkkp//ZOEJJTQQhAAAAAABhAAAAAQEAAAAPAEEAZABvAGIAZQAgAFAAaABvAHQAbwBzAGgAbwBwAAAAGQBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAgAEMAQwAgADIAMAAxADUALgA1AAAAAQA4QklNBAYAAAAAAAcACAAAAAEBAP/hDeFodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTMyIDc5LjE1OTI4NCwgMjAxNi8wNC8xOS0xMzoxMzo0MCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUuNSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE4LTA4LTIzVDIzOjM1OjMxLTA3OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDE4LTA4LTIzVDIzOjM1OjMxLTA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOC0wOC0yM1QyMzozNTozMS0wNzowMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpkY2ZmMGFlYy0zZTI1LTQ1NDctYmMyNi1mMDljNGQxMmVhNmMiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDplNWRkYzRkMC1hNzY3LTExZTgtODAyYS1iMTUzYWVhOTFiMWEiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo5N2YwNmQ2Zi1lYjgxLTBmNDMtOTIyMS1kMjlmYzc1YjU1NWMiIGRjOmZvcm1hdD0iaW1hZ2UvanBlZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyI+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6OTdmMDZkNmYtZWI4MS0wZjQzLTkyMjEtZDI5ZmM3NWI1NTVjIiBzdEV2dDp3aGVuPSIyMDE4LTA4LTIzVDIzOjM1OjMxLTA3OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxNS41IChXaW5kb3dzKSIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6ZGNmZjBhZWMtM2UyNS00NTQ3LWJjMjYtZjA5YzRkMTJlYTZjIiBzdEV2dDp3aGVuPSIyMDE4LTA4LTIzVDIzOjM1OjMxLTA3OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxNS41IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0idyI/Pv/uAA5BZG9iZQBkQAAAAAH/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAgICAgICAgICAgMDAwMDAwMDAwMBAQEBAQEBAQEBAQICAQICAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA//AABEIADwAtAMBEQACEQEDEQH/3QAEABf/xAGiAAAABgIDAQAAAAAAAAAAAAAHCAYFBAkDCgIBAAsBAAAGAwEBAQAAAAAAAAAAAAYFBAMHAggBCQAKCxAAAgEDBAEDAwIDAwMCBgl1AQIDBBEFEgYhBxMiAAgxFEEyIxUJUUIWYSQzF1JxgRhikSVDobHwJjRyChnB0TUn4VM2gvGSokRUc0VGN0djKFVWVxqywtLi8mSDdJOEZaOzw9PjKThm83UqOTpISUpYWVpnaGlqdnd4eXqFhoeIiYqUlZaXmJmapKWmp6ipqrS1tre4ubrExcbHyMnK1NXW19jZ2uTl5ufo6er09fb3+Pn6EQACAQMCBAQDBQQEBAYGBW0BAgMRBCESBTEGACITQVEHMmEUcQhCgSORFVKhYhYzCbEkwdFDcvAX4YI0JZJTGGNE8aKyJjUZVDZFZCcKc4OTRnTC0uLyVWV1VjeEhaOzw9Pj8ykalKS0xNTk9JWltcXV5fUoR1dmOHaGlqa2xtbm9md3h5ent8fX5/dIWGh4iJiouMjY6Pg5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6vr/2gAMAwEAAhEDEQA/AN/j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bk/70OjNbA+Gfx76+lgq6TY8G5spAQUym9qhtyyalsUkGMqlTb8U0bDUskdGkityDwLZRe3v3KPu6e3csF5acipum6x8J9zc3pr5HwHAtFYHKutsrg0IaoFIR5t+8j7vc3pLb3HNDWNi/GKyUWwp5jxFJuCCMFWmKkcRx6ND4YxD9uqCOER+FUivCEj06AkZiKGIKvC6bafxb3lT4MQh+nVNMOnSAvbRaUoummmgwKUp5U6gzxHMnis1ZNVanNTWtTWtanjWtfPpq29t3B7TwmM23trF0WEwWGpY6LGYvHwrBSUdNHchIo1+rMzFnZiXkdizEsSSVcu8ubFyjsm28t8s7TBY7DZx6IYIUCRxrUkgKPNmJZmNWd2Z2JZiSv3jeN05g3O93rer+W53W5kLyyyHU7sfMk+goABQKoCqAAB08+zrot697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de6//9bf49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3X/2Q=='); } .complex.amazon-pay-section .heading strong .amazon-payment-byline strong { font-weight: bold; } .section-config.with-button.amazon-pay-section .config-heading strong { font-weight: normal; } @@ -6,8 +6,8 @@ .complex.amazon-pay-section .amazon-payment-byline { display: inline-block; vertical-align: middle; width: 50%; } .amazon-pay-section.section-config.active > .admin__collapsible-block + input + fieldset { margin-left: 40px; } -.apake-getstarted { display:inline-block; padding:1em 0em; } -.apake-or { display:inline-block; } +.apkeys-getstarted { display:inline-block; padding:1em 0em; } +.apkeys-or { display:inline-block; } #amazon_autokeyexchange_back { display:none; margin-bottom:1em; margin-top:-0.5em; } #amazon_autokeyexchange td.creds { width:10%; } .autokeyexchange-wrapper-set.active .admin__collapsible-block { display:none; } From 7cb8bbb4777a97f697418f6f57dfb8bbcbcbb7a5 Mon Sep 17 00:00:00 2001 From: Spencer Gabhart Date: Tue, 7 Feb 2023 14:55:47 -0500 Subject: [PATCH 3/5] ASD-916 - KeyUpgrade safety/convention tweaks --- Helper/Key.php | 152 +++++++++++++++++++++++++++++++ Model/Config/AutoKeyExchange.php | 46 +++++++++- Model/Config/KeyUpgrade.php | 50 ++++++---- 3 files changed, 224 insertions(+), 24 deletions(-) create mode 100644 Helper/Key.php diff --git a/Helper/Key.php b/Helper/Key.php new file mode 100644 index 000000000..7d2e6a4dc --- /dev/null +++ b/Helper/Key.php @@ -0,0 +1,152 @@ +request = $request; + $this->storeManager = $storeManager; + + // Find store ID and scope + $this->_websiteId = $request->getParam('website', 0); + $this->_storeId = $request->getParam('store', 0); + $this->_scope = $request->getParam('scope'); + + // Website scope + if ($this->_websiteId) { + $this->_scope = !$this->_scope ? 'websites' : $this->_scope; + } else { + $this->_websiteId = $storeManager->getWebsite()->getId(); + } + + // Store scope + if ($this->_storeId) { + $this->_websiteId = $this->storeManager->getStore($this->_storeId)->getWebsite()->getId(); + $this->_scope = !$this->_scope ? 'stores' : $this->_scope; + } else { + $this->_storeId = $storeManager->getWebsite($this->_websiteId)->getDefaultStore()->getId(); + } + + // Set scope ID + switch ($this->_scope) { + case 'websites': + $this->_scopeId = $this->_websiteId; + break; + case 'stores': + $this->_scopeId = $this->_storeId; + break; + default: + $this->_scope = 'default'; + $this->_scopeId = 0; + break; + } + } + + /** + * Generate and save RSA keys + * + * @return array + */ + public function generateKeys() + { + // Magento 2.4.4 switches to phpseclib3, use that if it exists + if (class_exists(\phpseclib3\Crypt\RSA::class, true)) { + $keypair = \phpseclib3\Crypt\RSA::createKey(2048); + $keys = [ + "publickey" => $keypair->getPublicKey()->__toString(), + "privatekey" => $keypair->__toString() + ]; + } else { + $rsa = new \phpseclib\Crypt\RSA(); + $keys = $rsa->createKey(2048); + } + + return $keys; + } + + /** + * @return int + */ + public function getWebsiteId() + { + return $this->_websiteId; + } + + /** + * @return int + */ + public function getStoreId() + { + return $this->_storeId; + } + + /** + * @return string + */ + public function getScope() + { + return $this->_scope; + } + + /** + * @return int + */ + public function getScopeId() + { + return $this->_scopeId; + } +} diff --git a/Model/Config/AutoKeyExchange.php b/Model/Config/AutoKeyExchange.php index 08ebf27b3..c3e289b34 100755 --- a/Model/Config/AutoKeyExchange.php +++ b/Model/Config/AutoKeyExchange.php @@ -18,12 +18,13 @@ namespace Amazon\Pay\Model\Config; use Amazon\Pay\Helper\Data as AmazonHelper; +use Amazon\Pay\Helper\Key as KeyHelper; use Amazon\Pay\Model\AmazonConfig; use Magento\Framework\App\State; use Magento\Framework\App\Cache\Type\Config as CacheTypeConfig; use Magento\Backend\Model\UrlInterface; -class AutoKeyExchange extends KeyManagement +class AutoKeyExchange { const CONFIG_XML_PATH_PRIVATE_KEY = 'payment/amazon_payment/autokeyexchange/privatekey'; @@ -44,6 +45,26 @@ class AutoKeyExchange extends KeyManagement 'JPY' => 'ja', ]; + /** + * @var + */ + private $_storeId; + + /** + * @var + */ + private $_websiteId; + + /** + * @var string + */ + private $_scope; + + /** + * @var int + */ + private $_scopeId; + /** * @var AmazonHelper */ @@ -54,6 +75,11 @@ class AutoKeyExchange extends KeyManagement */ private $amazonConfig; + /** + * @var KeyHelper + */ + private $keyHelper; + /** * @var \Magento\Framework\App\Config\ConfigResource\ConfigInterface */ @@ -94,6 +120,11 @@ class AutoKeyExchange extends KeyManagement */ private $state; + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + private $storeManager; + /** * @var \Psr\Log\LoggerInterface */ @@ -112,6 +143,7 @@ class AutoKeyExchange extends KeyManagement /** * @param AmazonHelper $coreHelper * @param AmazonConfig $amazonConfig + * @param KeyHelper $keyHelper * @param \Magento\Framework\App\Config\ConfigResource\ConfigInterface $config * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\App\ProductMetadataInterface $productMeta @@ -119,7 +151,6 @@ class AutoKeyExchange extends KeyManagement * @param \Magento\Framework\Message\ManagerInterface $messageManager * @param \Magento\Framework\App\ResourceConnection $connection * @param \Magento\Framework\App\Cache\Manager $cacheManager - * @param \Magento\Framework\App\Request\Http $request * @param State $state * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param UrlInterface $backendUrl @@ -131,6 +162,7 @@ class AutoKeyExchange extends KeyManagement public function __construct( AmazonHelper $amazonHelper, AmazonConfig $amazonConfig, + KeyHelper $keyHelper, \Magento\Framework\App\Config\ConfigResource\ConfigInterface $config, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\App\ProductMetadataInterface $productMeta, @@ -138,7 +170,6 @@ public function __construct( \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Framework\App\ResourceConnection $connection, \Magento\Framework\App\Cache\Manager $cacheManager, - \Magento\Framework\App\Request\Http $request, \Magento\Framework\App\State $state, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Backend\Model\UrlInterface $backendUrl, @@ -147,6 +178,7 @@ public function __construct( ) { $this->amazonHelper = $amazonHelper; $this->amazonConfig = $amazonConfig; + $this->keyHelper = $keyHelper; $this->config = $config; $this->scopeConfig = $scopeConfig; $this->productMeta = $productMeta; @@ -158,9 +190,13 @@ public function __construct( $this->mathRandom = $mathRandom; $this->logger = $logger; + $this->storeManager = $storeManager; $this->messageManager = $messageManager; - parent::__construct($request, $storeManager); + $this->_storeId = $keyHelper->getStoreId(); + $this->_websiteId = $keyHelper->getWebsiteId(); + $this->_scope = $keyHelper->getScope(); + $this->_scopeId = $keyHelper->getScopeId(); } /** @@ -207,7 +243,7 @@ public function getListenerOrigins() */ protected function generateKeys() { - $keys = parent::generateKeys(); + $keys = $this->keyHelper->generateKeys(); $encrypt = $this->encryptor->encrypt($keys['privatekey']); $this->config diff --git a/Model/Config/KeyUpgrade.php b/Model/Config/KeyUpgrade.php index 30ab84c89..8d2a973f5 100644 --- a/Model/Config/KeyUpgrade.php +++ b/Model/Config/KeyUpgrade.php @@ -26,11 +26,11 @@ use Magento\Framework\HTTP\Client\Curl; use Magento\Store\Model\StoreManagerInterface; use Amazon\Pay\Api\KeyUpgradeInterface; +use Amazon\Pay\Helper\Key as KeyHelper; use Amazon\Pay\Logger\Logger; use Amazon\Pay\Model\AmazonConfig; -use Amazon\Pay\Model\Config\KeyManagement; -class KeyUpgrade extends KeyManagement implements KeyUpgradeInterface +class KeyUpgrade implements KeyUpgradeInterface { const ACTION = 'GetPublicKeyId'; @@ -38,6 +38,16 @@ class KeyUpgrade extends KeyManagement implements KeyUpgradeInterface const SIGNATURE_VERSION = '2'; + /** + * @var string + */ + private $_scope; + + /** + * @var int + */ + private $_scopeId; + /** * @var ScopeConfigInterface */ @@ -48,6 +58,11 @@ class KeyUpgrade extends KeyManagement implements KeyUpgradeInterface */ private $amazonConfig; + /** + * @var KeyHelper + */ + private $keyHelper; + /** * @var UrlInterface */ @@ -81,6 +96,7 @@ class KeyUpgrade extends KeyManagement implements KeyUpgradeInterface /** * @param ScopeConfigInterface $scopeConfig * @param AmazonConfig $amazonConfig + * @param KeyHelper $keyHelper * @param UrlInterface $backendUrl * @param Curl $curl * @param Http $request @@ -92,23 +108,23 @@ class KeyUpgrade extends KeyManagement implements KeyUpgradeInterface public function __construct( ScopeConfigInterface $scopeConfig, AmazonConfig $amazonConfig, + KeyHelper $keyHelper, UrlInterface $backendUrl, Curl $curl, - Http $request, - StoreManagerInterface $storeManager, EncryptorInterface $encryptor, ConfigInterface $config, Logger $logger ) { $this->scopeConfig = $scopeConfig; $this->amazonConfig = $amazonConfig; + $this->keyHelper = $keyHelper; $this->backendUrl = $backendUrl; $this->curl = $curl; $this->encryptor = $encryptor; $this->config = $config; $this->logger = $logger; - - parent::__construct($request, $storeManager); + $this->_scope = $keyHelper->getScope(); + $this->_scopeId = $keyHelper->getScopeId(); } /** @@ -137,6 +153,8 @@ public function getPublicKeyId( $serviceUrl = $this->getServiceUrl($scopeType, $scopeCode); if (empty($serviceUrl)) { + $this->logger->debug('Invalid Amazon Pay region detected in legacy credentials. ' . + 'Unable to perform automatic key upgrade.'); return ''; } @@ -160,7 +178,12 @@ public function getPublicKeyId( $request = $this->createCurlRequest($serviceUrl, $resourcePath, $params, $signature, $publicKey); $this->curl->setOption(CURLOPT_RETURNTRANSFER, 1); - $this->curl->get($request); + try { + $this->curl->get($request); + } catch (\Exception $e) { + $this->logger->error('Unable to successfully request a key upgrade: ' . $e->getMessage()); + return ''; + } $output = $this->curl->getBody(); $responseObj = json_decode($output); @@ -179,7 +202,7 @@ public function getPublicKeyId( public function getKeyPair() { if (empty($this->keys)) { - $this->generateKeys(); + $this->keys = $this->keyHelper->generateKeys(); } return $this->keys; @@ -259,17 +282,6 @@ public function getJsonAmazonKeyUpgradeConfig() ]; } - /** - * Generate RSA keypair - * - * @return void - */ - protected function generateKeys() - { - $keys = parent::generateKeys(); - $this->keys = $keys; - } - /** * Empty keypair for new public key ID request * From 8c1cc581c931b39f55ceaf97d2bad3d348cc78be Mon Sep 17 00:00:00 2001 From: Spencer Gabhart Date: Fri, 21 Apr 2023 16:05:20 -0400 Subject: [PATCH 4/5] GH-1184 - Restore backward compatibility when validating email addresses --- Helper/Customer.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Helper/Customer.php b/Helper/Customer.php index a42ebe31d..52cf7db5c 100644 --- a/Helper/Customer.php +++ b/Helper/Customer.php @@ -18,7 +18,6 @@ namespace Amazon\Pay\Helper; use Amazon\Pay\Api\Data\AmazonCustomerInterface; -use Magento\Framework\Validator\ValidatorChain; class Customer { @@ -79,8 +78,17 @@ public function getAmazonCustomer($buyerInfo) public function createCustomer(AmazonCustomerInterface $amazonCustomer) { - if (! ValidatorChain::is($amazonCustomer->getEmail(), '\Magento\Framework\Validator\EmailAddress')) { - throw new ValidatorException(__('the email address for your Amazon account is invalid')); + // Zend classes removed in Magento 2.4.6 + if (class_exists(\Magento\Framework\Validator\ValidatorChain::class, true)) { + if (! \Magento\Framework\Validator\ValidatorChain::is( + $amazonCustomer->getEmail(), \Magento\Framework\Validator\EmailAddress::class + )) { + throw new ValidatorException(__('the email address for your Amazon account is invalid')); + } + } else { + if (! \Zend_Validate::is($amazonCustomer->getEmail(), 'EmailAddress')) { + throw new ValidatorException(__('the email address for your Amazon account is invalid')); + } } $customerData = $this->customerLinkManagement->create($amazonCustomer); From 5506c02f06372006462979f162915b99196dac2f Mon Sep 17 00:00:00 2001 From: Spencer Gabhart Date: Wed, 26 Apr 2023 10:42:40 -0400 Subject: [PATCH 5/5] Version bump to 5.15.0 and update changelog --- CHANGELOG.md | 5 +++++ Helper/Customer.php | 3 ++- README.md | 2 +- composer.json | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d533c159..8aedd2d4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 5.15.0 +* Added Key Upgrade feature (automatically upgrade CV1 keys to CV2 if updating from legacy module) +* Fixed backward compatibility with Zend availability +* Fixed render issue with multiple Amazon Sign In buttons on the same page + ## 5.14.3 * Fixed PHP 7 compatibility diff --git a/Helper/Customer.php b/Helper/Customer.php index 52cf7db5c..5d9610066 100644 --- a/Helper/Customer.php +++ b/Helper/Customer.php @@ -81,7 +81,8 @@ public function createCustomer(AmazonCustomerInterface $amazonCustomer) // Zend classes removed in Magento 2.4.6 if (class_exists(\Magento\Framework\Validator\ValidatorChain::class, true)) { if (! \Magento\Framework\Validator\ValidatorChain::is( - $amazonCustomer->getEmail(), \Magento\Framework\Validator\EmailAddress::class + $amazonCustomer->getEmail(), + \Magento\Framework\Validator\EmailAddress::class )) { throw new ValidatorException(__('the email address for your Amazon account is invalid')); } diff --git a/README.md b/README.md index e43164907..55335adf1 100755 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ The following table provides an overview on which Git branch is compatible to wh Magento Version | Github Branch | Latest release ---|---|--- 2.2.6 - 2.2.11 (EOL) | [V2checkout-1.2.x](https://github.com/amzn/amazon-payments-magento-2-plugin/tree/V2checkout-1.2.x) | 1.20.0 (EOL) -2.3.0 - 2.4.x | [master](https://github.com/amzn/amazon-payments-magento-2-plugin/tree/master) | 5.14.3 +2.3.0 - 2.4.x | [master](https://github.com/amzn/amazon-payments-magento-2-plugin/tree/master) | 5.15.0 ## Release Notes See [CHANGELOG.md](/CHANGELOG.md) diff --git a/composer.json b/composer.json index 8972185b0..3c688a3de 100755 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "amzn/amazon-pay-magento-2-module", "description": "Official Magento2 Plugin to integrate with Amazon Pay", "type": "magento2-module", - "version": "5.14.3", + "version": "5.15.0", "license": [ "Apache-2.0" ],