我一直在绕圈子 - 我会尽量保持简洁。
我有一个 React JS 应用程序,并与 Stripe 集成用于计费。我有一个免费增值版本,但如果有人想要使用付费计划,他们可以在应用程序中升级 > 他们会被重定向到 stripe 的结帐处。我传递实例 ID,然后使用它来更新 Supabase 中的数据库以更新他们的计划数据,这样我就可以更新他们的功能可见性。
当我运行服务器时,它在本地工作,但是我使用 vercel 进行部署,并且它不托管服务器。所以我创建了一个 api/stripe-webhook 文件并添加了以下代码。然而它不起作用,在 Stripe 的仪表板中我可以看到我收到了 HTTP 状态代码 405(方法不允许)响应。
const { createClient } = require('@supabase/supabase-js')
const stripe = require('stripe')(process.env.VITE_STRIPE_SECRET_KEY_TEST)
const supabaseUrl = process.env.VITE_SUPABASE_URL
const supabaseAnonKey = process.env.VITE_SUPABASE_ANON_KEY
const service_role_key = process.env.VITE_SUPABASE_SERVICE_KEY
const supabase = createClient(supabaseUrl, supabaseAnonKey)
const supabaseAdmin = createClient(supabaseUrl, service_role_key, {
auth: {
autoRefreshToken: true,
persistSession: true,
supabaseClient: supabase,
},
})
const signingSecretTest = process.env.VITE_STRIPE_WEBHOOK_TEST
module.exports = async (req, res) => {
try {
const rawBody = req.body.toString('utf8')
const sigHeader = req.headers['stripe-signature']
const event = stripe.webhooks.constructEvent(
rawBody,
sigHeader,
signingSecretTest,
)
if (event.type === 'checkout.session.completed') {
const session = event.data.object
console.log(session)
if (session?.payment_status === 'paid' && session?.client_reference_id) {
const updateData = {
last_payment_amount: session?.amount_total,
last_payment_date: session?.created,
plan_status: 'active',
instance_id: session?.client_reference_id,
plan_name: 'standard',
price_per_seat:15
}
const { error } = await supabaseAdmin
.from('settings')
.update(updateData)
.eq('instance_id', session?.client_reference_id)
if (error) {
console.error('Error updating settings:', error)
}
}
}
return new Response('Webhook received successfully', {
status: 200,
headers: {
'Access-Control-Allow-Origin': '*',
},
})
} catch (err) {
console.error('Webhook error:', err)
res.status(400).send(`Webhook Error: ${err.message}`)
}
}
我尝试/做过的事情:
将 stripe-webhook.js 文件放在非常具体的位置(/api/stripe-webhook.js)
向我的 vercel 配置文件添加了信息,告诉它在哪里查找。
检查了 Vercel 中的所有环境变量
检查所有环境变量是否正确,并且我正在访问测试模式版本。
检查它是否在本地模式下工作 - 确实如此(未包含我的 server.js 代码,但可以根据需要添加)。
使用邮递员检查我是否遇到同样的错误 - 我确实遇到了。还是405方法不允许。
复制 Supabase 中的设置表并将新的设置表公开,以防与行级安全性相关。没有改变,恢复了。
我的 vercel.json:
{
"routes": [
{
"src": "/[^.]+",
"dest": "/",
"status": 200
},
{
"src": "/api/stripe-webhook",
"methods": ["POST", "OPTIONS"],
"headers": {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST",
"Access-Control-Allow-Headers": "Content-Type"
},
"dest": "/api/stripe-webhook.js"
}
]
}
我的vite.config:
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
export default defineConfig({
define: {
'process.env.VITE_STRIPE_API_KEY_PUBLISHABLE_TEST': JSON.stringify(
process.env.VITE_STRIPE_API_KEY_PUBLISHABLE_TEST,
),
},
plugins: [react()],
base: '/',
test: {
environment: 'jsdom',
},
build: {
outDir: 'dist',
assetsDir: 'assets',
},
server: {
watch: {
usePolling: true,
},
proxy: {
'/api': {
target: my url,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '/api/stripe-webhook'),
},
},
},
})
我非常困惑,希望得到任何见解。
这应该可以解决那些在本地但在 VERCEL / NETLIFY 上无法使用该解决方案的人的问题
如果您的应用程序位于 VERCEL 上,请编辑您的
.vercel.json
文件以包含以下代码。请记下 proxy
这个词,因为它是保留关键字。
抄送:https://vercel.com/docs/projects/project-configuration#rewrites
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
proxy: {
"/proxy": {
target: "https://example.com",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/proxy/, '')
},
},
}
})
.vercel.json
{
"rewrites": [
{ "source": "/proxy/:match*",
"destination": "https://example.com/:match*"
}
]
}
如果您的应用程序位于 NETLIFY 上,请编辑您的
_redirects
文件以包含以下代码。请记下 :splat
这个词,因为它是保留关键字。
抄送:https://docs.netlify.com/routing/redirects/rewrites-proxies/#shadowing
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
//
export default defineConfig({
plugins: [react()],
server: {
proxy: {
"/api": {
target: "https://example.com",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
},
},
}
})https://vitejs.dev/config/
_redirects
/api/* https://api.example.com/:splat 200