feat(order): WIP: telegram notifications

This commit is contained in:
Nikita Kiselev
2025-08-01 10:26:47 +03:00
parent 858be67c89
commit 454bd39f1f
7 changed files with 428 additions and 6 deletions

View File

@@ -38,6 +38,10 @@ class Controllerextensiontgshophandle extends Controller
'language_id' => (int) $this->config->get('config_language_id'), 'language_id' => (int) $this->config->get('config_language_id'),
'shop_base_url' => HTTPS_SERVER, 'shop_base_url' => HTTPS_SERVER,
'dir_image' => DIR_IMAGE, 'dir_image' => DIR_IMAGE,
'telegram' => [
'bot_token' => '7513204587:AAGvRL15OzzltESqwbL15vOEWi6ZZMikDpg',
'chat_id' => 849193407,
],
'db' => [ 'db' => [
'host' => DB_HOSTNAME, 'host' => DB_HOSTNAME,
'database' => DB_DATABASE, 'database' => DB_DATABASE,

View File

@@ -22,7 +22,8 @@
"ext-json": "*", "ext-json": "*",
"intervention/image": "^2.7", "intervention/image": "^2.7",
"rakit/validation": "^1.4", "rakit/validation": "^1.4",
"vlucas/phpdotenv": "^5.6" "vlucas/phpdotenv": "^5.6",
"guzzlehttp/guzzle": "^7.9"
}, },
"require-dev": { "require-dev": {
"roave/security-advisories": "dev-latest" "roave/security-advisories": "dev-latest"

View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "39c53e4dd9f5fa4822c5c5c87b882768", "content-hash": "7e1f9e747364eeaf0ebae0f7af3f8d2c",
"packages": [ "packages": [
{ {
"name": "graham-campbell/result-type", "name": "graham-campbell/result-type",
@@ -68,6 +68,215 @@
], ],
"time": "2024-07-20T21:45:45+00:00" "time": "2024-07-20T21:45:45+00:00"
}, },
{
"name": "guzzlehttp/guzzle",
"version": "7.9.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
"reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.5.3 || ^2.0.3",
"guzzlehttp/psr7": "^2.7.0",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
},
"provide": {
"psr/http-client-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"ext-curl": "*",
"guzzle/client-integration-tests": "3.0.2",
"php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.39 || ^9.6.20",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
"suggest": {
"ext-curl": "Required for CURL handler support",
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Jeremy Lindblom",
"email": "jeremeamia@gmail.com",
"homepage": "https://github.com/jeremeamia"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle is a PHP HTTP client library",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"psr-18",
"psr-7",
"rest",
"web service"
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.9.3"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
"type": "tidelift"
}
],
"time": "2025-03-27T13:37:11+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c",
"reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/2.2.0"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
"type": "tidelift"
}
],
"time": "2025-03-27T13:27:01+00:00"
},
{ {
"name": "guzzlehttp/psr7", "name": "guzzlehttp/psr7",
"version": "2.7.1", "version": "2.7.1",
@@ -396,6 +605,58 @@
}, },
"time": "2021-11-05T16:47:00+00:00" "time": "2021-11-05T16:47:00+00:00"
}, },
{
"name": "psr/http-client",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client"
},
"time": "2023-09-23T14:17:50+00:00"
},
{ {
"name": "psr/http-factory", "name": "psr/http-factory",
"version": "1.1.0", "version": "1.1.0",
@@ -594,6 +855,73 @@
}, },
"time": "2019-03-08T08:55:37+00:00" "time": "2019-03-08T08:55:37+00:00"
}, },
{
"name": "symfony/deprecation-contracts",
"version": "v2.5.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "605389f2a7e5625f273b53960dc46aeaf9c62918"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918",
"reference": "605389f2a7e5625f273b53960dc46aeaf9c62918",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/contracts",
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "2.5-dev"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-25T14:11:13+00:00"
},
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.32.0", "version": "v1.32.0",

View File

