# Handle payment events with webhooks How to use webhooks to respond to offline payment events. *Webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) 是一个 HTTP 端点,用于从 Stripe 接收事件。 通过 Webhook,您可以接收付款流程以外发生的支付事件的通知,例如: - 成功付款 (`payment_intent.succeeded`) - 有争议的付款 (`charge.dispute.created`) - Stripe 账户可用余额 (`balance.available`) 您可以使用管理平台进行一次性操作,例如退款或更新客户信息,尽管 Webhook 可以扩展您的支付集成和处理大量重要业务事件。 ## 构建您自己的 Webhook 可在自己的服务器上构建一个 Webhook 处理程序,用以管理您的所有线下付款流程。首先公开一个可以接收 Stripe 的请求的端点并用 CLI 在本地测试您的集成。来自 Stripe 的每个请求都会包含一个 [Event](https://docs.stripe.com/api/events/object.md) 对象,其中引用了 Stripe 上修改的对象。 ## 创建 Webhook 端点 在您的应用中添加新端点。您可通过检查请求体内发送的事件对象的 `type` 字段来操作某些事件。然后,您可以通过标准输出打印,确保您的 Webhook 能正常工作。 添加完新的端点后启动服务器。 #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') require 'stripe' require 'sinatra' require 'json' # Using the Sinatra framework set :port, 4242 post '/webhook' do payload = request.body.read event = nil begin event = Stripe::Event.construct_from( JSON.parse(payload, symbolize_names: true) ) rescue JSON::ParserError => e # Invalid payload status 400 return end # Handle the event case event.type when 'payment_intent.succeeded' payment_intent = event.data.object # contains a Stripe::PaymentIntent puts 'PaymentIntent was successful!' when 'payment_method.attached' payment_method = event.data.object # contains a Stripe::PaymentMethod puts 'PaymentMethod was attached to a Customer!' # ... handle other event types else puts "Unhandled event type: #{event.type}" end status 200 end ``` ## 安装并设置 Stripe CLI 如需更多安装选项,请查看[用 Stripe CLI 开始](https://docs.stripe.com/stripe-cli.md)。 如果您安装着 Stripe CLI,则在命令行中运行 `stripe login`,生成一个配对代码来关联到您的 Stripe 账户。按**回车**启动浏览器,登入您的 Stripe 账户来允许访问。生成的 API 有效期为 90 天。可在管理平台的 [API 密钥](https://dashboard.stripe.com/apikeys)下修改或删除密钥。 > 您可以创建项目特定的配置,方法是在登录时和运行该项目的命令时包含 [–project-name](https://docs.stripe.com/cli/login#login-project-name) 标志。 测试 ```bash stripe login Your pairing code is: humour-nifty-finer-magic Press Enter to open up the browser (^C to quit) ``` 如果要使用现有的 API 密钥,则使用 `--api-key` 标志: ```bash stripe login --api-key <> Your pairing code is: humour-nifty-finer-magic Press Enter to open up the browser (^C to quit) ``` ## 在本地测试您的 Webhook 通过 `listen` 指令,用 CLI 将事件转到您的本地 Webhook 端点。 假设您的应用的运行端口是 4242,运行: ```bash stripe listen --forward-to http://localhost:4242/webhook ``` 在另一个终端选项卡中,用 `trigger` CLI 指令触发一个模拟 Webhook 事件。 ```bash stripe trigger payment_intent.succeeded ``` 您的 `listen` 选项卡中会显示以下事件: ```bash [200 POST] OK payment_intent.succeeded ``` “PaymentIntent 已成功!”出现在您的服务器运行的终端选项卡中。 ## Optional: 检查 Webhook 签名 Stripe 在每个事件的 `Stripe-Signature` 头内都包含了一个签名。这样可表示事件是由 Stripe 发送的,而非第三方。要验证签名,可以使用我们的官方库,也可以用您自己的方案[手动验证签名](https://docs.stripe.com/webhooks.md#verify-manually)。 首先,找出您的 Webhook 端点密钥并将它作为 `endpoint_secret` 添加到您的 Webhook 处理程序。由于您仍在用 Stripe CLI 在本地部署您的端点,因此需要用 `trigger` 命令从 CLI 获取 Webhook 端点密钥。 ```bash stripe listen ``` Webhook 端点密钥以 `whsec_` 开头,后跟一串数字和字母。妥善保管此 Webhook 端点,切勿公开。 #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') require 'stripe' require 'sinatra' # If you are testing your webhook locally with the Stripe CLI you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboardendpoint_secret = 'whsec_...' # Using the Sinatra framework set :port, 4242 post '/my/webhook/url' do payload = request.body.readsig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil beginevent = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload puts "Error parsing payload: #{e.message}" status 400 return rescue Stripe::SignatureVerificationError => e# Invalid signature puts "Error verifying webhook signature: #{e.message}" status 400 return end # Handle the event case event.type when 'payment_intent.succeeded' payment_intent = event.data.object # contains a Stripe::PaymentIntent puts 'PaymentIntent was successful!' when 'payment_method.attached' payment_method = event.data.object # contains a Stripe::PaymentMethod puts 'PaymentMethod was attached to a Customer!' # ... handle other event types else puts "Unhandled event type: #{event.type}" end status 200 end ``` ## 部署您的 Webhook 端点 准备好将 Webhook 端点部署到生产时,您需要进行以下操作: 1. 使用您的[真实模式 API 密钥](https://docs.stripe.com/keys.md#test-live-modes),不要使用测试模式的密钥。 1. 在 [Workbench](https://docs.stripe.com/workbench.md) 中或通过 API 配置 Webhook 端点。 1. 要在 Workbench 中配置端点,请转到 [Webhook 选项卡](https://dashboard.stripe.com/workbench/webhooks)。 1. 点击**添加目标**,然后输入 Stripe API 版本和您希望 Stripe 发送的特定事件。点击**继续**,然后从可用目标类型列表中选择 **Webhook 端点**。点击**继续**,然后输入端点的 URL、可选名称和可选描述。点击 **创建目标**。 1. 将应用程序中的 Webhook 端点密钥替换为 Workbench 的目标详情视图中为端点显示的新密钥。 您的应用现在可以进行真实事件了。有关配置 Webhook 端点的详细信息,请参阅 [Webhook Endpoint](https://docs.stripe.com/api/webhook_endpoints.md) API。要在沙盒中进行测试,[请参阅我们的开发指南](https://docs.stripe.com/webhooks.md)。