应用程序-特定权限设置
Let’s hurry up already and make this website!
让我们已经快点建立这个网站!
Are you new to this series? Check out the first blog for an introduction and a table of contents!
您是这个系列的新手吗? 查看第 一个博客 以获取简介和目录!
So far, the code we’ve written for American Sock Market has been for the backend. In this post, we’re finally tackling the front end!
到目前为止,我们为American Sock Market编写的代码已用于后端。 在本文中,我们终于要解决前端问题了!
In my last blog post, I described the components of the storefront. In this post, I walk through the implementation. Go to the part-3-set-up-shop-website
folder so we can check out the code!
在上一篇博客文章中 ,我描述了店面的组成部分。 在本文中,我将逐步介绍实施过程。 转到part-3-set-up-shop-website
文件夹,以便我们检查代码!
Inside the folder, you’ll find another folder and some files:
在该文件夹内,您将找到另一个文件夹和一些文件:
- public/ 上市/
- firebase.json firebase.json
- firestore.rules firestore.rules
- package.json package.json
- README.md 自述文件
There are a couple files here that you may not be familiar with: firebase.json
and firestore.rules
. I will explain these in a bit. For now, let’s pretend they don’t matter even though they actually do matter a lot.
这里有一些您可能不熟悉的文件: firebase.json
和firestore.rules
。 我将稍作解释。 现在,让我们假装它们无关紧要,尽管它们实际上确实很重要。
Opening the public/
folder, we find the main code that we’re going to explore:
打开public/
文件夹,我们找到了要探索的主要代码:
- img/ img /
- 404.html 404.html
- canceled.html canceled.html
- completed.html complete.html
- global.css global.css
- normalize.css normalize.css
- index.html index.html
- index.js index.js
I suggest opening all of the files and taking a gander, just to get an idea of how the app works. Open index.html
in a Chrome window. Finally, an actual website to look at!
我建议打开所有文件并仔细阅读,以了解应用程序的工作原理。 在Chrome窗口中打开index.html
。 最后,一个实际的网站来看看!
But of course, this site isn’t up and running yet. This is just the HTML. So if you click the dropdown menu, you’ll just see this lonely placeholder sock.
但是,当然,该站点尚未启动并运行。 这只是HTML。 因此,如果您单击下拉菜单,您只会看到此孤独的占位符袜子。
Inspecting the HTML also doesn’t reveal too much excitement. The page is kept purposely simple so you can easily see how to customize it to fit your needs. Let’s focus on the bottom of the body where we find some script tags.
检查HTML也不会显示太多的兴奋。 该页面特意保持简单,因此您可以轻松地查看如何自定义它以满足您的需求。 让我们集中在找到一些脚本标签的正文底部。
<script src="https://www.gstatic.com/firebasejs/7.15.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.15.0/firebase-firestore.js"></script>
<script src="/__/firebase/init.js"></script>
These scripts used to incorporate Firestore in the app. The version numbers I show in this blog are up to date at the time I published this, but they may have changed since then. Be sure to check the Firestore documentation to find the latest version numbers.
这些脚本用于将Firestore整合到应用中。 我在此博客中显示的版本号是我发布此版本时的最新信息,但此后可能已更改。 请务必查看Firestore文档以查找最新版本号。
The first script is the core Firebase SDK. It’s required for all projects using Firebase. The second script adds the Firebase product we’re going to use: Firestore. The third initializes Firebase for use in this specific application. It always goes after any other Firebase-related scripts.
第一个脚本是核心Firebase SDK。 使用Firebase的所有项目都需要使用它。 第二个脚本添加了我们将要使用的Firebase产品:Firestore。 第三部分初始化Firebase以在此特定应用程序中使用。 它总是追随其他任何与Firebase相关的脚本。
为什么选择Firebase? (Why Firebase?)
So it turns out that Cloud Firestore is a Cloud product and a Firebase product. You can find implementation steps in both the Google Cloud and Firebase docs and these directions are the same. To access Firestore client-side, you use the Firebase SDKs.
因此,事实证明Cloud Firestore是Cloud产品和 Firebase产品。 您可以在Google Cloud和Firebase文档中找到实施步骤,这些指示是相同的。 要访问Firestore客户端,请使用Firebase SDK。
Additionally, the website is hosted on Firebase Hosting. The advantage of this over other hosting options is that the Firebase app’s configuration is automatically provided by the Hosting environment, meaning that you don’t have to provide configuration details. This makes it easy to use the same web app code across multiple Firebase projects.
此外,该网站托管在Firebase Hosting上。 与其他托管选项相比,这样做的优势在于托管环境会自动提供Firebase应用程序的配置,这意味着您不必提供配置详细信息。 这样可以轻松地在多个Firebase项目中使用相同的Web应用程序代码。
So that’s about all the excitement in index.html
. Again, feel free to peruse it to your liking. Just keep in mind that it’s intentionally basic. There are no frameworks or optimizations. The payment-related code can be found in index.js
, so let’s spend some time to walk through it.
这就是index.html
所有令人兴奋的地方。 同样,请随时按自己的喜好仔细阅读。 请记住,这是故意的。 没有框架或优化。 与支付有关的代码可以在index.js
找到,所以让我们花一些时间来完成它。
代码 (The Code)
Alright, let’s check out index.js
.
好吧,让我们看看index.js
。
First, as usual, we have some initializers.
首先,像往常一样,我们有一些初始化程序。
const stripe = Stripe('pk_test_ABCde');
const db = firebase.firestore();
const sockRef = db.collection('socks');
let selectedProduct;
let productList = '';
Notice that you will provide your Stripe public key here. Since this key is (as the name suggests) public, you don’t have to be concerned about the client having access to it. When you deploy your app, be sure to include your public key, which can be found in the Stripe dashboard.
请注意,您将在此处提供您的Stripe公钥。 由于此密钥(顾名思义)是公开的,因此您不必担心客户端可以访问它。 部署应用程序时,请确保包含您的公钥,该公钥可在Stripe仪表板中找到。
获取最新的袜子 (Get the latest socks)
Next up in our code, we get up-to-date information about our sock patterns from Cloud Firestore.
接下来,在我们的代码中,我们从Cloud Firestore获得有关袜子模式的最新信息。
sockRef.get().then(querySnapshot => {
querySnapshot.forEach(doc => {
const data = doc.data();
let name = data.name;
// capitalize first letter for display purposes
let displayName = name.charAt(0).toUpperCase() + name.slice(1);
if (!selectedProduct) {
selectedProduct = name;
}
const amount = data.price;
const image = data.images[0];
productList = productList+`<option data-amount="${amount}" data-id="${name}" data-img="${image}">${displayName}</option>`
});
document.getElementById('select').innerHTML = productList;
});
Here are the basic steps taken in this code:
以下是此代码中采取的基本步骤:
Get the documents in the
socks
collection获取
socks
集中的文件- iterate through the documents 遍历文件
- Get the data from each document 从每个文档获取数据
- Use this to populate an HTML tag 使用它来填充HTML标签
Keep in mind that the way I’m populating the HTML is less than ideal. In your own app, you’re probably using some kind of JavaScript framework that will update your HTML in a more elegant fashion.
请记住,我填充HTML的方式并不理想。 在您自己的应用程序中,您可能正在使用某种JavaScript框架,该框架将以更优雅的方式更新HTML。
退房时间 (Checkout time)
Once the customer has selected an item, it’s time to check out. This is where we initiate the Stripe Checkout session by making a call to our Cloud Run endpoint.
客户选择了商品后,就该结账了。 在这里,我们通过调用Cloud Run端点来启动Stripe Checkout会话。
fetch(
'https://[your_cloud_run_url]/session?product='+selectedProduct
)
.then(function(response) {
return response.json();
})
.then(function(session) {
document.getElementById(“spinner”).classList.add(“hidden”);
document.getElementById(“label”).classList.remove(“hidden”);
stripe
.redirectToCheckout({
sessionId: session.id
})
//...
});
In the call to Cloud Run, we pass the selected product as a query parameter. The response data includes the Stripe Checkout session ID, which we need to complete checkout. Using the Stripe client SDK, we redirect to the Stripe Checkout page. From there, the payment is handled by Stripe, so there’s no additional coding on your part! And that’s about all there is to it to start a simple storefront.
在对Cloud Run的调用中,我们将所选产品作为查询参数传递。 响应数据包括Stripe Checkout会话ID,我们需要完成该ID。 使用Stripe客户端SDK,我们重定向到Stripe Checkout页面。 从那里开始,付款由Stripe处理,因此您不需要任何其他编码! 这就是建立一个简单的店面的全部内容。
很好…但是您似乎掩盖了该文件夹中的某些内容 (Great…but you seemed to gloss over some stuff in that folder)
You didn’t think I’d forget, did you? There were indeed a couple files in the project folder that I wanted to talk about before deploying:
你没有想到我会忘记,是吗? 在部署之前,项目文件夹中确实确实有几个文件需要讨论:
- firebase.json firebase.json
- firestore.rules firestore.rules
These small files play important roles in our project. Let’s examine each of them.
这些小文件在我们的项目中起着重要的作用。 让我们检查它们中的每一个。
firebase.json (firebase.json)
Open the firebase.json
file. Inside, you’ll find the following code:
打开firebase.json
文件。 在内部,您将找到以下代码:
{
"firestore": {
"rules": "firestore.rules"
},
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
This file contains the configuration for deploying your Firebase project via the Firebase CLI. If I run the command firebase deploy
, then by default I’m deploying to both Firestore and Hosting in the configuration outlines in this file.
该文件包含用于通过Firebase CLI部署Firebase项目的配置。 如果运行命令firebase deploy
,则默认情况下,我将同时在此文件的配置概述中同时部署到Firestore和Hosting。
For Hosting, the configuration tells Firebase which folder is the public folder, and which files and folders to ignore.
对于托管,配置会告诉Firebase哪个文件夹是公用文件夹,以及哪些文件和文件夹要忽略。
For Firestore, the config tells me which files will be included in deployment. In this case, we’re using the CLI to configure the security rules for Firestore. This seems like a great segue into that firestore.rules
file!
对于Firestore,配置会告诉我哪些文件将包含在部署中。 在这种情况下,我们使用CLI来配置Firestore的安全规则。 这似乎是对该firestore.rules
文件的一个很好的选择!
firestore.rules (firestore.rules)
Before I explain the security rules of this project, I want to emphasize that security is not optional and should be considered as you’re designing your database schema. Security rules are a meaty topic, and I implore you to read the documentation, test out examples, and be sure that you have a deep understanding of how Firestore security rules work. I’m not trying to lecture you but at the same time, I admit I’m lecturing you. I don’t care if you think I’m being a nag if it means you’ll actually take security seriously!
在解释该项目的安全规则之前,我想强调一下,安全性不是可选的,在设计数据库模式时应考虑安全性。 安全规则是一个棘手的话题,我恳请您阅读文档 ,测试示例,并确保您对Firestore安全规则的工作方式有深入的了解。 我不是要教你,但同时我要讲给你讲。 如果您认为我会认真对待安全性,我不在乎您是否认为我是个na夫!
Phew! Alright, with that out of the way, let’s get back to the rules we use in American Sock Market. We can examine the Firestore security rules in the firestore.rules
file:
! 好了,顺便说一句,让我们回到在美国袜子市场上使用的规则。 我们可以在firestore.rules
文件中检查Firestore安全规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /socks/{sock=**} {
allow read: if true;
}
}
}
If you’re unfamiliar with the format of security rules, then definitely spend some time in those docs. These rules allow public access to read the socks
collection and all subcollections under it. Since the default security condition is false, unless otherwise specified, no client can read or write to any part of the database. Thus, customers cannot write to the `socks` collection and they cannot read or write any other part of the database.
如果您不熟悉安全规则的格式,那么一定要花一些时间在这些文档中 。 这些规则允许公众访问读取socks
集合及其下的所有子集合。 由于默认的安全条件为false,除非另有说明,否则任何客户端都无法读取或写入数据库的任何部分。 因此,客户无法写入“ socks”集合,也无法读取或写入数据库的任何其他部分。
This is a very rudimentary set of rules and it’s definitely not recommended for a production app. Even in testing, it’s a good idea to keep your database secure by including authentication as a requirement to interact with any part of the database. I set the socks
collection to be able to be publicly read, when in reality I prefer to use at least anonymous authentication. So as you might suspect, we’ll be adding authentication in a future post! If it sounds like I’m getting preachy again, so be it. Did you check out the rules doc yet?
这是一组非常基本的规则,绝对不建议用于生产应用程序。 即使在测试中,通过将身份验证作为与数据库的任何部分进行交互的要求,也可以确保数据库的安全,这是一个好主意。 我将socks
集合设置为可以公开阅读,而实际上我更喜欢至少使用匿名身份验证。 因此,您可能会怀疑,我们将在以后的帖子中添加身份验证! 如果听起来我又开始讲道了,那就去吧。 您是否签出了规则文档 ?
部署到Firebase托管 (Deploy to Firebase Hosting)
It’s the moment you’ve been waiting for: time to bring this app to life! Way back in the very first blog post of this series, I outlined the requirements to build the project. One of these was installing the Firebase CLI. If you don’t already have it installed, then you can follow the steps in the CLI reference docs to get it up and running.
您一直在等待的时刻:是时候让这个应用程序栩栩如生了! 在本系列的第一篇博客文章中,我概述了构建项目的要求。 其中之一是安装Firebase CLI。 如果尚未安装,则可以按照CLI参考文档中的步骤进行安装和运行。
Set the default project to the project you’re using.
将默认项目设置为您正在使用的项目。
firebase use PROJECT_ID
Now any commands we run will automatically use this project unless you add a --project
flag and include another project.
现在,除非您添加--project
标志并包含另一个项目,否则我们运行的所有命令将自动使用此项目。
Deploy the website to Hosting and the security rules to Firebase by running this command:
通过运行以下命令,将网站部署到Hosting并将安全规则部署到Firebase:
firebase deploy
Once deployed, follow the link to your hosted web page to give it a try!
部署后,请点击您托管网页的链接以尝试一下!
它还活着! (It’s alive!)
Well, maybe our storefront is not so much alive as it is live. Go ahead and click around to get a feel for the app. When you’re ready to try the checkout functionality, you can use Stripe’s dummy credit card number, 4242 4242 4242 4242.
嗯,也许我们的店面不是那么活着 ,而是活着 。 继续并单击以了解该应用程序。 准备好尝试结帐功能时,可以使用Stripe的虚拟信用卡号4242 4242 4242 4242。
You can verify that the payment was successful via the Stripe dashboard.
您可以通过Stripe仪表板验证付款是否成功。
完成... ish (Done…ish)
What we have now is a free-standing application that can make payments, so you could say that it’s done. But there are a lot of other things to consider, like verifying that payments were successful, account creation so customers can save their purchase history, refund management, and much more. You can bet this series is far from over! Stick with me for some payment processing fun!
我们现在拥有的是一款可以付款的独立应用程序,因此您可以说它已经完成。 但是,还有很多其他事情需要考虑,例如验证付款是否成功,创建帐户,以便客户可以保存其购买历史记录,退款管理等等。 你可以打赌这个系列还远远没有结束! 坚持使用我的一些付款处理乐趣!
In the meantime, continue to play with your project. You can fork the repo and make changes. If you think you’re on to something good, go ahead and make a pull request!
同时,继续进行您的项目。 您可以派生回购并进行更改。 如果您认为自己的工作进展顺利,请继续提出要求!
Also, be sure to:
另外,请确保:
Learn up on Cloud Firestore security rules (yes, I’m bringing it up again!)
了解Cloud Firestore安全规则 (是的,我再次提出来!)
Scope out the Stripe documentation
整理Stripe文档
Dig into Cloud Firestore
应用程序-特定权限设置