@@ -0,0 +1,47 @@
<?php
namespace Openguru\OpenCartFramework\Telegram;
use Exception;
use GuzzleHttp\Client;
use Openguru\OpenCartFramework\Logger\Logger;
class TelegramService
{
private Logger $logger;
private Client $client;
public function __construct(string $botToken, Logger $logger)
{
$this->logger = $logger;
$this->client = $this->createGuzzleClient("https://api.telegram.org/bot{$botToken}/");
}
public function sendMessage(int $chatId, string $text): bool
{
try {
$query = [
'chat_id' => $chatId,
'text' => $text,
'parse_mode' => 'MarkdownV2',
];
$this->client->get('sendMessage', [
'query' => $query,
]);
return true;
} catch (Exception $exception) {
$this->logger->error('Telegram sendMessage error: ' . json_encode($query));
$this->logger->logException($exception);
return false;
}
}
private function createGuzzleClient(string $uri): Client
{
return new Client([
'base_uri' => $uri,
'timeout' => 5.0,
]);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Openguru\OpenCartFramework\Telegram;
use Openguru\OpenCartFramework\Application;
use Openguru\OpenCartFramework\Container\ServiceProvider;
use Openguru\OpenCartFramework\Logger\Logger;
class TelegramServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->container->singleton(TelegramService::class, function (Application $app) {
$botToken = $app->getConfigValue('telegram.bot_token');
return new TelegramService(
$botToken,
$app->get(Logger::class),
);
});
}
}

View File

@@ -8,6 +8,7 @@ use Openguru\OpenCartFramework\Cache\CacheServiceProvider;
use Openguru\OpenCartFramework\QueryBuilder\QueryBuilderServiceProvider; use Openguru\OpenCartFramework\QueryBuilder\QueryBuilderServiceProvider;
use Openguru\OpenCartFramework\Router\RouteServiceProvider; use Openguru\OpenCartFramework\Router\RouteServiceProvider;
use Openguru\OpenCartFramework\Support\Arr; use Openguru\OpenCartFramework\Support\Arr;
use Openguru\OpenCartFramework\Telegram\TelegramServiceProvider;
class ApplicationFactory class ApplicationFactory
{ {
@@ -21,6 +22,7 @@ class ApplicationFactory
CacheServiceProvider::class, CacheServiceProvider::class,
RouteServiceProvider::class, RouteServiceProvider::class,
AppServiceProvider::class, AppServiceProvider::class,
TelegramServiceProvider::class,
]); ]);
} }
} }

View File

@@ -5,9 +5,8 @@ namespace App\Services;
use App\Decorators\OcRegistryDecorator; use App\Decorators\OcRegistryDecorator;
use App\Exceptions\OrderValidationFailedException; use App\Exceptions\OrderValidationFailedException;
use Openguru\OpenCartFramework\Config\Settings; use Openguru\OpenCartFramework\Config\Settings;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface; use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
use Openguru\OpenCartFramework\Telegram\TelegramService;
use Rakit\Validation\Validator; use Rakit\Validation\Validator;
use RuntimeException; use RuntimeException;
@@ -17,20 +16,23 @@ class OrderCreateService
private CartService $cartService; private CartService $cartService;
private OcRegistryDecorator $oc; private OcRegistryDecorator $oc;
private Settings $settings; private Settings $settings;
private TelegramService $telegramService;
public function __construct( public function __construct(
ConnectionInterface $database, ConnectionInterface $database,
CartService $cartService, CartService $cartService,
OcRegistryDecorator $registry, OcRegistryDecorator $registry,
Settings $settings Settings $settings,
TelegramService $telegramService
) { ) {
$this->database = $database; $this->database = $database;
$this->cartService = $cartService; $this->cartService = $cartService;
$this->oc = $registry; $this->oc = $registry;
$this->settings = $settings; $this->settings = $settings;
$this->telegramService = $telegramService;
} }
public function create(array $data, array $meta = []) public function create(array $data, array $meta = []): void
{ {
$this->validate($data); $this->validate($data);
@@ -153,6 +155,23 @@ class OrderCreateService
); );
$this->cartService->flush(); $this->cartService->flush();
$message = <<<MARKDOWN
*Новый заказ в магазине %s*
Покупатель: %s %s
Сумма: %s
MARKDOWN;
$this->telegramService->sendMessage(
$this->settings->get('telegram.chat_id'),
sprintf(
$message,
$storeName,
$data['firstName'],
$data['lastName'],
$total,
),
);
} }
private function validate(array $data): void private function validate(array $data): void