使用 Vercel + Supabase (React JS) 时如何访问 Stripe webhooks

问题描述 投票:0回答:1

我一直在绕圈子 - 我会尽量保持简洁。

我有一个 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'),
      },
    },
  },
})

我非常困惑,希望得到任何见解。

reactjs stripe-payments vercel supabase
1个回答
0
投票

这应该可以解决那些在本地但在 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

© www.soinside.com 2019 - 2024. All rights reserved.