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

Flutter迁移Supabase后如何实现数据库触发的推送通知?

实现数据库变更触发推送通知的方案

核心思路

Supabase本身没有内置推送通知服务,但可以通过PostgreSQL触发器+自定义函数结合外部推送服务(比如你之前用的FCM)实现需求,流程如下:

  1. 在Supabase数据库存储用户设备令牌
  2. 编写PostgreSQL函数,在目标表变更时调用外部推送API
  3. 给目标表绑定触发器,触发上述函数

具体步骤

1. 存储设备令牌

先创建存储令牌的表:

CREATE TABLE user_devices (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
  device_token TEXT NOT NULL,
  platform TEXT CHECK (platform IN ('ios', 'android')) NOT NULL,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

Flutter端将从firebase_messaging获取的设备令牌插入该表即可。

2. 创建推送函数

以调用FCM API为例,先启用http扩展:

CREATE EXTENSION IF NOT EXISTS http;

再创建推送函数:

CREATE OR REPLACE FUNCTION send_push_notification()
RETURNS TRIGGER AS $$
DECLARE
  target_token TEXT;
  fcm_api_key TEXT := '你的FCM服务器密钥'; -- 替换为实际密钥
BEGIN
  -- 根据业务逻辑获取目标用户令牌,这里假设触发表关联user_id
  SELECT device_token INTO target_token
  FROM user_devices
  WHERE user_id = NEW.user_id;

  IF target_token IS NOT NULL THEN
    PERFORM http_post(
      'https://fcm.googleapis.com/fcm/send',
      json_build_object(
        'to', target_token,
        'notification', json_build_object(
          'title', '数据更新',
          'body', '你的相关内容已变更'
        )
      )::TEXT,
      ARRAY[
        'Content-Type: application/json',
        'Authorization: key=' || fcm_api_key
      ]
    );
  END IF;

  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

3. 绑定触发器到目标表

比如当orders表发生更新时触发推送:

CREATE TRIGGER trigger_order_update
AFTER UPDATE ON orders
FOR EACH ROW
EXECUTE FUNCTION send_push_notification();

替代方案:使用Supabase Edge Functions

若不想用PostgreSQL函数,可基于Deno编写Edge Function处理:

  1. 创建Edge Function(示例TypeScript代码):
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";

serve(async (req) => {
  const supabase = createClient(
    Deno.env.get("SUPABASE_URL")!,
    Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!
  );

  const { userId } = await req.json();

  const { data: devices } = await supabase
    .from("user_devices")
    .select("device_token")
    .eq("user_id", userId);

  if (devices && devices.length > 0) {
    await fetch("https://fcm.googleapis.com/fcm/send", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `key=${Deno.env.get("FCM_API_KEY")}`
      },
      body: JSON.stringify({
        to: devices[0].device_token,
        notification: {
          title: "数据更新",
          body: "你的相关内容已变更"
        }
      })
    });
  }

  return new Response(JSON.stringify({ status: "success" }), {
    headers: { "Content-Type": "application/json" },
  });
});
  1. 创建触发器调用该Edge Function:
CREATE OR REPLACE FUNCTION call_edge_function()
RETURNS TRIGGER AS $$
BEGIN
  PERFORM http_post(
    '你的Edge Function URL',
    json_build_object('userId', NEW.user_id)::TEXT,
    ARRAY['Content-Type: application/json']
  );
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_data_change
AFTER INSERT ON your_table
FOR EACH ROW
EXECUTE FUNCTION call_edge_function();

注意事项

  • 推送服务密钥需存入Supabase环境变量,避免硬编码
  • 需处理令牌失效场景,比如FCM返回无效令牌时,从user_devices表删除对应条目
  • 批量变更场景需考虑性能,避免频繁调用推送API

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 08:06:51