条纹 & 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);
我正在尝试按照 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);