Current section
Files
Jump to
Current section
Files
lib/paddle/subscription/subscription.ex
defmodule Paddle.Subscription do
@moduledoc """
This module corresponds to the `subscription/users` endpoint in the Paddle API,
I've changed it to Subscription as I found it to be more accurate.
"""
@type t :: %{
subscription_id: integer,
plan_id: integer,
user_id: integer,
user_email: String.t(),
marketing_consent: boolean,
state: String.t(),
signup_date: String.t(),
last_payment: map,
next_payment: map | nil,
update_url: String.t(),
cancel_url: String.t(),
paused_at: String.t() | nil,
paused_from: String.t() | nil,
payment_information: map
}
defstruct [
:subscription_id,
:plan_id,
:user_id,
:user_email,
:marketing_consent,
:state,
:signup_date,
:last_payment,
:next_payment,
:update_url,
:cancel_url,
:paused_at,
:paused_from,
:payment_information
]
@doc """
List all users subscribed to any of your subscription plans
Optionally also accepts `plan_id`, `subscription_id`, and `state` to filter the response to just users of a specific plan, a user subscription, or the status of the user’s subscription.
If not filtering by the `subscription_id`, it is strongly recommend to utilize `results_per_page` and `page` to limit the amount of results returned within each API call. This ensures that the response time remains quick and consistent as the amount of user subscriptions build up over time.
## Examples
Paddle.Subscriber.list()
{:ok, [
%Paddle.Subscriber{
subscription_id: 502198,
plan_id: 496199,
user_id: 285846,
user_email: "name@example.com",
marketing_consent: true,
update_url: "https://checkout.paddle.com/subscription/update?user=12345&subscription=87654321&hash=eyJpdiI6Ik1RTE1nbHpXQmtJUG5...",
cancel_url: "https://checkout.paddle.com/subscription/cancel?user=12345&subscription=87654321&hash=eyJpdiI6IlU0Nk5cL1JZeHQyTXd...",
state: "active",
signup_date: ~U"2015-10-06 09:44:23Z",
last_payment: %{
"amount" => 5,
"currency" => "USD",
"date" => ~D"2015-10-06"
},
payment_information: %{
"payment_method" => "card",
"card_type" => "visa",
"last_four_digits" => "1111",
"expiry_date" => "02/2020"
},
next_payment: %{
"amount" => 10,
"currency" => "USD",
"date" => ~D"2015-11-06"
}
}
]}
"""
@spec list(keyword()) ::
{:ok, [t()]} | {:error, Paddle.Error.t()}
def list(opts \\ []) do
params =
Enum.into(opts, %{})
|> Map.take([:subscription_id, :plan_id, :state, :page, :results_per_page])
case Paddle.Request.post("/2.0/subscription/users", params) do
{:ok, list} ->
{:ok,
Enum.map(list, fn elm ->
Paddle.Helpers.map_to_struct(elm, __MODULE__)
|> convert_dates()
end)}
{:error, reason} ->
{:error, reason}
end
end
@doc """
Update the quantity, price, and/or plan of a user’s subscription
## Usage Notes
- Subscribers on non-quantity plans can move to quantity plans but not the inverse.
- Subscribers must be billed immediately when moving to a plan with a different billing interval.
- Subscribers cannot be moved to a plan where the current currency is not enabled.
- Subscribers cannot be moved to a different plan while on a trialing state.
- Subscribers in a paused state cannot be modified until they restart their subscription.
- Subscribers in a past due state can only have the passthrough or pause field updated.
- The currency of an existing subscription cannot be changed.
- Recurring coupons (if present) will be removed when this API is used.
## Examples
params = %{
bill_immediately: true,
plan_id: 525123,
prorate: true,
keep_modifiers: true,
passthrough: true,
pause: true
}
Paddle.Subscriber.update(12345, params)
{:ok, %{
subscription_id: 12345,
user_id: 425123,
plan_id: 525123,
next_payment: %{
"amount" => 144.06,
"currency" => "GBP",
"date" => ~D"2018-02-15",
}
}}
"""
@spec update(integer, params) :: {:ok, map} | {:error, Paddle.Error.t()}
when params: %{
:quantity => integer,
optional(:currency) => String.t(),
optional(:recurring_price) => number,
optional(:bill_immediately) => boolean,
optional(:plan_id) => integer,
optional(:prorate) => boolean,
optional(:keep_modifiers) => boolean,
optional(:passthrough) => String.t(),
optional(:pause) => boolean
}
def update(subscription_id, params) do
params = Map.put(params, :subscription_id, subscription_id)
case Paddle.Request.post("/2.0/subscription/users/update", params) do
{:ok, user} ->
user = %{
subscription_id: user["subscription_id"],
user_id: user["user_id"],
plan_id: user["plan_id"],
next_payment: user["next_payment"]
}
user =
put_in(user, [:next_payment, "date"], Date.from_iso8601!(user.next_payment["date"]))
{:ok, user}
{:error, reason} ->
{:error, reason}
end
end
@doc """
Cancel the specified user’s subscription
## Examples
Paddle.Subscriber.cancel(12345)
{:ok, nil}
"""
@spec(cancel(integer) :: {:ok, nil}, {:error, Paddle.Error.t()})
def cancel(subscription_id) do
Paddle.Request.post("/2.0/subscription/users/cancel", %{subscription_id: subscription_id})
end
defp convert_dates(user) do
user = put_in(user.last_payment["date"], Date.from_iso8601!(user.last_payment["date"]))
user = put_in(user.next_payment["date"], Date.from_iso8601!(user.next_payment["date"]))
{:ok, signup_datetime, 0} = DateTime.from_iso8601(user.signup_date <> "Z")
put_in(user.signup_date, signup_datetime)
end
end