Packages
mercury_client
1.0.0
A complete, production-grade Elixir client for the Mercury Banking API (accounts, transactions, recipients, invoices, payments, treasury, webhooks, and more), with typed errors, retry with backoff, and lazy auto-paginating streams.
Current section
Files
Jump to
Current section
Files
lib/mercury/payments.ex
defmodule Mercury.InternalTransferResponse do
@moduledoc "Both legs (debit and credit) of a completed internal transfer."
@type t :: %__MODULE__{
debit_transaction: Mercury.Transaction.t(),
credit_transaction: Mercury.Transaction.t()
}
defstruct [:debit_transaction, :credit_transaction]
@doc false
def from_json(map) when is_map(map) do
%__MODULE__{
debit_transaction: Mercury.Transaction.from_json(map["debitTransaction"]),
credit_transaction: Mercury.Transaction.from_json(map["creditTransaction"])
}
end
end
defmodule Mercury.SendMoneyApprovalRequest do
@moduledoc "A send-money request that requires approval before execution."
@type t :: %__MODULE__{
id: String.t(),
account_id: String.t(),
amount: float(),
status: String.t(),
recipient_id: String.t(),
payment_method: String.t(),
created_at: DateTime.t() | nil,
updated_at: DateTime.t() | nil,
note: String.t() | nil
}
defstruct [
:id,
:account_id,
:amount,
:status,
:recipient_id,
:payment_method,
:created_at,
:updated_at,
:note
]
@doc false
def from_json(map) when is_map(map) do
%__MODULE__{
id: map["id"],
account_id: map["accountId"],
amount: map["amount"],
status: map["status"],
recipient_id: map["recipientId"],
payment_method: map["paymentMethod"],
created_at: Mercury.Types.datetime(map["createdAt"]),
updated_at: Mercury.Types.datetime(map["updatedAt"]),
note: map["note"]
}
end
end
defmodule Mercury.Payments do
@moduledoc """
Mercury payment and transfer APIs: internal transfers between accounts in
the same org, and send-money requests that require approval.
"""
alias Mercury.{Client, HTTP, Page, Pagination, SendMoneyApprovalRequest, Support}
alias Mercury.InternalTransferResponse
@doc """
Transfers funds between two Mercury accounts in the same org, returning
both the debit and credit legs. `POST /transfer`
Mercury.Payments.create_internal_transfer(client, %{
from_account_id: checking_id,
to_account_id: savings_id,
amount: 1_000.0
})
"""
@spec create_internal_transfer(client :: Client.t(), attrs :: map() | keyword()) ::
{:ok, InternalTransferResponse.t()} | {:error, Exception.t()}
def create_internal_transfer(%Client{} = client, attrs) do
with {:ok, body} <- HTTP.post(client, "transfer", attrs) do
{:ok, InternalTransferResponse.from_json(body)}
end
end
@spec create_internal_transfer!(client :: Client.t(), attrs :: map() | keyword()) ::
InternalTransferResponse.t()
def create_internal_transfer!(client, attrs),
do: Support.bang!(create_internal_transfer(client, attrs))
@doc """
Creates a send-money request that requires approval before execution.
`POST /request-send-money`
"""
@spec request_send_money(client :: Client.t(), attrs :: map() | keyword()) ::
{:ok, SendMoneyApprovalRequest.t()} | {:error, Exception.t()}
def request_send_money(%Client{} = client, attrs) do
with {:ok, body} <- HTTP.post(client, "request-send-money", attrs) do
{:ok, SendMoneyApprovalRequest.from_json(body)}
end
end
@spec request_send_money!(client :: Client.t(), attrs :: map() | keyword()) ::
SendMoneyApprovalRequest.t()
def request_send_money!(client, attrs), do: Support.bang!(request_send_money(client, attrs))
@doc """
Returns a single send-money approval request by ID.
`GET /send-money-approval-requests/{id}`
"""
@spec get_approval_request(client :: Client.t(), request_id :: String.t()) ::
{:ok, SendMoneyApprovalRequest.t()} | {:error, Exception.t()}
def get_approval_request(%Client{} = client, request_id) do
with {:ok, body} <- HTTP.get(client, "send-money-approval-requests/#{request_id}") do
{:ok, SendMoneyApprovalRequest.from_json(body)}
end
end
@spec get_approval_request!(client :: Client.t(), request_id :: String.t()) ::
SendMoneyApprovalRequest.t()
def get_approval_request!(client, request_id),
do: Support.bang!(get_approval_request(client, request_id))
@doc """
Returns one page of send-money approval requests.
`GET /send-money-approval-requests`
Accepts `:account_id` and `:status` filters in addition to the common
list options.
"""
@spec list_approval_requests(client :: Client.t(), opts :: keyword()) ::
{:ok, Page.t(SendMoneyApprovalRequest.t())} | {:error, Exception.t()}
def list_approval_requests(%Client{} = client, opts \\ []) do
with {:ok, body} <- HTTP.get(client, "send-money-approval-requests", opts) do
{:ok, Page.from_json(body, "requests", &SendMoneyApprovalRequest.from_json/1)}
end
end
@spec list_approval_requests!(client :: Client.t(), opts :: keyword()) ::
Page.t(SendMoneyApprovalRequest.t())
def list_approval_requests!(client, opts \\ []),
do: Support.bang!(list_approval_requests(client, opts))
@doc "A lazy, auto-paginating stream of every send-money approval request."
@spec stream_approval_requests(client :: Client.t(), opts :: keyword()) :: Enumerable.t()
def stream_approval_requests(%Client{} = client, opts \\ []) do
opts = Keyword.new(opts)
Pagination.stream(fn cursor ->
list_approval_requests(client, Keyword.put(opts, :start_after, cursor))
end)
end
end