• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

PayPal支付回调:PayPal Webhook

Webhook 是发生某事时发生的 HTTP回调;一个通过 HTTP post 的简单事件通知系统,允许开发人员轻松访问支付活动的通知,例如支付状态更新或重复收费。处理完每个通知后,您可以在后端执行操作,例如:

  • 通过电子邮件将购买确认信息发送给您的客户。

  • 启用数字媒体的下载。

  • 发出退款。

  • 跟踪哪些订阅处于活动状态。

要创建 Webhook,请导航到 PayPal Dashboard,然后单击My Apps & Credentials。然后选择要在其中设置 Webhook 的应用程序

PayPal支付回调:PayPal Webhook  第1张您可以查看有关您的应用程序的详细信息。注意右上角有两个按钮(Sandbox、Live),在本教程中我将使用Sandbox  ,但您需要在开始 Live 之前设置 Live 设置。要为此应用程序配置 Webhook,请单击屏幕截图中显示的添加 Webhook:

PayPal支付回调:PayPal Webhook  第2张
选择您希望收到通知的事件类型,然后输入Webhook将被发送到的 URL(它必须是 HTTPS)。为了处理 Webhook 调用,我将向 HomeController 添加一个名为“Webhook”的新操作方法:

public IActionResult Webhook()
{
    // TODO: Handle Webhook call
}

所以这种情况下的 Webhook Url 将是:https://pedroalonso.localtunnel.me/home/webhook。我将在下一节解释“localtunnel”部分。

PayPal支付回调:PayPal Webhook  第3张
保存 Webhook 后,您将看到以下确认屏幕:

PayPal支付回调:PayPal Webhook  第4张现在 Webhook 已设置好,您可以在左侧菜单中的“Webhooks Simulator”下看到,在这里您可以将“test”webhook 事件发送到您的 URL 以测试您的代码是否正常工作。此外,在“Webhooks 事件”下,您可以看到 PayPal 为该应用程序发送的所有事件。如果要进行进一步测试,您可以验证您是否正确处理了事件并重新发送它们。

为了了解 Webhook 是如何工作的,我运行了我们在上一个教程中构建的项目,并创建了一个“授权付款并稍后捕获”,以便 PayPal 发送事件。运行示例后,我点击了“Webhooks event”,可以看到该事件已发送:

PayPal支付回调:PayPal Webhook  第5张
如您所见,如果您想调试代码并查看如何正确实现处理程序,则在右侧有一个Resend按钮。此外,如果您单击该事件,您可以看到所有详细信息:

PayPal支付回调:PayPal Webhook  第6张这是 Webhook 事件的完整 JSON:

{
    "id": "WH-9U51749144910293K-8LX80763BC1567402",
    "create_time": "2016-01-19T17:50:30Z",
    "resource_type": "sale",
    "event_type": "PAYMENT.SALE.COMPLETED",
    "summary": "Payment completed for $ 100.0 USD",
    "resource": {
        "amount": {
            "total": "100.00",
            "currency": "USD",
            "details": {
                "subtotal": "100.00",
                "tax": "15.00",
                "shipping": "10.00"
            }
        },
        "id": "73G8209522783053E",
        "parent_payment": "PAY-7MB27930V5981832YK2PHN7Q",
        "update_time": "2016-01-19T17:49:05Z",
        "create_time": "2016-01-19T17:49:05Z",
        "payment_mode": "INSTANT_TRANSFER",
        "state": "completed",
        "links": [
            {
                "href": "https://api.sandbox.paypal.com/v1/payments/sale/73G8209522783053E",
                "rel": "self",
                "method": "GET"
            },
            {
                "href": "https://api.sandbox.paypal.com/v1/payments/sale/73G8209522783053E/refund",
                "rel": "refund",
                "method": "POST"
            },
            {
                "href": "https://api.sandbox.paypal.com/v1/payments/payment/PAY-7MB27930V5981832YK2PHN7Q",
                "rel": "parent_payment",
                "method": "GET"
            }
        ],
        "protection_eligibility_type": "ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE",
        "transaction_fee": {
            "value": "3.20",
            "currency": "USD"
        },
        "protection_eligibility": "ELIGIBLE"
    },
    "status": "PENDING",
    "transmissions": [
        {
            "webhook_url": "https://pedroalonso.localtunnel.me/home/webhook",
            "response_headers": {
                "Date": "Wed, 20 Jan 2016 12:53:51 GMT",
                "Content-Length": "53",
                "HTTP/1.1 502 Bad Gateway": "",
                "SERVER_INFO": "",
                "Connection": "keep-alive",
                "Server": "nginx/1.7.8"
            },
            "transmission_id": "218dc9c0-bed5-11e5-927f-6b62a8a99ac4",
            "status": "PENDING",
            "timestamp": "2016-01-19T17:50:30Z"
        }
    ],
    "links": [
        {
            "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9U51749144910293K-8LX80763BC1567402",
            "rel": "self",
            "method": "GET",
            "encType": "application/json"
        },
        {
            "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9U51749144910293K-8LX80763BC1567402/resend",
            "rel": "resend",
            "method": "POST",
            "encType": "application/json"
        }
    ]
}

