条纹 & Node.js - "Cannot POST /create-checkout-session"

Stripe & Node.js - "Cannot POST /create-checkout-session"

我正在尝试按照 Stripe Checkout 订阅说明进行操作: https://stripe.com/docs/billing/subscriptions/build-subscriptions?ui=checkout

当我提交表单时,通过本地主机我得到 "Cannot POST /create-checkout-session"(网络选项卡中的 404),如果我从我的生产服务器 运行,它只是打开 /create-checkout-session 作为新的(空白的)Vue 页面。我曾尝试将表单操作更改为 https://mydomain.xyz/create-checkout-session,但没有成功。

Subscribe.vue

<form action="/create-checkout-session" method="POST">
  <input type="hidden" name="priceId" value="[removed for Stack Overflow]" />
  <button type="submit">Checkout</button>
</form>

我不知道端点是否受到干扰,所以我复制了整个 app.js 文件:

app.js

let express = require('express'),
  cors = require('cors'),
  mongoose = require('mongoose'),
  database = require('./database'),
  bodyParser = require('body-parser');

// Set your secret key. Remember to switch to your live secret key in production.
// See your keys here: https://dashboard.stripe.com/apikeys
const stripe = require('stripe')('[removed for Whosebug]');

//connect mongoDB
mongoose.Promise = global.Promise;
mongoose.connect(database.db, {
  useNewUrlParser: true,
  useUnifiedTopology: true
}).then(() => {
  console.log("Database connected")
  },
  error => {
    console.log("Database couldn't be connected to: " + error);
  }
)

const cryptoEndPoint = require('../backend/routes/crypto.route')
const app = express();
                app.use(decodeIDToken);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: false
}));
app.use(cors())

//API
app.use('/api', cryptoEndPoint)


app.post("/create-checkout-session", async (req, res) => {

  console.log("can't even get anything to console log, only get createError is not defined");
  const { priceId } = req.body;

  // Create new Checkout Session for the order
  // Other optional params include:
  // [billing_address_collection] - to display billing address details on the page
  // [customer] - if you have an existing Stripe Customer ID
  // [customer_email] - lets you prefill the email input in the form
  // [automatic_tax] - to automatically calculate sales tax, VAT and GST in the checkout page
  // For full details see https://stripe.com/docs/api/checkout/sessions/create
  try {
    const session = await stripe.checkout.sessions.create({
      mode: 'subscription',
      line_items: [
        {
          price: priceId,
          // For metered billing, do not pass quantity
          quantity: 1,
        },
      ],
      // {CHECKOUT_SESSION_ID} is a string literal; do not change it!
      // the actual Session ID is returned in the query parameter when your customer
      // is redirected to the success page.
      success_url: 'https://mydomain.xyz/thankyou?session_id={CHECKOUT_SESSION_ID}',
      cancel_url: 'https://mydomain.xyz/thankyou',
    });

    return res.redirect(303, session.url);
  } catch (e) {
    res.status(400);
    return res.send({
      error: {
        message: e.message,
      }
    });
  }
});


//create port
const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
  console.log('Connected to port ' + port);
})

//Find 404
app.use((req, res, next) => {
  next(createError(404));
})

//error handler
app.use(function (err, req, res, next) {
  console.log(err.message);
  if (!err.statusCode) err.statusCode = 500;
  res.status(err.statusCode).send(err.message);
})




            /**
             * Decodes the JSON Web Token sent via the frontend app
             * Makes the currentUser (firebase) data available on the body.
             */
            async function decodeIDToken(req, res, next) {
              if (req.headers?.authorization?.startsWith('Bearer ')) {

                const idToken = req.headers.authorization.split('Bearer ')[1];

                // console.log(idToken);

                try {
                  const decodedToken = await admin.auth().verifyIdToken(idToken);
                  // console.log("one");
                  req['currentUser'] = decodedToken;
                  // console.log("two");
                } catch (err) {
                  console.log("error: " + err);
                }
              }

              next();
            }



            app.post("/webhook", async (req, res) => {
              let data;
              let eventType;
              // Check if webhook signing is configured.
              const webhookSecret = '[removed for Stack Overflow]'
              if (webhookSecret) {
                // Retrieve the event by verifying the signature using the raw body and secret.
                let event;
                let signature = req.headers["stripe-signature"];

                try {
                  event = stripe.webhooks.constructEvent(
                    req.body,
                    signature,
                    webhookSecret
                  );
                } catch (err) {
                  console.log(`⚠️  Webhook signature verification failed.`);
                  return res.sendStatus(400);
                }
                // Extract the object from the event.
                data = event.data;
                eventType = event.type;
              } else {
                // Webhook signing is recommended, but if the secret is not configured in `config.js`,
                // retrieve the event data directly from the request body.
                data = req.body.data;
                eventType = req.body.type;
              }

              switch (eventType) {
                  case 'checkout.session.completed':
                    //...
                    break;
                  case 'invoice.paid':
                    //...
                    break;
                  case 'invoice.payment_failed':
                    //...
                    break;
                  default:
                    
                  // Unhandled event type
                }

              res.sendStatus(200);
            });

有谁知道出了什么问题吗?

我将其添加到我的 app.js 文件中,它正在运行:

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', "*");
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    next();
}

app.use(allowCrossDomain);