defmodule Braintree.Transaction do
@moduledoc """
Create a new sale.
To create a transaction, you must include an amount and either a
payment_method_nonce or a payment_method_token.
https://developers.braintreepayments.com/reference/response/transaction/ruby
"""
use Braintree.Construction
alias Braintree.{AddOn, HTTP}
@type t :: %__MODULE__{
add_ons: [AddOn.t()],
additional_processor_response: String.t(),
amount: String.t(),
android_pay_card: map,
apple_pay: map,
avs_error_response_code: String.t(),
avs_postal_code_response_code: String.t(),
avs_street_address_response_code: String.t(),
billing: map,
channel: String.t(),
coinbase_details: String.t(),
created_at: String.t(),
credit_card: map,
currency_iso_code: String.t(),
custom_fields: map,
customer: map,
cvv_response_code: String.t(),
descriptor: map,
disbursement_details: map,
discounts: [any],
disputes: [any],
escrow_status: String.t(),
gateway_rejection_reason: String.t(),
id: String.t(),
merchant_account_id: String.t(),
order_id: String.t(),
payment_instrument_type: String.t(),
paypal: map,
plan_id: String.t(),
processor_authorization_code: String.t(),
processor_response_code: String.t(),
processor_response_text: String.t(),
processor_settlement_response_code: String.t(),
processor_settlement_response_text: String.t(),
purchase_order_number: String.t(),
recurring: String.t(),
refund_ids: String.t(),
refunded_transaction_id: String.t(),
risk_data: String.t(),
service_fee_amount: number,
settlement_batch_id: String.t(),
shipping: map,
status: String.t(),
status_history: String.t(),
subscription_details: map,
subscription_id: String.t(),
tax_amount: number,
tax_exempt: boolean,
type: String.t(),
updated_at: String.t(),
voice_referral_number: String.t()
}
defstruct add_ons: [],
additional_processor_response: nil,
amount: "0",
android_pay_card: nil,
apple_pay: nil,
avs_error_response_code: nil,
avs_postal_code_response_code: nil,
avs_street_address_response_code: nil,
billing: %{},
channel: nil,
coinbase_details: nil,
created_at: nil,
credit_card: %{},
currency_iso_code: nil,
custom_fields: %{},
customer: %{},
cvv_response_code: nil,
descriptor: %{},
disbursement_details: nil,
discounts: [],
disputes: [],
escrow_status: nil,
gateway_rejection_reason: nil,
id: nil,
merchant_account_id: nil,
order_id: nil,
payment_instrument_type: nil,
paypal: %{},
plan_id: nil,
processor_authorization_code: nil,
processor_response_code: nil,
processor_response_text: nil,
processor_settlement_response_code: nil,
processor_settlement_response_text: nil,
purchase_order_number: nil,
recurring: nil,
refund_ids: nil,
refunded_transaction_id: nil,
risk_data: nil,
service_fee_amount: 0,
settlement_batch_id: nil,
shipping: %{},
status: nil,
status_history: nil,
subscription_details: %{},
subscription_id: nil,
tax_amount: 0,
tax_exempt: false,
type: nil,
updated_at: nil,
voice_referral_number: nil
@doc """
Use a `payment_method_nonce` or `payment_method_token` to make a one time
charge against a payment method.
## Example
{:ok, transaction} = Transaction.sale(%{
amount: "100.00",
payment_method_nonce: @payment_method_nonce,
options: %{submit_for_settlement: true}
})
transaction.status # "settling"
"""
@spec sale(map, Keyword.t()) :: {:ok, t} | HTTP.error()
def sale(params, opts \\ []) do
sale_params = Map.merge(params, %{type: "sale"})
with {:ok, payload} <- HTTP.post("transactions", %{transaction: sale_params}, opts) do
{:ok, new(payload)}
end
end
@doc """
Use a `transaction_id` and optional `amount` to settle the transaction.
Use this if `submit_for_settlement` was false while creating the charge using sale.
## Example
{:ok, transaction} = Transaction.submit_for_settlement("123", %{amount: "100"})
transaction.status # "settling"
"""
@spec submit_for_settlement(String.t(), map, Keyword.t()) :: {:ok, t} | HTTP.error()
def submit_for_settlement(transaction_id, params, opts \\ []) do
path = "transactions/#{transaction_id}/submit_for_settlement"
with {:ok, payload} <- HTTP.put(path, %{transaction: params}, opts) do
{:ok, new(payload)}
end
end
@doc """
Use a `transaction_id` and optional `amount` to issue a refund
for that transaction
## Example
{:ok, transaction} = Transaction.refund("123", %{amount: "100.00"})
transaction.status # "refunded"
"""
@spec refund(String.t(), map, Keyword.t()) :: {:ok, t} | HTTP.error()
def refund(transaction_id, params, opts \\ []) do
path = "transactions/#{transaction_id}/refund"
with {:ok, payload} <- HTTP.post(path, %{transaction: params}, opts) do
{:ok, new(payload)}
end
end
@doc """
Use a `transaction_id` to issue a void for that transaction
## Example
{:ok, transaction} = Transaction.void("123")
transaction.status # "voided"
"""
@spec void(String.t(), Keyword.t()) :: {:ok, t} | HTTP.error()
def void(transaction_id, opts \\ []) do
path = "transactions/#{transaction_id}/void"
with {:ok, payload} <- HTTP.put(path, opts) do
{:ok, new(payload)}
end
end
@doc """
Find an existing transaction by `transaction_id`
## Example
{:ok, transaction} = Transaction.find("123")
"""
@spec find(String.t(), Keyword.t()) :: {:ok, t} | HTTP.error()
def find(transaction_id, opts \\ []) do
path = "transactions/#{transaction_id}"
with {:ok, payload} <- HTTP.get(path, opts) do
{:ok, new(payload)}
end
end
@doc """
Convert a map into a Transaction struct.
Add_ons are converted to a list of structs as well.
## Example
transaction =
Braintree.Transaction.new(%{
"subscription_id" => "subxid",
"status" => "submitted_for_settlement"
})
"""
def new(%{"transaction" => map}) do
new(map)
end
def new(map) when is_map(map) do
transaction = super(map)
%{transaction | add_ons: AddOn.new(transaction.add_ons)}
end
def new(list) when is_list(list) do
Enum.map(list, &new/1)
end
end