Files
zyt/WEB_TO_MINIPROGRAM_CALL_FIX.md
T
2026-03-04 15:32:30 +08:00

335 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Web端呼叫小程序端通话问题修复指南
## 问题描述
Web端可以呼叫Web端,但无法呼叫小程序端。
## 原因分析
### 1. 用户ID格式不一致
- Web端医生: `doctor_{admin_id}`
- 小程序端患者: 需要确认格式是否为 `patient_{patient_id}` 或其他格式
### 2. 小程序端未登录IM
- 小程序端必须先登录腾讯云IM才能接收通话邀请
- 需要在小程序启动时初始化 TUICallKit
### 3. 跨平台通话配置
- 需要确保 SDKAppID 一致
- 需要确保 UserSig 生成方式一致
- 需要确保双方都使用相同的通话协议版本
## 解决方案
### 步骤1: 确认小程序端用户ID格式
检查小程序端的用户ID生成逻辑,确保与Web端一致。
**后端代码检查点:**
```php
// server/app/adminapi/logic/tcm/DiagnosisLogic.php
// 查找 createPatientTrtcAccount 方法
// 确认患者的 userId 格式
```
**预期格式:**
- 医生: `doctor_{admin_id}`
- 患者: `patient_{patient_id}`
### 步骤2: 检查小程序端是否正确初始化
小程序端需要在 `app.js` 或页面 `onLoad` 时初始化 TUICallKit
```javascript
// 小程序端代码示例
import { TUICallKit } from '@tencentcloud/call-uikit-wechat'
// 初始化
await TUICallKit.init({
SDKAppID: YOUR_SDKAPPID,
userID: 'patient_123', // 患者ID
userSig: 'YOUR_USERSIG' // 从后端获取
})
// 监听来电
TUICallKit.on('onCallReceived', (event) => {
console.log('收到来电', event)
})
```
### 步骤3: 确保小程序端在线
小程序端必须:
1. 已登录到腾讯云IM
2. 保持在线状态
3. 正确监听来电事件
### 步骤4: 检查Web端发起通话的userId
在Web端发起通话时,确保使用正确的患者userId:
```typescript
// admin/src/components/video-call/index.vue
// 检查 startCall 方法中的 userId
// 应该使用患者的 IM userId,而不是患者的数据库ID
await TUICallKitServer.call({
userID: 'patient_123', // 必须是小程序端登录IM时使用的userId
type: TUICallType.VIDEO_CALL
})
```
### 步骤5: 后端返回正确的患者userId
修改后端逻辑,在获取签名时同时返回患者的userId:
```php
// server/app/adminapi/logic/tcm/DiagnosisLogic.php
public static function getCallSignature(array $params)
{
// ... 现有代码 ...
// 获取患者信息
$patientId = $params['patient_id'] ?? 0;
$patientUserId = 'patient_' . $patientId;
return [
'sdkAppId' => (int)$config['sdkAppId'],
'userId' => $userId, // 医生的userId
'userSig' => $userSig,
'patientUserId' => $patientUserId, // 添加患者的userId
'expireTime' => 86400
];
}
```
### 步骤6: 前端使用患者userId发起通话
修改前端代码,使用后端返回的患者userId:
```typescript
// admin/src/components/video-call/index.vue
const startCall = async () => {
try {
// ... 获取签名 ...
const res = await getCallSignature({
diagnosis_id: callInfo.value.diagnosisId,
patient_id: callInfo.value.patientId
})
// ... 初始化 ...
// 发起通话时使用后端返回的 patientUserId
await TUICallKitServer.call({
userID: res.patientUserId, // 使用后端返回的患者userId
type: TUICallType.VIDEO_CALL
})
} catch (error) {
// ... 错误处理 ...
}
}
```
## 调试步骤
### 1. 检查患者是否在线
在Web端发起通话前,可以先检查患者是否在线:
```typescript
// 可以通过腾讯云IM的REST API查询用户在线状态
// 或者在发起通话时捕获 60011 错误码(用户不在线)
```
### 2. 查看控制台日志
**Web端:**
- 打开浏览器控制台
- 查看发起通话时的userId
- 查看是否有错误提示
**小程序端:**
- 打开微信开发者工具控制台
- 查看是否收到来电事件
- 查看IM登录状态
### 3. 常见错误码
- `60011`: 对方不在线 - 小程序端未登录IM或已退出
- `60010`: 对方忙线中 - 小程序端正在通话中
- `60008`: 对方拒绝了通话
- `60009`: 对方未接听(超时)
## 完整修复代码
### 后端修改
```php
// server/app/adminapi/logic/tcm/DiagnosisLogic.php
public static function getCallSignature(array $params)
{
try {
$config = self::getTrtcConfig();
if (!$config) {
self::setError('请先配置腾讯云TRTC参数');
return false;
}
$adminId = $params['admin_id'] ?? 0;
$patientId = $params['patient_id'] ?? 0;
if (!$adminId) {
self::setError('获取管理员信息失败');
return false;
}
if (!$patientId) {
self::setError('获取患者信息失败');
return false;
}
// 医生userId
$doctorUserId = 'doctor_' . $adminId;
// 患者userId(必须与小程序端一致)
$patientUserId = 'patient_' . $patientId;
// 生成医生的 UserSig
$userSig = self::generateUserSig(
$config['sdkAppId'],
$config['secretKey'],
$doctorUserId
);
if (!$userSig) {
self::setError('生成签名失败');
return false;
}
// 导入医生账号到IM
self::importDoctorAccountToIm($adminId, $doctorUserId);
// 确保患者账号也已导入IM
self::ensurePatientImAccount($patientId, $patientUserId);
return [
'sdkAppId' => (int)$config['sdkAppId'],
'userId' => $doctorUserId,
'userSig' => $userSig,
'patientUserId' => $patientUserId, // 返回患者userId
'expireTime' => 86400
];
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 确保患者IM账号存在
*/
private static function ensurePatientImAccount(int $patientId, string $userId): bool
{
try {
// 获取患者信息
$diagnosis = Diagnosis::where('patient_id', $patientId)->find();
$nick = $diagnosis ? $diagnosis->patient_name : '患者' . $patientId;
// 调用IM服务导入账号
$imService = new \app\common\service\TencentImService();
$result = $imService->importAccount($userId, $nick);
return $result['success'];
} catch (\Exception $e) {
\think\facade\Log::error('导入患者IM账号失败: ' . $e->getMessage());
return false;
}
}
```
### 前端修改
```typescript
// admin/src/components/video-call/index.vue
const startCall = async () => {
try {
initializing.value = true
callRejected.value = false
statusText.value = '正在获取签名...'
// 获取腾讯云签名
const res = await getCallSignature({
diagnosis_id: callInfo.value.diagnosisId,
patient_id: callInfo.value.patientId
})
if (!res || !res.userSig || !res.patientUserId) {
throw new Error('获取签名失败,返回数据不完整')
}
console.log('签名获取成功:', {
doctorUserId: res.userId,
patientUserId: res.patientUserId,
sdkAppId: res.sdkAppId
})
// ... 初始化代码 ...
// 发起通话 - 使用后端返回的 patientUserId
console.log('准备发起通话,目标用户:', res.patientUserId)
await TUICallKitServer.call({
userID: res.patientUserId, // 使用后端返回的患者userId
type: TUICallType.VIDEO_CALL
})
console.log('通话已发起')
statusText.value = '等待对方接听...'
feedback.msgSuccess('通话已发起,等待对方接听...')
} catch (error: any) {
console.error('启动通话失败:', error)
// 特殊处理用户不在线的情况
if (error.code === 60011) {
feedback.msgError('患者不在线,请确认患者已打开小程序')
} else {
const errorMessage = error.message || '启动通话失败,请稍后重试'
feedback.msgError(errorMessage)
}
// ... 错误处理 ...
} finally {
initializing.value = false
}
}
```
## 测试清单
- [ ] 后端返回正确的 patientUserId
- [ ] 小程序端使用相同的 userId 格式登录IM
- [ ] 小程序端保持在线状态
- [ ] Web端使用 patientUserId 发起通话
- [ ] 小程序端能收到来电通知
- [ ] 小程序端能正常接听
- [ ] 视频和音频正常传输
## 注意事项
1. **userId格式必须完全一致**:Web端和小程序端必须使用相同的userId格式
2. **小程序端必须先登录**:在发起通话前,确保小程序端已登录IM
3. **检查网络环境**:小程序端需要在HTTPS环境或微信开发者工具中测试
4. **版本兼容性**:确保Web端和小程序端使用兼容的TUICallKit版本
## 相关文档
- [TUICallKit Web端文档](https://www.tencentcloud.com/document/product/647/50993)
- [TUICallKit 小程序端文档](https://www.tencentcloud.com/document/product/647/50994)
- [腾讯云IM跨平台通话](https://www.tencentcloud.com/document/product/1047/45907)