@green-api/greenapi-integration 0.6.0 → 0.6.1
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.
- package/LICENSE +21 -0
- package/README.md +1080 -1061
- package/README.ru.md +1092 -1068
- package/dist/types/types.d.ts +14 -1
- package/package.json +42 -41
package/README.ru.md
CHANGED
|
@@ -1,1068 +1,1092 @@
|
|
|
1
|
-
# Универсальная интеграционная платформа для GREEN-API
|
|
2
|
-
|
|
3
|
-
## Поддержка
|
|
4
|
-
|
|
5
|
-
[](mailto:support@greenapi.com)
|
|
6
|
-
[](https://t.me/greenapi_support_bot)
|
|
7
|
-
[](https://wa.me/77273122366)
|
|
8
|
-
|
|
9
|
-
## Руководства и новости
|
|
10
|
-
|
|
11
|
-
[](https://www.youtube.com/@green-api)
|
|
12
|
-
[](https://t.me/green_api)
|
|
13
|
-
[](https://whatsapp.com/channel/0029VaLj6J4LNSa2B5Jx6s3h)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
- [
|
|
26
|
-
- [
|
|
27
|
-
- [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
// Обработка вебхуков от
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
//
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
//
|
|
82
|
-
await adapter.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
//
|
|
92
|
-
await adapter.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
res.status(
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
res.status(
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
logger.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
logger.
|
|
208
|
-
logger.
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
- `
|
|
236
|
-
- `
|
|
237
|
-
- `
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
"
|
|
247
|
-
"
|
|
248
|
-
"
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
"
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
"
|
|
282
|
-
"
|
|
283
|
-
"
|
|
284
|
-
"
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
"
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
```typescript
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
logger.
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
//
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
```
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
import
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
bootstrap()
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
//
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
```
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
const
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
//
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1
|
+
[# Универсальная интеграционная платформа для GREEN-API
|
|
2
|
+
|
|
3
|
+
## Поддержка
|
|
4
|
+
|
|
5
|
+
[](mailto:support@greenapi.com)
|
|
6
|
+
[](https://t.me/greenapi_support_bot)
|
|
7
|
+
[](https://wa.me/77273122366)
|
|
8
|
+
|
|
9
|
+
## Руководства и новости
|
|
10
|
+
|
|
11
|
+
[](https://www.youtube.com/@green-api)
|
|
12
|
+
[](https://t.me/green_api)
|
|
13
|
+
[](https://whatsapp.com/channel/0029VaLj6J4LNSa2B5Jx6s3h)
|
|
14
|
+
|
|
15
|
+
[](https://www.npmjs.com/package/@green-api/whatsapp-chatbot-js-v2)
|
|
16
|
+
[](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
|
+
]()
|