btcPayService = $BTCPayService;
$this->logger = $logger;
$this->cache = $cache;
$this->scopeConfig = $scopeConfig;
$this->storeRepository = $storeRepository;
$this->storeManager = $storeManager;
}
public function getWebhookSecret(): ?string
{
$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($magentoStoreId);
$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
$btcPayStoreId = $this->btcPayService->getBtcPayStore($magentoStoreId);
if ($btcPayStoreId) {
if ($this->checkWebhook($magentoStoreId, true)) {
// There are no errors...
// TODO check if the store has any actual payment methods we can use. The store may still be misconfigured (i.e. no wallet is configured). To check this, we need a new API call, but we don't have it yet.
} 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 add it for this 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;
}
private function checkWebhook(int $magentoStoreId, bool $autoCreateIfNeeded): bool
{
try {
$webhookData = $this->btcPayService->getWebhookForStore($magentoStoreId);
} catch (ForbiddenException $e) {
// Bad configuration
return false;
}
if ($webhookData === null) {
if ($autoCreateIfNeeded) {
try {
//TODO: create webhook
/* $this->btcPayService->createWebhook($magentoStoreId);*/
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;
}
}
}
}
// TODO delete the webhook and create a new one with the required data...
return false;
}
}
public function getStoreViewsWithApiKeyInfo()
{
$magentoStoreViews = $this->getAllMagentoStoreViews();
$magentoStoreViewsWithApiKeyInfo = [];
foreach ($magentoStoreViews as $magentoStoreView) {
$storeId = (int)$magentoStoreView->getId();
$storeName = $magentoStoreView->getName();
$apiKey = $this->btcPayService->getApiKey($storeId);
if (!$apiKey) {
$apiKey = '' . __('No API key generated for this store yet.') . '';
}
$magentoStoreViewsWithApiKeyInfo[$storeName]['api_key'] = $apiKey;
$generateUrl = $this->getGenerateApiKeyUrl($storeId);
$magentoStoreViewsWithApiKeyInfo[$storeName]['generate_url'] = $generateUrl;
}
return $magentoStoreViewsWithApiKeyInfo;
}
public function getAllMagentoStoreViews()
{
$stores = $this->storeManager->getStores();
return $stores;
}
public function getGenerateApiKeyUrl(int $magentoStoreId)
{
$magentoRootDomain = $this->scopeConfig->getValue('web/secure/base_url', 'store', 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($magentoStoreId);
$authorizeUrl = \BTCPayServer\Client\ApiKey::getAuthorizeUrl($baseUrl, \Storefront\BTCPay\Helper\Data::REQUIRED_API_PERMISSIONS, 'Magento 2 @ ' . $magentoRootDomain, true, true, $redirectToUrlAfterCreation, $applicationIdentifier);
return $authorizeUrl;
}
public function isBtcPayBaseUrlSet():bool
{
if ($this->btcPayService->getBtcPayServerBaseUrl(0)) {
return true;
}
return false;
}
}