这是四部分系列文章中的第三篇。在第一部分中,我们在 Azure 上设置了一个无服务器 Stripe 函数。第二部分介绍了如何在 Github 上托管该函数。本文将重点介绍如何将其连接为一个 Vue.js 应用程序。
文章系列
Stripe 提供了许多构建结账表单的方法,最基本的方法是在页面上放置一个按钮,触发该按钮以弹出其自定义模态框。有一个 此组件的代码库和组件,但尽管它易于实现(这可能是最简单的方法),但我想要更多自定义,并希望结账流程成为页面和应用程序的一部分。这种方法不适合我的需求。
Stripe 元素
Stripe 还提供了一个称为 元素 的功能。元素允许您将 Stripe 的支付系统集成到您自己的结账表单中,并将其样式设置为与您自己的网站一致,从而获得连贯的体验。您不会感觉自己正在使用第三方插件。如果您更喜欢开箱即用的内容,他们确实有一些 预设样式示例。
幸运的是,有一个非常不错的代码库,其中包含 Stripe 元素的 Vue 版本,名为 vue-stripe-elements。该代码库的文档非常不错,您可以查看一下。以下是我的使用方法
npm i vue-stripe-elements-plus --save
…或使用 Yarn
yarn add vue-stripe-elements-plus
现在让我们谈谈我们的购物车并将其集成。
购物车
以下是应用程序鸟瞰图的样子。我们已经讨论了函数和 Stripe 部分,现在让我们深入了解应用程序本身。

在这些文章中,我们不会介绍整个应用程序的设置,而只介绍购物车和结账。如果您需要了解 Vue、Vuex 和 Nuxt 的基础知识,建议您在继续之前查看以下链接
在我们使用 Vuex 设置的通用商店中,我们保存了所有产品数据的清单,用于填充页面上的商品。我们还将使用这些信息填充一个(目前为空)购物车对象,以便将商品添加到其中进行购买。我们将在 pages 目录中的 `Cart.vue` 页面上使用这些数据。如果您不熟悉 Nuxt.js,它允许我们通过在 pages 目录中创建 `vue` 组件来将其用作页面。我们仍然可以使用 components 目录中的组件填充这些页面,以创建更模块化的应用程序。以下是我们现在讨论的部分

我们需要从 Vuex 中的存储中获取两条信息:`cart` 的内容和 `cartTotal`。
我们将在 `pages/Cart.vue` 中使用计算属性来获取这些信息,以便我们可以在购物车中缓存和使用它们。
computed: {
cart() {
return this.$store.state.cart;
},
cartTotal() {
return this.$store.state.cartTotal;
},
...
}
…并且我们将创建一个新的计算属性,它也将存储购物车中商品的货币总计
computed: {
...
total() {
return Object.values(this.cart)
.reduce((acc, el) => acc + (el.count * el.price), 0)
.toFixed(2);
}
}
我们将首先检查购物车中是否有商品。如果有,则需要检查是否已经处理了付款。我们需要这样做,因为如果购物车中没有商品或已经为添加的商品处理了付款,则无需显示结账表单。
<div v-if="cartTotal > 0">
<!--we'll add our checkout here-->
</div>
<!--If the cart is empty, give them the ability to get back to the main page to add items-->
<div v-else-if="cartTotal === 0 && success === false" class="empty">
<!--we'll add our empty state here-->
</div>
<!--If there's a success, let's let people know it's being processed, we'll add a success component later on-->
<div v-else>
<!--we'll add success here-->
</div>
我们还将在我们的数据中创建一个 success 属性,我们将其初始设置为 `false`,并在稍后用于记录付款是否已成功提交。
data() {
return {
success: false
};
},
如果存在购物车商品,我们希望显示它们、它们的单个总计(因为我们可以拥有多个相同商品的数量)以及最终总计。
<div v-if="cartTotal > 0">
<h1>Cart</h1>
<div class="cartitems"
v-for="item in cart"
key="item">
<div class="carttext">
<h4>{{ item.name }}</h4>
<p>{{ item.price | usdollar }} x {{ item.count }}</p>
<p>Total for this item: <strong>{{ item.price * item.count }}</strong></p>
</div>
<img class="cartimg" :src="`/${item.img}`" :alt="`Image of ${item.name}`">
</div>
<div class="total">
<h3>Total: {{ total | usdollar }}</h3>
</div>
<!--we're going to add our checkout here-->
</div>
我们使用过滤器以美元格式化价格。我以这种方式格式化它们,而不是对其进行硬编码,以防将来需要支持其他货币。
filters: {
usdollar: function(value) {
return `$${value}`;
}
}
设置结账组件
现在我们将创建我们的 `checkout` 组件,它将包含所有 Stripe 结账逻辑并连接到我们在 第二部分 中设置的无服务器函数。我们将在 `Cart.vue` 文件中注册该组件
import AppCheckout from './../components/AppCheckout.vue';
export default {
components: {
AppCheckout
},
...
}
我们现在处于以下状态

并且,在 `checkout` 组件本身中,我们将引入我们在 vue-stripe-elements 代码库文档中看到的该文件的基准
<template>
<div id='app'>
<h1>Please give us your payment details:</h1>
<card class='stripe-card'
:class='{ complete }'
stripe='pk_test_XXXXXXXXXXXXXXXXXXXXXXXX'
:options='stripeOptions'
@change='complete = $event.complete'
/>
<button class='pay-with-stripe' @click='pay' :disabled='!complete'>Pay with credit card</button>
</div>
</template>
<script>
import { stripeKey, stripeOptions } from './stripeConfig.json'
import { Card, createToken } from 'vue-stripe-elements-plus'
export default {
data () {
return {
complete: false,
stripeOptions: {
// see https://stripe.com/docs/stripe.js#element-options for details
}
}
},
components: { Card },
methods: {
pay () {
// createToken returns a Promise which resolves in a result object with
// either a token or an error key.
// See https://stripe.com/docs/api#tokens for the token object.
// See https://stripe.com/docs/api#errors for the error object.
// More general https://stripe.com/docs/stripe.js#stripe-create-token.
createToken().then(data => console.log(data.token))
}
}
}
</script>
接下来…
到目前为止,这就是该组件开箱即用的样子。我们将不得不稍微更新一下此组件以满足我们的需求,但不会太多。敬请期待明天的最后一期,届时我们将把我们的组件连接到我们的无服务器函数并完成结账!