# php-push-sdk **Repository Path**: hifisher/php-push-sdk ## Basic Information - **Project Name**: php-push-sdk - **Description**: PHP版本的推送消息SDK,支持单条或批量发送 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-07 - **Last Updated**: 2026-09-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # FlashExpress Push SDK for PHP FlashExpress 推送消息 PHP SDK,支持单条/批量推送、站内信发送、设备 Token 获取,通过 JSON-RPC 调用 ard-api / by_rpc 接口。 ## 环境要求 - PHP >= 7.2 - ext-curl - ext-json - ext-openssl ## 安装 ```bash composer require flash-express/php-push-sdk:^1.0 ``` ## 快速开始 ### 初始化 ```php 'http://ard-api.svc/svc/call', // 可选: by_rpc 地址 (用于获取待审批数量等) 'by_rpc_endpoint' => 'http://by-rpc.svc', // 必填: push.* 接口签名鉴权凭据 (ard-api SignatureAuthMiddleware 强制校验) 'app_id' => 'your_app_id', 'app_key' => 'your_app_key', // 可选: 语言环境, 默认 zh-CN 'locale' => 'zh-CN', // 可选: HTTP 超时 (秒), 默认 10 'timeout' => 10, // 可选: RPC 失败重试次数, 默认 0 (不重试) 'retry_times' => 0, // 可选: 重试间隔 (毫秒), 默认 200 'retry_delay' => 200, ]); ``` --- ## API 接口 ### 1. 单条推送 (按工号/客户 ID) 向单个指定用户发送 push 消息,SDK 自动获取设备 Token。 ```php $response = $client->pushToStaff([ 'src' => Client::SRC_BACKYARD, // 来源系统: c | ka | kit | backyard | osm 'staff_info_id' => '100001', // 工号或客户 ID 'message_title' => '您有新的审批待处理', 'message_content' => '请及时前往审批中心处理', 'message_scheme' => 'app://approval/detail', // 可选: 点击跳转 Scheme 'message_priority' => 0, // 可选: 0 普通 | 1 优先 'silence' => 0, // 可选: 0 有声音 | 1 静默推送 'thumbnail' => 'https://xxx.com/icon.png', // 可选: 图片推送 (iOS 富推送 / Android 图文) ]); if ($response->isSuccess()) { echo $response->getMessage(); } else { echo $response->getMessage(); } ``` **来源系统常量**: | 常量 | 值 | 说明 | |------------------------|--------------|------------------| | `Client::SRC_C` | `'c'` | C端用户 | | `Client::SRC_KA` | `'ka'` | KA客户 | | `Client::SRC_KIT` | `'kit'` | KIT (快递员手持客户端) | | `Client::SRC_BACKYARD` | `'backyard'` | OA (员工端) | | `Client::SRC_OSM` | `'osm'` | OSM (外协员工管理客户端) | | `Client::SRC_PAY` | `'flashpay'` | FlashPay (支付客户端) | --- ### 2. 批量推送 (按工号/客户 ID 列表) 一次性向最多 100 个用户推送消息,支持批量设置公共参数。 ```php $response = $client->pushToStaffs( // 每个用户独立参数 [ ['staff_info_id' => '100001', 'src' => Client::SRC_BACKYARD], ['staff_info_id' => '100002', 'src' => Client::SRC_BACKYARD], ], // 公共参数 (会被独立参数覆盖) [ 'message_title' => '团队通知', 'message_content' => '今日例会时间调整为 15:00', 'message_scheme' => 'app://meeting', ] ); if ($response->isSuccess()) { $data = $response->getData(); echo "总计: {$data['total']}, 成功: {$data['success']}, 失败: {$data['fail']}"; } ``` --- ### 3. 直接设备 Token 推送 跳过设备 Token 查询,直接推送。适用于调用方已有设备 Token 的场景。 ```php $response = $client->pushToDevices([ [ 'os' => 'android', // 'android' | 'ios' 'device_token' => 'APA91b...', // 设备 Token 'device_type' => Client::DEVICE_TYPE_GOOGLE, // 可选: 1 Google | 2 华为 'staff_info_id' => '100001', // 可选: 关联工号 'src' => Client::SRC_OSM, // 可选, 默认 osm 'message_title' => '新订单来了', 'message_content' => '点击查看详情', 'message_scheme' => 'app://order', 'message_priority' => 0, 'badge' => 0, ], ]); ``` **设备类型常量**: | 常量 | 值 | |---|---| | `Client::DEVICE_TYPE_GOOGLE` | `1` | | `Client::DEVICE_TYPE_HUAWEI` | `2` | --- ### 4. 发送站内信 ```php $response = $client->sendInternalMessage([ 'staff_info_id' => '100001', // 工号, 多值传数组: ['100001', '100002'] 'message_title' => '系统公告', 'message_content' => '春节期间服务调整通知...', 'category' => -1, // 可选: 分类 ID 'category_code' => 0, // 可选: 分类编码 'top_state' => 0, // 可选: 0 不置顶 | 1 置顶 'related_id' => 'order_20260901_001', // 可选: 关联业务 ID ]); ``` --- ### 5. 组合方法: 站内信 + Push 一次调用完成站内信和 Push 发送,通过开关控制是否发送。 ```php $response = $client->pushMsgByStaffs([ 'staff_ids' => ['100001', '100002', '100003'], // 通知内容 'src' => Client::SRC_BACKYARD, 'title' => '审批通知', 'content' => '您有一条新的审批待处理', 'push_content' => '审批待处理', // 可选: Push 与站内信内容不同时使用, 默认同 content // 发送开关 'is_mail' => true, // 是否发送站内信, 默认 true 'is_push' => true, // 是否发送 push, 默认 true // 后院 Badge 控制 (可选) 'is_by_badge' => true, // true = 使用指定 badge 值; false = 自动查询待审批数 'by_banding_counts' => [ // 当 is_by_badge=true 时, 每个员工的 badge 值 '100001' => 3, '100002' => 1, ], // 站内信扩展字段 (可选) 'category' => -1, 'category_code' => 0, 'top_state' => 0, 'related_id' => '', ]); if ($response->isSuccess()) { $data = $response->getData(); echo "站内信: 成功 {$data['internal_mail']['success']} / 失败 {$data['internal_mail']['fail']}\n"; echo "Push: 成功 {$data['push']['success']} / 失败 {$data['push']['fail']}\n"; } ``` --- ## 响应格式 所有方法统一返回 `FlashExpress\Push\Contracts\ResponseInterface` 对象: ```php $response->isSuccess(); // code === 1 $response->isFail(); // code === 0 $response->isError(); // code === -1 $response->getCode(); // 1=成功 | 0=业务失败 | -1=系统/参数错误 $response->getMessage(); // 消息文本 $response->getData(); // 业务数据 (mixed) $response->getRaw(); // 原始 JSON-RPC 响应 (string) $response->toArray(); // 转数组 ['code'=>1, 'msg'=>'ok', 'data'=>...] ``` --- ## 异常处理 SDK 不会主动抛出异常,所有错误都通过 `Response::error()` / `Response::fail()` 返回。 如需捕获底层异常,可 catch 以下类型: | 异常类 | 触发场景 | |---|---| | `FlashExpress\Push\Exceptions\ValidationException` | 配置项缺失 / 参数校验失败 | | `FlashExpress\Push\Exceptions\RpcException` | JSON-RPC 调用异常 | | `FlashExpress\Push\Exceptions\PushException` | SDK 通用异常 (基类) | ```php use FlashExpress\Push\Exceptions\RpcException; use FlashExpress\Push\Exceptions\ValidationException; try { $response = $client->pushToStaff([...]); } catch (ValidationException $e) { echo '参数错误: ' . $e->getMessage(); echo '详细: ' . json_encode($e->getErrors()); } catch (RpcException $e) { echo 'RPC 调用失败: ' . $e->getMessage(); } ``` --- ## 鉴权配置 ard-api 的 `push.*` 开头的 JSON-RPC 接口已强制开启签名鉴权,由 `SignatureAuthMiddleware` 在 SVC Server 层统一拦截校验。SDK 自动完成签名计算并附加到每个请求,调用方只需传入凭据。 > **范围说明**:仅对 JSON-RPC 方法名以 `push.` 开头的接口生效(如 `push.sendToMQ`、`push.getDeviceToken`、`push.sendInternalMessage`),其他 SVC 方法(如 by_rpc 的 `get_panding_count`)不受影响,无需签名。 ### 申请凭据 在 ard-api 侧为调用方分配一对 `app_id` / `app_key`,服务端通过以下方式之一验证: - **推荐(生产)**:环境变量 `PUSH_SDK_APPKEY_{APP_ID}`(app_id 转大写) - **开发调试**:`SignatureAuthMiddleware::APP_SECRETS` 常量数组 ### 完整调用示例 ```php use FlashExpress\Push\Client; $client = new Client([ 'ard_api_endpoint' => 'http://ard-api.svc/svc/call', 'app_id' => 'your_app_id', // 必填 'app_key' => 'your_app_key', // 必填 'locale' => 'zh-CN', 'timeout' => 10, ]); $response = $client->pushToStaff([ 'src' => Client::SRC_BACKYARD, 'staff_info_id' => '100001', 'message_title' => '您有新的审批待处理', 'message_content' => '请及时前往审批中心处理', ]); if ($response->isSuccess()) { echo "推送成功\n"; } else { echo "推送失败: " . $response->getMessage() . "\n"; } ``` ### SDK 自动附加的 HTTP Header 所有对 `push.*` 方法的调用会自动附带以下 Header,调用方**无需手动设置**: | Header | 说明 | |---------------|-------------------------------------| | `X-App-Id` | 应用 ID | | `X-Timestamp` | 秒级时间戳,服务端 **±5 分钟** 有效期 | | `X-Nonce` | 32 位随机十六进制字符串 | | `X-Signature` | 签名值 | ### 签名算法(与服务端 SignatureAuthMiddleware 一致) ``` stringToSign = X-Timestamp + X-Nonce + json_encode(params, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) X-Signature = hash_hmac('sha256', stringToSign, app_key) ``` > **注意**:签名仅对 JSON-RPC 请求体的 `params` 字段计算,不包含 `jsonrpc` / `id` / `method` 等其他顶层字段。 ### 常见鉴权失败 | 服务端返回 | 原因 | 排查方向 | |-----------|------|----------| | `缺少必要 Header` | SDK 未传 `app_id` / `app_key` 或值为空 | 确认初始化配置已传凭据 | | `无效的 App ID` | app_id 在服务端未注册 | 检查 `PUSH_SDK_APPKEY_{APP_ID}` 环境变量或常量 | | `时间戳已过期` | 服务器时间与客户端差超过 5 分钟 | 检查服务器/客户端 NTP 同步 | | `签名不匹配` | 签名计算逻辑不一致 | 确认 SDK 版本与服务端 SignatureAuthMiddleware 一致 | ### 调试技巧 开启 debug 模式可在日志中看到每次请求的完整 Header、Payload 和响应: ```php $client->setDebug(true); // 或直接在 config 里传 'debug' => true $response = $client->pushToStaff([...]); // 最近一次请求的完整调试上下文 $debug = $client->getDebugInfo(); echo json_encode($debug, JSON_PRETTY_PRINT); // 包含: endpoint / method / payload / headers / http_code / curl_error / response / duration_ms ``` --- ## 架构说明 ``` ┌──────────────┐ JSON-RPC ┌──────────────┐ │ Push SDK │ ───────────▶ │ ard-api │ │ (Client) │ sendToMQ │ PushController └──────┬───────┘ getDeviceToken └──────────────┘ │ │ JSON-RPC ▼ ┌──────────────┐ │ by_rpc │ │ (待审批数) │ └──────────────┘ ``` SDK 通过 `push.*` 方法名调用 ard-api SVC 接口,通过 `get_panding_count` 调用 by_rpc。 --- ## License MIT