用Stripe建立一个无服务器的订阅网站(详细指南)

806 阅读8分钟

在本教程中,我们将建立一个网站,使用Stripe创建一个结账系统,然后触发一个通过AWS Amplify提供的AWS Lambda函数,为购买者创建一个用户。然后,用户就可以登录并看到付费的内容了。这种模式适用于会员制或课程网站,你希望用户为访问内容付费。你也可以稍微修改代码,通过电子邮件向客户发送数字产品。

本教程假设有中级ReactAWS Amplify和Node.js知识,尽管你可以将Node.js代码用于任何前端栈。

第一步,是创建一个Stripe账户并确认你的电子邮件。你将需要这个来生成一个API密钥。另外,在结账设置页面的底部,启用只针对客户的结账。如果你想建立自己的表单等,你可以实现全栈式结账,但这将使你在最初的时候进展得更快一点。

然后,使用Stripe仪表板创建一个产品。在左边的导航中,选择 "产品",然后选择 "+添加产品"。填好表格!我把我的产品做成了20美元/月的订阅。

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

npx create-react-app membership-site
cd membership-site

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

npm i aws-amplify @stripe/stripe.js

清除App.js组件的return 语句,使其暂时只返回一个空的<div>

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

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

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

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

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

  return <button onClick={handleClick}>Get Course Access</button>
}

在该事件监听器中,使用loadStripe 函数,并将您的Stripe可发布密钥作为参数。您可以在主页顶部的 "获取您的API密钥 "下找到您的Stripe可发布密钥。

然后,用你的信息运行Stripe的redirectToCheckout 方法 -- 首先是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'
  })
}

在你的应用程序组件中渲染这个组件。

import './App.css'

import Subscribe from './Subscribe'

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

export default App

试试这个 -- 你应该可以用这个表单 "购买 "一个项目你可以使用信用卡号码 "4242 4242 4242 4242 "来测试Stripe,而不用实际付款。现在我们已经实现了本教程的第一步:结账!

现在让我们继续讨论webhook处理程序,它将在物品被购买后创建一个新用户。

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

amplify init

按回车键,接受建议的配置。然后,我们将初始化auth。

amplify add auth

对弹出的每个问题按回车键,接受默认的认证设置。现在我们将添加一个API,这样webhook就可以向一个URL发出请求。

amplify add api

像这样回答前几个问题:

? 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

然后,我们还将创建一个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)

我们确实想为这个项目启用高级设置。对这个问题回答 "是":

? Do you want to configure advanced settings? Yes

首先,我们要从我们的Lambda函数中访问auth:

? 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

对下面的三个问题回答 "不":

? 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

我们将;但是,配置我们的函数可以访问的秘密值。对于你的秘密名称,选择 "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

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

换到你的函数所在的目录,安装AWS SDK和Stripe Node SDK。

cd /amplify/backend/function/stripedemofunction/src
npm i aws-sdk stripe

现在我们开始写逻辑了!

首先,在你的app.js 文件中删除Lambda函数的注释下面的所有内容,然后粘贴以下内容。其中大部分内容已经在文件中了。它将为你的无服务器应用程序设置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')
})

现在我们将编写一个函数,以检索我们的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
}

现在,我们将创建一个路由,处理对我们设置的/webhook 路由的发布请求。

首先,我们将得到我们的Stripe密钥,然后配置Stripe来使用它。你还需要确保在生产应用中,请求是由Stripe正确签名的。

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

然后,我们将实例化AWS Cognito SDK并使用它来创建一个具有管理API的用户。你可以在你的app.js 文件顶部的注释中获得你的UserPoolId 。它将与我代码中的略有不同。然后,我们将确保用户账户是通过电子邮件发送的,并使用该电子邮件来创建账户。

如果我们成功了,我们将发送一个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
  })
})

现在我们需要在用户完成购买时触发Lambda函数。我们首先需要该应用程序的URL。如果你进入你的aws-exports.js 文件(在你的src/ 目录中),你会看到一个endpoint 关键。例如,我的看起来像这样"https://rw7cx5fyn3.execute-api.us-east-1.amazonaws.com/dev"。另外,在URL的末尾添加/webhook ,例如"https://rw7cx5fyn3.execute-api.us-east-1.amazonaws.com/dev/webhook"

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

你的事件应该工作了再次测试结账,然后检查你的电子邮件,看看是否有登录。

现在是展示代码--让我们添加一个登录表格,然后在他们登录后呈现一些付费内容

在你的<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>
  )
}

现在,我们将完成App组件!我们将创建一个user 状态属性,一旦用户签到就会更新。如果用户签到了,我们将呈现付费内容,否则我们将显示签到表格。

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

如果你想关闭这个演示,你可以运行amplify delete ,取消云资源的配置

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