Forstå FreePBX og integrere det med Bitrix24 og mere

Bitrix24 er en kæmpe mejetærsker, der kombinerer CRM, arbejdsgang, regnskab og mange andre ting, som ledere virkelig kan lide, og som it-personale ikke rigtig kan lide. Portalen bruges af en masse små og mellemstore virksomheder, herunder små klinikker, producenter og endda skønhedssaloner. Hovedfunktionen som ledere "elsker" er integrationen af ​​telefoni og CRM, når et opkald straks optages i CRM, oprettes klientkort, ved indkommende vises information om klienten, og du kan straks se, hvem han er, hvad han er. kan sælge og hvor meget han skylder. Men telefoni fra Bitrix24 og dets integration med CRM koster penge, nogle gange meget. I artiklen vil jeg fortælle dig oplevelsen af ​​at integrere med åbne værktøjer og den populære IP PBX FreePBX, og overveje også logikken i arbejdet i forskellige dele

Jeg arbejder som outsourcer i en virksomhed, der sælger og konfigurerer, integrerer IP-telefoni. Da jeg blev spurgt, om vi kunne tilbyde noget til dette og dette firma for at integrere Bitrix24 med PBX'er, som kunderne har, samt med virtuelle PBX'er på forskellige VDS-selskaber, gik jeg til Google. Og selvfølgelig gav han mig et link til artikel i habr, hvor der er en beskrivelse, og github, og alt ser ud til at virke. Men da man forsøgte at bruge denne løsning, viste det sig, at Bitrix24 ikke længere er det samme som før, og meget skal laves om. Derudover er FreePBX ikke en bare stjerne for dig, her skal du tænke over, hvordan du kombinerer brugervenlighed og en hardcore opkaldsplan i konfigurationsfiler.

Vi studerer arbejdets logik

Så for det første, hvordan det hele skal fungere. Når et opkald modtages udefra på PBX'en (SIP INVITE hændelse fra udbyderen), begynder behandlingen af ​​opkaldsplanen (opkaldsplan, opkaldsplan) - reglerne for hvad og i hvilken rækkefølge man skal gøre med opkaldet. Fra den første pakke kan du få en masse information, som så kan bruges i reglerne. Et glimrende værktøj til at studere det indre af SIP er analysatoren sngrep (link) som blot installeres i populære distributioner via apt install/yum install og lignende, men det kan også bygges fra kilde. Lad os se på opkaldsloggen i sngrep

Forstå FreePBX og integrere det med Bitrix24 og mere

I en forenklet form omhandler opkaldsplanen kun den første pakke, nogle gange også under samtalen, opkald overføres, knaptryk (DTMF), forskellige interessante ting som FollowMe, RingGroup, IVR og andre.

Hvad er der i invitationspakken

Forstå FreePBX og integrere det med Bitrix24 og mere

Faktisk fungerer de fleste simple opkaldsplaner med de to første felter, og hele logikken drejer sig om DID og CallerID. DID - hvor vi ringer, CallerID - hvem ringer.

Men vi har trods alt et firma og ikke én telefon - hvilket betyder, at PBX'en højst sandsynligt har opkaldsgrupper (samtidig/konsekutiv ringning af flere enheder) på bynumre (Ring Group), IVR (Hej, du ringede ... Tryk en for ...), Telefonsvarer ( Sætninger), Tidsbetingelser, Viderestilling til andre numre eller til en celle (FølgMig, Videresend). Det betyder, at det er meget svært entydigt at afgøre, hvem der rent faktisk skal modtage et opkald, og hvem der skal have en samtale med, når der kommer et opkald. Her er et eksempel på begyndelsen af ​​et typisk opkald i vores kunders PBX

Forstå FreePBX og integrere det med Bitrix24 og mere

