Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Payment Refund #2

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/paypal/order/purchase_unit.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule Paypal.Order.PurchaseUnit do

alias Paypal.Common.CurrencyValue
alias Paypal.Order.PurchaseUnit.Item
alias Paypal.Order.PurchaseUnit.PaymentCollection

@derive Jason.Encoder

Expand All @@ -27,8 +28,7 @@ defmodule Paypal.Order.PurchaseUnit do
field(:soft_descriptor, :string)
embeds_many(:items, Item)
embeds_one(:amount, CurrencyValue)
# TODO
field(:payments, :map)
embeds_one(:payments, PaymentCollection)
# TODO
field(:payee, :map)
# TODO
Expand All @@ -49,7 +49,6 @@ defmodule Paypal.Order.PurchaseUnit do
payment_instruction
shipping
supplementary_data
payments
]a

@doc false
Expand All @@ -58,6 +57,7 @@ defmodule Paypal.Order.PurchaseUnit do
|> cast(params, @fields)
|> cast_embed(:amount, required: true)
|> cast_embed(:items)
|> cast_embed(:payments)
|> validate_length(:reference_id, min: 1, max: 256)
|> validate_length(:description, min: 1, max: 127)
|> validate_length(:custom_id, min: 1, max: 127)
Expand Down
77 changes: 77 additions & 0 deletions lib/paypal/order/purchase_unit/capture.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
defmodule Paypal.Order.PurchaseUnit.Capture do
@moduledoc """
Represents a Capture object from the PayPal v2 PurchaseUnit API.

## Fields

- `id` - The unique ID for the capture.
- `status` - The status of the capture (e.g. `"COMPLETED"`).
- `status_details` - The details of the capture status.
- `invoice_id` - The API caller-provided external invoice number for this order.
- `custom_id` - The API caller-provided external ID.
- `final_capture` - A boolean indicating if this is the final capture.
- `create_time` - The date and time when the capture was created (ISO 8601 string).
- `update_time` - The date and time when the capture was last updated (ISO 8601 string).
- `amount` - An embedded schema representing the monetary amount of the capture.
- `disbursement_mode` - An embedded schema containing details about the disbursement mode.
- `processor_response` - An embedded schema containing details about the processor response.
- `seller_protection` - An embedded schema containing details about seller protection.
- `seller_receivable_breakdown` - An embedded schema that details the receivables.
- `network_transaction_reference` - Reference values used by the card network to identify a transaction.
- `links` - A list of embedded link objects for further API actions.
"""

use TypedEctoSchema
import Ecto.Changeset
alias Paypal.Common.CurrencyValue
alias Paypal.Common.Link

@primary_key false
typed_embedded_schema do
field(:id, :string)
field(:status, :string)
field(:status_details, :string)
field(:invoice_id, :string)
field(:custom_id, :string)
field(:final_capture, :boolean)
field(:create_time, :string)
field(:update_time, :string)
# TODO
field(:seller_protection, :map)
# TODO
field(:seller_receivable_breakdown, :map)
# TODO
field(:network_transaction_reference, :map)
# TODO
field(:disbursement_mode, :map)
# TODO
field(:processor_response, :map)

embeds_one(:amount, CurrencyValue)
embeds_many(:links, Link)
end

@fields ~w[
status
status_details
id
invoice_id
custom_id
network_transaction_reference
seller_protection
final_capture
seller_receivable_breakdown
disbursement_mode
processor_response
create_time
update_time
]a

@doc false
def changeset(model \\ %__MODULE__{}, params) do
model
|> cast(params, @fields)
|> cast_embed(:amount, required: true)
|> cast_embed(:links)
end
end
32 changes: 32 additions & 0 deletions lib/paypal/order/purchase_unit/payment_collection.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule Paypal.Order.PurchaseUnit.PaymentCollection do
@moduledoc """
Represents a Payment Collection object from the PayPal v2 API.

This object holds details about payment captures, refunds, and authorizations.
"""

use TypedEctoSchema
import Ecto.Changeset

alias Paypal.Order.PurchaseUnit.Capture

typed_embedded_schema do
embeds_many(:captures, Capture)
# TODO
field(:authorizations, :map)
# TODO
field(:refunds, :map)
end

@fields ~w[
authorizations
refunds
]a

@doc false
def changeset(model \\ %__MODULE__{}, params) do
model
|> cast(params, @fields)
|> cast_embed(:captures, with: &Capture.changeset/2)
end
end
17 changes: 17 additions & 0 deletions lib/paypal/payment.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ defmodule Paypal.Payment do
alias Paypal.Common.Error, as: PaymentError
alias Paypal.Payment.Captured
alias Paypal.Payment.Info
alias Paypal.Payment.Refund
alias Paypal.Payment.RefundRequest

