这是四部分系列文章中的第四篇。在第一部分中,我们在 Azure 上设置了一个无服务器 Stripe 函数。第二部分介绍了如何在 Github 上托管该函数。第三部分介绍了 Vue 中的 Stripe Elements。这篇最后一篇文章展示了如何配置结账组件并使购物车完全正常工作。
文章系列
提醒一下,这是我们目前应用程序所处的位置

配置结账组件
为了使组件满足我们的需求,我们需要做几件事
- 确保表单仅在我们未提交时显示——我们将在稍后的
pay
方法中处理此逻辑 - 允许表单获取客户的电子邮件地址,以防订单出现问题。
- 在提供必需的电子邮件地址之前禁用提交按钮
- 最后也是最重要的是,更改为我们的测试密钥
这是我们更新后的 checkout
组件,其中突出显示了对原始代码的更改
<div v-if="!submitted" class="payment">
<h3>Please enter your payment details:</h3>
<label for="email">Email</label>
<input id="email" type="email" v-model="stripeEmail" placeholder="[email protected]"/>
<label for="card">Credit Card</label>
<p>Test using this credit card: <span class="cc-number">4242 4242 4242 4242</span>, and enter any 5 digits for the zip code</p>
<card class='stripe-card'
id="card"
:class='{ complete }'
stripe='pk_test_5ThYi0UvX3xwoNdgxxxTxxrG'
:options='stripeOptions'
@change='complete = $event.complete'
/>
<button class='pay-with-stripe' @click='pay' :disabled='!complete || !stripeEmail'>Pay with credit card</button>
</div>
我们需要存储和使用许多内容才能使用此组件,因此让我们将它们添加到 data
中或作为 props
引入。我们需要从父组件获取的 props
将是 total
和 success
。我们需要购买的 total
金额才能将其发送到 Stripe,而 success
是我们需要在此组件和父组件之间协调的内容,因为这两个组件都需要知道付款是否成功。我还写出了我的 props 的数据类型以及默认值。
props: {
total: {
type: [Number, String],
default: '50.00'
},
success: {
type: Boolean,
default: false
}
},
接下来,我们需要存储的数据将是我们在表单中收集的 stripeEmail
、我保留的 stripeOptions
以向您展示您可以为表单配置一些选项,以及我们将从与服务器和 Stripe 通信中获得的 status
和 response
。我们还希望保存表单是否已提交,以及表单是否已完成以启用和禁用提交按钮,这两者都可以是布尔值。
data() {
return {
submitted: false,
complete: false,
status: '',
response: '',
stripeOptions: {
// you can configure that cc element. I liked the default, but you can
// see https://stripe.com/docs/stripe.js#element-options for details
},
stripeEmail: ''
};
},
现在是魔法时间!我们拥有了所有必要的东西——我们只需要更改我们的 pay()
方法,它将为我们完成所有繁重的工作。我将为此使用 Axios,它将接收和转换数据
npm i axios --save
…或使用 Yarn
yarn add axios
如果您不熟悉 Axios 及其作用,请查看 这篇文章 以获取一些背景信息。
pay() {
createToken().then(data => {
this.submitted = true; // we'll change the flag to let ourselves know it was submitted
console.log(data.token); // this is a token we would use for the stripeToken below
axios
.post(
'https://sdras-stripe.azurewebsites.net/api/charge?code=zWwbn6LLqMxuyvwbWpTFXdRxFd7a27KCRCEseL7zEqbM9ijAgj1c1w==',
{
stripeEmail: this.stripeEmail, // send the email
stripeToken: data.token.id, // testing token
stripeAmt: this.total // send the amount
},
{
headers: {
'Content-Type': 'application/json'
}
}
)
.then(response => {
this.status = 'success';
this.$emit('successSubmit');
this.$store.commit('clearCartCount');
// console logs for you :)
this.response = JSON.stringify(response, null, 2);
console.log(this.response);
})
.catch(error => {
this.status = 'failure';
// console logs for you :)
this.response = 'Error: ' + JSON.stringify(error, null, 2);
console.log(this.response);
});
});
},
上面的代码做了很多事情
- 它允许我们使用
this.submitted
跟踪我们是否已提交表单。 - 它使用 Axios 发布到我们的函数。我们通过转到函数在门户中的位置并在屏幕右侧点击“获取函数 URL”来获取此 URL。
- 它将电子邮件、令牌和总计发送到无服务器函数
- 如果成功,它会将状态更改为
success
,提交到我们的 Vuex 存储,使用 mutation 清空我们的购物车,并向父购物车组件发出付款成功的信号。它还会将响应记录到控制台,不过这是出于教育目的,应在生产环境中删除。 - 如果出错,它会将状态更改为
failure
,并记录错误响应以帮助调试
如果付款失败,我们可以从 status
中知道,我们需要让用户知道出了问题,清空我们的购物车,并允许他们重试。在我们的模板中
<div v-if="status === 'failure'">
<h3>Oh No!</h3>
<p>Something went wrong!</p>
<button @click="clearCheckout">Please try again</button>
</div>
该按钮执行以下 clearCheckout
方法,该方法清除许多字段并允许客户重试
clearCheckout() {
this.submitted = false;
this.status = '';
this.complete = false;
this.response = '';
}
如果付款成功,我们将显示一个加载组件,该组件将在我们收到服务器的回复之前播放 SVG 动画。有时这可能需要几秒钟,因此如果在短时间或长时间内看到动画,重要的是我们的动画要有意义,并且可以根据需要循环。
<div v-else class="loadcontain">
<h4>Please hold, we're filling up your cart with goodies</h4>
<app-loader />
</div>
看起来是这样的
查看 Sarah Drasner 在 CodePen 上的笔 shop loader(@sdras)。
现在,如果我们重新访问在 pages/cart.vue
中查看的第一个购物车组件,我们可以根据之前设置的逻辑填充该页面,因为它已完成
<div v-if="cartTotal > 0">
<h1>Cart</h1>
...
<app-checkout :total="total" @successSubmit="success = true"></app-checkout>
</div>
<div v-else-if="cartTotal === 0 && success === false" class="empty">
<h1>Cart</h1>
<h3>Your cart is empty.</h3>
<nuxt-link exact to="/"><button>Fill 'er up!</button></nuxt-link>
</div>
<div v-else>
<app-success @restartCart="success = false"/>
<h2>Success!</h2>
<p>Your order has been processed, it will be delivered shortly.</p>
</div>
如果我们的购物车中有商品,我们会显示购物车。如果购物车为空且 success 为 false,我们会让他们知道他们的购物车为空。否则,如果刚刚处理了结账,我们会让他们知道一切都已成功执行!
我们现在在这里

