使用 Stripe 构建无服务器订阅网站

2025-06-08

使用 Stripe 构建无服务器订阅网站

在本教程中,我们将构建一个网站,使用 Stripe 创建结账系统,然后触发通过 AWS Amplify 配置的 AWS Lambda 函数,为购买者创建用户。之后,用户可以登录并查看付费内容!这种模式适用于会员制或课程网站,用户需要付费才能访问内容。您也可以稍微修改代码,将数字产品通过电子邮件发送给客户!

请注意,我是 AWS Amplify 团队的开发倡导者,如果您对此有任何反馈或疑问,请联系我或在我们的 discord 上提问 - discord.gg/amplify!

本教程假设您具有中级ReactAWS Amplify和 Node.js 知识,但您可以将 Node.js 代码与任何前端堆栈一起使用。

第一步是创建一个Stripe 帐户并确认您的邮箱地址。您需要用此邮箱地址来生成 API 密钥。此外,请在结账设置页面底部启用“仅限客户端结账”。如果您想自行构建表单等,可以实现全栈结账,但这会让您初期操作更快一些。

然后,使用 Stripe 仪表板创建产品。在左侧导航栏中,选择“产品”,然后选择“+ 添加产品”。填写表单!我选择的是每月 20 美元的订阅服务。

现在,创建一个 React 应用程序。

npx create-react-app membership-site
cd membership-site
Enter fullscreen mode Exit fullscreen mode

然后安装 Amplify 库和 Stripe 的 JavaScript SDK。

npm i aws-amplify @stripe/stripe.js
Enter fullscreen mode Exit fullscreen mode

清除 App.js 组件的return语句,以便它<div>现在只返回一个空的。

创建两个新的空 React 组件文件,一个名为SignIn.js,一个名为Subscribe.js

让我们首先实现Subscribe.js。从 Stripe SDK 导入 loadStripe。

import { loadStripe } from '@stripe/stripe-js'

Enter fullscreen mode Exit fullscreen mode

创建一个在点击时触发事件监听器的按钮。

export default function Subscribe () {
  const handleClick = async e => {
  }

  return <button onClick={handleClick}>Get Course Access</button>
}
Enter fullscreen mode Exit fullscreen mode

在该事件监听器中,使用loadStripe带有 Stripe Publishable 密钥作为参数的函数。您可以在主页顶部的“获取 API 密钥”下找到您的 Stripe Publishable 密钥。

redirectToCheckout然后,使用您的信息(首先是 )运行 Stripe 的方法lineItems。如果您有多个商品可供用户选择,您需要实现某种购物车结账功能,将商品及其数量添加到此数组中。在本例中,对于一个简单的应用,我们将数量设置为 1,并使用商品的价格键。您可以前往您的产品页面,然后复制价格旁边的 API ID 来找到价格键。

如果您将商品设置为订阅,请将其设置为模式,否则请使用“产品”或您创建的任何内容。然后设置成功和取消的 URL——如果成功,我会将他们重定向回主页!我没有实现错误页面,但您可以实现。

const handleClick = async e => {
  const stripe = await loadStripe('your_stripe_publishable_key')
  const { error } = await stripe.redirectToCheckout({
    lineItems: [{
      price: 'price_key',
      quantity: 1
    }],
    mode: 'subscription',
    successUrl: 'http://localhost:3000/',
    cancelUrl: 'http://localhost:3000/cancel'
  })
}
Enter fullscreen mode Exit fullscreen mode

在您的 App 组件中呈现此组件。

import './App.css'

import Subscribe from './Subscribe'

