@16x/webphone-sdk 3.1.9 → 3.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +6 -1
- package/dist/CCBarClient-B7SRICz8.cjs +1 -0
- package/dist/{CCBarClient-CfHT0tl2.js → CCBarClient-Dmw3T0lF.js} +189 -120
- package/dist/{Diagnostics-CfbmMp-b.js → Diagnostics-BLHANihC.js} +1 -1
- package/dist/Diagnostics-Dmhx4niF.cjs +1 -0
- package/dist/core/CCBarClient.d.ts +5 -1
- package/dist/diagnostics/index.cjs +1 -1
- package/dist/diagnostics/index.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +3 -3
- package/dist/index.umd.js +17 -17
- package/dist/legacy/index.cjs +1 -1
- package/dist/legacy/index.js +102 -131
- package/dist/legacy/legacyAes.d.ts +4 -26
- package/dist/legacy/legacySessionProvider.d.ts +8 -4
- package/dist/version.d.ts +1 -1
- package/package.json +109 -109
- package/dist/CCBarClient-B6WqgloY.cjs +0 -1
- package/dist/Diagnostics-DkKlZQnY.cjs +0 -1
package/dist/legacy/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../SharedWorkerProtocol-39dch6xL.cjs"),t=require("../CCBarClient-B6WqgloY.cjs");require("../createJsSipFactory-Dr8HbLl-.cjs");var n=class extends Error{code=`LEGACY_METHOD_DEPRECATED`;constructor(e,t){super(`${e} 已废弃:${t}`),this.name=`DeprecatedError`}},r=class{client;warnedMethods=new Set;unsubscribeIncoming;currentCall;constructor(e){this.client=new t.t(e),this.unsubscribeIncoming=this.client.on(`call.incoming`,({callId:e})=>{this.currentCall=this.client.getCalls().find(t=>t.id===e)})}getToken(...e){return this.warn(`getToken`,`请改用 client.connect()`),this.client.connect()}getAccount(...e){return this.warn(`getAccount`,`请改用 client.connect()`),this.client.connect()}login(...e){return this.warn(`login`,`请改用 client.connect()`),this.client.connect()}async call(e,...t){this.warn(`call`,`请改用 client.dial({ destination })`);let n=await this.client.dial({destination:String(e)});return this.currentCall=n,n}async insideCall(e,...t){this.warn(`insideCall`,`请改用 client.dial({ destination, type: 'extension' })`);let n=await this.client.dial({destination:String(e),type:`extension`});return this.currentCall=n,n}answer(...e){this.warn(`answer`,`请改用 call.answer()`);let t=this.requireCurrentCall();return this.client.answer(t.id)}async hangup(...e){this.warn(`hangup`,`请改用 call.hangup()`);let t=this.requireCurrentCall();try{await t.hangup()}finally{this.currentCall===t&&(this.currentCall=void 0)}}holdCall(...e){return this.warn(`holdCall`,`请改用 call.hold()`),this.requireCurrentCall().hold()}unholdCall(...e){return this.warn(`unholdCall`,`请改用 call.resume()`),this.requireCurrentCall().resume()}transSo(e,...t){return this.warn(`transSo`,`请改用 call.transfer({ target, type: 'blind' })`),this.requireCurrentCall().transfer({target:String(e),type:`blind`})}async signOut(...e){this.warn(`signOut`,`请改用 client.disconnect() 和 client.dispose()`);let t;try{await this.client.disconnect()}catch(e){t=e}try{await this.client.dispose()}catch(e){t??=e}if(this.unsubscribeIncoming(),this.currentCall=void 0,t!==void 0)throw t}setId(...e){return this.warn(`setId`,`请改用 client.setAgentStatus('available')`),this.client.setAgentStatus(`available`)}setBu(...e){throw this.warn(`setBu`,`busy由通话状态或服务端状态策略控制,浏览器不得伪造`),new n(`setBu()`,`busy由通话状态或服务端状态策略控制,浏览器不得伪造`)}setRe(...e){return this.warn(`setRe`,`请改用 client.setAgentStatus('break')`),this.client.setAgentStatus(`break`)}requireCurrentCall(){let t=this.client.getActiveCall();if(t!==void 0&&(this.currentCall=t),this.currentCall===void 0)throw new e.i(`CALL_NOT_CONNECTED`,`call`,!1);return this.currentCall}warn(e,t){i()&&!this.warnedMethods.has(e)&&(this.warnedMethods.add(e),console.warn(`[CCBarSDK] ${e}() 已废弃。${t}`))}};function i(){return!1}var a=`q7X4p6MvK1z8Lb3A`,o=`W9e2T4mN0aQ7Ru6C`;async function s(t,n={}){let r=String(t??``).replace(/\s+/g,``);if(!r)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`解密的密文为空:坐席账号里没有 password/registerPassword`});let i=n.subtle??globalThis.crypto?.subtle;if(i===void 0)throw new e.i(`CONFIG_INVALID`,`configuration`,!1,{cause:`需要 WebCrypto 才能解 SIP 密码:请在安全上下文(https / localhost)或 Node 18+ 里运行`});let s;try{let e=atob(r);s=new Uint8Array(new ArrayBuffer(e.length));for(let t=0;t<e.length;t+=1)s[t]=e.charCodeAt(t)}catch{throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`密文不是合法的 Base64:确认取的是 password/registerPassword 原值,没有被截断或转义`})}let l=await i.importKey(`raw`,c(n.key??a),`AES-CBC`,!1,[`decrypt`]);try{let e=await i.decrypt({name:`AES-CBC`,iv:c(n.iv??o)},l,s);return new TextDecoder(`utf-8`).decode(e).trim()}catch(t){throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`SIP 密码解密失败(检查 key/iv 与该环境是否一致):${t instanceof Error?t.message:String(t)}`})}}function c(e){let t=new TextEncoder().encode(e),n=new Uint8Array(new ArrayBuffer(t.byteLength));return n.set(t),n}var l=`/openapi/token/v1`,u=`/seat/account/get`,d=`/seats/set-status`,f=`/api/fs/sip-ws`,p=7443,m=3478,h=600,g=600,_=180,v=60,y=5e3,b=2e4,x=[`outbound`,`inbound`,`mute`,`dtmf`,`hold`,`blind_transfer`],S={available:{status:`Available`,reason:`空闲`},break:{status:`On Break`,reason:`休息`},offline:{status:`Logged Out`,reason:``}};function C(t){let n=w(t.host),r=T(t.pathPrefix??l),i=`${n}${r}${E(t.accountPath??u)}`,a=`${n}${r}${E(t.statusPath??d)}`,o=E(t.sipWsPath??f),c={...t.aesKey?{key:t.aesKey}:{},...t.aesIv?{iv:t.aesIv}:{}},b=Math.max(0,t.refreshBufferSeconds??_),C=t.fetchImpl??globalThis.fetch,j,M,N=``;async function P(){if(t.getToken!==void 0)return t.getToken();if(t.tokenUrl!==void 0){let n=t.tokenMethod??`POST`,r={method:n,headers:{Accept:`application/json`,...t.tokenHeaders??{}},credentials:`include`};n===`POST`&&(r.headers={"Content-Type":`application/json`,...r.headers},r.body=JSON.stringify(t.tokenBody??{}));let i=await A(C,t.tokenUrl,r,`取 token`),a=await i.text();try{return JSON.parse(a)}catch{throw new e.i(`AUTH_TOKEN_UNAVAILABLE`,`auth`,!0,{status:i.status,cause:`取 token 的接口返回了非 JSON 响应(HTTP ${i.status}):${a.trim().slice(0,120)}`})}}throw new e.i(`CONFIG_INVALID`,`configuration`,!1,{cause:`createLegacySessionProvider 需要 getToken 或 tokenUrl;坐席状态也可以直接用会话软电话地址里的 token(setAgentStatus 的 context.wssUrl),但这次调用没有会话可用`})}async function F(){if(j&&j.expiresAtMs-Date.now()>y)return j.token;let t;try{t=await P()}catch(t){throw t instanceof e.i?t:new e.i(`AUTH_TOKEN_UNAVAILABLE`,`auth`,!0,{cause:t})}let n=k(t);if(!n.token)throw new e.i(`AUTH_TOKEN_UNAVAILABLE`,`auth`,!0,{cause:`取 token 的返回里没有 token(支持 {token}、{accessToken}、{data:{token}} 或裸字符串)`});let r=O(n.expires,3600);return j={token:n.token,expiresAtMs:Date.now()+r*1e3},j.token}function I(e){if(!e)return``;try{return String(new URL(e).searchParams.get(`token`)??``).trim()}catch{return``}}async function L(e){let t=I(e?.wssUrl);return t?(N=t,t):N||F()}async function R(t){let n=t||await F(),r=await A(C,i,{method:`POST`,headers:{Authorization:n,"Content-Type":`application/json`,Accept:`application/json`},body:`{}`},`取坐席账号`),a=await r.text(),o;try{o=JSON.parse(a)}catch{throw new e.i(`LEGACY_PLATFORM_UNREACHABLE`,`network`,!0,{status:r.status,cause:`${i} 返回了非 JSON 响应(HTTP ${r.status});请确认 host 填的是接口网关(不是文档站)`})}let s=Number(o.code??NaN);if(!r.ok||s!==0)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,s===50,{status:r.status,serverCode:Number.isFinite(s)?String(s):void 0,cause:o.message||`取坐席账号失败(HTTP ${r.status})`});if(!o.data)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`坐席账号接口没有返回 data`});return M=o.data,M}let z=e=>s(e,c);function B(r,i){let a=Number(r.wssPort)||p,s=String(r.domain??``).trim(),c=String(t.sipWsUrl??``).trim(),l;if(c)l=new URL(c,n),l.protocol===`http:`&&(l.protocol=`ws:`),l.protocol===`https:`&&(l.protocol=`wss:`);else{if(!s)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`坐席账号里没有 domain,无法拼软电话地址;可用 sipWsUrl 显式指定`});let t=a===443?``:`:${a}`;l=new URL(`wss://${s}${t}${o}`)}return(t.attachTokenToWss??!0)&&i&&l.searchParams.set(`token`,i),l.toString()}function V(e){let t=(Array.isArray(e.iceServers)?e.iceServers:[]).map(e=>{let t=(Array.isArray(e?.urls)?e.urls:typeof e?.urls==`string`?[e.urls]:[]).map(e=>String(e??``).trim()).filter(Boolean);if(t.length!==0)return{urls:t,...e?.username?{username:String(e.username)}:{},...e?.credential?{credential:String(e.credential)}:{}}}).filter(e=>e!==void 0);if(t.length>0)return t;let n=String(e.turnIp??``).trim();return n?[{urls:[`stun:${n}:${Number(e.turnPort)||m}`]}]:[]}async function H(){let r=await F(),i=await R(),a=String(i.username??i.account??``).trim();if(!a)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`坐席账号里没有 username`});let o=String(i.registerPassword??i.password??``),s=o?await z(o):``;if(!s)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`坐席账号里没有 password/registerPassword,或解密后为空`});let c=O(i.expiresIn??i.expires_in,g),l=Math.max(0,Math.round((j.expiresAtMs-Date.now())/1e3)),u=Math.max(v,Math.min(l||c,c)-b),d=String(i.domain??``).trim()||D(n),f=B(i,r);return r&&(N=r),{sessionId:`legacy-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`,expiresAt:Math.floor(Date.now()/1e3)+u,agent:{id:a,externalUserId:a,displayName:a,extension:a,status:`Available`},sip:{uri:`sip:${a}@${d}`,registrar:d,registerTicket:s,registerExpires:Number(t.registerExpires)>0?Number(t.registerExpires):h,ticketExpiresIn:u},transport:{wssUrl:f,ticket:``,ticketExpiresIn:u},iceServers:V(i),policy:{maxConcurrentCalls:Number(t.maxConcurrentCalls)>0?Number(t.maxConcurrentCalls):2,incomingEnabled:t.incomingEnabled??!0,mobileIncomingEnabled:t.mobileIncomingEnabled??!0,backgroundCallingSupported:!1},capabilities:[...t.capabilities??x]}}return{createSession:H,refreshSession:H,setAgentStatus:async({status:t,reason:n},r)=>{let i=await L(r),o=M??await R(i),s=String(o.username??o.account??``).trim();if(!s)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`坐席账号里没有 username`});let c=S[t],l=await A(C,a,{method:`POST`,headers:{Authorization:i,"Content-Type":`application/json`,Accept:`application/json`},body:JSON.stringify({extension:s,status:c.status,reason:n||c.reason})},`设置坐席状态`),u=await l.text(),d;try{d=JSON.parse(u)}catch{throw new e.i(`LEGACY_PLATFORM_UNREACHABLE`,`network`,!0,{status:l.status,cause:`${a} 返回了非 JSON 响应(HTTP ${l.status})`})}let f=Number(d.code??NaN);if(!l.ok||f!==0)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,f===50,{status:l.status,serverCode:Number.isFinite(f)?String(f):void 0,cause:d.message||`设置坐席状态失败(HTTP ${l.status})`})},invalidateToken:()=>{j=void 0,N=``},getSeatAccount:async()=>M??R()}}function w(t){let n=String(t??``).trim().replace(/\/+$/,``);if(!n)throw new e.i(`CONFIG_INVALID`,`configuration`,!1,{cause:`createLegacySessionProvider 需要 host`});return/^https?:\/\//i.test(n)?n:`https://${n}`}function T(e){let t=String(e??``).trim();return!t||t===`/`?``:`/${t.replace(/^\/+|\/+$/g,``)}`}function E(e){let t=String(e??``).trim();return t.startsWith(`/`)?t:`/${t}`}function D(e){try{return new URL(e).hostname}catch{return``}}function O(e,t){let n=Number(e);return!Number.isFinite(n)||n<=0?t:(n>86400&&(n/=1e3),Math.min(Math.max(Math.floor(n),v),86400))}function k(e){if(typeof e==`string`)return{token:e.trim()};let t=e??{},n=typeof t.data==`object`&&t.data!==null?t.data:void 0;for(let e of[t,n]){if(e===void 0)continue;let t=e.token??e.accessToken;if(typeof t==`string`&&t.trim()){let n=Number(e.expires??e.expiresIn??e.expires_at);return{token:t.trim(),...Number.isFinite(n)&&n>0?{expires:n}:{}}}}return{token:``}}async function A(t,n,r,i){let a=new AbortController,o=setTimeout(()=>a.abort(),b);try{return await t(n,{...r,signal:a.signal})}catch(t){let r=a.signal.aborted;throw new e.i(r?`NETWORK_TIMEOUT`:`LEGACY_PLATFORM_UNREACHABLE`,`network`,!0,{cause:r?`${i}超时(${b/1e3} 秒):POST ${n}`:`${i}失败:无法请求 ${n}(${t instanceof Error?t.message:String(t)})`})}finally{clearTimeout(o)}}var j=`0.1.0`;typeof window<`u`&&(window.CCBarSDK=r),exports.CCBarSDK=r,exports.DeprecatedError=n,exports.createLegacySessionProvider=C,exports.decryptSipPassword=s,exports.legacyVersion=j;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../SharedWorkerProtocol-39dch6xL.cjs"),t=require("../CCBarClient-B7SRICz8.cjs");require("../createJsSipFactory-Dr8HbLl-.cjs");var n=class extends Error{code=`LEGACY_METHOD_DEPRECATED`;constructor(e,t){super(`${e} 已废弃:${t}`),this.name=`DeprecatedError`}},r=class{client;warnedMethods=new Set;unsubscribeIncoming;currentCall;constructor(e){this.client=new t.t(e),this.unsubscribeIncoming=this.client.on(`call.incoming`,({callId:e})=>{this.currentCall=this.client.getCalls().find(t=>t.id===e)})}getToken(...e){return this.warn(`getToken`,`请改用 client.connect()`),this.client.connect()}getAccount(...e){return this.warn(`getAccount`,`请改用 client.connect()`),this.client.connect()}login(...e){return this.warn(`login`,`请改用 client.connect()`),this.client.connect()}async call(e,...t){this.warn(`call`,`请改用 client.dial({ destination })`);let n=await this.client.dial({destination:String(e)});return this.currentCall=n,n}async insideCall(e,...t){this.warn(`insideCall`,`请改用 client.dial({ destination, type: 'extension' })`);let n=await this.client.dial({destination:String(e),type:`extension`});return this.currentCall=n,n}answer(...e){this.warn(`answer`,`请改用 call.answer()`);let t=this.requireCurrentCall();return this.client.answer(t.id)}async hangup(...e){this.warn(`hangup`,`请改用 call.hangup()`);let t=this.requireCurrentCall();try{await t.hangup()}finally{this.currentCall===t&&(this.currentCall=void 0)}}holdCall(...e){return this.warn(`holdCall`,`请改用 call.hold()`),this.requireCurrentCall().hold()}unholdCall(...e){return this.warn(`unholdCall`,`请改用 call.resume()`),this.requireCurrentCall().resume()}transSo(e,...t){return this.warn(`transSo`,`请改用 call.transfer({ target, type: 'blind' })`),this.requireCurrentCall().transfer({target:String(e),type:`blind`})}async signOut(...e){this.warn(`signOut`,`请改用 client.disconnect() 和 client.dispose()`);let t;try{await this.client.disconnect()}catch(e){t=e}try{await this.client.dispose()}catch(e){t??=e}if(this.unsubscribeIncoming(),this.currentCall=void 0,t!==void 0)throw t}setId(...e){return this.warn(`setId`,`请改用 client.setAgentStatus('available')`),this.client.setAgentStatus(`available`)}setBu(...e){throw this.warn(`setBu`,`busy由通话状态或服务端状态策略控制,浏览器不得伪造`),new n(`setBu()`,`busy由通话状态或服务端状态策略控制,浏览器不得伪造`)}setRe(...e){return this.warn(`setRe`,`请改用 client.setAgentStatus('break')`),this.client.setAgentStatus(`break`)}requireCurrentCall(){let t=this.client.getActiveCall();if(t!==void 0&&(this.currentCall=t),this.currentCall===void 0)throw new e.i(`CALL_NOT_CONNECTED`,`call`,!1);return this.currentCall}warn(e,t){i()&&!this.warnedMethods.has(e)&&(this.warnedMethods.add(e),console.warn(`[CCBarSDK] ${e}() 已废弃。${t}`))}};function i(){return!1}var a=`/openapi/token/v1`,o=`/seat/account/get`,s=`/seats/set-status`,c=3478,l=600,u=600,d=180,f=60,p=5e3,m=2e4,h=[`outbound`,`inbound`,`mute`,`dtmf`,`hold`,`blind_transfer`],g={available:{status:`Available`,reason:`空闲`},break:{status:`On Break`,reason:`休息`},offline:{status:`Logged Out`,reason:``}};function _(n){let r=v(n.host),i=y(n.pathPrefix??a),m=`${r}${i}${b(n.accountPath??o)}`,_=`${r}${i}${b(n.statusPath??s)}`,T={...n.aesKey?{key:n.aesKey}:{},...n.aesIv?{iv:n.aesIv}:{}},E=Math.max(0,n.refreshBufferSeconds??d),D=n.fetchImpl??globalThis.fetch,O,k,A=``;async function j(){if(n.getToken!==void 0)return n.getToken();if(n.tokenUrl!==void 0){let t=n.tokenMethod??`POST`,r={method:t,headers:{Accept:`application/json`,...n.tokenHeaders??{}},credentials:`include`};t===`POST`&&(r.headers={"Content-Type":`application/json`,...r.headers},r.body=JSON.stringify(n.tokenBody??{}));let i=await w(D,n.tokenUrl,r,`取 token`),a=await i.text();try{return JSON.parse(a)}catch{throw new e.i(`AUTH_TOKEN_UNAVAILABLE`,`auth`,!0,{status:i.status,cause:`取 token 的接口返回了非 JSON 响应(HTTP ${i.status}):${a.trim().slice(0,120)}`})}}throw new e.i(`CONFIG_INVALID`,`configuration`,!1,{cause:`createLegacySessionProvider 需要 getToken 或 tokenUrl;坐席状态也可以直接用会话软电话地址里的 token(setAgentStatus 的 context.wssUrl),但这次调用没有会话可用`})}async function M(){if(O&&O.expiresAtMs-Date.now()>p)return O.token;let t;try{t=await j()}catch(t){throw t instanceof e.i?t:new e.i(`AUTH_TOKEN_UNAVAILABLE`,`auth`,!0,{cause:t})}let n=C(t);if(!n.token)throw new e.i(`AUTH_TOKEN_UNAVAILABLE`,`auth`,!0,{cause:`取 token 的返回里没有 token(支持 {token}、{accessToken}、{data:{token}} 或裸字符串)`});let r=S(n.expires,3600);return O={token:n.token,expiresAtMs:Date.now()+r*1e3},O.token}function N(e){if(!e)return``;try{return String(new URL(e).searchParams.get(`token`)??``).trim()}catch{return``}}async function P(e){let t=N(e?.wssUrl);return t?(A=t,t):A||M()}async function F(t){let n=t||await M(),r=await w(D,m,{method:`POST`,headers:{Authorization:n,"Content-Type":`application/json`,Accept:`application/json`},body:`{}`},`取坐席账号`),i=await r.text(),a;try{a=JSON.parse(i)}catch{throw new e.i(`LEGACY_PLATFORM_UNREACHABLE`,`network`,!0,{status:r.status,cause:`${m} 返回了非 JSON 响应(HTTP ${r.status});请确认 host 填的是接口网关(不是文档站)`})}let o=Number(a.code??NaN);if(!r.ok||o!==0)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,o===50,{status:r.status,serverCode:Number.isFinite(o)?String(o):void 0,cause:a.message||`取坐席账号失败(HTTP ${r.status})`});if(!a.data)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`坐席账号接口没有返回 data`});return k=a.data,k}let I=e=>t.i(e,T);function L(t){let r=String(n.sipWsUrl??``).trim();if(!r)throw new e.i(`CONFIG_INVALID`,`configuration`,!1,{cause:`需要 sipWsUrl:软电话 WSS 地址由接入方提供(wss:// 或 ws:// 开头的完整地址)`});let i;try{i=new URL(r)}catch{throw new e.i(`CONFIG_INVALID`,`configuration`,!1,{cause:`sipWsUrl 不是完整地址(需要 wss:// 或 ws:// 开头):${r}`})}if(i.protocol!==`wss:`&&i.protocol!==`ws:`)throw new e.i(`CONFIG_INVALID`,`configuration`,!1,{cause:`sipWsUrl 需要 wss:// 或 ws:// 开头:${r}`});return(n.attachTokenToWss??!0)&&t&&i.searchParams.set(`token`,t),i.toString()}function R(e){let t=(Array.isArray(e.iceServers)?e.iceServers:[]).map(e=>{let t=(Array.isArray(e?.urls)?e.urls:typeof e?.urls==`string`?[e.urls]:[]).map(e=>String(e??``).trim()).filter(Boolean);if(t.length!==0)return{urls:t,...e?.username?{username:String(e.username)}:{},...e?.credential?{credential:String(e.credential)}:{}}}).filter(e=>e!==void 0);if(t.length>0)return t;let n=String(e.turnIp??``).trim();return n?[{urls:[`stun:${n}:${Number(e.turnPort)||c}`]}]:[]}async function z(){let t=await M(),i=await F(),a=String(i.username??i.account??``).trim();if(!a)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`坐席账号里没有 username`});let o=String(i.registerPassword??i.password??``),s=o?await I(o):``;if(!s)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`坐席账号里没有 password/registerPassword,或解密后为空`});let c=S(i.expiresIn??i.expires_in,u),d=Math.max(0,Math.round((O.expiresAtMs-Date.now())/1e3)),p=Math.max(f,Math.min(d||c,c)-E),m=String(i.domain??``).trim()||x(r),g=L(t);return t&&(A=t),{sessionId:`legacy-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`,expiresAt:Math.floor(Date.now()/1e3)+p,agent:{id:a,externalUserId:a,displayName:a,extension:a,status:`Available`},sip:{uri:`sip:${a}@${m}`,registrar:m,registerTicket:s,registerExpires:Number(n.registerExpires)>0?Number(n.registerExpires):l,ticketExpiresIn:p},transport:{wssUrl:g,ticket:``,ticketExpiresIn:p},iceServers:R(i),policy:{maxConcurrentCalls:Number(n.maxConcurrentCalls)>0?Number(n.maxConcurrentCalls):2,incomingEnabled:n.incomingEnabled??!0,mobileIncomingEnabled:n.mobileIncomingEnabled??!0,backgroundCallingSupported:!1},capabilities:[...n.capabilities??h]}}return{createSession:z,refreshSession:z,setAgentStatus:async({status:t,reason:n},r)=>{let i=await P(r),a=k??await F(i),o=String(a.username??a.account??``).trim();if(!o)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,!1,{cause:`坐席账号里没有 username`});let s=g[t],c=await w(D,_,{method:`POST`,headers:{Authorization:i,"Content-Type":`application/json`,Accept:`application/json`},body:JSON.stringify({extension:o,status:s.status,reason:n||s.reason})},`设置坐席状态`),l=await c.text(),u;try{u=JSON.parse(l)}catch{throw new e.i(`LEGACY_PLATFORM_UNREACHABLE`,`network`,!0,{status:c.status,cause:`${_} 返回了非 JSON 响应(HTTP ${c.status})`})}let d=Number(u.code??NaN);if(!c.ok||d!==0)throw new e.i(`LEGACY_PLATFORM_REJECTED`,`auth`,d===50,{status:c.status,serverCode:Number.isFinite(d)?String(d):void 0,cause:u.message||`设置坐席状态失败(HTTP ${c.status})`})},invalidateToken:()=>{O=void 0,A=``},getSeatAccount:async()=>k??F()}}function v(t){let n=String(t??``).trim().replace(/\/+$/,``);if(!n)throw new e.i(`CONFIG_INVALID`,`configuration`,!1,{cause:`createLegacySessionProvider 需要 host`});return/^https?:\/\//i.test(n)?n:`https://${n}`}function y(e){let t=String(e??``).trim();return!t||t===`/`?``:`/${t.replace(/^\/+|\/+$/g,``)}`}function b(e){let t=String(e??``).trim();return t.startsWith(`/`)?t:`/${t}`}function x(e){try{return new URL(e).hostname}catch{return``}}function S(e,t){let n=Number(e);return!Number.isFinite(n)||n<=0?t:(n>86400&&(n/=1e3),Math.min(Math.max(Math.floor(n),f),86400))}function C(e){if(typeof e==`string`)return{token:e.trim()};let t=e??{},n=typeof t.data==`object`&&t.data!==null?t.data:void 0;for(let e of[t,n]){if(e===void 0)continue;let t=e.token??e.accessToken;if(typeof t==`string`&&t.trim()){let n=Number(e.expires??e.expiresIn??e.expires_at);return{token:t.trim(),...Number.isFinite(n)&&n>0?{expires:n}:{}}}}return{token:``}}async function w(t,n,r,i){let a=new AbortController,o=setTimeout(()=>a.abort(),m);try{return await t(n,{...r,signal:a.signal})}catch(t){let r=a.signal.aborted;throw new e.i(r?`NETWORK_TIMEOUT`:`LEGACY_PLATFORM_UNREACHABLE`,`network`,!0,{cause:r?`${i}超时(${m/1e3} 秒):POST ${n}`:`${i}失败:无法请求 ${n}(${t instanceof Error?t.message:String(t)})`})}finally{clearTimeout(o)}}var T=`0.1.0`;typeof window<`u`&&(window.CCBarSDK=r),exports.CCBarSDK=r,exports.DeprecatedError=n,exports.createLegacySessionProvider=_,exports.decryptSipPassword=t.i,exports.legacyVersion=T;
|
package/dist/legacy/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { i as e } from "../SharedWorkerProtocol-DKVQ5-po.js";
|
|
2
|
-
import { t } from "../CCBarClient-
|
|
2
|
+
import { i as t, t as n } from "../CCBarClient-Dmw3T0lF.js";
|
|
3
3
|
//#region src/legacy/CCBarSDK.ts
|
|
4
|
-
var
|
|
4
|
+
var r = class extends Error {
|
|
5
5
|
code = "LEGACY_METHOD_DEPRECATED";
|
|
6
6
|
constructor(e, t) {
|
|
7
7
|
super(`${e} 已废弃:${t}`), this.name = "DeprecatedError";
|
|
8
8
|
}
|
|
9
|
-
},
|
|
9
|
+
}, i = class {
|
|
10
10
|
client;
|
|
11
11
|
warnedMethods = /* @__PURE__ */ new Set();
|
|
12
12
|
unsubscribeIncoming;
|
|
13
13
|
currentCall;
|
|
14
14
|
constructor(e) {
|
|
15
|
-
this.client = new
|
|
15
|
+
this.client = new n(e), this.unsubscribeIncoming = this.client.on("call.incoming", ({ callId: e }) => {
|
|
16
16
|
this.currentCall = this.client.getCalls().find((t) => t.id === e);
|
|
17
17
|
});
|
|
18
18
|
}
|
|
@@ -83,7 +83,7 @@ var n = class extends Error {
|
|
|
83
83
|
return this.warn("setId", "请改用 client.setAgentStatus('available')"), this.client.setAgentStatus("available");
|
|
84
84
|
}
|
|
85
85
|
setBu(...e) {
|
|
86
|
-
throw this.warn("setBu", "busy由通话状态或服务端状态策略控制,浏览器不得伪造"), new
|
|
86
|
+
throw this.warn("setBu", "busy由通话状态或服务端状态策略控制,浏览器不得伪造"), new r("setBu()", "busy由通话状态或服务端状态策略控制,浏览器不得伪造");
|
|
87
87
|
}
|
|
88
88
|
setRe(...e) {
|
|
89
89
|
return this.warn("setRe", "请改用 client.setAgentStatus('break')"), this.client.setAgentStatus("break");
|
|
@@ -94,53 +94,22 @@ var n = class extends Error {
|
|
|
94
94
|
return this.currentCall;
|
|
95
95
|
}
|
|
96
96
|
warn(e, t) {
|
|
97
|
-
|
|
97
|
+
a() && !this.warnedMethods.has(e) && (this.warnedMethods.add(e), console.warn(`[CCBarSDK] ${e}() 已废弃。${t}`));
|
|
98
98
|
}
|
|
99
99
|
};
|
|
100
|
-
function
|
|
100
|
+
function a() {
|
|
101
101
|
return !1;
|
|
102
102
|
}
|
|
103
103
|
//#endregion
|
|
104
|
-
//#region src/legacy/legacyAes.ts
|
|
105
|
-
var a = "q7X4p6MvK1z8Lb3A", o = "W9e2T4mN0aQ7Ru6C";
|
|
106
|
-
async function s(t, n = {}) {
|
|
107
|
-
let r = String(t ?? "").replace(/\s+/g, "");
|
|
108
|
-
if (!r) throw new e("LEGACY_PLATFORM_REJECTED", "auth", !1, { cause: "解密的密文为空:坐席账号里没有 password/registerPassword" });
|
|
109
|
-
let i = n.subtle ?? globalThis.crypto?.subtle;
|
|
110
|
-
if (i === void 0) throw new e("CONFIG_INVALID", "configuration", !1, { cause: "需要 WebCrypto 才能解 SIP 密码:请在安全上下文(https / localhost)或 Node 18+ 里运行" });
|
|
111
|
-
let s;
|
|
112
|
-
try {
|
|
113
|
-
let e = atob(r);
|
|
114
|
-
s = new Uint8Array(new ArrayBuffer(e.length));
|
|
115
|
-
for (let t = 0; t < e.length; t += 1) s[t] = e.charCodeAt(t);
|
|
116
|
-
} catch {
|
|
117
|
-
throw new e("LEGACY_PLATFORM_REJECTED", "auth", !1, { cause: "密文不是合法的 Base64:确认取的是 password/registerPassword 原值,没有被截断或转义" });
|
|
118
|
-
}
|
|
119
|
-
let l = await i.importKey("raw", c(n.key ?? a), "AES-CBC", !1, ["decrypt"]);
|
|
120
|
-
try {
|
|
121
|
-
let e = await i.decrypt({
|
|
122
|
-
name: "AES-CBC",
|
|
123
|
-
iv: c(n.iv ?? o)
|
|
124
|
-
}, l, s);
|
|
125
|
-
return new TextDecoder("utf-8").decode(e).trim();
|
|
126
|
-
} catch (t) {
|
|
127
|
-
throw new e("LEGACY_PLATFORM_REJECTED", "auth", !1, { cause: `SIP 密码解密失败(检查 key/iv 与该环境是否一致):${t instanceof Error ? t.message : String(t)}` });
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
function c(e) {
|
|
131
|
-
let t = new TextEncoder().encode(e), n = new Uint8Array(new ArrayBuffer(t.byteLength));
|
|
132
|
-
return n.set(t), n;
|
|
133
|
-
}
|
|
134
|
-
//#endregion
|
|
135
104
|
//#region src/legacy/legacySessionProvider.ts
|
|
136
|
-
var
|
|
105
|
+
var o = "/openapi/token/v1", s = "/seat/account/get", c = "/seats/set-status", l = 3478, u = 600, d = 600, f = 180, p = 60, m = 5e3, h = 2e4, g = [
|
|
137
106
|
"outbound",
|
|
138
107
|
"inbound",
|
|
139
108
|
"mute",
|
|
140
109
|
"dtmf",
|
|
141
110
|
"hold",
|
|
142
111
|
"blind_transfer"
|
|
143
|
-
],
|
|
112
|
+
], _ = {
|
|
144
113
|
available: {
|
|
145
114
|
status: "Available",
|
|
146
115
|
reason: "空闲"
|
|
@@ -154,27 +123,27 @@ var l = "/openapi/token/v1", u = "/seat/account/get", d = "/seats/set-status", f
|
|
|
154
123
|
reason: ""
|
|
155
124
|
}
|
|
156
125
|
};
|
|
157
|
-
function
|
|
158
|
-
let
|
|
159
|
-
...
|
|
160
|
-
...
|
|
161
|
-
},
|
|
162
|
-
async function
|
|
163
|
-
if (
|
|
164
|
-
if (
|
|
165
|
-
let
|
|
166
|
-
method:
|
|
126
|
+
function v(n) {
|
|
127
|
+
let r = y(n.host), i = b(n.pathPrefix ?? o), a = `${r}${i}${x(n.accountPath ?? s)}`, h = `${r}${i}${x(n.statusPath ?? c)}`, v = {
|
|
128
|
+
...n.aesKey ? { key: n.aesKey } : {},
|
|
129
|
+
...n.aesIv ? { iv: n.aesIv } : {}
|
|
130
|
+
}, E = Math.max(0, n.refreshBufferSeconds ?? f), D = n.fetchImpl ?? globalThis.fetch, O, k, A = "";
|
|
131
|
+
async function j() {
|
|
132
|
+
if (n.getToken !== void 0) return n.getToken();
|
|
133
|
+
if (n.tokenUrl !== void 0) {
|
|
134
|
+
let t = n.tokenMethod ?? "POST", r = {
|
|
135
|
+
method: t,
|
|
167
136
|
headers: {
|
|
168
137
|
Accept: "application/json",
|
|
169
|
-
...
|
|
138
|
+
...n.tokenHeaders ?? {}
|
|
170
139
|
},
|
|
171
140
|
credentials: "include"
|
|
172
141
|
};
|
|
173
|
-
|
|
142
|
+
t === "POST" && (r.headers = {
|
|
174
143
|
"Content-Type": "application/json",
|
|
175
144
|
...r.headers
|
|
176
|
-
}, r.body = JSON.stringify(
|
|
177
|
-
let i = await
|
|
145
|
+
}, r.body = JSON.stringify(n.tokenBody ?? {}));
|
|
146
|
+
let i = await T(D, n.tokenUrl, r, "取 token"), a = await i.text();
|
|
178
147
|
try {
|
|
179
148
|
return JSON.parse(a);
|
|
180
149
|
} catch {
|
|
@@ -186,23 +155,23 @@ function C(t) {
|
|
|
186
155
|
}
|
|
187
156
|
throw new e("CONFIG_INVALID", "configuration", !1, { cause: "createLegacySessionProvider 需要 getToken 或 tokenUrl;坐席状态也可以直接用会话软电话地址里的 token(setAgentStatus 的 context.wssUrl),但这次调用没有会话可用" });
|
|
188
157
|
}
|
|
189
|
-
async function
|
|
190
|
-
if (
|
|
158
|
+
async function M() {
|
|
159
|
+
if (O && O.expiresAtMs - Date.now() > m) return O.token;
|
|
191
160
|
let t;
|
|
192
161
|
try {
|
|
193
|
-
t = await
|
|
162
|
+
t = await j();
|
|
194
163
|
} catch (t) {
|
|
195
164
|
throw t instanceof e ? t : new e("AUTH_TOKEN_UNAVAILABLE", "auth", !0, { cause: t });
|
|
196
165
|
}
|
|
197
|
-
let n =
|
|
166
|
+
let n = w(t);
|
|
198
167
|
if (!n.token) throw new e("AUTH_TOKEN_UNAVAILABLE", "auth", !0, { cause: "取 token 的返回里没有 token(支持 {token}、{accessToken}、{data:{token}} 或裸字符串)" });
|
|
199
|
-
let r =
|
|
200
|
-
return
|
|
168
|
+
let r = C(n.expires, 3600);
|
|
169
|
+
return O = {
|
|
201
170
|
token: n.token,
|
|
202
171
|
expiresAtMs: Date.now() + r * 1e3
|
|
203
|
-
},
|
|
172
|
+
}, O.token;
|
|
204
173
|
}
|
|
205
|
-
function
|
|
174
|
+
function N(e) {
|
|
206
175
|
if (!e) return "";
|
|
207
176
|
try {
|
|
208
177
|
return String(new URL(e).searchParams.get("token") ?? "").trim();
|
|
@@ -210,12 +179,12 @@ function C(t) {
|
|
|
210
179
|
return "";
|
|
211
180
|
}
|
|
212
181
|
}
|
|
213
|
-
async function
|
|
214
|
-
let t =
|
|
215
|
-
return t ? (
|
|
182
|
+
async function P(e) {
|
|
183
|
+
let t = N(e?.wssUrl);
|
|
184
|
+
return t ? (A = t, t) : A || M();
|
|
216
185
|
}
|
|
217
|
-
async function
|
|
218
|
-
let n = t || await
|
|
186
|
+
async function F(t) {
|
|
187
|
+
let n = t || await M(), r = await T(D, a, {
|
|
219
188
|
method: "POST",
|
|
220
189
|
headers: {
|
|
221
190
|
Authorization: n,
|
|
@@ -223,13 +192,13 @@ function C(t) {
|
|
|
223
192
|
Accept: "application/json"
|
|
224
193
|
},
|
|
225
194
|
body: "{}"
|
|
226
|
-
}, "取坐席账号"),
|
|
195
|
+
}, "取坐席账号"), i = await r.text(), o;
|
|
227
196
|
try {
|
|
228
|
-
o = JSON.parse(
|
|
197
|
+
o = JSON.parse(i);
|
|
229
198
|
} catch {
|
|
230
199
|
throw new e("LEGACY_PLATFORM_UNREACHABLE", "network", !0, {
|
|
231
200
|
status: r.status,
|
|
232
|
-
cause: `${
|
|
201
|
+
cause: `${a} 返回了非 JSON 响应(HTTP ${r.status});请确认 host 填的是接口网关(不是文档站)`
|
|
233
202
|
});
|
|
234
203
|
}
|
|
235
204
|
let s = Number(o.code ?? NaN);
|
|
@@ -239,20 +208,22 @@ function C(t) {
|
|
|
239
208
|
cause: o.message || `取坐席账号失败(HTTP ${r.status})`
|
|
240
209
|
});
|
|
241
210
|
if (!o.data) throw new e("LEGACY_PLATFORM_REJECTED", "auth", !1, { cause: "坐席账号接口没有返回 data" });
|
|
242
|
-
return
|
|
211
|
+
return k = o.data, k;
|
|
243
212
|
}
|
|
244
|
-
let
|
|
245
|
-
function
|
|
246
|
-
let
|
|
247
|
-
if (
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
213
|
+
let I = (e) => t(e, v);
|
|
214
|
+
function L(t) {
|
|
215
|
+
let r = String(n.sipWsUrl ?? "").trim();
|
|
216
|
+
if (!r) throw new e("CONFIG_INVALID", "configuration", !1, { cause: "需要 sipWsUrl:软电话 WSS 地址由接入方提供(wss:// 或 ws:// 开头的完整地址)" });
|
|
217
|
+
let i;
|
|
218
|
+
try {
|
|
219
|
+
i = new URL(r);
|
|
220
|
+
} catch {
|
|
221
|
+
throw new e("CONFIG_INVALID", "configuration", !1, { cause: `sipWsUrl 不是完整地址(需要 wss:// 或 ws:// 开头):${r}` });
|
|
252
222
|
}
|
|
253
|
-
|
|
223
|
+
if (i.protocol !== "wss:" && i.protocol !== "ws:") throw new e("CONFIG_INVALID", "configuration", !1, { cause: `sipWsUrl 需要 wss:// 或 ws:// 开头:${r}` });
|
|
224
|
+
return (n.attachTokenToWss ?? !0) && t && i.searchParams.set("token", t), i.toString();
|
|
254
225
|
}
|
|
255
|
-
function
|
|
226
|
+
function R(e) {
|
|
256
227
|
let t = (Array.isArray(e.iceServers) ? e.iceServers : []).map((e) => {
|
|
257
228
|
let t = (Array.isArray(e?.urls) ? e.urls : typeof e?.urls == "string" ? [e.urls] : []).map((e) => String(e ?? "").trim()).filter(Boolean);
|
|
258
229
|
if (t.length !== 0) return {
|
|
@@ -263,17 +234,17 @@ function C(t) {
|
|
|
263
234
|
}).filter((e) => e !== void 0);
|
|
264
235
|
if (t.length > 0) return t;
|
|
265
236
|
let n = String(e.turnIp ?? "").trim();
|
|
266
|
-
return n ? [{ urls: [`stun:${n}:${Number(e.turnPort) ||
|
|
237
|
+
return n ? [{ urls: [`stun:${n}:${Number(e.turnPort) || l}`] }] : [];
|
|
267
238
|
}
|
|
268
|
-
async function
|
|
269
|
-
let
|
|
239
|
+
async function z() {
|
|
240
|
+
let t = await M(), i = await F(), a = String(i.username ?? i.account ?? "").trim();
|
|
270
241
|
if (!a) throw new e("LEGACY_PLATFORM_REJECTED", "auth", !1, { cause: "坐席账号里没有 username" });
|
|
271
|
-
let o = String(i.registerPassword ?? i.password ?? ""), s = o ? await
|
|
242
|
+
let o = String(i.registerPassword ?? i.password ?? ""), s = o ? await I(o) : "";
|
|
272
243
|
if (!s) throw new e("LEGACY_PLATFORM_REJECTED", "auth", !1, { cause: "坐席账号里没有 password/registerPassword,或解密后为空" });
|
|
273
|
-
let c =
|
|
274
|
-
return
|
|
244
|
+
let c = C(i.expiresIn ?? i.expires_in, d), l = Math.max(0, Math.round((O.expiresAtMs - Date.now()) / 1e3)), f = Math.max(p, Math.min(l || c, c) - E), m = String(i.domain ?? "").trim() || S(r), h = L(t);
|
|
245
|
+
return t && (A = t), {
|
|
275
246
|
sessionId: `legacy-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
276
|
-
expiresAt: Math.floor(Date.now() / 1e3) +
|
|
247
|
+
expiresAt: Math.floor(Date.now() / 1e3) + f,
|
|
277
248
|
agent: {
|
|
278
249
|
id: a,
|
|
279
250
|
externalUserId: a,
|
|
@@ -282,34 +253,34 @@ function C(t) {
|
|
|
282
253
|
status: "Available"
|
|
283
254
|
},
|
|
284
255
|
sip: {
|
|
285
|
-
uri: `sip:${a}@${
|
|
286
|
-
registrar:
|
|
256
|
+
uri: `sip:${a}@${m}`,
|
|
257
|
+
registrar: m,
|
|
287
258
|
registerTicket: s,
|
|
288
|
-
registerExpires: Number(
|
|
289
|
-
ticketExpiresIn:
|
|
259
|
+
registerExpires: Number(n.registerExpires) > 0 ? Number(n.registerExpires) : u,
|
|
260
|
+
ticketExpiresIn: f
|
|
290
261
|
},
|
|
291
262
|
transport: {
|
|
292
|
-
wssUrl:
|
|
263
|
+
wssUrl: h,
|
|
293
264
|
ticket: "",
|
|
294
|
-
ticketExpiresIn:
|
|
265
|
+
ticketExpiresIn: f
|
|
295
266
|
},
|
|
296
|
-
iceServers:
|
|
267
|
+
iceServers: R(i),
|
|
297
268
|
policy: {
|
|
298
|
-
maxConcurrentCalls: Number(
|
|
299
|
-
incomingEnabled:
|
|
300
|
-
mobileIncomingEnabled:
|
|
269
|
+
maxConcurrentCalls: Number(n.maxConcurrentCalls) > 0 ? Number(n.maxConcurrentCalls) : 2,
|
|
270
|
+
incomingEnabled: n.incomingEnabled ?? !0,
|
|
271
|
+
mobileIncomingEnabled: n.mobileIncomingEnabled ?? !0,
|
|
301
272
|
backgroundCallingSupported: !1
|
|
302
273
|
},
|
|
303
|
-
capabilities: [...
|
|
274
|
+
capabilities: [...n.capabilities ?? g]
|
|
304
275
|
};
|
|
305
276
|
}
|
|
306
277
|
return {
|
|
307
|
-
createSession:
|
|
308
|
-
refreshSession:
|
|
278
|
+
createSession: z,
|
|
279
|
+
refreshSession: z,
|
|
309
280
|
setAgentStatus: async ({ status: t, reason: n }, r) => {
|
|
310
|
-
let i = await
|
|
311
|
-
if (!
|
|
312
|
-
let
|
|
281
|
+
let i = await P(r), a = k ?? await F(i), o = String(a.username ?? a.account ?? "").trim();
|
|
282
|
+
if (!o) throw new e("LEGACY_PLATFORM_REJECTED", "auth", !1, { cause: "坐席账号里没有 username" });
|
|
283
|
+
let s = _[t], c = await T(D, h, {
|
|
313
284
|
method: "POST",
|
|
314
285
|
headers: {
|
|
315
286
|
Authorization: i,
|
|
@@ -317,57 +288,57 @@ function C(t) {
|
|
|
317
288
|
Accept: "application/json"
|
|
318
289
|
},
|
|
319
290
|
body: JSON.stringify({
|
|
320
|
-
extension:
|
|
321
|
-
status:
|
|
322
|
-
reason: n ||
|
|
291
|
+
extension: o,
|
|
292
|
+
status: s.status,
|
|
293
|
+
reason: n || s.reason
|
|
323
294
|
})
|
|
324
|
-
}, "设置坐席状态"),
|
|
295
|
+
}, "设置坐席状态"), l = await c.text(), u;
|
|
325
296
|
try {
|
|
326
|
-
|
|
297
|
+
u = JSON.parse(l);
|
|
327
298
|
} catch {
|
|
328
299
|
throw new e("LEGACY_PLATFORM_UNREACHABLE", "network", !0, {
|
|
329
|
-
status:
|
|
330
|
-
cause: `${
|
|
300
|
+
status: c.status,
|
|
301
|
+
cause: `${h} 返回了非 JSON 响应(HTTP ${c.status})`
|
|
331
302
|
});
|
|
332
303
|
}
|
|
333
|
-
let
|
|
334
|
-
if (!
|
|
335
|
-
status:
|
|
336
|
-
serverCode: Number.isFinite(
|
|
337
|
-
cause:
|
|
304
|
+
let d = Number(u.code ?? NaN);
|
|
305
|
+
if (!c.ok || d !== 0) throw new e("LEGACY_PLATFORM_REJECTED", "auth", d === 50, {
|
|
306
|
+
status: c.status,
|
|
307
|
+
serverCode: Number.isFinite(d) ? String(d) : void 0,
|
|
308
|
+
cause: u.message || `设置坐席状态失败(HTTP ${c.status})`
|
|
338
309
|
});
|
|
339
310
|
},
|
|
340
311
|
invalidateToken: () => {
|
|
341
|
-
|
|
312
|
+
O = void 0, A = "";
|
|
342
313
|
},
|
|
343
|
-
getSeatAccount: async () =>
|
|
314
|
+
getSeatAccount: async () => k ?? F()
|
|
344
315
|
};
|
|
345
316
|
}
|
|
346
|
-
function
|
|
317
|
+
function y(t) {
|
|
347
318
|
let n = String(t ?? "").trim().replace(/\/+$/, "");
|
|
348
319
|
if (!n) throw new e("CONFIG_INVALID", "configuration", !1, { cause: "createLegacySessionProvider 需要 host" });
|
|
349
320
|
return /^https?:\/\//i.test(n) ? n : `https://${n}`;
|
|
350
321
|
}
|
|
351
|
-
function
|
|
322
|
+
function b(e) {
|
|
352
323
|
let t = String(e ?? "").trim();
|
|
353
324
|
return !t || t === "/" ? "" : `/${t.replace(/^\/+|\/+$/g, "")}`;
|
|
354
325
|
}
|
|
355
|
-
function
|
|
326
|
+
function x(e) {
|
|
356
327
|
let t = String(e ?? "").trim();
|
|
357
328
|
return t.startsWith("/") ? t : `/${t}`;
|
|
358
329
|
}
|
|
359
|
-
function
|
|
330
|
+
function S(e) {
|
|
360
331
|
try {
|
|
361
332
|
return new URL(e).hostname;
|
|
362
333
|
} catch {
|
|
363
334
|
return "";
|
|
364
335
|
}
|
|
365
336
|
}
|
|
366
|
-
function
|
|
337
|
+
function C(e, t) {
|
|
367
338
|
let n = Number(e);
|
|
368
|
-
return !Number.isFinite(n) || n <= 0 ? t : (n > 86400 && (n /= 1e3), Math.min(Math.max(Math.floor(n),
|
|
339
|
+
return !Number.isFinite(n) || n <= 0 ? t : (n > 86400 && (n /= 1e3), Math.min(Math.max(Math.floor(n), p), 86400));
|
|
369
340
|
}
|
|
370
|
-
function
|
|
341
|
+
function w(e) {
|
|
371
342
|
if (typeof e == "string") return { token: e.trim() };
|
|
372
343
|
let t = e ?? {}, n = typeof t.data == "object" && t.data !== null ? t.data : void 0;
|
|
373
344
|
for (let e of [t, n]) {
|
|
@@ -383,8 +354,8 @@ function k(e) {
|
|
|
383
354
|
}
|
|
384
355
|
return { token: "" };
|
|
385
356
|
}
|
|
386
|
-
async function
|
|
387
|
-
let a = new AbortController(), o = setTimeout(() => a.abort(),
|
|
357
|
+
async function T(t, n, r, i) {
|
|
358
|
+
let a = new AbortController(), o = setTimeout(() => a.abort(), h);
|
|
388
359
|
try {
|
|
389
360
|
return await t(n, {
|
|
390
361
|
...r,
|
|
@@ -392,14 +363,14 @@ async function A(t, n, r, i) {
|
|
|
392
363
|
});
|
|
393
364
|
} catch (t) {
|
|
394
365
|
let r = a.signal.aborted;
|
|
395
|
-
throw new e(r ? "NETWORK_TIMEOUT" : "LEGACY_PLATFORM_UNREACHABLE", "network", !0, { cause: r ? `${i}超时(${
|
|
366
|
+
throw new e(r ? "NETWORK_TIMEOUT" : "LEGACY_PLATFORM_UNREACHABLE", "network", !0, { cause: r ? `${i}超时(${h / 1e3} 秒):POST ${n}` : `${i}失败:无法请求 ${n}(${t instanceof Error ? t.message : String(t)})` });
|
|
396
367
|
} finally {
|
|
397
368
|
clearTimeout(o);
|
|
398
369
|
}
|
|
399
370
|
}
|
|
400
371
|
//#endregion
|
|
401
372
|
//#region src/legacy/index.ts
|
|
402
|
-
var
|
|
403
|
-
typeof window < "u" && (window.CCBarSDK =
|
|
373
|
+
var E = "0.1.0";
|
|
374
|
+
typeof window < "u" && (window.CCBarSDK = i);
|
|
404
375
|
//#endregion
|
|
405
|
-
export {
|
|
376
|
+
export { i as CCBarSDK, r as DeprecatedError, v as createLegacySessionProvider, t as decryptSipPassword, E as legacyVersion };
|
|
@@ -1,29 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* 是 **AES-128-CBC / Pkcs7 的密文,Base64 编码**,需要解密才有明文 SIP 密码。
|
|
2
|
+
* 老平台坐席密码解密的入口(`@16x/webphone-sdk/legacy` 子入口导出 `decryptSipPassword`)。
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* 实现在 `src/crypto/legacySipTicket.ts`:core 的会话入口也要用同一套 AES 参数做兜底
|
|
5
|
+
* (`tryDecryptSipTicket`),所以实现放在两边都能拿到的地方,这里只做转发,行为与以前一致。
|
|
7
6
|
*/
|
|
8
|
-
export
|
|
9
|
-
/** AES key(16 字节,UTF-8),默认用老平台内置值 */
|
|
10
|
-
key?: string;
|
|
11
|
-
/** AES iv(16 字节,UTF-8),默认用老平台内置值 */
|
|
12
|
-
iv?: string;
|
|
13
|
-
/** 解密实现所用的 WebCrypto(测试可注入),默认全局 crypto.subtle */
|
|
14
|
-
subtle?: SubtleCrypto;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* 解出 SIP 密码明文。
|
|
18
|
-
*
|
|
19
|
-
* ```ts
|
|
20
|
-
* import { decryptSipPassword } from '@16x/webphone-sdk/legacy';
|
|
21
|
-
*
|
|
22
|
-
* const res = await fetch(`${host}/openapi/token/v1/seat/account/get`, { method: 'POST', headers: { Authorization: token }, body: '{}' });
|
|
23
|
-
* const { data } = await res.json();
|
|
24
|
-
* const password = await decryptSipPassword(data.password); // 明文 SIP 密码
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* 失败时抛 `CCBarError`:可读原因在 `error.cause` 上(密文为空 / 不是合法 Base64 / 解密失败)。
|
|
28
|
-
*/
|
|
29
|
-
export declare function decryptSipPassword(cipherText: string, options?: DecryptSipPasswordOptions): Promise<string>;
|
|
7
|
+
export { decryptSipPassword, type DecryptSipPasswordOptions } from '../crypto/legacySipTicket.js';
|
|
@@ -15,7 +15,9 @@ export interface LegacySeatAccount {
|
|
|
15
15
|
registerPassword?: string;
|
|
16
16
|
expiresIn?: number;
|
|
17
17
|
expires_in?: number;
|
|
18
|
+
/** SIP 域名:拼 `sip.uri` / `sip.registrar` 用(软电话地址不再从这里拼,见 `sipWsUrl`) */
|
|
18
19
|
domain?: string;
|
|
20
|
+
/** 平台返回的端口字段:SDK 不再读它们(软电话地址由接入方传 `sipWsUrl`) */
|
|
19
21
|
wsPort?: number;
|
|
20
22
|
wssPort?: number;
|
|
21
23
|
turnIp?: string;
|
|
@@ -46,10 +48,12 @@ export interface LegacyPlatformSessionProviderOptions {
|
|
|
46
48
|
accountPath?: string;
|
|
47
49
|
/** 坐席状态路径(相对 pathPrefix),默认 `/seats/set-status` */
|
|
48
50
|
statusPath?: string;
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
/**
|
|
52
|
+
* 软电话 WSS 地址(必填):`wss://` 或 `ws://` 开头的**完整地址**。
|
|
53
|
+
* SDK 只在这个地址上挂 `?token=<fs token>`(见 `attachTokenToWss`),
|
|
54
|
+
* 不再按坐席账号的 domain / wssPort 拼装,也不接受相对路径。
|
|
55
|
+
*/
|
|
56
|
+
sipWsUrl: string;
|
|
53
57
|
/** 是否把 token 挂到 WSS 的 `?token=`,默认 true(旧页面那套不挂时可设 false) */
|
|
54
58
|
attachTokenToWss?: boolean;
|
|
55
59
|
/** AES key / iv(16 字节,UTF-8);默认用平台内置值 */
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "3.1.
|
|
1
|
+
export declare const SDK_VERSION = "3.1.11";
|