如何在Express PayPal支付流程的外部函数中获取amount变量?
amount from /pay to /success Route in Express PayPal Integration Got it, let's work through this problem. The key issue here is that after redirecting the user to PayPal's approval page and then back to your /success route, you lose access to the original req.body data from the /pay request. Here are three reliable approaches to share the amount value between these routes:
1. Use Express Session (Recommended for Most Cases)
Session storage is a secure way to persist user-specific data across requests. Here's how to implement it:
First, install the express-session package if you haven't already:
npm install express-session
Then configure session middleware in your Express app (add this before your route definitions):
const session = require('express-session'); app.use(session({ secret: 'your-strong-unique-secret-key', // Replace with a secure, unique secret resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production' } // Enable secure cookies in production }));
Modify your /pay route to store the amount in the session:
app.post("/pay", (req, res) => { console.log(req.body); const { amount , description , name } = req.body; // Store the amount in the user's session req.session.paymentAmount = amount; const create_payment_json = { intent: "sale", payer: { payment_method: "paypal", }, redirect_urls: { return_url: "http://localhost:3000/success", cancel_url: "http://localhost:3000/cancel", }, transactions: [ { item_list: { items: [ { name: name, sku: "001", price: amount, currency: "USD", quantity: 1, }, ], }, amount: { currency: "USD", total: amount, }, description: description, }, ], }; paypal.payment.create(create_payment_json, function (error, payment) { if (error) { throw error; } else { for (let i = 0; i < payment.links.length; i++) { if (payment.links[i].rel === "approval_url") { res.redirect(payment.links[i].href); } } } }); });
Update your /success route to retrieve the amount from the session (and clear it after use):
app.get("/success", (req, res) => { const payerId = req.query.PayerID; const paymentId = req.query.paymentId; const amount = req.session.paymentAmount; // Fetch amount from session // Optional: Clear the session value to prevent accidental reuse delete req.session.paymentAmount; const execute_payment_json = { payer_id: payerId, transactions: [ { amount: { currency: "USD", total: amount, }, }, ], }; paypal.payment.execute( paymentId, execute_payment_json, function (error, payment) { if (error) { console.log(error.response); } else { console.log(JSON.stringify(payment)); res.send("Success"); } } ); });
2. Store Amount in PayPal Payment's Custom Field
You can embed the amount directly into the PayPal payment object using the custom field, then retrieve it when handling the success callback. This ties the data directly to the payment itself:
Modify the /pay route's create_payment_json to include the custom field:
const create_payment_json = { intent: "sale", payer: { payment_method: "paypal", }, redirect_urls: { return_url: "http://localhost:3000/success", cancel_url: "http://localhost:3000/cancel", }, transactions: [ { item_list: { items: [ { name: name, sku: "001", price: amount, currency: "USD", quantity: 1, }, ], }, amount: { currency: "USD", total: amount, }, description: description, custom: amount // Store the amount in this custom field }, ], };
In the /success route, first fetch the payment details to get the custom value:
app.get("/success", (req, res) => { const payerId = req.query.PayerID; const paymentId = req.query.paymentId; // First retrieve the payment details to get the stored amount paypal.payment.get(paymentId, function(error, payment) { if (error) { console.log(error.response); return res.send("Error retrieving payment details"); } const amount = payment.transactions[0].custom; // Extract amount from custom field const execute_payment_json = { payer_id: payerId, transactions: [ { amount: { currency: "USD", total: amount, }, }, ], }; paypal.payment.execute( paymentId, execute_payment_json, function (error, payment) { if (error) { console.log(error.response); } else { console.log(JSON.stringify(payment)); res.send("Success"); } } ); }); });
3. Avoid: Pass Amount via Return URL Parameters
While you could append the amount to your return_url like http://localhost:3000/success?amount=${amount}, this is not recommended. URLs are easily tampered with, so a malicious user could modify the amount parameter before returning to your site, leading to incorrect payment execution. Only use this method for non-sensitive data.
内容的提问来源于stack exchange,提问作者AnonymousKing

