昨天我们完成了一个基本的购物流程,但程序码内有着不安全的问题,今天我们要用 .env 的形式来规避这个风险,至於怎麽做呢?就让我们看下去吧!
补充说明一下 Sku 指的是库存,因此若没有依照 Stripe Document来正确的创建产品与库存,是无法顺利地完成这篇文章的范例唷!
首先,我们打开昨天制作的 ecommerce-gatsby-tutorial 目录,并在里面输入以下指令来安装 gatsby-source-stripe 套件
npm install gatsby-source-stripe
Gatsby-source-stripe 套件可以让我们在 gatsby-config.js 中设定我们的 Key 与其他的私人资讯,并在需要的地方显示出来,所以安装完毕後,让我们打开 gatsby-config.js 档并贴上以下程序码
{
resolve: `gatsby-source-stripe`,
options: {
objects: ["Sku"],
secretKey: process.env.STRIPE_SECRET_KEY,
downloadFiles: true,
},
},
我们会将在 Stirpe 上拿到的私 Key 设定在这,不过会是代入环境变数的方式来设定。
如果对於环境变数有兴趣的读者,可以参考这一篇 Environment Variables - Gatsby
接下来我们在根目录下新增一个 .env.development 档,来放置我们的环境变数
STRIPE_SECRET_KEY=sk_test_xxx
建立完环境变数後,我们会在 gatsby-config.js 中引入它,引入的方式如下
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
})
最後避免这只档案被放到 GitHub 上公开,所以我们会在 .gitignore 中新增 .env.development 此档名,来避免他被 git 纪录,所以我们会加入以下程序码。
.env
.env.development
.env.production
在完成变数设定後,我们到 components 目录下在建立一个 Products 资料夹,我们会在里面放上我们的商品元件,首先,我们会需要捞出 SKU 的元件,由於是元件,所以我们会用静态查询 ( StaticQuery ) 的方式来通过 GraphQL 来捞取资料,并将我们捞取的资料下去跑回圈,就能列出我们所有的商品列表罗!
import React from "react"
import { graphql, StaticQuery } from "gatsby"
export default props => (
// 使用静态查询捞资料
<StaticQuery
query={graphql`
query SkusForProduct {
skus: allStripeSku {
edges {
node {
id
currency
price
attributes {
name
}
}
}
}
}
`}
render={({ skus }) => (
// 将捞取的资料跑回圈并列出列表
<div>
{skus.edges.map(({ node: sku }) => (
<p key={sku.id}>{sku.attributes.name}</p>
))}
</div>
)}
/>
)
若没有正确的新增库存,此时你的终端机应该会出现以下错误
Cannot query field "allStripeSku" on type "Query".
只要正确新增 Sku 後,即可正常显示罗!
接着我们创建一个新页面来放置这个列表,所以我们在 pages 中建立一个页面名称为 advanced.js 并在里面贴上以下程序码,程序码中,我们引入了刚刚建立好的 Sku 元件,并显示在上面。
import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import Skus from "../components/Products/Skus"
const AdvancedExamplePage = () => (
<Layout>
<SEO title="Advanced Example" />
<h1>This is the advanced example</h1>
<Skus />
</Layout>
)
export default AdvancedExamplePage
完成後,我们可以点击 http://localhost:8000/advanced 就能看到我们的列表罗!
虽然完成了列表,但列表只显示单纯的文字并不能让身为视觉动物的客户有任何的购买慾望,所以我们必须做一点视觉上的美化与增加它的互动性,所以我们在 Products 下再建立一个元件名称为 SkuCard.js,这个元件之後会在跑完回圈後,Render 它。
import React from "react"
// 增加产品卡片样式
const cardStyles = {
display: "flex",
flexDirection: "column",
justifyContent: "space-around",
alignItems: "flex-start",
padding: "1rem",
marginBottom: "1rem",
boxShadow: "5px 5px 25px 0 rgba(46,61,73,.2)",
backgroundColor: "#fff",
borderRadius: "6px",
maxWidth: "300px",
}
const buttonStyles = {
fontSize: "13px",
textAlign: "center",
color: "#fff",
outline: "none",
padding: "12px",
boxShadow: "2px 5px 10px rgba(0,0,0,.1)",
backgroundColor: "rgb(255, 178, 56)",
borderRadius: "6px",
letterSpacing: "1.5px",
}
const formatPrice = (amount, currency) => {
let price = (amount / 100).toFixed(2)
let numberFormat = new Intl.NumberFormat(["en-US"], {
style: "currency",
currency: currency,
currencyDisplay: "symbol",
})
return numberFormat.format(price)
}
const SkuCard = class extends React.Component {
async redirectToCheckout(event, sku, quantity = 1) {
event.preventDefault()
const { error } = await this.props.stripe.redirectToCheckout({
items: [{ sku, quantity }],
successUrl: `http://localhost:8000/page-2/`,
cancelUrl: `http://localhost:8000/advanced`,
})
if (error) {
console.warn("Error:", error)
}
}
// 从 Props 中捞取对应的 sku 来确保我们找到对应的产品
render() {
const sku = this.props.sku
return (
<div style={cardStyles}>
<h4>{sku.attributes.name}</h4>
<p>Price: {formatPrice(sku.price, sku.currency)}</p>
<button
style={buttonStyles}
onClick={event => this.redirectToCheckout(event, sku.id)}
>
购买
</button>
</div>
)
}
}
export default SkuCard
完成後,我们就立马来调整刚刚的 Skus.js 元件
首先要调整的大概分为三个小部分。
import SkuCard from './SkuCard'
state = {
stripe: null,
}
componentDidMount() {
const stripe = window.Stripe(process.env.GATSBY_STRIPE_PUBLIC_KEY)
this.setState({ stripe })
}
<SkuCard key={sku.id} sku={sku} stripe={this.state.stripe} />
完成後,我们重启开发者服务器,就能看到美美的商品卡片罗!这样的做法是不是既方便又安全呢?若有兴趣的读者也可以尝试用绿界或其他台湾常见的支付商家来串接看看唷!
Gatsby E-commerce Tutorial - Gatsby
<<: [3D地图-CesiumJS系列] 二、建立飞航轨迹及动画
>>: Day 28:IRQ (Part 2) - 中断突进!简单的 IRQ 程序
在前几篇文章中我们都是用 微软内建的RouteAttribute跟HttpMethodAttribu...
CSS的选择器分为基础选择器以及复合选择器 本日将先说明基础选择器 DAY6将继续说明复合选择器 C...
有兴趣的朋友可以点选以下连结,看到我这周撰写「系统分析师养成之路」的心得: https://itun...
免接触 免拿笔签名 流程 人进场 --> 手机扫描 QR --> 填写资料 -->...
终於,花了一个月的时间,我们从零开始认识 Highcharts 到现在已经能够配合 Vue.js 一...