Unofficial API Client for Fortnox. For more details about Fortnox API, please see https://developer.fortnox.se/documentation/
Built from Unofficial OpenAPI Specification at https://github.com/rsystem-se/fortnox_openapi
The documentation for FortnoxEx can be found at https://hexdocs.pm/fortnox_ex
Please see the specification at https://github.com/rsystem-se/fortnox_openapi before opening any issues in this repository.
Not used in production. Untested to most degree. Help wanted. Rate limiting is tested. Use with caution.
To install the required dependencies and to build the elixir project, run:
mix local.hex --force
mix do deps.get, compile
If available in Hex, the package can be installed
by adding fortnox_ex
to your list of dependencies in mix.exs
:
def deps do
[{:fortnox_ex, "~> 0.4.2"}]
end
config :fortnox_ex,
client_id: "<CLIENT_ID_FROM_FORTNOX>",
client_secret: "<CLIENT_SECRET_FROM_FORTNOX>"
Please select the scopes that you would like to use, remember to also use them in the oAuth Authorization URL call. Other than that you would also need to enable authorization as a service account (Möjliggör auktorisering som servicekonto), without this you'll not get this library to work.
@fortnox_scopes ["companyinformation", "article", "payment", "invoice", "currency", "customer"]
redirect_url = "URL TO APPLICATION HERE"
FortnoxEx.Authorization.get_authorization_code_url(
redirect_url,
@fortnox_scopes,
"random-state"
)
redirect_url = "URL TO APPLICATION HERE"
FortnoxEx.Connection.get_access_token(authorization_code, redirect_url)
{:ok, "65cc2c87-de81-45d6-c792-aad68528ff17"}
defmodule MyProject.FortnoxWorker do
use GenServer
def start_link(_) do
GenServer.start_link(__MODULE__, %{})
end
@impl true
def init(state) do
# Schedule work to be performed on start
schedule_work()
{:ok, state}
end
@impl true
def handle_info(:work, state) do
# Do the desired work here
run_job()
# Reschedule once more
schedule_work()
{:noreply, state}
end
defp schedule_work do
# We schedule the work to happen in 25 minutes (written in milliseconds).
# Alternatively, one might write :timer.hours(2)
Process.send_after(self(), :work, 25 * 60 * 1000)
end
def run_job() do
fortnox_clients = MyProject.FortnoxClients.list_fortnox_clients()
Enum.map(fortnox_clients, fn client ->
case FortnoxEx.Authorization.get_refresh_token(client.refresh_token) do
{:ok, body} ->
access_token = Map.get(body, "access_token")
refresh_token = Map.get(body, "refresh_token")
client_params = %{
"access_token" => access_token,
"refresh_token" => refresh_token
}
MyProject.FortnoxClients.update_fortnox_client(client, client_params)
{:error, _} ->
# Delete it if we can't refresh it!
MyProject.FortnoxClients.delete_fortnox_client(client)
end
end)
end
end
Add this line to your children in the start method:
@impl true
def start(_type, _args) do
children = [
...
MyProject.FortnoxWorker, # 25 minutes
...
]
connection = FortnoxEx.Connection.new("1234", "567890")
customer = FortnoxEx.Api.Default.get_customer_by_customer_number(connection, "1")
IO.puts("Customer name is: #{customer."Name"}")
Note that the keys of the models are PascalCase and therefore needs to be
accessed like this: model."KeyName"
instead of just model.KeyName