352 lines
8.2 KiB
Markdown
352 lines
8.2 KiB
Markdown
# userId 格式检查指南
|
||
|
||
## 🎯 核心问题
|
||
|
||
**userId 格式必须完全一致!**
|
||
|
||
如果格式不一致,会导致:
|
||
- ❌ 提示"对方不在线"(错误代码 60011)
|
||
- ❌ 无法接听来电
|
||
- ❌ 无法发起通话
|
||
|
||
## 📋 正确的格式
|
||
|
||
### 医生端(Web)
|
||
```
|
||
登录 userId: doctor_1
|
||
呼叫目标: patient_2
|
||
```
|
||
|
||
### 患者端(小程序)
|
||
```
|
||
登录 userId: patient_2
|
||
呼叫目标: doctor_1
|
||
```
|
||
|
||
## 🔍 检查步骤
|
||
|
||
### 步骤 1:检查后端接口
|
||
|
||
#### 医生端获取签名接口
|
||
**接口:** `POST /api/tcm/getCallSignature`
|
||
|
||
**请求:**
|
||
```json
|
||
{
|
||
"diagnosis_id": 1,
|
||
"patient_id": 2,
|
||
"admin_id": 1
|
||
}
|
||
```
|
||
|
||
**期望响应:**
|
||
```json
|
||
{
|
||
"code": 1,
|
||
"data": {
|
||
"userId": "doctor_1", // 医生自己的 userId(字符串)
|
||
"patientUserId": "patient_2", // 要呼叫的患者 userId(字符串)
|
||
"sdkAppId": "1400xxxxxx", // 字符串或数字都可以
|
||
"userSig": "eJw1..."
|
||
}
|
||
}
|
||
```
|
||
|
||
**关键检查点:**
|
||
- [ ] `userId` 是字符串 `"doctor_1"`,不是数字 `1`
|
||
- [ ] `patientUserId` 是字符串 `"patient_2"`,不是数字 `2`
|
||
- [ ] 格式统一:都是 `prefix_number` 格式
|
||
|
||
#### 患者端获取签名接口
|
||
**接口:** `GET /api/tcm/getPatientSignature?patient_id=2`
|
||
|
||
**期望响应:**
|
||
```json
|
||
{
|
||
"code": 1,
|
||
"data": {
|
||
"userId": "patient_2", // 患者自己的 userId(字符串)
|
||
"sdkAppId": "1400xxxxxx",
|
||
"userSig": "eJw1..."
|
||
}
|
||
}
|
||
```
|
||
|
||
**关键检查点:**
|
||
- [ ] `userId` 是字符串 `"patient_2"`,不是数字 `2`
|
||
- [ ] 格式与医生端一致:`prefix_number`
|
||
|
||
### 步骤 2:检查 Web 端日志
|
||
|
||
**登录时:**
|
||
```javascript
|
||
console.log('=== 发起一对一通话 ===')
|
||
console.log('后端返回的 patientUserId:', res.patientUserId) // 应该是 "patient_2"
|
||
console.log('最终使用的 targetUserId:', targetUserId) // 应该是 "patient_2"
|
||
```
|
||
|
||
**关键检查点:**
|
||
- [ ] `patientUserId` 是字符串 `"patient_2"`
|
||
- [ ] `targetUserId` 是字符串 `"patient_2"`
|
||
- [ ] 没有多余的空格或特殊字符
|
||
|
||
### 步骤 3:检查小程序端日志
|
||
|
||
**登录时:**
|
||
```javascript
|
||
console.log('=== 小程序端登录信息 ===')
|
||
console.log('userId:', userId) // 应该是 "patient_2"
|
||
```
|
||
|
||
**关键检查点:**
|
||
- [ ] `userId` 是字符串 `"patient_2"`
|
||
- [ ] 格式与 Web 端一致
|
||
|
||
### 步骤 4:对比验证
|
||
|
||
| 端 | 登录 userId | 呼叫目标 | 格式 |
|
||
|----|------------|---------|------|
|
||
| Web(医生) | `doctor_1` | `patient_2` | ✅ 一致 |
|
||
| 小程序(患者) | `patient_2` | `doctor_1` | ✅ 一致 |
|
||
|
||
**必须满足:**
|
||
- Web 端呼叫的 `patient_2` === 小程序端登录的 `patient_2`
|
||
- 小程序端呼叫的 `doctor_1` === Web 端登录的 `doctor_1`
|
||
|
||
## ⚠️ 常见错误
|
||
|
||
### 错误 1:数字 vs 字符串
|
||
|
||
**错误示例:**
|
||
```javascript
|
||
// ❌ 错误:后端返回数字
|
||
{
|
||
"userId": 1, // 数字
|
||
"patientUserId": 2 // 数字
|
||
}
|
||
|
||
// ✅ 正确:应该返回字符串
|
||
{
|
||
"userId": "doctor_1", // 字符串
|
||
"patientUserId": "patient_2" // 字符串
|
||
}
|
||
```
|
||
|
||
**后果:**
|
||
- Web 端使用 `2` 呼叫
|
||
- 小程序端登录为 `"patient_2"`
|
||
- 格式不匹配,无法通话
|
||
|
||
### 错误 2:前缀不一致
|
||
|
||
**错误示例:**
|
||
```javascript
|
||
// ❌ 错误:前缀不一致
|
||
Web 端: "doctor_1"
|
||
小程序端: "patient2" // 缺少下划线
|
||
|
||
// ✅ 正确:前缀一致
|
||
Web 端: "doctor_1"
|
||
小程序端: "patient_2" // 都使用下划线
|
||
```
|
||
|
||
### 错误 3:大小写不一致
|
||
|
||
**错误示例:**
|
||
```javascript
|
||
// ❌ 错误:大小写不一致
|
||
Web 端: "Doctor_1"
|
||
小程序端: "doctor_1"
|
||
|
||
// ✅ 正确:大小写一致
|
||
Web 端: "doctor_1"
|
||
小程序端: "doctor_1"
|
||
```
|
||
|
||
## 🛠️ 后端代码检查
|
||
|
||
### PHP 后端示例
|
||
|
||
**医生端获取签名:**
|
||
```php
|
||
public static function getCallSignature(array $params)
|
||
{
|
||
$adminId = $params['admin_id'] ?? 0;
|
||
$patientId = $params['patient_id'] ?? 0;
|
||
|
||
// ✅ 正确:使用字符串格式
|
||
$doctorUserId = 'doctor_' . $adminId; // "doctor_1"
|
||
$patientUserId = 'patient_' . $patientId; // "patient_2"
|
||
|
||
// ❌ 错误:不要这样做
|
||
// $doctorUserId = $adminId; // 1
|
||
// $patientUserId = $patientId; // 2
|
||
|
||
return [
|
||
'sdkAppId' => (int)$config['sdkAppId'],
|
||
'userId' => $doctorUserId, // "doctor_1"
|
||
'userSig' => $userSig,
|
||
'patientUserId' => $patientUserId, // "patient_2"
|
||
];
|
||
}
|
||
```
|
||
|
||
**患者端获取签名:**
|
||
```php
|
||
public static function getPatientSignature(int $patientId)
|
||
{
|
||
// ✅ 正确:使用字符串格式
|
||
$patientUserId = 'patient_' . $patientId; // "patient_2"
|
||
|
||
// ❌ 错误:不要这样做
|
||
// $patientUserId = $patientId; // 2
|
||
|
||
return [
|
||
'sdkAppId' => (int)$config['sdkAppId'],
|
||
'userId' => $patientUserId, // "patient_2"
|
||
'userSig' => $userSig,
|
||
];
|
||
}
|
||
```
|
||
|
||
## 🧪 测试验证
|
||
|
||
### 测试 1:打印 userId
|
||
|
||
**Web 端(浏览器控制台):**
|
||
```javascript
|
||
// 在发起通话前
|
||
console.log('=== userId 格式检查 ===');
|
||
console.log('类型:', typeof res.patientUserId); // 应该是 "string"
|
||
console.log('值:', res.patientUserId); // 应该是 "patient_2"
|
||
console.log('长度:', res.patientUserId.length); // 应该是 9
|
||
```
|
||
|
||
**小程序端(微信开发者工具控制台):**
|
||
```javascript
|
||
// 在登录后
|
||
console.log('=== userId 格式检查 ===');
|
||
console.log('类型:', typeof userId); // 应该是 "string"
|
||
console.log('值:', userId); // 应该是 "patient_2"
|
||
console.log('长度:', userId.length); // 应该是 9
|
||
```
|
||
|
||
### 测试 2:对比 userId
|
||
|
||
**在 Web 端发起呼叫时:**
|
||
```javascript
|
||
console.log('=== 对比检查 ===');
|
||
console.log('Web 端呼叫目标:', targetUserId); // "patient_2"
|
||
console.log('小程序端应该登录为:', targetUserId); // "patient_2"
|
||
console.log('是否完全相等:', targetUserId === "patient_2"); // true
|
||
```
|
||
|
||
### 测试 3:手动验证
|
||
|
||
1. **Web 端控制台执行:**
|
||
```javascript
|
||
console.log(JSON.stringify({
|
||
type: typeof res.patientUserId,
|
||
value: res.patientUserId,
|
||
length: res.patientUserId.length
|
||
}));
|
||
```
|
||
|
||
2. **小程序端控制台执行:**
|
||
```javascript
|
||
console.log(JSON.stringify({
|
||
type: typeof userId,
|
||
value: userId,
|
||
length: userId.length
|
||
}));
|
||
```
|
||
|
||
3. **对比结果:**
|
||
- 类型必须都是 `"string"`
|
||
- 值必须完全相同
|
||
- 长度必须相同
|
||
|
||
## 📊 诊断表
|
||
|
||
| 检查项 | Web 端 | 小程序端 | 状态 |
|
||
|--------|--------|----------|------|
|
||
| userId 类型 | string | string | ✅ |
|
||
| userId 值 | doctor_1 | patient_2 | ✅ |
|
||
| 呼叫目标类型 | string | string | ✅ |
|
||
| 呼叫目标值 | patient_2 | doctor_1 | ✅ |
|
||
| 格式一致性 | prefix_number | prefix_number | ✅ |
|
||
|
||
## 🔧 修复建议
|
||
|
||
### 如果后端返回的是数字
|
||
|
||
**修改后端代码:**
|
||
```php
|
||
// 在返回前确保转换为字符串
|
||
return [
|
||
'userId' => (string)$doctorUserId, // 强制转换为字符串
|
||
'patientUserId' => (string)$patientUserId,
|
||
// ...
|
||
];
|
||
```
|
||
|
||
### 如果前端收到的是数字
|
||
|
||
**修改前端代码:**
|
||
```javascript
|
||
// Web 端
|
||
const targetUserId = String(res.patientUserId); // 确保是字符串
|
||
|
||
// 小程序端
|
||
const userId = String(signatureData.userId); // 确保是字符串
|
||
```
|
||
|
||
## ✅ 验证清单
|
||
|
||
在测试前,请确认:
|
||
|
||
- [ ] 后端返回的 userId 是字符串格式
|
||
- [ ] 后端返回的 patientUserId 是字符串格式
|
||
- [ ] Web 端日志显示正确的 userId 格式
|
||
- [ ] 小程序端日志显示正确的 userId 格式
|
||
- [ ] Web 端呼叫目标与小程序端登录 userId 完全一致
|
||
- [ ] 小程序端呼叫目标与 Web 端登录 userId 完全一致
|
||
- [ ] 没有多余的空格或特殊字符
|
||
- [ ] 大小写完全一致
|
||
|
||
## 📞 如果仍然有问题
|
||
|
||
请提供以下信息:
|
||
|
||
1. **后端接口响应**(隐藏 userSig):
|
||
```json
|
||
{
|
||
"userId": "???",
|
||
"patientUserId": "???",
|
||
"sdkAppId": "???"
|
||
}
|
||
```
|
||
|
||
2. **Web 端日志**:
|
||
```
|
||
类型: ???
|
||
值: ???
|
||
长度: ???
|
||
```
|
||
|
||
3. **小程序端日志**:
|
||
```
|
||
类型: ???
|
||
值: ???
|
||
长度: ???
|
||
```
|
||
|
||
4. **具体错误信息**:
|
||
- 错误代码
|
||
- 错误提示
|
||
|
||
---
|
||
|
||
**最后更新:** 2024-03-04
|
||
**版本:** 1.0
|