Efter at opkaldet er kommet ind i PBX'en, kører det gennem opkaldsplanen i forskellige "sammenhænge". Konteksten set fra Asterisks synspunkt er et nummereret sæt kommandoer, som hver indeholder et filter efter det kaldte nummer (det kaldes exten, for et eksternt opkald i den indledende fase exten=DID). Kommandoerne i opkaldslinjen kan være hvad som helst - interne funktioner (f.eks. ring til en intern abonnent - Dial(), læg telefonen fra dig - Hangup()), betingede operatører (IF, ELSE, ExecIF og lignende), overgange til andre regler i denne sammenhæng (Goto, GotoIF), overgang til andre sammenhænge i form af et funktionskald (Gosub, Makro). Et særskilt direktiv include имя_контекста, som tilføjer kommandoer fra en anden kontekst til slutningen af ​​den aktuelle kontekst. Kommandoer inkluderet via include udføres altid efter kommandoer i den aktuelle kontekst.

Hele logikken i FreePBX er bygget på inklusion af forskellige kontekster i hinanden gennem inkludere og kalde via Gosub, Macro og Handler handlere. Overvej konteksten af ​​indgående FreePBX-opkald

Forstå FreePBX og integrere det med Bitrix24 og mere

Kaldet går gennem alle sammenhænge fra top til bund på skift, i hver sammenhæng kan der være opkald til andre sammenhænge som makroer (Macro), funktioner (Gosub) eller blot overgange (Goto), så det rigtige træ af det der kaldes kan kun spores i loggene.

Et typisk opsætningsdiagram for en typisk PBX er vist nedenfor. Ved opkald søges DID i indgående ruter, midlertidige forhold tjekkes for det, hvis alt er i orden, startes stemmemenuen. Fra den, ved at trykke på knap 1 eller timeout, forlad gruppen af ​​opkaldsoperatører. Efter at opkaldet er afsluttet, kaldes hangupcall-makroen, hvorefter intet kan gøres i opkaldsplanen, bortset fra specielle handlere (hangup-handler).

Forstå FreePBX og integrere det med Bitrix24 og mere

Hvor i denne opkaldsalgoritme skal vi levere information om begyndelsen af ​​opkaldet til CRM, hvor vi skal starte optagelsen, hvor vi skal afslutte optagelsen og sende det sammen med information om opkaldet til CRM?

Integration med eksterne systemer

Hvad er PBX og CRM integration? Det er indstillinger og programmer, der konverterer data og hændelser mellem disse to platforme og sender dem til hinanden. Den mest almindelige måde for uafhængige systemer at kommunikere på er gennem API'er, og den mest populære måde at få adgang til API'er er HTTP REST. Men ikke for stjerne.

Inde i stjernen er:

  • AGI - synkront kald til eksterne programmer/komponenter, bruges hovedsageligt i opkaldsplanen, der er biblioteker som f.eks. phpagi, PAGI

  • AMI - en tekst TCP-socket, der fungerer efter princippet om at abonnere på begivenheder og indtaste tekstkommandoer, ligner SMTP indefra, kan spore begivenheder og administrere opkald, der er et bibliotek PAMI - den mest populære til at skabe en forbindelse med Asterisk

Eksempel på AMI-output

Begivenhed: Ny kanal
Privilegium: ring, alle
Kanal: PJSIP/VMS_pjsip-0000078b
Kanaltilstand: 4
ChannelStateDesc: Ring
Opkalds-ID: 111222
Opkalds-ID: 111222
ConnectedLineNum:
tilsluttet linjenavn:
Sprog: en
kontokode:
Kontekst: fra-pstn
Udvidelse: s
Prioritet: 1
Uniqueid: 1599589046.5244
Linkedid: 1599589046.5244

  • ARI er en blanding af begge, alt via REST, WebSocket, i JSON-format - men med friske biblioteker og indpakninger, ikke særlig godt, umiddelbart fundet (phparia, phpari) som blev i deres udvikling for omkring 3 år siden.

Eksempel på ARI-output, når et opkald påbegyndes

{ "variable":"CallMeCallerIDName", "value":"111222", "type":"ChannelVarset", "timestamp":"2020-09-09T09:38:36.269+0000", "channel":{ "id" »:»1599644315.5334″, «navn»:»PJSIP/VMSpjsip-000007b6″, "state":"Ring", "opkalder":{ "navn":"111222", "nummer":"111222" }, "forbundet":{ "navn":"", "nummer" :"" }, "accountcode":"", "dialplan":{ "context":"fra-pstn", "exten":"s", "priority":2, "appname":"Stasis", "appdata":"hello-world" }, "creationtime":"2020-09-09T09:38:35.926+0000", "language":"da" }, "stjerneid":"48:5b:aa:aa:aa:aa", "application":"hello-world" }

