我如何使用 Medusa、Gatsby、PayPal 和 MeiliSearch 创建漫画书店
Medusa是一个面向开发人员的开源无头商务平台。它可用于建立成熟的在线商店。它具有许多基本电子商务功能包括自动化 RMA 流程、即插即用集成、产品和订单管理等等。
在本教程中,您将学习如何使用 Medusa 创建漫画书店。您还将为您的商店添加重要的电子商务功能,包括使用 MeiliSearch 的搜索引擎和使用 PayPal 的支付提供商。
您可以在这个 GitHub 存储库上找到本教程的完整代码。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--6LFLMeiS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to -uploads.s3.amazonaws.com/uploads/articles/c7sfxf71c9hevlmh43o9.gif)
架构概述
在开始学习本教程之前,如果您不熟悉它,这里有一个美杜莎架构的简短概述。如果您愿意,您可以继续并跳到下一部分。
美杜莎由 3 个主要成分组成:
-
Headless Server 是您电子商务商店的核心。它负责处理所有逻辑、电子商务功能和数据。所有其他组件使用REST API连接到服务器。
-
Medusa Admin 是商店经营者可以用来查看和管理其商店数据(例如,产品和订单)的用户界面。 Medusa 提供了一个直观的现成管理面板供您使用。或者,您可以构建自己的并使用 REST API 连接到服务器。
-
Storefront 是客户查看产品并进行购买的在线商店。 Medusa 提供了两个初始店面,一个使用Next.js构建,一个使用Gatsby构建。您还可以使用您选择的任何框架构建店面,并使用 REST API 连接到服务器。
在本教程中,您将了解如何设置它们以及如何使用它们。
先决条件
在开始之前,您需要安装以下要求:
1.节点v14 或更高版本。
2.Postgres创建了一个空数据库。
3.MeiliSearch为搜索引擎。
4.PayPal开发者账号。
5.MinIO用于文件存储。您也可以使用S3或DigitalOcean Spaces。
安装服务器
要安装 Medusa 服务器,您需要先安装 Medusa CLI:
npm install -g @medusajs/medusa-cli
进入全屏模式 退出全屏模式
然后,运行以下命令将 Medusa 服务器安装到新目录comic-store
中:
medusa new comic-store
进入全屏模式 退出全屏模式
安装插件
下一步是安装您将在 Medusa 服务器上使用的插件。对于本教程,您需要 PayPal、MeiliSearch 和 MinIO 集成的插件。
在comic-store
目录中运行以下命令安装 3 个插件:
npm install medusa-file-minio medusa-plugin-meilisearch medusa-payment-paypal
进入全屏模式 退出全屏模式
如果不是 MinIO,请将
medusa-file-minio
替换为您正在使用的文件服务。
确保在package.json
中@medusajs/medusa
、medusa-interfaces
和@medusajs/medusa-cli
的版本大于或等于1.3.0
。如果不是,请使用以下命令更新它们:
npm install @medusajs/medusa@latest medusa-interfaces@latest @medusajs/medusa-cli@latest
进入全屏模式 退出全屏模式
添加环境变量
Medusa 让您可以自由地根据您的服务器处理环境变量。在本教程中,您将在.env
变量中添加所有环境变量。
打开.env
文件。添加以下变量:
#PostgreSQL Database URL
DATABASE_URL=
#MinIO configurations
MINIO_ACCESS_KEY=
MINIO_SECRET_KEY=
MINIO_BUCKET=
MINIO_SERVER=
#PayPal Configurations
PAYPAL_SANDBOX=true
PAYPAL_CLIENT_ID=
PAYPAL_CLIENT_SECRET=
PAYPAL_AUTH_WEBHOOK_ID=
#MeiliSearch Configurations
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_API_KEY=
进入全屏模式 退出全屏模式
这些环境变量对于与数据库、MinIO、PayPal 和 MeiliSearch 相关的配置非常重要。
DATABASE_URL
是连接到 PostgreSQL 数据库模式的 URL。它的格式应该是postgres://<USERNAME>:<PASSWORD>@<HOST>/<DB_NAME>
。
您可以参考我们的文档了解如何检索MinIO和MeiliSearch的必要变量。
如果您使用的文件服务与 MinIO 不同,请参阅文件服务的文档以了解您需要哪些变量。
对于 PayPal,您可以参考PayPal 的文档来检索 Client ID、Client Secret 和 Webhook ID。您还通过将PAYPAL_SANDBOX
设置为true
来打开沙盒模式以进行测试。
配置服务器
您需要将这些环境变量传递给服务器配置。
服务器配置都在medusa-config.js
里面。这包括数据库、插件等配置。
打开medusa-config.js
。在文件开头添加以下内容:
const dotenv = require('dotenv');
let ENV_FILE_NAME = '';
switch (process.env.NODE_ENV) {
case 'prod':
ENV_FILE_NAME = '.env';
break;
case 'test':
ENV_FILE_NAME = '.env.test';
break;
default:
ENV_FILE_NAME = '.env';
break;
}
dotenv.config({ path: process.cwd() + '/' + ENV_FILE_NAME });
进入全屏模式 退出全屏模式
这允许您从.env
文件加载环境变量。
接下来,在plugins
数组中,在数组末尾添加以下 3 个插件:
const plugins = [
//...
{
resolve: `medusa-payment-paypal`,
options: {
sandbox: process.env.PAYPAL_SANDBOX,
client_id: process.env.PAYPAL_CLIENT_ID,
client_secret: process.env.PAYPAL_CLIENT_SECRET,
auth_webhook_id: process.env.PAYPAL_AUTH_WEBHOOK_ID
}
},
{
resolve: `medusa-file-minio`,
options: {
endpoint: process.env.MINIO_SERVER,
bucket: process.env.MINIO_BUCKET,
access_key_id: process.env.MINIO_ACCESS_KEY,
secret_access_key: process.env.MINIO_SECRET_KEY,
}
},
{
resolve: `medusa-plugin-meilisearch`,
options: {
config: {
host: process.env.MEILISEARCH_HOST,
apiKey: process.env.MEILISEARCH_API_KEY
},
settings: {
products: {
searchableAttributes: ["title", "description", "variant_sku"],
displayedAttributes: ["title", "description", "variant_sku"],
},
},
},
}
];
进入全屏模式 退出全屏模式
这会加载您之前安装的 3 个插件,并为每个插件传递必要的选项。
最后,在导出函数中更改projectConfig
中的数据库配置以使用您的 PostgreSQL 数据库而不是 SQLite 数据库:
module.exports = {
projectConfig: {
//...
database_url: DATABASE_URL,
database_type: "postgres",
//**comment out or remove these lines:**
// database_database: "./medusa-db.sql",
// database_type: "sqlite",
},
//...
};
进入全屏模式 退出全屏模式
迁移和种子数据库
运行服务器之前的最后一步是迁移和播种数据库。迁移意味着将必要的表添加到您的数据库模式中以使其与 Medusa 一起使用。
播种意味着将虚拟数据添加到您的数据库中以快速开始。
运行以下命令以迁移和种子数据库:
npm run seed
进入全屏模式 退出全屏模式
这将使用您传递给环境变量DATABASE_URL
的 URL 连接到您的数据库。请确保您在运行此命令之前已经创建了数据库。
运行服务器
确保 MeiliSearch 和 MinIO 服务正在运行。然后,使用以下命令运行您的服务器:
npm start
进入全屏模式 退出全屏模式
这将在端口9000
上运行您的服务器。您应该在整个教程中保持服务器运行,因为 Medusa 管理员和店面依赖于服务器。
设置美杜莎管理员
在本节中,您将安装Medusa Admin,向其中添加产品,并启用 PayPal 作为支付提供商。
安装管理员
在您的终端和与comic-store
目录不同的目录中,运行以下命令:
git clone https://github.com/medusajs/admin comic-admin
进入全屏模式 退出全屏模式
然后,切换到新创建的comic-admin
目录并安装必要的依赖项:
cd comic-admin
npm install
进入全屏模式 退出全屏模式
确保 Medusa 服务器仍在运行。然后,运行以下命令来启动管理员:
npm start
进入全屏模式 退出全屏模式
默认情况下,这将在端口7000
上启动您的 Medusa 管理员。在浏览器中打开它,您应该会看到一个登录屏幕。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--kIFTXMF---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to -uploads.s3.amazonaws.com/uploads/articles/ntmwk9naznm5cjkibepn.png)
您可以使用默认邮箱“admin@medusa-test.com”和密码“supersecret”登录。
添加产品
登录后,从侧边栏“产品”中选择。您会看到在为数据库播种时添加的一些产品。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--mMd7-Rpa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to -uploads.s3.amazonaws.com/uploads/articles/q19k2jycxdek7f2kzhqu.png)
继续并通过单击每个点的 3 个点然后删除来删除它们。
接下来,通过单击右上角的“新产品”按钮将产品添加到您的漫画书店。
您需要填写与产品信息相关的字段。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--N2IrnGAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/v3dmj8s5cvbrh877ncmu.png)
在继续下一步之前,添加任意数量的产品。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--0Pe3ibP7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/dab0r1jznq7edr97bkkn.png)
启用贝宝
要启用 PayPal 作为支付提供商,请单击设置,然后选择区域。
对于要添加 PayPal 作为支付提供商的每个地区,单击“Payment Providers”输入并选择“paypal”,然后单击“保存”。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--_2f9xQ1d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/zk508ln26itnqi65i45l.png)
设置店面
最后一步是设置店面。本节介绍安装Gatsby 店面,对其进行一些自定义,添加 MeiliSearch 栏,以及为 PayPal 添加 UI。
安装店面
在您的终端中,在与comic-store
和comic-admin
目录不同的目录中,运行以下命令:
gatsby new comic-storefront https://github.com/medusajs/gatsby-starter-medusa
进入全屏模式 退出全屏模式
这会将 Gatsby 店面安装在新目录comic-storefront
中。
然后,切换到comic-storefront
目录,将.env.template
重命名为.env.development
:
mv .env.template .env.development
进入全屏模式 退出全屏模式
添加环境变量
您需要添加环境变量才能在您的店面使用 MeiliSearch 和 PayPal。在.env.development
中添加以下变量:
#MeiliSearch Configurations
GATSBY_MEILISEARCH_HOST=
GATSBY_MEILISEARCH_API_KEY=
#PayPal Configurations
GATSBY_PAYPAL_CLIENT_ID=
进入全屏模式 退出全屏模式
这些配置的值与您在服务器上使用的值相同。
跑盖茨比店面
确保 Medusa 服务器正在运行。然后运行以下命令来启动 Gatsby 店面:
npm start
进入全屏模式 退出全屏模式
这将在localhost:8000
上运行您的店面。在浏览器中打开它。您应该会看到一个主图和您添加的产品。
[](https://res.cloudinary.com/practicaldev/image/fetch/s---DJbGtXr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/qhvt2ugmuwags2asapav.png)
自定义店面
英雄横幅是添加到代码中的静态横幅。您现在将对其进行自定义以显示与您的漫画书店相关的内容。
打开src/pages/index.js
。您应该在返回的 JSX 中找到组件StaticImage
,后跟一个 div。将它们更改为以下内容:
<StaticImage
src="../images/hero.png"
alt="A black Medusa hoodie and a white Medusa coffee mug"
placeholder="tracedSVG"
className="w-full lg:w-1/2 h-auto lg:my-5"
/>
<div className="lg:ml-7">
<h1 className="text-4xl">The Best Comic Books</h1>
<p className="mt-2 text-lg font-normal">
Buy the best Marvel and DC Comic Books!
</p>
</div>
进入全屏模式 退出全屏模式
这会更改使用的文本和图像。您可以从此处下载新图像。将其放置在src/images
,名称为hero.png
。
如果您现在打开店面,您应该会看到更新的英雄形象。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--DZLWfLsy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/54432hmtyratxjp5yg44.png)
添加搜索栏
在本节中,您将添加一个搜索栏来使用 MeiliSearch 搜索产品。
在您的终端中,运行以下命令来安装一些必要的依赖项:
npm install react-instantsearch-dom @meilisearch/instant-meilisearch
进入全屏模式 退出全屏模式
然后,使用以下内容创建文件src/components/header/search.jsx
:
import {
Highlight,
Hits,
InstantSearch,
SearchBox,
connectStateResults
} from "react-instantsearch-dom"
import React from "react"
import { instantMeiliSearch } from "@meilisearch/instant-meilisearch"
const searchClient = instantMeiliSearch(
process.env.GATSBY_MEILISEARCH_HOST,
process.env.GATSBY_MEILISEARCH_API_KEY
)
const Search = () => {
const Results = connectStateResults(({ searchState, searchResults, children }) =>
searchState && searchState.query && searchResults && searchResults.nbHits !== 0 ? (
<div className="absolute top-full w-full p-2 bg-gray-200 shadow-md">
{children}
</div>
) : (
<div></div>
)
);
return (
<div className="relative">
<InstantSearch indexName="products" searchClient={searchClient}>
<SearchBox submit={null} reset={null} />
<Results>
<Hits hitComponent={Hit} />
</Results>
</InstantSearch>
</div>
)
}
const Hit = ({ hit }) => {
return (
<div key={hit.id} className="relative">
<div className="hit-name">
<Highlight attribute="title" hit={hit} tagName="mark" />
</div>
</div>
)
}
export default Search;
进入全屏模式 退出全屏模式
这将使用从您刚刚安装的依赖项@meilisearch/instant-meilisearch
导出的方法instantMeiliSearch
创建一个搜索客户端。您将之前为配置添加的环境变量传递给该方法。
然后,Search
组件使用来自react-instantsearch-dom
的组件显示一个搜索栏。当用户输入查询并且有结果时,每个结果都使用Hit
组件呈现。
如果您想了解有关如何自定义搜索栏 UI 及其选项的更多信息,可以查看 Algolia 的React InstantSearch 文档。
接下来,您将搜索栏添加到导航栏。为此,请打开index.jsx
并在文件开头导入Search
组件:
import Search from "./search"
进入全屏模式 退出全屏模式
然后,在返回的 JSX 中,在RegionPopover
之前添加Search
组件:
//...
<Search />
<RegionPopover regions={mockData.regions} />
//...
进入全屏模式 退出全屏模式
保存所有更改并立即打开店面。您应该会在导航栏中看到一个搜索栏。尝试输入您的一种产品的名称,您应该会在结果中看到它。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--r2JTz-fY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/0jnfppxjhw6a5coc7yyu.png)
添加贝宝用户界面
在本节中,您将添加使用 PayPal 作为付款方式所需的 UI。
在您的终端中使用以下命令安装 PayPal 的 React 库:
npm install @paypal/react-paypal-js
进入全屏模式 退出全屏模式
然后,使用以下内容创建文件src/components/payment/paypal-payment/index.jsx
:
import { PayPalButtons, PayPalScriptProvider } from "@paypal/react-paypal-js";
import React, { useMemo, useState } from "react";
import { navigate } from "gatsby"
import { useCart } from "../../../hooks/use-cart"
import { useMedusa } from "../../../hooks/use-medusa";
const paypalClientId = process.env.GATSBY_PAYPAL_CLIENT_ID || ""
const PaypalPayment = () => {
const {
cart,
actions: { completeCart, setPaymentSession },
} = useCart()
const [errorMessage, setErrorMessage] = useState(undefined)
const [processing, setProcessing] = useState(false)
const client = useMedusa()
const paypalSession = useMemo(() => {
if (cart.payment_sessions) {
return cart.payment_sessions.find(s => s.provider_id === "paypal")
}
return null
}, [cart.payment_sessions])
if (!paypalSession) {
return null
}
const completeOrder = async (authorizationOrder) => {
const cart = await setPaymentSession("paypal")
if (!cart) {
setProcessing(false)
return
}
await client.carts.updatePaymentSession(cart.id, "paypal", {
data: {
data: {
...authorizationOrder
}
}
});
const order = await completeCart(cart.id)
if (!order || order.object !== "order") {
setProcessing(false)
return
}
setProcessing(false)
navigate("/order-confirmed", { state: { order } })
}
const handlePayment = (data, actions) => {
actions.order.authorize().then((authorization) => {
if (authorization.status !== 'COMPLETED') {
setErrorMessage(`An error occurred, status: ${authorization.status}`);
setProcessing(false);
return;
}
completeOrder(authorization)
})
}
return (
<PayPalScriptProvider options={{
"client-id": paypalClientId,
"currency": cart.region.currency_code.toUpperCase(),
"intent": "authorize"
}}>
{errorMessage && (
<span className="text-rose-500 mt-4">{errorMessage}</span>
)}
<PayPalButtons
style={{ layout: "horizontal" }}
onApprove={handlePayment}
disabled={processing}
/>
</PayPalScriptProvider>
)
}
export default PaypalPayment;
进入全屏模式 退出全屏模式
简单解释一下这段代码:
-
您呈现一个 PayPal 按钮,允许客户使用您刚刚安装的
@paypal/react-paypal-js
中的组件使用 PayPal 付款。您将来自环境变量的 PayPal 客户端 ID 传递给组件PayPalScriptProvider
。 -
单击按钮时,执行方法
handlePayment
,使用方法actions.order.authorize()
向 PayPal 发起授权。这将在新窗口中打开 PayPal 的支付门户。 -
客户支付成功后,执行传递给
then
的履行回调函数。如果授权中有任何错误,将显示错误消息。否则,将调用completeOrder
方法。 -
在
completeOrder
方法中,首先将PayPal设置为当前购物车的支付会话。然后,在客户授权付款后,使用从 PayPal 收到的数据在服务器上进行更新。 -
最后,下订单,客户被重定向到
order-confirmed
页面,他们可以在其中查看订单详细信息的摘要。
接下来,在src/components/payment/index.jsx
文件开头添加PaypalPayment
组件的导入:
import PaypalPayment from "./paypal-payment"
进入全屏模式 退出全屏模式
然后,在返回的 JSX 中,你会发现一个 switch 语句,它根据支付提供商的 ID 呈现组件。在default
案例之前的 switch 语句中添加一个新案例。当客户可用的支付提供商的 ID 为paypal
时,这将呈现PaypalPayment
:
switch (ps.provider_id) {
case "stripe":
//...
case "manual":
//...
case "paypal":
return <PaypalPayment />
default:
return null
}
进入全屏模式 退出全屏模式
在继续测试整个流程之前保存所有更改。
测试结帐流程
在本节中,您将测试在店面下订单,然后在管理员上查看详细信息并获取付款。
确保所有 3 个组件(美杜莎服务器、美杜莎管理员和店面)都在运行。然后,在您的店面,选择一个产品并将其放入购物车。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--fmZbIuJm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/ssja3se7cyrg0c6w4pht.png)
然后,单击购物车图标,然后单击弹出窗口中的“结帐”按钮。
您将被带到单页结账处,您必须在其中输入您的详细信息并选择一种运输方式。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--khVmVEgh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/p38re0olkhv4n4mnc2kt.png)
完成结帐的最后一步后,您应该会看到当前地区可用的付款方式,包括 PayPal。
如果您看不到 PayPal,请确保在导航栏的右上角选择了正确的区域。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--iqMPqcAa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/s0hh1oe6zguqxgnttjp1.png)
通过单击第一个 PayPal 按钮尝试使用 PayPal 付款。将打开一个新页面,要求您登录 PayPal 并授权付款。
使用沙盒帐户授权付款后,您将被带回店面。如果授权成功,您将很快被重定向到订单摘要页面。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--jtmpUlhL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/94vsbmph5x1l9g894m19.png)
在您的美杜莎管理员上,单击侧栏中的订单。您应该看到一个新订单。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--YAsV_7DU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to -uploads.s3.amazonaws.com/uploads/articles/f6olx3or6hxbj55dre4d.png)
点击订单。您将看到订单详情,包括订购的商品和付款详情。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--kDLqMotN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/uploads/articles/bc7a6hlt6cq8pe2obesp.png)
要捕获付款,请单击“捕获付款”按钮。
接下来是什么?
您刚刚使用 Medusa 创建了一个漫画书商店,该商店有一个使用 MeiliSearch 和 PayPal 作为支付提供商的搜索引擎。
您可以使用电子商务商店做更多事情:
-
检查您可以添加的更多插件以向您的电子商务商店添加更多功能,包括将Strapi用于 CMS。
-
通过添加自定义端点自定义您的美杜莎服务器。
-
在 Heroku](https://docs.medusajs.com/how-to/deploying-on-heroku)上部署[服务器,在 Netlify 上部署Medusa Admin和Storefront。
如果您有任何与美杜莎相关的问题或疑问,请随时通过Discord与美杜莎团队联系。
更多推荐
所有评论(0)