I'm trying to build an App which allows the customer to download a custom document after his order (so, the product I'm selling it's a digital custom document in pdf).
I'm trying to build that using React for the frontend, Node and Express for the backend, and PayPal Express Checkout (full-stack implementation) as payment.
What is not clear to me is what steps I should take to process an order.
I'm a this point:
- Once customer clicks on PayPal button on client side it starts a call on
http://localhost/api/paypal/orders
endpoint which create the order on the Paypal side and return the PayPal order ID (e.g.id12345
) - After the customer approves the payment on the PayPal popup, the client starts a call on
http://localhost/api/paypal/orders/id12345/capture
endpoint
then? What other endpoints should I crete on the server and what they should return? Maybe... 1 for save the actual store order on my MongoDB and the transaction details, 1 for create the invoice for the order, 1 for allowing the product download ???
Could you please clarify what steps I need to take, what are the endpoints I should create, and what each endpoints should return?
CodePudding user response:
You're trying to do too many things in too many routes. just create a route called something like process-order
then you could have an async controller of that route which would contain separate functions for
- Storing the order details in mongodb.
- Create an invoice
- Send a token that allows access to download page.
first , just await
the function to complete then call the next.
exports.processOrder = async (req, res, next) => {
try {
const newOrder = await Order.create({
order: req.params.id,
details: req.body.details
})
const createInvoice = () => {
return newOrder._id;
}
const invoice = createInvoice();
const token = jwt.sign(
{
invoiceId = newOrder._id,
},
process.env.JWT_SECRET,
{
expiresIn: '24h'
}
);
return res.status(200).json({status: 'success', message: 'you have 24 hours to download your digital goods', token})
} catch (error) {
res.status(500).send(error)
}
}
This is a very basic idea, but basically store all of your info in one controller, then send a token with the id of the invoice, then when they go to download the book you would have a route where you verify the token. If it succeeds then the book is sent. like this:
app.use(
'/book-download',
expressJwt({ secret: process.env.JWT_SECRET, algorithms: ['HS256'] })
);
app.get('/book-download/success', async (req, res) => {
try{
const invoiceId = req.user.invoiceId;
const invoice = await Invoice.find({_id: invoiceId})
if (invoice) {
return res.status(200).json({status: 'success', message: 'congratulations on your new download', data: {E-book})
} else {
return.res.status(404).json({status: 'fail', message: 'could not find an invoice with that ID'})
} catch (error) {
return res.send(error)
}
});
You can choose to send the pdf via express, or you can allow them to enter a certain part of the website if the return is valid. There you go, that's an idea.
CodePudding user response:
In Express check out, you need to define success / cancel handler
Ref here : https://www.section.io/engineering-education/nodejs-paypal-checkout/
In the success handler, based on the returned URI => you will get a Payer ID and payment ID. Based on that retrieve the transactio information (that internally contains yours order ID). Update your Order id as scucess / cancelled based on the paypal response.
app.get('/success', (req, res) => {
const payerId = req.query.PayerID;
const paymentId = req.query.paymentId;
const execute_payment_json = {
"payer_id": payerId,
"transactions": [{
"amount": {
"currency": "USD",
"total": "25.00"
}
}]
};
// Obtains the transaction details from paypal
paypal.payment.execute(paymentId, execute_payment_json, function (error, payment) {
//When error occurs when due to non-existent transaction, throw an error else log the transaction details in the console then send a Success string reposponse to the user.
if (error) {
console.log(error.response);
throw error;
} else {
console.log(JSON.stringify(payment));
res.send('Success');
}
});
});