Architectural solutions in the Bitrix24 telephony system



    Despite the era of the Internet and all kinds of means of communication, telephone communication remains one of the most important channels for the company to interact with its customers. And no matter what the corporate site, the face of the company, the lack of a telephone or poor quality of communication can greatly spoil the impression of customers and partners. Therefore, we once seriously took care to integrate into Bitrix24 a complete telephone communication system that our users can use to support and develop their business. And on the pages of this post we want to talk about the architecture and principles of functioning of the created system.

    Working out the requirements for telephony, which was planned to be integrated into 1C-Bitrix, we immediately decided that each telephone account should be isolated from each other. So that no client could interfere or harm another. We were not happy with the scheme when one telephone account is allocated to our company, customers transfer money to us, and we somehow distribute traffic. We needed complete isolation so that each user had his own statistics, his own balance, separate provision of other services. This required Voximplant, whose productwe chose to create telephony, finalized our system. As a result, the so-called master account was introduced, under which all of our user’s child accounts are created, each portal has its own. Although, in fact, four master accounts are technically used: for rubles, hryvnias, dollars and euros.

    This architectural solution made it possible to implement a number of services in the future. For example, on each portal, users can connect their own PBX. It would be incredibly difficult to provide such functionality on one common account, because you would have to create a complex accounting system and ensure the security of each call. And isolated user accounts allowed to avoid all this, as well as many other problems.

    Telephony controller


    However, this has not yet solved all our problems. The fact is that Voximplant is not just a service for organizing telephony. This is a platform for developers. And this implies that all the necessary tools must be created by the developers themselves, depending on their needs, accepted business logic and existing conditions.

    Therefore, in order to implement the separation of user accounts that we had conceived, we had to write a module for Bitrix24 called the telephony controller in PHP and MySQL . It acts as a kind of information intermediary between the user portal and the Voximplant server.



    When a user initiates a call for the first time, the telephony module on its portal contacts the telephony controller and requests credentials. The controller checks on the license server that this user has the right to use this service, and then applies for the credentials to the Voximplant server. If there is no account yet, then it is immediately created. After that, the controller returns the credentials for connecting to the SIP to the portal, they are written to the database on the portal and are used for all subsequent calls. That is, in the future, the telephony controller is no longer involved.

    Upon receipt of the credentials, the user directly contacts Voximplant and all voice traffic goes via WebRTC without any intermediaries. To transfer all other information, a protocol connection is used.The WebSocket . When the call ends, Voximplant notifies the controller, and the Voximplant records this in the user's statistics. All communication with Voximplant servers is based on the REST principle .

    The same thing happens if the user wants to perform some other operations, for example, find out the balance, view call statistics or purchase a phone number. The portal first turns to the controller with the corresponding request, and the latter requests the necessary data in the corresponding source and passes it to the user.

    In other words, the user portals themselves do not know anything about Voximplant, for them the entry point is always the telephony controller. The result is an isolated system in which the user himself does not worry at all about how the calls are made. All statistics and the current balance are displayed directly on the portal, payment is made there, the user does not need to go anywhere else. This allows you to start using the telephony service as quickly as possible: just go to your portal, select a number, pay money immediately, and you can make calls. No need to create any additional accounts, configure anything.

    In contrast to calls through a browser, the telephone sets of Bitrix24 users»Connect to the Voximplant server directly, bypassing the telephony controller. To do this, during the initial connection, the login and password are entered into the phone, which are subsequently used for each call. The user receives these credentials during setup in the Telephony section, the procedure is the same as when making the first call. And already on the basis of these registration data, Voximplant sends statistics about completed calls. And since telephones (including applications for VoIP-telephony) can change hosts, the administrator has the opportunity to quickly change the password or completely disable this account.



    When an incoming call arrives from an external network to a number rented by Bitrix24 user", Then it gets to the Voximplant server. He turns to the controller for information about who needs to send a call. A notification about an incoming call appears on the portal of the corresponding user, and as soon as someone answers, the server connects both subscribers directly.

    Security


    Despite the presence of an information intermediary in the form of a telephony controller, this does not harm security. Firstly, all data is transmitted via HTTPS, that is, encrypted with SSL . In addition, each data exchange (any REST command) between the portal and the telephony controller, based on the transmitted information and the license key, generates a unique request key (it will be different for each data set). The same encryption is performed during data exchange between the controller and Voximplant voice terminals. Key exchange is also carried out when a direct connection is established between the user portal and the Voximplant server.

    Account Registration


    When a new user enters the telephony section on the Bitrix24 portal , the telephony controller automatically creates an account for him in Voximplant. When making the first call or connecting a telephone, information about the telephone number is added to the account. That is, all registration operations are performed sequentially, as the user performs certain actions. Thus, we avoid the peak load on the servers during the registration process.

    Account Updates


    One of the main reasons for creating a telephony controller was the need to control accounts with the ability to easily update them. Inside user accounts on portals, call script settings, routing rules, and much more are stored. And since we have already created tens of thousands of accounts, the total amount of data is very large. And in case we find some kind of error in the script or want to add new functionality, you need to go into each account and change something.

    But it is even with a hundred clients very difficult and long. Therefore, we made an update system. It works like this: we create a new script, number it, send it to the telephony controller, and it gradually starts to update all telephone accounts.



    Since we have many users who once tried our telephone service, but did not continue to use it, we decided to update only those accounts that will use the telephone service after the update. That is, the procedure will be launched only if a call or balance check is initiated. This allows you to systematically conduct updates, as you apply, without arranging each time an emergency and not loading the system with updating many thousands of accounts.

    Call Scenarios


    Voximplant allows you to create absolutely any call scenario. The following is an example of a simplified diagram of an incoming call.



    Let's look at this scheme. So, we have an incoming call. Since Voximplant is an external system for Bitrix24 , first it needs to get the settings for the called party (in JSON format ) from the controller , based on which the script performs the actions provided for incoming or outgoing calls. After the first call, the JSON settings are cached, and subsequently we do not need to go to the user portal for them every time. The script itself is a software module written in JavaScript and containing about 3,000 lines of code.

    After receiving the settings, the processing of the script begins, that is, the execution of the algorithm of numerous checks. Whether the calling number is blacklisted, is a day off or a work day, whether it is necessary to play a greeting and check additional codes, and much more.

    We process all standard scenarios that may be in demand by our users. For example, if an incoming call is made at night, you need to inform that there is no one in the place yet, call back later or leave a message. Or CRM processing scenarios: should this be done, if so, then transfer the call to the responsible person and immediately tell him who the call came from. To the caller immediately answered: "Hello, Ivan Ivanovich. What would you like?"

    The scenario scheme is executed sequentially: immediately after the start of the greeting, the necessary data is requested, if the subscriber did not answer the call, the corresponding stage of the scenario is performed, etc. That is, the scheme, although it looks very impressive, is processed in stages, and not at once, so the subscriber does not have to wait.

    Additional features


    Using the telephony controller, we can warn users that their balance has reached a certain limit. This is especially important for companies that actively use telephone communications, and early notification allows you to deposit funds to your account in advance, without suddenly being unavailable for some time.

    The controller also allows us to transfer all user settings when switching from the cloud version of Bitrix24 to the boxed one. Since the telephone account is not tied tightly to the portal, it is quite simple to reassign it to another version of the product. Therefore, the client does not need to reconfigure anything, immediately after the migration, he can continue to use telephone communications.

    Among other things, through a telephony controller, our technical support can assist users. When someone addresses a problem, a technical support specialist asks the user for authorization data. And then, according to the approved regulations, he asks him for permission to view statistics. After the permission is obtained, through the telephony controller we get the phone account data, call logs and other information that allows us to solve the problem that the user contacted. Often, to fully diagnose the problem, it is enough to analyze the call log, therefore, our experts rarely request access directly to the telephony account. Here's what the log looks like in the original:

    Log
    2015-07-24 08:50:08 Loading scenario bitrix24
    2015-07-24 08:50:08 Sent event to JS onPhoneEvent with params [{accessURL = ;  accountId = XXXXX ;  applicationId = XXXXX ;  logURL = ;  name = Application.Started ;  sessionId = 48475497 ;  userId = 1 ;  } ;  ]
    2015-07-24 08:50:08 Sent event to JS onPhoneEvent with params [{callerid = test ;  destination = 74012XXXXXX ;  displayName = 79112233444 ;  fromURI = sip:test@ip.accountName.voximplant.com ;  headers = {VI-Client-Device = SIP ;  VI-Client-IP = 69.167.178.6 ;  VI-Client-Type = user ;  } ;  id = 16214d90008034a8.1437727808.225341 ;  name = Application.CallAlerting ;  toURI = sip:74012XXXXXX@ip.accountName.voximplant.com ;  } ;  ]
    2015-07-24 08:50:08 Executing JS command: SetCustomData with params [{data = 16214d90008034a8.1437727808.225341 ;  } ;  ]
    2015-07-24 08:50:08 Executing JS command: StartAudio with params [{headers = NULL ;  id = 16214d90008034a8.1437727808.225341 ;  } ;  ]
    2015-07-24 08:50:08 Executing JS command: PlayToneScript with params [{id = 16214d90008034a8.1437727808.225341 ;  loop = true ;  script = 440@-19,480@-19;*(2/4/1+2) ;  } ;  ]
    2015-07-24 08:50:08
    2015-07-24 08:50:08 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:08 Start INCOMING scenario (version: 9)
    2015-07-24 08:50:08 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:08
    2015-07-24 08:50:08
    2015-07-24 08:50:08 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:08 Pure variables
    2015-07-24 08:50:08 Call scenario user: 1
    2015-07-24 08:50:08 Call callerId: test
    2015-07-24 08:50:08 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = 16214d90008034a8.1437727808.225341 ;  name = Call.AudioStarted ;  } ;  ]
    2015-07-24 08:50:08 Call destination: 74012XXXXXX
    2015-07-24 08:50:08 Call displayName: 79112233444
    2015-07-24 08:50:08 Call number/destination: 74012XXXXXX
    2015-07-24 08:50:08 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:08
    2015-07-24 08:50:09
    2015-07-24 08:50:09 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:09 Get B24 config:
    2015-07-24 08:50:09 ID: 23   /   PORTAL_MODE: RENT   /   SEARCH_ID: test   /   PHONE_NAME: 88002501860   /   CRM: Y   /   CRM_RULE: queue   /   CRM_CREATE: lead   /   CRM_FORWARD: Y   /   QUEUE_TIME: 3   /   QUEUE_TYPE: evenly   /   DIRECT_CODE: Y   /   DIRECT_CODE_RULE: voicemail   /   RECORDING: Y   /   RECORDING_TIME: 0   /   NO_ANSWER_RULE: voicemail   /   FORWARD_NUMBER:    /   FORWARD_LINE: default   /   TIMEMAN: N   /   VOICEMAIL: Y   /   MELODY_LANG: RU   /   MELODY_WELCOME: http://dl.bitrix24.com/vi/RU01.mp3   /   MELODY_WELCOME_ENABLE: Y   /   MELODY_WAIT: http://dl.bitrix24.com/vi/MELODY.mp3   /   MELODY_HOLD: http://dl.bitrix24.com/vi/MELODY.mp3   /   DATE_DELETE: null   /   TO_DELETE: N   /   MELODY_VOICEMAIL: http://dl.bitrix24.com/vi/RU03.mp3   /   PHONE_TITLE: 88002501860   /   PORTAL_URL: https://phone.bitrix24.ru/
    2015-07-24 08:50:09 PORTAL_SIGN: -hidden-
    2015-07-24 08:50:09 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:09
    2015-07-24 08:50:09
    2015-07-24 08:50:09 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:09 Call type is: TEST CALL
    2015-07-24 08:50:09 Phone number: 74012XXXXXX
    2015-07-24 08:50:09 Call to: 79112233444
    2015-07-24 08:50:09 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:09
    2015-07-24 08:50:09 Call in correct worktime
    2015-07-24 08:50:09 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:09
    2015-07-24 08:50:09 Executing JS command: AcceptCall with params [{headers = NULL ;  id = 16214d90008034a8.1437727808.225341 ;  } ;  ]
    2015-07-24 08:50:09 Executing JS command: Play with params [{id = 16214d90008034a8.1437727808.225341 ;  loop = false ;  url = http://dl.bitrix24.com/vi/RU01.mp3 ;  } ;  ]
    2015-07-24 08:50:09 Executing JS command: HandleTones with params [{handle = true ;  id = 16214d90008034a8.1437727808.225341 ;  } ;  ]
    2015-07-24 08:50:10 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = 16214d90008034a8.1437727808.225341 ;  name = Call.Connected ;  } ;  ]
    2015-07-24 08:50:17 Sent event to JS onPhoneEvent with params [{id = 16214d90008034a8.1437727808.225341 ;  name = Call.PlaybackFinished ;  } ;  ]
    2015-07-24 08:50:17 Executing JS command: Stop with params [{id = 16214d90008034a8.1437727808.225341 ;  } ;  ]
    2015-07-24 08:50:19 Executing JS command: HandleTones with params [{handle = false ;  id = 16214d90008034a8.1437727808.225341 ;  } ;  ]
    2015-07-24 08:50:19
    2015-07-24 08:50:19 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:19 Direct code is: none
    2015-07-24 08:50:19 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:19
    2015-07-24 08:50:19 Executing JS command: Play with params [{id = 16214d90008034a8.1437727808.225341 ;  loop = true ;  url = http://dl.bitrix24.com/vi/MELODY.mp3 ;  } ;  ]
    2015-07-24 08:50:20
    2015-07-24 08:50:20 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:20 Get B24 invite answer: {"COMMAND":"wait","TYPE_CONNECT":"crm","USER_ID":"67","USER_HAVE_PHONE":"Y"}
    2015-07-24 08:50:20 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:20
    2015-07-24 08:50:20
    2015-07-24 08:50:20 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:20 Action: Send invite to phone67
    2015-07-24 08:50:20 from number: 74012XXXXXX
    2015-07-24 08:50:20 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:20
    2015-07-24 08:50:20 Executing JS command: CallUser with params [{id = viXMtbt2TrSdBzRsqoyzSUQTaqDxKESGr_bNdm7UuBI ;  } ;  {callerid = 79112233444 ;  displayName = NULL ;  headers = NULL ;  username = phone67 ;  video = NULL ;  } ;  ]
    2015-07-24 08:50:21 Sent event to JS onPhoneEvent with params [{content = {"COMMAND":"wait","OPERATOR_ID":"67"} ;  method = POST ;  name = Application.HttpRequest ;  path = /request/28ccd1538fd88709.1437727808.225342_38.88.16.65/e2a2f42cebd2f7a2 ;  } ;  ]
    2015-07-24 08:50:21
    2015-07-24 08:50:21 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:21 Get command from B24 portal: {"COMMAND":"wait","OPERATOR_ID":"67"}
    2015-07-24 08:50:21 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:21
    2015-07-24 08:50:22 Sent event to JS onPhoneEvent with params [{content = {"COMMAND":"wait","OPERATOR_ID":"67"} ;  method = POST ;  name = Application.HttpRequest ;  path = /request/28ccd1538fd88709.1437727808.225342_38.88.16.65/e2a2f42cebd2f7a2 ;  } ;  ]
    2015-07-24 08:50:22
    2015-07-24 08:50:22 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:22 Get command from B24 portal: {"COMMAND":"wait","OPERATOR_ID":"67"}
    2015-07-24 08:50:22 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:22
    2015-07-24 08:50:25 Sent event to JS onPhoneEvent with params [{content = {"COMMAND":"user","OPERATOR_ID":"67","USER_ID":67} ;  method = POST ;  name = Application.HttpRequest ;  path = /request/28ccd1538fd88709.1437727808.225342_38.88.16.65/e2a2f42cebd2f7a2 ;  } ;  ]
    2015-07-24 08:50:25
    2015-07-24 08:50:25 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:25 Get command from B24 portal: {"COMMAND":"user","OPERATOR_ID":"67","USER_ID":67}
    2015-07-24 08:50:25 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:25
    2015-07-24 08:50:25
    2015-07-24 08:50:25 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:25 Action: Connect to user67
    2015-07-24 08:50:25 from number: 74012XXXXXX
    2015-07-24 08:50:25 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:25
    2015-07-24 08:50:25 Executing JS command: CallUser with params [{id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  } ;  {callerid = 79112233444 ;  displayName = NULL ;  headers = NULL ;  username = user67 ;  video = NULL ;  } ;  ]
    2015-07-24 08:50:26 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  name = Call.Ringing ;  } ;  ]
    2015-07-24 08:50:26 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  name = Call.Ringing ;  } ;  ]
    2015-07-24 08:50:26 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  name = Call.AudioStarted ;  } ;  ]
    2015-07-24 08:50:26 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  name = Call.Connected ;  } ;  ]
    2015-07-24 08:50:26 Executing JS command: HangupCall with params [{code =  3.0200E+02 ;  headers = NULL ;  id = viXMtbt2TrSdBzRsqoyzSUQTaqDxKESGr_bNdm7UuBI ;  } ;  ]
    2015-07-24 08:50:26 Executing JS command: SendMediaBetween with params [{id1 = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  id2 = 16214d90008034a8.1437727808.225341 ;  } ;  ]
    2015-07-24 08:50:26 Executing JS command: Record with params [{id = 16214d90008034a8.1437727808.225341 ;  stereo = false ;  } ;  ]
    2015-07-24 08:50:26 Sent event to JS onPhoneEvent with params [{id = 16214d90008034a8.1437727808.225341 ;  name = Call.RecordStarted ;  url = http://recordUrl.com/record.mp3 ;  } ;  ]
    2015-07-24 08:50:26
    2015-07-24 08:50:26 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:26 Send CallStart: COMMAND=StartCall&CALL_ID=16214d90008034a8.1437727808.225341&CALL_DEVICE=WEBRTC&EXTERNAL=N&USER_ID=67
    2015-07-24 08:50:26 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:26
    2015-07-24 08:50:26
    2015-07-24 08:50:26 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:26 Start recording call: http://recordUrl.com/record.mp3
    2015-07-24 08:50:26 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:26
    2015-07-24 08:50:31 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  name = Call.MessageReceived ;  text = {"COMMAND":"hold"} ;  } ;  ]
    2015-07-24 08:50:31
    2015-07-24 08:50:31 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:31 Get command from B24 user: {"COMMAND":"hold"}
    2015-07-24 08:50:31 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:31
    2015-07-24 08:50:31 Executing JS command: StopMediaBetween with params [{id1 = 16214d90008034a8.1437727808.225341 ;  id2 = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  } ;  ]
    2015-07-24 08:50:31 Executing JS command: Stop with params [{id = 16214d90008034a8.1437727808.225341 ;  } ;  ]
    2015-07-24 08:50:31 Executing JS command: Play with params [{id = 16214d90008034a8.1437727808.225341 ;  loop = true ;  url = http://dl.bitrix24.com/vi/MELODY.mp3 ;  } ;  ]
    2015-07-24 08:50:31 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  name = Call.MessageReceived ;  text = {"COMMAND":"meter","PERCENT":100,"GRADE":5} ;  } ;  ]
    2015-07-24 08:50:31
    2015-07-24 08:50:31 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:31 Get command from B24 user: {"COMMAND":"meter","PERCENT":100,"GRADE":5}
    2015-07-24 08:50:31 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:31
    2015-07-24 08:50:36 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  name = Call.MessageReceived ;  text = {"COMMAND":"meter","PERCENT":100,"GRADE":5} ;  } ;  ]
    2015-07-24 08:50:36
    2015-07-24 08:50:36 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:36 Get command from B24 user: {"COMMAND":"meter","PERCENT":100,"GRADE":5}
    2015-07-24 08:50:36 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:36
    2015-07-24 08:50:36 Sent event to JS onPhoneEvent with params [{code = 487 ;  headers = {} ;  id = viXMtbt2TrSdBzRsqoyzSUQTaqDxKESGr_bNdm7UuBI ;  name = Call.Failed ;  reason = Request Terminated ;  } ;  ]
    2015-07-24 08:50:39 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  name = Call.MessageReceived ;  text = {"COMMAND":"unhold"} ;  } ;  ]
    2015-07-24 08:50:39
    2015-07-24 08:50:39 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:39 Get command from B24 user: {"COMMAND":"unhold"}
    2015-07-24 08:50:39 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:39
    2015-07-24 08:50:39 Executing JS command: Stop with params [{id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  } ;  ]
    2015-07-24 08:50:39 Executing JS command: Stop with params [{id = 16214d90008034a8.1437727808.225341 ;  } ;  ]
    2015-07-24 08:50:39 Executing JS command: SendMediaBetween with params [{id1 = 16214d90008034a8.1437727808.225341 ;  id2 = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  } ;  ]
    2015-07-24 08:50:41 Sent event to JS onPhoneEvent with params [{headers = {} ;  id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  name = Call.MessageReceived ;  text = {"COMMAND":"meter","PERCENT":100,"GRADE":5} ;  } ;  ]
    2015-07-24 08:50:41
    2015-07-24 08:50:41 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:41 Get command from B24 user: {"COMMAND":"meter","PERCENT":100,"GRADE":5}
    2015-07-24 08:50:41 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:41
    2015-07-24 08:50:44 Sent event to JS onPhoneEvent with params [{cost =  0.0000E+00 ;  direction = any outgoing voip ;  duration = 18 ;  headers = {} ;  id = aI2BuvHLRLmeITs0LNDdq1O4AmrcWkZUmtayuwx7k_o ;  name = Call.Disconnected ;  } ;  ]
    2015-07-24 08:50:44 Executing JS command: HangupCall with params [{code =  6.0300E+02 ;  headers = NULL ;  id = 16214d90008034a8.1437727808.225341 ;  } ;  ]
    2015-07-24 08:50:44 Sent event to JS onPhoneEvent with params [{content = {"COMMAND":"queue","OPERATOR_ID":"67"} ;  method = POST ;  name = Application.HttpRequest ;  path = /request/28ccd1538fd88709.1437727808.225342_38.88.16.65/e2a2f42cebd2f7a2 ;  } ;  ]
    2015-07-24 08:50:44
    2015-07-24 08:50:44 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:44 Get command from B24 portal: {"COMMAND":"queue","OPERATOR_ID":"67"}
    2015-07-24 08:50:44 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:44
    2015-07-24 08:50:44 Sent event to JS onPhoneEvent with params [{cost =  0.0000E+00 ;  direction = any Incoming VoIP ;  duration = 34 ;  headers = {} ;  id = 16214d90008034a8.1437727808.225341 ;  name = Call.Disconnected ;  } ;  ]
    2015-07-24 08:50:44
    2015-07-24 08:50:44 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:44 Send HangupCall: COMMAND=HangupCall&PHONE_NUMBER=74012XXXXXX&ACCOUNT_SEARCH_ID=test&CALL_ID=16214d90008034a8.1437727808.225341&USER_ID=67
    2015-07-24 08:50:44 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:44
    2015-07-24 08:50:44
    2015-07-24 08:50:44 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:44 Send call history
    2015-07-24 08:50:44 Call code: 200
    2015-07-24 08:50:44 Call reason: Success call
    2015-07-24 08:50:44 Call direction: any%20Incoming%20VoIP
    2015-07-24 08:50:44 Call params: COMMAND=AddCallHistory&ACCOUNT_ID=XXXXX&PORTAL_USER_ID=67&APPLICATION_ID=XXXXX&PORTAL_TYPE=RENT&PORTAL_NUMBER=74012XXXXXX&PORTAL_CALL=N&ACCOUNT_SEARCH_ID=test&PHONE_NUMBER=79112233444&URL=http://recordUrl.com/record.mp3&INCOMING=2&CALL_ID=16214d90008034a8.1437727808.225341&CALL_LOG=http://callLog/call.log&CALL_DURATION=34&CALL_START_DATE=1437727826308&CALL_STATUS=true&CALL_QUALITY=100&CALL_DEVICE=WEBRTC&CALL_VOTE=0&COST=0
    2015-07-24 08:50:44 ------------------------------------------------------------------------------------------
    2015-07-24 08:50:44
    2015-07-24 08:50:45 Sent event to JS onPhoneEvent with params [{cost = 0 ;  duration = 18 ;  id = 16214d90008034a8.1437727808.225341 ;  name = Call.RecordStopped ;  reason = Stopped by user ;  url = http://recordUrl.com/record.mp3 ;  } ;  ]
    2015-07-24 08:50:45 Executing JS command: close with params [void ;  ]
    2015-07-24 08:50:45 Session terminated
    



    All invoked JavaScript methods are registered in the Voximplant API .
    To make it easier for specialists to read the logs, we made a small plug-in for Chrome, which changes the formatting a bit:



    Since the telephony service is provided as part of the Bitrix24 service , we apply the same security policies to it as the service itself. We guarantee users that without their knowledge we don’t go to their portals, we don’t listen to recordings of conversations, and so on. We only store statistics on the number and duration of calls. And the recordings of conversations themselves are stored only by the operator in a closed section and on the client’s portal. In addition, the circle of specialists who can, with the permission of users, access records is strictly limited.

    Implementation difficulties


    In general, we did not encounter any difficulties in implementing the telephone communication system in Bitrix24 . One point can be noted, and even that is not connected at all with the Voximplant platform.

    The problem was related to the implementation of the “SIP connector”. This is a service that allows the user to connect their PBX (cloud or office) to make calls through it, and not through the browser interface. It turned out that different service providers and cloud PBX operators (not to mention office PBXs) work differently with number formats. Someone perfectly understands what 7495 is; someone needs to specify a leading +; for some, a country code is not required. For Kazakh operators, you need to indicate 8495 instead of 7495, otherwise you will not get through. Also, subscribers of Kazakh operators for international calls (to all numbers except Kazakh and Russian) need to indicate 810 before the country code.

    In general, the problem of numbering exists even in the minds of users: someone dials the prefix +7 before the number, someone 8; someone dials 007495, and someone 0117495. Many users like to indicate numbers in this form: 8 (495) 445-11-20, and we have to bring them to the international format (without the + sign) 74954451120.

    Not so long ago, Voximplant implemented the logic with which the system recognizes where the user is calling from. And for the Russian Federation, for example, the prefix 8 replaces with 7. We are not yet ready for this transition, it seems to us that here we need to focus not on the country of registration of the number, but on the user's preferences and traditions; still, a Russian person on a business trip is much more accustomed to dial 8 than some obscure 00.

    Future plans


    The capabilities of the Voximplant platform are very extensive, and today we use only about 30% of its functionality. For example, we plan to introduce a multi-level IVR system.. We are also going to supplement the warning function about a small balance of funds in the account with some adaptive algorithm. By default, notifications are sent to Voximplant when they reach a certain limit common to all users. But each company has its own level of use of telephone communications, and if for one 300 rubles on the account it is quite possible to work quietly for a couple of days until the balance is replenished, then for another even 2000 rubles will not be enough for a working day. So we want to supplement the telephony controller with a module that will analyze the company's expenses for telephone communications within a week, and based on the data received, will set an individual account balance threshold, upon reaching which a notification will be sent.

    In addition, in the near future we will introduce the ability to make calls to internal numbers, transfer calls between telephones, conference calls and fix the call source in CRM. All this functionality is already at the testing stage, and closer to mid-August it will become available to our users.

    In other words, telephony for Bitrix24 is actively developing, we carefully monitor all the wishes of our users and try to introduce the necessary new products as quickly as possible.

    Also popular now: