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

喜大普奔: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

相关帖子

2024年10月31日 13:00

Moving Baselime from AWS to Cloudflare: simpler architecture, improved performance, over 80% lower cloud costs

Post-acquisition, we migrated Baselime from AWS to the Cloudflare Developer Platform and in the process, we improved query times, simplified data ingestion, and now handle far more events, all while cutting costs. Here’s how we built a modern, high-performing observability platform on Cloudflare’s network. ...