# Extripe
[![Hex.pm](https://img.shields.io/hexpm/v/extripe.svg)](https://hex.pm/packages/extripe)
[![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](https://hexdocs.pm/extripe/Extripe.html)
Stripe API wrapper in Elixir [Read Documentation](http://hexdocs.pm/extripe/)
## Installation
1. Add extripe to your list of dependencies in `mix.exs`:
```elixir
def deps do
[{:extripe, "~> 1.0"}]
end
```
2. Ensure `httpoison` is started before your application:
```elixir
def application do
[applications: [:httpoison]]
end
```
## Usage
- Use with env var `stripe_secret_key`
```elixir
stripe_secret_key=sk_test_abcdefg12345678 iex -S mix
```
- Or config it
```elixir
config :extripe,
stripe_secret_key: "sk_test_abcdefg12345678"
```
### Features
#### Simple CRUD
Using `Plan`, `Customer` and `Subscirption` in the following examples, all entities should be supported, if you find anything that is not supported or new endpoints coming out from stripe, don't hesitate to [file an issue](https://github.com/princemaple/extripe/issues/new)
```elixir
iex(1)> Extripe.Plan.index
{:ok,
%{"data" => [%{"amount" => 1500, "created" => 1455733031, "currency" => "gbp",
"id" => "regular_gb", "interval" => "month", "interval_count" => 1,
"livemode" => false, "metadata" => %{}, "name" => "Regular GB",
"object" => "plan", "statement_descriptor" => nil,
"trial_period_days" => nil},
%{"amount" => 1000, "created" => 1455632453, "currency" => "aud",
"id" => "regular_au", "interval" => "month", "interval_count" => 1,
"livemode" => false, "metadata" => %{}, "name" => "Regular AU",
"object" => "plan", "statement_descriptor" => nil,
"trial_period_days" => 15},
%{"amount" => 1000, "created" => 1455593353, "currency" => "usd",
"id" => "regular", "interval" => "month", "interval_count" => 1,
"livemode" => false, "metadata" => %{}, "name" => "REGULAR",
"object" => "plan", "statement_descriptor" => nil,
"trial_period_days" => 15}], "has_more" => false, "object" => "list",
"url" => "/v1/plans"}}
iex(2)> Extripe.Plan.show "regular"
{:ok,
%{"amount" => 1000, "created" => 1455593353, "currency" => "usd",
"id" => "regular", "interval" => "month", "interval_count" => 1,
"livemode" => false, "metadata" => %{}, "name" => "REGULAR",
"object" => "plan", "statement_descriptor" => nil,
"trial_period_days" => 15}}
iex(3)> Extripe.Plan.create %{id: "test", name: "My Test Plan", amount: 1999, interval: "month", currency: "usd"}
{:ok,
%{"amount" => 1999, "created" => 1455736111,
"currency" => "usd", "id" => "test", "interval" => "month",
"interval_count" => 1, "livemode" => false, "metadata" => %{},
"name" => "My Test Plan", "object" => "plan", "statement_descriptor" => nil,
"trial_period_days" => nil}}
# or Extripe.Plan.update "test_id", %{name: "MY TTTTEST PLAN"}
iex(4)> Extripe.Plan.update %{id: "test_id", name: "MY TTTTEST PLAN"}
{:ok,
%{"amount" => 1999, "created" => 1455736111,
"currency" => "usd", "id" => "test", "interval" => "month",
"interval_count" => 1, "livemode" => false, "metadata" => %{},
"name" => "MY TTTTEST PLAN", "object" => "plan",
"statement_descriptor" => nil, "trial_period_days" => nil}}
iex(5)> Extripe.Plan.delete "test"
{:ok, %{"deleted" => true, "id" => "test"}}
```
#### Response
All actions return either `{:ok, body :: map}` or `{:error, reason :: binary}`
#### Nested resources
```elixir
# find a customer first
iex(1)> Extripe.Customer.index
{:ok,
%{"data" => [%{"account_balance" => 0, "created" => 1455721994,
"currency" => "usd", "default_source" => nil, "delinquent" => false,
"description" => "test self", "discount" => nil,
"email" => "chenpaul914@hotmail.com", "id" => "cus_7vNk0duWVulcPe",
"livemode" => false, "metadata" => %{}, "object" => "customer",
"shipping" => nil,
"sources" => %{"data" => [], "has_more" => false, "object" => "list",
"total_count" => 0,
"url" => "/v1/customers/cus_7vNk0duWVulcPe/sources"},
"subscriptions" => %{"data" => [], "has_more" => false,
"object" => "list", "total_count" => 0,
"url" => "/v1/customers/cus_7vNk0duWVulcPe/subscriptions"}}],
"has_more" => false, "object" => "list", "url" => "/v1/customers"}}
# find the subscriptions that belong to the customer
iex(2)> Extripe.Subscription.index customer: "cus_7vNk0duWVulcPe"
{:ok,
%{"data" => [], "has_more" => false,
"object" => "list",
"url" => "/v1/customers/cus_7vNk0duWVulcPe/subscriptions"}}
# manipulations...
iex(3)> Extripe.Subscription.create customer: "cus_7vNk0duWVulcPe", %{plan: "regular"}
{:ok,
%{"application_fee_percent" => nil,
"cancel_at_period_end" => false, "canceled_at" => nil,
"current_period_end" => 1457032418, "current_period_start" => 1455736418,
"customer" => "cus_7vNk0duWVulcPe", "discount" => nil, "ended_at" => nil,
"id" => "sub_7vRdUiQQhv3M7u", "metadata" => %{}, "object" => "subscription",
"plan" => %{"amount" => 1000, "created" => 1455593353, "currency" => "usd",
"id" => "regular", "interval" => "month", "interval_count" => 1,
"livemode" => false, "metadata" => %{}, "name" => "REGULAR",
"object" => "plan", "statement_descriptor" => nil,
"trial_period_days" => 15}, "quantity" => 1, "start" => 1455736418,
"status" => "trialing", "tax_percent" => nil, "trial_end" => 1457032418,
"trial_start" => 1455736418}}
iex(4)> Extripe.Subscription.delete "sub_7vRdUiQQhv3M7u"
{:ok,
%{"application_fee_percent" => nil,
"cancel_at_period_end" => false, "canceled_at" => 1455736452,
"current_period_end" => 1457032418, "current_period_start" => 1455736418,
"customer" => "cus_7vNk0duWVulcPe", "discount" => nil,
"ended_at" => 1455736452, "id" => "sub_7vRdUiQQhv3M7u", "metadata" => %{},
"object" => "subscription",
"plan" => %{"amount" => 1000, "created" => 1455593353, "currency" => "usd",
"id" => "regular", "interval" => "month", "interval_count" => 1,
"livemode" => false, "metadata" => %{}, "name" => "REGULAR",
"object" => "plan", "statement_descriptor" => nil,
"trial_period_days" => 15}, "quantity" => 1, "start" => 1455736418,
"status" => "canceled", "tax_percent" => nil, "trial_end" => 1457032418,
"trial_start" => 1455736418}}
```
#### Pagination
```elixir
iex(1)> Extripe.Plan.index starting_after: "regular_au"
{:ok,
%{"data" => [%{"amount" => 1000, "created" => 1455593353, "currency" => "usd",
"id" => "regular", "interval" => "month", "interval_count" => 1,
"livemode" => false, "metadata" => %{}, "name" => "REGULAR",
"object" => "plan", "statement_descriptor" => nil,
"trial_period_days" => 15}], "has_more" => false, "object" => "list",
"url" => "/v1/plans"}}
iex(2)> Extripe.Plan.index ending_before: "regular_au"
{:ok,
%{"data" => [%{"amount" => 1500,
"created" => 1455733031, "currency" => "gbp", "id" => "regular_gb",
"interval" => "month", "interval_count" => 1, "livemode" => false,
"metadata" => %{}, "name" => "Regular GB", "object" => "plan",
"statement_descriptor" => nil, "trial_period_days" => nil}],
"has_more" => false, "object" => "list", "url" => "/v1/plans"}}
iex(3)> Extripe.Plan.index limit: 1
{:ok,
%{"data" => [%{"amount" => 1500,
"created" => 1455733031, "currency" => "gbp", "id" => "regular_gb",
"interval" => "month", "interval_count" => 1, "livemode" => false,
"metadata" => %{}, "name" => "Regular GB", "object" => "plan",
"statement_descriptor" => nil, "trial_period_days" => nil}],
"has_more" => true, "object" => "list", "url" => "/v1/plans"}}
iex(4)> {:ok, events} = Extripe.Event.index created: [lt: 1455733031]
{:ok,
%{"data" => [%{"api_version" => "2016-02-03", "created" => 1455732840,
"data" => %{"object" => %{"amount" => 1000, "created" => 1455593353,
"currency" => "usd", "id" => "regular", "interval" => "month",
"interval_count" => 1, "livemode" => false, "metadata" => %{},
"name" => "REGULAR", "object" => "plan",
"statement_descriptor" => nil, "trial_period_days" => 15},
"previous_attributes" => %{"name" => "Regular"}},
"id" => "evt_17fZoKEhB5xMvgQ7Fdl7krpl", "livemode" => false,
"object" => "event", "pending_webhooks" => 0,
"request" => "req_7vQfTWcjfnH7JW", "type" => "plan.updated"},
%{"api_version" => "2016-02-03", "created" => 1455732634,
"data" => %{"object" => %{"amount" => 1500, "created" => 1455730831,
"currency" => "gbp", "id" => "regular_gb", "interval" => "month",
"interval_count" => 1, "livemode" => false, "metadata" => %{},
"name" => "REGULAR GB", "object" => "plan",
"statement_descriptor" => nil, "trial_period_days" => nil}},
"id" => "evt_17fZl0EhB5xMvgQ7Ekqu42UQ", "livemode" => false,
"object" => "event", "pending_webhooks" => 0,
"request" => "req_7vQc2AYrZYzkv3", "type" => "plan.deleted"},
%{"api_version" => "2016-02-03", "created" => 1455732348,
"data" => %{"object" => %{"application_fee_percent" => nil,
"cancel_at_period_end" => false, "canceled_at" => 1455732348,
"current_period_end" => 1457027674,
"current_period_start" => 1455731674,
"customer" => "cus_7vNk0duWVulcPe", "discount" => nil,
"ended_at" => 1455732348, "id" => "sub_7vQMcLg9Qvbuzn",
"metadata" => %{}, "object" => "subscription",
"plan" => %{"amount" => 1000, "created" => 1455593353,
"currency" => "usd", "id" => "regular", "interval" => "month",
"interval_count" => 1, "livemode" => false, "metadata" => %{},
"name" => "Regular", "object" => "plan",
"statement_descriptor" => nil, "trial_period_days" => 15},
"quantity" => 1, "start" => 1455731674, "status" => "canceled",
"tax_percent" => nil, "trial_end" => 1457027674,
"trial_start" => 1455731674}}, "id" => "evt_17fZgOEhB5xMvgQ750S7kXaH",
"livemode" => false, "object" => "event", "pending_webhooks" => 0,
"request" => "req_7vQXJ6d8hVgjA5",
"type" => "customer.subscription.deleted"},
...]}}
iex(5)> {:ok, events} = Extripe.Event.index created: [gt: 1455733031]
# similar to the previous one
# and you also have gte, lte
# or you could just specify an integer unix timestamp for :created instead of a map or a keyword list
```
## Contributing
```elixir
# Adding a new resource
defmodule Extripe.NewResource do
# normal resource
# note: new_resource is probably plural
use Extripe.Actions.CRUD, resource: "new_resource"
# not fully CRUDable resource
use Extripe.Actions.CRUD, only: [:index, :show], resource: "new_resource"
# or
use Extripe.Actions.CRUD, except: [:delete], resource: "new_resource"
# nested resource
# when the scoping resource is plural, e.g. /v1/customers/customer_id/subscriptions
use Extripe.Actions.CRUD, scope: "customers", resource: "subscriptions"
# when the scoping resource is singular, e.g. /v1/balance/history
use Extripe.Actions.CRUD, scope: {"balance", :singular}, resource: "history"
# singluar resource
# currently only Balance is of this kind, /v1/balance
use Extripe.Actions.CRUD, only: [:show], resource: "balance", singular: true
# special case implementations
def pay(id), do: # pay bill
# special CRUD implementations
def list do
# special implementation of list
end
end
```