Một giải pháp liên kết với tổng đài Asterisk để thông báo cho CRM mỗi khi có cuộc gọi đến/đi realtime, sử dụng Socket.io.
Mục lục
Cài đặt các gói thư viện
npm install --save express \ socket.io \ asterisk-manager
Cài đặt pm2 – chạy app Node.js lúc khởi động
npm install -g pm2
Mã nguồn chương trình
Chương trình sau xử lý chuỗi để lấy thông tin cuộc gọi đến và đi (số extension phía chủ và số điện thoại phía khách) nhờ giao diện AMI (Asterisk Manager Interface), sau đó gửi đến client bằng Socket.IO.
Dữ liệu trao đổi qua Socket.IO có thể được mã hóa bằng giao thức HTTPS. Trong ví dụ này, tôi dùng chứng chỉ SSL miễn phí của Let’s Encrypt. Lưu ý là thư mục lưu chứng chỉ của Let’s Encrypt được phân quyền chỉ cho user root
truy cập.
~/astereport/index.js
/** * References: * https://www.tutorialspoint.com/socket.io/index.htm * https://github.com/pipobscure/NodeJS-AsteriskManager * https://wiki.asterisk.org/wiki/display/AST/Asterisk+11+AMI+Events * * TODO * Each Extension has an individual namespace. */ const port = 3000; const fs = require("fs"); const app = require("express")(); const server = require("http").Server(app); // Socket IO - listening on port 3000 const io = require("socket.io").listen(server); io.on("connection", (socket) => { console.log("A user has connected"); socket.on("disconnect", () => { console.log("A user has disconnected"); }); }); server.listen(port, () => console.log("astereport.js is listening on *:" + port)); // Present an Intro page when accessing https://example.com app.get("/", (request, response) => response.sendFile(__dirname + "/index.html")); // Asterisk Manager const ami = require("asterisk-manager")( "5038", "localhost", "admin", "password", true); ami.keepConnected(); // on 'dial' event occurs when there is an incoming or outgoing call ami.on("dial", (evt) => { var phone = evt.calleridnum; var ext = evt.dialstring; var subevt = evt.subevent; var uniqueid = evt.uniqueid; var data = {}; if (isNumber(phone) && subevt === "Begin" ) { console.log(evt); if (phone.length > 6 && ext.length < 6 && isNumber(ext)) { // push the incoming call info to the clients io.sockets.emit('incoming', { phone: phone, ext: ext }); } else { if (!isNumber(ext)) { var channel = evt.channel; var n_bg, n_ed; if (-1 == channel.indexOf("@")) { n_bg = channel.indexOf("/"); n_ed = channel.indexOf("-"); } else { n_bg = channel.indexOf("@"); n_ed = channel.indexOf("-"); } ext = channel.substring(n_bg + 1, n_ed - n_bg + 3); phone = evt.connectedlinenum; // push the incoming call info to the clients io.sockets.emit('outgoing', { phone: phone, ext: ext }); } } } }); // Check if the input `n` is a valid number function isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); }
Dùng NGINX làm reverse proxy + Let’s Encrypt để mã hóa thông tin
T.B.C
Cài đặt & khởi động
cd ~/astereport pm2 start index.js pm2 startup
Xử lý sự kiện ở client
Phía client nhận sự kiện real-time từ Socket.IO rất đơn giản như sau:
Bước 1: Liên kết thư viện client JavaScript của socket.io
, như dưới đây tôi tải qua CDN.
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.slim.js"></script>
Bước 2: Xử lý sự kiện khi có cuộc gọi đến / đi bằng JavaScript.
const socket = io("http://example.com:3000"); // There is an outgoing call socket.on("outgoing", (data) => { console.log("outgoing call: " + data.ext + " -> " + data.phone); }); // There is an incoming call socket.on('incoming', (data) => { console.log("incoming call: " + data.phone + " -> " + data.ext); });