| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>JsSIP WSS Register Test</title>
- <style>
- body {
- font-family: Arial, sans-serif;
- margin: 24px;
- line-height: 1.5;
- background: #f5f7fa;
- color: #222;
- }
- .card {
- max-width: 900px;
- background: #fff;
- padding: 20px;
- border-radius: 10px;
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
- }
- .row {
- display: flex;
- gap: 12px;
- margin-bottom: 12px;
- flex-wrap: wrap;
- }
- .field {
- flex: 1 1 280px;
- }
- label {
- display: block;
- font-size: 14px;
- margin-bottom: 6px;
- font-weight: bold;
- }
- input {
- width: 100%;
- padding: 10px;
- box-sizing: border-box;
- border: 1px solid #ccc;
- border-radius: 6px;
- font-size: 14px;
- }
- button {
- padding: 10px 16px;
- border: 0;
- border-radius: 6px;
- font-size: 14px;
- cursor: pointer;
- background: #1677ff;
- color: #fff;
- }
- button.secondary {
- background: #666;
- }
- pre {
- margin-top: 16px;
- padding: 12px;
- min-height: 260px;
- overflow: auto;
- background: #0d1117;
- color: #d7e3f4;
- border-radius: 8px;
- white-space: pre-wrap;
- word-break: break-word;
- }
- .hint {
- font-size: 13px;
- color: #666;
- margin-top: 10px;
- }
- .ok {
- color: #0a7f2e;
- font-weight: bold;
- }
- .err {
- color: #c62828;
- font-weight: bold;
- }
- </style>
- </head>
- <body>
- <div class="card">
- <h2>JsSIP WSS Register Test</h2>
- <div class="row">
- <div class="field">
- <label for="wsUrl">WSS</label>
- <input id="wsUrl" value="wss://sip.ylrzcloud.com:8443">
- </div>
- <div class="field">
- <label for="sipDomain">SIP Domain</label>
- <input id="sipDomain" value="sip.ylrzcloud.com">
- </div>
- </div>
- <div class="row">
- <div class="field">
- <label for="username">分机号</label>
- <input id="username" value="1228">
- </div>
- <div class="field">
- <label for="password">分机密码</label>
- <input id="password" type="password" placeholder="请输入分机密码">
- </div>
- </div>
- <div class="row">
- <div class="field">
- <label for="registrarServer">Registrar</label>
- <input id="registrarServer" value="sip:sip.ylrzcloud.com">
- </div>
- <div class="field">
- <label for="realm">Realm</label>
- <input id="realm" value="sip.ylrzcloud.com">
- </div>
- </div>
- <div class="row">
- <button id="startBtn" disabled>开始注册</button>
- <button id="stopBtn" class="secondary">停止</button>
- <button id="clearBtn" class="secondary">清空日志</button>
- </div>
- <div id="status">状态:未启动</div>
- <div class="hint">
- 打开页面后先输入分机密码,再点击“开始注册”。如果浏览器证书未信任,请先在浏览器中访问一次
- <code>wss://sip.ylrzcloud.com:8443</code> 对应域名页面,确认无证书拦截。
- </div>
- <pre id="log"></pre>
- </div>
- <script src="./jssip.min.js"></script>
- <script>
- let ua = null;
- let jssipReady = !!window.JsSIP;
- function log(message, data) {
- const logEl = document.getElementById("log");
- const now = new Date().toLocaleTimeString();
- let line = "[" + now + "] " + message;
- if (typeof data !== "undefined") {
- try {
- line += "\n" + JSON.stringify(data, null, 2);
- } catch (e) {
- line += "\n" + String(data);
- }
- }
- logEl.textContent += line + "\n\n";
- logEl.scrollTop = logEl.scrollHeight;
- console.log(message, data || "");
- }
- function setStatus(text, className) {
- const el = document.getElementById("status");
- el.textContent = "状态:" + text;
- el.className = className || "";
- }
- function setStartButtonEnabled(enabled) {
- document.getElementById("startBtn").disabled = !enabled;
- }
- function ensureJsSIPLoaded() {
- if (window.JsSIP) {
- jssipReady = true;
- setStartButtonEnabled(true);
- setStatus("JsSIP 已就绪", "ok");
- log("已从本地文件加载 JsSIP", "./jssip.min.js");
- return;
- }
-
- setStatus("JsSIP 加载失败", "err");
- log("无法从本地加载 JsSIP,请确认当前页面与 ./jssip.min.js 在同一目录,并通过 HTTP 服务访问该页面。");
- }
- function stopUA() {
- if (ua) {
- try {
- ua.stop();
- log("已调用 ua.stop()");
- } catch (e) {
- log("停止 UA 异常", e.message || String(e));
- }
- ua = null;
- }
- setStatus("已停止");
- }
- function buildConfig() {
- const wsUrl = document.getElementById("wsUrl").value.trim();
- const sipDomain = document.getElementById("sipDomain").value.trim();
- const username = document.getElementById("username").value.trim();
- const password = document.getElementById("password").value;
- const registrarServer = document.getElementById("registrarServer").value.trim();
- const realm = document.getElementById("realm").value.trim();
- if (!wsUrl || !sipDomain || !username || !password || !registrarServer || !realm) {
- throw new Error("WSS、SIP 域名、分机号、密码、Registrar、Realm 都不能为空");
- }
- const socket = new JsSIP.WebSocketInterface(wsUrl);
- const configuration = {
- sockets: [socket],
- uri: "sip:" + username + "@" + sipDomain,
- authorization_user: username,
- password: password,
- registrar_server: registrarServer,
- realm: realm,
- register: true,
- session_timers: false
- };
- return configuration;
- }
- function bindUAEvents(instance) {
- instance.on("connecting", function(data) {
- setStatus("正在连接 WSS...");
- log("[SIP] connecting", data);
- });
- instance.on("connected", function(data) {
- setStatus("WSS 已连接");
- log("[SIP] connected", data);
- });
- instance.on("disconnected", function(data) {
- setStatus("WSS 已断开", "err");
- log("[SIP] disconnected", {
- code: data && data.code,
- reason: data && data.reason
- });
- });
- instance.on("registered", function(data) {
- setStatus("注册成功", "ok");
- log("[SIP] 注册成功", data);
- });
- instance.on("unregistered", function(data) {
- setStatus("已注销");
- log("[SIP] unregistered", data);
- });
- instance.on("registrationFailed", function(data) {
- setStatus("注册失败", "err");
- log("[SIP] 注册失败", {
- cause: data && data.cause,
- status_code: data && data.response && data.response.status_code,
- reason_phrase: data && data.response && data.response.reason_phrase
- });
- });
- instance.on("newRTCSession", function(data) {
- log("[SIP] newRTCSession", {
- direction: data && data.session && data.session.direction
- });
- });
- }
- document.getElementById("startBtn").addEventListener("click", function() {
- try {
- if (!jssipReady || !window.JsSIP) {
- throw new Error("JsSIP 库还没有加载成功");
- }
- stopUA();
- const configuration = buildConfig();
- log("准备启动 JsSIP", {
- sockets: configuration.sockets.map(function(item) { return item.url; }),
- uri: configuration.uri,
- authorization_user: configuration.authorization_user,
- registrar_server: configuration.registrar_server,
- realm: configuration.realm,
- register: configuration.register
- });
- ua = new JsSIP.UA(configuration);
- bindUAEvents(ua);
- ua.start();
- setStatus("已启动,等待连接...");
- } catch (e) {
- setStatus("启动失败", "err");
- log("启动异常", e.message || String(e));
- }
- });
- document.getElementById("stopBtn").addEventListener("click", function() {
- stopUA();
- });
- document.getElementById("clearBtn").addEventListener("click", function() {
- document.getElementById("log").textContent = "";
- });
- ensureJsSIPLoaded();
- </script>
- </body>
- </html>
|