btcPayService = $BTCPayService;
$this->logger = $logger;
$this->cache = $cache;
$this->scopeConfig = $scopeConfig;
$this->storeRepository = $storeRepository;
$this->storeManager = $storeManager;
}
public function getWebhookSecret(): ?string
{
return $this->scopeConfig->getValue('payment/btcpay/webhook_secret', ScopeInterface::SCOPE_STORE, 0);
}
public function getInstallationErrors(int $magentoStoreId, bool $useCache): array
{
$cacheKey = 'BTCPAY_INSTALLATION_ERRORS_STORE_' . $magentoStoreId;
$errors = false;
if ($useCache) {
$errors = $this->cache->load($cacheKey);
if ($errors !== false) {
$errors = \json_decode($errors, true);
}
}
if ($errors === false) {
$secret = $this->btcPayService->getWebhookSecret($magentoStoreId);
$errors = [];
$myPermissions = $this->btcPayService->getApiKeyPermissions('default', 0);
$permissionsSeparator = ':';
$specificStores = [];
if ($myPermissions) {
foreach ($myPermissions as $permission) {
$parts = explode($permissionsSeparator, $permission);
if (count($parts) === 1) {
// This is not a store-specific permission
} elseif (count($parts) === 2) {
// Store-specific permission
$btcPayStoreId = $parts[1];
if (!in_array($btcPayStoreId, $specificStores, true)) {
$specificStores[] = $btcPayStoreId;
}
} else {
throw new \Storefront\BTCPay\Model\BTCPay\Exception\InvalidPermissionFormat($permission);
}
}
$neededPermissions = [];
if (count($specificStores) === 0) {
// The user does not have any store-specific permissions, so he can access all stores.
$neededPermissions = self::REQUIRED_API_PERMISSIONS;
} else {
// The user has store-specific permissions, so these should all be present for each store
foreach ($specificStores as $specificStore) {
foreach (self::REQUIRED_API_PERMISSIONS as $essentialPermission) {
$neededPermissions[] = $essentialPermission . $permissionsSeparator . $specificStore;
}
}
}
sort($myPermissions);
sort($neededPermissions);
if ($myPermissions === $neededPermissions) {
// Permissions are exact
$this->btcPayService->removeDeletedBtcPayStores();
$btcPayStoreId = $this->btcPayService->getBtcPayStore($magentoStoreId);
if ($btcPayStoreId) {
if ($this->installWebhookIfNeeded($magentoStoreId, true)) {
$paymentMethods = $this->btcPayService->getBtcPayStorePaymentMethods($btcPayStoreId);
if (count($paymentMethods) === 0) {
$errors[] = __('Please configure a payment method in BTCPay Server for this BTCPay store.');
} else {
$enabledPaymentMethod = false;
foreach ($paymentMethods as $paymentMethod) {
if ($paymentMethod->isEnabled()) {
$enabledPaymentMethod = true;
}
if (!$enabledPaymentMethod) {
$errors[] = __('No enabled payment method for this BTCPay store in BTCPay Server.');
} else {
// No errors
}
}
}
} else {
$errors[] = __('Could not install the webhook in BTCPay Server for this Magento installation.');
}
} else {
$errors[] = __('Please select a BTCPay Server Store to use.');
}
} else {
// You either have too many permissions or too few!
$missingPermissions = array_diff($neededPermissions, $myPermissions);
$superfluousPermissions = array_diff($myPermissions, $neededPermissions);
if (count($missingPermissions)) {
foreach ($missingPermissions as $missingPermission) {
$errors[] = __('Your API key does not have the %1 permission. Please regenerate the API key.', $missingPermission);
}
}
if (count($superfluousPermissions)) {
foreach ($superfluousPermissions as $superfluousPermission) {
$errors[] = __('Your API key has the %1 permission, but we don\'t need it. Please use an API key that has the exact permissions for increased security.', '' . $superfluousPermission . '');
}
}
}
if ($useCache) {
$this->cache->save(\json_encode($errors, JSON_THROW_ON_ERROR), $cacheKey, [Config::CACHE_TAG], 15 * 60);
}
} else {
$errors[] = __('No permissions, please check if your API key is valid.');
}
}
return $errors;
}
public function installWebhookIfNeeded(int $magentoStoreId, bool $autoCreateIfNeeded): bool
{
try {
$apiKey = $this->btcPayService->getApiKey('default', 0);
if ($apiKey) {
$btcPayStoreId = $this->btcPayService->getBtcPayStore($magentoStoreId);
if ($btcPayStoreId) {
$webhookData = $this->btcPayService->getWebhooksForStore($magentoStoreId, $btcPayStoreId, $apiKey);
if (!$webhookData) {
if ($autoCreateIfNeeded) {
try {
$webhook = $this->btcPayService->createWebhook($magentoStoreId, $apiKey);
if (!$webhook) {
return false;
}
return true;
} catch (CannotCreateWebhook $e) {
$this->logger->error($e);
return false;
}
} else {
return false;
}
} else {
// Example: {
// "id": "8kR8zG81EERX59FGav5WWo",
// "enabled": true,
// "automaticRedelivery": true,
// "url": "http:\/\/mybtcpay.com\/admin\/V1\/btcpay\/webhook\/key\/8c7982460d83d57fb3e351ade2335aa88c42f5654eeee282a4e70e5751422dab\/",
// "authorizedEvents": {
// "everything": true,
// "specificEvents": []
// }
//}
if ($webhookData['enabled'] === true) {
if ($webhookData['automaticRedelivery'] === true) {
if ($webhookData['authorizedEvents']['everything'] === true) {
$url = $this->btcPayService->getWebhookUrl($magentoStoreId);
if ($webhookData['url'] === $url) {
return true;
}
}
}
}
return false;
}
}
}
return false;
} catch (ForbiddenException $e) {
// Bad configuration
return false;
}
}
public function getApiKeyInfo($scope, $scopeId)
{
$apiCreated = true;
$apiKeyInfo = [];
$apiKey = $this->btcPayService->getApiKey($scope, $scopeId);
if (!$apiKey) {
$apiKey = '' . __('No API key yet.') . '';
$apiCreated = false;
}
$generateUrl = $this->getGenerateApiKeyUrl($scopeId);
$apiKeyInfo['api_created'] = $apiCreated;
$apiKeyInfo['api_key'] = $apiKey;
$apiKeyInfo['generate_url'] = $generateUrl;
return $apiKeyInfo;
}
public function getAllMagentoStoreViews()
{
$stores = $this->storeManager->getStores();
return $stores;
}
public function getAllMagentoStoreViewIds()
{
$storeIds = [];
$stores = $this->getAllMagentoStoreViews();
foreach ($stores as $store) {
$storeId = $store->getId();
$storeIds[] = $storeId;
}
return $storeIds;
}
public function getGenerateApiKeyUrl(int $magentoStoreId)
{
$magentoRootDomain = $this->scopeConfig->getValue('web/secure/base_url', 'default', 0);
$magentoRootDomain = parse_url($magentoRootDomain, PHP_URL_HOST);
$magentoRootDomain = str_replace(['http://', 'https://'], '', $magentoRootDomain);
$magentoRootDomain = rtrim($magentoRootDomain, '/');
$redirectToUrlAfterCreation = $this->btcPayService->getReceiveApikeyUrl($magentoStoreId);
$applicationIdentifier = 'magento2';
$baseUrl = $this->btcPayService->getBtcPayServerBaseUrl();
$authorizeUrl = \BTCPayServer\Client\ApiKey::getAuthorizeUrl($baseUrl, \Storefront\BTCPay\Helper\Data::REQUIRED_API_PERMISSIONS, 'Magento 2 @ ' . $magentoRootDomain, true, false, $redirectToUrlAfterCreation, $applicationIdentifier);
return $authorizeUrl;
}
public function isBtcPayBaseUrlSet(): bool
{
if ($this->btcPayService->getBtcPayServerBaseUrl()) {
return true;
}
return false;
}
public function getAllBtcPayStoresAssociative($magentoStoreId): array
{
$baseUrl = $this->btcPayService->getBtcPayServerBaseUrl();
$apiKey = $this->btcPayService->getApiKey('default', 0);
return $this->btcPayService->getAllBtcPayStoresAssociative($baseUrl, $apiKey);
}
public function getSelectedBtcPayStoreForMagentoStore(int $magentoStoreId)
{
return $this->btcPayService->getBtcPayStore($magentoStoreId);
}
public function deleteWebhookIfNeeded(int $storeId, string $apiKey, string $btcPayStoreId)
{
$webhook = $this->btcPayService->getWebhooksForStore($storeId, $btcPayStoreId, $apiKey);
if ($webhook) {
$webhookId = $webhook['id'];
$deleted = $this->btcPayService->deleteWebhook($storeId, $btcPayStoreId, $webhookId, $apiKey);
}
return true;
}
public function deleteWebhooksIfNeeded($storeIds, $apiKey, $btcPayStoreId)
{
foreach ($storeIds as $storeId) {
$this->deleteWebhookIfNeeded((int)$storeId, $apiKey, $btcPayStoreId);
}
return true;
}
public function getCurrentStoreId()
{
return $this->btcPayService->getCurrentMagentoStoreId();
}
public function getApiKey($scope, $scopeId)
{
return $this->btcPayService->getApiKey($scope, $scopeId);
}
}