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);
});








