订阅以接收新文章的通知:

喜大普奔:Cloudflare Workers 提供对 Stripe JavaScript SDK 原生支持

2021-11-19

3 分钟阅读时间
这篇博文也有 English日本語版本。

在应用中处理支付是建立在线业务的关键。对于许多开发者来说,处理支付的主要选择是 Stripe。自从大约七年前我第一次接触 Stripe 以来,这项服务的发展已经远远超出了简单的支付处理。在我去年分享的电子商务示例应用程序中,Stripe使用 Connect 产品管理了一个完整的卖家市场。对于那些不满足于接受支付功能的开发者来说,Stripe 的产品套件非常适用。

Announcing native support for Stripe’s JavaScript SDK in Cloudflare Workers

与许多流行的 JavaScript 包一样,早期版本的 Stripe SDK 有核心的 Node.js 依赖项。就 Stripe 而言,它直接与核心 Node.js 库(比如 'net/http') 交互,以处理 HTTP 交互。对 Cloudflare Workers 这个基于 V8 的运行时来说,这意味着官方 Stripe JS 库无法工作;您必须回退以使用 Stripe (有非常完善的文档说明)的 REST API。如此以来,你会失去使用 Stripe 原生 JS 库的好处——比如编辑器中的自动类型检查,以及'stripe.customers.create()' 等函数调用的简单性,因而必须手动构建 HTTP 请求并与 Stripe 的各种功能交互。

今年 4 月,我们说过我们正专注于增加 Workers 所兼容的 JavaScript 包数量:

我们将不断努力,直至用户能无缝导入流行 Node.js 库为止。这是一项规模宏大且持续进行的工作,但我们认为非常值得。

今天,我很高兴能宣布 stripe JS 包对 Cloudflare Workers 的普遍可用。您现在可在项目中直接使用原生 Stripe SDK 了!想要立刻开始使用,请在您的项目中安装 stripe:`npm i stripe`。

对于已经将站点部署到 Cloudflare Pages 的开发人员来说,这也会提供一个绝佳的机会,可在其应用程序中直接使用 Stripe。本周我们宣布了 Cloudflare Pages 对无服务器函数的支持,因此,只需在您的 Pages 项目增加几行 JavaScript 代码,就能为您的数字产品接受付款,或为您的会员网站处理订阅。不需额外配置,而且会自动扩展,一如您的 Pages 站点。

我们准备了一个示例开源代码库,展示如何将 Stripe Checkout 集成到 Pages 应用中。不需要额外配置——正如我们昨日所宣布的那样,Pages 的新 Workers 函数功能允许您部署可无限扩展的函数,只需在您的项目文件中添加一个新的`functions`文件夹。请在 stripe.pages.dev 查看实例演示,或浏览 Github 上的开源代码库

安装 SDK 后,您就可以开始在应用程序中直接接受支付。下面的例子展示了如何启动一个新的 Checkout 会话,并重定向到 Stripe 托管的 Checkout 页面:

在 Cloudflare Workers 中原生支持 Stripe SDK,您可以利用的将不限于支付处理。Stripe 丰富文档中的任何 JavaScript 示例在 Workers 中可直接运行,无需任何更改。

import Stripe from 'stripe/lib/stripe.js';

// use web crypto 
export const webCrypto = Stripe.createSubtleCryptoProvider();

export function getStripe({env}){
  if(!env?.STRIPE_KEY){
    throw new Error('Can not initialize Stripe without STRIPE_KEY');
  }
  const client = Stripe(env.STRIPE_KEY, {
      httpClient: Stripe.createFetchHttpClient(), // ensure we use a Fetch client, and not Node's `http`
  });
  return client;
}



