使用 Stripe、Nuxt.js 和 vercel 接受付款

2025-06-05

使用 Stripe、Nuxt.js 和 vercel 接受付款

距离我上次发帖已经过去很久了,我想写一篇关于如何使用 Stripe 接受付款的小文章,因为我正在将 Stripe 集成到我目前正在构建的 SaaS 项目中。

接受付款并不困难,甚至不需要服务器。

我将使用 Nuxt.js、Tailwindcss 构建此应用程序并将其托管在 vercel 上。

TLDR;代码和现场演示可以在本文底部找到

我制作的网站并不完整,也没有响应,但如果有人想提出 PR 并使其正常运行,请继续。

  1. 用它搭建一个新的 Nuxt 项目yarn create nuxt-app stripe-nuxt,您可以选择自己喜欢的 CSS 框架,我选择了 Tailwindcss,选择了 axios,并且我还使用了 nuxt-content 来存储产品数据库。

清除 index.vue 页面并从 default.vue 文件中删除样式。

在 index.vue 中添加此标记和脚本,这将在主页上显示产品网格。

<template>
  <main class="min-h-screen">
    <section class="p-8 max-w-4xl mx-auto">
      <div class="grid grid-cols-1 lg:grid-cols-3 xl:grid-cols-3 gap-6">
        <nuxt-link
          :to="product.slug"
          class="overflow-hidden text-center"
          v-for="(product, p) in products"
          :key="p"
        >
          <img :src="product.images[0]" alt="product.name" class="mb-4" />
          <p class="font-semibold text-gray-700 mb-1">
            {{ product.name }}
          </p>
          <p class="text-sm">$ {{ product.amount }}</p>
        </nuxt-link>
      </div>
    </section>
  </main>
</template>

<script>
export default {
  transition: "fade",
  async asyncData({ $content }) {
    const products = await $content("products").fetch();
    return { products };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

上述代码将被渲染并看起来像这样。
替代文本

创建一个新文件并将其命名_slug.vue为与 index.vue 相同的目录,这将作为我们的产品页面,并用以下代码填充它。

<template>
   <main>
      <div class="flex">
         <div class="w-1/2 h-screen flex items-center justify-center">
            <img :src="product.images[0]" :alt="product.name" />
         </div>
         <div
            class="w-1/2 h-screen text-white flex items-center justify-center p-8 relative"
            :style="{ backgroundColor: `#${product.color.hex}` }"
            >
            <nuxt-link
               to="/"
               class="flex items-center space-x-2 absolute top-8 left-8"
               >
               <svg
                  class="w-5 h-5"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                  xmlns="http://www.w3.org/2000/svg"
                  >
                  <path
                     stroke-linecap="round"
                     stroke-linejoin="round"
                     stroke-width="2"
                     d="M7 16l-4-4m0 0l4-4m-4 4h18"
                     ></path>
               </svg>
               <p>Home</p>
            </nuxt-link>
            <div class="space-y-4">
               <p class="text-2xl font-bold">{{ product.name }}</p>
               <p>$ {{ product.amount }}</p>
               <p class="text-gray-100 text-sm">{{ product.description }}</p>
               <button
                  @click="buy()"
                  class="w-full py-3 bg-white text-gray-800 font-semibold flex items-center justify-center space-x-2"
                  :class="{ 'opacity-50 cursor-not-allowed': loading }"
                  >
                  <btn-loader v-if="loading" />
                  <p>Buy Now</p>
               </button>
            </div>
         </div>
      </div>
   </main>
</template>
<script>
   export default {
     transition: "fade",
     async asyncData({ $content, params }) {
       const product = await $content("products", params.slug).fetch();
       return { product };
     },
     data() {
       return {
         stripe: null,
         loading: false,
       };
     },
     methods: {
       async buy() {
         try {
           this.loading = true;
           const { data } = await this.$axios.post("/api/checkout", {
             order: {
               name: this.product.name,
               description: this.product.description,
               images: this.product.images,
               amount: this.product.amount * 100,
               currency: this.product.currency,
               quantity: 1,
             },
             slug: this.$route.params.slug,
           });
           this.stripe.redirectToCheckout({ sessionId: data.id });
         } catch (err) {
           alert(err);
           this.loading = false;
         }
       },
     },
     mounted() {
       this.stripe = Stripe("pk_test_ZaFKDdkCzVR4hCmDsUKWodm200fZIzrcmf");
     },
   };
</script>
Enter fullscreen mode Exit fullscreen mode

这将使页面看起来像这样,不是很花哨,但看起来不错(没有响应)。

替代文本

我们需要在文件中添加条纹结帐脚本nuxt.config.js,将其添加到 head 对象中。

script: [{src: "https://js.stripe.com/v3/"}]
Enter fullscreen mode Exit fullscreen mode

让我们关注一下剧本,看看到底发生了什么。
替代文本

  1. 创建一个空的条纹对象,我们将在这里初始化条纹对象。

  2. 现在将条纹公钥传递给条纹方法(我们在 head 标签中添加的方法),您可以从条纹仪表板获取公钥

  3. 让我们创建一个结账 API,并使用 Vercel 的无服务器函数。我们在名为 的文件夹下添加的任何 js 文件都api将在 Vercel 中充当无服务器函数,这很酷吧?所以我创建了一个名为 checkout.js 的文件夹,并编写了一个小脚本。

const stripe = require("stripe")(process.env.STRIPE_TEST_SK);
const hostUrl = "http://localhost:3000";

export default async (req, res) => {
  const session = await stripe.checkout.sessions.create({
    payment_method_types: ["card"],
    line_items: [req.body.order],
    success_url: `${hostUrl}/${req.body.slug}?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${hostUrl}/${req.body.slug}?failed=true`
  });

  return res.status(200).json(session);
};

Enter fullscreen mode Exit fullscreen mode

您需要安装并导入 Stripe 软件包,这样就可以创建结账会话(密钥可以在 Stripe 仪表板中找到)。
成功 URL 和取消 URL,顾名思义,分别指示 Stripe 重定向到哪里。

  1. 现在我们已经收到了会话 ID,只需将其传递给 Stripe 重定向方法
this.stripe.redirectToCheckout({ sessionId: data.id });
Enter fullscreen mode Exit fullscreen mode

这是代码,这是现场演示

如果您喜欢我的作品并希望获得最新信息,请订阅我的时事通讯,或者如果您想给我买些咖啡,您可以在这里捐款,我们可以边喝咖啡边进行在线交流。

文章来源:https://dev.to/fayaz/accepting- payments-with-stripe-nuxt-js-and-vercel-1m14
PREV
使用短路求值编写美观而优雅的 Javascript 代码。
NEXT
Redux:引擎盖之下之旅