🇷🇺 Русская версия | 🇰🇿 Қазақша нұсқасы
🎯 Современный PHP SDK для интеграции с Aitu Messenger API
⚡ Полная поддержка Aitu Passport (OAuth) и Aitu Apps (Push Notifications) с глубокой интеграцией в Laravel
|
|
|
|
- 📊 Аналитика - Статистика доставки уведомлений
- 🧪 Полное тестирование - Unit, Feature и Integration тесты
- 📚 Подробная документация - Примеры и руководства
- 🔄 Автоматическое восстановление - Retry механизмы для API запросов
- 🌐 Мультиязычность - Поддержка локализации уведомлений
|
PHP 8.1+ |
Laravel 10.0+ |
Guzzle HTTP 7.0+ |
![]() Composer |
composer require madarlan/aitu-messenger-phpИспользуйте Artisan команду для полной автоматической настройки:
php artisan aitu:install🔧 Что делает команда установки?
- ✅ Публикует конфигурационные файлы
- ✅ Создает маршруты для webhook'ов
- ✅ Публикует миграции базы данных
- ✅ Добавляет переменные окружения в
.env - ✅ Показывает следующие шаги настройки
# Установить только Aitu Passport
php artisan aitu:install --passport
# Установить только Aitu Apps
php artisan aitu:install --apps
# Перезаписать существующие файлы
php artisan aitu:install --forceРазвернуть инструкции по ручной установке
# 1. Публикация конфигурации
php artisan vendor:publish --tag="aitu-messenger-config"
# 2. Публикация маршрутов
php artisan vendor:publish --tag="aitu-messenger-routes"
# 3. Публикация миграций
php artisan vendor:publish --tag="aitu-messenger-migrations"
# 4. Выполнение миграций
php artisan migrateДобавьте следующие переменные в ваш .env файл:
# 🔐 Aitu Passport OAuth
AITU_PASSPORT_CLIENT_ID=your_passport_client_id
AITU_PASSPORT_CLIENT_SECRET=your_passport_client_secret
AITU_PASSPORT_REDIRECT_URI=https://yourapp.com/auth/aitu/callback
# 📱 Aitu Apps Push Notifications
AITU_APPS_APP_ID=your_apps_app_id
AITU_APPS_APP_SECRET=your_apps_app_secret
# 🔒 Webhook Security
AITU_WEBHOOK_SECRET=your_webhook_secret
AITU_WEBHOOK_VERIFY_SIGNATURE=true
# 🛠️ Опциональные настройки
AITU_LOGGING_ENABLED=true
AITU_CACHE_ENABLED=true
AITU_API_TIMEOUT=30
AITU_RETRY_ATTEMPTS=3Пошаговая настройка Aitu Passport
-
Создание приложения
- Перейдите в панель управления Aitu Passport
- Создайте новое приложение
- Получите
Client IDиClient Secret
-
Настройка Redirect URI
https://your-domain.com/auth/aitu/callback -
Настройка webhook'ов
- Authorization webhook:
https://your-domain.com/api/webhooks/aitu/passport
- Authorization webhook:
- General webhook:
https://your-domain.com/api/webhooks/aitu
Пошаговая настройка Aitu Apps
-
Создание приложения
- Перейдите в панель управления Aitu Apps
- Создайте новое приложение
- Получите
App IDиApp Secret
-
Настройка webhook'ов
- Apps webhook:
https://your-domain.com/api/webhooks/aitu/apps
- Apps webhook:
- General webhook:
https://your-domain.com/api/webhooks/aitu
use MadArlan\AituMessenger\Facades\AituPassport;
// 🎯 Получить URL для авторизации
$authUrl = AituPassport::getAuthorizationUrl(['profile', 'email']);
return redirect($authUrl);
// 🔄 Обработать callback
$tokens = AituPassport::exchangeCodeForTokens($request->get('code'));
$userInfo = AituPassport::getUserInfo($tokens['access_token']);
// 👤 Информация о пользователе
echo "👋 Привет, " . $userInfo->getName();
echo "📧 Email: " . $userInfo->getEmail();
echo "📱 Телефон: " . $userInfo->getPhone();use MadArlan\AituMessenger\Facades\AituApps;
// 🎯 Уведомление конкретному пользователю
$result = AituApps::sendTargetedNotification(
userId: 'user_123',
title: '🎉 Поздравляем!',
body: 'Ваш заказ успешно оформлен',
data: ['order_id' => 12345, 'status' => 'confirmed']
);
// 👥 Групповое уведомление
$result = AituApps::sendGroupNotification(
groupId: 'group_456',
title: '📢 Важное объявление',
body: 'Новые функции уже доступны!'
);
// ⏰ Запланированное уведомление
$scheduledTime = now()->addHours(2);
$result = AituApps::scheduleNotification(
userId: 'user_123',
title: '⏰ Напоминание',
body: 'Не забудьте про встречу в 15:00',
scheduledAt: $scheduledTime
);Webhook'и автоматически обрабатываются через маршруты с middleware aitu.webhook для проверки подписи:
// 🌐 Автоматически подключенные маршруты
Route::post('/api/webhooks/aitu', [WebhookController::class, 'handleGeneralWebhook'])
->middleware('aitu.webhook');
Route::post('/api/webhooks/aitu/passport', [WebhookController::class, 'handlePassportWebhook'])
->middleware('aitu.webhook');
Route::post('/api/webhooks/aitu/apps', [WebhookController::class, 'handleAppsWebhook'])
->middleware('aitu.webhook');🔒 Безопасность: Middleware
aitu.webhookавтоматически проверяет подпись webhook'а с использованием секретного ключа из конфигурации.
Контроллер авторизации
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use MadArlan\AituMessenger\Facades\AituPassport;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
class AituAuthController extends Controller
{
/**
* 🚀 Перенаправление на авторизацию
*/
public function login()
{
$authUrl = AituPassport::getAuthorizationUrl([
'profile',
'email',
'phone'
], 'custom_state_' . time());
return redirect($authUrl);
}
/**
* 🔄 Обработка callback'а
*/
public function callback(Request $request)
{
try {
// Проверяем state для безопасности
if (!$request->has('state') || !str_starts_with($request->state, 'custom_state_')) {
throw new \Exception('Invalid state parameter');
}
// Обмениваем код на токены
$tokenData = AituPassport::exchangeCodeForTokens($request->code);
$user = AituPassport::getUserInfo($tokenData['access_token']);
// Создаем или обновляем пользователя
$localUser = User::updateOrCreate(
['aitu_id' => $user->getId()],
[
'name' => $user->getName(),
'email' => $user->getEmail(),
'phone' => $user->getPhone(),
'avatar' => $user->getAvatar(),
'aitu_access_token' => $tokenData['access_token'],
'aitu_refresh_token' => $tokenData['refresh_token'],
'aitu_token_expires_at' => now()->addSeconds($tokenData['expires_in']),
]
);
Auth::login($localUser);
return redirect('/dashboard')->with('success', '🎉 Успешная авторизация через Aitu!');
} catch (\Exception $e) {
return redirect('/login')->with('error', '❌ Ошибка авторизации: ' . $e->getMessage());
}
}
/**
* 🚪 Выход из системы
*/
public function logout(Request $request)
{
$user = Auth::user();
if ($user && $user->aitu_access_token) {
// Отзываем токен в Aitu
AituPassport::revokeToken($user->aitu_access_token);
}
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/')->with('success', '👋 До свидания!');
}
}Job для отправки уведомлений
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use MadArlan\AituMessenger\Facades\AituApps;
use Illuminate\Support\Facades\Log;
class SendAituNotificationJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(
private string $userId,
private string $title,
private string $body,
private array $data = [],
private ?string $icon = null,
private ?string $image = null,
private ?string $clickAction = null
) {}
/**
* 🚀 Выполнение задачи
*/
public function handle(): void
{
try {
$notification = [
'title' => $this->title,
'body' => $this->body,
'user_id' => $this->userId,
'data' => $this->data,
];
// Добавляем дополнительные параметры если они есть
if ($this->icon) {
$notification['icon'] = $this->icon;
}
if ($this->image) {
$notification['image'] = $this->image;
}
if ($this->clickAction) {
$notification['click_action'] = $this->clickAction;
}
$response = AituApps::sendTargetedNotification($notification);
if ($response->isSuccessful()) {
Log::info('✅ Aitu notification sent successfully', [
'user_id' => $this->userId,
'notification_id' => $response->getData('notification_id')
]);
} else {
Log::error('❌ Failed to send Aitu notification', [
'user_id' => $this->userId,
'error' => $response->getError()
]);
}
} catch (\Exception $e) {
Log::error('💥 Exception while sending Aitu notification', [
'user_id' => $this->userId,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
throw $e; // Перебрасываем исключение для retry механизма
}
}
}Использование:
// 🎯 Простое уведомление
SendAituNotificationJob::dispatch(
userId: 'user-uuid-123',
title: '🛒 Новый заказ',
body: 'Ваш заказ #12345 принят в обработку'
);
// 🎨 Уведомление с медиа и действием
SendAituNotificationJob::dispatch(
userId: 'user-uuid-123',
title: '🎉 Специальное предложение!',
body: 'Скидка 50% на все товары до конца недели',
data: ['promo_code' => 'SALE50', 'discount' => 50],
icon: 'https://example.com/sale-icon.png',
image: 'https://example.com/sale-banner.jpg',
clickAction: 'https://example.com/sale'
);
// ⏰ Отложенная отправка
SendAituNotificationJob::dispatch(
userId: 'user-uuid-123',
title: '⏰ Напоминание',
body: 'Через час начнется ваша встреча'
)->delay(now()->addMinutes(50));Различные типы уведомлений
use MadArlan\AituMessenger\Facades\AituApps;
// 🎯 Таргетированное уведомление с полными параметрами
$response = AituApps::sendTargetedNotification([
'title' => '🎁 Персональное предложение',
'body' => 'Специально для вас скидка 30%!',
'user_id' => 'user-uuid-123',
'icon' => 'https://example.com/gift-icon.png',
'image' => 'https://example.com/personal-offer.jpg',
'click_action' => 'https://example.com/personal-offer',
'data' => [
'offer_id' => 'PERSONAL_30',
'discount' => 30,
'expires_at' => '2024-12-31T23:59:59Z'
],
'badge' => 1,
'sound' => 'default',
'priority' => 'high'
]);
// 👥 Массовая рассылка
$userIds = ['user-1', 'user-2', 'user-3', 'user-4', 'user-5'];
$response = AituApps::sendMultipleNotifications([
'title' => '📢 Важное объявление',
'body' => 'Обновление системы запланировано на завтра в 02:00'
], $userIds);
// 🏷️ Уведомления по тегам
$response = AituApps::sendNotificationByTags([
'title' => '⭐ Для VIP клиентов',
'body' => 'Эксклюзивная распродажа только для вас!'
], ['vip', 'premium']);
// 📡 Broadcast всем пользователям
$response = AituApps::sendBroadcastNotification([
'title' => '🚨 Системное уведомление',
'body' => 'Плановые технические работы с 02:00 до 04:00'
]);
// ⏰ Запланированное уведомление
$scheduledTime = now()->addDays(1)->setTime(9, 0); // Завтра в 9:00
$response = AituApps::scheduleNotification(
userId: 'user-uuid-123',
title: '☀️ Доброе утро!',
body: 'Начните день с нашими новостями',
scheduledAt: $scheduledTime,
data: ['type' => 'morning_digest']
);Отслеживание доставки уведомлений
use MadArlan\AituMessenger\Facades\AituApps;
// 📊 Получение статистики уведомления
$notificationId = 'notification-uuid-from-response';
$stats = AituApps::getNotificationStatistics($notificationId);
if ($stats->isSuccessful()) {
$data = $stats->getData();
echo "📤 Отправлено: " . $data['sent_count'] . "\n";
echo "✅ Доставлено: " . $data['delivered_count'] . "\n";
echo "👀 Просмотрено: " . $data['viewed_count'] . "\n";
echo "👆 Кликнуто: " . $data['clicked_count'] . "\n";
echo "📈 CTR: " . round(($data['clicked_count'] / $data['delivered_count']) * 100, 2) . "%\n";
}
// 🔍 Проверка статуса уведомления
$status = AituApps::getNotificationStatus($notificationId);
if ($status->isSuccessful()) {
$statusData = $status->getData();
switch ($statusData['status']) {
case 'pending':
echo "⏳ Уведомление в очереди на отправку";
break;
case 'sending':
echo "🚀 Уведомление отправляется";
break;
case 'sent':
echo "✅ Уведомление отправлено";
break;
case 'failed':
echo "❌ Ошибка отправки: " . $statusData['error_message'];
break;
}
}
// ❌ Отмена запланированного уведомления
$scheduledNotificationId = 'scheduled-notification-uuid';
$cancelResponse = AituApps::cancelScheduledNotification($scheduledNotificationId);
if ($cancelResponse->isSuccessful()) {
echo "✅ Запланированное уведомление отменено";
} else {
echo "❌ Не удалось отменить уведомление: " . $cancelResponse->getError()['message'];
}SDK можно использовать в любом PHP проекте:
use MadArlan\AituMessenger\AituPassportClient;
use MadArlan\AituMessenger\AituAppsClient;
// 🔐 Aitu Passport
$passportClient = new AituPassportClient(
clientId: 'your_client_id',
clientSecret: 'your_client_secret',
redirectUri: 'https://yourapp.com/callback'
);
$authUrl = $passportClient->getAuthorizationUrl(['profile', 'email']);
$tokens = $passportClient->exchangeCodeForTokens($authorizationCode);
$user = $passportClient->getUserInfo($tokens['access_token']);
// 📱 Aitu Apps
$appsClient = new AituAppsClient(
appId: 'your_app_id',
appSecret: 'your_app_secret'
);
$response = $appsClient->sendTargetedNotification([
'title' => 'Заголовок',
'body' => 'Текст уведомления',
'user_id' => 'user-uuid-123'
]);# Все тесты
composer test
# Тесты с покрытием кода
composer test-coverage
# Только unit тесты
composer test -- --testsuite=Unit
# Только feature тесты
composer test -- --testsuite=Feature
# Только integration тесты
composer test -- --testsuite=Integration# PHPStan анализ
composer analyse
# PHP CS Fixer
composer format
# Проверка стиля кода
composer check-styleСоздайте тестовый маршрут:
// routes/web.php
Route::get('/test-aitu', function () {
try {
// 🧪 Тест Aitu Passport
$passportClient = app(\MadArlan\AituMessenger\AituPassportClient::class);
$authUrl = $passportClient->getAuthorizationUrl(['profile']);
// 🧪 Тест Aitu Apps
$appsClient = app(\MadArlan\AituMessenger\AituAppsClient::class);
return response()->json([
'status' => '✅ success',
'passport_auth_url' => $authUrl,
'apps_client' => '✅ initialized',
'timestamp' => now()->toISOString()
]);
} catch (\Exception $e) {
return response()->json([
'status' => '❌ error',
'message' => $e->getMessage(),
'timestamp' => now()->toISOString()
], 500);
}
});Частые проблемы и их решения
composer dump-autoload
php artisan optimize:clear# Очистка всех кэшей
php artisan optimize:clear
# Или по отдельности
php artisan config:clear
php artisan cache:clear
php artisan route:clear
php artisan view:clear# Linux/Mac
sudo chown -R www-data:www-data storage/
sudo chmod -R 775 storage/
# Windows (в PowerShell от администратора)
icacls storage /grant "IIS_IUSRS:(OI)(CI)F" /T- Проверьте URL webhook'ов в панели управления Aitu
- Убедитесь что HTTPS настроен правильно
- Проверьте секретный ключ в
.envфайле - Включите логирование для отладки:
AITU_LOGGING_ENABLED=true
LOG_LEVEL=debug// Увеличьте таймаут в конфигурации
'http' => [
'timeout' => 60, // секунд
'retry_attempts' => 5,
'retry_delay' => 1000, // миллисекунд
],- 📋 Требования и установка - Полное руководство по установке
- ⚙️ Конфигурация - Настройка всех параметров
- 🚀 Быстрый старт - Начните использовать за 5 минут
- 💡 Примеры использования - Готовые решения
- 🧪 Тестирование - Как тестировать ваш код
В папке examples/ вы найдете готовые примеры:
- 🔐
passport_oauth.php- OAuth авторизация - 📱
apps_notifications.php- Push уведомления - 🔗
webhook_handler.php- Обработка webhook'ов
Изучите тесты для понимания всех возможностей:
- 🔬
tests/Unit/- Unit тесты - 🎯
tests/Feature/- Feature тесты - 🔗
tests/Integration/- Integration тесты
- 📖 Сначала проверьте документацию - большинство вопросов уже освещены
- 🔍 Поищите в Issues - возможно, ваш вопрос уже обсуждался
- 🐛 Создайте новый Issue - если не нашли ответ
- 📧 Напишите нам - для срочных вопросов
Если вы обнаружили уязвимость в безопасности, НЕ создавайте публичный Issue. Отправьте email на madinovarlan@gmail.com.
Мы приветствуем участие в разработке!
- 🍴 Fork репозиторий
- 🌿 Создайте ветку для вашей функции (
git checkout -b feature/amazing-feature) - ✅ Добавьте тесты для новой функциональности
- 🧪 Убедитесь что все тесты проходят (
composer test) - 📝 Commit ваши изменения (
git commit -m 'Add amazing feature') - 📤 Push в ветку (
git push origin feature/amazing-feature) - 🔄 Создайте Pull Request
- ✅ Следуйте PSR-12 стандарту кодирования
- 🧪 Покрывайте тестами новую функциональность
- 📝 Документируйте изменения в коде
- 🔄 Обновляйте CHANGELOG.md при необходимости
Этот проект лицензирован под MIT License - подробности в файле LICENSE.
MIT License
Copyright (c) 2025 Madinov Arlan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

