所有文章
PayPal 沙盒付款事件通过安全的 HTTPS 隧道传送到开发者笔记本电脑上运行的 Webhook 监听器。
PayPalsandboxwebhookslocal testing

在 localhost 测试 PayPal 沙盒 Webhook

要在本地主机上测试 PayPal 沙箱 Webhooks,请在本地运行侦听器,通过公共 HTTPS 隧道公开其路由,在沙箱应用程序上注册该 URL,并在 PayPal 的 Webhooks 模拟器中触发真实的沙箱交易或模拟事件。 保持签名验证启用:模拟器事件和应用程序关联的沙箱事件有一个重要的验证差异解释下面.

为什么PayPal无法直接发送到本地主机

PayPal 从其自己的服务器传送 webhook 通知。从 PayPal 的角度来看,诸如 http://localhost:3000/api/paypal 这样的地址指向 PayPal 的机器,而不是您的机器。 localhost 隧道 为本地进程提供公共 HTTPS 地址,同时将应用程序保留在您的计算机上。

官方PayPal Webhooks模拟器文档表示其侦听器必须可通过端口443上的HTTPS访问。隧道处理该公共TLS端点并将请求转发到任何本地端口,例如3000或8080.

选择正确的PayPal测试路径

用于监听器开发的模拟模拟器事件

模拟器可以发送代表性事件,包括付款捕获、退款和计费事件,而无需创建交易。这是确认路由、JSON 解析、响应代码和事件调度的最快方法。模拟事件不绑定到 REST 应用程序,不会出现在应用程序的 Webhook 事件查看器中,无法重新发送,并且不代表真实交易。

端到端行为的真实沙箱事件

为了实现实际集成,请在 PayPal 开发人员仪表板中创建 REST 应用程序,将隧道端点添加为 Webhook,选择所需的事件类型,并完成沙箱结帐或 API 操作。这些事件属于沙盒应用程序,并使用您在生产之前使用的相同应用程序凭据、Webhook ID、事件查看器和重新发送工作流程。

在本地主机上设置 PayPal webhook

  1. 启动您的应用程序并确认路由在本地有效:curl -i -X POST http://localhost:3000/api/webhooks/paypal -H 'content-type: application/json' -d '{"event_type":"LOCAL.PING"}'.
  2. 运行npx portpreview 3000并复制生成的HTTPS URL.
  3. 构建完整回调,例如https://your-subdomain.portpreview.dev/api/webhooks/paypal.
  4. 对于模拟测试,请将其粘贴到 Webhooks 模拟器中并选择一个事件。对于应用程序测试,请将其添加到沙盒 REST 应用程序的 Webhook 设置下。
  5. 发送事件并检查传入方法、PayPal 标头、原始正文、处理程序日志和 HTTP 响应。

仅订阅您的应用程序处理的事件。广泛的订阅会产生噪音,并且更容易意外地为您从未建模的事件运行业务逻辑。

A practical Express listener

import express from 'express';

const app = express();
app.use(express.json({ verify: (req, _res, buf) => {
  req.rawBody = Buffer.from(buf);
}}));

app.post('/api/webhooks/paypal', async (req, res) => {
  const event = req.body;

  // Verify first; do not fulfill an order from untrusted JSON.
  const verified = await verifyPayPal(req.headers, event);
  if (!verified) return res.status(401).send('invalid signature');

  // Claim the event ID atomically so retries cannot duplicate work.
  const firstDelivery = await claimEvent(event.id);
  if (!firstDelivery) return res.sendStatus(200);

  if (event.event_type === 'PAYMENT.CAPTURE.COMPLETED') {
    await markOrderPaid(event.resource.id);
  }

  return res.sendStatus(200);
});

app.listen(3000);

保持确认工作简短。存储事件,返回 2xx 响应,并在队列中执行缓慢的电子邮件或履行工作。事件ID是天然的幂等键;强制执行唯一的数据库约束,而不是依赖于内存中的集合。

正确验证PayPal签名

PayPal 在标头中发送传输元数据,包括 PAYPAL-AUTH-ALGOPAYPAL-CERT-URLPAYPAL-TRANSMISSION-IDPAYPAL-TRANSMISSION-SIGPAYPAL-TRANSMISSION-TIME。对于与应用程序关联的事件,您可以将这些值、Webhook ID 和事件提交到沙箱 /v1/notifications/verify-webhook-signature API。成功的 HTTP 响应是不够的;要求 verification_status 等于 SUCCESS。 PayPal 还在其 webhook 集成指南.

