16 Email Purchase Receipts

16 Email Purchase Receipts
type
Post
status
Published
date
Feb 8, 2026
slug
nextjs-shopping-platform-016
summary
tags
Next.js
category
编程学习
icon
password
😀

1. Section Intro

In this section, we are going to implement email receipts when a user places and pays for an order. 在本章节中,我们将实现当用户下单并支付订单时发送电子邮件收据。
We are going to use a service called Resend. They offer email services for developers. So if you need to send emails from your app. 我们将使用一个名为Resend的服务。他们为开发者提供电子邮件服务。所以如果你需要从你的应用程序发送电子邮件。
We'll start by creating a free account and setting up our API keys 我们将从创建一个免费账户并设置我们的API密钥开始。
Then we're going to create the email template. We'll be using the Resend NPM package but we'll also be using a library called "React Email", which is a great library that gives us pre-built UI components for creating email templates. 然后我们将创建电子邮件模板。我们将使用Resend NPM包,但我们也将使用一个名为"React Email"的库,这是一个很棒的库,为我们提供了用于创建电子邮件模板的预构建UI组件。
Once we have the template, we can add some sample data so that we can see what the email will look like before we send it. 一旦我们有了模板,我们可以添加一些示例数据,这样我们就可以在发送之前看到电子邮件的样子。
Then finally, we'll send the email when the order is paid. 最后,当订单支付后,我们将发送电子邮件。

2. Resend Account and API Key Resend账户和API密钥

We are going to use a service called Resend to send email. Resend is a developer-focused service designed to simplify the process of sending emails. It provides a simple API for sending emails, making it easy to integrate into your applications. 我们将使用一个名为Resend的服务来发送电子邮件。Resend是一个以开发者为中心的服务,旨在简化发送电子邮件的过程。它提供了一个简单的API来发送电子邮件,使其易于集成到你的应用程序中。
The first thing you need to do is create an account. You can go to Resend and click on the "Sign Up" button. Or you can do what I did and just use your GitHub account. 你需要做的第一件事是创建一个账户。你可以访问Resend并点击"Sign Up"按钮。或者你可以像我一样,直接使用你的GitHub账户。
Once you log in you will see the dashboard. Click on "Add API Key" and copy it and then paste it into your .env file. You also want to add the sender email address. Ultimately, you want to set this to an email that you own the domain but for testing, you can actually use onboarding@resend.dev and it will work. 登录后,你将看到仪表板。点击"Add API Key",复制它,然后粘贴到你的.env文件中。你还需要添加发件人电子邮件地址。最终,你应该将其设置为你拥有域名的电子邮件,但为了测试,你实际上可以使用onboarding@resend.dev,它会正常工作。
It should look something like this: 它应该看起来像这样:
You also need to add these variables to Vercel for the production environment. Go to settings->Environment Variables and add the same variables. 你还需要将这些变量添加到Vercel用于生产环境。进入设置->环境变量并添加相同的变量。
Let's also add the sender email to our constants file. Add the following to app/constants/index.ts: 让我们也将发件人电子邮件添加到我们的常量文件中。将以下内容添加到app/constants/index.ts

Install Packages 安装包

We are going to install a few packages to send emails. Open a terminal and run the following command: 我们将安装几个包来发送电子邮件。打开终端并运行以下命令:
The resend package is the official Node.js SDK for Resend. It provides a simple API for sending emails. The react-email package is a library for creating email templates in React. The @react-email/components package is a set of pre-built components for creating email templates. resend包是Resend的官方Node.js SDK。它提供了一个简单的API来发送电子邮件。react-email包是一个用于在React中创建电子邮件模板的库。@react-email/components包是一组用于创建电子邮件模板的预构建组件。
That's it for now. In the next lesson, we will create our email purchase receipt. 现在就这些了。在下一课中,我们将创建我们的电子邮件购买收据。

3. Resend Main Function Resend 主函数

