如何给单个设备发送推送通知?Flutter+WordPress场景技术求助
给单个设备发送Firebase推送通知的解决方案
核心逻辑
要实现「客户下单后仅给该用户发通知」,关键是把用户的Firebase设备Token和WordPress中的用户账号绑定,下单时通过WordPress获取该用户对应的Token,调用Firebase API发送专属通知。
你的疑问解答
1. 何时获取Token?
应用初始化时获取是正确的,但Token可能会因卸载重装、应用更新、设备系统变更等情况刷新,所以必须同时监听Token的变化。
2. 何时把Token发送到站点服务器?
- 第一次获取到Token时立即发送;
- 监听到Token刷新时重新发送;
- 用户在WebView中完成WordPress登录后,必须将Token与当前登录的用户ID绑定后再发送(否则服务器不知道这个Token属于哪个用户)。
3. 需要添加哪些代码?
- 新增Token刷新监听;
- 实现Token上传到WordPress的接口请求;
- 打通WebView与Flutter的通信,获取当前登录的WordPress用户ID;
- 添加本地通知展示逻辑(当前代码仅打印日志,用户看不到通知弹窗)。
修改后的main.dart代码
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:flutter/foundation.dart'; // 本地通知插件实例 final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(); print("处理后台消息: ${message.messageId}"); // 后台也展示通知 _showNotification(message); } // 展示通知弹窗的方法 void _showNotification(RemoteMessage message) async { const AndroidNotificationDetails androidDetails = AndroidNotificationDetails( 'order_notification_channel', // 通知渠道ID '订单通知', // 通知渠道名称 importance: Importance.max, priority: Priority.high, ); const NotificationDetails notificationDetails = NotificationDetails(android: androidDetails); await flutterLocalNotificationsPlugin.show( message.hashCode, message.notification?.title ?? '下单成功', message.notification?.body ?? '你的订单已提交成功,我们会尽快处理', notificationDetails, payload: json.encode(message.data), ); } // 上传Token到WordPress服务器的方法 Future<void> uploadTokenToWordPress(String? token, int? userId) async { if (token == null || userId == null) return; // WordPress自定义API接口(需要你在WordPress端开发) final url = Uri.parse('你的WordPress站点域名/wp-json/custom/v1/save-fcm-token'); final response = await http.post( url, headers: {'Content-Type': 'application/json'}, body: json.encode({ 'user_id': userId, 'fcm_token': token, }), ); if (response.statusCode == 200) { print('Token上传成功'); } else { print('Token上传失败: ${response.body}'); } } void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); FirebaseMessaging messaging = FirebaseMessaging.instance; // 请求通知权限 NotificationSettings settings = await messaging.requestPermission( alert: true, announcement: false, badge: true, carPlay: false, criticalAlert: false, provisional: false, sound: true, ); // 初始化本地通知插件 const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); const InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid); await flutterLocalNotificationsPlugin.initialize(initializationSettings); // 获取初始Token String? token = await messaging.getToken(); if (kDebugMode) { print('Registration Token=$token'); } // TODO: 这里需要从WebView获取当前登录的WordPress用户ID // 比如通过WebView的JS桥接收用户ID,示例中先设为null,后续替换 int? currentUserId = null; // 如果已经获取到用户ID,上传Token if (currentUserId != null) { await uploadTokenToWordPress(token, currentUserId); } // 监听Token刷新 FirebaseMessaging.instance.onTokenRefresh.listen((newToken) { print('Token已刷新: $newToken'); if (currentUserId != null) { uploadTokenToWordPress(newToken, currentUserId); } }); // 前台消息监听 FirebaseMessaging.onMessage.listen((RemoteMessage message) { print('收到前台消息!'); print('消息数据: ${message.data}'); _showNotification(message); }); FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( pageTransitionsTheme: const PageTransitionsTheme( builders: { TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), TargetPlatform.android: CupertinoPageTransitionsBuilder(), }, ), home: SplashScreen(), ); } } // 占位的启动页 class SplashScreen extends StatelessWidget { @override Widget build(BuildContext context) { return const Scaffold( body: Center(child: Text('启动中...')), ); } }
WordPress端需要做的操作
- 开发自定义API接口:用PHP写一个接口,接收Flutter传来的
user_id和fcm_token,将Token存入WordPress的用户元数据(user_meta)中。 - 绑定下单钩子:在WooCommerce的订单完成钩子(比如
woocommerce_order_status_completed)中,获取订单对应的用户ID,查询其存储的FCM Token,调用Firebase的sendAPI发送通知。 - 配置Firebase密钥:在WordPress后台配置Firebase的服务器密钥(从Firebase控制台的项目设置->云消息服务中获取)。
内容的提问来源于stack exchange,提问作者Daniil
相关产品推荐
相关产品推荐