Bekvemmelighed eller besvær, muligheden eller umuligheden af ​​at arbejde med en bestemt API afgøres af de opgaver, der skal løses. Opgaverne for integration med CRM er som følger:

  • Spor begyndelsen af ​​opkaldet, hvor det blev overført, træk opkalds-ID, DID, start- og sluttider, måske data fra telefonbogen (for at søge efter en forbindelse mellem telefonen og CRM-brugeren)

  • Start og afslut optagelsen af ​​opkaldet, gem det i det ønskede format, informer i slutningen af ​​optagelsen, hvor filen er placeret

  • Start et opkald på en ekstern begivenhed (fra programmet), ring til et internt nummer, et eksternt nummer og tilslut dem

  • Valgfri: Integrer med CRM, opkaldsgrupper og FollowME for automatisk omstilling af opkald i mangel af et sted (ifølge CRM)

Alle disse opgaver kan løses gennem AMI eller ARI, men ARI giver meget mindre information, der er ikke mange hændelser, mange variabler som AMI stadig har (f.eks. makrokald, indstilling af variabler inde i makroer, inklusive opkaldsoptagelse) spores ikke. Derfor, for korrekt og præcis sporing, lad os vælge AMI for nu (men ikke helt). Derudover (nå, hvor ville det være uden dette, vi er dovne mennesker) - i det originale værk (artikel i habr) brug PAMI. *Så skal du prøve at omskrive til ARI, men ikke det faktum, at det vil virke.

Genopfinde integration

For at vores FreePBX på enkle måder kan rapportere til AMI om begyndelsen af ​​opkaldet, sluttidspunkt, numre, navne på optagede filer, er det nemmest at beregne varigheden af ​​opkaldet ved hjælp af samme trick som de oprindelige forfattere - Indtast dine variabler og parse outputtet for deres tilstedeværelse. PAMI foreslår at gøre dette blot gennem en filterfunktion.

Her er et eksempel på indstilling af din egen variabel for starttidspunktet for opkaldet (s er et særligt nummer i opkaldsplanen, der udføres FØR du starter DID-søgningen)

[ext-did-custom]

exten => s,1,Set(CallStart=${STRFTIME(epoch,,%s)})

Et eksempel på AMI-hændelse for denne linje

Begivenhed: Ny kanal

Privilegium: ring, alle

Kanal: PJSIP/VMS_pjsip-0000078b

Kanaltilstand: 4

ChannelStateDesc: Ring

Opkalds-ID: 111222

Opkalds-ID: 111222

ConnectedLineNum:

tilsluttet linjenavn:

Sprog: en

kontokode:

Kontekst: fra-pstn

Udvidelse: s

Prioritet: 1

Uniqueid: 1599589046.5244

Linkedid: 1599589046.5244

Applikation: Indstil AppData:

CallStart=1599571046

Fordi FreePBX overskriver filerne extension.conf og extension_additional.conf, vil vi bruge filen forlængelse_skik.konf

Fuld kode for extension_custom.conf

[globals]	
;; Проверьте пути и права на папки - юзер asterisk должен иметь права на запись
;; Сюда будет писаться разговоры
WAV=/var/www/html/callme/records/wav 
MP3=/var/www/html/callme/records/mp3

;; По этим путям будет воспроизводится и скачиваться запись
URLRECORDS=https://www.host.ru/callmeplus/records/mp3

;; Адрес для калбека при исходящем вызове
URLPHP=https://www.host.ru/callmeplus

;; Да пишем разговоры
RECORDING=1