在 AppSuccess.vue
组件中,我们有一个小的 SVG 动画,旨在让他们对购买感到满意
查看 Sarah Drasner 在 CodePen 上的笔 success(@sdras)。
(您可能需要点击“重新运行”以重新播放动画。)
我们还在 mounted()
生命周期钩子中添加了一个小计时器
window.setTimeout(() => this.$emit('restartCart'), 3000);
这将在他们阅读时显示三秒钟的成功信息,然后启动上面组件中显示的 restartCart
。这允许我们在他们想继续购物的情况下重置购物车。
结论
您学习了如何创建无服务器函数、将其托管在 Github 上、添加所需的依赖项、与 Stripe 通信、在 Vue 应用程序中设置购物车、建立与无服务器函数和 Stripe 的连接以及处理所有购物车状态的逻辑。哇,干得好!
值得一提的是,我们查看的演示应用程序是一个专门为此教程目的而构建的示例应用程序。对于生产站点,您需要执行许多步骤,包括测试、构建应用程序的 dist 文件夹、使用真实的 Stripe 密钥、仅从客户端发送商品并在无服务器函数中添加价格等。还有很多方法可以设置它,无服务器函数与 Vue 等结合起来可以非常灵活。希望这能帮助您入门,并在您自己尝试时节省时间。
感谢您提供的精彩教程系列!不确定这是否已在某个地方配置但我错过了,但我必须使用分值金额 50.00 -> 5000 才能将交易提取到 Stripe 中。再次感谢!
哦,很有趣!我不必这样做,我想知道有什么不同。感谢您让大家知道,以防他们也遇到这种情况。
我相信直接从客户端发送价格是不安全的!您应该在结论中向新手提及这一点!
啊,是的,当然,我会在最后的注意事项中添加那个额外的要点。谢谢!
嗨,好文章。但是我们怎么知道客户买了什么?您只向 Stripe 发送金额。Azure 函数是否应该获取商品并将其存储在某个数据库中,以便我们交付订单?
谢谢
是的!结论中提到了这一点 :)
作为一个小提示,NPM 不再需要 --save 标志来将包包含在依赖项中。