You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用exponent-server-sdk-php推送安卓通知失败,求排查指导

Expo PHP推送通知失败问题排查

核心问题

使用exponent-server-sdk-php实现PHP后端向安卓APP用户推送通知,但推送未成功:无报错日志,首次执行生成token文件,但安卓设备未收到通知。

关键错误点

  • Recipient字段填写错误:将Firebase服务器密钥填入ExponentPushToken[]是完全错误的用法。ExponentPushToken必须是客户端(React Native/Expo APP)生成的用户设备推送令牌,而非Firebase服务器密钥。

当前代码存在的问题

  1. 订阅后立即取消订阅:代码中先执行$expo->subscribe($channelName, $recipient),紧接着调用$expo->unSubscribe($channelName, $recipient),导致目标用户根本不在订阅频道内,无法收到通知。
  2. Notification数据格式错误:data字段使用json_encode处理,Expo通知的data应直接传入数组,无需提前JSON编码,否则客户端解析会异常。
  3. 异常捕获不完整:仅捕获ExpoException,未覆盖其他类型异常,导致部分错误无法被记录。

修复步骤与建议

1. 获取正确的Expo Push Token

在React Native/Expo客户端通过expo-notifications库生成用户设备的推送令牌,示例客户端代码:

import * as Notifications from 'expo-notifications';

async function getPushToken() {
  const { status } = await Notifications.requestPermissionsAsync();
  if (status === 'granted') {
    const token = await Notifications.getExpoPushTokenAsync({
      projectId: '你的Expo项目ID',
    });
    // 将token发送到PHP后端存储(如数据库)
    console.log(token.data); // 格式为ExponentPushToken[xxxxxxx]
  }
}

后端需从存储中取出所有有效的用户Push Token,而非填入Firebase服务器密钥。

2. 修复PHP代码

$response = array();
require_once __DIR__.'/exponent-server-sdk-php/vendor/autoload.php';

use ExponentPhpSDK\Expo;
use ExponentPhpSDK\ExpoException;

$channelName = 'video_alert';
// 从数据库获取的用户Push Token列表(示例取单个测试)
$recipientTokens = [
    'ExponentPushToken[AAAAnrlyESE:APA91bHYeOkFi5MlUB9eitKn1yEuReJ1dNrRSnlMob0lcBLAjoanDaAIposGTBWQD164CGMV8F0hriJtsXuaFPdoKxEpjtrnXshoxlZQmxdlrCjP_F5TyRToNGP43YqwahCd6XYhKvwX]'
];

$expo = Expo::normalSetup();

// 批量订阅用户到频道(按需使用)
foreach ($recipientTokens as $token) {
    $expo->subscribe($channelName, $token);
}

// 构建正确格式的通知数据
$notification = [
    'title' => 'Watch Movies',
    'body' => 'Catch new latest movie ('.$movie_title.') on DooBuxx Movies today!',
    'data' => ['notification_type' => 'service_requested']
];

try {
    // 通知频道内的所有订阅用户
    $expo->notify([$channelName], $notification);
    $response["message"] = "通知已发送";
} catch (ExpoException $e) {
    $response["message"] = "Expo错误:".$e->getMessage();
} catch (\Exception $e) {
    $response["message"] = "系统错误:".$e->getMessage();
}

// 按需取消订阅(如不需要长期保留频道订阅)
// foreach ($recipientTokens as $token) {
//     $expo->unSubscribe($channelName, $token);
// }

3. 额外排查项

  • 确认Expo项目已正确配置Firebase安卓凭据:在Expo控制台项目设置中,填入google-services.json相关信息。
  • 单Token测试:先用单个有效客户端Token调用$expo->notify($singleToken, $notification),排除频道订阅逻辑问题。
  • 服务器网络检查:确保PHP服务器可访问Expo推送API(https://exp.host/--/api/v2/push/send),无防火墙或代理限制。
  • 查看Expo推送记录:在Expo控制台的「Notifications」面板,查看推送状态及失败原因。

内容的提问来源于stack exchange,提问作者Tosin Seyi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 12:05:27