{"_id":"@94ai/softphone-sdk-readme","_rev":"5-2f81cc237c6b2e0eb01d9743e4afb289","time":{"created":"2023-05-04T00:59:15.043Z","1.0.0":"2023-05-01T14:44:49.983Z","modified":"2024-05-24T09:11:32.698Z","1.0.1":"2023-05-04T00:59:15.330Z"},"name":"@94ai/softphone-sdk-readme","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.1":{"name":"@94ai/softphone-sdk-readme","version":"1.0.1","description":"94 Intelligent Technology Co., Ltd softphone SDK","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"repository":{"type":"git","url":"https://gitee.com/sdk-demo"},"publishConfig":{"registry":"https://registry.npmjs.org/"},"keywords":["94ai, 94 Intelligent Technology Co., Ltd, softphone SDK"],"author":{"name":"xccjh"},"license":"ISC","gitHead":"aaaf21590d1c12abcc62dcb03aa8e62bf883922d","_id":"@94ai/softphone-sdk-readme@1.0.1","_nodeVersion":"16.19.1","_npmVersion":"8.19.3","dist":{"integrity":"sha512-mYJdDZ5iXiZ0OmQEp/VJuzCbPvTH1Y1kzjeA3TQbJKBq7qtulyTsrn0Vw/ne97ZO7nX4xF4mX/BdegFrztpG3A==","shasum":"8173fdd735797d00689ba4e7cba72e75e6d1b4a9","tarball":"https://registry.npmjs.org/@94ai/softphone-sdk-readme/-/softphone-sdk-readme-1.0.1.tgz","fileCount":5,"unpackedSize":16226,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF1yj/d2i4A1pgBa6MNWfHp4z1kYW1t+cYyJrWiOJm1+AiEA97JRBnzVCxZUWVfK8Bc83b6+vAXTmLyaM9YsoHy1E7g="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkUwNjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrdHA/8CT2Sm9x5GRk2YY5NakNQaLxsrv5+HX9LrmaNwsTERbwoV0Of\r\nS7l00rokoIARpWLccK8IoMIopF1AyAo2tr1RAjiVJQXp9cTaWVULGXXf5qrO\r\nEU/uHecAKee/FV0QGL7eKZ5dkXR4cae9oHqnch5DLdAzXHwf6CEWkqxSdpi9\r\n4FCaD1aIx8gPDjfeNu6vmrC4guuuLzrsk/Q1FKIvnzi+w/9L+bAQX+zXQKyx\r\nNo8Upvz0t2MvG//CT89vwl8DHoXXdPRkh3iBC97a6R/6oXY9bkrTF9ef4ghA\r\nz5MIPcdhyNtenQ0rjYqQjK5A711+6Bb3by6CcQmNh1O772btS1MYYYPP51fn\r\ntTOo+DEd1h5UOEvmGEA2g3KBWhGCz9Gcv9RjHLGjO9x1jRfj0BmgpWgNfJVD\r\nhhFY6JVwWgKLMrlADTLGr0R1YKM8XdoVPMDTf3Ka5XEpFOVcq7VoNiRNj9sm\r\nj+9RRZOvN8bTBYUN8tHqc2AIgfz12nE5oM5w0rkY3IxamLUTP5znVVWOKVnT\r\nSIVhQ+WURsh6r3cneQBHFdnBZp4s/p9WlIGjO6PLQ2qGHLSMpufcIt4Fdwcc\r\n2sqJjwLDoDacCSpKVs8fmsQ4QiRDqkoD0bMxosz5iXUeBH6QBU6srxTTf5xC\r\nVhQkaCB4JpS2yyuILV9AC3jXGSWEhajObNk=\r\n=DdFN\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"94ai","email":"zjh15018707394@gmail.com"},"directories":{},"maintainers":[{"name":"94ai","email":"zjh15018707394@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/softphone-sdk-readme_1.0.1_1683161955123_0.7535555592065375"},"_hasShrinkwrap":false}},"maintainers":[{"email":"liuxiangxiang1992@gmail.com","name":"louislxx"},{"email":"zjh15018707394@gmail.com","name":"nfai"}],"description":"94 Intelligent Technology Co., Ltd softphone SDK","keywords":["94ai, 94 Intelligent Technology Co., Ltd, softphone SDK"],"repository":{"type":"git","url":"https://gitee.com/sdk-demo"},"author":{"name":"xccjh"},"license":"ISC","readme":"# 前言\n\n94ai软电话前端SDK，框架无关（支持vue，react，angular等）\n\n项目参考demo: https://gitee.com/softphone-demo（有权限问题，具体找94智能开发同事拉入团队组织即可）\n\n# 安装\n94智能sdk目前暂不在公网公布sdk源码，如有需要，可以联系94智能开发同事加入团队，具体步骤：\n\n## 获取加入团队邀请链接\n1. 向94智能开发同事申请到【加入到团队的连接】，如：\n   https://account-devops.aliyun.com/account/invite?sign=ab965d478dbed5dad3cc145a5a5b406c&next_url=https%3A%2F%2Fpackages.aliyun.com%3ForgId%3D644f755a97d94d909e43534c\n\n2. 进入上述链接后，进到阿里云登录页\n\n- 如果你是主账号，直接登录即可：\n\n  ![img.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img.png)\n\n- 如果你是RAM子账号，选择下面RAM用户登录：\n\n  ![img_1.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_1.png)\n\n  进入RAM 用户登录页登录即可:\n\n  ![img_2.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_2.png)\n\n## 阿里的数字安全码\n\n登录过程会提示你填写 验证虚拟MFA设备数字安全码\n\n### 1.如果以前使用过阿里云产品并绑定过\n可以直接在【阿里云app】或使用【虚拟MFA验证小程序】获取【数字安全码】填写即可，如下：\n- 下载阿里云app\n\n![1.jpg](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_11.jpg)\n\n- 定位首页的mfa图标\n\n![2.jpg](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_12.jpg)\n\n- 找到对应账号的数字安全码\n\n![3.jpg](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_13.jpg)\n\n### 2.如果以前没有绑定过\n- 如下面选择 虚拟 MFA 设备\n\n  ![img_5.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_5.png)\n\n- 然后在手机安装【阿里云app】或使用【小程序虚拟MFA验证】，然后扫码绑定设备\n\n  ![img_6.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_6.png)\n\n- 在设备添加账号点确定\n\n  ![img_7.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_17.png)\n\n- 之后会每隔一小段时间会刷新获取到最新的【数字安全码】\n\n  ![img_18.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_18.png)\n\n### 3.如果使用小程序\n\n在微信搜索mfa二次验证如下，具体可以百度下：\n\n![20230501-205150.jpg](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/20230501-205150.jpg)\n\n### 4.设置昵称申请加入\n\n登录成功后会提示你加入团队，设置号昵称点加入\n\n![img_4.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_4.png)\n\n![img_7.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_7.png)\n\n## 查看个人账号信息\n\n等待审核通过后，刷新页面，点击进入企业\n\n![img_8.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_8.png)\n\n### 1.选择角色\n\n选择作为研发者，开始工作\n\n![img_9.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_9.png)\n\n### 2.进入制品仓库\n在工作台选择【制品仓库】进入\n\n![Snipaste_2023-05-01_21-22-33.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/Snipaste_2023-05-01_21-22-33.png)\n\n### 3.查看账号密码\n\n选择设置查看个人账号信息\n\n![Snipaste_2023-05-01_21-24-27.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/Snipaste_2023-05-01_21-24-27.png)\n\n![Snipaste_2023-05-01_21-26-20.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/Snipaste_2023-05-01_21-26-20.png)\n\n## 设置私库源\n\n### 1.新建rc文件\n\n在需要使用94智能sdk的项目根目录,新建一个rc文件：\n\n- 如果你使用的npm或pnpm，新建.npmrc，内容如下：\n```hell\n@94ai:registry=https://packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/\n//packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/:username=username\n//packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/:_password=password\n//packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/:always-auth=true\n```\n\n- 如果你使用的yarn1,新建.yarnrc，内容如下：\n```shell\n\"@94ai:registry\" \"https://packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/\"\n\"//packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/:username\" \"username\"\n\"//packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/:_password\" \"password\"\n\"//packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/:always-auth\" true\n```\n\n- 如果你使用的yarn2~3,新建.yarnrc.yml，内容如下：\n```shell\nenableImmutableInstalls: false\nnodeLinker: node-modules\nyarnPath: .yarn/releases/yarn-3.1.1.cjs\n#npmRegistryServer: \"https://nexusdev.k8s.94ai.pro/repository/npm-group/\"\nnpmScopes:\n  94ai:\n    npmRegistryServer: \"https://packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/\"\n    npmAlwaysAuth: true\n    npmAuthIdent: \"username:password\"\n#unsafeHttpWhitelist:\n#  - 192.168.20.9\n```\n\n### 2.配置个人账号信息\n\n1. 把对应rc文件`username`替换成你的账号名称\n\n2. 如果你使用的是yarn1,npm或pnpm，则把你的账号密码做base64加密之后替换掉对应rc文件`password`,如在这里[在线base64加密](https://stackoverflow.org.cn/base64/)获取base64加密的密码\n\n![img_10.png](https://xccjhzjh.oss-cn-hongkong.aliyuncs.com/xccjh-images/img_10.png)\n\n3. 如果你使用的是yarn2~3,则把你的账号密码直接替换掉对应rc文件`password`\n\n### 3.安装依赖\n\n之后该项目只要是@94ai域的私包都会经过94智能私服抓取\n\n其他包【包括@94ai域私包的子包（非@94ai域）】都会经由个人电脑配置的npm包registry源抓取\n\n执行install命令即可成功安装@94ai域的所有私包，包括sdk,如\n\n```shell\n$ yarn add @94ai/softphone\n# or\n$ npm i @94ai/softphone\n# or\n$ pnpm add @94ai/softphone\n```\n\n# 使用\n## 初始化\n### 1.作为NPM包使用\n```ts\n// Example:\n// 1.softphone.ts\nimport { UserAgent, userAgentManager, URI } from '@94ai/softphone'\nimport FingerprintJS from '@fingerprintjs/fingerprintjs'\n\ninterface UserAgentOptions {\n  authorizationPassword: string, // 通过openApi获取坐席组分机用户密码\n  authorizationUsername: string, // 通过openApi获取坐席组分机用户名\n  viaHost: string, // 指纹，唯一标志，用来排查线路故障\n  uri: URI, // sip服务地址\n  logLevel: 'debug' | 'log' | 'warn' | 'error', // sip日志查看等级，一般情况下生产开error,开发用debugger\n  transportOptions: {\n    server: string // websocket协商地址\n  },\n  contactName: string // 一般设置同authorizationUsername，相当于MicroSIP的显示名称\n}\n\nexport class SoftphoneManager {\n  static #getDeviceId: () => Promise<string>\n  #userAgentManager: InstanceType<typeof UserAgentManager>\n\n  static {\n    /**\n     * 获取指纹\n     */\n    SoftphoneManager.#getDeviceId = (() => {\n      let visitorId = ''\n      return async (): Promise<string> => {\n        if (visitorId) return visitorId\n        const fp = await FingerprintJS.load()\n        const result = await fp.get()\n        visitorId = result.visitorId\n        return visitorId\n      }\n    })()\n  }\n\n  async getUserAgentManager () {\n    if (!this.#userAgentManager) {\n      this.#userAgentManager = UserAgentFactory.getUserAgentManager(await this.initSeatsInfo()) // 👈 得到softphone代理对象\n    }\n    return this.#userAgentManager\n  }\n\n  /**\n   * 通过openApi获取分机信息\n   */\n  async initSeatsInfo (): Promise<UserAgentOptions> {\n    const result = await getSeatsInfo()\n    if (result.code === 200) {\n      const {\n        extPassword, // 分机密码\n        extensionNumber, // 分机号\n        wsRegisterAddress, // socket地址\n        wsProtocol // socket协议\n      } = result.data\n      return {\n        authorizationPassword: extPassword,\n        authorizationUsername: extensionNumber,\n        viaHost: `${await SoftphoneManager.#getDeviceId()}.sip`,\n        uri: UserAgent.makeURI(`sip:${extensionNumber}@${wsRegisterAddress}`),\n        logLevel: 'error',\n        transportOptions: {\n          server: `${wsProtocol}://${wsRegisterAddress}`\n        },\n        contactName: extensionNumber\n      }\n    }\n    const tips = i18nManagerInstance.getI18nInstance().global.t('faileObtInfo')\n    useToast.showToast(tips)\n    throw new Error(tips)\n  }\n}\n\nconst getUserAgentManager = async () => await new SoftphoneManager().getUserAgentManager()\n\nexport {\n  getUserAgentManager\n}\n// 2.other.ts\nconst userAgentManager = await getUserAgentManager()\nuserAgentManager.prepareUserAgent(\n  { // config\n    refresh(path, value) { // 当软电话状态变化时会实时刷新这个方法\n    }\n  },\n  { // event\n    onInvite(invitation) { // 当有外呼过来\n    }\n  }\n)\n```\n### 2.直接在JavaScript中使用\n1. 获取umd文件\n- 确保安装了node，随手新建一个目录，打开cmd或bash。\n- 设置@4ai域账号授权，依次执行执行如下,其中`:username=xxxx`替换你的账号名字,`:_password=xxxx`替换你的账号密码在做base64加密后的结果\n```shell\nnpm config set @94ai:registry=https://packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/\nnpm config set //packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/:username=xxx\nnpm config set //packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/:_password=xxx\nnpm config set //packages.aliyun.com/644f755a97d94d909e43534c/npm/npm-registry/:always-auth=true\n```\n- 最后执行`npx -y @94ai/softphone -- sdk-umd`,之后在当前执行命令路径下即可获取到`softphone.umd.min.js`\n\n2. 在index.html引入`softphone.umd.min.js`文件\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\" />\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no\" />\n  <title>softphone</title>\n</head>\n<body>\n<div id=\"softphone-app\"></div>\n<script src='./softphone.umd.min.js'></script>\n<script>\nconst {\n  UserAgentFactory,\n  UserAgent\n} = softphone\nconst userAgentManager = UserAgentFactory.getUserAgentManager({\n  authorizationPassword: 'xxx',\n  authorizationUsername: 'xxx',\n  viaHost: 'xxx',\n  uri: UserAgent.makeURI('xxx'),\n  logLevel: 'error',\n  transportOptions: {\n    server: 'xxx'\n  },\n  contactName: 'xxx'\n})\nuserAgentManager.prepareUserAgent(\n    { // config\n      refresh(path, value) { // 当软电话状态变化时会实时刷新这个方法\n      }\n    },\n    { // event\n      onInvite(invitation) { // 当有外呼过来\n      }\n    }\n)\n</script>\n</body>\n</html>\n```\n## 签入\n```js\nuserAgentManager.prepareUserAgent(\n  { // config\n    refresh(path, value) { // 当软电话状态变化时会实时刷新这个方法\n      userAgentStatus[path] = value // 外部想要响应状态可以实时更新外部的userAgentStatus\n    }\n  },\n  { // event\n    onInvite(invitation) { // 当有外呼过来\n      playMedia('localAudio') // 播放模拟来电响铃\n      popNotice() // 提示通知   来电了\n      invitation.stateChange.addListener((state) => { // 一旦接听（执行accept）,监听会话的生命周期\n        switch (state) {\n          case SessionState.Initial:\n            break\n          case SessionState.Establishing:\n            break\n          case SessionState.Established: // session建立后就可拿到webrtc的各种基础api，如userAgentManager.getPeerConnection(),如userAgentManager.getSenders()等等\n            const mediaElement1 = getMedia('remoteAudio')\n            mediaElement1.srcObject = userAgentManager.getStream() // 获取流\n            mediaElement1.play() // 把softphone流导入到audio接入用户语音\n            break\n          case SessionState.Terminating:\n          case SessionState.Terminated: // 在挂断电话时候会执行\n            const mediaElement2 = getMedia(id) // 获取audio dom\n            mediaElement2.srcObject = null\n            mediaElement2.pause() // 释放audio\n            break\n          default:\n            throw new Error('Unknown session state.')\n        }\n      })\n    }\n  })\n```\n## 接听\n```js\nconst acceptInvite = () => {\n  refreshShowTime() // 重新计算通话时长\n  pauseMedia('localAudio') // 暂停来电铃声\n  userAgentManager.acceptInvite() // 👈 接入电话流\n}\n```\n## 忽略\n```js\nconst ignoreInvite = () => {\n  pauseMedia('localAudio') // 暂停来电铃声\n  userAgentManager.ignoreInvite() // 👈 忽略\n}\n```\n## 挂断\n```js\nconst hangUpInvite = () => {\n  refreshShowTime()\n  userAgentManager.hangUpInvite() // 👈 挂断\n}\n```\n## 按*号转人工\n```js\nconst sendStarDtmf = () => {\n  refreshShowTime()\n  userAgentManager.sendStarDtmf() // 👈 按*号转人工\n}\n```\n\n## 销毁\n```js\nconst disconnect = () => {\n  refreshShowTime()\n  userAgentManager.dispose() // 👈 一个方法安全销毁\n}\n```\n## 传输本地声音到远端\n```js\nconst unMuteLocalAudio = () => {\n  userAgentManager.unMuteLocalAudio() // 👈 通过webrtc的方式控制 本地音频流 推送到 远端\n}\n```\n## 不传输本地声音到远端\n```js\nconst muteLocalAudio = () => {\n  userAgentManager.muteLocalAudio() // 👈 通过webrtc的方式控制 本地音频流 禁用推送\n}\n```\n## 接听远端声音\n```js\nconst unMuteRemoteAudio = () => {\n  userAgentManager.unMuteRemoteAudio() // 👈 通过webrtc的方式控制 是否接受 远端音频流\n} \n```\n## 不接听远端声音\n```js\nconst muteRemoteAudio = () => {\n  userAgentManager.muteRemoteAudio() // 👈 通过webrtc的方式控制 是否接受 远端音频流\n}\n```\n## 获取webrtc基础api\n```js\nconst senders = userAgentManager.getSenders()\nconst receivers = userAgentManager.getReceivers()\nconst peerConnection = userAgentManager.getPeerConnection()\n```\n## 获取代理用户相关sip协议通讯实例\n```js\nconst userAgent = userAgentManager.getUserAgent()\nconst sessionDescriptionHandler = userAgentManager.getSessionDescriptionHandler()\nconst currentInvitation = userAgentManager.getCurrentInvitation()\nconst currentInviter = userAgentManager.getCurrentInviter()\nconst localMixedMediaStream = userAgentManager.getStream()\n```\n## 查看代理用户目前状态\n```ts\ninterface userAgentStatus {\n  connectStatus: boolean, // 软电话是否已签入\n  registerStatus: boolean, // 软电话是否已注册\n  invitatingStatus: boolean, // 软电话是否正拨出\n  incomingStatus: boolean, // 软电话是否正来电\n  answerStatus: boolean, // 软电话是否正接听\n}\nconst userAgentStatus: userAgentStatus = userAgentManager.getUserAgentStatue()\n```\n\n> 软电话状态可以根据企业特定业务流程定制扩展额外的状态，如94智能决策系统 额外扩展了 【监听中】，【整理中】，【小休中】等状态\n\n","readmeFilename":"README.md"}