export default {
  async fetch(request, env) {
    const stripe = getStripe({ env })
    const session = await stripe.checkout.sessions.create({
      line_items: [{
        price_data: {
          currency: 'usd',
          product_data: {
            name: 'T-shirt',
          },
          unit_amount: 2000,
        },
        quantity: 1,
      }],
      payment_method_types: [
        'card',
      ],
      mode: 'payment',
      success_url: `${YOUR_DOMAIN}/success.html`,
      cancel_url: `${YOUR_DOMAIN}/cancel.html`,
    });

    return Response.redirect(session.url)
  }
}

具体而言,通过使用 Workers 来处理大量可用的 Stripe webhook,您可以更好地掌握现有系统的运行情况,无需启动任何新的基础设施。下面的例子展示了如何安全地验证对 Worker 函数的传入 webhook 请求,并通过解析webhook 中的数据来执行业务逻辑:

我们同时宣布一个与 Stripe 合作的新 Workers 模板。该模板将帮助您使用我们的最佳实践来启动使用 Stripe 的 Workers 项目。

import Stripe from 'stripe/lib/stripe.js';

// use web crypto 
export const webCrypto = Stripe.createSubtleCryptoProvider();

export function getStripe({env}){
  if(!env?.STRIPE_KEY){
    throw new Error('Can not initialize Stripe without STRIPE_KEY');
  }
  const client = Stripe(env.STRIPE_KEY, {
      httpClient: Stripe.createFetchHttpClient(), // ensure we use a Fetch client, and not Node's `http`
  });
  return client;
}

export default {
  async fetch(request, env) {
    const stripe = getStripe({ env })
    const body = await request.text()
    const sig = request.headers.get('stripe-signature')
    
const event = await stripe.webhooks.constructEventAsync(
      body
      sig,
      env.STRIPE_ENDPOINT_SECRET,
      undefined,
      webCrypto
    );


    // Handle the event
    switch (event.type) {
      case 'payment_intent.succeeded':
        const paymentIntent = event.data.object;
        // Then define and call a method to handle the successful payment intent.
        // handlePaymentIntentSucceeded(paymentIntent);
        break;
      case 'payment_method.attached':
        const paymentMethod = event.data.object;
        // Then define and call a method to handle the successful attachment of a PaymentMethod.
        // handlePaymentMethodAttached(paymentMethod);
        break;
      // ... handle other event types
      default:
        console.log(`Unhandled event type ${event.type}`);
    }

    // Return a response to acknowledge receipt of the event
    return new Response(JSON.stringify({ received: true }), {
      headers: { 'Content-type': 'application/json' }
    })
  }
}

不到 5 分钟,您就能开始为您的下一个数字产品或会员业务接受支付了。您也能通过单一代码库在边缘处理和验证传入 webhook 。这一切无需前期成本和服务器配置,也不用考虑任何标准扩展问题。把您的无服务器函数部署到 Cloudflare 边缘,就可以开始赚钱了!

我们 Stripe 是 Cloudflare Workers 的忠实粉丝。借助边缘上的杰出性能和超棒的无服务器开发体验,我们都很想看到你们能以怎样的新方式来使用 Stripe 创建精彩应用。— Brian Holt,Stripe

这个针对 Stripe JavaScript SDK 的更新令人难以置信,我们都兴奋不已。我们也很想知道您会利用 Workers 对 Stripe 的原生支持创造出怎样的应用。欢迎登录我们的 Discord 服务器,并在 #what-i-built 频道分享您的作品——在此获得邀请

我们保护整个企业网络,帮助客户高效构建互联网规模的应用程序,加速任何网站或互联网应用程序抵御 DDoS 攻击,防止黑客入侵,并能协助您实现 Zero Trust 的过程

从任何设备访问 1.1.1.1,以开始使用我们的免费应用程序,帮助您更快、更安全地访问互联网。要进一步了解我们帮助构建更美好互联网的使命,请从这里开始。如果您正在寻找新的职业方向,请查看我们的空缺职位
Full Stack WeekCloudflare WorkersJavaScript开发人员Developer Platform

在 X 上关注

Kristian Freeman|@kristianf_
Cloudflare|@cloudflare

相关帖子