This commit is contained in:
Pierre de Lacroix 2026-01-22 16:29:25 +01:00
parent 617c2ab725
commit c451662178
Signed by: lateralus23
GPG key ID: 53E0CEC29C24EF39
17 changed files with 602 additions and 2 deletions

View file

@ -14,7 +14,8 @@ defmodule CampApi.Application do
# Start a worker by calling: CampApi.Worker.start_link(arg)
# {CampApi.Worker, arg},
# Start to serve requests, typically the last entry
CampApiWeb.Endpoint
CampApiWeb.Endpoint,
CampApi.PaymentLinks.Qonto
]
# See https://hexdocs.pm/elixir/Supervisor.html

View file

@ -0,0 +1,110 @@
defmodule CampApi.PaymentLinks do
@moduledoc """
The PaymentLinks context.
"""
# import Ecto.Query, warn: false
alias CampApi.Repo
alias CampApi.PaymentLinks.Link
alias CampApi.PaymentLinks.Qonto
def connect() do
body = %{
"partner_callback_url" => "http://localhost:4000",
"user_bank_account_id" => "01982d1e-6813-7bdf-a96f-0c583e6fa063",
"user_phone_number" => "+33612345678",
"user_website_url" => "http://localhost:4000",
"business_description" => "This needs a long long long description. This needs a long long long description."
}
Qonto.request(:post, "/v2/payment_links/connections", body)
end
@doc """
Returns the list of links.
## Examples
iex> list_links()
[%Link{}, ...]
"""
def list_links do
raise "TODO"
end
@doc """
Gets a single link.
Raises if the Link does not exist.
## Examples
iex> get_link!(123)
%Link{}
"""
def get_link!(id), do: raise "TODO"
@doc """
Creates a link.
## Examples
iex> create_link(%{field: value})
{:ok, %Link{}}
iex> create_link(%{field: bad_value})
{:error, ...}
"""
def create_link(attrs) do
raise "TODO"
end
@doc """
Updates a link.
## Examples
iex> update_link(link, %{field: new_value})
{:ok, %Link{}}
iex> update_link(link, %{field: bad_value})
{:error, ...}
"""
def update_link(%Link{} = link, attrs) do
raise "TODO"
end
@doc """
Deletes a Link.
## Examples
iex> delete_link(link)
{:ok, %Link{}}
iex> delete_link(link)
{:error, ...}
"""
def delete_link(%Link{} = link) do
raise "TODO"
end
@doc """
Returns a data structure for tracking link changes.
## Examples
iex> change_link(link)
%Todo{...}
"""
def change_link(%Link{} = link, _attrs \\ %{}) do
raise "TODO"
end
end

View file

@ -0,0 +1,3 @@
defmodule CampApi.PaymentLinks.Link do
defstruct name: "John", age: 27
end

View file

@ -0,0 +1,151 @@
defmodule CampApi.PaymentLinks.Qonto do
use GenServer
use CampApiWeb, :verified_routes
def base_url() do
if Application.get_env(CampApi, :qonto, :staging) do
"https://thirdparty-sandbox.staging.qonto.co"
else
""
end
end
def oauth_url() do
if Application.get_env(CampApi, :qonto, :staging) do
"https://oauth-sandbox.staging.qonto.co"
else
"https://oauth.qonto.com"
end
end
def client_id() do
if Application.get_env(CampApi, :qonto, :staging) do
"d78920aa-e35f-4bfd-97df-e457f8337e2d"
else
""
end
end
def client_secret() do
if Application.get_env(CampApi, :qonto, :staging) do
"EqrS29dZYPy1Nfg8V8Bt6aRR1u"
else
""
end
end
def start_link(_) do
GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
end
def request(method, url, body) do
GenServer.call(__MODULE__, {:request, method, url, body})
end
def init(%{}) do
oauth_client =
OAuth2.Client.new(
strategy: OAuth2.Strategy.AuthCode,
client_id: client_id(),
client_secret: client_secret(),
site: oauth_url(),
redirect_uri: url(~p"/api/qonto_auth"),
authorize_url: "/oauth2/auth",
token_url: "/oauth2/token"
)
|> OAuth2.Client.put_serializer("application/json;charset=UTF-8", Jason)
|> OAuth2.Client.put_serializer("application/json", Jason)
{:ok, %{status: :disconnected, auth_state: nil, oauth_client: oauth_client}, {:continue, nil}}
end
def handle_continue(_, state) do
auth_state = :crypto.strong_rand_bytes(24) |> Base.url_encode64(padding: false)
# auth_url = %URI{
# # scheme: "https",
# # host: oauth_url(),
# URI.parse(oauth_url()) |
# path: "/oauth2/auth",
# query:
# URI.encode_query(%{
# client_id: client_id(),
# redirect_uri: url(~p"/api/qonto_auth"),
# scope: "payment_link.write payment_link.read",
# response_type: "code",
# state: auth_state
# # organization_id: TODO
# })
# }
auth_url = OAuth2.Client.authorize_url!(state.oauth_client, state: auth_state, scope: "payment_link.write payment_link.read")
IO.puts("Plz go to the following URL:")
IO.puts(auth_url)
{:noreply, %{state | status: :pending, auth_state: auth_state}}
end
def create_token(code, auth_state) do
GenServer.call(__MODULE__, {:create_token, code, auth_state})
end
def handle_call({:create_token, code, auth_state}, _from, state) do
# with state.status == :pending && state.auth_state == auth_state,
# {:ok, %{body: %{"json" => %{"access_token" => access_token, "refresh_token" => refresh_token}}}} <- Req.post(base_url: oauth_url(), url: "/outh2/token",
# {:reply, :ok, %{state | status: :connected,
#
headers =
if Application.get_env(CampApi, :qonto, :staging) do
[
{"x-qonto-staging-token", "0CxYRit4ZV7uwjoUluN93XgQvOt7bke96Nn0x5MUg2w="},
{"authorization", ""}
]
else
[]
end
with state.status == :pending && state.auth_state == auth_state,
{:ok, oauth_client} <- OAuth2.Client.get_token(state.oauth_client, [code: code, client_secret: state.oauth_client.client_secret], headers) do
{:reply, :ok, %{state | status: :connected, oauth_client: oauth_client}}
else
_ ->
{:reply, :error, state}
end
end
# def handle_call({:request, method, url, body}, _from, state) do
# access_token =
# headers =
# if Application.get_env(CampApi, :qonto, :staging) do
# [
# authorization: "Bearer #{state.access_token}",
# x_qonto_staging_token: "0CxYRit4ZV7uwjoUluN93XgQvOt7bke96Nn0x5MUg2w="
# ]
# else
# []
# end
#
# Req.request(method: method, base_url: base_url(), url: url, headers: headers, json: body)
# end
def handle_call({:request, method, url, body}, _from, state) do
url = base_url() <> url
headers =
if Application.get_env(CampApi, :qonto, :staging) do
[
# x_qonto_staging_token: "0CxYRit4ZV7uwjoUluN93XgQvOt7bke96Nn0x5MUg2w="
{"x-qonto-staging-token", "0CxYRit4ZV7uwjoUluN93XgQvOt7bke96Nn0x5MUg2w="}
]
else
[]
end
case OAuth2.Request.request(method, state.oauth_client, url, Jason.encode!(body), headers, []) do
{:ok, resp} -> {:reply, {:ok, resp}, state}
_ -> {:reply, :error, state}
end
end
end