# `LatticeStripe.PaymentIntent`
[🔗](https://github.com/szTheory/lattice_stripe/blob/v1.1.0/lib/lattice_stripe/payment_intent.ex#L1)

Operations on Stripe PaymentIntent objects.

A PaymentIntent guides you through the process of collecting a payment from
your customer. It tracks the lifecycle of a payment — from initial creation
through confirmation, capture, and completion.

PaymentIntents are the recommended way to accept payments for most Stripe
integrations. They handle complex flows like 3D Secure authentication,
SCA requirements, and multi-step payment methods.

## Usage

    client = LatticeStripe.Client.new!(api_key: "sk_live_...", finch: MyApp.Finch)

    # Create a PaymentIntent (amount in smallest currency unit, e.g., cents)
    {:ok, pi} = LatticeStripe.PaymentIntent.create(client, %{
      "amount" => 2000,
      "currency" => "usd",
      "metadata" => %{"order_id" => "ord_123"}
    })

    # Confirm a PaymentIntent with a payment method
    {:ok, pi} = LatticeStripe.PaymentIntent.confirm(client, pi.id, %{
      "payment_method" => "pm_card_visa"
    })

    # Capture a manually-captured PaymentIntent
    {:ok, pi} = LatticeStripe.PaymentIntent.capture(client, pi.id)

    # Cancel a PaymentIntent
    {:ok, pi} = LatticeStripe.PaymentIntent.cancel(client, pi.id, %{
      "cancellation_reason" => "abandoned"
    })

    # List PaymentIntents with filters
    {:ok, resp} = LatticeStripe.PaymentIntent.list(client, %{"limit" => "10"})
    payment_intents = resp.data.data  # [%PaymentIntent{}, ...]

    # Stream all PaymentIntents lazily (auto-pagination)
    client
    |> LatticeStripe.PaymentIntent.stream!()
    |> Stream.take(100)
    |> Enum.each(&process_payment/1)

## Security and Inspect

The `Inspect` implementation hides `client_secret` — this value must never
appear in logs. Only `id`, `object`, `amount`, `currency`, and `status` are
shown in inspect output.

Note: PaymentIntents cannot be deleted. There is no `delete/3` function.

## Stripe API Reference

See the [Stripe PaymentIntent API](https://docs.stripe.com/api/payment_intents) for the full
object reference and available parameters.

# `t`

```elixir
@type t() :: %LatticeStripe.PaymentIntent{
  amount: integer() | nil,
  amount_capturable: integer() | nil,
  amount_details: map() | nil,
  amount_received: integer() | nil,
  application: String.t() | nil,
  application_fee_amount: integer() | nil,
  automatic_payment_methods: map() | nil,
  canceled_at: integer() | nil,
  cancellation_reason: String.t() | nil,
  capture_method: String.t() | nil,
  client_secret: String.t() | nil,
  confirmation_method: String.t() | nil,
  created: integer() | nil,
  currency: String.t() | nil,
  customer: String.t() | nil,
  customer_account: map() | nil,
  description: String.t() | nil,
  excluded_payment_method_types: [String.t()] | nil,
  extra: map(),
  hooks: map() | nil,
  id: String.t() | nil,
  last_payment_error: map() | nil,
  latest_charge: String.t() | nil,
  livemode: boolean() | nil,
  metadata: map() | nil,
  next_action: map() | nil,
  object: String.t(),
  on_behalf_of: String.t() | nil,
  payment_method: String.t() | nil,
  payment_method_configuration_details: map() | nil,
  payment_method_options: map() | nil,
  payment_method_types: [String.t()] | nil,
  processing: map() | nil,
  receipt_email: String.t() | nil,
  review: String.t() | nil,
  setup_future_usage: String.t() | nil,
  shipping: map() | nil,
  source: String.t() | nil,
  statement_descriptor: String.t() | nil,
  statement_descriptor_suffix: String.t() | nil,
  status: String.t() | nil,
  transfer_data: map() | nil,
  transfer_group: String.t() | nil
}
```

A Stripe PaymentIntent object.

See the [Stripe PaymentIntent API](https://docs.stripe.com/api/payment_intents/object) for field definitions.

# `cancel`

```elixir
@spec cancel(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}
```

Cancels a PaymentIntent.

Sends `POST /v1/payment_intents/:id/cancel` with optional params and returns
`{:ok, %PaymentIntent{status: "canceled"}}`. A PaymentIntent can be canceled
when it is in `requires_payment_method`, `requires_capture`,
`requires_confirmation`, or `requires_action` status.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The PaymentIntent ID string
- `params` - Optional cancel params (e.g., `%{"cancellation_reason" => "abandoned"}`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %PaymentIntent{status: "canceled"}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

## Example

    {:ok, pi} = LatticeStripe.PaymentIntent.cancel(client, pi.id, %{
      "cancellation_reason" => "abandoned"
    })

# `cancel!`

```elixir
@spec cancel!(LatticeStripe.Client.t(), String.t(), map(), keyword()) :: t()
```

Like `cancel/4` but raises `LatticeStripe.Error` on failure.

# `capture`

```elixir
@spec capture(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}
```

Captures an authorized PaymentIntent.

Sends `POST /v1/payment_intents/:id/capture` with optional params and returns
`{:ok, %PaymentIntent{}}`. Only applicable when `capture_method` is `"manual"`.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The PaymentIntent ID string
- `params` - Optional capture params (e.g., `%{"amount_to_capture" => 1500}`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %PaymentIntent{}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

## Example

    {:ok, pi} = LatticeStripe.PaymentIntent.capture(client, pi.id)

# `capture!`

```elixir
@spec capture!(LatticeStripe.Client.t(), String.t(), map(), keyword()) :: t()
```

Like `capture/4` but raises `LatticeStripe.Error` on failure.

# `confirm`

```elixir
@spec confirm(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}
```

Confirms a PaymentIntent, attempting to collect payment.

Sends `POST /v1/payment_intents/:id/confirm` with optional params and returns
`{:ok, %PaymentIntent{}}`. After confirmation, the PaymentIntent will have a
`status` indicating whether payment succeeded or requires additional steps.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The PaymentIntent ID string
- `params` - Optional confirmation params (e.g., `%{"payment_method" => "pm_..."}`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %PaymentIntent{}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

## Example

    {:ok, pi} = LatticeStripe.PaymentIntent.confirm(client, pi.id, %{
      "payment_method" => "pm_card_visa"
    })

# `confirm!`

```elixir
@spec confirm!(LatticeStripe.Client.t(), String.t(), map(), keyword()) :: t()
```

Like `confirm/4` but raises `LatticeStripe.Error` on failure.

# `create`

```elixir
@spec create(LatticeStripe.Client.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}
```

Creates a new PaymentIntent.

Sends `POST /v1/payment_intents` with the given params and returns
`{:ok, %PaymentIntent{}}`. The `amount` and `currency` params are required
by Stripe.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Map of PaymentIntent attributes (e.g., `%{"amount" => 2000, "currency" => "usd"}`)
- `opts` - Per-request overrides (e.g., `[idempotency_key: "..."]`)

## Returns

- `{:ok, %PaymentIntent{}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

## Example

    {:ok, pi} = LatticeStripe.PaymentIntent.create(client, %{
      "amount" => 2000,
      "currency" => "usd"
    })

    # Error handling
    case LatticeStripe.PaymentIntent.create(client, %{"amount" => 2000, "currency" => "usd"}) do
      {:ok, pi} -> pi.id
      {:error, %LatticeStripe.Error{type: :card_error} = err} -> handle_card_error(err)
      {:error, %LatticeStripe.Error{type: :invalid_request_error} = err} -> handle_error(err)
      {:error, %LatticeStripe.Error{}} = err -> handle_error(err)
    end

# `create!`

```elixir
@spec create!(LatticeStripe.Client.t(), map(), keyword()) :: t()
```

Like `create/3` but raises `LatticeStripe.Error` on failure.

# `from_map`

```elixir
@spec from_map(map()) :: t()
```

Converts a decoded Stripe API map to a `%PaymentIntent{}` struct.

Maps all known Stripe PaymentIntent fields. Any unrecognized fields are
collected into the `extra` map so no data is silently lost.

## Example

    pi = LatticeStripe.PaymentIntent.from_map(%{
      "id" => "pi_123",
      "amount" => 2000,
      "currency" => "usd",
      "status" => "requires_payment_method"
    })

# `list`

```elixir
@spec list(LatticeStripe.Client.t(), map(), keyword()) ::
  {:ok, LatticeStripe.Response.t()} | {:error, LatticeStripe.Error.t()}
```

Lists PaymentIntents with optional filters.

Sends `GET /v1/payment_intents` and returns `{:ok, %Response{data: %List{}}}` with
typed `%PaymentIntent{}` items.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Filter params (e.g., `%{"limit" => "10", "customer" => "cus_123"}`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %Response{data: %List{data: [%PaymentIntent{}, ...]}}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

## Example

    {:ok, resp} = LatticeStripe.PaymentIntent.list(client, %{"limit" => "20"})
    Enum.each(resp.data.data, &IO.inspect/1)

# `list!`

```elixir
@spec list!(LatticeStripe.Client.t(), map(), keyword()) :: LatticeStripe.Response.t()
```

Like `list/3` but raises `LatticeStripe.Error` on failure.

# `retrieve`

```elixir
@spec retrieve(LatticeStripe.Client.t(), String.t(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}
```

Retrieves a PaymentIntent by ID.

Sends `GET /v1/payment_intents/:id` and returns `{:ok, %PaymentIntent{}}`.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The PaymentIntent ID string (e.g., `"pi_123"`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %PaymentIntent{}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

# `retrieve!`

```elixir
@spec retrieve!(LatticeStripe.Client.t(), String.t(), keyword()) :: t()
```

Like `retrieve/3` but raises `LatticeStripe.Error` on failure.

# `search`

```elixir
@spec search(LatticeStripe.Client.t(), String.t(), keyword()) ::
  {:ok, LatticeStripe.Response.t()} | {:error, LatticeStripe.Error.t()}
```

Searches PaymentIntents using Stripe's search query language.

Sends `GET /v1/payment_intents/search` with the query string and returns typed results.
Note: search results have eventual consistency — newly created PaymentIntents may not
appear immediately.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `query` - Stripe search query string (e.g., `"status:'succeeded' AND currency:'usd'"`)
- `opts` - Per-request overrides

## Returns

- `{:ok, %Response{data: %List{data: [%PaymentIntent{}, ...]}}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

## Example

    {:ok, resp} = LatticeStripe.PaymentIntent.search(client, "status:'succeeded'")

# `search!`

```elixir
@spec search!(LatticeStripe.Client.t(), String.t(), keyword()) ::
  LatticeStripe.Response.t()
```

Like `search/3` but raises `LatticeStripe.Error` on failure.

# `search_stream!`

```elixir
@spec search_stream!(LatticeStripe.Client.t(), String.t(), keyword()) ::
  Enumerable.t()
```

Returns a lazy stream of all PaymentIntents matching the search query (auto-pagination).

Emits individual `%PaymentIntent{}` structs, fetching additional search pages as needed.
Raises `LatticeStripe.Error` if any page fetch fails.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `query` - Stripe search query string
- `opts` - Per-request overrides

## Returns

An `Enumerable.t()` of `%PaymentIntent{}` structs.

# `stream!`

```elixir
@spec stream!(LatticeStripe.Client.t(), map(), keyword()) :: Enumerable.t()
```

Returns a lazy stream of all PaymentIntents matching the given params (auto-pagination).

Emits individual `%PaymentIntent{}` structs, fetching additional pages as needed.
Raises `LatticeStripe.Error` if any page fetch fails.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `params` - Filter params (e.g., `%{"limit" => "100"}`)
- `opts` - Per-request overrides

## Returns

An `Enumerable.t()` of `%PaymentIntent{}` structs.

## Example

    client
    |> LatticeStripe.PaymentIntent.stream!()
    |> Stream.take(500)
    |> Enum.to_list()

# `update`

```elixir
@spec update(LatticeStripe.Client.t(), String.t(), map(), keyword()) ::
  {:ok, t()} | {:error, LatticeStripe.Error.t()}
```

Updates a PaymentIntent by ID.

Sends `POST /v1/payment_intents/:id` with the given params and returns
`{:ok, %PaymentIntent{}}`.

## Parameters

- `client` - A `%LatticeStripe.Client{}` struct
- `id` - The PaymentIntent ID string
- `params` - Map of fields to update
- `opts` - Per-request overrides

## Returns

- `{:ok, %PaymentIntent{}}` on success
- `{:error, %LatticeStripe.Error{}}` on failure

# `update!`

```elixir
@spec update!(LatticeStripe.Client.t(), String.t(), map(), keyword()) :: t()
```

Like `update/4` but raises `LatticeStripe.Error` on failure.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