;; Это макрос для записи разговоров в нашу папку. 
;; Можно использовать и системную запись, но пока пусть будет эта - 
;; она работает
[recording]
exten => ~~s~~,1,Set(LOCAL(calling)=${ARG1})
exten => ~~s~~,2,Set(LOCAL(called)=${ARG2})
exten => ~~s~~,3,GotoIf($["${RECORDING}" = "1"]?4:14)
exten => ~~s~~,4,Set(fname=${UNIQUEID}-${STRFTIME(${EPOCH},,%Y-%m-%d-%H_%M)}-${calling}-${called})
exten => ~~s~~,5,Set(datedir=${STRFTIME(${EPOCH},,%Y/%m/%d)})
exten => ~~s~~,6,System(mkdir -p ${MP3}/${datedir})
exten => ~~s~~,7,System(mkdir -p ${WAV}/${datedir})
exten => ~~s~~,8,Set(monopt=nice -n 19 /usr/bin/lame -b 32  --silent "${WAV}/${datedir}/${fname}.wav"  "${MP3}/${datedir}/${fname}.mp3" && rm -f "${WAV}/${fname}.wav" && chmod o+r "${MP3}/${datedir}/${fname}.mp3")
exten => ~~s~~,9,Set(FullFname=${URLRECORDS}/${datedir}/${fname}.mp3)
exten => ~~s~~,10,Set(CDR(filename)=${fname}.mp3)
exten => ~~s~~,11,Set(CDR(recordingfile)=${fname}.wav)
exten => ~~s~~,12,Set(CDR(realdst)=${called})
exten => ~~s~~,13,MixMonitor(${WAV}/${datedir}/${fname}.wav,b,${monopt})
exten => ~~s~~,14,NoOp(Finish if_recording_1)
exten => ~~s~~,15,Return()


;; Это основной контекст для начала разговора
[ext-did-custom]

;; Это хулиганство, делать это так и здесь, но работает - добавляем к номеру '8'
exten =>  s,1,Set(CALLERID(num)=8${CALLERID(num)})

;; Тут всякие переменные для скрипта
exten =>  s,n,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
exten =>  s,n,ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp())
exten =>  s,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten =>  s,n,Set(CallMeDISPOSITION=${CDR(disposition)})

;; Самое главное! Обработчик окончания разговора. 
;; Обычные пути обработки конца через (exten=>h,1,чтототут) в FreePBX не работают - Macro(hangupcall,) все портит. 
;; Поэтому вешаем Hangup_Handler на окончание звонка
exten => s,n,Set(CHANNEL(hangup_handler_push)=sub-call-from-cid-ended,s,1(${CALLERID(num)},${EXTEN}))

;; Обработчик окончания входящего вызова
[sub-call-from-cid-ended]

;; Сообщаем о значениях при конце звонка
exten => s,1,Set(CDR_PROP(disable)=true)
exten => s,n,Set(CallStop=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)})

;; Статус вызова - Ответ, не ответ...
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})
exten => s,n,Return


;; Обработчик исходящих вызовов - все аналогичено
[outbound-allroutes-custom]

;; Запись
exten => _.,1,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
;; Переменные
exten => _.,n,Set(__CallIntNum=${CALLERID(num)})
exten => _.,n,Set(CallExtNum=${EXTEN})
exten => _.,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten => _.,n,Set(CallmeCALLID=${SIPCALLID})

;; Вешаем Hangup_Handler на окончание звонка
exten => _.,n,Set(CHANNEL(hangup_handler_push)=sub-call-internal-ended,s,1(${CALLERID(num)},${EXTEN}))

;; Обработчик окончания исходящего вызова
[sub-call-internal-ended]

;; переменные
exten => s,1,Set(CDR_PROP(disable)=true)
exten => s,n,Set(CallStop=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)})
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})

;; Вызов скрипта, который сообщит о звонке в CRM - это исходящий, 
;; так что по факту окончания
exten => s,n,System(curl -s ${URLPHP}/CallMeOut.php --data action=sendcall2b24 --data ExtNum=${CallExtNum} --data call_id=${SIPCALLID} --data-urlencode FullFname='${FullFname}' --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition='${CallMeDISPOSITION}')
exten => s,n,Return

Funktion og forskel fra den originale telefonplan for forfatterne til den originale artikel -

  • Dialplan i .conf-format, som FreePBX ønsker det (ja, det kan .ael, men ikke alle versioner, og det er ikke altid praktisk)

  • I stedet for at behandle slutningen gennem exten=>h, blev behandlingen introduceret gennem hangup_handler, fordi FreePBX-opkaldsplanen kun fungerede med den

  • Fast script opkaldsstreng, tilføjede tilbud og eksternt opkaldsnummer ExtNum

  • Behandling flyttes til _brugerdefinerede kontekster og giver dig mulighed for ikke at røre ved eller redigere FreePBX-konfigurationer - indgående via [ext-gjorde-brugerdefinerede], udgående gennem [udgående-allroutes-tilpasset]

  • Ingen binding til tal - filen er universel og skal kun konfigureres til stien og linket til serveren

