Skip to content

Commit a930b4e

Browse files
authored
Merge pull request #75 from basir/Video-60-Email-Order-Receipt
Video-60-Email-Order-Receipt
2 parents fa2ce8e + 44742b6 commit a930b4e

File tree

4 files changed

+107
-3
lines changed

4 files changed

+107
-3
lines changed

README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -398,4 +398,11 @@ $ npm start
398398
59. Implement Pagination
399399
1. add pagination to product router in backend
400400
2. apply page number to actions and reducers in frontend
401-
3. show page numbers in search screen
401+
3. show page numbers in search screen
402+
60. Email order receipt by mailgun
403+
1. create mailgun account
404+
2. add and verify your domain to mailgun
405+
3. install mailgun-js
406+
4. set api key in env file
407+
5. change pay order in orderRouter
408+
6. send email the

backend/routers/orderRouter.js

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import express from 'express';
22
import expressAsyncHandler from 'express-async-handler';
33
import Order from '../models/orderModel.js';
4-
import { isAdmin, isAuth, isSellerOrAdmin } from '../utils.js';
4+
import {
5+
isAdmin,
6+
isAuth,
7+
isSellerOrAdmin,
8+
mailgun,
9+
payOrderEmailTemplate,
10+
} from '../utils.js';
511

612
const orderRouter = express.Router();
713
orderRouter.get(
@@ -71,7 +77,10 @@ orderRouter.put(
7177
'/:id/pay',
7278
isAuth,
7379
expressAsyncHandler(async (req, res) => {
74-
const order = await Order.findById(req.params.id);
80+
const order = await Order.findById(req.params.id).populate(
81+
'user',
82+
'email name'
83+
);
7584
if (order) {
7685
order.isPaid = true;
7786
order.paidAt = Date.now();
@@ -82,6 +91,23 @@ orderRouter.put(
8291
email_address: req.body.email_address,
8392
};
8493
const updatedOrder = await order.save();
94+
mailgun()
95+
.messages()
96+
.send(
97+
{
98+
from: 'Amazona <[email protected]>',
99+
to: `${order.user.name} <${order.user.email}>`,
100+
subject: `New order ${order._id}`,
101+
html: payOrderEmailTemplate(order),
102+
},
103+
(error, body) => {
104+
if (error) {
105+
console.log(error);
106+
} else {
107+
console.log(body);
108+
}
109+
}
110+
);
85111
res.send({ message: 'Order Paid', order: updatedOrder });
86112
} else {
87113
res.status(404).send({ message: 'Order Not Found' });

backend/utils.js

+70
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import jwt from 'jsonwebtoken';
2+
import mg from 'mailgun-js';
23

34
export const generateToken = (user) => {
45
return jwt.sign(
@@ -57,3 +58,72 @@ export const isSellerOrAdmin = (req, res, next) => {
5758
res.status(401).send({ message: 'Invalid Admin/Seller Token' });
5859
}
5960
};
61+
62+
export const mailgun = () =>
63+
mg({
64+
apiKey: process.env.MAILGUN_API_KEY,
65+
domain: process.env.MAILGUN_DOMIAN,
66+
});
67+
68+
export const payOrderEmailTemplate = (order) => {
69+
return `<h1>Thanks for shopping with us</h1>
70+
<p>
71+
Hi ${order.user.name},</p>
72+
<p>We have finished processing your order.</p>
73+
<h2>[Order ${order._id}] (${order.createdAt.toString().substring(0, 10)})</h2>
74+
<table>
75+
<thead>
76+
<tr>
77+
<td><strong>Product</strong></td>
78+
<td><strong>Quantity</strong></td>
79+
<td><strong align="right">Price</strong></td>
80+
</thead>
81+
<tbody>
82+
${order.orderItems
83+
.map(
84+
(item) => `
85+
<tr>
86+
<td>${item.name}</td>
87+
<td align="center">${item.qty}</td>
88+
<td align="right"> $${item.price.toFixed(2)}</td>
89+
</tr>
90+
`
91+
)
92+
.join('\n')}
93+
</tbody>
94+
<tfoot>
95+
<tr>
96+
<td colspan="2">Items Price:</td>
97+
<td align="right"> $${order.itemsPrice.toFixed(2)}</td>
98+
</tr>
99+
<tr>
100+
<td colspan="2">Tax Price:</td>
101+
<td align="right"> $${order.taxPrice.toFixed(2)}</td>
102+
</tr>
103+
<tr>
104+
<td colspan="2">Shipping Price:</td>
105+
<td align="right"> $${order.shippingPrice.toFixed(2)}</td>
106+
</tr>
107+
<tr>
108+
<td colspan="2"><strong>Total Price:</strong></td>
109+
<td align="right"><strong> $${order.totalPrice.toFixed(2)}</strong></td>
110+
</tr>
111+
<tr>
112+
<td colspan="2">Payment Method:</td>
113+
<td align="right">${order.paymentMethod}</td>
114+
</tr>
115+
</table>
116+
<h2>Shipping address</h2>
117+
<p>
118+
${order.shippingAddress.fullName},<br/>
119+
${order.shippingAddress.address},<br/>
120+
${order.shippingAddress.city},<br/>
121+
${order.shippingAddress.country},<br/>
122+
${order.shippingAddress.postalCode}<br/>
123+
</p>
124+
<hr/>
125+
<p>
126+
Thanks for shopping with us.
127+
</p>
128+
`;
129+
};

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"express": "^4.17.1",
2525
"express-async-handler": "^1.1.4",
2626
"jsonwebtoken": "^8.5.1",
27+
"mailgun-js": "^0.22.0",
2728
"mongoose": "^5.10.7",
2829
"multer": "^1.4.2"
2930
},

0 commit comments

Comments
 (0)