中记录了本地加密验证

模拟器警告: PayPal的回发验证端点不支持模拟模拟器事件。 PayPal 记录了文字 Webhook ID WEBHOOK_ID,用于自我验证模拟器签名。不要将该特殊值与分配给沙箱应用程序的真实 Webhook ID 混淆。如果您的直接目标是测试回发 API 本身,请生成实际的沙箱事务而不是模拟模拟器事件。

在下载之前验证任何证书 URL 是否遵循 PayPal 记录的规则,保留验证方法所需的确切事件表示,并且绝不记录访问令牌、客户端机密、签名或完整的支付负载。

测试换钱或访问的事件

  • PAYMENT.CAPTURE.COMPLETED:仅在检查预期订单标识符、金额、货币和捕获状态后才授予履行。
  • PAYMENT.CAPTURE.REFUNDED:安全地撤销权利并支持部分退款。
  • 结帐订单事件:区分批准和已完成的捕获;仅获得批准并不能证明资金已被捕获。
  • 订阅事件:针对您的计费状态机测试激活、暂停、取消、付款失败和无序交付。

Provider 事件是通知,而不是毫无疑问的数据库命令。对于敏感转换,请使用经过身份验证的 API 凭据检索引用的 PayPal 资源,并将其与您自己的订单记录进行比较。

本地交付失败故障排除

模拟器无法连接

确认 URL 以 https:// 开头,包含确切的 Webhook 路径,并且仍然指向正在运行的隧道。使用 curl 自行测试公共 URL。 404通常表示路径或框架路由错误; 502通常意味着隧道无法到达本地进程。

处理程序返回401

首先判断该事件是来自模拟器还是来自注册的沙箱应用。相应地检查 webhook ID 和验证方法。然后验证代理是否保留了所有 PAYPAL-* 标头,并且您没有将实时凭证与 api-m.sandbox.paypal.com.

混合

PayPal 重试或标记发送失败

仅在事件被持久接受后才返回 2xx。避免路由上的重定向、HTML 错误页面、身份验证中间件和长时间同步作业。使用事件查看器查看真实的应用程序事件,使用模拟器结果进行模拟交付诊断。请参阅重试和幂等性指南了解持久处理模式。

上线前安全检查表

  • 使用单独的沙箱和实时客户端凭据、Webhook ID 和端点机密。
  • 在解析业务字段或更改状态之前验证每个签名。
  • 通过 PayPal 事件 ID 进行重复数据删除并使履行交易原子化。
  • 仅允许POST,限制请求大小,应用速率限制,并尽可能保持隧道 URL 的私密性。
  • 从日志中编辑买家数据和凭证;旋转调试期间暴露的任何内容。
  • 用稳定的生产端点替换临时隧道 URL,并重复签名和重试测试。

有关完整的事件和验证架构,请使用 PayPal 的主要Webhooks API 参考。有关原始主体和安全比较的独立于框架的详细信息,请阅读 webhook 签名验证指南.

常见问题

PayPal Webhooks 模拟器可以发送到本地主机吗?
不直接。使用公共 HTTPS 隧道公开本地 Webhook 路由,然后在模拟器中输入该 HTTPS URL。 PayPal 需要一个可以通过互联网访问的侦听器。
为什么模拟器活动的 PayPal 签名验证失败?
模拟模拟器事件无法发布到 PayPal 的 verify-webhook-signature 端点。 PayPal 文档 WEBHOOK_ID 用于自验证模拟器签名;使用真实的沙箱应用程序事件来测试回发验证。
PayPal 沙箱和模拟器 webhook 有什么区别?
模拟器 Webhooks 是模拟的、独立于应用程序的负载,用于侦听器测试。沙箱应用程序 Webhook 来自沙箱活动,使用应用程序的真实 Webhook ID,出现在其事件工具中,并支持正常的验证工作流程。
PayPal webhook 应返回哪种 HTTP 状态?
事件经过验证并持久接受后,返回 2xx 响应。拒绝无效签名,并将缓慢的履行或通知工作移至队列,以便交付不会超时。