For at komme i gang skal du også køre scripts i AMI ved login og adgangskode - til dette har FreePBX også en _custom fil

manager_custom.conf fil

;;  это логин
[callmeplus]
;; это пароль
secret = trampampamturlala
deny = 0.0.0.0/0.0.0.0

;; я работаю с локальной машиной - но если надо, можно и другие прописать
permit = 127.0.0.1/255.255.255.255
read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan
write = system,call,agent,log,verbose,user,config,command,reporting,originate

Begge disse filer skal placeres i /etc/asterisk, og genlæs derefter konfigurationerne (eller genstart asterisken)

# astrisk -rv
  Connected to Asterisk 16.6.2 currently running on freepbx (pid = 31629)
#freepbx*CLI> dialplan reload
     Dialplan reloaded.
#freepbx*CLI> exit

Lad os nu gå videre til PHP

Initialisering af scripts og oprettelse af en service

Da ordningen for at arbejde med Bitrix 24, en service til AMI, ikke er helt enkel og gennemsigtig, skal den diskuteres særskilt. Asterisk, når AMI er aktiveret, åbner du blot porten, og det er det. Når en klient tilslutter sig, anmoder den om autorisation, hvorefter klienten abonnerer på de nødvendige begivenheder. Hændelser kommer i almindelig tekst, som PAMI konverterer til strukturerede objekter og giver mulighed for kun at indstille filtreringsfunktionen for begivenheder af interesse, felter, tal osv.

Så snart opkaldet kommer ind, udløses NewExten-begivenheden fra den overordnede [from-pstn]-kontekst, hvorefter alle hændelser går i rækkefølgen efter linjerne i sammenhængene. Når der modtages oplysninger fra variablerne CallMeCallerIDName og CallStart, der er angivet i _custom dialplan,

  1. Funktionen med at anmode om det bruger-id, der svarer til lokalnummeret, hvor opkaldet kom. Hvad hvis det er en opkaldsgruppe? Spørgsmålet er politisk, skal du oprette et opkald til alle på én gang (når alle ringer på én gang) eller oprette som de kalder, når du ringer på skift? De fleste klienter har Fisrt Available-strategien, så der er ikke noget problem med dette, kun én ringer. Men problemet skal løses.

  2. Opkaldsregistreringsfunktionen i Bitrix24, som returnerer CallID, som så skal rapportere opkaldsparametrene og et link til optagelsen. Kræver enten lokalnummer eller bruger-ID

Forstå FreePBX og integrere det med Bitrix24 og mere

Efter afslutningen af ​​opkaldet kaldes record download-funktionen, som samtidig rapporterer status for opkaldets afslutning (Optaget, Intet svar, Succes), og også downloader et link til mp3-filen med posten (hvis nogen).

Fordi CallMeIn.php-modulet skal køre kontinuerligt, er der oprettet en SystemD-startfil til det callme.service, som skal sættes i /etc/systemd/system/callme.service

[Unit]
Description=CallMe

[Service]
WorkingDirectory=/var/www/html/callmeplus
ExecStart=/usr/bin/php /var/www/html/callmeplus/CallMeIn.php 2>&1 >>/var/log/callmeplus.log
ExecStop=/bin/kill -WINCH ${MAINPID}
KillSignal=SIGKILL

Restart=on-failure
RestartSec=10s

#тут надо смотреть,какие права на папки
#User=www-data  #Ubuntu - debian
#User=nginx #Centos

[Install]
WantedBy=multi-user.target

initialisering og lancering af scriptet sker gennem systemctl eller service

# systemctl enable callme
# systemctl start callme

Tjenesten genstarter sig selv efter behov (i tilfælde af nedbrud). Indbakkesporingstjenesten kræver ikke, at en webserver er installeret, kun php er nødvendig (som bestemt er på FeePBX-serveren). Men i mangel af adgang til opkaldsposter via webserveren (også med https), vil det ikke være muligt at lytte til opkaldsposter.

