@green-api/greenapi-integration 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1080 -1061
  3. package/README.ru.md +1092 -1068
  4. package/dist/types/types.d.ts +161 -6
  5. package/package.json +42 -41
package/README.ru.md CHANGED
@@ -1,1068 +1,1092 @@
1
- # Универсальная интеграционная платформа для GREEN-API
2
-
3
- ## Поддержка
4
-
5
- [![Support](https://img.shields.io/badge/support@green--api.com-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:support@greenapi.com)
6
- [![Support](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/greenapi_support_bot)
7
- [![Support](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://wa.me/77273122366)
8
-
9
- ## Руководства и новости
10
-
11
- [![Guides](https://img.shields.io/badge/YouTube-%23FF0000.svg?style=for-the-badge&logo=YouTube&logoColor=white)](https://www.youtube.com/@green-api)
12
- [![News](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/green_api)
13
- [![News](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://whatsapp.com/channel/0029VaLj6J4LNSa2B5Jx6s3h)
14
-
15
- - [Documentation in English](./README.md)
16
-
17
- Гибкая интеграционная платформа, разработанная для упрощения процесса подключения WhatsApp шлюза GREEN-API к различным
18
- сторонним сервисам.
19
-
20
- ## Содержание
21
-
22
- - [Установка](#установка)
23
- - [Основные компоненты](#основные-компоненты)
24
- - [Руководство разработчика](#руководство-разработчика)
25
- - [Рабочий пример](#рабочий-пример)
26
- - [Реальные примеры](#реальные-примеры)
27
- - [Лучшие практики](#лучшие-практики)
28
-
29
- ## Установка
30
-
31
- ```bash
32
- npm install @green-api/greenapi-integration
33
- ```
34
-
35
- ## Основные компоненты
36
-
37
- ### 1. BaseAdapter
38
-
39
- Основа вашей интеграции. Управляет сообщениями и инстансами, а также логикой взаимодействия с платформой.
40
-
41
- ```typescript
42
- abstract class BaseAdapter<TPlatformWebhook, TPlatformMessage> {
43
- public constructor(
44
- transformer: MessageTransformer<TPlatformWebhook, TPlatformMessage>,
45
- storage: StorageProvider
46
- );
47
-
48
- public abstract createPlatformClient(params: any): Promise<any>;
49
-
50
- public abstract sendToPlatform(message: TPlatformMessage, instance: TInstance): Promise<void>;
51
- }
52
- ```
53
-
54
- #### Методы
55
-
56
- При расширении BaseAdapter, ваша реализация получает доступ к следующим методам:
57
-
58
- ##### Обработка вебхуков
59
-
60
- Эти методы обработки вебхуков автоматически вызывают ваши методы преобразования (маппинга) сообщений, без необходимости
61
- использовать их напрямую.
62
-
63
- ```typescript
64
- // Обработка вебхуков от вашей платформы
65
- await adapter.handlePlatformWebhook(webhookData, instanceId);
66
-
67
- // Обработка вебхуков от GREEN-API. Второй параметр указывает функции, какие конкретные вебхуки обрабатывать.
68
- // Второй параметр должен быть указан, иначе вебхуки не будут обработаны.
69
- await adapter.handleGreenApiWebhook(webhook, ['incomingMessageReceived']);
70
- ```
71
-
72
- ##### Управление инстансами
73
-
74
- ```typescript
75
- // Создание нового инстанса
76
- const instance = await adapter.createInstance(instanceData, settings, userEmail);
77
-
78
- // Получение данных инстанса
79
- const details = await adapter.getInstance(instanceId);
80
-
81
- // Удаление инстанса
82
- await adapter.removeInstance(instanceId);
83
- ```
84
-
85
- ##### Управление пользователями
86
-
87
- ```typescript
88
- // Создание нового пользователя
89
- const user = await adapter.createUser(userEmail, userData);
90
-
91
- // Обновление пользователя
92
- await adapter.updateUser(userEmail, updateData);
93
- ```
94
-
95
- #### Пример реализации вебхуков
96
-
97
- ```typescript
98
- // Конечная точка для вебхуков платформы
99
- app.post('/webhook/platform', async (req, res) => {
100
- try {
101
- await adapter.handlePlatformWebhook(req.body, instanceId);
102
- res.status(200).send();
103
- } catch (error) {
104
- console.error('Не удалось обработать вебхук платформы:', error);
105
- res.status(500).send();
106
- }
107
- });
108
-
109
- // Конечная точка для вебхуков GREEN-API
110
- app.post('/webhook/green-api', async (req, res) => {
111
- try {
112
- // Обработка определенных типов вебхуков
113
- await adapter.handleGreenApiWebhook(req.body, [
114
- 'incomingMessageReceived',
115
- 'outgoingMessageStatus'
116
- ]);
117
- res.status(200).send();
118
- } catch (error) {
119
- console.error('Не удалось обработать вебхук GREEN-API:', error);
120
- res.status(500).send();
121
- }
122
- });
123
- ```
124
-
125
- ### 2. MessageTransformer
126
-
127
- Преобразовывает форматы сообщений между GREEN-API и вашей платформой.
128
-
129
- ```typescript
130
- abstract class MessageTransformer<TPlatformWebhook, TPlatformMessage> {
131
- abstract toPlatformMessage(webhook: GreenApiWebhook): TPlatformMessage;
132
-
133
- abstract toGreenApiMessage(message: TPlatformWebhook): Message;
134
- }
135
- ```
136
-
137
- ### 3. StorageProvider
138
-
139
- Интерфейс для операций с хранением данных.
140
-
141
- ```typescript
142
- abstract class StorageProvider<TUser extends BaseUser = BaseUser, TInstance extends BaseInstance = Instance> {
143
- abstract createInstance(instance: BaseInstance, userId: bigint | number): Promise<TInstance>;
144
-
145
- abstract getInstance(idInstance: number | bigint): Promise<TInstance | null>;
146
-
147
- abstract removeInstance(instanceId: number | bigint): Promise<TInstance>;
148
-
149
- abstract createUser(data: any): Promise<TUser>;
150
-
151
- abstract findUser(identifier: string): Promise<TUser | null>;
152
-
153
- abstract updateUser(identifier: string, data: any): Promise<TUser>;
154
- }
155
- ```
156
-
157
- ### 4. BaseGreenApiAuthGuard
158
-
159
- Аутентифицирует входящие вебхуки от GREEN-API.
160
-
161
- ```typescript
162
- abstract class BaseGreenApiAuthGuard<T extends BaseRequest = BaseRequest> {
163
- constructor(protected storage: StorageProvider);
164
-
165
- // Валидация входящих вебхуков
166
- async validateRequest(request: T): Promise<boolean>;
167
- }
168
- ```
169
-
170
- Пример использования `BaseGreenApiAuthGuard`:
171
-
172
- ```typescript
173
- class YourAuthGuard extends BaseGreenApiAuthGuard<YourRequest> {
174
- constructor(storage: StorageProvider) {
175
- super(storage);
176
- }
177
- }
178
-
179
- // Использование с Express
180
- app.post('/webhook', async (req, res) => {
181
- const guard = new YourAuthGuard(storage);
182
- try {
183
- await guard.validateRequest(req);
184
- // Обработка вебхука ...
185
- } catch (error) {
186
- if (error instanceof AuthenticationError) {
187
- res.status(401).json({error: error.message});
188
- return;
189
- }
190
- res.status(500).json({error: 'Internal server error'});
191
- }
192
- });
193
- ```
194
-
195
- ### 5. GreenApiLogger
196
-
197
- Структурированный JSON-логгер с цветным выводом. Обеспечивает единый формат логирования в вашем приложении с корректной
198
- обработкой ошибок и сериализацией.
199
-
200
- ```typescript
201
- const logger = GreenApiLogger.getInstance("YourComponent");
202
-
203
- // Базовое логирование
204
- logger.debug("Debug message", {someContext: "value"});
205
- logger.info("Info message", {userId: 123});
206
- logger.warn("Warning message", {alert: true});
207
- logger.error("Error occurred", {errorCode: 500});
208
- logger.fatal("Fatal error", {critical: true});
209
-
210
- // Логирование ошибок с контекстом
211
- try {
212
- await someOperation();
213
- } catch (error) {
214
- logger.logErrorResponse(error, "Operation failed", {
215
- operationId: "123",
216
- additionalInfo: "some context"
217
- });
218
- }
219
- ```
220
-
221
- #### Возможности
222
-
223
- - Структурированное JSON-логирование в едином формате
224
- - Цветной вывод в зависимости от уровня лога (debug=голубой, info=зеленый, warn=желтый, error=красный, fatal=пурпурный)
225
- - Встроенная обработка ошибок с форматированием стека вызовов
226
- - Автоматическая сериализация
227
- - Независимость от фреймворка - работает с любым Node.js приложением
228
- - Специальная обработка ошибок Axios с подробной информацией о запросе/ответе
229
-
230
- #### Уровни логирования
231
-
232
- - `debug` - Подробная информация для отладки
233
- - `info` - Общая информация о работе системы
234
- - `warn` - Предупреждения о потенциально опасных ситуациях
235
- - `error` - Сообщения об ошибках
236
- - `fatal` - Критические ошибки, требующие немедленного внимания
237
- - `log` - Альтернатива info (для совместимости)
238
-
239
- #### Формат вывода
240
-
241
- ```json
242
- {
243
- "timestamp": "30/01/2025, 04:34:49",
244
- "level": "error",
245
- "context": "CoreService",
246
- "message": "Operation failed",
247
- "error": "Failed to process request",
248
- "stack": [
249
- "Error: Failed to process request",
250
- " at CoreService.process (/app/service.js:123:45)",
251
- " at async Router.handle (/app/router.js:67:89)"
252
- ],
253
- "additionalContext": {
254
- "requestId": "abc-123",
255
- "userId": "user_456"
256
- }
257
- }
258
- ```
259
-
260
- #### Обработка ошибок
261
-
262
- ```typescript
263
- // Обработка ошибок Axios
264
- try {
265
- await apiRequest();
266
- } catch (error) {
267
- logger.logErrorResponse(error, "API Request failed", {
268
- endpoint: "/users",
269
- method: "POST"
270
- });
271
- }
272
- ```
273
-
274
- // Получим подробную информацию об ошибке API:
275
-
276
- ```json
277
- {
278
- "timestamp": "30/01/2025, 04:34:49",
279
- "level": "error",
280
- "context": "ApiService",
281
- "message": "API Request failed - API Error:",
282
- "status": 400,
283
- "statusText": "Bad Request",
284
- "data": {
285
- "error": "Invalid input"
286
- },
287
- "url": "https://api.example.com/users",
288
- "method": "POST",
289
- "endpoint": "/users"
290
- }
291
- ```
292
-
293
- #### Использование с фреймворками
294
-
295
- Логгер независим от фреймворков, но легко интегрируется с любым из них:
296
-
297
- ```typescript
298
- // Пример с NestJS
299
- const app = await NestFactory.create(AppModule, {
300
- logger: GreenApiLogger.getInstance("NestJS")
301
- });
302
-
303
- // Пример с Express
304
- app.use((err, req, res, next) => {
305
- const logger = GreenApiLogger.getInstance("Express");
306
- logger.error("Request failed", {
307
- path: req.path,
308
- method: req.method,
309
- error: err.message
310
- });
311
- next(err);
312
- });
313
- ```
314
-
315
- #### Методы
316
-
317
- ##### Основные методы логирования
318
-
319
- - `debug(message: string, context?: Record<string, any>)`: Логирование отладочной информации
320
- - `info(message: string, context?: Record<string, any>)`: Логирование информационных сообщений
321
- - `warn(message: string, context?: Record<string, any>)`: Логирование предупреждений
322
- - `error(message: string, context?: Record<string, any>)`: Логирование ошибок
323
- - `fatal(message: string, context?: Record<string, any>)`: Логирование критических ошибок
324
- - `log(message: string, context?: string)`: Альтернатива методу info
325
-
326
- ##### Специальные методы
327
-
328
- - `logErrorResponse(error: any, context: string, additionalContext?: Record<string, any>)`:
329
- Расширенное логирование ошибок со специальной обработкой ошибок Axios и стека вызовов
330
-
331
- ##### Вспомогательные методы
332
-
333
- - `getInstance(context: string = "Global"): GreenApiLogger`: Получение или создание экземпляра логгера для указанного
334
- контекста
335
-
336
- #### Лучшие практики
337
-
338
- 1. **Используйте последовательные имена контекста**
339
-
340
- ```typescript
341
- // В вашем компоненте/сервисе
342
- private readonly
343
- logger = GreenApiLogger.getInstance(YourService.name);
344
- ```
345
-
346
- 2. **Включайте релевантный контекст**
347
-
348
- ```typescript
349
- logger.info("User action completed", {
350
- userId: user.id,
351
- action: "profile_update",
352
- duration: timeTaken
353
- });
354
- ```
355
-
356
- 3. **Правильная обработка ошибок**
357
-
358
- ```typescript
359
- try {
360
- await complexOperation();
361
- } catch (error) {
362
- logger.logErrorResponse(error, "Complex operation failed", {
363
- operationId: id,
364
- parameters: params
365
- });
366
- }
367
- ```
368
-
369
- 4. **Используйте соответствующие уровни логирования**
370
-
371
- ```typescript
372
- // Debug для детальной информации
373
- logger.debug("Processing chunk", {chunkId: 123, size: 1024});
374
-
375
- // Info для общей информации о работе
376
- logger.info("User logged in", {userId: 456});
377
-
378
- // Warn для потенциальных проблем
379
- logger.warn("High memory usage", {memoryUsage: "85%"});
380
-
381
- // Error для реальных проблем
382
- logger.error("Database connection failed", {dbHost: "primary"});
383
-
384
- // Fatal для критических проблем
385
- logger.fatal("System shutdown required", {reason: "data corruption"});
386
- ```
387
-
388
- ### 6. GreenApiClient
389
-
390
- Прямой интерфейс к методам GREEN-API.
391
-
392
- ```typescript
393
- const client = new GreenApiClient({
394
- idInstance: 'your_instance_id',
395
- apiTokenInstance: 'your_token'
396
- });
397
-
398
- // Примеры специальных операций:
399
- await client.setProfilePicture(fileBlob);
400
- await client.getAuthorizationCode(phoneNumber);
401
- await client.getQR();
402
- ```
403
-
404
- ## Руководство для разработчика
405
-
406
- Это руководство проведет вас через процесс создания вашей первой интеграции с WhatsApp шлюзом GREEN-API.
407
-
408
- ### Структура проекта
409
-
410
- ```
411
- your-integration/
412
- ├── src/
413
- │ ├── core/
414
- │ │ ├── adapter.ts # Адаптер платформы
415
- │ │ ├── transformer.ts # Преобразователь сообщений
416
- │ │ ├── storage.ts # Реализация хранилища
417
- │ │ └── router.ts # Эндпоинты для вебхуков
418
- │ ├── types/
419
- │ │ └── types.ts # Типы
420
- │ └── main.ts # Точка запуска приложения
421
- ├── package.json
422
- └── tsconfig.json
423
- ```
424
-
425
- ```mermaid
426
- graph TB
427
- subgraph "WhatsApp в Платформу"
428
- WA[WhatsApp] -->|Отправка сообщения| GA1[GREEN-API]
429
- GA1 -->|Вебхук| INT1[Ваша Интеграция]
430
- INT1 -->|1 . Валидация вебхука| GD1[BaseGreenApiAuthGuard]
431
- INT1 -->|2 . Преобразование сообщения| TR1[MessageTransformer]
432
- INT1 -->|3 . Отправка в платформу| PL1[Ваша Платформа]
433
- end
434
-
435
- subgraph "Платформа в WhatsApp"
436
- PL2[Ваша Платформа] -->|Вебхук| INT2[Ваша Интеграция]
437
- INT2 -->|1 . Преобразование сообщения| TR2[MessageTransformer]
438
- INT2 -->|2 . Отправка через API| GA2[GREEN-API]
439
- GA2 -->|Отправка сообщения| WA2[WhatsApp]
440
- end
441
-
442
- subgraph "Компоненты"
443
- style Компоненты fill: #f9f9f9, stroke: #333, stroke-width: 2px
444
- TR[MessageTransformer]
445
- ST[StorageProvider]
446
- AD[BaseAdapter]
447
- GD[WebhookGuard]
448
- end
449
- ```
450
-
451
- ### Этапы реализации
452
-
453
- #### Этап 1: Определение типов платформы
454
-
455
- Сначала определите типы сообщений для вашей платформы:
456
-
457
- ```typescript
458
- // types/types.ts
459
- export interface YourPlatformWebhook {
460
- id: string;
461
- from: string;
462
- message: string;
463
- timestamp: number;
464
- // Добавьте другие поля, специфичные для вашей платформы
465
- }
466
-
467
- export interface YourPlatformMessage {
468
- recipient: string;
469
- content: string;
470
- // Добавьте другие поля, специфичные для вашей платформы
471
- }
472
- ```
473
-
474
- #### Этап 2. Создание преобразователя сообщений
475
-
476
- Создайте преобразователь, который конвертирует сообщения между форматом вашей платформы и форматом GREEN-API:
477
-
478
- ```typescript
479
- // core/transformer.ts
480
- import { MessageTransformer, Message, GreenApiWebhook } from '@green-api/greenapi-integration';
481
- import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
482
-
483
- export class YourTransformer extends MessageTransformer<YourPlatformWebhook, YourPlatformMessage> {
484
- toPlatformMessage(webhook: GreenApiWebhook): YourPlatformMessage {
485
- // Преобразование вебхука GREEN-API в формат вашей платформы
486
- return {
487
- recipient: webhook.senderData.sender,
488
- content: webhook.messageData.textMessageData?.textMessage || '',
489
- };
490
- }
491
-
492
- toGreenApiMessage(message: YourPlatformWebhook): Message {
493
- // Преобразование вебхука вашей платформы в формат GREEN-API
494
- return {
495
- type: 'text',
496
- chatId: message.from,
497
- message: message.message,
498
- };
499
- }
500
- }
501
- ```
502
-
503
- #### Этап 3: Реализация хранилища
504
-
505
- Создайте провайдер хранилища для управления пользователями и инстансами. Вы можете использовать любую базу данных или
506
- ORM:
507
-
508
- ```typescript
509
- // core/storage.ts
510
- import { StorageProvider, BaseUser, Instance, Settings } from '@green-api/greenapi-integration';
511
- import { PrismaClient } from '@prisma/client'; // Or your database client
512
-
513
- export class YourStorage extends StorageProvider {
514
- private db: PrismaClient;
515
-
516
- constructor() {
517
- this.db = new PrismaClient();
518
- }
519
-
520
- async createInstance(instance: Instance, userId: bigint) {
521
- return this.db.instance.create({
522
- data: {
523
- idInstance: instance.idInstance,
524
- apiTokenInstance: instance.apiTokenInstance,
525
- userId,
526
- settings: instance.settings || {},
527
- },
528
- });
529
- }
530
-
531
- // Остальные методы
532
- }
533
- ```
534
-
535
- #### Этап 4: Создание адаптера платформы
536
-
537
- Адаптер обрабатывает фактическое взаимодействие между платформами:
538
-
539
- ```typescript
540
- // core/adapter.ts
541
- import { BaseAdapter, Instance } from '@green-api/greenapi-integration';
542
- import { YourPlatformClient } from 'your-platform-sdk';
543
- import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
544
-
545
- export class YourAdapter extends BaseAdapter<YourPlatformWebhook, YourPlatformMessage> {
546
- async createPlatformClient(config: { apiKey: string, apiUrl: string }) {
547
- return new YourPlatformClient({
548
- baseUrl: config.apiUrl,
549
- apiKey: config.apiKey,
550
- });
551
- }
552
-
553
- async sendToPlatform(message: YourPlatformMessage, instance: Instance) {
554
- const client = await this.createPlatformClient(instance.config);
555
- await client.sendMessage(message);
556
- }
557
- }
558
- ```
559
-
560
- #### Этап 5: Реализация контроллера вебхуков
561
-
562
- Определите эндпоинты вебхуков, которые будет слушать ваше приложение:
563
-
564
- ```typescript
565
- // core/webhook.ts
566
- import express from 'express';
567
- import { YourAdapter } from '../core/adapter';
568
- import { YourTransformer } from '../core/transformer';
569
- import { YourStorage } from '../core/storage';
570
-
571
- const router = express.Router();
572
- const storage = new YourStorage();
573
- const transformer = new YourTransformer();
574
- const adapter = new YourAdapter(transformer, storage);
575
-
576
- class WebhookGuard extends BaseGreenApiAuthGuard {
577
- constructor(storage: StorageProvider) {
578
- super(storage);
579
- }
580
- }
581
-
582
- const guard = new WebhookGuard(storage);
583
-
584
- // Эндпоинты для вебхуков
585
- router.post('/green-api', async (req, res) => {
586
- try {
587
- // Проверка вебхука
588
- await guard.validateRequest(req);
589
-
590
- // Обработка вебхука после проверки.
591
- // В списке вторым параметром укажите типы вебхуков, которые необходимо обработать
592
- await adapter.handleGreenApiWebhook(req.body, ['incomingMessageReceived']);
593
- res.status(200).json({status: 'ok'});
594
- } catch (error) {
595
- if (error instanceof AuthenticationError) {
596
- res.status(401).json({error: 'Ошибка аутентификации'});
597
- return;
598
- }
599
- console.error('Ошибка обработки вебхука:', error);
600
- res.status(500).json({error: 'Внутренняя ошибка сервера'});
601
- }
602
- });
603
-
604
- router.post('/platform', async (req, res) => {
605
- try {
606
- const instanceId = req.query.instanceId;
607
- await adapter.handlePlatformWebhook(req.body, instanceId);
608
- res.status(200).json({status: 'ok'});
609
- } catch (error) {
610
- console.error('Ошибка обработки вебхука платформы:', error);
611
- res.status(500).json({error: 'Внутренняя ошибка сервера'});
612
- }
613
- });
614
-
615
- router.post('/instance', async (req, res) => {
616
- try {
617
- const {idInstance, apiTokenInstance, userEmail} = req.body;
618
-
619
- if (!idInstance || !apiTokenInstance || !userEmail) {
620
- throw new BadRequestError('Отсутствуют обязательные поля');
621
- }
622
-
623
- const instance = await adapter.createInstance({
624
- idInstance: Number(idInstance),
625
- apiTokenInstance,
626
- settings: {
627
- webhookUrl: `${process.env.APP_URL}/webhook/green-api`,
628
- webhookUrlToken: `token_${Date.now()}`,
629
- incomingWebhook: 'yes'
630
- }
631
- }, userEmail);
632
-
633
- res.status(200).json({
634
- status: 'ok',
635
- data: instance,
636
- message: 'Инстанс успешно создан. Подождите 2 минуты для применения настроек.'
637
- });
638
-
639
- } catch (error) {
640
- console.error('Ошибка создания инстанса:', error);
641
- res.status(500).json({error: 'Не удалось создать инстанс'});
642
- }
643
- });
644
-
645
- export default router;
646
- ```
647
-
648
- #### Этап 6: Создание точки входа приложения
649
-
650
- Соберите все компоненты вместе в точке входа:
651
-
652
- ```typescript
653
- // main.ts
654
- import express from 'express';
655
- import bodyParser from 'body-parser';
656
- import dotenv from 'dotenv';
657
- import webhookRouter from './controllers/webhook';
658
- import { YourAdapter } from './core/adapter';
659
- import { YourTransformer } from './core/transformer';
660
- import { YourStorage } from './core/storage';
661
-
662
- // Загрузка переменных окружения
663
- dotenv.config();
664
-
665
- async function bootstrap() {
666
- // Инициализация компонентов
667
- const storage = new YourStorage();
668
- const transformer = new YourTransformer();
669
- const adapter = new YourAdapter(transformer, storage);
670
-
671
- // Создание Express приложения
672
- const app = express();
673
- app.use(bodyParser.json());
674
-
675
- // Настройка маршрутов для вебхуков
676
- app.use('/webhook', webhookRouter);
677
-
678
- // Запуск сервера
679
- const port = process.env.PORT || 3000;
680
- app.listen(port, () => {
681
- console.log(`Сервер запущен на порту ${port}`);
682
- });
683
-
684
- console.log('Интеграционная платформа готова!');
685
- }
686
-
687
- // Обработка ошибок
688
- bootstrap();
689
- ```
690
-
691
- Или с NestJS:
692
-
693
- ```typescript
694
- // main.ts
695
- import { NestFactory } from '@nestjs/core';
696
- import { AppModule } from './app.module';
697
- import helmet from 'helmet';
698
-
699
- async function bootstrap() {
700
- const app = await NestFactory.create(AppModule);
701
- app.setGlobalPrefix('api');
702
- app.use(helmet());
703
- await app.listen(process.env.PORT ?? 3000);
704
- }
705
-
706
- bootstrap();
707
- ```
708
-
709
- ### Сборка приложения
710
-
711
- 1. **Подготовка package.json**
712
-
713
- ```json
714
- {
715
- "name": "greenapi-integration-yourplatform",
716
- "version": "1.0.0",
717
- "main": "dist/index.js",
718
- "types": "dist/index.d.ts",
719
- "scripts": {
720
- "build": "tsc",
721
- "prepublishOnly": "npm run build"
722
- },
723
- "dependencies": {
724
- "@green-api/greenapi-integration": "^0.4.0",
725
- "@prisma/client": "^5.0.0",
726
- "express": "^4.18.2"
727
- // другие зависимости
728
- }
729
- }
730
- ```
731
-
732
- 2. **Сборка**
733
-
734
- ```bash
735
- npm run build
736
- npm publish
737
- ```
738
-
739
- ## Рабочий пример
740
-
741
- В директории `/examples/custom-adapter` вы найдете полный рабочий пример, демонстрирующий:
742
-
743
- - Двустороннюю передачу сообщений между WhatsApp и пользовательской платформой
744
- - Обработку вебхуков
745
- - Настройку и конфигурацию инстанса
746
- - Преобразование сообщений
747
- - Обработку ошибок
748
-
749
- ### Запуск примера
750
-
751
- 1. Клонируйте репозиторий
752
- 2. Обновите .env данными ваших инстансов GREEN-API:
753
-
754
- ```env
755
- VISITOR_ID_INSTANCE=your_visitor_instance_id
756
- VISITOR_API_TOKEN=your_visitor_instance_token
757
- AGENT_ID_INSTANCE=your_agent_instance_id
758
- AGENT_API_TOKEN=your_agent_instance_token
759
- AGENT_PHONE_NUMBER=your_agent_phone_number
760
- WEBHOOK_URL=your_webhook_url
761
- PORT=3000
762
- ```
763
-
764
- 3. Установите зависимости и запустите:
765
-
766
- ```bash
767
- cd examples/custom-adapter
768
- npm install
769
- npm start
770
- ```
771
-
772
- # Полная реализация примера
773
-
774
- ### Структура проекта
775
-
776
- ```
777
- examples/
778
- └── custom-adapter/
779
- ├── src/
780
- │ ├── main.ts
781
- │ ├── simple-adapter.ts
782
- │ ├── simple-transformer.ts
783
- │ ├── simple-storage.ts
784
- │ └── types.ts
785
- ├── .env
786
- ├── package.json
787
- └── tsconfig.json
788
- ```
789
-
790
- ### types.ts
791
-
792
- ```typescript
793
- interface SimplePlatformWebhook {
794
- messageId: string;
795
- from: string;
796
- text: string;
797
- timestamp: number;
798
- }
799
-
800
- interface SimplePlatformMessage {
801
- to: string;
802
- content: string;
803
- replyTo?: string;
804
- }
805
- ```
806
-
807
- ### simple-transformer.ts
808
-
809
- ```typescript
810
- import {
811
- MessageTransformer,
812
- Message,
813
- GreenApiWebhook,
814
- formatPhoneNumber,
815
- IntegrationError
816
- } from '@green-api/greenapi-integration';
817
-
818
- export class SimpleTransformer extends MessageTransformer<SimplePlatformWebhook, SimplePlatformMessage> {
819
- toPlatformMessage(webhook: GreenApiWebhook): SimplePlatformMessage {
820
- if (webhook.typeWebhook === "incomingMessageReceived") {
821
- if (webhook.messageData.typeMessage !== "extendedTextMessage") {
822
- throw new IntegrationError("Поддерживаются только текстовые сообщения", "BAD_REQUEST_ERROR", 400);
823
- }
824
-
825
- return {
826
- to: webhook.senderData.sender,
827
- content: webhook.messageData.extendedTextMessageData?.text || "",
828
- };
829
- }
830
- throw new IntegrationError("Поддерживаются только вебхуки вида incomingMessageReceived", "INTEGRATION_ERROR", 500);
831
- }
832
-
833
- toGreenApiMessage(message: SimplePlatformWebhook): Message {
834
- return {
835
- type: 'text',
836
- chatId: formatPhoneNumber(message.from),
837
- message: message.text,
838
- };
839
- }
840
- }
841
- ```
842
-
843
- ### simple-storage.ts
844
-
845
- ```typescript
846
- import { StorageProvider, BaseUser, Instance, Settings } from '@green-api/greenapi-integration';
847
-
848
- export class SimpleStorage extends StorageProvider {
849
- private users: Map<string, BaseUser> = new Map();
850
- private instances: Map<number, Instance> = new Map();
851
-
852
- async createInstance(instance: Instance, userId: bigint): Promise<Instance> {
853
- this.instances.set(Number(instance.idInstance), {
854
- ...instance,
855
- });
856
- return instance;
857
- }
858
-
859
- async getInstance(idInstance: number): Promise<Instance | null> {
860
- return this.instances.get(idInstance) || null;
861
- }
862
-
863
- async removeInstance(instanceId: number): Promise<Instance> {
864
- const instance = this.instances.get(instanceId);
865
- if (!instance) throw new Error('Инстанс не найден');
866
- this.instances.delete(instanceId);
867
- return instance;
868
- }
869
-
870
- async createUser(data: any): Promise<BaseUser> {
871
- const user = {id: Date.now(), ...data};
872
- this.users.set(data.email, user);
873
- return user;
874
- }
875
-
876
- async findUser(identifier: string): Promise<BaseUser | null> {
877
- return this.users.get(identifier) || null;
878
- }
879
-
880
- async updateUser(identifier: string, data: any): Promise<BaseUser> {
881
- const user = await this.findUser(identifier);
882
- if (!user) throw new Error('Пользователь не найден');
883
- const updated = {...user, ...data};
884
- this.users.set(identifier, updated);
885
- return updated;
886
- }
887
- }
888
- ```
889
-
890
- ### simple-adapter.ts
891
-
892
- ```typescript
893
- import { BaseAdapter, Instance } from "@green-api/greenapi-integration";
894
- import axios from 'axios';
895
-
896
- export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlatformMessage> {
897
- async createPlatformClient(config: { apiKey: string, apiUrl: string }) {
898
- return axios.create({
899
- baseURL: config.apiUrl,
900
- headers: {
901
- 'Authorization': `Bearer ${config.apiKey}`,
902
- 'Content-Type': 'application/json'
903
- }
904
- });
905
- }
906
-
907
- async sendToPlatform(message: SimplePlatformMessage, instance: Instance): Promise<void> {
908
- // В реальной реализации мы бы отправляли сообщение на платформу
909
- // Для демонстрации просто логируем и симулируем ответ
910
- console.log('Платформа получила сообщение:', message);
911
-
912
- // Симулируем обработку и ответ платформы
913
- setTimeout(() => {
914
- console.log('Обработка платформой завершена, отправляем ответ...');
915
- this.simulatePlatformResponse(message, instance.idInstance);
916
- }, 1000);
917
- }
918
-
919
- private async simulatePlatformResponse(originalMessage: SimplePlatformMessage, idInstance: number | bigint) {
920
- const platformWebhook: SimplePlatformWebhook = {
921
- messageId: `resp_${Date.now()}`,
922
- from: originalMessage.to.replace('@c.us', ''),
923
- text: `Спасибо за ваше сообщение: "${originalMessage.content}". Это автоматический ответ.`,
924
- timestamp: Date.now()
925
- };
926
-
927
- await this.handlePlatformWebhook(platformWebhook, idInstance);
928
- }
929
- }
930
- ```
931
-
932
- ### main.ts
933
-
934
- ```typescript
935
- import express from "express";
936
- import bodyParser from "body-parser";
937
- import { formatPhoneNumber, GreenApiClient } from "@green-api/greenapi-integration";
938
- import { SimpleTransformer } from "./simple-transformer";
939
- import { SimpleStorage } from "./simple-storage";
940
- import { SimpleAdapter } from "./simple-adapter";
941
- import * as dotenv from "dotenv";
942
-
943
- dotenv.config();
944
-
945
- async function main() {
946
- // Инициализация компонентов
947
- const transformer = new SimpleTransformer();
948
- const storage = new SimpleStorage();
949
- const adapter = new SimpleAdapter(transformer, storage);
950
-
951
- // Конфигурация обоих инстансов
952
- const visitorInstance = {
953
- idInstance: Number(process.env.VISITOR_ID_INSTANCE),
954
- apiTokenInstance: process.env.VISITOR_API_TOKEN!,
955
- };
956
-
957
- const agentInstance = {
958
- idInstance: Number(process.env.AGENT_ID_INSTANCE),
959
- apiTokenInstance: process.env.AGENT_API_TOKEN!,
960
- };
961
-
962
- // Создание клиента GREEN-API для посетителя (для отправки начального сообщения)
963
- const visitorClient = new GreenApiClient(visitorInstance);
964
-
965
- // Настройка инстанса агента
966
- console.log("Настройка инстанса агента...");
967
- const user = await adapter.createUser("agent@example.com", {
968
- email: "agent@example.com",
969
- name: "Agent",
970
- });
971
-
972
- const instance = await adapter.createInstance({
973
- idInstance: agentInstance.idInstance, apiTokenInstance: agentInstance.apiTokenInstance, settings: {
974
- webhookUrl: process.env.WEBHOOK_URL + "/webhook/green-api",
975
- webhookUrlToken: "your-secure-token",
976
- incomingWebhook: "yes",
977
- },
978
- }, user.email);
979
-
980
- console.log("Ожидание 2 минуты для применения настроек...");
981
- await new Promise(resolve => setTimeout(resolve, 120000));
982
- console.log("Инстанс готов!");
983
-
984
- // Настройка веб-сервера
985
- const app = express();
986
- app.use(bodyParser.json());
987
-
988
- // Обработка вебхуков от GREEN-API
989
- app.post("/webhook/green-api", async (req, res) => {
990
- try {
991
- console.log("Получен вебхук от GREEN-API:", req.body);
992
- await adapter.handleGreenApiWebhook(req.body, ["incomingMessageReceived"]);
993
- res.status(200).json({status: "ok"});
994
- } catch (error) {
995
- console.error("Ошибка обработки вебхука:", error);
996
- res.status(500).json({error: "Внутренняя ошибка сервера"});
997
- }
998
- });
999
-
1000
- // Запуск сервера
1001
- const port = Number(process.env.PORT) || 3000;
1002
- app.listen(port, () => {
1003
- console.log(`Сервер вебхуков запущен на порту ${port}`);
1004
- });
1005
-
1006
- // Отправка начального сообщения от посетителя
1007
- console.log("Отправка начального сообщения от посетителя...");
1008
- await visitorClient.sendMessage({
1009
- chatId: formatPhoneNumber(process.env.AGENT_PHONE_NUMBER!),
1010
- message: "Здравствуйте! Это тестовое сообщение от посетителя.",
1011
- type: "text",
1012
- });
1013
-
1014
- console.log("Начальное сообщение отправлено! Проверьте WhatsApp агента для просмотра ответа.");
1015
- }
1016
-
1017
- main().catch(console.error);
1018
- ```
1019
-
1020
- ### .env
1021
-
1022
- ```env
1023
- VISITOR_ID_INSTANCE=your_visitor_instance_id
1024
- VISITOR_API_TOKEN=your_visitor_instance_token
1025
- AGENT_ID_INSTANCE=your_agent_instance_id
1026
- AGENT_API_TOKEN=your_agent_instance_token
1027
- AGENT_PHONE_NUMBER=your_agent_phone_number
1028
- WEBHOOK_URL=your_webhook_url
1029
- PORT=3000
1030
- ```
1031
-
1032
- ## Реальные примеры
1033
-
1034
- Для полных примеров реальных интеграций, смотрите:
1035
-
1036
- - [Интеграция с Rocket.Chat](https://github.com/green-api/greenapi-integration-rocketchat)
1037
-
1038
- ## Утилиты
1039
-
1040
- Платформа предоставляет несколько вспомогательных функций:
1041
-
1042
- ```typescript
1043
- // Форматирование телефонных номеров для GREEN-API
1044
- formatPhoneNumber('+1234567890') // Возвращает '1234567890@c.us'
1045
-
1046
- // Генерация безопасных случайных токенов
1047
- generateRandomToken(32) // Возвращает 32-символьный случайный токен
1048
-
1049
- // Извлечение номера телефона из vcard
1050
- const vcard = 'BEGIN:VCARD\nTEL:+1234567890\nEND:VCARD'
1051
- extractPhoneNumberFromVCard(vcard) // Возвращает '+1234567890'
1052
-
1053
- // Проверка значений настроек
1054
- isValidSettingValue('webhookUrl', 'https://example.com') // Возвращает true
1055
-
1056
- // Очистка настроек
1057
- const input = {
1058
- webhookUrl: 'https://example.com',
1059
- outgoingWebhook: 'yes',
1060
- invalidKey: 'value',
1061
- delaySendMessagesMilliseconds: 'invalid'
1062
- }
1063
- validateAndCleanSettings(input) // Возвращает { webhookUrl: 'https://example.com', outgoingWebhook: 'yes' }
1064
- ```
1065
-
1066
- ## Лицензия
1067
-
1068
- MIT
1
+ [# Универсальная интеграционная платформа для GREEN-API
2
+
3
+ ## Поддержка
4
+
5
+ [![Support](https://img.shields.io/badge/support@green--api.com-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:support@greenapi.com)
6
+ [![Support](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/greenapi_support_bot)
7
+ [![Support](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://wa.me/77273122366)
8
+
9
+ ## Руководства и новости
10
+
11
+ [![Guides](https://img.shields.io/badge/YouTube-%23FF0000.svg?style=for-the-badge&logo=YouTube&logoColor=white)](https://www.youtube.com/@green-api)
12
+ [![News](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/green_api)
13
+ [![News](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://whatsapp.com/channel/0029VaLj6J4LNSa2B5Jx6s3h)
14
+
15
+ [![NPM Version](https://img.shields.io/npm/v/@green-api/greenapi-integration)](https://www.npmjs.com/package/@green-api/whatsapp-chatbot-js-v2)
16
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
17
+
18
+ - [Documentation in English](./README.md)
19
+
20
+ Гибкая интеграционная платформа, разработанная для упрощения процесса подключения WhatsApp шлюза GREEN-API к различным
21
+ сторонним сервисам.
22
+
23
+ ## Содержание
24
+
25
+ - [Установка](#установка)
26
+ - [Основные компоненты](#основные-компоненты)
27
+ - [Руководство разработчика](#руководство-разработчика)
28
+ - [Рабочий пример](#рабочий-пример)
29
+ - [Реальные примеры](#реальные-примеры)
30
+ - [Лучшие практики](#лучшие-практики)
31
+
32
+ ## Установка
33
+
34
+ ```bash
35
+ npm install @green-api/greenapi-integration
36
+ ```
37
+
38
+ ## Основные компоненты
39
+
40
+ ### 1. BaseAdapter
41
+
42
+ Основа вашей интеграции. Управляет сообщениями и инстансами, а также логикой взаимодействия с платформой.
43
+
44
+ ```typescript
45
+ abstract class BaseAdapter<TPlatformWebhook, TPlatformMessage> {
46
+ public constructor(
47
+ transformer: MessageTransformer<TPlatformWebhook, TPlatformMessage>,
48
+ storage: StorageProvider
49
+ );
50
+
51
+ public abstract createPlatformClient(params: any): Promise<any>;
52
+
53
+ public abstract sendToPlatform(message: TPlatformMessage, instance: TInstance): Promise<void>;
54
+ }
55
+ ```
56
+
57
+ #### Методы
58
+
59
+ При расширении BaseAdapter, ваша реализация получает доступ к следующим методам:
60
+
61
+ ##### Обработка вебхуков
62
+
63
+ Эти методы обработки вебхуков автоматически вызывают ваши методы преобразования (маппинга) сообщений, без необходимости
64
+ использовать их напрямую.
65
+
66
+ ```typescript
67
+ // Обработка вебхуков от вашей платформы
68
+ await adapter.handlePlatformWebhook(webhookData, instanceId);
69
+
70
+ // Обработка вебхуков от GREEN-API. Второй параметр указывает функции, какие конкретные вебхуки обрабатывать.
71
+ // Второй параметр должен быть указан, иначе вебхуки не будут обработаны.
72
+ await adapter.handleGreenApiWebhook(webhook, ['incomingMessageReceived']);
73
+ ```
74
+
75
+ ##### Управление инстансами
76
+
77
+ ```typescript
78
+ // Создание нового инстанса
79
+ const instance = await adapter.createInstance(instanceData, settings, userEmail);
80
+
81
+ // Получение данных инстанса
82
+ const details = await adapter.getInstance(instanceId);
83
+
84
+ // Удаление инстанса
85
+ await adapter.removeInstance(instanceId);
86
+ ```
87
+
88
+ ##### Управление пользователями
89
+
90
+ ```typescript
91
+ // Создание нового пользователя
92
+ const user = await adapter.createUser(userEmail, userData);
93
+
94
+ // Обновление пользователя
95
+ await adapter.updateUser(userEmail, updateData);
96
+ ```
97
+
98
+ #### Пример реализации вебхуков
99
+
100
+ ```typescript
101
+ // Конечная точка для вебхуков платформы
102
+ app.post('/webhook/platform', async (req, res) => {
103
+ try {
104
+ await adapter.handlePlatformWebhook(req.body, instanceId);
105
+ res.status(200).send();
106
+ } catch (error) {
107
+ console.error('Не удалось обработать вебхук платформы:', error);
108
+ res.status(500).send();
109
+ }
110
+ });
111
+
112
+ // Конечная точка для вебхуков GREEN-API
113
+ app.post('/webhook/green-api', async (req, res) => {
114
+ try {
115
+ // Обработка определенных типов вебхуков
116
+ await adapter.handleGreenApiWebhook(req.body, [
117
+ 'incomingMessageReceived',
118
+ 'outgoingMessageStatus'
119
+ ]);
120
+ res.status(200).send();
121
+ } catch (error) {
122
+ console.error('Не удалось обработать вебхук GREEN-API:', error);
123
+ res.status(500).send();
124
+ }
125
+ });
126
+ ```
127
+
128
+ ### 2. MessageTransformer
129
+
130
+ Преобразовывает форматы сообщений между GREEN-API и вашей платформой.
131
+
132
+ ```typescript
133
+ abstract class MessageTransformer<TPlatformWebhook, TPlatformMessage> {
134
+ abstract toPlatformMessage(webhook: GreenApiWebhook): TPlatformMessage;
135
+
136
+ abstract toGreenApiMessage(message: TPlatformWebhook): Message;
137
+ }
138
+ ```
139
+
140
+ ### 3. StorageProvider
141
+
142
+ Интерфейс для операций с хранением данных.
143
+
144
+ ```typescript
145
+ abstract class StorageProvider<TUser extends BaseUser = BaseUser, TInstance extends BaseInstance = Instance> {
146
+ abstract createInstance(instance: BaseInstance, userId: bigint | number): Promise<TInstance>;
147
+
148
+ abstract getInstance(idInstance: number | bigint): Promise<TInstance | null>;
149
+
150
+ abstract removeInstance(instanceId: number | bigint): Promise<TInstance>;
151
+
152
+ abstract createUser(data: any): Promise<TUser>;
153
+
154
+ abstract findUser(identifier: string): Promise<TUser | null>;
155
+
156
+ abstract updateUser(identifier: string, data: any): Promise<TUser>;
157
+ }
158
+ ```
159
+
160
+ ### 4. BaseGreenApiAuthGuard
161
+
162
+ Аутентифицирует входящие вебхуки от GREEN-API.
163
+
164
+ ```typescript
165
+ abstract class BaseGreenApiAuthGuard<T extends BaseRequest = BaseRequest> {
166
+ constructor(protected storage: StorageProvider);
167
+
168
+ // Валидация входящих вебхуков
169
+ async validateRequest(request: T): Promise<boolean>;
170
+ }
171
+ ```
172
+
173
+ Пример использования `BaseGreenApiAuthGuard`:
174
+
175
+ ```typescript
176
+ class YourAuthGuard extends BaseGreenApiAuthGuard<YourRequest> {
177
+ constructor(storage: StorageProvider) {
178
+ super(storage);
179
+ }
180
+ }
181
+
182
+ // Использование с Express
183
+ app.post('/webhook', async (req, res) => {
184
+ const guard = new YourAuthGuard(storage);
185
+ try {
186
+ await guard.validateRequest(req);
187
+ // Обработка вебхука ...
188
+ } catch (error) {
189
+ if (error instanceof AuthenticationError) {
190
+ res.status(401).json({error: error.message});
191
+ return;
192
+ }
193
+ res.status(500).json({error: 'Internal server error'});
194
+ }
195
+ });
196
+ ```
197
+
198
+ ### 5. GreenApiLogger
199
+
200
+ Структурированный JSON-логгер с цветным выводом. Обеспечивает единый формат логирования в вашем приложении с корректной
201
+ обработкой ошибок и сериализацией.
202
+
203
+ ```typescript
204
+ const logger = GreenApiLogger.getInstance("YourComponent");
205
+
206
+ // Базовое логирование
207
+ logger.debug("Debug message", {someContext: "value"});
208
+ logger.info("Info message", {userId: 123});
209
+ logger.warn("Warning message", {alert: true});
210
+ logger.error("Error occurred", {errorCode: 500});
211
+ logger.fatal("Fatal error", {critical: true});
212
+
213
+ // Логирование ошибок с контекстом
214
+ try {
215
+ await someOperation();
216
+ } catch (error) {
217
+ logger.logErrorResponse(error, "Operation failed", {
218
+ operationId: "123",
219
+ additionalInfo: "some context"
220
+ });
221
+ }
222
+ ```
223
+
224
+ #### Возможности
225
+
226
+ - Структурированное JSON-логирование в едином формате
227
+ - Цветной вывод в зависимости от уровня лога (debug=голубой, info=зеленый, warn=желтый, error=красный, fatal=пурпурный)
228
+ - Встроенная обработка ошибок с форматированием стека вызовов
229
+ - Автоматическая сериализация
230
+ - Независимость от фреймворка - работает с любым Node.js приложением
231
+ - Специальная обработка ошибок Axios с подробной информацией о запросе/ответе
232
+
233
+ #### Уровни логирования
234
+
235
+ - `debug` - Подробная информация для отладки
236
+ - `info` - Общая информация о работе системы
237
+ - `warn` - Предупреждения о потенциально опасных ситуациях
238
+ - `error` - Сообщения об ошибках
239
+ - `fatal` - Критические ошибки, требующие немедленного внимания
240
+ - `log` - Альтернатива info (для совместимости)
241
+
242
+ #### Формат вывода
243
+
244
+ ```json
245
+ {
246
+ "timestamp": "30/01/2025, 04:34:49",
247
+ "level": "error",
248
+ "context": "CoreService",
249
+ "message": "Operation failed",
250
+ "error": "Failed to process request",
251
+ "stack": [
252
+ "Error: Failed to process request",
253
+ " at CoreService.process (/app/service.js:123:45)",
254
+ " at async Router.handle (/app/router.js:67:89)"
255
+ ],
256
+ "additionalContext": {
257
+ "requestId": "abc-123",
258
+ "userId": "user_456"
259
+ }
260
+ }
261
+ ```
262
+
263
+ #### Обработка ошибок
264
+
265
+ ```typescript
266
+ // Обработка ошибок Axios
267
+ try {
268
+ await apiRequest();
269
+ } catch (error) {
270
+ logger.logErrorResponse(error, "API Request failed", {
271
+ endpoint: "/users",
272
+ method: "POST"
273
+ });
274
+ }
275
+ ```
276
+
277
+ // Получим подробную информацию об ошибке API:
278
+
279
+ ```json
280
+ {
281
+ "timestamp": "30/01/2025, 04:34:49",
282
+ "level": "error",
283
+ "context": "ApiService",
284
+ "message": "API Request failed - API Error:",
285
+ "status": 400,
286
+ "statusText": "Bad Request",
287
+ "data": {
288
+ "error": "Invalid input"
289
+ },
290
+ "url": "https://api.example.com/users",
291
+ "method": "POST",
292
+ "endpoint": "/users"
293
+ }
294
+ ```
295
+
296
+ #### Использование с фреймворками
297
+
298
+ Логгер независим от фреймворков, но легко интегрируется с любым из них:
299
+
300
+ ```typescript
301
+ // Пример с NestJS
302
+ const app = await NestFactory.create(AppModule, {
303
+ logger: GreenApiLogger.getInstance("NestJS")
304
+ });
305
+
306
+ // Пример с Express
307
+ app.use((err, req, res, next) => {
308
+ const logger = GreenApiLogger.getInstance("Express");
309
+ logger.error("Request failed", {
310
+ path: req.path,
311
+ method: req.method,
312
+ error: err.message
313
+ });
314
+ next(err);
315
+ });
316
+ ```
317
+
318
+ #### Важное примечание об использовании логгера
319
+
320
+ Хотя вы можете использовать этот логгер вместе с другими решениями для логирования, рекомендуется отключить встроенный
321
+ логер вашего фреймворка во избежание дублирования или некорректного форматирования логов.
322
+
323
+ Например, при использовании NestJS, вы можете отключить его встроенный логер следующим образом:
324
+
325
+ ```typescript
326
+ // main.ts
327
+ const app = await NestFactory.create(AppModule, {
328
+ logger: false // Отключение логера NestJS
329
+ });
330
+ ```
331
+
332
+ А затем использовать его в вашем классе так:
333
+
334
+ ```typescript
335
+ gaLogger = GreenApiLogger.getInstance(YourClass.name);
336
+ ```
337
+
338
+ #### Методы
339
+
340
+ ##### Основные методы логирования
341
+
342
+ - `debug(message: string, context?: Record<string, any>)`: Логирование отладочной информации
343
+ - `info(message: string, context?: Record<string, any>)`: Логирование информационных сообщений
344
+ - `warn(message: string, context?: Record<string, any>)`: Логирование предупреждений
345
+ - `error(message: string, context?: Record<string, any>)`: Логирование ошибок
346
+ - `fatal(message: string, context?: Record<string, any>)`: Логирование критических ошибок
347
+ - `log(message: string, context?: string)`: Альтернатива методу info
348
+
349
+ ##### Специальные методы
350
+
351
+ - `logErrorResponse(error: any, context: string, additionalContext?: Record<string, any>)`:
352
+ Расширенное логирование ошибок со специальной обработкой ошибок Axios и стека вызовов
353
+
354
+ ##### Вспомогательные методы
355
+
356
+ - `getInstance(context: string = "Global"): GreenApiLogger`: Получение или создание экземпляра логгера для указанного
357
+ контекста
358
+
359
+ #### Лучшие практики
360
+
361
+ 1. **Используйте последовательные имена контекста**
362
+
363
+ ```typescript
364
+ // В вашем компоненте/сервисе
365
+ private readonly
366
+ logger = GreenApiLogger.getInstance(YourService.name);
367
+ ```
368
+
369
+ 2. **Включайте релевантный контекст**
370
+
371
+ ```typescript
372
+ logger.info("User action completed", {
373
+ userId: user.id,
374
+ action: "profile_update",
375
+ duration: timeTaken
376
+ });
377
+ ```
378
+
379
+ 3. **Правильная обработка ошибок**
380
+
381
+ ```typescript
382
+ try {
383
+ await complexOperation();
384
+ } catch (error) {
385
+ logger.logErrorResponse(error, "Complex operation failed", {
386
+ operationId: id,
387
+ parameters: params
388
+ });
389
+ }
390
+ ```
391
+
392
+ 4. **Используйте соответствующие уровни логирования**
393
+
394
+ ```typescript
395
+ // Debug для детальной информации
396
+ logger.debug("Processing chunk", {chunkId: 123, size: 1024});
397
+
398
+ // Info для общей информации о работе
399
+ logger.info("User logged in", {userId: 456});
400
+
401
+ // Warn для потенциальных проблем
402
+ logger.warn("High memory usage", {memoryUsage: "85%"});
403
+
404
+ // Error для реальных проблем
405
+ logger.error("Database connection failed", {dbHost: "primary"});
406
+
407
+ // Fatal для критических проблем
408
+ logger.fatal("System shutdown required", {reason: "data corruption"});
409
+ ```
410
+
411
+ ### 6. GreenApiClient
412
+
413
+ Прямой интерфейс к методам GREEN-API.
414
+
415
+ ```typescript
416
+ const client = new GreenApiClient({
417
+ idInstance: 'your_instance_id',
418
+ apiTokenInstance: 'your_token'
419
+ });
420
+
421
+ // Примеры специальных операций:
422
+ await client.setProfilePicture(fileBlob);
423
+ await client.getAuthorizationCode(phoneNumber);
424
+ await client.getQR();
425
+ ```
426
+
427
+ ## Руководство для разработчика
428
+
429
+ Это руководство проведет вас через процесс создания вашей первой интеграции с WhatsApp шлюзом GREEN-API.
430
+
431
+ ### Структура проекта
432
+
433
+ ```
434
+ your-integration/
435
+ ├── src/
436
+ │ ├── core/
437
+ │ │ ├── adapter.ts # Адаптер платформы
438
+ │ │ ├── transformer.ts # Преобразователь сообщений
439
+ │ │ ├── storage.ts # Реализация хранилища
440
+ │ │ └── router.ts # Эндпоинты для вебхуков
441
+ │ ├── types/
442
+ │ │ └── types.ts # Типы
443
+ │ └── main.ts # Точка запуска приложения
444
+ ├── package.json
445
+ └── tsconfig.json
446
+ ```
447
+
448
+ ```mermaid
449
+ graph TB
450
+ subgraph "WhatsApp в Платформу"
451
+ WA[WhatsApp] -->|Отправка сообщения| GA1[GREEN-API]
452
+ GA1 -->|Вебхук| INT1[Ваша Интеграция]
453
+ INT1 -->|1 . Валидация вебхука| GD1[BaseGreenApiAuthGuard]
454
+ INT1 -->|2 . Преобразование сообщения| TR1[MessageTransformer]
455
+ INT1 -->|3 . Отправка в платформу| PL1[Ваша Платформа]
456
+ end
457
+
458
+ subgraph "Платформа в WhatsApp"
459
+ PL2[Ваша Платформа] -->|Вебхук| INT2[Ваша Интеграция]
460
+ INT2 -->|1 . Преобразование сообщения| TR2[MessageTransformer]
461
+ INT2 -->|2 . Отправка через API| GA2[GREEN-API]
462
+ GA2 -->|Отправка сообщения| WA2[WhatsApp]
463
+ end
464
+
465
+ subgraph "Компоненты"
466
+ style Компоненты fill: #f9f9f9, stroke: #333, stroke-width: 2px
467
+ TR[MessageTransformer]
468
+ ST[StorageProvider]
469
+ AD[BaseAdapter]
470
+ GD[WebhookGuard]
471
+ end
472
+ ```
473
+
474
+ ### Этапы реализации
475
+
476
+ #### Этап 1: Определение типов платформы
477
+
478
+ Сначала определите типы сообщений для вашей платформы:
479
+
480
+ ```typescript
481
+ // types/types.ts
482
+ export interface YourPlatformWebhook {
483
+ id: string;
484
+ from: string;
485
+ message: string;
486
+ timestamp: number;
487
+ // Добавьте другие поля, специфичные для вашей платформы
488
+ }
489
+
490
+ export interface YourPlatformMessage {
491
+ recipient: string;
492
+ content: string;
493
+ // Добавьте другие поля, специфичные для вашей платформы
494
+ }
495
+ ```
496
+
497
+ #### Этап 2. Создание преобразователя сообщений
498
+
499
+ Создайте преобразователь, который конвертирует сообщения между форматом вашей платформы и форматом GREEN-API:
500
+
501
+ ```typescript
502
+ // core/transformer.ts
503
+ import { MessageTransformer, Message, GreenApiWebhook } from '@green-api/greenapi-integration';
504
+ import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
505
+
506
+ export class YourTransformer extends MessageTransformer<YourPlatformWebhook, YourPlatformMessage> {
507
+ toPlatformMessage(webhook: GreenApiWebhook): YourPlatformMessage {
508
+ // Преобразование вебхука GREEN-API в формат вашей платформы
509
+ return {
510
+ recipient: webhook.senderData.sender,
511
+ content: webhook.messageData.textMessageData?.textMessage || '',
512
+ };
513
+ }
514
+
515
+ toGreenApiMessage(message: YourPlatformWebhook): Message {
516
+ // Преобразование вебхука вашей платформы в формат GREEN-API
517
+ return {
518
+ type: 'text',
519
+ chatId: message.from,
520
+ message: message.message,
521
+ };
522
+ }
523
+ }
524
+ ```
525
+
526
+ #### Этап 3: Реализация хранилища
527
+
528
+ Создайте провайдер хранилища для управления пользователями и инстансами. Вы можете использовать любую базу данных или
529
+ ORM:
530
+
531
+ ```typescript
532
+ // core/storage.ts
533
+ import { StorageProvider, BaseUser, Instance, Settings } from '@green-api/greenapi-integration';
534
+ import { PrismaClient } from '@prisma/client'; // Or your database client
535
+
536
+ export class YourStorage extends StorageProvider {
537
+ private db: PrismaClient;
538
+
539
+ constructor() {
540
+ this.db = new PrismaClient();
541
+ }
542
+
543
+ async createInstance(instance: Instance, userId: bigint) {
544
+ return this.db.instance.create({
545
+ data: {
546
+ idInstance: instance.idInstance,
547
+ apiTokenInstance: instance.apiTokenInstance,
548
+ userId,
549
+ settings: instance.settings || {},
550
+ },
551
+ });
552
+ }
553
+
554
+ // Остальные методы
555
+ }
556
+ ```
557
+
558
+ #### Этап 4: Создание адаптера платформы
559
+
560
+ Адаптер обрабатывает фактическое взаимодействие между платформами:
561
+
562
+ ```typescript
563
+ // core/adapter.ts
564
+ import { BaseAdapter, Instance } from '@green-api/greenapi-integration';
565
+ import { YourPlatformClient } from 'your-platform-sdk';
566
+ import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
567
+
568
+ export class YourAdapter extends BaseAdapter<YourPlatformWebhook, YourPlatformMessage> {
569
+ async createPlatformClient(config: { apiKey: string, apiUrl: string }) {
570
+ return new YourPlatformClient({
571
+ baseUrl: config.apiUrl,
572
+ apiKey: config.apiKey,
573
+ });
574
+ }
575
+
576
+ async sendToPlatform(message: YourPlatformMessage, instance: Instance) {
577
+ const client = await this.createPlatformClient(instance.config);
578
+ await client.sendMessage(message);
579
+ }
580
+ }
581
+ ```
582
+
583
+ #### Этап 5: Реализация контроллера вебхуков
584
+
585
+ Определите эндпоинты вебхуков, которые будет слушать ваше приложение:
586
+
587
+ ```typescript
588
+ // core/webhook.ts
589
+ import express from 'express';
590
+ import { YourAdapter } from '../core/adapter';
591
+ import { YourTransformer } from '../core/transformer';
592
+ import { YourStorage } from '../core/storage';
593
+
594
+ const router = express.Router();
595
+ const storage = new YourStorage();
596
+ const transformer = new YourTransformer();
597
+ const adapter = new YourAdapter(transformer, storage);
598
+
599
+ class WebhookGuard extends BaseGreenApiAuthGuard {
600
+ constructor(storage: StorageProvider) {
601
+ super(storage);
602
+ }
603
+ }
604
+
605
+ const guard = new WebhookGuard(storage);
606
+
607
+ // Эндпоинты для вебхуков
608
+ router.post('/green-api', async (req, res) => {
609
+ try {
610
+ // Проверка вебхука
611
+ await guard.validateRequest(req);
612
+
613
+ // Обработка вебхука после проверки.
614
+ // В списке вторым параметром укажите типы вебхуков, которые необходимо обработать
615
+ await adapter.handleGreenApiWebhook(req.body, ['incomingMessageReceived']);
616
+ res.status(200).json({status: 'ok'});
617
+ } catch (error) {
618
+ if (error instanceof AuthenticationError) {
619
+ res.status(401).json({error: 'Ошибка аутентификации'});
620
+ return;
621
+ }
622
+ console.error('Ошибка обработки вебхука:', error);
623
+ res.status(500).json({error: 'Внутренняя ошибка сервера'});
624
+ }
625
+ });
626
+
627
+ router.post('/platform', async (req, res) => {
628
+ try {
629
+ const instanceId = req.query.instanceId;
630
+ await adapter.handlePlatformWebhook(req.body, instanceId);
631
+ res.status(200).json({status: 'ok'});
632
+ } catch (error) {
633
+ console.error('Ошибка обработки вебхука платформы:', error);
634
+ res.status(500).json({error: 'Внутренняя ошибка сервера'});
635
+ }
636
+ });
637
+
638
+ router.post('/instance', async (req, res) => {
639
+ try {
640
+ const {idInstance, apiTokenInstance, userEmail} = req.body;
641
+
642
+ if (!idInstance || !apiTokenInstance || !userEmail) {
643
+ throw new BadRequestError('Отсутствуют обязательные поля');
644
+ }
645
+
646
+ const instance = await adapter.createInstance({
647
+ idInstance: Number(idInstance),
648
+ apiTokenInstance,
649
+ settings: {
650
+ webhookUrl: `${process.env.APP_URL}/webhook/green-api`,
651
+ webhookUrlToken: `token_${Date.now()}`,
652
+ incomingWebhook: 'yes'
653
+ }
654
+ }, userEmail);
655
+
656
+ res.status(200).json({
657
+ status: 'ok',
658
+ data: instance,
659
+ message: 'Инстанс успешно создан. Подождите 2 минуты для применения настроек.'
660
+ });
661
+
662
+ } catch (error) {
663
+ console.error('Ошибка создания инстанса:', error);
664
+ res.status(500).json({error: 'Не удалось создать инстанс'});
665
+ }
666
+ });
667
+
668
+ export default router;
669
+ ```
670
+
671
+ #### Этап 6: Создание точки входа приложения
672
+
673
+ Соберите все компоненты вместе в точке входа:
674
+
675
+ ```typescript
676
+ // main.ts
677
+ import express from 'express';
678
+ import bodyParser from 'body-parser';
679
+ import dotenv from 'dotenv';
680
+ import webhookRouter from './controllers/webhook';
681
+ import { YourAdapter } from './core/adapter';
682
+ import { YourTransformer } from './core/transformer';
683
+ import { YourStorage } from './core/storage';
684
+
685
+ // Загрузка переменных окружения
686
+ dotenv.config();
687
+
688
+ async function bootstrap() {
689
+ // Инициализация компонентов
690
+ const storage = new YourStorage();
691
+ const transformer = new YourTransformer();
692
+ const adapter = new YourAdapter(transformer, storage);
693
+
694
+ // Создание Express приложения
695
+ const app = express();
696
+ app.use(bodyParser.json());
697
+
698
+ // Настройка маршрутов для вебхуков
699
+ app.use('/webhook', webhookRouter);
700
+
701
+ // Запуск сервера
702
+ const port = process.env.PORT || 3000;
703
+ app.listen(port, () => {
704
+ console.log(`Сервер запущен на порту ${port}`);
705
+ });
706
+
707
+ console.log('Интеграционная платформа готова!');
708
+ }
709
+
710
+ // Обработка ошибок
711
+ bootstrap();
712
+ ```
713
+
714
+ Или с NestJS:
715
+
716
+ ```typescript
717
+ // main.ts
718
+ import { NestFactory } from '@nestjs/core';
719
+ import { AppModule } from './app.module';
720
+ import helmet from 'helmet';
721
+
722
+ async function bootstrap() {
723
+ const app = await NestFactory.create(AppModule);
724
+ app.setGlobalPrefix('api');
725
+ app.use(helmet());
726
+ await app.listen(process.env.PORT ?? 3000);
727
+ }
728
+
729
+ bootstrap();
730
+ ```
731
+
732
+ ### Сборка приложения
733
+
734
+ 1. **Подготовка package.json**
735
+
736
+ ```json
737
+ {
738
+ "name": "greenapi-integration-yourplatform",
739
+ "version": "1.0.0",
740
+ "main": "dist/index.js",
741
+ "types": "dist/index.d.ts",
742
+ "scripts": {
743
+ "build": "tsc",
744
+ "prepublishOnly": "npm run build"
745
+ },
746
+ "dependencies": {
747
+ "@green-api/greenapi-integration": "^0.4.0",
748
+ "@prisma/client": "^5.0.0",
749
+ "express": "^4.18.2"
750
+ // другие зависимости
751
+ }
752
+ }
753
+ ```
754
+
755
+ 2. **Сборка**
756
+
757
+ ```bash
758
+ npm run build
759
+ npm publish
760
+ ```
761
+
762
+ ## Рабочий пример
763
+
764
+ В директории `/examples/custom-adapter` вы найдете полный рабочий пример, демонстрирующий:
765
+
766
+ - Двустороннюю передачу сообщений между WhatsApp и пользовательской платформой
767
+ - Обработку вебхуков
768
+ - Настройку и конфигурацию инстанса
769
+ - Преобразование сообщений
770
+ - Обработку ошибок
771
+
772
+ ### Запуск примера
773
+
774
+ 1. Клонируйте репозиторий
775
+ 2. Обновите .env данными ваших инстансов GREEN-API:
776
+
777
+ ```env
778
+ VISITOR_ID_INSTANCE=your_visitor_instance_id
779
+ VISITOR_API_TOKEN=your_visitor_instance_token
780
+ AGENT_ID_INSTANCE=your_agent_instance_id
781
+ AGENT_API_TOKEN=your_agent_instance_token
782
+ AGENT_PHONE_NUMBER=your_agent_phone_number
783
+ WEBHOOK_URL=your_webhook_url
784
+ PORT=3000
785
+ ```
786
+
787
+ 3. Установите зависимости и запустите:
788
+
789
+ ```bash
790
+ cd examples/custom-adapter
791
+ npm install
792
+ npm start
793
+ ```
794
+
795
+ # Полная реализация примера
796
+
797
+ ### Структура проекта
798
+
799
+ ```
800
+ examples/
801
+ └── custom-adapter/
802
+ ├── src/
803
+ │ ├── main.ts
804
+ │ ├── simple-adapter.ts
805
+ │ ├── simple-transformer.ts
806
+ │ ├── simple-storage.ts
807
+ │ └── types.ts
808
+ ├── .env
809
+ ├── package.json
810
+ └── tsconfig.json
811
+ ```
812
+
813
+ ### types.ts
814
+
815
+ ```typescript
816
+ interface SimplePlatformWebhook {
817
+ messageId: string;
818
+ from: string;
819
+ text: string;
820
+ timestamp: number;
821
+ }
822
+
823
+ interface SimplePlatformMessage {
824
+ to: string;
825
+ content: string;
826
+ replyTo?: string;
827
+ }
828
+ ```
829
+
830
+ ### simple-transformer.ts
831
+
832
+ ```typescript
833
+ import {
834
+ MessageTransformer,
835
+ Message,
836
+ GreenApiWebhook,
837
+ formatPhoneNumber,
838
+ IntegrationError
839
+ } from '@green-api/greenapi-integration';
840
+
841
+ export class SimpleTransformer extends MessageTransformer<SimplePlatformWebhook, SimplePlatformMessage> {
842
+ toPlatformMessage(webhook: GreenApiWebhook): SimplePlatformMessage {
843
+ if (webhook.typeWebhook === "incomingMessageReceived") {
844
+ if (webhook.messageData.typeMessage !== "extendedTextMessage") {
845
+ throw new IntegrationError("Поддерживаются только текстовые сообщения", "BAD_REQUEST_ERROR", 400);
846
+ }
847
+
848
+ return {
849
+ to: webhook.senderData.sender,
850
+ content: webhook.messageData.extendedTextMessageData?.text || "",
851
+ };
852
+ }
853
+ throw new IntegrationError("Поддерживаются только вебхуки вида incomingMessageReceived", "INTEGRATION_ERROR", 500);
854
+ }
855
+
856
+ toGreenApiMessage(message: SimplePlatformWebhook): Message {
857
+ return {
858
+ type: 'text',
859
+ chatId: formatPhoneNumber(message.from),
860
+ message: message.text,
861
+ };
862
+ }
863
+ }
864
+ ```
865
+
866
+ ### simple-storage.ts
867
+
868
+ ```typescript
869
+ import { StorageProvider, BaseUser, Instance, Settings } from '@green-api/greenapi-integration';
870
+
871
+ export class SimpleStorage extends StorageProvider {
872
+ private users: Map<string, BaseUser> = new Map();
873
+ private instances: Map<number, Instance> = new Map();
874
+
875
+ async createInstance(instance: Instance, userId: bigint): Promise<Instance> {
876
+ this.instances.set(Number(instance.idInstance), {
877
+ ...instance,
878
+ });
879
+ return instance;
880
+ }
881
+
882
+ async getInstance(idInstance: number): Promise<Instance | null> {
883
+ return this.instances.get(idInstance) || null;
884
+ }
885
+
886
+ async removeInstance(instanceId: number): Promise<Instance> {
887
+ const instance = this.instances.get(instanceId);
888
+ if (!instance) throw new Error('Инстанс не найден');
889
+ this.instances.delete(instanceId);
890
+ return instance;
891
+ }
892
+
893
+ async createUser(data: any): Promise<BaseUser> {
894
+ const user = {id: Date.now(), ...data};
895
+ this.users.set(data.email, user);
896
+ return user;
897
+ }
898
+
899
+ async findUser(identifier: string): Promise<BaseUser | null> {
900
+ return this.users.get(identifier) || null;
901
+ }
902
+
903
+ async updateUser(identifier: string, data: any): Promise<BaseUser> {
904
+ const user = await this.findUser(identifier);
905
+ if (!user) throw new Error('Пользователь не найден');
906
+ const updated = {...user, ...data};
907
+ this.users.set(identifier, updated);
908
+ return updated;
909
+ }
910
+ }
911
+ ```
912
+
913
+ ### simple-adapter.ts
914
+
915
+ ```typescript
916
+ import { BaseAdapter, Instance } from "@green-api/greenapi-integration";
917
+ import axios from 'axios';
918
+
919
+ export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlatformMessage> {
920
+ async createPlatformClient(config: { apiKey: string, apiUrl: string }) {
921
+ return axios.create({
922
+ baseURL: config.apiUrl,
923
+ headers: {
924
+ 'Authorization': `Bearer ${config.apiKey}`,
925
+ 'Content-Type': 'application/json'
926
+ }
927
+ });
928
+ }
929
+
930
+ async sendToPlatform(message: SimplePlatformMessage, instance: Instance): Promise<void> {
931
+ // В реальной реализации мы бы отправляли сообщение на платформу
932
+ // Для демонстрации просто логируем и симулируем ответ
933
+ console.log('Платформа получила сообщение:', message);
934
+
935
+ // Симулируем обработку и ответ платформы
936
+ setTimeout(() => {
937
+ console.log('Обработка платформой завершена, отправляем ответ...');
938
+ this.simulatePlatformResponse(message, instance.idInstance);
939
+ }, 1000);
940
+ }
941
+
942
+ private async simulatePlatformResponse(originalMessage: SimplePlatformMessage, idInstance: number | bigint) {
943
+ const platformWebhook: SimplePlatformWebhook = {
944
+ messageId: `resp_${Date.now()}`,
945
+ from: originalMessage.to.replace('@c.us', ''),
946
+ text: `Спасибо за ваше сообщение: "${originalMessage.content}". Это автоматический ответ.`,
947
+ timestamp: Date.now()
948
+ };
949
+
950
+ await this.handlePlatformWebhook(platformWebhook, idInstance);
951
+ }
952
+ }
953
+ ```
954
+
955
+ ### main.ts
956
+
957
+ ```typescript
958
+ import express from "express";
959
+ import bodyParser from "body-parser";
960
+ import { formatPhoneNumber, GreenApiClient } from "@green-api/greenapi-integration";
961
+ import { SimpleTransformer } from "./simple-transformer";
962
+ import { SimpleStorage } from "./simple-storage";
963
+ import { SimpleAdapter } from "./simple-adapter";
964
+ import * as dotenv from "dotenv";
965
+
966
+ dotenv.config();
967
+
968
+ async function main() {
969
+ // Инициализация компонентов
970
+ const transformer = new SimpleTransformer();
971
+ const storage = new SimpleStorage();
972
+ const adapter = new SimpleAdapter(transformer, storage);
973
+
974
+ // Конфигурация обоих инстансов
975
+ const visitorInstance = {
976
+ idInstance: Number(process.env.VISITOR_ID_INSTANCE),
977
+ apiTokenInstance: process.env.VISITOR_API_TOKEN!,
978
+ };
979
+
980
+ const agentInstance = {
981
+ idInstance: Number(process.env.AGENT_ID_INSTANCE),
982
+ apiTokenInstance: process.env.AGENT_API_TOKEN!,
983
+ };
984
+
985
+ // Создание клиента GREEN-API для посетителя (для отправки начального сообщения)
986
+ const visitorClient = new GreenApiClient(visitorInstance);
987
+
988
+ // Настройка инстанса агента
989
+ console.log("Настройка инстанса агента...");
990
+ const user = await adapter.createUser("agent@example.com", {
991
+ email: "agent@example.com",
992
+ name: "Agent",
993
+ });
994
+
995
+ const instance = await adapter.createInstance({
996
+ idInstance: agentInstance.idInstance, apiTokenInstance: agentInstance.apiTokenInstance, settings: {
997
+ webhookUrl: process.env.WEBHOOK_URL + "/webhook/green-api",
998
+ webhookUrlToken: "your-secure-token",
999
+ incomingWebhook: "yes",
1000
+ },
1001
+ }, user.email);
1002
+
1003
+ console.log("Ожидание 2 минуты для применения настроек...");
1004
+ await new Promise(resolve => setTimeout(resolve, 120000));
1005
+ console.log("Инстанс готов!");
1006
+
1007
+ // Настройка веб-сервера
1008
+ const app = express();
1009
+ app.use(bodyParser.json());
1010
+
1011
+ // Обработка вебхуков от GREEN-API
1012
+ app.post("/webhook/green-api", async (req, res) => {
1013
+ try {
1014
+ console.log("Получен вебхук от GREEN-API:", req.body);
1015
+ await adapter.handleGreenApiWebhook(req.body, ["incomingMessageReceived"]);
1016
+ res.status(200).json({status: "ok"});
1017
+ } catch (error) {
1018
+ console.error("Ошибка обработки вебхука:", error);
1019
+ res.status(500).json({error: "Внутренняя ошибка сервера"});
1020
+ }
1021
+ });
1022
+
1023
+ // Запуск сервера
1024
+ const port = Number(process.env.PORT) || 3000;
1025
+ app.listen(port, () => {
1026
+ console.log(`Сервер вебхуков запущен на порту ${port}`);
1027
+ });
1028
+
1029
+ // Отправка начального сообщения от посетителя
1030
+ console.log("Отправка начального сообщения от посетителя...");
1031
+ await visitorClient.sendMessage({
1032
+ chatId: formatPhoneNumber(process.env.AGENT_PHONE_NUMBER!),
1033
+ message: "Здравствуйте! Это тестовое сообщение от посетителя.",
1034
+ type: "text",
1035
+ });
1036
+
1037
+ console.log("Начальное сообщение отправлено! Проверьте WhatsApp агента для просмотра ответа.");
1038
+ }
1039
+
1040
+ main().catch(console.error);
1041
+ ```
1042
+
1043
+ ### .env
1044
+
1045
+ ```env
1046
+ VISITOR_ID_INSTANCE=your_visitor_instance_id
1047
+ VISITOR_API_TOKEN=your_visitor_instance_token
1048
+ AGENT_ID_INSTANCE=your_agent_instance_id
1049
+ AGENT_API_TOKEN=your_agent_instance_token
1050
+ AGENT_PHONE_NUMBER=your_agent_phone_number
1051
+ WEBHOOK_URL=your_webhook_url
1052
+ PORT=3000
1053
+ ```
1054
+
1055
+ ## Реальные примеры
1056
+
1057
+ Для полных примеров реальных интеграций, смотрите:
1058
+
1059
+ - [Интеграция с Rocket.Chat](https://github.com/green-api/greenapi-integration-rocketchat)
1060
+
1061
+ ## Утилиты
1062
+
1063
+ Платформа предоставляет несколько вспомогательных функций:
1064
+
1065
+ ```typescript
1066
+ // Форматирование телефонных номеров для GREEN-API
1067
+ formatPhoneNumber('+1234567890') // Возвращает '1234567890@c.us'
1068
+
1069
+ // Генерация безопасных случайных токенов
1070
+ generateRandomToken(32) // Возвращает 32-символьный случайный токен
1071
+
1072
+ // Извлечение номера телефона из vcard
1073
+ const vcard = 'BEGIN:VCARD\nTEL:+1234567890\nEND:VCARD'
1074
+ extractPhoneNumberFromVCard(vcard) // Возвращает '+1234567890'
1075
+
1076
+ // Проверка значений настроек
1077
+ isValidSettingValue('webhookUrl', 'https://example.com') // Возвращает true
1078
+
1079
+ // Очистка настроек
1080
+ const input = {
1081
+ webhookUrl: 'https://example.com',
1082
+ outgoingWebhook: 'yes',
1083
+ invalidKey: 'value',
1084
+ delaySendMessagesMilliseconds: 'invalid'
1085
+ }
1086
+ validateAndCleanSettings(input) // Возвращает { webhookUrl: 'https://example.com', outgoingWebhook: 'yes' }
1087
+ ```
1088
+
1089
+ ## Лицензия
1090
+
1091
+ MIT
1092
+ ]()