We need to now create our email template for the purchase receipt, but first, we need to setup the main function that sends the email. We will use the resend for this and the react-email packages to create our email template.
我们现在需要创建购买收据的邮件模板,但首先,我们需要设置发送邮件的主函数。我们将使用 resend 包和 react-email 包来创建邮件模板。
If you go to this link: https://www.npmjs.com/package/resend you will see how to use the resend package to send emails. We simply import the resend package and then call the resend.emails.send method with the properties of to, from, subject, etc. Since we are using React, we can set a property called react and pass in our email template.
如果你访问这个链接:https://www.npmjs.com/package/resend,你会看到如何使用 resend 包来发送邮件。我们只需导入 resend 包,然后调用 resend.emails.send 方法,并传入 tofromsubject 等属性。由于我们使用 React,我们可以设置一个名为 react 的属性,并传入我们的邮件模板。
So let's create a new file in the root of our project at email/index.tsx. Don't add it to the app folder because we don't want it to be a page.
所以让我们在项目根目录创建一个新文件 email/index.tsx。不要将其添加到 app 文件夹中,因为我们不希望它成为一个页面。
Add the following code for now:
暂时添加以下代码:
We are just creating a new instance of the Resend class and calling the emails.send method. We are passing in the properties of from, to, subject, and react. The react property is where we will pass in our email template.
我们只是创建了 Resend 类的一个新实例,并调用 emails.send 方法。我们传入了 fromtosubjectreact 属性。react 属性是我们将传入邮件模板的地方。
NOTE: While in development, you can only send emails to your own email address so just make sure when you test, you create a prostore account with the same email address that you used to register for Resend.
注意:在开发环境中,你只能向自己的邮箱地址发送邮件,所以在测试时,请确保使用与注册 Resend 时相同的邮箱地址创建一个 prostore 账户。
Let's create a file at email/purchase-receipt.tsx. This is where we will create our email template.
让我们在 email/purchase-receipt.tsx 创建一个文件。这是我们将创建邮件模板的地方。
Add the following imports and type:
添加以下导入和类型:
We are bringing in a bunch of components from the @react-email/components package. We are also bringing in the formatCurrency function from our lib/utils file. We are also bringing in the Order type from our types file. We are also bringing in the sampleData object from our db/sample-data file. This is because I'm going to use sample data to preview the email.
我们从 @react-email/components 包中引入了一堆组件。我们还从 lib/utils 文件中引入了 formatCurrency 函数。我们还从 types 文件中引入了 Order 类型。我们还从 db/sample-data 文件中引入了 sampleData 对象。这是因为我将使用示例数据来预览邮件。
Since we are using environment variables outside of the main app folder, we need to require the dotenv package and call the config method.
由于我们在主应用文件夹之外使用环境变量,我们需要引入 dotenv 包并调用 config 方法。
We also create a dateFormatter object to format the date.
我们还创建了一个 dateFormatter 对象来格式化日期。

Apply the Email Template 应用邮件模板

Now back in the email/index.tsx file, we need to apply the PurchaseReceiptEmail component to the send function.
现在回到 email/index.tsx 文件,我们需要将 PurchaseReceiptEmail 组件应用到 send 函数中。
Import it like this:
像这样导入它:
Then pass it into the react property with the order as a prop:
然后将其作为 prop 传入 react 属性:
In the next lesson, we will create the template with React Email.
在下一课中,我们将使用 React Email 创建模板。

4. Purchase Email Receipt Template 收据邮件模板

Now we will create the email template using the components from React Email. Open the email/purchase-receipt.tsx file and add the following to the return:
现在我们将使用 React Email 的组件来创建电子邮件模板。打开 email/purchase-receipt.tsx 文件,并将以下内容添加到 return 语句中:
In this template, we used the Tailwind component to apply Tailwind CSS classes to our email. We are also using the Row and Column components to layout our email. We are also using the Img component to display an image. We are also using the formatCurrency function to format the price.
在此模板中,我们使用了 Tailwind 组件来将 Tailwind CSS 类应用到我们的电子邮件中。我们还使用了 RowColumn 组件来布局我们的电子邮件。我们还使用了 Img 组件来显示图像。我们还使用了 formatCurrency 函数来格式化价格。
We get the order items and map over them to display a row for each item. We are also displaying the total price of the order. For the image, we are checking if the image is a relative path or an absolute path. If it is a relative path, we are adding the process.env.NEXT_PUBLIC_SERVER_URL to the path.
我们获取订单项目并遍历它们,为每个项目显示一行。我们还显示了订单的总价。对于图像,我们检查图像是相对路径还是绝对路径。如果是相对路径,我们将 process.env.NEXT_PUBLIC_SERVER_URL 添加到路径中。
In the next lesson, we are going to add some preview props to our email template so that we can preview it in the browser.
在下一课中,我们将向我们的电子邮件模板添加一些预览属性,以便我们可以在浏览器中预览它。

5. Preview Email In Browser With React Email 在浏览器中预览邮件