Lad os nu tale om udgående opkald. CallMeOut.php-scriptet har to funktioner:

  • Igangsættelse af et opkald, når der modtages en anmodning om et php-script (inklusive brug af knappen "Ring op" i selve Bitrix). Det virker ikke uden en webserver, anmodningen modtages via HTTP POST, anmodningen indeholder et token

  • Besked om opkaldet, dets parametre og registreringer i Bitrix. Udløst af Asterisk i [sub-call-internal-ended] opkaldsplanen, når et opkald afsluttes

Forstå FreePBX og integrere det med Bitrix24 og mere

Webserveren er kun nødvendig til to ting - download af Bitrix record-filer (via HTTPS) og kalder CallMeOut.php-scriptet. Du kan bruge den indbyggede FreePBX-server, hvor filerne er /var/www/html, du kan installere en anden server eller angive en anden sti.

Webserver

Lad os forlade webserveropsætningen til uafhængig undersøgelse (tyts, tyts, tyts). Hvis du ikke har et domæne, kan du prøve FreeDomain( https://www.freenom.com/ru/index.html), som vil give dig et gratis navn til din hvide IP (glem ikke at videresende porte 80, 443 gennem routeren, hvis den eksterne adresse kun er på den). Hvis du lige har oprettet et DNS-domæne, så skal du vente (fra 15 minutter til 48 timer), indtil alle servere er indlæst. Ifølge erfaringerne med at arbejde med indenlandske udbydere - fra 1 time til en dag.

Installationsautomatisering

Der er udviklet et installationsprogram på github for at gøre installationen endnu nemmere. Men det var glat på papiret - mens vi installerer det hele manuelt, da det efter at have puslet med alt dette blev krystalklart, hvad der er venner med hvem, hvem der går hvorhen og hvordan man fejlretter det. Der er endnu ingen installationsprogram

Docker

Hvis du hurtigt vil prøve løsningen - der er en mulighed med Docker - lav hurtigt en container, giv den porte udenfor, slip indstillingsfilerne og prøv (dette er muligheden med LetsEncrypt containeren, hvis du allerede har et certifikat, kan du skal bare omdirigere den omvendte proxy til FreePBX-webserveren (vi gav den en anden port er 88), LetsEncrypt i docker baseret på denne artikel

Du skal køre filen i den downloadede projektmappe (efter git clone), men først gå ind i asterisk configs (stjerne mappe) og skriv stierne til posterne og URL'en på dit websted der

version: '3.3'
services:
  nginx:
    image: nginx:1.15-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/ssl_docker.conf:/etc/nginx/conf.d/ssl_docker.conf
  certbot:
    image: certbot/certbot
  freepbx:
    image: flaviostutz/freepbx
    ports:
      - 88:80 # для настройки
      - 5060:5060/udp
      - 5160:5160/udp
      - 127.0.0.1:5038:5038 # для CallMeOut.php
#      - 3306:3306
      - 18000-18100:18000-18100/udp
    restart: always
    environment:
      - ADMIN_PASSWORD=admin123
    volumes:
      - backup:/backup
      - recordings:/var/spool/asterisk/monitor
      - ./callme:/var/www/html/callme
      - ./systemd/callme.service:/etc/systemd/system/callme.conf
      - ./asterisk/manager_custom.conf:/etc/asterisk/manager_custom.conf
      - ./asterisk/extensions_custom.conf:/etc/asterisk/extensions_custom.conf
#      - ./conf/startup.sh:/startup.sh

volumes:
  backup:
  recordings:

Denne docker-compose.yaml-fil køres via

docker-compose up -d

Hvis nginx ikke starter, er der noget galt med konfigurationen i mappen nginx/ssl_docker.conf

Andre integrationer

Og hvorfor ikke lægge noget CRM ind i scripts på samme tid, tænkte vi. Vi studerede flere andre CRM API'er, især den gratis indbyggede PBX - ShugarCRM og Vtiger, og ja! ja, princippet er det samme. Men dette er en anden historie, som vi senere vil uploade til github separat.

RЎSЃS <P "RєRё

Ansvarsfraskrivelse: Enhver lighed med virkeligheden er fiktiv, og det var ikke mig.

Kilde: www.habr.com

Tilføj en kommentar