📜 ⬆️ ⬇️

Architectural solutions for 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 of interaction between the company and its customers. And whatever the corporate site is - the face of the company - the lack of a phone 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 full-fledged telephone communication system, which 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 through 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 can prevent or harm another. We were not satisfied with the scheme, when one phone account is allocated to our company, clients transfer money to us, and we somehow distribute the traffic. We needed complete isolation, so that each user had his own statistics, his own balance, separate provision of other services. To do this, it took the company Voximplant, whose product we chose to create telephony, to refine its system. As a result, the so-called master account was introduced, under which all affiliated accounts of our users are created, for each portal 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 every 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 some kind of service for organizing telephony. This is a platform for developers. This implies that all the necessary tools should be created by the developers themselves, depending on their needs, the accepted business logic and the existing conditions.

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



When a user initiates a call for the first time, the telephony module on his portal contacts the telephony controller and asks for credentials. The controller checks on the license server that this user has the right to use this service, and then applies for credentials to the Voximplant server. If there is no account yet, then it is immediately created. After that, the controller returns the portal credentials for SIP connection, they are recorded in 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 receiving the credentials, the user directly contacts Voximplant and all voice traffic goes through WebRTC without any intermediaries. For transfer of all other information connection through the WebSocket protocol is used. When the call ends, Voximplant notifies the controller, and Voximplant records this in the user’s statistics. All communication with the 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 contacts the controller with the corresponding request, and the latter requests the necessary data from the corresponding source and transmits 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 calls are made. All statistics and current balance are displayed directly on the portal, payment is made in the same place, the user does not need to go somewhere else. This allows you to quickly start using the telephony service: just go to your portal, select a number, pay money immediately, and you can make calls. No need to create any additional accounts, something to configure.

Unlike browser calls, Bitrix24 users' telephones connect to the Voximplant server directly, bypassing the telephony controller. To do this, during the initial connection, a login and password are entered into the phone, which are subsequently used for each call. The user receives these credentials during the configuration 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 on calls made. And since the telephones (including applications for VoIP-telephony) can change the owners, the administrator has the ability to quickly change the password or disable this account altogether.



When an incoming call arrives from the external network to the number rented by the user of Bitrix24 , it goes to the Voximplant server. He refers to the controller for information about who needs to send a call. A notification of 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, security does not harm it. First, all data is transmitted over HTTPS, that is, encrypted with SSL . In addition, at each data exchange (any REST command) between the portal and the telephony controller, it forms a unique request key (for each data set it will be different) based on the information transmitted and the license key. The same encryption is performed when data is exchanged between the controller and the Voximplant voice terminals. Key exchange is also performed when a direct connection is established between the user portal and the Voximplant server.

Registration of accounts


When a new user enters the telephony section on the Bitrix24 portal, the telephony controller automatically creates an account for it in Voximplant. When making the first call or connecting the 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 update


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

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



Since we have many users who once tried our telephone connection, but did not continue to use it, we decided to update only those accounts that will use the telephone connection after the update is released. That is, the procedure will be launched only if a call or balance check is initiated. This allows you to systematically carry out the update, as far as it goes, without arranging every time and without loading the system with updating thousands of accounts.

Call scenarios


Voximplant allows you to create absolutely any call script. Below is an example of a simplified incoming call.



Let's understand this scheme. So, we have an incoming call. Since Voximplant is an external system for Bitrix24 , first it needs to obtain the settings for the called subscriber from the controller (in JSON format ), on the basis of which the script performs the actions provided for incoming or outgoing calls. After the first call, the JSON settings are cached, and subsequently we don’t need to go to the user portal every time. The script itself is a software module written in JavaScript and containing about 3000 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, whether it is a day off or a working day, whether to play the greeting and check the extension codes, and much more.

We process all typical scenarios that can be requested by our users. For example, if an incoming call is made at night, then you need to report that there is no one on the spot yet, call back later or leave a message. Or CRM processing scenarios: do you need to do this, if yes, 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 script is executed sequentially: immediately after the greeting is launched, the required data is requested, if the subscriber did not answer the call, the corresponding stage of the script is executed, etc. That is, the scheme, although it looks very impressive, but is processed in stages, and not at the same time, so that the subscriber does not have to wait.

Additional features


With the help of a 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 into your account in advance, without suddenly being left without communication for a while.

Also, the controller allows us to transfer all user settings when it is transferred from the cloud version of Bitrix24 to the boxed one. Since the phone account is not tied tightly to the portal, then simply reassigning 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 the telephone connection.

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

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 called JavaScript methods are registered in the Voximplant API .
To make it easier for professionals to read the logs, we made a small plugin for Chrome, which slightly changes the formatting:



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

Implementation difficulties


In general, we did not encounter any difficulties in implementing the telephone system in Bitrix24 . One thing that can be noted is that one moment, and that one 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 his PBX (cloud or office) to make calls through it, and not through the browser interface. It turned out that different service providers and operators of cloud PBX (not to mention the office PBX) work differently with the formats of numbers. Someone perfectly understands what 7495 is; someone needs to specify a leading +; for some, you do not need to enter a country code. For Kazakh operators, instead of 7495, you need to specify 8495, 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 heads of users: someone dials the prefix +7, someone 8; someone dials 007495, and someone 0117495. Many users like to specify 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 a logic in 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 established traditions; after all, a Russian person who is on a business trip, where it’s customary to dial 8 than some strange 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 implement a multi-level IVR system. We are also going to supplement the warning function of a small balance of funds on the account with a certain adaptive algorithm. By default, notifications in Voximplant are sent after reaching a certain limit common to all users. But each company has its own level of telephone use, and if for one 300 rubles in the account it is quite possible to work quietly for a couple of days until the balance is replenished, then for another even 2,000 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 telephone communication expenses during the week, and based on the data received, it will establish an individual account balance threshold at which a notification will be sent.

In addition, in the near future, we will introduce the possibility of making calls to internal numbers, transferring calls between telephone sets, conference calls and recording the source of the call in CRM. All this functionality is already at the testing stage, and closer to the middle of August it will be available to our users.

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

Source: https://habr.com/ru/post/263915/


All Articles