Сегодня мы поговорим о том, как реализовать автоматическую отправку SMS-уведомлений через платформу МТС Exolve при получении предоплаты в сервисе МойСклад.
Кейс из жизни

В логистической компании менеджер обычно работает по стандартному договору: запускает заказ после предоплаты от клиента. Чтобы не ждать подтверждения из бухгалтерии и не отвлекаться от текущих задач, можно настроить отправку SMS-уведомления сразу после зачисления средств на счёт. Так менеджер моментально даст распоряжение сотрудникам и запустит процесс доставки.
Настройка
Чтобы реализовать систему, потребуется:
Сервис управления товарооборотом МойСклад — учётная система, где фиксируются финансовые операции
Платформа для отправки SMS-уведомлений МТС Exolve — сервис отправки сообщений клиентам и сотрудникам по заданным условиям
Настройка интеграции между МойСклад и МТС Exolve с помощью API
Для успешной реализации проекта подключим API МойСклад и МТС Exolve, настроим правильную интеграцию между сервисами. Разработаем сценарий обработки предоплат с автоматической отправкой SMS-уведомлений.
Порядок работы системы:
Фиксация платежа
Клиент переводит предоплату на счёт компании
МойСклад регистрирует поступление средств на счёт компании
Автоматическая отправка SMS
Настроенный сценарий в МойСклад автоматически передаёт информацию о платеже в сервис Exolve
Exolve формирует SMS и отправляет его на номер ответственного менеджера
Реакция менеджера
Получив уведомление, менеджер оперативно принимает решение и отдаёт распоряжение складу и водителям для начала выполнения заказа.
Работа с API МойСкладдля обработки предоплат
В ERP МойСклад есть удобный JSON API для работы с предоплатами. Код сущности предоплаты — ключевое слово prepayment. Чтобы получить список всех предоплат, можно использовать контекстный поиск с параметром search, который ищет строки по одному полю одновременно, без использования сложной токенизации. Так мы быстро и эффективно будем обрабатывать данные.
Начнём реализацию проекта на языке php: инициализируем его и установим требуемые зависимости. Теперь определим, как будет устроен наш проект:
moysklad_sms/
├── src/
│ ├── SmsSender.php # Реализация функционала отправки SMS
│ ├── MoySkladClient.php # Взаимодействие с системой "МойСклад" для получения данных
│ ├── Worker.php # Организация параллельной обработки задач рассылки SMS
│ ├── main.php # Главный исполняемый файл
├── .env # Конфигурационный файл
├── composer.json # Файл зависимостей
Выполним необходимые команды для создания проекта и установки требуемых зависимостей:
mkdir moysklad_sms
cd moysklad_sms
composer init
composer require vlucas/phpdotenv guzzlehttp/guzzle
В конфигурационный файл .env запишем пять строк:
MOYSKLAD_API_KEY=ваш_ключ_от_мойсклад
MOYSKLAD_BASE_URL=https://online.moysklad.ru/api/remap/1.2
EXOLVE_API_KEY=ваш_ключ_от_exolve
EXOLVE_SENDER=номер_отправителя
MANAGER_PHONE=номер_менеджера
Настройка автозагрузки в composer.json. Этот блок указывает Composer, что классы из пространства имён App находятся в директории src/.
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
Выполним команду для генерации автозагрузчика:
composer dump-autoload
Извлечение данных о предоплатах из МойСклад
Файл (src/MoySkladClient.php
) отвечает за получение списка заказов с предоплатой:
<?php
namespace App;
use GuzzleHttp\Client;
use Dotenv\Dotenv;
use GuzzleHttp\Exception\RequestException;
class MoySkladClient
{
private Client $client;
private string $baseUrl;
private string $apiKey;
public function __construct()
{
$dotenv = Dotenv::createImmutable(__DIR__ . '/../');
$dotenv->load();
$this->baseUrl = $_ENV['MOYSKLAD_BASE_URL'];
$this->apiKey = $_ENV['MOYSKLAD_API_KEY'];
$this->client = new Client();
}
public function getPrepaidOrders(): array
{
$url = "{$this->baseUrl}/entity/prepayment";
try {
$response = $this->client->get($url, [
'headers' => [
'Authorization' => 'Basic ' . base64_encode($this->apiKey),
'Accept' => 'application/json',
],
]);
} catch (RequestException $exception) {
echo "Произошла ошибка при выполнении запроса: " . $exception->getMessage() . PHP_EOL;
return [];
}
return json_decode($response->getBody(), true) ?? [];
}
}
В (src/SmsSender.php
) создадим логику отправки SMS:
<?php
namespace App;
use GuzzleHttp\Client;
class SmsSender
{
private Client $client;
private string $apiKey;
private string $sender;
public function __construct()
{
$this->client = new Client();
$this->apiKey = $_ENV['EXOLVE_API_KEY'];
$this->sender = $_ENV['EXOLVE_SENDER'];
}
public function sendSMS(string $to, string $message): bool
{
$url = 'https://api.exolve.ru/sms/v1/send';
$data = [
'from' => $this->sender,
'to' => $to,
'message' => $message,
];
for ($i = 0; $i < 3; $i++) { // 3 попытки
try {
$response = $this->client->post($url, [
'headers' => [
'Authorization' => "Bearer {$this->apiKey}",
'Content-Type' => 'application/json',
],
'json' => $data,
]);
if ($response->getStatusCode() === 200) {
echo "SMS отправлено: $to\n";
return true;
}
} catch (\Exception $exception) {
echo "Ошибка отправки SMS (попытка " . ($i + 1) . "): " . $exception->getMessage() . PHP_EOL;
}
}
return false;
}
}
Для обработки большого объёма номеров используем многопоточный подход. В (src/Worker.php
) реализуем логику работы с очередью:
<?php
namespace App;
class Worker
{
public function process(array $prepayments)
{
$managerPhone = $_ENV['MANAGER_PHONE'];
if (!$managerPhone) {
die("Ошибка: номер менеджера не указан в .env\n");
}
$smsSender = new SmsSender();
$children = [];
foreach ($prepayments as $prepayment) {
$pid = pcntl_fork();
if ($pid == -1) {
die("Ошибка создания процесса\n");
} elseif ($pid) {
$children[] = $pid;
} else {
// Дочерний процесс
$this->handlePrepayment($prepayment, $smsSender, $managerPhone);
exit(0);
}
}
// Ждем завершения всех дочерних процессов
foreach ($children as $child) {
pcntl_waitpid($child, $status);
}
}
private function handlePrepayment(array $prepayment, SmsSender $smsSender, string $managerPhone)
{
$managerMessage = "Заказ {$prepayment['id']} получил предоплату от {$prepayment['agent']['name']}.";
$clientMessage = "Ваша предоплата успешно получена! Спасибо за покупку.";
// Отправка SMS менеджеру
if ($smsSender->sendSMS($managerPhone, $managerMessage)) {
echo date('Y/m/d H:i:s') . " SMS успешно отправлено менеджеру: $managerPhone\n";
} else {
echo date('Y/m/d H:i:s') . " Ошибка отправки SMS менеджеру: $managerPhone\n";
}
// Отправка SMS клиенту
if (!empty($prepayment['agent']['phone'])) {
if ($smsSender->sendSMS($prepayment['agent']['phone'], $clientMessage)) {
echo date('Y/m/d H:i:s') . " SMS успешно отправлено клиенту: {$prepayment['agent']['phone']}\n";
} else {
echo date('Y/m/d H:i:s') . " Ошибка отправки SMS клиенту: {$prepayment['agent']['phone']}\n";
}
}
}
}
Основной исполняемый файл (src/index.php
).
<?php
require __DIR__ . '/../vendor/autoload.php';
use App\MoySkladClient;
use App\Worker;
use Dotenv\Dotenv;
$dotenv = Dotenv::createImmutable(__DIR__ . '/../');
$dotenv->load();
$moySklad = new MoySkladClient();
$prepayments = $moySklad->getPrepaidOrders();
if (empty($prepayments)) {
die("Нет предоплат для обработки.\n");
} else {
echo date('Y/m/d H:i:s') . " Получено " . count($prepayments) . " предоплаты из \"МойСклад\"\n";
}
$worker = new Worker();
$worker->process($prepayments);
echo date('Y/m/d H:i:s') . " Все SMS успешно отправлены\n";
Запуск программы
Когда все файлы проекта готовы и переменные окружения настроены, проверим работу. Для этого выполним следующую команду в терминале:
php src/index.php
В итоге получим примерно следующий вывод:
/var/www/html/moysklad_sms # php src/index.php
2025/03/05 00:36:22 Получено 3 предоплаты из "МойСклад"
2025/03/05 00:36:23 SMS успешно отправлено менеджеру: +79123456789
2025/03/05 00:36:24 SMS успешно отправлено клиенту: +79876543210
2025/03/05 00:36:25 SMS успешно отправлено менеджеру: +79123456789
2025/03/05 00:36:26 SMS успешно отправлено клиенту: +79876543211
2025/03/05 00:36:27 SMS успешно отправлено менеджеру: +79123456789
2025/03/05 00:36:28 SMS успешно отправлено клиенту: +79876543212
2025/03/05 00:36:29 Все SMS успешно отправлены
Скриншоты полученных сообщений
Для менеджера

Для клиента

Вот и всё! Теперь у нас есть проект по автоматической отправке SMS-уведомлений при получении предоплаты в МойСклад. Решение экономит время, автоматизирует процессы и повышает прозрачность работы.
Система гибкая, её легко адаптировать под различные задачи, например, добавив напоминания о скидках или уведомления о завершении операции.