WIP
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
<?php
|
||||
|
||||
use Bastion\ApplicationFactory;
|
||||
use Openguru\OpenCartFramework\Logger\OpenCartLogAdapter;
|
||||
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
|
||||
use Openguru\OpenCartFramework\OpenCart\OcConfigDecorator;
|
||||
|
||||
$sysLibPath = rtrim(DIR_SYSTEM, '/') . '/library/oc_telegram_shop';
|
||||
$basePath = rtrim(DIR_APPLICATION, '/') . '/..';
|
||||
@@ -191,7 +194,12 @@ class ControllerExtensionModuleTgshop extends Controller
|
||||
],
|
||||
]);
|
||||
|
||||
$app->bootAndHandleRequest();
|
||||
|
||||
$app->bind(OcRegistryDecorator::class, fn () => new OcRegistryDecorator($this->registry));
|
||||
|
||||
$app
|
||||
->withLogger(fn () => new OpenCartLogAdapter($this->log, 'TeleCartAdmin'))
|
||||
->bootAndHandleRequest();
|
||||
}
|
||||
|
||||
protected function validate(): bool
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
|
||||
{# ChatID #}
|
||||
{% elseif item['type'] == 'chatid' %}
|
||||
{% if module_tgshop_bot_token %}
|
||||
<div class="input-group">
|
||||
<span class="input-group-btn">
|
||||
<button id="{{ settingKey }}-btn" class="btn btn-primary" type="button">
|
||||
@@ -161,6 +162,7 @@
|
||||
/>
|
||||
<script>
|
||||
$('#{{ settingKey }}-btn').click(function () {
|
||||
const $resultLabel = $('#{{ settingKey }}-result-label');
|
||||
const telegramToken = $('#module_tgshop_bot_token').val().trim(); // fetch from input
|
||||
if (! telegramToken) {
|
||||
alert('Сначала введите Telegram Bot Token!');
|
||||
@@ -176,7 +178,9 @@
|
||||
}
|
||||
|
||||
$('#{{ settingKey }}').val(data.data.chat_id);
|
||||
alert('ChatID успешно получен и подставлен в поле.');
|
||||
$resultLabel
|
||||
.text('✅ ChatID успешно получен и подставлен в поле. Не забудьте сохранить настройки!')
|
||||
.css('color', 'green');
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
@@ -187,6 +191,8 @@
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<div id="{{ settingKey }}-result-label"></div>
|
||||
|
||||
<button class="btn btn-link btn-xs" type="button" data-toggle="collapse" data-target="#{{ settingKey }}-collapse" aria-expanded="false" aria-controls="collapseExample">
|
||||
Инструкция как получить ChatID.
|
||||
</button>
|
||||
@@ -200,7 +206,11 @@
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
<div class="alert alert-warning">
|
||||
<strong>BotToken</strong> не указан. Пожалуйста, введите корректный BotToken и сохраните настройки. После этого здесь станет доступна настройка ChatID.
|
||||
</div>
|
||||
{% endif %}
|
||||
{% elseif item['type'] == 'tg_message_template' %}
|
||||
<div style="margin-bottom: 10px;">
|
||||
<textarea name="{{ settingKey }}"
|
||||
@@ -328,6 +338,7 @@
|
||||
const $input = $('#{{ settingKey }}');
|
||||
const $resultLabel = $('#{{ settingKey }}-result-label');
|
||||
const botToken = $input.val();
|
||||
const url = '/admin/index.php?route=extension/module/tgshop/handle&api_action=configureBotToken&user_token={{ user_token }}';
|
||||
|
||||
if (botToken.trim().length === 0) {
|
||||
$resultLabel
|
||||
@@ -336,34 +347,46 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$input.attr('disabled', true);
|
||||
$input.attr('readonly', true);
|
||||
$resultLabel.text('Проверяю...');
|
||||
|
||||
$.ajax({
|
||||
url: `https://api.telegram.org/bot${botToken}/getMe`,
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (resp) {
|
||||
if (resp.ok) {
|
||||
const user = resp.result;
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ botToken }),
|
||||
})
|
||||
.then(async (res) => {
|
||||
const response = await res.json().catch(() => null);
|
||||
|
||||
if (res.status === 422) {
|
||||
console.error(res, response);
|
||||
$resultLabel
|
||||
.text(`✅ Бот: @${user.username} (id: ${user.id})`)
|
||||
.text(`❌ Ошибка: ${response.error}`)
|
||||
.css('color', 'red');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Ошибка ${response.error || res.statusText}`);
|
||||
}
|
||||
|
||||
if (! response.id) {
|
||||
throw new Error(`bot token is not found in server response.`);
|
||||
}
|
||||
|
||||
$resultLabel
|
||||
.text(`✅ Бот: @${response.username} (id: ${response.id}) webhook: ${response.webhook_url}`)
|
||||
.css('color', 'green');
|
||||
} else {
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
$resultLabel
|
||||
.text(`❌ Ошибка: ${resp.description || 'неверный токен'}`)
|
||||
.text(`❌ Ошибка проверки BotToken.`)
|
||||
.css('color', 'red');
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
$resultLabel
|
||||
.text(`❌ Ошибка соединения (${xhr.status})`)
|
||||
.css('color', 'red');
|
||||
},
|
||||
complete: function () {
|
||||
$input.attr('disabled', false);
|
||||
}
|
||||
});
|
||||
})
|
||||
.finally(() => $input.attr('readonly', false))
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
use App\Adapters\OcModelCatalogProductAdapter;
|
||||
use App\ApplicationFactory;
|
||||
use App\Decorators\OcRegistryDecorator;
|
||||
use Cart\Cart;
|
||||
use Cart\Currency;
|
||||
use Cart\Tax;
|
||||
use Openguru\OpenCartFramework\ImageTool\ImageTool;
|
||||
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
|
||||
use Openguru\OpenCartFramework\Logger\OpenCartLogAdapter;
|
||||
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
|
||||
|
||||
$sysLibPath = rtrim(DIR_SYSTEM, '/') . '/library/oc_telegram_shop';
|
||||
$basePath = rtrim(DIR_APPLICATION, '/') . '/..';
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Bastion\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class BotTokenConfiguratorException extends Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Bastion\Handlers;
|
||||
|
||||
use Bastion\Exceptions\BotTokenConfiguratorException;
|
||||
use Bastion\Services\BotTokenConfigurator;
|
||||
use Exception;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Openguru\OpenCartFramework\Http\Request;
|
||||
use Openguru\OpenCartFramework\Http\Response;
|
||||
|
||||
class SettingsHandler
|
||||
{
|
||||
private BotTokenConfigurator $botTokenConfigurator;
|
||||
|
||||
public function __construct(BotTokenConfigurator $botTokenConfigurator)
|
||||
{
|
||||
$this->botTokenConfigurator = $botTokenConfigurator;
|
||||
}
|
||||
|
||||
public function configureBotToken(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$data = $this->botTokenConfigurator->configure(trim($request->json('botToken', '')));
|
||||
return new JsonResponse($data);
|
||||
} catch (BotTokenConfiguratorException $e) {
|
||||
return new JsonResponse(['error' => $e->getMessage()], Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
} catch (Exception $e) {
|
||||
return new JsonResponse(['error' => $e->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ use Openguru\OpenCartFramework\Cache\CacheInterface;
|
||||
use Openguru\OpenCartFramework\Config\Settings;
|
||||
use Openguru\OpenCartFramework\Http\JsonResponse;
|
||||
use Openguru\OpenCartFramework\Http\Response;
|
||||
use Openguru\OpenCartFramework\Logger\Logger;
|
||||
use Openguru\OpenCartFramework\Router\Router;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
use Openguru\OpenCartFramework\Telegram\TelegramService;
|
||||
@@ -15,82 +14,20 @@ use RuntimeException;
|
||||
|
||||
class TelegramHandler
|
||||
{
|
||||
private TelegramService $telegramService;
|
||||
private Logger $logger;
|
||||
private Router $router;
|
||||
private Settings $settings;
|
||||
private CacheInterface $cache;
|
||||
|
||||
public function __construct(
|
||||
TelegramService $telegramService,
|
||||
Logger $logger,
|
||||
Router $router,
|
||||
Settings $settings,
|
||||
CacheInterface $cache
|
||||
) {
|
||||
$this->telegramService = $telegramService;
|
||||
$this->logger = $logger;
|
||||
$this->router = $router;
|
||||
$this->settings = $settings;
|
||||
public function __construct(CacheInterface $cache)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
public function getMe(): JsonResponse
|
||||
{
|
||||
$data = $this->telegramService->exec('getMe');
|
||||
|
||||
return new JsonResponse($data);
|
||||
}
|
||||
|
||||
public function setWebhook(): JsonResponse
|
||||
{
|
||||
$publicUrl = $this->settings->get('public_url');
|
||||
if (! $publicUrl || $publicUrl === '/' || str_contains($publicUrl, 'localhost')) {
|
||||
throw new RuntimeException('public_url is required in settings to create webhook.');
|
||||
}
|
||||
|
||||
$webHookUrl = trim($publicUrl, '/') . $this->router->url('webhook');
|
||||
|
||||
try {
|
||||
$data = $this->telegramService->exec('setWebhook', [
|
||||
'url' => $webHookUrl,
|
||||
]);
|
||||
|
||||
return new JsonResponse($data);
|
||||
} catch (Exception $exception) {
|
||||
return new JsonResponse(['error' => $exception->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function getWebhookInfo(): JsonResponse
|
||||
{
|
||||
try {
|
||||
$data = $this->telegramService->exec('getWebhookInfo');
|
||||
|
||||
return new JsonResponse($data);
|
||||
} catch (Exception $exception) {
|
||||
return new JsonResponse(['error' => $exception->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteWebhook(): JsonResponse
|
||||
{
|
||||
try {
|
||||
$data = $this->telegramService->exec('deleteWebhook');
|
||||
|
||||
return new JsonResponse($data);
|
||||
} catch (Exception $exception) {
|
||||
return new JsonResponse(['error' => $exception->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function getChatId(): JsonResponse
|
||||
{
|
||||
$message = $this->cache->get('tg_latest_msg');
|
||||
|
||||
if (! $message) {
|
||||
return new JsonResponse([
|
||||
'message' => 'Сообщение не найдено. Убедитесь что отправили кодовое слово в чат с ботом и повторите через 10 секунд.'
|
||||
'message' => 'Сообщение не найдено. Убедитесь что отправили кодовое слово в чат с ботом и повторите через 10 секунд. У Вас есть 60 секунд после отправки сообщения в чат, чтобы нажать на кнопку! Это сделано в целях безопасности.'
|
||||
], Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Bastion\Services;
|
||||
|
||||
use Bastion\Exceptions\BotTokenConfiguratorException;
|
||||
use Exception;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Openguru\OpenCartFramework\Config\Settings;
|
||||
use Openguru\OpenCartFramework\Logger\LoggerInterface;
|
||||
use Openguru\OpenCartFramework\Router\Router;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
use Openguru\OpenCartFramework\Telegram\TelegramClientException;
|
||||
use Openguru\OpenCartFramework\Telegram\TelegramService;
|
||||
|
||||
class BotTokenConfigurator
|
||||
{
|
||||
private TelegramService $telegramService;
|
||||
private Settings $settings;
|
||||
private Router $router;
|
||||
private LoggerInterface $logger;
|
||||
|
||||
public function __construct(
|
||||
TelegramService $telegramService,
|
||||
Settings $settings,
|
||||
Router $router,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->telegramService = $telegramService;
|
||||
$this->settings = $settings;
|
||||
$this->router = $router;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws BotTokenConfiguratorException
|
||||
*/
|
||||
public function configure(string $botToken): array
|
||||
{
|
||||
$this->telegramService->setBotToken($botToken);
|
||||
|
||||
try {
|
||||
$me = $this->telegramService->exec('getMe');
|
||||
$webhookUrl = $this->telegramService->getWebhookUrl();
|
||||
|
||||
if (! $webhookUrl) {
|
||||
$this->telegramService->exec('setWebhook', [
|
||||
'url' => $this->getWebhookUrl(),
|
||||
]);
|
||||
}
|
||||
|
||||
$webhookUrl = $this->telegramService->getWebhookUrl();
|
||||
|
||||
return [
|
||||
'first_name' => Arr::get($me, 'result.first_name'),
|
||||
'username' => Arr::get($me, 'result.username'),
|
||||
'id' => Arr::get($me, 'result.id'),
|
||||
'webhook_url' => $webhookUrl,
|
||||
];
|
||||
} catch (TelegramClientException $exception) {
|
||||
$this->logger->logException($exception);
|
||||
if ($exception->getCode() === 404 || $exception->getCode() === 401) {
|
||||
throw new BotTokenConfiguratorException(
|
||||
'Telegram сообщает, что BotToken не верный. Проверьте корректность.'
|
||||
);
|
||||
}
|
||||
|
||||
throw new BotTokenConfiguratorException($exception->getMessage());
|
||||
} catch (Exception|GuzzleException $exception) {
|
||||
$this->logger->logException($exception);
|
||||
throw new BotTokenConfiguratorException($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function getWebhookUrl(): string
|
||||
{
|
||||
$publicUrl = rtrim($this->settings->get('public_url'), '/');
|
||||
|
||||
if (! $publicUrl) {
|
||||
throw new BotTokenConfiguratorException('Public URL is not set in configuration.');
|
||||
}
|
||||
|
||||
$webhook = $this->router->url($this->settings->get('tg_webhook_handler', 'webhook'));
|
||||
|
||||
return $publicUrl . $webhook;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
<?php
|
||||
|
||||
use Bastion\Handlers\SettingsHandler;
|
||||
use Bastion\Handlers\TelegramHandler;
|
||||
|
||||
return [
|
||||
'getMe' => [TelegramHandler::class, 'getMe'],
|
||||
'setWebhook' => [TelegramHandler::class, 'setWebhook'],
|
||||
'getWebhookInfo' => [TelegramHandler::class, 'getWebhookInfo'],
|
||||
'deleteWebhook' => [TelegramHandler::class, 'deleteWebhook'],
|
||||
'configureBotToken' => [SettingsHandler::class, 'configureBotToken'],
|
||||
'getChatId' => [TelegramHandler::class, 'getChatId'],
|
||||
];
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Decorators;
|
||||
namespace Openguru\OpenCartFramework\OpenCart\Decorators;
|
||||
|
||||
use Cart\Cart;
|
||||
use Cart\Currency;
|
||||
use Config;
|
||||
use Loader;
|
||||
use ModelCatalogProduct;
|
||||
use ModelSettingSetting;
|
||||
use Registry;
|
||||
use Session;
|
||||
|
||||
@@ -15,7 +17,8 @@ use Session;
|
||||
* @property Session $session
|
||||
* @property Currency $currency
|
||||
* @property Config $config
|
||||
* @property \ModelCatalogProduct $model_catalog_product
|
||||
* @property ModelCatalogProduct $model_catalog_product
|
||||
* @property ModelSettingSetting $model_setting_setting
|
||||
*/
|
||||
class OcRegistryDecorator
|
||||
{
|
||||
@@ -5,16 +5,15 @@ namespace Openguru\OpenCartFramework\Telegram;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
|
||||
class TelegramService
|
||||
{
|
||||
private Client $client;
|
||||
private ?string $botToken;
|
||||
|
||||
public function __construct(?string $botToken = null)
|
||||
{
|
||||
$this->botToken = $botToken;
|
||||
$this->client = $this->createGuzzleClient("https://api.telegram.org/bot{$botToken}/");
|
||||
}
|
||||
|
||||
public function escapeTelegramMarkdownV2(string $text): string
|
||||
@@ -39,13 +38,15 @@ class TelegramService
|
||||
return;
|
||||
}
|
||||
|
||||
$client = $this->createGuzzleClient("https://api.telegram.org/bot{$this->botToken}/");
|
||||
|
||||
$query = [
|
||||
'chat_id' => $chatId,
|
||||
'text' => $text,
|
||||
'parse_mode' => 'MarkdownV2',
|
||||
];
|
||||
|
||||
$this->client->get('sendMessage', [
|
||||
$client->get('sendMessage', [
|
||||
'query' => $query,
|
||||
]);
|
||||
}
|
||||
@@ -79,13 +80,21 @@ class TelegramService
|
||||
throw new TelegramClientException('BotToken is empty');
|
||||
}
|
||||
|
||||
$client = $this->createGuzzleClient("https://api.telegram.org/bot{$this->botToken}/");
|
||||
|
||||
try {
|
||||
$response = $this->client->post($methodName, [
|
||||
$response = $client->post($methodName, [
|
||||
'json' => $params,
|
||||
]);
|
||||
|
||||
$json = json_decode($response->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
if (! $json['ok']) {
|
||||
throw new TelegramClientException(
|
||||
$json['code'] ?? 'Unknown Code' . ': ' . $json['description'] ?? 'Unknown Error'
|
||||
);
|
||||
}
|
||||
|
||||
return $json;
|
||||
} catch (ClientException $exception) {
|
||||
$response = $exception->getResponse()->getBody()->getContents();
|
||||
@@ -97,4 +106,11 @@ class TelegramService
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function getWebhookUrl(): string
|
||||
{
|
||||
$webhookInfo = $this->exec('getWebhookInfo');
|
||||
|
||||
return Arr::get($webhookInfo, 'result.url');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Decorators\OcRegistryDecorator;
|
||||
use Cart\Cart;
|
||||
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
|
||||
|
||||
class CartService
|
||||
{
|
||||
|
||||
@@ -4,13 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Decorators\OcRegistryDecorator;
|
||||
use App\Exceptions\OrderValidationFailedException;
|
||||
use Cassandra\Date;
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use Openguru\OpenCartFramework\Config\Settings;
|
||||
use Openguru\OpenCartFramework\Logger\LoggerInterface;
|
||||
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
use Openguru\OpenCartFramework\Telegram\TelegramService;
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
namespace App\Services;
|
||||
|
||||
use App\Adapters\OcModelCatalogProductAdapter;
|
||||
use App\Decorators\OcRegistryDecorator;
|
||||
use Cart\Currency;
|
||||
use Cart\Tax;
|
||||
use Exception;
|
||||
use Openguru\OpenCartFramework\Config\Settings;
|
||||
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
|
||||
use Openguru\OpenCartFramework\OpenCart\Decorators\OcRegistryDecorator;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\Builder;
|
||||
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
|
||||
use Openguru\OpenCartFramework\Support\Arr;
|
||||
|
||||
Reference in New Issue
Block a user