defmodule Stripe.Source do
@moduledoc """
Work with Stripe source objects.
Stripe API reference: https://stripe.com/docs/api#sources
"""
use Stripe.Entity
import Stripe.Request
@type source_type :: String.t()
@type customer :: Stripe.id()
@type ach_credit_transfer :: %{
account_number: String.t() | nil,
bank_name: String.t() | nil,
fingerprint: String.t() | nil,
routing_number: String.t() | nil,
swift_code: String.t() | nil
}
@type ach_debit :: %{
bank_name: String.t() | nil,
country: String.t() | nil,
fingerprint: String.t() | nil,
last_4: String.t() | nil,
routing_number: String.t() | nil,
type: String.t() | nil
}
@type alipay :: %{
data_string: String.t() | nil,
native_url: String.t() | nil,
statement_descriptor: String.t() | nil
}
@type bancontact :: %{
bank_code: String.t() | nil,
bank_name: String.t() | nil,
bic: String.t() | nil,
preferred_language: String.t() | nil,
statement_descriptor: String.t() | nil
}
@type bitcoin :: %{
address: String.t() | nil,
amount: String.t() | nil,
amount_charged: String.t() | nil,
amount_received: String.t() | nil,
amount_returned: String.t() | nil,
refund_address: String.t() | nil,
uri: String.t() | nil
}
@type card :: %{
address_line1_check: String.t() | nil,
address_zip_check: String.t() | nil,
brand: String.t() | nil,
country: String.t() | nil,
cvc_check: String.t() | nil,
dynamic_last4: String.t() | nil,
exp_month: integer | nil,
exp_year: integer | nil,
fingerprint: String.t(),
funding: String.t() | nil,
last4: String.t() | nil,
skip_validation: boolean,
three_d_secure: String.t(),
tokenization_method: String.t() | nil
}
@type code_verification_flow :: %{
attempts_remaining: integer,
status: String.t()
}
@type eps :: %{
reference: String.t() | nil,
string_descriptor: String.t() | nil
}
@type giropay :: %{
bank_code: String.t() | nil,
bank_name: String.t() | nil,
bic: String.t() | nil,
statement_descriptor: String.t() | nil
}
@type ideal :: %{
bank: String.t() | nil,
bic: String.t() | nil,
iban_last4: String.t() | nil,
statement_descriptor: String.t() | nil
}
@type multibanco :: %{
entity: String.t() | nil,
reference: String.t() | nil,
refund_account_holder_address_city: String.t() | nil,
refund_account_holder_address_country: String.t() | nil,
refund_account_holder_address_line1: String.t() | nil,
refund_account_holder_address_line2: String.t() | nil,
refund_account_holder_address_postal_code: String.t() | nil,
refund_account_holder_address_state: String.t() | nil,
refund_account_holder_name: String.t() | nil,
refund_iban: String.t() | nil
}
@type owner :: %{
address: Stripe.Types.address() | nil,
email: String.t() | nil,
name: String.t() | nil,
phone: String.t() | nil,
verifired_address: Stripe.Types.address() | nil,
verified_email: String.t() | nil,
verified_name: String.t() | nil,
verified_phone: String.t() | nil
}
@type p24 :: %{
reference: String.t() | nil
}
@type receiver_flow :: %{
address: String.t() | nil,
amount_charged: integer,
amount_received: integer,
amount_returned: integer
}
@type redirect_flow :: %{
failure_reason: String.t() | nil,
return_url: String.t(),
status: String.t(),
url: String.t()
}
@type sepa_debit :: %{
bank_code: String.t() | nil,
branch_code: String.t() | nil,
country: String.t() | nil,
fingerprint: String.t() | nil,
last4: String.t() | nil,
mandate_reference: String.t() | nil,
mandate_url: String.t() | nil,
skip_validations: boolean
}
@type sofort :: %{
bank_code: String.t() | nil,
bank_name: String.t() | nil,
bic: String.t() | nil,
country: String.t() | nil,
iban_last4: String.t() | nil,
preferred_language: String.t() | nil,
statement_descriptor: String.t() | nil
}
@type three_d_secure :: %{
result: String.t() | nil,
card: String.t() | nil,
customer: String.t() | nil
}
@type t :: %__MODULE__{
id: Stripe.id(),
object: String.t(),
ach_credit_transfer: ach_credit_transfer | nil,
ach_debit: ach_debit | nil,
alipay: alipay | nil,
amount: non_neg_integer | nil,
bancontact: bancontact | nil,
bitcoin: bitcoin | nil,
card: card | nil,
client_secret: String.t(),
code_verification: code_verification_flow | nil,
created: Stripe.timestamp(),
currency: String.t() | nil,
eps: eps | nil,
flow: String.t(),
giropay: giropay | nil,
ideal: ideal | nil,
livemode: boolean,
metadata: Stripe.Types.metadata(),
multibanco: multibanco | nil,
owner: owner | nil,
p24: p24 | nil,
receiver: receiver_flow | nil,
redirect: redirect_flow | nil,
sepa_debit: sepa_debit | nil,
sofort: sofort | nil,
statement_descriptor: String.t() | nil,
status: String.t(),
three_d_secure: three_d_secure | nil,
type: source_type,
usage: String.t() | nil
}
defstruct [
:id,
:object,
:ach_credit_transfer,
:ach_debit,
:alipay,
:amount,
:bancontact,
:bitcoin,
:card,
:client_secret,
:code_verification,
:created,
:currency,
:customer,
:eps,
:flow,
:giropay,
:ideal,
:livemode,
:metadata,
:multibanco,
:owner,
:p24,
:receiver,
:redirect,
:sepa_debit,
:sofort,
:statement_descriptor,
:status,
:three_d_secure,
:type,
:usage,
:klarna
]
@plural_endpoint "sources"
@doc """
Create a source.
"""
@spec create(params, Keyword.t()) :: {:ok, t} | {:error, Stripe.Error.t()}
when params: %{
:type => String.t(),
optional(:amount) => non_neg_integer,
optional(:currency) => String.t(),
optional(:flow) => String.t(),
optional(:mandate) => map,
optional(:metadata) => Stripe.Types.metadata(),
optional(:owner) => owner,
optional(:receiver) => receiver_flow,
optional(:redirect) => redirect_flow,
optional(:statement_descriptor) => String.t(),
optional(:token) => String.t(),
optional(:usage) => String.t()
}
def create(%{} = params, opts \\ []) do
new_request(opts)
|> put_endpoint(@plural_endpoint)
|> put_params(params)
|> put_method(:post)
|> make_request()
end
@doc """
Retrieve a source.
"""
@spec retrieve(Stripe.id() | t, params, Stripe.options()) ::
{:ok, t} | {:error, Stripe.Error.t()}
when params: %{
optional(:client_secret) => String.t()
}
def retrieve(id, %{} = params, opts \\ []) do
new_request(opts)
|> put_endpoint(@plural_endpoint <> "/#{get_id!(id)}")
|> put_method(:get)
|> put_params(params)
|> make_request()
end
@doc """
Update a source.
Takes the `id` and a map of changes
"""
@spec update(Stripe.id() | t, params, Stripe.options()) :: {:ok, t} | {:error, Stripe.Error.t()}
when params: %{
optional(:mandate) => map,
optional(:metadata) => Stripe.Types.metadata(),
optional(:owner) => owner
}
def update(id, %{} = params, opts \\ []) do
new_request(opts)
|> put_endpoint(@plural_endpoint <> "/#{get_id!(id)}")
|> put_method(:post)
|> put_params(params)
|> make_request()
end
defp customer_endpoint(%{customer: id}) do
"customers/" <> id <> "/sources"
end
@doc """
Attach a source to a customer.
"""
@spec attach(map, Keyword.t()) :: {:ok, t} | {:error, Stripe.Error.t()}
def attach(%{customer: _, source: _} = params, opts \\ []) do
endpoint = params |> customer_endpoint()
new_request(opts)
|> put_endpoint(endpoint)
|> put_params(params |> Map.delete(:customer))
|> put_method(:post)
|> make_request()
end
@doc """
Detach a source from a customer.
"""
@spec detach(Stripe.id() | t, map, Stripe.options()) :: {:ok, t} | {:error, Stripe.Error.t()}
def detach(id, %{customer: _} = params, opts \\ []) do
endpoint = params |> customer_endpoint()
new_request(opts)
|> put_endpoint(endpoint <> "/#{get_id!(id)}")
|> put_method(:delete)
|> make_request()
end
end