# 腾讯云呼叫中心音视频客服小程序SDK

腾讯云呼叫中心支持小程序音视频通话，用户通过小程序发起通话，客服可在电脑端工作台接待。

## 环境要求

- 请使用企业小程序账号申请相关权限进行开发，因为小程序测试号不具备 `<live-pusher>` 和 `<live-player>` 的使用权限。
- 需要在真机上进行运行体验，因为微信开发者工具不支持原生组件 `<live-pusher>` 和 `<live-player>` 。
- 请使用原生小程序开发环境，不支持 uniapp 等开发框架。
- 微信 App iOS 最低版本要求：7.0.9
- 微信 App Android 最低版本要求：7.0.8
- 小程序基础库最低版本要求：2.10.0

## 前提条件

1. 已完成注册[微信小程序账号](https://mp.weixin.qq.com/)
2. 已完成安装[微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html)
3. 已完成安装[Nodejs](https://nodejs.org/zh-cn/)
4. **确保小程序符合微信要求，并开通音视频权限。**
     - 仅支持企业类小程序
     - 仅支持[指定类目](https://developers.weixin.qq.com/miniprogram/dev/component/live-pusher.html)的小程序，具体见[微信小程序live-push文档](https://developers.weixin.qq.com/miniprogram/dev/component/live-pusher.html)
     - 在[微信公众平台](https://mp.weixin.qq.com/)>*开发>开发管理>接口设置* 中开启**实时播放音视频流**、**实时录制音视频流** 两个权限。

## 配置服务器域名
1. 登录[微信公众平台](https://mp.weixin.qq.com/)
2. 选择*开发>开发管理>开发设置>服务器域名*，根据下表配置

<escape> 
<table>    
  <tr>
    <th>合法域名类型</th>
    <th>域名</th>
  </tr>
  <tr>
    <td rowspan="4">request合法域名</td>
    <td>https://api.tccc.qcloud.com</td>
  </tr>
  <tr>
    <td>https://yun.tim.qq.com</td>
  </tr>
  <tr>
    <td>https://web.sdk.qcloud.com</td>
  </tr>
  <tr>
    <td>https://webim.tim.qq.com</td>
  </tr>
  <tr>
    <td rowspan="3">socket合法域名</td>
    <td>wss://api.tccc.qcloud.com</td>
  </tr>
  <tr><td>wss://wss.im.qcloud.com</td></tr>
  <tr><td>wss://wss.tim.qq.com</td></tr>
</table>   
</escape> 

## 引入SDK
1. 使用npm下载
```bash
npm install tccc-wx-sdk
```

2. 导入SDK组件

```json
  {
    "usingComponents": {
      "tccc-wx-sdk": "tccc-wx-sdk"
    }
  }
```

3. 引入SDK视频组件

>如果不需要视频客服功能，可跳过此步骤

>注意⚠️, `pusher`和`player`组件必须在`tccc-wx-sdk`层级下

```json
  {
    "usingComponents": {
      "tccc-wx-sdk": "tccc-wx-sdk",
      "tccc-wx-sdk-pusher": "tccc-wx-sdk/pusher",
      "tccc-wx-sdk-player": "tccc-wx-sdk/player"
    }
  }
```

4. 在wxml中自定义本地和远端视频
```html
<tccc-wx-sdk
  id="tcccSdk"
  sdkAppId="{{sdkAppId}}"
  bind:error="handleTcccError"
  bind:sessionEnded="handleEnd"
  bind:accepted="handleAccept"
  bind:sessionStart="handleStart"
>
  <!-- 本地视频画面，音频通话可忽略  -->
  <tccc-wx-sdk-pusher />
  <!-- 远端视频画面，音频通话可忽略  -->
  <tccc-wx-sdk-player />
</tccc-wx-sdk>
```

## API目录

### 通用API
1. [login - 登录](#login-登录)
2. [checkLogin - 检查是否已登录](#checkLogin-检查是否已登录)


### 音频呼叫API

1. [startCall - 发起音频通话](#startCall-发起音频通)
2. [endCall - 挂断通话](#endCall-挂断通话)
3. [sendDigits - 发送分机号](#sendDigits-发送分机号)

### 视频呼叫API

1. [startSession - 发起视频通话](#startSession-发起视频通话)
2. [endSession - 挂断视频通话](#endSession-挂断视频通话)
3. [switchCamera - 切换摄像头](#switchCamera-切换摄像头)
4. [disableCamera - 关闭摄像头](#disableCamera-关闭摄像头)
5. [enableCamera - 开启摄像头](#enableCamera-开启摄像头)

### 会话通用API

1. [setSoundMode - 设置声音输出方式](#setSoundMode-设置声音输出方式)
2. [muteAudio - 静音](#muteAudio-静音)
3. [unmnuteAudio - 取消静音](#unmuteAudio-取消静音)

### 通用事件

1. [sessionStart - 会话开始](#sessionStart-会话开始)
2. [accepted - 对方接听](#accpeted-对方接听)
3. [sessionEnded - 会话结束](#sessionEnded-会话结束)
4. [error 通话错误](#error-通话错误)


TCCC小程序SDK提供登录、呼叫等方法

#### login - 登录

<escape> 
<table>    
  <tr><th>参数</th><th>类型</th><th>是否必填</th><th>说明</th></tr>
  <tr><td>sdkAppId</td><td>String</td><td>是</td><td>腾讯云呼叫中心应用SdkAppId</td></tr>
  <tr><td>jsCode</td><td>String</td><td>是</td><td>wx.login获取</td></tr>
  <tr><td>dataEnc</td><td>String</td><td>否</td><td>wx.getUserProfile的encryptedData</td></tr>
  <tr><td>dataIv</td><td>String</td><td>否</td><td>wx.getUserProfile的iv</td></tr>
  <tr><td>mobileEnv</td><td>String</td><td>否</td><td>通过button open-type="getPhoneNumber"方式获取</td></tr>
  <tr><td>mobileIv</td><td>String</td><td>否</td><td>通过button open-type="getPhoneNumber"方式获取</td></tr>
</table>   
</escape> 

#### checkLogin - 检查是否已登录
<escape> 
<table>    
  <tr><th colspan="2">参数</th><th>类型</th><th>是否必填</th><th>说明</th></tr>
  <tr><td rowspan="1">options</td><td>sdkAppId</td><td>string</td><td>是</td><td>腾讯云呼叫中心应用SdkAppId</td></tr>
</table>   
</escape>

```javascript
import { login, checkLogin } from 'tccc-wx-sdk/login'
const sdkAppId = '1400000000';
// 登录示例代码
checkLogin({ sdkAppId }).then((result) => {
  if (result) {
    // 检查登录成功
  } else {
    throw new Error('登录已过期')
  }
}).catch(() => {
  wx.login({
    success: ({ code }) => {
      // 登录tccc
      login({
        jsCode: code,
        sdkAppId,
      }).then(() => {
        // 登录成功
      }).catch(e => {
        wx.showToast({
          icon: 'error',
          title: e.message,
        })
      })
    }
  })
})
```

#### startCall-发起音频通话
<escape> 
<table>    
  <tr><th colspan="2">参数</th><th>类型</th><th>是否必填</th><th>说明</th></tr>
  <tr><td rowspan="1">options</td><td>channelId</td><td>string</td><td>是</td><td>IVR入口ID</td></tr>
</table>   
</escape>

```javascript
try {
  const channelId = 'xxx';
  const { sessionId } = await this.selectComponent('#tcccSdk').startCall({ channelId });
} catch (e) {
  wx.showToast({
    icon: 'error',
    title: e.message,
  });
}
```


#### endCall-挂断音频通话
```javascript
this.selectComponent('#tcccSdk').endCall();
```

#### startSession-发起视频呼叫
<escape> 
<table>    
  <tr><th colspan="2">参数</th><th>类型</th><th>是否必填</th><th>说明</th></tr>
  <tr><td rowspan="1">options</td><td>channelId</td><td>string</td><td>是<td>IVR入口ID</td></tr>
</table>   
</escape>

```javascript
try {
  const channelId = 'xxx';
  const { sessionId } = await this.selectComponent('#tcccSdk').startCall({ channelId });
} catch (e) {
  wx.showToast({
    icon: 'error',
    title: e.message,
  });
}
```

#### endSession-挂断视频通话
```javascript
this.selectComponent('#tcccSdk').endCall();
```

#### sendDigits-发送分机号
```javascript
this.selectComponent('#tcccSdk').sendDigits(param)
```
<escape> 
<table>    
</table>   
</escape>

#### muteAudio-静音
```javascript
this.selectComponent('#tcccSdk').muteAudio()
```

#### unmuteAudio-取消静音
```javascript
this.selectComponent('#tcccSdk').unmuteAudio()
```

#### setSoundMode-设置声音输出方式

<escape> 
<table>    
  <tr><th>参数</th><th>类型</th><th>是否必填</th><th>说明</th></tr>
  <tr>
    <td>soundMode</td>
    <td>'ear' | 'speaker'</td>
    <td>是</td>
    <td>
      speaker：扬声器，ear：听筒
    </td>
  </tr>
</table>   
</escape> 

```javascript
const soundMode = this.data.soundMode === 'speaker' ? 'ear' : 'speaker';
this.selectComponent('#tcccSdk').setSoundMode(soundeMode);
this.setData({
  soundMode,
});
```

### 事件类型

#### sessionStart-会话开始
```html
<tccc-wx-sdk bind:sessionStart="handleStart"/>
```
```javascript
handleStart() {
  wx.showToast({
    icon: 'success',
    title: '通话开始',
  })
}
```

#### accept-对方接听

```html
<tccc-wx-sdk bind:accepted="handleAccepted"/>
```
```javascript
handleAccepted(){
  wx.showToast({
    icon: 'none',
    title: '对方已接听',
  })
}
```

#### sessionEnded-会话结束
```html
<tccc-wx-sdk bind:sessionEnded="handleSessionEnded>
```
```javascript
handleSessionEnded({ closeBy }){
  if (closeBy === 'admin') {
    wx.showToast({
      icon: 'none',
      title: '系统原因挂断',
    })
  } else if(cloeBy === 'seat') {
    wx.showToast({
      icon: 'none',
      title: '通话结束，对方已挂断',
    })
  } else {
    // 挂断成功
  }
}
```

#### error-会话错误
```html
<tccc-wx-sdk bind:error="handleError>
```
```javascript
handleError({ message }){
  wx.showToast({
    icon: 'error',
    title: message || '发生错误，请重试',
  })
}
```