从本地主机运行的Stripe结帐示例遇到CORS错误

30

我试图按照这里的说明https://stripe.com/docs/payments/accept-a-payment?integration=checkout在node中集成Stripe结账(Checkout)功能。

我完全按照他们的说明进行操作,并将示例中的API密钥更新为我的帐户中的实际(测试)密钥。

我在前端使用React,在后端使用express,并启用了cors。

来自React到后端的请求成功,并触发了一个预检请求(preflight request)到Stripe。 Stripe的预检响应是403,实际请求因CORS错误被阻止 -PreflightMissingAllowOriginHeader

后端代码(最小化)

const express = require("express");
const app = express();
const cors = require("cors");

const stripe = require("stripe")(
  process.env.STRIPE_SECRET_KEY
);

app.use(
  cors({
    origin: ["http://localhost:8000", "https://checkout.stripe.com"],
  })
);

app.post("/create-checkout-session", async (req, res) => {
  console.log('getting here 1')
  const session = await stripe.checkout.sessions.create({
    payment_method_types: ["card"],
    line_items: [
      {
        price_data: {
          currency: "usd",
          product_data: {
            name: "T-shirt",
          },
          unit_amount: 2000,
        },
        quantity: 1,
      },
    ],
    mode: "payment",
    success_url: "http://localhost:4242/success.html",
    cancel_url: "http://localhost:4242/cancel.html",
  });
  
  console.log('getting here 2')
  res.redirect(303, session.url);
});

app.listen(4242, () => console.log(`Listening on port ${4242}!`));

前端代码

  handleClick = () => {
    const res = fetch(`${process.env.BACKEND_API_URL}/create-checkout-session`, {
      method: 'POST',
      headers: {
        "Content-Type": 'text/html'
      }
    })
  }

9
在这里,你正在使用fetch执行Ajax POST调用。在POST请求中,res.redirect不起作用。相反,你有两个选择:选项1:在/create-checkout-session中返回JSON,在获取结果后,在前端重定向;选项2:执行一个“表单提交POST”,而不是使用fetch - wsw
谢谢。最终选择了选项1,它起作用了! - saq7
1个回答

57
以下是我在尝试调试时学到的一些内容:
  1. Stripe checkout使用AWS Cloudfront,它不允许选项请求(根据Stripe的配置)
  2. 当我在前端更改请求类型为text/plain时,OPTIONS请求不会发送到Stripe。(是的,在我的服务器返回带有Stripe网址的303后,Chrome不会向Stripe发送OPTIONS请求)
  3. 在使用React时最好避免重定向
以下是解决问题的更新后端和前端代码,分别如下:
app.post("/create-checkout-session", async (req, res) => {
  const session = await stripe.checkout.sessions.create({
    payment_method_types: ["card"],
    line_items: [
      {
        price_data: {
          currency: "usd",
          product_data: {
            name: "T-shirt",
          },
          unit_amount: 2000,
        },
        quantity: 1,
      },
    ],
    mode: "payment",
    success_url: "http://localhost:8000/success",
    cancel_url: "http://localhost:8000/cancel",
  });

  res.json({url: session.url}) // <-- this is the changed line
});

  handleClick = async () => {
    const res = await fetch(`${process.env.BACKEND_API_URL}/create-checkout-session`, {
      method: 'POST',
      headers: {
        "Content-Type": 'application/json'
      }
    })
    const body = await res.json()
    window.location.href = body.url
  }


有道理,感谢您发布解决方案。最终,它只是利用SPA和现代后端协议,跳过旧的遗留重定向方法。 - Gabe Karkanis
对于C# dotnet,您可以遵循类似的模式并返回Ok(session.Url) - Corey P

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接