# 开放接口 PHP 客户端使用指南 ## 📋 文件说明 | 文件 | 说明 | 用途 | |------|------|------| | `OpenApiClient.php` | PHP 客户端类 | 封装签名计算、请求发送等逻辑 | | `quickstart.php` | 快速开始示例 | 最简单的调用示例 | | `openapi-student-list-test.php` | 完整测试示例 | 演示多种查询场景 | | `README.md` | 使用文档 | 本文件 | --- ## 🚀 快速开始 ### 1. 准备工作 **环境要求**: - PHP 7.4 或以上 - 启用 curl 扩展 **检查 PHP 版本**: ```bash php -v ``` **检查 curl 扩展**: ```bash php -m | grep curl ``` ### 2. 获取应用凭证 在盘古管理后台获取您的应用凭证: 1. 登录管理后台:http://localhost:80 2. 进入【应用管理】菜单 3. 新增或查看应用,获取: - **应用编码**(AppCode):如 `YY000001` - **应用密钥**(AppSecret):如 `a1b2c3d4e5f6789012345678901234ab` ### 3. 运行快速示例 ```bash cd /Users/felix/pgWorkSpace/pangu-user-platform/scripts/test # 方式一:使用命令行参数 php quickstart.php # 方式二:修改 quickstart.php 中的配置后运行 php quickstart.php ``` --- ## 📖 详细使用 ### 方式一:使用完整测试脚本 ```bash # 基本用法 php openapi-student-list-test.php [baseUrl] # 示例:连接本地服务 php openapi-student-list-test.php YY000001 a1b2c3d4e5f6789012345678901234ab # 示例:连接远程服务 php openapi-student-list-test.php YY000001 a1b2c3d4e5f6789012345678901234ab http://your-domain.com:8080 ``` **输出示例**: ``` ======================================== 【开放接口调用】 ======================================== 【请求方法】GET 【请求 URL】http://localhost:8080/open/api/student/list?pageNum=1&pageSize=10 【请求头】 X-App-Id: YY000001 X-Timestamp: 1738656000000 X-Sign: A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6 Content-Type: application/json 【请求参数】 { "pageNum": 1, "pageSize": 10 } 【签名计算】 签名字符串: pageNum=1&pageSize=10&appSecret=a1b2c3d4e5f6789012345678901234ab MD5 结果: A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6 ======================================== 【响应状态码】200 【响应内容】 {"code":200,"msg":"操作成功","rows":[...],"total":100} ✅ 调用成功! ``` ### 方式二:在您的项目中使用 **1. 引入客户端类**: ```php require_once '/path/to/OpenApiClient.php'; ``` **2. 创建客户端实例**: ```php $client = new OpenApiClient( 'http://localhost:8080', // API 基础地址 'YY000001', // 应用编码 'a1b2c3d4e5f6789012345678901234ab', // 应用密钥 false // 调试模式(true=开启, false=关闭) ); ``` **3. 调用接口**: ```php try { // GET 请求 $result = $client->get('/open/api/student/list', [ 'pageNum' => 1, 'pageSize' => 10, 'studentName' => '张', 'schoolId' => 1 ]); // 处理响应 if ($result['code'] === 200) { echo "总记录数: {$result['total']}\n"; foreach ($result['rows'] as $student) { echo "{$student['studentName']} - {$student['studentCode']}\n"; } } else { echo "调用失败: {$result['msg']}\n"; } } catch (Exception $e) { echo "异常: {$e->getMessage()}\n"; } ``` --- ## 🔐 签名算法说明 ### 签名计算步骤 1. **收集请求参数**(不含签名本身) ``` pageNum=1, pageSize=10, studentName=张 ``` 2. **按参数名 ASCII 码升序排序** ``` pageNum=1, pageSize=10, studentName=张 ``` 3. **拼接键值对,末尾追加 appSecret** ``` pageNum=1&pageSize=10&studentName=张&appSecret=a1b2c3d4e5f6789012345678901234ab ``` 4. **MD5 加密并转大写** ```php $sign = strtoupper(md5($signStr)); ``` ### PHP 实现示例 ```php function calculateSign(array $params, string $appSecret): string { // 1. 按 key 升序排序 ksort($params); // 2. 拼接参数 $signStr = ''; foreach ($params as $key => $value) { if ($value === '' || $value === null) continue; if ($signStr !== '') $signStr .= '&'; $signStr .= $key . '=' . $value; } // 3. 追加密钥 if ($signStr !== '') $signStr .= '&'; $signStr .= 'appSecret=' . $appSecret; // 4. MD5 加密并转大写 return strtoupper(md5($signStr)); } ``` --- ## 🔍 常见问题 ### 1. 签名验证失败 **错误信息**:`签名验证失败` **可能原因**: - appSecret 不正确 - 参数排序错误(必须按 ASCII 码升序) - MD5 结果未转大写 - 签名字符串拼接错误 **解决方法**: ```bash # 开启调试模式,查看签名计算过程 $client = new OpenApiClient($baseUrl, $appCode, $appSecret, true); ``` ### 2. 请求已过期 **错误信息**:`请求已过期` **可能原因**: - 服务器时间与客户端时间相差超过 5 分钟 **解决方法**: ```bash # 同步服务器时间 sudo ntpdate -u time.apple.com ``` ### 3. 无权访问该接口 **错误信息**:`无权访问该接口` **可能原因**: - 应用未授权访问该接口 **解决方法**: 1. 登录管理后台 2. 进入【应用管理】 3. 编辑应用,勾选需要的接口 4. 保存配置 ### 4. 应用已停用 **错误信息**:`应用已停用` **可能原因**: - 应用状态为停用 **解决方法**: 1. 登录管理后台 2. 进入【应用管理】 3. 编辑应用,将状态改为正常 4. 保存配置 --- ## 📚 接口参数说明 ### 学生列表查询 **接口路径**:`/open/api/student/list` **请求方法**:`GET` **请求参数**: | 参数名 | 类型 | 必填 | 说明 | 示例 | |--------|------|------|------|------| | pageNum | int | 是 | 页码(从 1 开始) | 1 | | pageSize | int | 是 | 每页条数 | 10 | | studentName | string | 否 | 学生姓名(模糊查询) | 张 | | schoolId | int | 否 | 学校 ID | 1 | | gradeId | int | 否 | 年级 ID | 1 | | classId | int | 否 | 班级 ID | 1 | **响应数据**: ```json { "code": 200, "msg": "操作成功", "rows": [ { "studentId": 1, "studentCode": "S2024001", "studentName": "张*", "gender": "1", "schoolId": 1, "schoolName": "第一小学", "gradeId": 1, "gradeName": "三年级", "classId": 1, "className": "1班" } ], "total": 100 } ``` **字段说明**: | 字段 | 类型 | 说明 | |------|------|------| | studentId | int | 学生 ID | | studentCode | string | 学号 | | studentName | string | 学生姓名(已脱敏) | | gender | string | 性别(0未知 1男 2女) | | schoolId | int | 学校 ID | | schoolName | string | 学校名称 | | gradeId | int | 年级 ID | | gradeName | string | 年级名称 | | classId | int | 班级 ID | | className | string | 班级名称 | --- ## 🔗 相关链接 - **技术文档**:`/docs/应用管理-需求与技术设计方案.md` - **实现说明**:`/docs/开放接口实现说明.md` - **Swagger 文档**:http://localhost:8080/doc.html --- ## 📝 更新日志 ### v1.0 (2026-02-04) - 初始版本 - 支持学生列表查询接口 - 提供完整的签名计算实现 - 提供调试模式 --- ## 🤝 技术支持 如有问题,请联系技术支持或查看项目文档。 **pangu**