Перейти к основному содержимому

Примеры интеграции | Документация для разработчиков

Примеры интеграции

Обновлено: 25 февраля 2026 г
В этом руководстве объясняется интеграция распространенных VoIP-платформ с API бизнес-звонков WhatsApp.
Данное руководство носит исключительно информационный характер и не предоставляет никаких гарантий или поддержки со стороны Meta или какого-либо поставщика. Существует множество способов интеграции, и в руководстве описан лишь один из них, исключительно в иллюстративных целях.

Asterisk с использованием SIP

Обзор

В этом руководстве объясняется, как настроить API для бизнес-звонков WhatsApp с использованием SIP-сигнализации в Asterisk открытой АТС (частной телефонной станции). Вы узнаете, как настроить сервер Asterisk, подключить SIP-телефоны и обрабатывать как входящие, так и исходящие звонки WhatsApp.
Звонки, инициированные пользователем
    Пользователь WhatsApp набирает номер компании.Вызов принимается системой Asterisk и направляется через IVR, предлагая пользователю ввести добавочный номер, зарегистрированный на том же сервере Asterisk.Затем вызов соединяется с указанным добавочным номером.
    Звонки, инициированные бизнесом
      Бизнес-агент/пользователь регистрируется в Asterisk, используя учетные данные SIP (см. раздел « Настройка VoIP-телефона »).Корпоративный пользователь набирает добавочный номер b2c-sip (бизнес для потребителя), который обрабатывается системой интерактивного голосового ответа (IVR). IVR запрашивает номер WhatsApp для звонка.Затем звонок соединяется с пользователем WhatsApp.
      На этапе передачи данных от WA к Asterisk используется SDES для обмена ключами шифрования мультимедиа и Opus для аудиокодека
      В соединении Asterisk с SIP UA для обмена ключами шифрования мультимедиа используется SDES, а для аудиокодеков — Opus или G711

      Предварительные требования

        Развертывание Asterisk: Asterisk развертывается (например, на экземпляре публичного облака)Операционная система: Любая ОС, совместимая с Asterisk. Например, CentOS 9Домен: Сервер Asterisk доступен через общедоступный домен с действительным сертификатомWhatsApp Business API: Зарегистрирован бизнес-номер телефона WhatsApp, и включена возможность совершения звонков.Поддержка SIP: SIP включен на бизнес-номере WhatsApp.SDES: Функция SDES включена для бизнес-номера WhatsApp.

        Сборка и установка Asterisk

        Данное руководство было протестировано с использованием Asterisk версии 22.5.2

        Конфигурация Asterisk

        Эти конфигурационные файлы находятся в каталоге /etc/asterisk/
        extensions.conf
        Замените следующие заполнители фактическими значениями
          {wa-business-phone-number}: Рабочий номер телефона WhatsApp{asterisk-sip-server-dns}: DNS-имя вашего SIP-сервера Asteriskincoming_welcome: incoming_welcome.wav (не предоставлен) поместите этот файл в /var/lib/asterisk/soundsoutgoing_welcome: outgoing_welcome.wav (не предоставлен) поместите этот файл в /var/lib/asterisk/sounds
          [ c2b - sub - dial ] exten => s , 1 , NoOp () same => n , Read ( Digits , incoming_welcome , 0 ,, 5 , 500 ) same => n , Dial ( PJSIP / $ { Digits }) same => n , Hangup () [ whatsapp ] exten => _10XX , 1 , NoOp () same => n , Dial ( PJSIP / $ { EXTEN }) same => n , Hangup () ; Расширение для бизнес - звонков B2C через шлюз Meta SIP exten = > b2c - sip , 1 , NoOp ( ) same = > n , Read ( Digits , outgoing_welcome , 0 , 5 , 500 ) same = > n , Dial ( PJSIP / whatsapp / sip : $ { Digits}@wa.meta.vc ) ; Расширение для обработки входящих запросов приглашения от шлюза Meta SIP на <wa-business-phone-number> @ <asterisk-sip-server-dns> exten = > _ + <wa-business-phone-number> , 1 , Goto ( c2b - sub - dial , s , 1 )
          Pjsip.conf
          Замените следующие заполнители фактическими значениями
            {wa-business-phone-number} : рабочий номер телефона{local-net}: локальная сеть сервера Asterisk{external-media-address}: Публичный IP-адрес медиасервера Asterisk{external-signaling-address}: Публичный IP-адрес сигнального сервера Asterisk{sip-ua-password}: Выбранный пароль SIP User Agent{domain-name}: доменное имя, присвоенное серверу Asterisk
            Файлы сертификатов следует размещать в папках /var/lib/asterisk/certs/fullchain.cer и /var/lib/asterisk/certs/cer.key
            [ transport - tls ] type = transport protocol = tls bind = 0.0.0.0:5061 cert_file = /var/lib/asterisk/certs/fullchain.cer priv_key_file = /var/lib/asterisk/certs/cer.key method = sslv23 allow_wildcard_certs = yes external_media_address = { external - media - address } ; External address for SIP signalling external_signaling_address = { external - signaling - address } ; Сеть, которую следует считать локальной, используется для целей NAT local_net ={ local - net } [ sdes_endpointtemplate ](!) type = endpoint context = whatsapp disallow = all allow = OPUS direct_media = no rtp_symmetric = yes force_rport = yes rewrite_contact = no media_use_received_transport = yes media_encryption = sdes [ authtemplate ](!) type = auth auth_type = userpass password ={ sip - ua - password } [ aortemplate ](!) type = aor max_contacts = 1 remove_existing = yes [ aoridentitytemplate ](!) type = identify match_header = X - FB - External - Domain : wa . meta . vc ; SDES users [ 1000 ]( sdes_endpointtemplate ) auth = 1000 _auth aors = 1000 [ 1000 _auth ]( authtemplate ) username = 1000 [ 1000 ]( aortemplate ) [ 1000 ]( aoridentitytemplate ) endpoint = 1000 [ 1001 ]( sdes_endpointtemplate ) auth = 1001 _auth aors = 1001 [ 1001 _auth ]( authtemplate ) username = 1001 [ 1001 ]( aortemplate ) [ 1001 ]( aoridentitytemplate ) endpoint = 1001 [ 1002 ]( sdes_endpointtemplate ) auth = 1002 _auth aors = 1002 [ 1002 _auth ]( authtemplate ) username = 1002 [ 1002 ]( aortemplate ) [ 1002 ]( aoridentitytemplate ) endpoint = 1002 [ 1003 ]( sdes_endpointtemplate ) auth = 1003 _auth aors = 1003 [ 1003 _auth ]( authtemplate ) username = 1003 [ 1003 ]( aortemplate ) [ 1003 ]( aoridentitytemplate ) endpoint = 1003 [ 1004 ]( sdes_endpointtemplate ) auth = 1004 _auth aors = 1004 [ 1004 _auth ]( authtemplate ) username = 1004 [ 1004 ]( aortemplate ) [ 1004 ]( aoridentitytemplate ) endpoint = 1004 [ 1005 ]( sdes_endpointtemplate ) auth = 1005 _auth aors = 1005 [ 1005 _auth ]( authtemplate ) username = 1005 [ 1005 ]( aortemplate ) [ 1005 ]( aoridentitytemplate ) endpoint = 1005 ; Эта конечная точка сопоставляется с IVR для вызовов C2B [ c2b - sip ]( sdes_endpointtemplate ) [ c2b - sip ]( aortemplate ) [ c2b - sip ] type = identify endpoint = c2b - sip match_header = X - FB - External - Domain : wa . meta . vc ; специальная конечная точка для интеграции с Meta SIP Gateway ; Эта конечная точка соответствует IVR для звонков B2C [ b2c - sip ]( sdes_endpointtemplate ) [ b2c - sip ]( aortemplate ) [ whatsapp ]( sdes_endpointtemplate ) type = endpoint transport = transport - tls disallow = all allow = opus , ulaw , alaw aors = whatsapp from_user ={ wa - business - phone - number } from_domain ={ domain - name } outbound_auth = whatsapp [ whatsapp ] type = aor contact = sip : wa . meta . vc [ whatsapp ] type = identify endpoint = whatsapp [ whatsapp ] type = auth auth_type = digest password ={ meta - sip - user - password } username ={ wa - business - phone - number } realm =*
            rtp.conf
            [ общие ] ; Имя хоста или адрес STUN-сервера, используемого для определения внешнего IP - адреса и порта , по которому можно получить доступ к RTP-сессии . Номер порта является необязательным . Если он опущен , будет использоваться значение по умолчанию 3478. Эта опция отключена по умолчанию . Разрешение имен  во время загрузки , и если используется DNS , разрешение имен будет происходить многократно после истечения TTL . ; ; например stundaddr = mystun.server.com:3478 ; stunaddr = stun.l.google.com:19302 rtpstart = 10000 rtpend = 60000

            Настройка VoIP-телефона

            Загрузите и установите программный телефонный клиент (например, Linphone ) для тестирования как деловых, так и пользовательских звонков.
            Настройка учетной записи
              Выберите добавочный номер для регистрации в качестве SIP-пользователя (добавочные номера 1001–1005).Откройте настройки.В разделе «Учетные записи SIP» нажмите «Добавить учетную запись»Введите следующие данные:
                SIP-адрес: например, sip:1001@{asterisk-sip-server-dns}Адрес SIP-сервера: например, sip:{asterisk-sip-server-dns};transport=tlsТранспорт: TLSОтключить ICEВключить AVPFОтключите функцию «Публиковать информацию о присутствии»Подтвердите и сохраните учетную запись.Введите пароль, когда появится соответствующий запрос (например, {sip-ua-password})После подключения вернитесь в «Настройки» и выберите вкладку «Аудио». Включите все аудиокодеки.На вкладке «Звонки и чат»:
                  Выберите «Шифрование»Выберите «SRTP-SDES»Включите параметр «Шифрование обязательно»Подтвердите настройки

                  Итоговый контрольный список

                    Тщательно проверьте все конфигурационные файлы на правильность номеров, паролей и доменных имен.Убедитесь, что ваш брандмауэр разрешает порты SIP (5061/TLS) и RTP (10000-20000).Более подробную информацию о настройке SIP-пароля см. в документации по WhatsApp Cloud API .

                    Поиск неисправностей

                    Не удается зарегистрировать SIP UA
                    Убедитесь, что SIP-URL указан правильно и домен указывает на сервер Asterisk. Выполните команду `host {domain-name}`, чтобы проверить, что IP-адрес указывает на сервер Asterisk.
                    Отсутствие подтверждения (ACK) от Meta ИЛИ прерывание звука в Business примерно через 30 секунд ИЛИ Meta возвращает ответ 404 на BYE
                    При инициированном пользователем вызове Meta отправляет SIP INVITE вашему SIP-серверу, который затем отвечает кодом 200 OK . Meta подтверждает ваш 200 OK кодом ACK , но вы его никогда не получаете. Поэтому ваш SIP-сервер продолжает повторно отправлять 200 OK , и в конечном итоге диалог SIP завершается из-за истечения времени ожидания ACK (обычно 32 секунды).
                    Наиболее вероятная причина этой проблемы — некорректные Record-Route в вашем 200 OK на Meta. 200 OK не должен изменять Record-Route , включенные в исходный INVITE . Ваш SIP-сервер может добавлять новые Record-Route , но не может изменять те, которые присутствуют в нашем INVITE.
                    Решение этой проблемы заключается в изменении параметра rewrite_contact=yes на rewrite_contact=no в конфигурации конечной точки WhatsApp в файле pjsip.conf. После этого убедитесь, что ваш ответ 200 OK заголовки в списке последних двух :
                    Эту проблему сложно обнаружить или диагностировать. Даже при наличии этой ошибки соединение устанавливается, и медиапоток передается с обеих сторон, но примерно через 32 секунды ваш SIP-сервер завершает вызов, и он не передается клиенту WhatsApp, потому что ваш запрос BYE содержит некорректные Route . Поэтому пользователь WA перестает слышать деловой звук примерно через 32 секунды.
                    Record - Route : < sip : wa.meta.vc ; transport = tls ; lr > Record - Route : < sip : onevc-sip-proxy.fbinfra.net : 8191 ; transport = tls ; lr >

                    FreeSWITCH с использованием SIP

                    Обзор

                    В этом руководстве объясняется, как настроить API бизнес-звонков WhatsApp с использованием SIP-сигнализации и FreeSWITCH коммуникационной платформы с открытым исходным кодом. Вы узнаете, как настроить сервер FreeSWITCH, подключить SIP-телефоны и обрабатывать как инициированные пользователем, так и инициированные компанией звонки WhatsApp.
                    Звонки, инициированные пользователем
                      Пользователь WhatsApp набирает номер компании.Звонок принимается системой FreeSWITCH и направляется через IVR, которая предлагает пользователю ввести добавочный номер оператора, зарегистрированный на том же сервере FreeSWITCH.После ввода добавочного номера звонок соединяется с указанным абонентом.
                      Звонки, инициированные бизнесом
                        Бизнес-агент или пользователь регистрируется в FreeSWITCH, используя учетные данные SIP ( подробности см. в разделе «Настройка VoIP-телефона Корпоративный пользователь набирает добавочный номер b2c-sip (бизнес-потребитель), который управляется системой интерактивного голосового ответа (IVR). Затем IVR запрашивает номер WhatsApp для звонка.После ввода номера звонок соединяется с пользователем WhatsApp по протоколу SIP.
                        На участке WA — FreeSWITCH для обмена ключами шифрования мультимедиа используется SDES, а в качестве аудиокодека — Opus. На участке FreeSWITCH — SIP UA для обмена ключами шифрования мультимедиа используется SDES, а в качестве аудиокодеков — Opus или G.711

                        Предварительные требования

                          Развертывание FreeSWITCH: FreeSWITCH развернут (например, на экземпляре публичного облака)Операционная система: любая ОС, совместимая с FreeSWITCH. Например, CentOS 9Домен: Сервер FreeSWITCH доступен через общедоступный домен с действительным сертификатомWhatsApp Business API: Зарегистрирован бизнес-номер телефона WhatsApp, и включена функция звонков .Поддержка SIP: SIP включен на бизнес-номере WhatsApp.
                            Примечание: FreeSWITCH настроен на прослушивание порта 5081 для протокола TLSSDES: Функция SDES включена для бизнес-номера WhatsApp.

                            Сборка и установка FreeSWITCH

                            Данное руководство было протестировано с использованием FreeSWITCH версии 1.10.12. FreeSWITCH использует Sofia (библиотеку пользовательских агентов SIP с открытым исходным кодом). Для данного руководства использовалась Sofia версии 1.13.17
                            Конфигурация FreeSWITCH
                            Эти конфигурационные файлы находятся в каталоге /usr/share/freeswitch/etc/freeswitch
                            wa-biz-api-dialplan.xml
                            Разместите план набора номера в файле /usr/share/freeswitch/etc/freeswitch/dialplan/default/wa-biz-api-dialplan.xml
                             name = "c2b_calls_sip_ivr" >  поле = "${sip_from_host}" выражение = "^wa.meta.vc$" >   application = "check_acl" data = "${network_addr} whatsapp_allow normal_clearing" />  application = "set" data = "rtp_secure_media=true" />  application = "answer" />   application = "playback" data = "silence_stream://1000" />  application = "play_and_get_digits" data = "2 5 3 7000 # $${base_dir}/sounds/incoming_welcome.wav $${base_dir}/sounds/incoming_invalid.wav extension \d+" />  application = "set" data = "ringback=%(2000, 4000, 440.0, 480.0)" />  application = "export" data = "nolocal:absolute_codec_string=PCMA,PCMU,OPUS@48000h@20i" />  application = "bridge" data = "user/${extension}" />  application = "hangup" />  name = "b2c_calls_ivr" >  поле = "номер_пункта назначения" выражение = "^b2c-sip$" >  application = "set" data = "rtp_secure_media=true" />  application = "answer" />  application = "playback" data = "silence_stream://1000" />  application = "set" data = "caller_id_check=${caller_id_number}" />  application = "play_and_get_digits" data = "2 12 3 20000 # $${base_dir}/sounds/outgoing_welcome.wav $${base_dir}/sounds/outgoing_invalid.wav whatsapp_number \d+" />  application = "log" data = "INFO [whatsapp_number] is ${whatsapp_number}" />  application = "set" data = "ringback=%(2000, 4000, 440.0, 480.0)" />  application = "export" data = "nolocal:absolute_codec_string=OPUS@48000h@20i,OPUS@8000h@20i" />  application = "bridge" data = "sofia/gateway/whatsapp/+${whatsapp_number}" />  application = "hangup" />
                            Аудиофайлы следует размещать в папке /usr/share/freeswitch/sounds (не входит в комплект)
                              incoming_welcome.wavIncoming_invalid.wavoutgoing_welcome.wavoutgoing_invalid.wav
                              whatsapp.xml
                              Этот файл настраивает шлюз WhatsApp. Скопируйте его в /usr/share/freeswitch/etc/freeswitch/sip_profiles/external/whatsapp.xml
                                имя = "whatsapp" >  name = "username" value = "{phone-number}" />  name = "password" value = "{meta-sip-password}" />  name = "register" value = "false" />  name = "realm" value = "wa.meta.vc" />  name = "from-user" value = "{phone-number}" />  name = "from-domain" value = "{domain-name}" />
                              Замените следующие заполнители фактическими значениями
                                {номер телефона}: Рабочий номер телефона WhatsApp{meta-sip-password}: SIP-пароль, выданный Meta. Для получения более подробной информации о настройке SIP-пароля см. документацию по WhatsApp Cloud API .{domain-name}: DNS-имя вашего SIP-сервера FreeSWITCH
                                acl.conf.xml
                                Откройте файл /usr/share/freeswitch/etc/freeswitch/autoload_configs/acl.conf.xml
                                Добавьте следующий список в элемент network-lists.
                                  name = "whatsapp_allow" default = "deny" >  type = "allow" cidr = "31.13.24.0/21" />  type = "allow" cidr = "31.13.64.0/18" />  type = "allow" cidr = "45.64.40.0/22" />  type = "allow" cidr = "57.141.0.0/21" />  type = "allow" cidr = "57.141.8.0/22" />  type = "allow" cidr = "57.141.12.0/23" />  type = "allow" cidr = "57.144.0.0/14" />  type = "allow" cidr = "66.220.144.0/20" />  type = "allow" cidr = "69.63.176.0/20" />  type = "allow" cidr = "69.171.224.0/19" />  type = "allow" cidr = "74.119.76.0/22" />  type = "allow" cidr = "102.132.96.0/20" />  type = "allow" cidr = "103.4.96.0/22" />  type = "allow" cidr = "129.134.0.0/16" />  type = "allow" cidr = "147.75.208.0/20" />  type = "allow" cidr = "157.240.0.0/16" />  type = "allow" cidr = "163.70.128.0/17" />  type = "allow" cidr = "163.77.128.0/17" />  type = "allow" cidr = "173.252.64.0/18" />  type = "allow" cidr = "179.60.192.0/22" />  type = "allow" cidr = "185.60.216.0/22" />  type = "allow" cidr = "185.89.216.0/22" />  type = "allow" cidr = "204.15.20.0/22" />
                                vars.xml
                                Измените файл /usr/share/freeswitch/etc/freeswitch/vars.xml
                                Добавьте строку < X - PRE - PROCESS cmd = "set" data = "rtp_secure_media=mandatory" /> под Замените < X - PRE - PROCESS cmd = "set" data = "default_password=1234" /> на ( замените { sip_ua_password } на ваш пароль ) < X - PRE - PROCESS cmd = "set" data = "default_password={sip-ua-password}" /> Замените < X - PRE - PROCESS cmd = "set" data = "domain=$${local_ip_v4}" /> на ( замените { domain - name } на DNS вашего  FreeSWITCH ) < X - PRE - PROCESS cmd = "set" data = "domain={domain-name}"/> Замените stun-set" data="external_sip_ip=stun:stun.freeswitch.org"/> (замените {external-ip} на ваш публичный IP-адрес FreeSWITCH) set" data="external_sip_ip={external-ip}"/> Заменять stun-set" data="external_rtp_ip=stun:stun.freeswitch.org"/> (замените {external-ip} на ваш публичный IP-адрес FreeSWITCH) stun-set" data="external_rtp_ip={external-ip}"/>
                                внутренний.xml
                                Измените файл /usr/share/freeswitch/etc/freeswitch/sip_profiles/internal.xml. Найдите:
                                 name = "sip-trace" value = "no" />
                                Замените это на
                                 name = "sip-trace" value = "yes" />
                                файл /usr/share/freeswitch/etc/freeswitch/sip_profiles/external.xml
                                Замените < param name = "sip-trace" value = "no" /> на < param name = "sip-trace" value = "yes" /> Замените < param name = "tls" value = "$${external_ssl_enable}" /> на < param name = "tls" value = "true" /> Замените param name="tls-cert-dir" value=""/>--> с < param name = "tls-cert-dir" value = "/usr/share/freeswitch/etc/freeswitch/certs" />
                                Убедитесь, что сертификаты размещены в папке /usr/share/freeswitch/etc/freeswitch/certs

                                Итоговый контрольный список

                                  Тщательно проверьте все конфигурационные файлы на правильность номеров, паролей и доменных имен.Убедитесь, что ваш брандмауэр разрешает порты SIP (5081/TLS) и RTP (10000-20000).Более подробную информацию о настройке SIP-пароля см. в документации по WhatsApp Cloud API .

                                  Поиск неисправностей

                                  Не удается зарегистрировать SIP UA
                                  Убедитесь, что SIP-URL указан правильно и домен указывает на сервер FreeSWITCH. Выполните команду `host {domain-name}`, чтобы проверить, что IP-адрес указывает на сервер FreeSWITCH.
                                  Отслеживание SIP-сообщений
                                  Запустите CLI (/usr/share/freeswitch/bin/fs_cli), чтобы просмотреть SIP-сообщения

                                  FreeSWITCH использует Graph API с Janus

                                  Обзор

                                  В этом руководстве объясняется, как настроить WhatsApp Business Calling API, используя сигнализацию WhatsApp Cloud API с FreeSWITCH открытым фреймворком для связи — и Janus универсальным WebRTC-сервером. Вы узнаете, как настроить сервер FreeSWITCH, подключить SIP-телефоны и обрабатывать как входящие, так и исходящие звонки WhatsApp.
                                  Архитектурная схема, демонстрирующая интеграцию FreeSWITCH с Janus
                                  Звонки, инициированные пользователем
                                    Пользователь WhatsApp набирает номер компании.Вызов принимается сервером Webhook, который перенаправляет его на сервер FreeSWITCH через плагин Janus SIP.Звонок принимается системой FreeSWITCH и перенаправляется через IVR, предлагая пользователю ввести добавочный номер, зарегистрированный на том же сервере FreeSWITCH.Затем вызов соединяется с указанным добавочным номером.
                                    Звонки, инициированные бизнесом
                                      Бизнес-агент/пользователь регистрируется в FreeSWITCH, используя учетные данные SIP (см. раздел « Настройка VoIP-телефона »).Корпоративный пользователь набирает добавочный номер b2c-sip (бизнес для потребителя), который обрабатывается системой интерактивного голосового ответа (IVR). IVR запрашивает номер WhatsApp для звонка.FreeSWITCH перенаправляет вызов на добавочный номер, зарегистрированный в плагине Janus SIP, который затем преобразуется в API-запрос к MetaЗатем звонок соединяется с пользователем WhatsApp.
                                      Сервер Janus находится между WA и FreeSWITCH и преобразует медиафайлы из WA (совместимые с WebRTC и использующие обмен ключами DTLS) в медиафайлы, согласованные с FreeSWITCH (использующие обмен ключами SDES).
                                      FreeSWITCH - Sip UA будет использовать SDES для обмена ключами шифрования мультимедиа и Opus или G711 для аудиокодеков

                                      Предварительные требования

                                        Развертывание FreeSWITCH: FreeSWITCH развернут (например, на экземпляре публичного облака)Janus Deployment: Может быть развернут на той же машине, что и FreeSWITCHОперационная система: любая ОС, совместимая с FreeSWITCH. Например, CentOS 9Домен: Сервер FreeSWITCH и сервер Webhook доступны через общедоступный домен с действительным сертификатомWhatsApp Business API: Зарегистрирован бизнес-номер телефона WhatsApp, и включена функция звонков .Веб-хуки: Настройте URL-адрес обратного вызова веб-хука, указывающий на доменное имя сервера веб-хуков

                                        Интеграция с сигнализацией Cloud API

                                        Вам потребуется реализовать интеграционный модуль, который будет выступать посредником между WA и Janus и преобразовывать сообщения Cloud API Signalling в сообщения плагина Janus SIP и наоборот.
                                        Вам понадобится
                                          Веб-сервер для приема событий веб-перехвата вызовов от MetaМодуль Graph API для отправки сообщений о вызовах в MetaРеализация SIP-плагина Janus для подключения к Janus. Реализация плагина Janus будет подключаться к FreeSWITCH, используя добавочный номер 1000, зарезервированный для мостового соединения.
                                          Звонки, инициированные бизнесом
                                            Модуль получит SIP INVITE через плагин Janus SIP на добавочном номере 1000. SIP INVITE преобразуется в запрос Graph API . Полученный в SIP INVITE SDP отправляется в неизменном виде в качестве предложения SDP в WA через вызов Graph API.Когда звонок принимается пользователем WA, поступает подтверждение через веб-перехватчик. После получения веб-перехватчика плагин Janus SIP принимает SIP INVITE, передавая ответный SDP в веб-перехватчике подключения.
                                            Звонки, инициированные пользователем
                                              Веб-хук-сервер получает входящий вызов через веб-хук-сообщение, содержащее SDP-предложение. После получения приглашения на вызов плагин Janus SIP отправляет приглашение в FreeSWITCH через добавочный номер 1000. Добавочный номер получателя — c2b-sip.Когда плагин Janus SIP получает SIP-код 200 OK, в Meta отправляется запрос на принятие вызова через Graph API, который принимает входящий вызов, передавая полученный SDP-код в составе SIP-ответа

                                              Сборка и установка системы Janus

                                              См. https://github.com/meetecho/janus-gateway . Данное руководство было протестировано с использованием версии 1.2.3.

                                              Конфигурация Януса

                                              janus.jcfg
                                              Измените файл janus.jcfg, который находится по адресу /usr/share/janus/etc/janus/janus.jcfg. Установите параметр nat_1_1_mapping на публичный IP-адрес сервера Janus
                                              Чтобы начать работу с Янусом
                                              / usr / share / janus / bin / janus --debug - level = 6 --libnice - debug = on - S stun.l.google.com:19302 --log - file = / var / log / janus.log --config = / usr / share / janus / etc / janus / janus.jcfg

                                              Сборка и установка FreeSWITCH

                                              Данное руководство было протестировано с использованием FreeSWITCH версии 1.10.12. FreeSWITCH использует Sofia (библиотеку пользовательских агентов SIP с открытым исходным кодом). Для данного руководства использовалась Sofia версии 1.13.17
                                              Конфигурация FreeSWITCH. Эти конфигурационные файлы находятся в каталоге /usr/share/freeswitch/etc/freeswitch.
                                              wa-biz-api-dialplan.xml
                                              Разместите план набора номера в файле /usr/share/freeswitch/etc/freeswitch/dialplan/default/wa-biz-api-dialplan.xml
                                               name = "c2b_calls_ivr" >  поле = "номер_пункта назначения" выражение = "^c2b-sip$" >  application = "set" data = "rtp_secure_media=true" />  application = "answer" />   application = "playback" data = "silence_stream://1000" />  application = "play_and_get_digits" data = "2 5 3 7000 # $${base_dir}/sounds/incoming_welcome.wav $${base_dir}/sounds/incoming_invalid.wav extension \d+" />  application = "set" data = "ringback=%(2000, 4000, 440.0, 480.0)" />    application = "export" data = "nolocal:absolute_codec_string=PCMA,PCMU,OPUS@48000h@20i,G722" />  application = "bridge" data = "user/${extension}" />  application = "hangup" />  name = "b2c_calls_ivr" >  поле = "номер_пункта назначения" выражение = "^b2c-sip$" >  application = "set" data = "rtp_secure_media=true" />  application = "answer" />  application = "playback" data = "silence_stream://1000" />  application = "set" data = "caller_id_check=${caller_id_number}" />  application = "log" data = "INFO [caller id ] is ${caller_id_check}" />  application = "play_and_get_digits" data = "2 12 3 20000 # $${base_dir}/sounds/outgoing_welcome.wav $${base_dir}/sounds/outgoing_invalid.wav whatsapp_number \d+" />  application = "log" data = "INFO [whatsapp_number] is ${whatsapp_number}" />   application = "export" data = "sip_h_X-WhatsApp-Number=${whatsapp_number" />  application = "set" data = "ringback=%(2000, 4000, 440.0, 480.0)" />    application = "export" data = "nolocal:absolute_codec_string=OPUS@48000h@20i,PCMU,PCMA" />   application = "bridge" data = "user/1000" />  application = "hangup" />
                                              Аудиофайлы следует размещать в папке /usr/share/freeswitch/sounds (не входит в комплект)
                                                incoming_welcome.wavIncoming_invalid.wavoutgoing_welcome.wavoutgoing_invalid.wav
                                                внутренний.xml
                                                Измените файл /usr/share/freeswitch/etc/freeswitch/sip_profiles/internal.xml. Найдите:
                                                 name = "sip-trace" value = "no" />
                                                Замените это на
                                                 name = "sip-trace" value = "yes" />

                                                Настройка VoIP-телефона

                                                Итоговый контрольный список

                                                  Тщательно проверьте все конфигурационные файлы на правильность номеров, паролей и доменных имен.Убедитесь, что ваш брандмауэр разрешает порты SIP (5061/TLS) и RTP (10000-20000).Более подробную информацию о настройке SIP-пароля см. в документации по WhatsApp Cloud API .

                                                  Поиск неисправностей

                                                  Не удается зарегистрировать SIP UA
                                                  Убедитесь, что SIP-URL указан правильно и домен указывает на сервер FreeSWITCH. Выполните команду `host {domain-name}`, чтобы проверить, что IP-адрес указывает на сервер FreeSWITCH.
                                                  Отслеживание SIP-сообщений
                                                  Запустите CLI (/usr/share/freeswitch/bin/fs_cli), чтобы просмотреть SIP-сообщения

                                                  Asterisk с использованием Graph API и RtpEngine

                                                  Обзор

                                                  В этом руководстве объясняется, как настроить WhatsApp Business Calling API с использованием сигнализации WhatsApp Cloud API в сочетании с Asterisk открытой АТС (PBX) — и RtpEngine открытым прокси-сервером, используемым для ретрансляции, обработки и управления потоками RTP. Вы узнаете, как настроить сервер Asterisk, подключить SIP-телефоны и обрабатывать как входящие, так и исходящие звонки WhatsApp.
                                                  Звонки, инициированные пользователем
                                                    Пользователь WhatsApp набирает номер компании.Вызов принимается сервером Webhook, который после передачи медиаданных с помощью RtpEngine перенаправляет его в Asterisk по протоколу SIP.Вызов принимается системой Asterisk и направляется через IVR, предлагая пользователю ввести добавочный номер, зарегистрированный на том же сервере Asterisk.Затем вызов соединяется с указанным добавочным номером.
                                                    Звонки, инициированные бизнесом
                                                      Бизнес-агент/пользователь регистрируется в Asterisk, используя учетные данные SIP (см. раздел « Настройка VoIP-телефона »).Корпоративный пользователь набирает добавочный номер b2c-sip (бизнес для потребителя), который обрабатывается системой интерактивного голосового ответа (IVR). IVR запрашивает номер WhatsApp для звонка.Asterisk обеспечивает связь вызова с внутренним номером, зарегистрированным модулем интеграции (см. «Интеграция с сигнализацией Cloud API»)После получения вызова модуль интеграции устанавливает медиасоединение с помощью RtpEngine, а затем преобразует его в API-запрос к MetaЗатем звонок соединяется с пользователем WhatsApp.
                                                      RtpEngine выступает в роли медиапрокси и находится между потоком данных от WA (совместимого с WebRTC протокола с обменом ключами DTLS) и Asterisk (обмен ключами SDES)

                                                      Предварительные требования

                                                        Развертывание Asterisk: Asterisk развертывается (например, на экземпляре публичного облака)Развертывание RTPEngine: может быть развернуто на той же машине, что и AsteriskОперационная система: любая ОС, совместимая с Asterisk и RTPEngine. Например, CentOS 9Домен: Сервер Asterisk и сервер Webhook доступны через общедоступный домен с действительным сертификатомWhatsApp Business API: Зарегистрирован бизнес-номер телефона WhatsApp, и включена функция звонков .Веб-хуки: Настройте URL-адрес обратного вызова веб-хука, указывающий на доменное имя сервера веб-хуков

                                                        Интеграция с сигнализацией Cloud API

                                                        Вам потребуется реализовать интеграционный модуль, который будет выступать в качестве моста между WhatsApp и Asterisk. Этот модуль будет:
                                                          Преобразование сигнальных сообщений Cloud API из WhatsApp в SIP для Asterisk и наоборотИспользуйте SIP-сигнализацию для связи между SIP-пользователем внутри модуля и AsteriskОбеспечьте связь между WhatsApp и Asterisk через RTPEngine
                                                          Для данной настройки вам потребуются следующие компоненты, входящие в состав модуля интеграции
                                                            Сервер веб-перехватчиков: принимает события веб-перехватчика вызовов от Meta (API облачной платформы WhatsApp)Клиент Graph API: отправляет запросы, связанные с вызовами, в Meta с помощью Graph APIПользовательский агент SIP (UA), например PJSIP: подключается к Asterisk, используя добавочный номер 1000, который зарезервирован для организации звонков между WhatsApp и Asterisk.RtpEngineClient: Для управления RtpEngine через протокол управления ng для создания мостовых медиаканалов
                                                            Архитектурная схема, демонстрирующая интеграцию Asterisk с RTPEngine для бизнес-звонков WhatsApp
                                                            Звонки, инициированные бизнесом
                                                              Агент, зарегистрированный на том же сервере Asterisk, набирает добавочный номер b2c-sip, чтобы инициировать звонок пользователю WhatsAppРасширение запрашивает у бизнес-агента ввод номера телефона пользователя из штата ВашингтонAsterisk отправляет SIP INVITE-запрос на добавочный номер 1000 с пользовательским заголовком, содержащим номер телефона набранного пользователя WASIP-агент внутри модуля зарегистрировался бы на добавочном номере 1000 и, следовательно, получил бы SIP-приглашение от AsteriskSDP, включенный в SIP INVITE, отправляется в RtpEngine, который возвращает новый SDPНовый SDP включается в запрос Graph API для инициирования нового вызова.Когда пользователь WhatsApp принимает звонок, он получает веб-хук с сообщением «принято»После получения этого веб-хука ответ, полученный в веб-хуке, отправляется в RtpEngine, который возвращает новый SDPАутентификатор SIP принимает исходный SIP INVITE (шаг 3), передавая новый SDP, полученный от RtpEngineТеперь соединение установлено между пользователем WA, RtpEngine и Asterisk
                                                              Звонки, инициированные пользователем
                                                                Веб-хук-сервер внутри модуля получает входящий веб-хук вызова от Meta, который включает в себя предложение SDP.После получения приглашения к звонку, SDP, включенный в предложение, отправляется в RtpEngine, который возвращает новый SDPSIP-агент, находящийся внутри модуля, отправляет SIP INVITE в Asterisk, используя добавочный номер 1000, передавая в SIP INVITE новый SDP от RtpEngine. Добавочный номер получателя — c2b-sip.Расширение предлагает пользователю WA набрать добавочный номер бизнес-агента для соединенияAsterisk набирает указанный добавочный номер и ожидает ответаПосле того, как оператор ответит на звонок, Asterisk отправляет SIP 200 OK на SIP-интерфейс UA 1000 внутри модуля. SDP в SIP 200 OK отправляется в RtpEngine, который возвращает новый SDPЗапрос к Graph API отправляется в Meta для принятия входящего вызова , при этом новый SDP получен от RtpEngine.

                                                                Сборка и установка Asterisk

                                                                См. https://docs.asterisk.org/Getting-Started/Installing-Asterisk/Installing-Asterisk-From-Source/Building-and-Installing-Asterisk/
                                                                Данное руководство было протестировано с использованием Asterisk версии 22.5.2

                                                                Сборка и установка RtpEngine

                                                                обратитесь к https://github.com/sipwise/rtpengine . Данное руководство было протестировано с использованием версии RtpEngine 13.3.1.4.
                                                                Подробную информацию о протоколе управления ng можно найти по ссылке https://rtpengine.readthedocs.io/en/latest/ng_control_protocol.html
                                                                Для запуска RTPEngine выполните команду
                                                                /usr/ bin / rtpengine --listen - ng = { local - ip } : 22222 --interface ={ local - ip } \ ! { public - ip } -f - E
                                                                Заменять
                                                                  {local-ip} с локальным IP-адресом сервера RtpEngine{public-ip} с публичным IP-адресом сервера RtpEngine
                                                                  Конфигурация Asterisk. Эти конфигурационные файлы находятся в каталоге /etc/asterisk/
                                                                  extensions.conf
                                                                  Замените следующие заполнители фактическими значениями
                                                                    incoming_welcome: incoming_welcome.wav (не предоставлен) поместите этот файл в /var/lib/asterisk/soundsoutgoing_welcome: outgoing_welcome.wav (не предоставлен) поместите этот файл в /var/lib/asterisk/sounds
                                                                    [ handler ] ; Установить заголовки для канала вызываемого абонента exten => addheader , 1 , Set ( PJSIP_HEADER ( add , X - WhatsApp - Number )= $ { DIGITS }) same => n , Return () [ default ] exten => _10XX , 1 , NoOp () same => n , Dial ( PJSIP / $ { EXTEN }) same => n , Hangup () exten => b2c - sip , 1 , NoOp () same => n , Read ( Digits , outgoing_welcome , 0 , 5 , 500 ) same => n , Set ( GLOBAL ( DIGITS )= $ { Digits }) ; Перед  - звонка добавьте заголовок WA клиента для хранения номера пользователя WA, полученного из цифр, введенных агентом ( DTMF ): same => n , Dial ( PJSIP / 1000 , b ( handler ^ addheader ^ 1 )) same => n , Hangup () exten => c2b - sip , 1 , NoOp () same => n , Read ( Digits , incoming_welcome , 0 , 5 , 500 ) same => n , Dial ( PJSIP / $ { Digits }) same => n , Hangup ()
                                                                    pjsip.conf
                                                                    Замените следующие заполнители фактическими значениями
                                                                      {external-media-address}: Публичный IP-адрес сервера Asterisk для медиафайлов{external-signaling-address}: Публичный IP-адрес сервера Asterisk для сигнализации{local-net}: локальная сеть сервера Asterisk{sip-ua-password}: Выбранный пароль SIP User Agent
                                                                      Примечание:
                                                                      Добавочный номер 1000 используется для соединения вызовов WA с Asterisk (см. раздел « Интеграция с сигнализацией Cloud API»).
                                                                      [ global ] type = global debug = yes ; Включить / отключить отладку SIP . Допустимые параметры: yes | no [transport-tcp] type = transport protocol = tcp bind = 0.0.0.0; Внешний IP - адрес для обработки RTP external_media_address = { external - media - address } ; Внешний адрес для сигнализации SIP external_signaling_address = { external - signaling - address } ; Сеть , которую следует считать локальной для целей NAT local_net = { local - net } [ endpointtemplate ] ( ! ) type = endpoint context = default disallow = all allow = OPUS , g722 , g729 , ulaw ; Нет звука , если direct_media установлено на yes direct_media = no rtp_symmetric = yes use_avpf = yes media_encryption = sdes media_use_received_transport = yes rtcp_mux = yes [ authtemplate ](!) type = auth auth_type = userpass password ={ sip - ua - password } [ aortemplate ](!) type = aor max_contacts = 1 remove_existing = yes [ 1000 ]( endpointtemplate ) disallow = all ; расширение 1000 используется RtpEngine для организации звонков WhatsApp ; WhatsApp поддерживает только OPUS. allow = OPUS auth = 1000 _auth aors = 1000 [ 1000 _auth ]( authtemplate ) username = 1000 [ 1000 ]( aortemplate ) [ 1001 ]( endpointtemplate ) auth = 1001 _auth aors = 1001 [ 1001 _auth ]( authtemplate ) username = 1001 [ 1001 ]( aortemplate ) [ 1002 ]( endpointtemplate ) auth = 1002 _auth aors = 1002 [ 1002 _auth ]( authtemplate ) username = 1002 [ 1002 ]( aortemplate ) [ 1003 ]( endpointtemplate  ) auth = 1003 _auth aors = 1003 [ 1003 _auth ]( authtemplate ) username = 1003 [ 1003 ]( aortemplate ) [ 1004 ]( endpointtemplate ) auth = 1004 _auth aors = 1004 [ 1004 _auth ]( authtemplate ) username = 1004 [ 1004 ]( aortemplate ) [ 1005 ]( endpointtemplate ) auth = 1005 _auth aors = 1005 [ 1005 _auth ]( authtemplate ) username = 1005 [ 1005 ]( aortemplate )

                                                                      Настройка VoIP-телефона

                                                                      Итоговый контрольный список

                                                                        Тщательно проверьте все конфигурационные файлы на правильность номеров, паролей и доменных имен.Убедитесь, что ваш брандмауэр разрешает порты SIP (5060/TCP) и RTP (10000-20000).Более подробную информацию о настройке SIP-пароля см. в документации по WhatsApp Cloud API .

                                                                        Поиск неисправностей

                                                                        Не удается зарегистрировать SIP UA
                                                                        Убедитесь, что SIP-URL указан правильно и домен указывает на сервер Asterisk. Выполните команду `host {domain-name}`, чтобы проверить, что IP-адрес указывает на сервер Asterisk.

                                                                        Asterisk со встроенным WebRTC, использующий Graph API

                                                                        Этот подход аналогичен использованию Asterisk Graph API с RtpEngine, за исключением того, что он использует встроенную поддержку WebRTC в Asterisk и, следовательно, не требует RtpEngine.
                                                                        Таким образом, компонент RtpEngineClient в этом подходе не требуется
                                                                        В плане конфигурации и настройки единственное отличие заключается в конфигурации расширения 1000, которая приведена ниже
                                                                        ... ; Остальное содержимое опущено для краткости [ 1000 ]( endpointtemplate ) disallow = all ; расширение 1000 используется SIP  модуля интеграции для организации звонков WhatsApp ; WhatsApp поддерживает только OPUS allow = OPUS auth = 1000 _auth aors = 1000 dtls_auto_generate_cert = yes webrtc = yes ; Установка webrtc = yes — это сокращение для установки следующих параметров : ; use_avpf = yes ; media_encryption = dtls ; dtls_verify = fingerprint ; dtls_setup = actpass ; ice_support = yes ; media_use_received_transport = yes ; rtcp_mux = yes