英文:
Cannot redirect to a success page after submitting payment information on Stripe. Works LOCALLY but not on HEROKU. ("Cannot GET /success")
问题
I am trying to generate a success page after submitting payment information on Stripe but it doesn't work when deployed on Heroku. Locally everything works fine and I am redirected to a success page.
在部署到Heroku后,我试图在Stripe上提交付款信息后生成一个成功页面,但不起作用。在本地一切正常,我被重定向到成功页面。
After submitting payment information it just redirects to a page saying "Cannot GET /success".
提交付款信息后,它只会重定向到一个页面上,显示"Cannot GET /success"。
I am using the MERN stack.
我正在使用MERN堆栈。
I am using a test key that anyone can obtain from Stripe's documentation so there is no need to hide it in an ENV file.
我正在使用任何人都可以从Stripe文档中获取的测试密钥,因此无需将其隐藏在ENV文件中。
Here are the Heroku logs:
以下是Heroku日志:
at=info method=GET path="/success?
session_id=cs_test_a1d94XAhzPyyubwBg7Lk3FXKmpViqUYK6UGzcqON3HAdD5ELFUINJyOVsX"
host=thawing-headland-75590.herokuapp.com request_id=7aff0f42-cd34-4d12-b5b3-
858ff60e16de fwd="174.112.119.39" dyno=web.1 connect=0ms service=1ms status=404
bytes=390 protocol=https.
这是Heroku日志:
Here is what shows in the console:
这是控制台中显示的内容:
constants.override.js:1
GET https://thawing-headland-75590.herokuapp.com/success?session_id=cs_test_a1jXbh7ZPggtKlX0840DpYCfTZXr5uZp5soNzvQoCfGRVBVEpmtzfR9lPj 404 (Not Found)
a.handleSuccess @ constants.override.js:1
a @ js.stripe.com/v3/fin…36134c4204a1d0.js:1
setTimeout (async)
(anonymous) @ js.stripe.com/v3/fin…36134c4204a1d0.js:1
value @ constants.override.js:1
Lr @ content.js:1
t.unstable_runWithPriority @ content.js:1
Ot @ content.js:1
jr @ content.js:1
Sr @ content.js:1
(anonymous) @ content.js:1
t.unstable_runWithPriority @ content.js:1
Ot @ content.js:1
At @ content.js:1
Nt @ content.js:1
_r @ content.js:1
notify @ content.js:1
notifyNestedSubs @ content.js:1
n @ content.js:1
l @ content.js:1
(anonymous) @ constants.override.js:1
(anonymous) @ content.js:1
dispatch @ content.js:1
(anonymous) @ constants.override.js:1.
这是控制台中显示的内容:
Here is my server.js
这是我的server.js文件:
const express = require("express");
const { ApolloServer } = require("apollo-server-express");
const path = require("path");
const { typeDefs, resolvers } = require("./schemas");
const { authMiddleware } = require("./utils/auth");
const db = require("./config/connection");
const PORT = process.env.PORT || 3001;
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
context: authMiddleware
});
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.use("/images", express.static(path.join(__dirname, "../client/images")));
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "../client/build")));
}
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "../client/build/index.html"));
});
const startApolloServer = async (typeDefs, resolvers) => {
await server.start();
server.applyMiddleware({ app });
db.once("open", () => {
app.listen(PORT, () => {
console.log(`API server running on port ${PORT}!`);
console.log(`Use GraphQL at http://localhost:${PORT}${server.graphqlPath}`);
});
});
};
startApolloServer(typeDefs, resolvers);
这是我的server.js文件:
Here is my resolver.js
这是我的resolver.js文件:
const { AuthenticationError } = require("apollo-server-express");
const { User, Product, Console, Order } = require("../models");
const { signToken } = require("../utils/auth");
const stripe = require("stripe")("sk_test_123");
const resolvers = {
Query: {
consoles: async () => {
return await Console.find();
},
products: async (parent, { console, name }) => {
const params = {};
if (console) {
params.console = console;
}
if (name) {
params.name = {
$regex: name
};
}
return await Product.find(params).populate("console");
},
product: async (parent, { _id }) => {
return await Product.findById(_id).populate("console");
},
user: async (parent, args, context) => {
if (context.user) {
const user = await User.findById(context.user._id).populate({
path: "orders.products",
populate: "console"
});
user.orders.sort((a, b) => b.purchaseDate - a.purchaseDate);
return user;
}
throw new AuthenticationError("Not logged in");
},
order: async (parent, { _id }, context) => {
if (context.user) {
const user = await User.findById(context.user._id).populate({
path: "orders.products",
populate: "console"
});
return user.orders.id(_id);
}
throw new AuthenticationError("Not logged in");
},
checkout: async (parent, args, context) => {
const url = new URL(context.headers.referer).origin;
const order = new Order({ products: args.products });
const line_items = [];
const { products } = await order.populate("products");
for (let i = 0; i < products.length; i++) {
const product = await stripe.products.create({
name: products[i].name,
description: products[i].description,
images: [`${url}/images/${products[i].image}`]
});
const price = await stripe.prices.create({
product: product.id,
unit_amount: products[i].price * 100,
currency: "usd",
});
line_items.push({
price: price.id,
quantity: 1
});
}
const session = await stripe.checkout.sessions
<details>
<summary>英文:</summary>
I am trying to generate a success page after submitting payment information on Stripe but it doesn't work when deployed on Heroku. Locally everything works fine and I am redirected to a success page.
After submitting payment information it just redirects to a page saying "Cannot GET /success".
I am using the MERN stack.
I am using a test key that anyone can obtain from stripes documentation so there is no need to hide it in an ENV file.
Here are the Heroku logs:
at=info method=GET path="/success?
session_id=cs_test_a1d94XAhzPyyubwBg7Lk3FXKmpViqUYK6UGzcqON3HAdD5ELFUINJyOVsX"
host=thawing-headland-75590.herokuapp.com request_id=7aff0f42-cd34-4d12-b5b3-
858ff60e16de fwd="174.112.119.39" dyno=web.1 connect=0ms service=1ms status=404
bytes=390 protocol=https.
Here is what shows in the console:
constants.override.js:1
GET https://thawing-headland-75590.herokuapp.com/success?session_id=cs_test_a1jXbh7ZPggtKlX0840DpYCfTZXr5uZp5soNzvQoCfGRVBVEpmtzfR9lPj 404 (Not Found)
a.handleSuccess @ constants.override.js:1
a @ js.stripe.com/v3/fin…36134c4204a1d0.js:1
setTimeout (async)
(anonymous) @ js.stripe.com/v3/fin…36134c4204a1d0.js:1
value @ constants.override.js:1
Lr @ content.js:1
t.unstable_runWithPriority @ content.js:1
Ot @ content.js:1
jr @ content.js:1
Sr @ content.js:1
(anonymous) @ content.js:1
t.unstable_runWithPriority @ content.js:1
Ot @ content.js:1
At @ content.js:1
Nt @ content.js:1
_r @ content.js:1
notify @ content.js:1
notifyNestedSubs @ content.js:1
n @ content.js:1
l @ content.js:1
(anonymous) @ constants.override.js:1
(anonymous) @ content.js:1
dispatch @ content.js:1
(anonymous) @ constants.override.js:1.
Here is my server.js
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const express = require("express");
const { ApolloServer } = require("apollo-server-express");
const path = require("path");
const { typeDefs, resolvers } = require("./schemas");
const { authMiddleware } = require("./utils/auth");
const db = require("./config/connection");
const PORT = process.env.PORT || 3001;
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
context: authMiddleware
});
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.use("/images", express.static(path.join(__dirname, "../client/images")));
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "../client/build")));
}
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "../client/build/index.html"));
});
const startApolloServer = async (typeDefs, resolvers) => {
await server.start();
server.applyMiddleware({ app });
db.once("open", () => {
app.listen(PORT, () => {
console.log(`API server running on port ${PORT}!`);
console.log(`Use GraphQL at http://localhost:${PORT}${server.graphqlPath}`);
})
})
};
startApolloServer(typeDefs, resolvers);
<!-- end snippet -->
Here is my resolver.js
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const { AuthenticationError } = require("apollo-server-express");
const { User, Product, Console, Order } = require("../models");
const { signToken } = require("../utils/auth");
const stripe = require("stripe")("sk_test_123");
const resolvers = {
Query: {
consoles: async () => {
return await Console.find();
},
products: async (parent, { console, name }) => {
const params = {};
if (console) {
params.console = console;
}
if (name) {
params.name = {
$regex: name
};
}
return await Product.find(params).populate("console");
},
product: async (parent, { _id }) => {
return await Product.findById(_id).populate("console");
},
user: async (parent, args, context) => {
if (context.user) {
const user = await User.findById(context.user._id).populate({
path: "orders.products",
populate: "console"
});
user.orders.sort((a, b) => b.purchaseDate - a.purchaseDate);
return user;
}
throw new AuthenticationError("Not logged in");
},
order: async (parent, { _id }, context) => {
if (context.user) {
const user = await User.findById(context.user._id).populate({
path: "orders.products",
populate: "console"
});
return user.orders.id(_id);
}
throw new AuthenticationError("Not logged in");
},
checkout: async (parent, args, context) => {
const url = new URL(context.headers.referer).origin;
const order = new Order({ products: args.products });
const line_items = [];
const { products } = await order.populate("products");
for (let i = 0; i < products.length; i++) {
const product = await stripe.products.create({
name: products[i].name,
description: products[i].description,
images: [`${url}/images/${products[i].image}`]
});
const price = await stripe.prices.create({
product: product.id,
unit_amount: products[i].price * 100,
currency: "usd",
});
line_items.push({
price: price.id,
quantity: 1
});
}
const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
line_items,
mode: "payment",
success_url: `${url}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${url}/`
});
return { session: session.id };
}
<!-- end snippet -->
Like I said before, everything works fine locally so I am kind of stuck as to why it won't work on Heroku. Every other part of this website works fine on Heroku. It is just going from PAYMENT to SUCCESS where there is a problem.
Thanks in advance!
</details>
# 答案1
**得分**: 0
现在可以正常工作了。在错误的方向上花了很多小时后,我只需要在我的 `server.js` 文件中添加以下内容:
```js
app.get("/success", (req, res) => {
res.sendFile(path.join(__dirname, "../client/build/index.html"));
});
英文:
It works now. After many hours of looking in the wrong direction all I needed to do was add the following in my server.js
file:
app.get("/success", (req, res) => {
res.sendFile(path.join(__dirname, "../client/build/index.html"));
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论