adapter({Tesla.Adapter.Finch, name: Paypal.Finch})

Expand Down Expand Up @@ -78,4 +80,19 @@ defmodule Paypal.Payment do
error
end
end

@spec refund(String.t(), RefundRequest.t() | map()) ::
{:ok, Info.t()} | {:error, PaymentError.t() | String.t()}
def(refund(id, body \\ %{})) do
case post("/captures/#{id}/refund", body |> RefundRequest.cast() |> Jason.encode!()) do
{:ok, %_{status: code, body: response}} when code in 200..299 ->
{:ok, Refund.cast(response)}

{:ok, %_{body: response}} ->
{:error, PaymentError.cast(response)}

{:error, _} = error ->
error
end
end
end
85 changes: 85 additions & 0 deletions lib/paypal/payment/refund.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
defmodule Paypal.Payment.Refund do
@moduledoc """
Payment refund information. The information retrieved from Paypal about the
refund.

## Fields

- `id` - The unique ID for the capture.
- `status` - The status of the capture (e.g. `"COMPLETED"`).
- `status_details` - The details of the capture status.
- `invoice_id` - The API caller-provided external invoice number for this order.
- `custom_id` - The API caller-provided external ID.
- `payer` - An embedded schema representing the payer.
- `create_time` - The date and time when the capture was created (ISO 8601 string).
- `update_time` - The date and time when the capture was last updated (ISO 8601 string).
- `amount` - An embedded schema representing the monetary amount of the capture.
- `acquirer_reference_number` - Reference ID issued for the card transaction.
- `note_to_payer` - The reason for the refund.
- `seller_protection` - An embedded schema containing details about seller protection.
- `seller_payable_breakdown` - An embedded schema that details the seller_payable_breakdown.
- `links` - A list of embedded link objects for further API actions.
"""

use TypedEctoSchema
import Ecto.Changeset
alias Paypal.Common.CurrencyValue
alias Paypal.Common.Link
alias Paypal.Order.Payer

@statuses [
cancelled: "CANCELLED",
failed: "FAILED",
pending: "PENDING",
completed: "COMPLETED"
]

@primary_key false
typed_embedded_schema do
field(:id, :string)
field(:status, Ecto.Enum, values: @statuses, embed_as: :dumped)
field(:status_details, :string)
field(:invoice_id, :string)
field(:custom_id, :string)
field(:create_time, :string)
field(:update_time, :string)
field(:acquirer_reference_number, :string)
field(:note_to_payer, :string)
# TODO
field(:seller_protection, :map)
# TODO
field(:seller_payable_breakdown, :map)

embeds_one(:payer, Payer)
embeds_one(:amount, CurrencyValue)
embeds_many(:links, Link)
end

@fields ~w[
status
status_details
id
invoice_id
custom_id
acquirer_reference_number
seller_protection
note_to_payer
seller_payable_breakdown
create_time
update_time
]a

@doc false
def changeset(model \\ %__MODULE__{}, params) do
model
|> cast(params, @fields)
|> cast_embed(:amount, required: true)
|> cast_embed(:links)
|> cast_embed(:payer)
end

@doc false
def cast(params) do
Ecto.embedded_load(__MODULE__, params, :json)
end
end
49 changes: 49 additions & 0 deletions lib/paypal/payment/refund_request.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
defmodule Paypal.Payment.RefundRequest do
@moduledoc """
Request object that Refunds a captured payment, by ID. For a full refund, include an empty
request body. For a partial refund, include an `amount` object in
the request body.

## Fields

- `amount` - The currency and amount for a financial transaction, such as a balance or payment due.
- `custom_id` - The API caller-provided external ID. Used to reconcile API caller-initiated transactions with PayPal transactions.
- `invoice_id` - The API caller-provided external invoice ID for this order.
- `note_to_payer` - The reason for the refund. Appears in both the payer's transaction history and the emails that the payer receives.
- `payment_instruction` - Any additional payments instructions during refund payment processing.
"""

use TypedEctoSchema
import Ecto.Changeset
alias Paypal.Common.CurrencyValue

@derive Jason.Encoder
@primary_key false
typed_embedded_schema do
embeds_one(:amount, CurrencyValue)
field(:custom_id, :string)
field(:invoice_id, :string)
field(:note_to_payer, :string)
# TODO
field(:payment_instruction, :map)
end

@fields ~w[
custom_id
invoice_id
note_to_payer
payment_instruction
]a

@doc false
def changeset(model \\ %__MODULE__{}, params) do
model
|> cast(params, @fields)
|> cast_embed(:amount)
end

@doc false
def cast(params) do
Ecto.embedded_load(__MODULE__, params, :json)
end
end
Loading