Packages
tokenio_client
1.0.0
Production-grade Elixir client for the Token.io Open Banking platform (Payments v2, VRP, AIS, Banks, Refunds, Payouts, Settlement, Transfers, Tokens, Token Requests, Account on File, Sub-TPPs, Auth Keys, Reports, Webhooks, Verification).
Current section
Files
Jump to
Current section
Files
lib/tokenio/payments/payment.ex
defmodule TokenioClient.Payments.Payment do
@moduledoc """
A Token.io payment resource returned by the Payments v2 API.
## Status predicates
payment = TokenioClient.Payments.Payment.from_map(raw)
TokenioClient.Payments.Payment.final?(payment)
TokenioClient.Payments.Payment.requires_redirect?(payment)
TokenioClient.Payments.Payment.requires_embedded_auth?(payment)
TokenioClient.Payments.Payment.completed?(payment)
TokenioClient.Payments.Payment.failed?(payment)
"""
alias TokenioClient.Types
@terminal_statuses ~w[
INITIATION_COMPLETED
INITIATION_REJECTED
INITIATION_REJECTED_INSUFFICIENT_FUNDS
INITIATION_FAILED
INITIATION_DECLINED
INITIATION_EXPIRED
INITIATION_NO_FINAL_STATUS_AVAILABLE
SETTLEMENT_COMPLETED
SETTLEMENT_INCOMPLETE
CANCELED
]
@redirect_statuses ~w[
INITIATION_PENDING_REDIRECT_AUTH
INITIATION_PENDING_REDIRECT_AUTH_VERIFICATION
INITIATION_PENDING_REDIRECT_HP
INITIATION_PENDING_REDIRECT_PBL
]
@embedded_statuses ~w[
INITIATION_PENDING_EMBEDDED_AUTH
INITIATION_PENDING_EMBEDDED_AUTH_VERIFICATION
]
@type t :: %__MODULE__{
id: String.t(),
member_id: String.t() | nil,
status: String.t(),
status_reason_information: String.t() | nil,
bank_payment_id: String.t() | nil,
bank_transaction_id: String.t() | nil,
redirect_url: String.t() | nil,
embedded_auth_fields: [Types.EmbeddedField.t()],
refund_details: Types.RefundDetails.t() | nil,
error_info: Types.ErrorInfo.t() | nil,
created_at: DateTime.t() | nil,
updated_at: DateTime.t() | nil,
raw: map()
}
defstruct [
:id,
:member_id,
:status,
:status_reason_information,
:bank_payment_id,
:bank_transaction_id,
:redirect_url,
:refund_details,
:error_info,
:created_at,
:updated_at,
embedded_auth_fields: [],
raw: %{}
]
@doc "Build a `Payment` from a raw API response map."
@spec from_map(map() | nil) :: t() | nil
def from_map(nil), do: nil
def from_map(m) when is_map(m) do
auth = m["authentication"] || %{}
%__MODULE__{
id: m["id"],
member_id: m["memberId"],
status: m["status"] || "",
status_reason_information: m["statusReasonInformation"],
bank_payment_id: m["bankPaymentId"],
bank_transaction_id: m["bankTransactionId"],
redirect_url: auth["redirectUrl"],
embedded_auth_fields: Enum.map(auth["embeddedAuth"] || [], &Types.EmbeddedField.from_map/1),
refund_details: Types.RefundDetails.from_map(m["refundDetails"]),
error_info: Types.ErrorInfo.from_map(m["errorInfo"]),
created_at: Types.parse_datetime(m["createdDateTime"]),
updated_at: Types.parse_datetime(m["updatedDateTime"]),
raw: m
}
end
@doc "Returns `true` when the payment has reached a terminal state."
@spec final?(t()) :: boolean()
def final?(%__MODULE__{status: s}), do: s in @terminal_statuses
@doc "Returns `true` when the PSU must be redirected to complete authentication."
@spec requires_redirect?(t()) :: boolean()
def requires_redirect?(%__MODULE__{status: s}), do: s in @redirect_statuses
@doc "Returns `true` when embedded auth fields must be collected and submitted."
@spec requires_embedded_auth?(t()) :: boolean()
def requires_embedded_auth?(%__MODULE__{status: s}), do: s in @embedded_statuses
@doc "Returns `true` when the bank is performing decoupled (push-notification) authentication."
@spec decoupled_auth?(t()) :: boolean()
def decoupled_auth?(%__MODULE__{status: "INITIATION_PENDING_DECOUPLED_AUTH"}), do: true
def decoupled_auth?(%__MODULE__{}), do: false
@doc "Returns `true` when the payment completed successfully."
@spec completed?(t()) :: boolean()
def completed?(%__MODULE__{status: "INITIATION_COMPLETED"}), do: true
def completed?(%__MODULE__{status: "SETTLEMENT_COMPLETED"}), do: true
def completed?(%__MODULE__{}), do: false
@doc "Returns `true` when the payment failed for any reason."
@spec failed?(t()) :: boolean()
def failed?(%__MODULE__{status: s})
when s in ~w[
INITIATION_FAILED
INITIATION_REJECTED
INITIATION_REJECTED_INSUFFICIENT_FUNDS
INITIATION_DECLINED
INITIATION_EXPIRED
],
do: true
def failed?(%__MODULE__{}), do: false
end