mirror of
https://github.com/plausible/analytics.git
synced 2024-12-19 15:41:56 +03:00
75 lines
2.4 KiB
Elixir
75 lines
2.4 KiB
Elixir
|
defmodule PlausibleWeb.Api.PaddleController do
|
||
|
use PlausibleWeb, :controller
|
||
|
use Plausible.Repo
|
||
|
require Logger
|
||
|
|
||
|
plug :verify_signature
|
||
|
|
||
|
def webhook(conn, %{"alert_name" => "subscription_created"} = params) do
|
||
|
Plausible.Billing.subscription_created(params)
|
||
|
|> webhook_response(conn, params)
|
||
|
end
|
||
|
|
||
|
def webhook(conn, %{"alert_name" => "subscription_updated"} = params) do
|
||
|
Plausible.Billing.subscription_updated(params)
|
||
|
|> webhook_response(conn, params)
|
||
|
end
|
||
|
|
||
|
def webhook(conn, %{"alert_name" => "subscription_cancelled"} = params) do
|
||
|
Plausible.Billing.subscription_cancelled(params)
|
||
|
|> webhook_response(conn, params)
|
||
|
end
|
||
|
|
||
|
def webhook(conn, %{"alert_name" => "subscription_payment_succeeded"} = params) do
|
||
|
Plausible.Billing.subscription_payment_succeeded(params)
|
||
|
|> webhook_response(conn, params)
|
||
|
end
|
||
|
|
||
|
def webhook(conn, _params) do
|
||
|
send_resp(conn, 404, "") |> halt
|
||
|
end
|
||
|
|
||
|
@paddle_key File.read!("priv/paddle.pem")
|
||
|
|
||
|
def verify_signature(conn, _opts) do
|
||
|
signature = Base.decode64!(conn.params["p_signature"])
|
||
|
msg = Map.delete(conn.params, "p_signature")
|
||
|
|> Enum.map(fn {key, val} -> {key, "#{val}"} end)
|
||
|
|> List.keysort(0)
|
||
|
|> PhpSerializer.serialize()
|
||
|
|
||
|
[key_entry] = :public_key.pem_decode(@paddle_key)
|
||
|
public_key = :public_key.pem_entry_decode(key_entry)
|
||
|
|
||
|
if :public_key.verify(msg, :sha, signature, public_key) do
|
||
|
conn
|
||
|
else
|
||
|
send_resp(conn, 400, "") |> halt
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def verified_signature?(params) do
|
||
|
signature = Base.decode64!(params["p_signature"])
|
||
|
msg = Map.delete(params, "p_signature")
|
||
|
|> Enum.map(fn {key, val} -> {key, "#{val}"} end)
|
||
|
|> List.keysort(0)
|
||
|
|> PhpSerializer.serialize()
|
||
|
|
||
|
[key_entry] = :public_key.pem_decode(@paddle_key)
|
||
|
public_key = :public_key.pem_entry_decode(key_entry)
|
||
|
:public_key.verify(msg, :sha, signature, public_key)
|
||
|
end
|
||
|
|
||
|
defp webhook_response({:ok, _}, conn, _params) do
|
||
|
json(conn, "")
|
||
|
end
|
||
|
|
||
|
defp webhook_response({:error, changeset}, conn, params) do
|
||
|
request = Sentry.Plug.build_request_interface_data(conn, [])
|
||
|
Sentry.capture_message("Error processing Paddle webhook", extra: %{errors: inspect(changeset.errors), params: params, request: request})
|
||
|
Logger.error("Error processing Paddle webhook: #{inspect(changeset)}")
|
||
|
|
||
|
conn |> send_resp(400, "") |> halt
|
||
|
end
|
||
|
end
|