Розроблення бота для автоматичної обробки відзивів на маркетплейсах
Маркетплейси — Ozon, Wildberries, Yandex.Market — вимагають оперативних відповідей на відзиви. Платформи враховують відсоток відповіданих відзивів при ранжуванні карток. Ручна обробка сотень відзивів на місяць — це втрата часу і постійні просрочки. Бот автоматизує три завдання: отримання нових відзивів, генерацію відповідей, публікацію через API.
Архітектура
Cron → API Polling → New Review Queue → Auto-Response Engine → Publish API
↓
Low-Score Alert → Human Queue
Логіка: відзиви з рейтингом 4–5 обробляються автоматично. Відзиви з рейтингом 1–3 йдуть у чергу для ручної відповіді зі сповіщенням у Telegram.
Інтеграція з Ozon API
class OzonReviewApiClient
{
private string $clientId;
private string $apiKey;
private string $baseUrl = 'https://api-seller.ozon.ru';
public function getUnprocessedReviews(): array
{
$response = Http::withHeaders([
'Client-Id' => $this->clientId,
'Api-Key' => $this->apiKey,
'Content-Type' => 'application/json',
])->post("{$this->baseUrl}/v1/review/list", [
'processed' => false,
'with_text' => true,
'page' => 1,
'page_size' => 100,
]);
return $response->json('result.reviews', []);
}
public function replyToReview(string $reviewId, string $text): bool
{
$response = Http::withHeaders([
'Client-Id' => $this->clientId,
'Api-Key' => $this->apiKey,
'Content-Type' => 'application/json',
])->post("{$this->baseUrl}/v1/review/comment/create", [
'review_id' => $reviewId,
'text' => $text,
]);
return $response->successful();
}
}
Генератор відповідей
Відповіді генеруються з шаблонів з персоналізацією або через GPT для унікальності.
Шаблонний підхід:
class TemplateResponseGenerator
{
private array $positiveTemplates = [
"Дякуємо за відзив, {author}! Раді, що вам сподобалось {product_short}. До побачення!",
"{author}, дякуємо за оцінку! Приємно чути позитивні слова про {product_short}.",
"Дякуємо, {author}! Ваш відзив дуже важливий для нас. Приємного користування {product_short}!",
];
private array $neutralTemplates = [
"Дякуємо за відзив, {author}. Якщо у вас виникнуть питання по {product_short} — зверніться до нашої підтримки.",
];
public function generate(ReviewDTO $review): string
{
$templates = $review->rating >= 4
? $this->positiveTemplates
: $this->neutralTemplates;
$template = $templates[array_rand($templates)];
return str_replace(
['{author}', '{product_short}'],
[$review->author, $this->shortProductName($review->productName)],
$template,
);
}
}
GPT-підхід для якісних унікальних відповідей:
class GptResponseGenerator
{
public function generate(ReviewDTO $review): string
{
$response = $this->openai->chat()->create([
'model' => 'gpt-4o-mini',
'messages' => [
[
'role' => 'system',
'content' => implode("\n", [
'Ти — спеціаліст підтримки інтернет-магазину. Пишеш відповідь на відзив покупця.',
'Вимоги: 1–3 речення. Без канцелярита. Називай покупця по імені якщо воно є.',
'Якщо плюси — поблагодари. Нейтральний — поблагодари і запропонуй допомогу.',
'Без обіцянок скидок і конкретних дат.',
]),
],
[
'role' => 'user',
'content' => "Товар: {$review->productName}\nРейтинг: {$review->rating}/5\nАвтор: {$review->author}\nВідзив: {$review->text}",
],
],
'max_tokens' => 150,
'temperature' => 0.8,
]);
return $response->choices[0]->message->content;
}
}
Job обробки відзиву
class ProcessMarketplaceReviewJob implements ShouldQueue
{
public int $tries = 3;
public function handle(
TemplateResponseGenerator $templateGen,
GptResponseGenerator $gptGen,
ReviewPublisher $publisher,
ReviewAlertService $alerts,
): void {
$review = $this->review;
if ($review->rating <= 3) {
// Сповістити команду — відповідь потрібна вручну
$alerts->urgentReviewAlert($review);
return;
}
// Вибір генератора
$text = config('reviews.use_gpt')
? $gptGen->generate($review)
: $templateGen->generate($review);
// Публікація через API маркетплейса
$success = $publisher->publish($review->platform, $review->externalId, $text);
if (!$success) {
throw new \RuntimeException("Не вдалося опублікувати відповідь на {$review->platform}");
}
// Запис відповіді в БД
Review::where('external_id', $review->externalId)
->update([
'reply_text' => $text,
'reply_published_at' => now(),
'is_processed' => true,
]);
}
}
Wildberries API
class WildberriesReviewApiClient
{
private string $apiKey;
private string $baseUrl = 'https://feedbacks-api.wildberries.ru';
public function getFeedbacks(bool $onlyNew = true): array
{
$response = Http::withToken($this->apiKey)
->get("{$this->baseUrl}/api/v1/feedbacks", [
'isAnswered' => $onlyNew ? 'false' : 'true',
'take' => 100,
'skip' => 0,
]);
return $response->json('data.feedbacks', []);
}
public function replyToFeedback(string $id, string $text): bool
{
$response = Http::withToken($this->apiKey)
->patch("{$this->baseUrl}/api/v1/feedbacks", [
'id' => $id,
'text' => $text,
]);
return $response->successful();
}
}
Контроль якості відповідей
До публікації відповідь проходить валідацію:
class ReplyValidator
{
public function validate(string $reply): ValidationResult
{
$errors = [];
if (mb_strlen($reply) < 20) {
$errors[] = 'Занадто коротка відповідь';
}
if (mb_strlen($reply) > 1000) {
$errors[] = 'Перевищено ліміт символів';
}
// Маркетплейси запрещают упоминание конкурентов и внешних ссылок
if (preg_match('/https?:\/\//i', $reply)) {
$errors[] = 'Посилання в відповідях заборонені';
}
$forbidden = ['wildberries', 'ozon', 'yandex', 'aliexpress'];
foreach ($forbidden as $word) {
if (mb_stripos($reply, $word) !== false) {
$errors[] = "Упоминание конкурента: {$word}";
}
}
return new ValidationResult(errors: $errors);
}
}
Метрики ефективності
| Метрика | Цільове значення |
|---|---|
| Відсоток оброблених відзивів | > 95% у протязі 24 годин |
| Доля автовідповідей (рейтинг 4–5) | 70–80% від всіх відзивів |
| Середній час відповіді | < 2 годин |
| Помилки публікації | < 1% |
Розписання
// Перевірка нових відзивів кожні 30 хвилин
$schedule->command('reviews:marketplace:poll')->everyThirtyMinutes();
// Щотижневий звіт зі статистикою відповідей
$schedule->job(new MarketplaceReviewsWeeklyReportJob)->weekly()->mondays()->at('09:00');
Графік реалізації
- Ozon API клієнт + шаблонний генератор: 1 день
- Wildberries + Yandex.Market API: +1 день
- GPT-генератор + валідатор: 1 день
- Job-система + черга ручних відповідей: 0.5 дня
- Telegram-сповіщення + метрики: 0.5 дня
Разом: 3–4 робочі дні.