正如您在图片中看到的,事件详细信息以 JSON 编码,并作为请求正文发送到您的 Webhook URL 处理程序。此外,我们需要在处理程序中使用几个重要的属性:

  • id :这是 webhook 事件的 id,如果我们要检索特定的 webhook 事件,我们需要将此参数发送到PayPal。

  • event_type:这用于了解我们正在接收的事件类型,因为我们可能需要以不同的方式处理不同的事件类型。

  • resource.parent_payment:这是与此事件相关的付款的 ID。我们可能将此 id 存储在数据库中,并且可以向我们的客户发送电子邮件或运送客户购买的商品。

根据前面的解释,这是动作控制器处理 Webhook 的代码:

public IActionResult Webhook()
{
    // The APIContext object can contain an optional override for the trusted certificate.
    var apiContext = PayPalConfiguration.GetAPIContext();
 
    // Get the received request's headers
    var requestheaders = HttpContext.Request.Headers;
 
    // Get the received request's body
    var requestBody = string.Empty;
    using (var reader = new System.IO.StreamReader(HttpContext.Request.Body))
    {
        requestBody = reader.ReadToEnd();
    }
 
    dynamic jsonBody = JObject.Parse(requestBody);
    string webhookId = jsonBody.id;
    var ev = WebhookEvent.Get(apiContext, webhookId);
     
    // We have all the information the SDK needs, so perform the validation.
    // Note: at least on Sandbox environment this returns false.
    // var isValid = WebhookEvent.ValidateReceivedEvent(apiContext, ToNameValueCollection(requestheaders), requestBody, webhookId);
     
    switch (ev.event_type)
    {
        case "PAYMENT.CAPTURE.COMPLETED":
            // Handle payment completed
            break;
        case "PAYMENT.CAPTURE.DENIED":
            // Handle payment denied
            break;
            // Handle other webhooks
        default:
            break;
    }
 
    return new HttpStatusCodeResult(200);
}

有几件事要从前面的函数中解释。从第 10-16 行开始,我只读取请求的正文并将 JSON 对象解析为动态 C# 对象。在第 18 行(可选)上,我使用事件 ID 调用 PayPal API 以获取完整的事件详细信息。这样做是为了安全,以验证我使用的是有效的 PayPal 对象。在第 24 行,我创建了一个开关来评估我想要处理的 Webhook 的类型,并根据需要编写自定义代码。 

您还可以看到,第 22 行被注释掉了。显然,该方法验证请求中的 SSL 证书有效并且属于 PayPal,但它在沙盒模式下不起作用。它可能在 Live 中工作,但我不喜欢在 Live 中有未经测试的代码,特别是如果它正在处理支付网关,所以我选择删除它并使用不同的方法。如果您使用 PayPal SDK 库的php版本,请记住函数 'ValidateReceivedEvent' 甚至不存在。

测试 Webhook:安全隧道

如您之前所见,为了测试 Webhook,我们需要配置一个公共 URL,PayPal 可以使用该 URL 来发送事件。如果我们在本地工作,通常我们使用'localhost'进行开发,所以这将是一个小问题。为了解决这个问题,我们需要为我们的本地计算机配置一个安全隧道。 

Localtunnel是一个小软件,可以在您的本地机器和可公开访问的域之间创建安全隧道。它对于测试 Webhook 很有用,但您也可以使用它来将实时 URL 共享到在您的开发机器上运行的 Web 应用程序,以用于测试、反馈或其他任务。

你需要有node.js 才能安装 localtunnel。然后只需打开控制台或终端,然后运行:

$ npm install -g localtunnel

要创建隧道,请运行:

$ lt --port 5000 --subdomain pedroalonso

这会将 URL ' https://pedroalonso.localtunnel.me ' 映射到 'localhost:5000'。如果您在 IIS Express 上运行项目,您可能会使用不同的端口,因此您需要在命令中反映这一点。

在设置 localtunnel 并且我们的项目正在运行后,我在 Visual Studio 中添加了一个断点来评估我得到的数据。如您在此屏幕截图中所见,我已将 JSON 事件对象映射到 C# 动态对象。

PayPal支付回调:PayPal Webhook  第7张使用事件 ID 从 PayPal API 检索事件,我们还可以获取事件详细信息,如您在此处看到的:

PayPal支付回调:PayPal Webhook  第8张

结论

Webhook 正在成为 rest API 通知应用程序有关事件的标准方式。如您所见,它们非常容易处理,并且被许多公司使用,例如 Stripe、SendGrid、mailchimp等。PayPal 曾经有即时付款通知,现在仍在使用,但他们建议尽可能实施 Webhook .  


文章目录
  • 测试 Webhook:安全隧道
  • 结论