首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无法执行成功的Paypal web钩子验证

无法执行成功的Paypal web钩子验证
EN

Stack Overflow用户
提问于 2020-04-24 01:22:47
回答 2查看 1.7K关注 0票数 1

我正在努力验证Paypal Web钩子数据,但我遇到了一个问题,它总是返回验证状态的失败。我想知道这是否是因为这一切都发生在沙箱环境和Paypal不允许验证沙箱网络钩子事件?我遵循这个API文档来实现调用:https://developer.paypal.com/docs/api/webhooks/v1/#verify-webhook-signature

相关代码(来自单独的灵丹妙药模块):

代码语言:javascript
运行
复制
def call(conn, _opts) do
  conn
    |> extract_webhook_signature(conn.params)
    |> webhook_signature_valid?()
    |> # handle the result
end

defp extract_webhook_signature(conn, params) do
  %{
    auth_algo: get_req_header(conn, "paypal-auth-algo") |> Enum.at(0, ""),
    cert_url: get_req_header(conn, "paypal-cert-url") |> Enum.at(0, ""),
    transmission_id: get_req_header(conn, "paypal-transmission-id") |> Enum.at(0, ""),
    transmission_sig: get_req_header(conn, "paypal-transmission-sig") |> Enum.at(0, ""),
    transmission_time: get_req_header(conn, "paypal-transmission-time") |> Enum.at(0, ""),
    webhook_id: get_webhook_id(),
    webhook_event: params
  }
end

def webhook_signature_valid?(signature) do
  body = Jason.encode!(signature)
  case Request.post("/v1/notifications/verify-webhook-signature", body) do
    {:ok, %{verification_status: "SUCCESS"}} -> true
    _ -> false
  end
end

我从Paypal得到一个200,这意味着Paypal得到了我的请求,并且能够正确地解析它并通过它的验证运行它,但是它总是返回验证状态的失败,这意味着请求的真实性无法被验证。我查看了我提交给他们端点的数据,这些数据看起来都是正确的,但出于某种原因,它并不是有效的。我将我发布到API中的JSON (从extract_webhook_signature)放到一个Pastebin中,因为它非常大:https://pastebin.com/SYBT7muv

如果有人有这方面的经验,并知道为什么会失败,我很想听听。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-25 03:21:47

我自己解决了问题。Paypal不规范他们的web钩子验证请求。当您收到来自Paypal的帖子时,在您在验证调用中将其发送回他们之前,不要解析请求体。如果您的webhook_event有任何不同(即使字段的顺序不同),则该事件将被视为无效,您将收到一个失败消息。您必须读取原始的POST正文,并在您的webhook_event中将准确的数据发回给Paypal。

示例:如果您接收到{"a":1,"b":2}并回发{..., "webhook_event":{"b":2,"a":1}, ...} (注意json字段与我们收到的内容和回发的内容的顺序不同),您将收到失败。你的帖子必须是{..., "webhook_event":{"a":1,"b":2}, ...}

票数 10
EN

Stack Overflow用户

发布于 2021-03-13 09:15:07

对于那些正在努力解决这个问题的人,我想给你们我的解决方案,其中包括被接受的答案。

在开始之前,请确保将raw_body存储在您的康涅狄格中,如验证web钩子-客户端中所述

代码语言:javascript
运行
复制
  @verification_url "https://api-m.sandbox.paypal.com/v1/notifications/verify-webhook-signature"
  @auth_token_url "https://api-m.sandbox.paypal.com/v1/oauth2/token"

 defp get_auth_token do
    headers = [
      Accept: "application/json",
      "Accept-Language": "en_US"
    ]

    client_id = Application.get_env(:my_app, :paypal)[:client_id]
    client_secret = Application.get_env(:my_app, :paypal)[:client_secret]

    options = [
      hackney: [basic_auth: {client_id, client_secret}]
    ]

    body = "grant_type=client_credentials"

    case HTTPoison.post(@auth_token_url, body, headers, options) do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        %{"access_token" => access_token} = Jason.decode!(body)
        {:ok, access_token}

      error ->
        Logger.error(inspect(error))
        {:error, :no_access_token}
    end
  end

  defp verify_event(conn, auth_token, raw_body) do
    headers = [
      "Content-Type": "application/json",
      Authorization: "Bearer #{auth_token}"
    ]

    body =
      %{
        transmission_id: get_header(conn, "paypal-transmission-id"),
        transmission_time: get_header(conn, "paypal-transmission-time"),
        cert_url: get_header(conn, "paypal-cert-url"),
        auth_algo: get_header(conn, "paypal-auth-algo"),
        transmission_sig: get_header(conn, "paypal-transmission-sig"),
        webhook_id: Application.get_env(:papervault, :paypal)[:webhook_id],
        webhook_event: "raw_body"
      }
      |> Jason.encode!()
      |> String.replace("\"raw_body\"", raw_body)

    with {:ok, %{status_code: 200, body: encoded_body}} <-
           HTTPoison.post(@verification_url, body, headers),
         {:ok, %{"verification_status" => "SUCCESS"}} <- Jason.decode(encoded_body) do
      :ok
    else
      error ->
        Logger.error(inspect(error))
        {:error, :not_verified}
    end
  end

  defp get_header(conn, key) do
    conn |> get_req_header(key) |> List.first()
  end
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61399557

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档