function App () {
  return (
    <div className='App'>
      <h1>My Fancy Subscription Site</h1>
      <Subscribe />
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

试试看——你应该可以用这个表单“购买”一件商品了!你可以用信用卡号“4242 4242 4242 4242”来测试 Stripe,无需实际付款。现在我们已经实现了本教程的第一步:结账!

现在让我们转到 webhook 处理程序,一旦购买了商品,它就会创建一个新用户。

首先,为您的项目初始化 Amplify。

amplify init
Enter fullscreen mode Exit fullscreen mode

按回车键接受建议的配置。然后我们将初始化身份验证。

amplify add auth
Enter fullscreen mode Exit fullscreen mode

每次弹出问题时,按 Enter 键接受默认身份验证设置。现在,我们将添加一个 API,以便 Webhook 可以向 URL 发出请求。

amplify add api
Enter fullscreen mode Exit fullscreen mode

像这样回答前几个问题:

? Please select from one of the below mentioned services: REST
? Would you like to add a new path to an existing REST API: No
? Provide a friendly name for your resource to be used as a label for this category in the project: apib104bfb8
? Provide a path (e.g., /book/{isbn}): /webhook
Enter fullscreen mode Exit fullscreen mode

然后,我们还将创建一个 AWS Lambda 函数。请用以下方式回答这组问题:

? Choose a Lambda source Create a new Lambda function
? Provide an AWS Lambda function name: stripedemofunction
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: Serverless ExpressJS function (Integration with
 API Gateway)
Enter fullscreen mode Exit fullscreen mode

我们确实想为该项目启用高级设置。请回答“是”。

? Do you want to configure advanced settings? Yes
Enter fullscreen mode Exit fullscreen mode

首先,我们要从 Lambda 函数访问身份验证。

? Select the categories you want this function to have access to. auth
? Select the operations you want to permit on stripedemo: create, read, update, delete
Enter fullscreen mode Exit fullscreen mode

对以下三个问题的回答都是“否”:

? Do you want to invoke this function on a recurring schedule? No
? Do you want to enable Lambda layers for this function? No
? Do you want to configure environment variables for this function? No
Enter fullscreen mode Exit fullscreen mode

但是,我们会配置函数可以访问的密钥值。密钥名称请选择“stripe_key”,然后输入您的 Stripe 密钥。密钥位于您之前找到可发布密钥的位置——您必须点击“显示测试密钥”才能看到它。

? Enter a secret name (this is the key used to look up the secret value): stripe_key
? Enter the value for stripe_key: [hidden]
? What do you want to do? I'm done
Enter fullscreen mode Exit fullscreen mode

然后运行amplify push将所有配置的资源部署到云端!

更改为您的函数所在的目录并安装 AWS SDK 和 Stripe Node SDK。

cd /amplify/backend/function/stripedemofunction/src
npm i aws-sdk stripe
Enter fullscreen mode Exit fullscreen mode

现在我们开始编写逻辑!

首先,删除Lambda 函数文件注释下方的所有内容app.js,然后粘贴以下内容。大部分内容已包含在文件中。它将为您的无服务器应用程序设置 Express。

const express = require('express')
const bodyParser = require('body-parser')
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')
const aws = require('aws-sdk')

// declare a new express app
const app = express()
app.use(bodyParser.json({
  verify: function (req, res, buf) {
    req.rawBody = buf.toString()
  }
}))
app.use(awsServerlessExpressMiddleware.eventContext())

// Enable CORS for all methods
app.use(function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*')
  res.header('Access-Control-Allow-Headers', '*')
  next()
})

app.listen(3000, function () {
  console.log('App started')
})
Enter fullscreen mode Exit fullscreen mode

现在我们将编写一个函数来检索 Stripe 密钥。如果你查看文件顶部,app.js你会发现它已经生成了!

const getStripeKey = async () => {
  const { Parameters } = await (new aws.SSM())
    .getParameters({
      Names: ['stripe_key'].map(secretName => process.env[secretName]),
      WithDecryption: true
    })
    .promise()
  return Parameters[0].Value
}
Enter fullscreen mode Exit fullscreen mode

现在我们将创建一条路线来处理我们设置的路线的发布请求/webhook

首先,我们需要获取 Stripe 密钥,然后配置 Stripe 来使用它。您还需要确保在生产应用中,该请求已由Stripe 正确签名。

我们将使用 Stripe 请求正文中发送给我们的客户 ID 来获取客户的电子邮件。

然后,我们将实例化 AWS Cognito SDK,并使用它通过 admin API 创建用户。您可以UserPoolId在文件顶部的注释中获取您的代码app.js。它与我的代码略有不同。然后,​​我们将确保通过电子邮件发送用户帐户,并使用该电子邮件创建帐户。

如果成功,我们将发送 200 响应。

app.post('/webhook', async function (req, res) {
  const stripeKey = await getStripeKey()
  const stripe = require('stripe')(stripeKey)
  console.log(stripeKey)

  const customer = await stripe.customers.retrieve(
    req.body.data.object.customer
  )

  const userEmail = customer.email

  const cognito = new aws.CognitoIdentityServiceProvider({ apiVersion: '2016-04-18' })

  cognito.adminCreateUser({
    UserPoolId: process.env.AUTH_STRIPEDEMO1C66A4D4_USERPOOLID,
    Username: userEmail,
    DesiredDeliveryMediums: [
      'EMAIL'
    ],

    UserAttributes: [
      {
        Name: 'email',
        Value: userEmail
      }],
    ValidationData: [
      {
        Name: 'email',
        Value: userEmail
      }
    ]
  }, function (err, data) {
    if (err) console.log(err, err.stack) // an error occurred
    else {
      console.log(data)
      res.sendStatus(200)
    } // successful response
  })
})
Enter fullscreen mode Exit fullscreen mode

现在,我们需要在用户完成购买时触发 Lambda 函数。首先,我们需要获取应用的 URL。如果您进入目录aws-exports.js中的文件src/,会看到一个endpoint键。例如,我的 URL 是这样的:“ https://rw7cx5fyn3.execute-api.us-east-1.amazonaws.com/dev ”/webhook 。此外,在 URL 末尾添加以下内容,例如:“ https://rw7cx5fyn3.execute-api.us-east-1.amazonaws.com/dev/webhook ”

然后,进入Stripe 控制面板,点击左侧导航栏中的“开发者”。然后点击下方的“Webhooks”。点击右上角的“+ 添加端点”按钮。粘贴上面的 URL,然后选择“payment_intent.succeeded”作为要监听的事件。

您的活动应该可以正常进行!请再次测试结账功能,然后查看您的邮箱,获取登录信息!

现在来看看演示代码——让我们添加一个登录表单,然后在登录后呈现一些付费内容!

在您的<SignIn>组件中,添加以下 React 表单,提交后将触发 Amplify 的登录方法。

import { useState } from 'react'
import { Auth } from 'aws-amplify'

export default function SignIn ({ setUser }) {
  async function logIn (e) {
    e.preventDefault()
    try {
      const user = await Auth.signIn(username, password)
      setUser(user)
    } catch (error) {
      console.log('error signing in', error)
    }
  }
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  return (
    <form onSubmit={logIn}>
      <input type='text' placeholder='username' onChange={e => setUsername(e.target.value)} />
      <input type='password' placeholder='password' onChange={e => setPassword(e.target.value)} />
      <input type='submit' value='log in' />
    </form>
  )
}
Enter fullscreen mode Exit fullscreen mode

现在我们来完善 App 组件!我们将创建一个userstate 属性,该属性会在用户登录后更新。如果用户已登录,我们将渲染付费墙内容;否则,我们将显示登录表单。

import './App.css'

import Subscribe from './Subscribe'
import SignIn from './SignIn'
import { Auth } from 'aws-amplify'
import { useState } from 'react'

function App () {
  const [user, setUser] = useState(null)
  return (
    <div className='App'>
      <h1>My Fancy Subscription Site</h1>
      <Subscribe />
      {user
        ? <h1>Paywalled content!</h1>
        : <SignIn setUser={setUser} />}
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

如果要关闭此演示,您可以运行amplify delete以取消配置云资源!

大功告成!在本教程中,我们创建了一个 Stripe 结账系统,它会触发账户创建。登录后,用户就可以查看付费内容了!如果您对 AWS Amplify 或本教程有任何反馈,请告诉我!

鏂囩珷鏉ユ簮锛�https://dev.to/aws/build-a-serverless-subscription-site-with-stripe-48h1
PREV
使用 Amplify Studio 构建社交媒体时间线
NEXT
⏱ 10 分钟教程:使用 Amplify Functions 部署 Apollo GraphQL 服务器