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

Flutter中OneSignal基于用户推送通知遇问题:无external_user_id方法且调用报错

Flutter中基于OneSignal实现用户定向推送的解决方案

错误原因分析

你遇到的错误是因为postNotificationWithJson是客户端侧方法,但调用OneSignal推送API必须携带REST API密钥做身份验证。直接在客户端调用这个方法不仅需要暴露密钥(严重不安全),而且SDK本身也不推荐这种做法——客户端的核心职责是接收推送和关联用户ID,推送逻辑应该放在后端服务中。

正确实现步骤

1. 客户端绑定External User ID

在Flutter客户端中,将你的业务系统用户ID绑定到OneSignal设备上,完成用户与设备的关联:

// 用户登录成功后调用此方法
await OneSignal.shared.setExternalUserId("123456789");

2. 后端调用OneSignal REST API发送推送

所有推送请求必须由后端发起,以此安全存储和使用REST API密钥。以下是两种实现示例:

示例1:curl命令(快速测试用)

curl --request POST \
--url https://onesignal.com/api/v1/notifications \
--header 'Authorization: Basic 你的REST_API密钥' \
--header 'Content-Type: application/json' \
--data '{
  "app_id": "你的OneSignal应用ID",
  "include_external_user_ids": ["123456789"],
  "contents": {"en": "test notification"}
}'

示例2:Dart后端代码(生产环境用)

如果后端基于Dart/Flutter开发,可使用http包发送请求:

import 'package:http/http.dart' as http;
import 'dart:convert';

Future<void> sendUserNotification(String externalUserId) async {
  const String restApiKey = '你的REST_API密钥';
  const String appId = '你的OneSignal应用ID';

  final Uri apiUrl = Uri.parse('https://onesignal.com/api/v1/notifications');
  final Map<String, String> headers = {
    'Authorization': 'Basic $restApiKey',
    'Content-Type': 'application/json',
  };
  final Map<String, dynamic> body = {
    'app_id': appId,
    'include_external_user_ids': [externalUserId],
    'contents': {'en': 'test notification'},
  };

  final http.Response response = await http.post(
    apiUrl,
    headers: headers,
    body: jsonEncode(body),
  );

  if (response.statusCode != 200) {
    throw Exception('推送失败:${response.body}');
  }
}

关键注意事项

  • 绝对禁止在客户端代码中硬编码REST API密钥:密钥一旦泄露,攻击者可随意调用你的OneSignal API,造成推送滥用或配额消耗。
  • 客户端仅需完成用户ID与设备的绑定,推送的触发、内容组装逻辑全部交给后端,既灵活又安全。

内容的提问来源于stack exchange,提问作者Hüseyin Sezen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:25:40