defmodule Plaid.PaymentInitiation do @moduledoc """ [Plaid Payment Initiation API](https://plaid.com/docs/api/products/#payment-initiation-uk-and-europe) calls and schema. """ alias Plaid.Castable alias Plaid.PaymentInitiation.{ Address, Amount, BACS, Payment, Recipient, Schedule } defmodule CreateRecipientResponse do @moduledoc """ [Plaid API /payment_initiation/recipient/create response schema.](https://plaid.com/docs/api/products/#payment_initiationrecipientcreate) """ @behaviour Castable @type t :: %__MODULE__{ recipient_id: String.t(), request_id: String.t() } defstruct [ :recipient_id, :request_id ] @impl true def cast(generic_map) do %__MODULE__{ recipient_id: generic_map["recipient_id"], request_id: generic_map["request_id"] } end end @doc """ Create a recipient for payment initiation. Does a `POST /payment_initiation/recipient/create` call which creates a payment recipient for payment initiation. The endpoint is idempotent: if a request has already been made with the same payment details, Plaid will return the same `recipient_id`. ## Params * `name` - The name of the recipient. ## Options * `:iban` - The International Bank Account Number (IBAN) for the recipient. * `:bacs` - The sort code of the account. * `:address` - The address of the payment recipient. If `:bacs` data is not provided, `:iban` becomes required. ## Examples PaymentInitiation.create_recipient("Wonder Wallet", client_id: "123", secret: "abc") {:ok, %PaymentInitiation.CreateRecipientResponse{}} """ @spec create_recipient(name :: String.t(), options, Plaid.config()) :: {:ok, CreateRecipientResponse.t()} | {:error, Plaid.Error.t()} when options: %{ optional(:iban) => String.t(), optional(:bacs) => BACS.t(), optional(:address) => Address.t() } def create_recipient(name, options \\ %{}, config) do options_payload = Map.take(options, [:iban, :bacs, :address]) payload = %{} |> Map.put(:name, name) |> Map.merge(options_payload) Plaid.Client.call( "/payment_initiation/recipient/create", payload, CreateRecipientResponse, config ) end defmodule GetRecipientResponse do @moduledoc """ [Plaid API /payment_initiation/recipient/get response schema.](https://plaid.com/docs/api/products/#payment_initiationrecipientget) """ @behaviour Castable @type t :: %__MODULE__{ recipient_id: String.t(), name: String.t(), address: Address.t() | nil, iban: String.t() | nil, bacs: BACS.t() | nil, request_id: String.t() } defstruct [ :recipient_id, :name, :address, :iban, :bacs, :request_id ] @impl true def cast(generic_map) do %__MODULE__{ recipient_id: generic_map["recipient_id"], name: generic_map["name"], address: Castable.cast(Address, generic_map["address"]), iban: generic_map["iban"], bacs: Castable.cast(BACS, generic_map["bacs"]), request_id: generic_map["request_id"] } end end @doc """ Get a recipient for payment initiation. Does a `POST /payment_initiation/recipient/get` call to get details about a payment recipient. ## Params * `recipient_id` - The ID of the recipient. ## Examples PaymentInitiation.get_recipient("recipient-id-sandbox-123xxx", client_id: "123", secret: "abc") {:ok, %PaymentInitiation.GetRecipientResponse{}} """ @spec get_recipient(recipient_id :: String.t(), Plaid.config()) :: {:ok, CreateRecipientResponse.t()} | {:error, Plaid.Error.t()} def get_recipient(recipient_id, config) do Plaid.Client.call( "/payment_initiation/recipient/get", %{recipient_id: recipient_id}, GetRecipientResponse, config ) end defmodule ListRecipientsResponse do @moduledoc """ [Plaid API /payment_initiation/recipient/list response schema.](https://plaid.com/docs/api/products/#payment_initiationrecipientlist) """ @behaviour Castable @type t :: %__MODULE__{ recipients: [Recipient.t()], request_id: String.t() } defstruct [ :recipients, :request_id ] @impl true def cast(generic_map) do %__MODULE__{ recipients: Castable.cast_list(Recipient, generic_map["recipients"]), request_id: generic_map["request_id"] } end end @doc """ List the payment recipients that you have previously created. Does a `POST /payment_initiation/recipient/list` call to list all recipients you have previously created. ## Examples PaymentInitiation.list_recipients(client_id: "123", secret: "abc") {:ok, %PaymentInitiation.ListRecipientsResponse{}} """ @spec list_recipients(Plaid.config()) :: {:ok, ListRecipientsResponse.t()} | {:error, Plaid.Error.t()} def list_recipients(config) do Plaid.Client.call( "/payment_initiation/recipient/list", ListRecipientsResponse, config ) end defmodule CreatePaymentResponse do @moduledoc """ [Plaid API /payment_initiation/payment/create response schema.](https://plaid.com/docs/api/products/#payment_initiationpaymentcreate) """ @behaviour Castable @type t :: %__MODULE__{ payment_id: String.t(), status: String.t(), request_id: String.t() } defstruct [ :payment_id, :status, :request_id ] @impl true def cast(generic_map) do %__MODULE__{ payment_id: generic_map["payment_id"], status: generic_map["status"], request_id: generic_map["request_id"] } end end @doc """ Create a payment for a recipient. Does a `POST /payment_initiation/payment/create` call which creates a one-time or standing (recurring) payment for a recipient. ## Params * `recipient_id` - The ID of the recipient the payment is for. * `reference` - A reference for the payment. * `amount` - A payment amount. ## Options * `:schedule` - The schedule that the payment will be executed on. ## Examples PaymentInitiation.create_payment( "recipient-id-prod-123xxx", "Purchase Order 123", %PaymentInitiation.Amount{currency: "GBP", value: 200}, %{ schedule: %PaymentInitiation.Schedule{ interval: "WEEKLY", interval_execution_day: 2, start_date: "2021-01-01", end_date: "2021-01-31" } }, client_id: "123", secret: "abc" ) {:ok, %PaymentInitiation.CreateRecipientResponse{}} """ @spec create_payment( recipient_id :: String.t(), reference :: String.t(), amount :: Amount.t(), options, Plaid.config() ) :: {:ok, CreatePaymentResponse.t()} | {:error, Plaid.Error.t()} when options: %{optional(:schedule) => Schedule.t()} def create_payment(recipient_id, reference, amount, options \\ %{}, config) do payload = %{} |> Map.put(:recipient_id, recipient_id) |> Map.put(:reference, reference) |> Map.put(:amount, amount) |> Plaid.Util.maybe_put(:schedule, options) Plaid.Client.call( "/payment_initiation/payment/create", payload, CreatePaymentResponse, config ) end defmodule GetPaymentResponse do @moduledoc """ [Plaid API /payment_initiation/payment/get response schema.](https://plaid.com/docs/api/products/#payment_initiationpaymentget) """ @behaviour Castable @type t :: %__MODULE__{ payment_id: String.t(), payment_token: String.t(), amount: Amount.t(), status: String.t(), recipient_id: String.t(), reference: String.t(), last_status_update: String.t(), schedule: Schedule.t() | nil, adjusted_reference: String.t() | nil, payment_expiration_time: String.t() | nil, request_id: String.t() } defstruct [ :payment_id, :payment_token, :amount, :status, :recipient_id, :reference, :last_status_update, :schedule, :adjusted_reference, :payment_expiration_time, :request_id ] @impl true def cast(generic_map) do %__MODULE__{ payment_id: generic_map["payment_id"], payment_token: generic_map["payment_token"], amount: Castable.cast(Amount, generic_map["amount"]), status: generic_map["status"], recipient_id: generic_map["recipient_id"], reference: generic_map["reference"], last_status_update: generic_map["last_status_update"], schedule: Castable.cast(Schedule, generic_map["schedule"]), adjusted_reference: generic_map["adjust_reference"], payment_expiration_time: generic_map["payment_expiration_time"], request_id: generic_map["request_id"] } end end @doc """ Get payment details. Does a `POST /payment_initiation/payment/create` call to get details about a payment. ## Params * `payment_id` - The payment_id returned from /payment_initiation/payment/create. ## Examples PaymentInitiation.get_payment( "payment-id-prod-123xxx", client_id: "123", secret: "abc" ) {:ok, %PaymentInitiation.GetPaymentResponse{}} """ @spec get_payment(payment_id :: String.t(), Plaid.config()) :: {:ok, GetPaymentResponse.t()} | {:error, Plaid.Error.t()} def get_payment(payment_id, config) do Plaid.Client.call( "/payment_initiation/payment/get", %{payment_id: payment_id}, GetPaymentResponse, config ) end defmodule ListPaymentsResponse do @moduledoc """ [Plaid API /payment_initiation/payment/list response schema.](https://plaid.com/docs/api/products/#payment_initiationpaymentlist) """ @behaviour Castable @type t :: %__MODULE__{ payments: [Payment.t()], next_cursor: String.t(), request_id: String.t() } defstruct [ :payments, :next_cursor, :request_id ] @impl true def cast(generic_map) do %__MODULE__{ payments: Castable.cast_list(Payment, generic_map["payments"]), next_cursor: generic_map["next_cursor"], request_id: generic_map["request_id"] } end end @doc """ List payments. Does a `POST /payment_initiation/payment/list` call to get all created payments. ## Options * `:count` - The maximum number of payments to return. * `:cursor` - A date string in RFC 3339 format. Only payments created before the cursor will be returned. ## Examples PaymentInitiation.list_payments( client_id: "123", secret: "abc" ) {:ok, %PaymentInitiation.ListPaymentsResponse{}} """ @spec list_payments(options, Plaid.config()) :: {:ok, ListPaymentsResponse.t()} | {:error, Plaid.Error.t()} when options: %{ optional(:count) => integer(), optional(:cursor) => String.t() } def list_payments(options \\ %{}, config) do payload = Map.take(options, [:count, :cursor]) Plaid.Client.call( "/payment_initiation/payment/list", payload, ListPaymentsResponse, config ) end end