Supabase第三方集成 #
一、Vercel集成 #
1.1 一键部署 #
text
Vercel集成步骤
├── 1. 访问 Vercel Marketplace
├── 2. 搜索 Supabase
├── 3. 点击 Add Integration
├── 4. 选择 Vercel 项目
├── 5. 选择 Supabase 项目
└── 6. 自动配置环境变量
1.2 手动配置 #
bash
# 在Vercel项目设置中添加环境变量
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
1.3 Vercel CLI #
bash
# 拉取环境变量
vercel env pull .env.local
# 添加环境变量
vercel env add NEXT_PUBLIC_SUPABASE_URL
二、Netlify集成 #
2.1 环境变量配置 #
bash
# netlify.toml
[build]
command = "npm run build"
publish = "dist"
[build.environment]
NEXT_PUBLIC_SUPABASE_URL = "https://xxx.supabase.co"
NEXT_PUBLIC_SUPABASE_ANON_KEY = "your-anon-key"
2.2 Netlify Functions #
javascript
// netlify/functions/hello.js
const { createClient } = require('@supabase/supabase-js')
exports.handler = async (event) => {
const supabase = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_SERVICE_ROLE_KEY
)
const { data } = await supabase.from('posts').select('*')
return {
statusCode: 200,
body: JSON.stringify(data),
}
}
三、Stripe集成 #
3.1 数据库表设计 #
sql
-- 订阅表
CREATE TABLE subscriptions (
id BIGSERIAL PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) NOT NULL,
stripe_customer_id TEXT UNIQUE,
stripe_subscription_id TEXT UNIQUE,
status TEXT NOT NULL,
price_id TEXT,
current_period_start TIMESTAMPTZ,
current_period_end TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- 支付历史
CREATE TABLE payment_history (
id BIGSERIAL PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) NOT NULL,
stripe_payment_intent_id TEXT UNIQUE,
amount INTEGER NOT NULL,
currency TEXT NOT NULL,
status TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
3.2 Webhook处理 #
typescript
// functions/stripe-webhook/index.ts
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
Deno.serve(async (req) => {
const signature = req.headers.get('stripe-signature')
const body = await req.text()
// 验证Webhook签名
// ...
const event = JSON.parse(body)
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
)
switch (event.type) {
case 'customer.subscription.created':
case 'customer.subscription.updated':
const subscription = event.data.object
await supabase.from('subscriptions').upsert({
user_id: subscription.metadata.user_id,
stripe_subscription_id: subscription.id,
stripe_customer_id: subscription.customer,
status: subscription.status,
current_period_start: new Date(subscription.current_period_start * 1000),
current_period_end: new Date(subscription.current_period_end * 1000),
})
break
case 'customer.subscription.deleted':
await supabase
.from('subscriptions')
.update({ status: 'canceled' })
.eq('stripe_subscription_id', event.data.object.id)
break
}
return new Response(JSON.stringify({ received: true }), {
headers: { 'Content-Type': 'application/json' },
})
})
3.3 创建订阅 #
typescript
// functions/create-checkout/index.ts
Deno.serve(async (req) => {
const { priceId } = await req.json()
const authHeader = req.headers.get('Authorization')
// 获取用户
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_ANON_KEY')!,
{ global: { headers: { Authorization: authHeader! } } }
)
const { data: { user } } = await supabase.auth.getUser()
// 创建Stripe Checkout Session
const response = await fetch('https://api.stripe.com/v1/checkout/sessions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${Deno.env.get('STRIPE_SECRET_KEY')}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
'mode': 'subscription',
'payment_method_types[]': 'card',
'line_items[0][price]': priceId,
'line_items[0][quantity]': '1',
'success_url': `${Deno.env.get('SITE_URL')}/success`,
'cancel_url': `${Deno.env.get('SITE_URL')}/cancel`,
'metadata[user_id]': user!.id,
}),
})
const session = await response.json()
return new Response(JSON.stringify({ url: session.url }), {
headers: { 'Content-Type': 'application/json' },
})
})
四、GitHub集成 #
4.1 OAuth配置 #
text
GitHub OAuth设置
├── 1. GitHub Settings > Developer settings > OAuth Apps
├── 2. 创建新应用
├── 3. 设置回调URL
│ └── https://xxx.supabase.co/auth/v1/callback
└── 4. 获取Client ID和Secret
4.2 Supabase配置 #
text
Dashboard > Authentication > Providers > GitHub
配置
├── Enable GitHub provider
├── Client ID
├── Client Secret
└── Redirect URL
4.3 使用GitHub登录 #
typescript
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'github',
options: {
scopes: 'repo user',
},
})
五、OpenAI集成 #
5.1 聊天功能 #
typescript
// functions/chat/index.ts
Deno.serve(async (req) => {
const { messages } = await req.json()
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${Deno.env.get('OPENAI_API_KEY')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-4-turbo-preview',
messages,
}),
})
const data = await response.json()
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
})
})
5.2 向量嵌入 #
typescript
// functions/embed/index.ts
Deno.serve(async (req) => {
const { text } = await req.json()
const response = await fetch('https://api.openai.com/v1/embeddings', {
method: 'POST',
headers: {
'Authorization': `Bearer ${Deno.env.get('OPENAI_API_KEY')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'text-embedding-ada-002',
input: text,
}),
})
const data = await response.json()
const embedding = data.data[0].embedding
// 存储到Supabase
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
)
await supabase.from('documents').insert({
content: text,
embedding,
})
return new Response(JSON.stringify({ success: true }), {
headers: { 'Content-Type': 'application/json' },
})
})
六、Twilio集成 #
6.1 发送短信 #
typescript
// functions/send-sms/index.ts
Deno.serve(async (req) => {
const { to, message } = await req.json()
const accountSid = Deno.env.get('TWILIO_ACCOUNT_SID')
const authToken = Deno.env.get('TWILIO_AUTH_TOKEN')
const fromNumber = Deno.env.get('TWILIO_PHONE_NUMBER')
const response = await fetch(
`https://api.twilio.com/2010-04-01/Accounts/${accountSid}/Messages.json`,
{
method: 'POST',
headers: {
'Authorization': `Basic ${btoa(`${accountSid}:${authToken}`)}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
To: to,
From: fromNumber!,
Body: message,
}),
}
)
const data = await response.json()
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
})
})
七、Resend邮件集成 #
7.1 发送邮件 #
typescript
// functions/send-email/index.ts
Deno.serve(async (req) => {
const { to, subject, html } = await req.json()
const response = await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${Deno.env.get('RESEND_API_KEY')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
from: 'noreply@yourdomain.com',
to,
subject,
html,
}),
})
const data = await response.json()
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
})
})
八、总结 #
第三方集成要点:
| 服务 | 用途 |
|---|---|
| Vercel | 部署托管 |
| Netlify | 部署托管 |
| Stripe | 支付订阅 |
| GitHub | OAuth登录 |
| OpenAI | AI功能 |
| Twilio | 短信服务 |
| Resend | 邮件服务 |
下一步,让我们学习自托管部署!
最后更新:2026-03-28