We are going to add some preview props to our email template so that we can preview it in the browser.
我们将向邮件模板添加一些预览属性,以便能够在浏览器中预览它。
Open the email/purchase-receipt.tsx file and import the db/sample-data.ts file if you have not done so already.
打开 email/purchase-receipt.tsx 文件,如果尚未导入,请导入 db/sample-data.ts 文件。
Add the following code right above the dateFormatter variable:
将以下代码添加到 dateFormatter 变量的正上方:
We are using the sample data from the sample-data.ts file to create a fake order.
我们使用 sample-data.ts 文件中的示例数据来创建一个模拟订单。
You will probably see a red line for the paymentResult property. To fix this, open the types/index.ts file and add the paymentResult property to the Order type:
你可能会看到 paymentResult 属性出现红色错误线。要修复此问题,请打开 types/index.ts 文件并将 paymentResult 属性添加到 Order 类型中:
You may have a red line in the app/(root)/order/[id]/page.tsx file. Where we embed the <OrderDetailsTable /> component. That is because added PaymentResult to the Order type that this component is using. So we can just open the component file, which is app/(root)/order/[id]/order-details-table.tsx and change this line:
你可能会在 app/(root)/order/[id]/page.tsx 文件中看到红色错误线。我们在该文件中嵌入了 <OrderDetailsTable /> 组件。这是因为向该组件使用的 Order 类型添加了 PaymentResult。因此,我们可以打开组件文件 app/(root)/order/[id]/order-details-table.tsx 并将这一行:
To this line:
改为这一行:
We are just omitting the paymentResult property from the Order type. Yes TypeScript can be a pain in the ass 😉
我们只是从 Order 类型中省略了 paymentResult 属性。是的,TypeScript 有时确实让人头疼 😉

Add NPM Script 添加 NPM 脚本

We are going to add a script to our package.json file to send the email.
我们将向 package.json 文件添加一个脚本来发送邮件。
Open the package.json file and add the following script:
打开 package.json 文件并添加以下脚本:
Let's break down what this script does:
让我们分解一下这个脚本的作用:
  • cp .env ./node_modules/react-email: This copies the .env file to the node_modules/react-email directory. This is because the react-email package uses the .env file to get the RESEND_API_KEY and SENDER_EMAIL variables.
  • cp .env ./node_modules/react-email:这将 .env 文件复制到 node_modules/react-email 目录。这是因为 react-email 包使用 .env 文件来获取 RESEND_API_KEYSENDER_EMAIL 变量。
  • email dev --dir email --port 3001: This starts the email package in development mode and opens the email in the browser.
  • email dev --dir email --port 3001:这将以开发模式启动 email 包并在浏览器中打开邮件。
Let's run the script:
让我们运行这个脚本:
Now if you go to http://localhost:3001 you should see the email in the browser. This is what your email will look like.
现在如果你访问 http://localhost:3001,你应该能在浏览器中看到邮件。这就是你的邮件的样子。
In the next lesson, we will send the email.
在下一课中,我们将发送邮件。

6. Send Email on Order Confirmation 订单确认时发送邮件

Now we want this email to be sent when the user completes the checkout process. 现在我们希望在用户完成结账流程时发送这封邮件。
Open the lib/actions/order.actions.ts file and import the sendPurchaseReceipt function from the email folder. We also need the ShippingAddress type from the types folder. 打开 lib/actions/order.actions.ts 文件,并从 email 文件夹导入 sendPurchaseReceipt 函数。我们还需要 types 文件夹中的 ShippingAddress 类型。
At the very end of the updateOrderToPaid function, after the transaction, we are going to get the updated order and send the email. 在 updateOrderToPaid 函数的最末尾,在事务之后,我们将获取更新后的订单并发送邮件。
Add the following code at the very end of the function: 在函数的最末尾添加以下代码:
We are getting the updated order after the transaction and then sending the email. We are also passing in the updated order as a prop to the sendPurchaseReceipt function along with the ShippingAddress type and PaymentResult because we need those for the email template. 我们在事务后获取更新后的订单,然后发送邮件。我们还将更新后的订单作为 props 传递给 sendPurchaseReceipt 函数,同时传递 ShippingAddress 类型和 PaymentResult,因为邮件模板需要这些信息。

Test The Email 测试邮件

Now let's test the email. Add items to the cart and go through the process. Select PayPal as it will be marked as paid after purchasing with a sandbox account. 现在让我们测试邮件。将商品添加到购物车并完成整个流程。选择 PayPal,因为使用沙盒账户购买后订单会被标记为已支付。
Once the order is paid, you should receive an email with the purchase receipt. You can also go to https://resend.com/emails and see the email that was sent. 订单支付完成后,你应该会收到一封带有购买收据的邮件。你也可以访问 https://resend.com/emails 查看已发送的邮件。
 

📎 参考文章

  • 一些引用
  • 引用文章
💡
欢迎您在底部评论区留言,一起交流~
上一篇
17 Homepage Components & Wrap Up
下一篇
15 Stripe Payments
Loading...