Skip to content

Commit

Permalink
Merge pull request #6 from htdc/feature/runtime-api-key-config
Browse files Browse the repository at this point in the history
[BREAKING] Allow API key on a per request basis
  • Loading branch information
mfeckie authored Jul 30, 2018
2 parents 7b7c885 + 157205b commit f7ff243
Show file tree
Hide file tree
Showing 24 changed files with 275 additions and 240 deletions.
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,33 @@ Documentation a (HexDocs)[https://hexdocs.pm/pinxs/]
```elixir
def deps do
[
{:pinxs, "~> 0.1.3"}
{:pinxs, "~> 1.0.0"}
]
end
```

You will also need to add your API key to your config.
Configure the endpoint you wish to use

```elixir
config :pinxs,
api_key: "${PIN_PAYMENTS_API_KEY}",
pin_url: "https://api.pinpayments.com" # or "https://test-api.pin.net.au/1" in test environment
pin_url: "https://api.pinpayments.com" # or "https://test-api.pin.net.au/1" in dev/test environment
```

You will also need to use your API key for authenticating each type of request.

## Overview

All responses are transformed to return `{:ok, item(s)}` or `{:error, PINX.Error}`
All requests must provide your API key. The helper `PINXS.config("YOUR KEY")`. The reason this is done on a per
request basis, rather than a global configuration is to allow changes at runtime on a per request basis.

All responses are transformed to return `{:ok, item(s)}` or `{:error, PINXS.Error}`

This enables us to leverage pattern matching and the `with` construct very nicely.

### Example charge creation

```elixir
order = Order.create(#...)
order = Order.create(...)

card = %Card{
number: "5520000000000000",
Expand All @@ -60,7 +64,7 @@ This enables us to leverage pattern matching and the `with` construct very nicel
}

with {:ok, created_order} <- Repo.insert(order),
{:ok, created_charge} <- Charge.create(charge),
{:ok, created_charge} <- Charge.create(charge, PINXS.config("MY API KEY")),
{:ok, paid_order} <- Order.mark_paid(created_order, created_charge),
{:ok, _email} <- Mailer.send("receipt", created_charge),
{:ok, _email} <- Mailer.send("notify_fulfullment_team", order)
Expand Down
4 changes: 0 additions & 4 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
use Mix.Config

if Mix.env() == :test do
config :pinxs,
api_key: System.get_env("PIN_API_KEY"),
pin_url: "https://test-api.pin.net.au/1"

config :exvcr,
vcr_cassette_library_dir: "test/http_recordings",
filter_request_headers: ["Authorization"]
Expand Down
6 changes: 3 additions & 3 deletions lib/balance.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ defmodule PINXS.Balance do
@doc """
Retrieves your balance information
"""
@spec get() :: {:ok, Balance.t()} | {:error, PINXS.Error.t()}
def get() do
API.get("/balance", __MODULE__)
@spec get(PINXS.t()) :: {:ok, Balance.t()} | {:error, PINXS.Error.t()}
def get(%PINXS{} = config) do
API.get("/balance", __MODULE__, config)
end
end
6 changes: 3 additions & 3 deletions lib/bank_accounts/bank_account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ defmodule PINXS.BankAccounts.BankAccount do
@doc """
Create a bank account
"""
@spec create(BankAccount.t) :: {:ok, BankAccount.t} | {:error, PINXS.Error.t}
def create(%BankAccount{} = bank_account) do
API.post("/bank_accounts", bank_account, __MODULE__)
@spec create(BankAccount.t(), PINXS.t()) :: {:ok, BankAccount.t} | {:error, PINXS.Error.t}
def create(%BankAccount{} = bank_account, %PINXS{} = config) do
API.post("/bank_accounts", bank_account, __MODULE__, config)
end
end
6 changes: 3 additions & 3 deletions lib/cards/card.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ defmodule PINXS.Cards.Card do
@doc """
Creates a tokenized credit card
"""
@spec create(Card.t()) :: {:ok, Card.t()} | {:error, PINXS.Error.t()}
def create(%Card{} = card) do
API.post("/cards", card, __MODULE__)
@spec create(Card.t(), PINXS.t()) :: {:ok, Card.t()} | {:error, PINXS.Error.t()}
def create(%Card{} = card, %PINXS{} = config) do
API.post("/cards", card, __MODULE__, config)
end
end
51 changes: 28 additions & 23 deletions lib/charges/charge.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,13 @@ defmodule PINXS.Charges.Charge do
@doc """
Captures a previously authorized charge
"""
def capture(%Charge{token: token}, amount \\ %{}) do
API.put("/charges/#{token}/capture", amount, __MODULE__)
@spec capture(Charge.t, PINXS.t()) :: {:ok, Charge.t()} | {:error, PINXS.Error.t()}
def capture(%Charge{} = charge, %PINXS{} = config) do
capture(charge, %{}, config)
end

def capture(%Charge{token: token}, amount, %PINXS{} = config) do
API.put("/charges/#{token}/capture", amount, __MODULE__, config)
end

@doc """
Expand All @@ -84,43 +89,43 @@ defmodule PINXS.Charges.Charge do
"""
@spec create(Charge.t()) :: {:ok, Charge.t()} | {:error, PINXS.Error.t()}
def create(%Charge{card: card} = charge_map) when not is_nil(card),
do: create_charge(charge_map)
@spec create(Charge.t(), PINXS.t()) :: {:ok, Charge.t()} | {:error, PINXS.Error.t()}
def create(%Charge{card: card} = charge_map, %PINXS{} = config) when not is_nil(card),
do: create_charge(charge_map, config)

def create(%Charge{card_token: card_token} = charge_map) when not is_nil(card_token),
do: create_charge(charge_map)
def create(%Charge{card_token: card_token} = charge_map, config) when not is_nil(card_token),
do: create_charge(charge_map, config)

def create(%Charge{customer_token: customer_token} = charge_map)
def create(%Charge{customer_token: customer_token} = charge_map, config)
when not is_nil(customer_token),
do: create_charge(charge_map)
do: create_charge(charge_map, config)

defp create_charge(charge_map) do
API.post("/charges", charge_map, __MODULE__)
defp create_charge(charge_map, config) do
API.post("/charges", charge_map, __MODULE__, config)
end

@doc """
Retrieves a paginated list of charges
"""
@spec get_all() :: {:ok, [Charge.t()]} | {:error, PINXS.Error.t}
def get_all() do
API.get("/charges", __MODULE__)
@spec get_all(PINXS.t()) :: {:ok, [Charge.t()]} | {:error, PINXS.Error.t}
def get_all(%PINXS{} = config) do
API.get("/charges", __MODULE__, config)
end

@doc """
Retrieves a specific pages of charges
"""
@spec get_all(integer()) :: {:ok, [Charge.t()]} | {:error, PINXS.Error.t}
def get_all(page) do
API.get("/charges?page=#{page}", __MODULE__)
@spec get_all(integer(), PINXS.t()) :: {:ok, [Charge.t()]} | {:error, PINXS.Error.t}
def get_all(page, %PINXS{} = config) do
API.get("/charges?page=#{page}", __MODULE__, config)
end

@doc """
Retrieves a single charge
"""
@spec get(String.t()) :: {:ok, Charge.t()} | {:error, PINXS.Error.t()}
def get(token) do
API.get("/charges/#{token}", __MODULE__)
@spec get(String.t(), PINXS.t()) :: {:ok, Charge.t()} | {:error, PINXS.Error.t()}
def get(token, %PINXS{} = config) do
API.get("/charges/#{token}", __MODULE__, config)
end

@doc """
Expand All @@ -138,8 +143,8 @@ defmodule PINXS.Charges.Charge do
```
"""

@spec search(map()) :: {:ok, [Charge.t()]} | {:error, PINXS.Error.t()}
def search(query_map) do
API.search("/charges/search", query_map, __MODULE__)
@spec search(map(), PINXS.t()) :: {:ok, [Charge.t()]} | {:error, PINXS.Error.t()}
def search(query_map, %PINXS{} = config) do
API.search("/charges/search", query_map, __MODULE__, config)
end
end
72 changes: 36 additions & 36 deletions lib/customers/customer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,93 +37,93 @@ defmodule PINXS.Customers.Customer do
@doc """
Adds a card to a customer
"""
@spec add_card(Customer.t(), Card.t()) :: {:ok, Card.t()} | {:error, PINXS.Error.t()}
def add_card(%Customer{token: token}, %Card{} = card) do
API.post("/customers/#{token}/cards", card, Card)
@spec add_card(Customer.t(), Card.t(), PINXS.t()) :: {:ok, Card.t()} | {:error, PINXS.Error.t()}
def add_card(%Customer{token: token}, %Card{} = card, %PINXS{} = config) do
API.post("/customers/#{token}/cards", card, Card, config)
end

def add_card(%Customer{token: token}, card_token) when is_binary(card_token) do
API.post("/customers/#{token}/cards", %{card_token: card_token}, Card)
def add_card(%Customer{token: token}, card_token, %PINXS{} = config) when is_binary(card_token) do
API.post("/customers/#{token}/cards", %{card_token: card_token}, Card, config)
end

@doc """
Creates a customer
"""
@spec create(Customer.t()) :: {:ok, Customer.t()} | {:error | PINXS.Error.t()}
def create(%Customer{card: card} = customer) when not is_nil(card),
do: create_customer(customer)
@spec create(Customer.t(), PINXS.t()) :: {:ok, Customer.t()} | {:error | PINXS.Error.t()}
def create(%Customer{card: card} = customer, %PINXS{} = config) when not is_nil(card),
do: create_customer(customer, config)

def create(%Customer{card_token: card_token} = customer) when not is_nil(card_token),
do: create_customer(customer)
def create(%Customer{card_token: card_token} = customer, %PINXS{} = config) when not is_nil(card_token),
do: create_customer(customer, config)

defp create_customer(customer) do
API.post("/customers", customer, __MODULE__)
defp create_customer(customer, config) do
API.post("/customers", customer, __MODULE__, config)
end

@doc """
Deletes a customer
"""
@spec delete(Customer.t()) :: {:ok, true} | {:error, PINXS.Error.t()}
def delete(%Customer{token: token}) do
API.delete("/customers/#{token}", __MODULE__)
@spec delete(Customer.t(), PINXS.t()) :: {:ok, true} | {:error, PINXS.Error.t()}
def delete(%Customer{token: token}, %PINXS{} = config) do
API.delete("/customers/#{token}", __MODULE__, config)
end

@doc """
Deletes a card belonging to a customer
"""
@spec delete_card(Customer.t(), String.t()) ::
@spec delete_card(Customer.t(), String.t(), PINXS.t()) ::
{:ok, Customer.t()} | {:error, PINXS.Error.t()}
def delete_card(%Customer{token: token}, card_token) do
API.delete("/customers/#{token}/cards/#{card_token}", __MODULE__)
def delete_card(%Customer{token: token}, card_token, %PINXS{} = config) do
API.delete("/customers/#{token}/cards/#{card_token}", __MODULE__, config)
end

@doc """
Retreives a customer
"""
@spec get(String.t()) :: {:ok, Customer.t()} | {:error, PINXS.Error.t()}
def get(token) do
API.get("/customers/#{token}", __MODULE__)
@spec get(String.t(), PINXS.t()) :: {:ok, Customer.t()} | {:error, PINXS.Error.t()}
def get(token, %PINXS{} = config) do
API.get("/customers/#{token}", __MODULE__, config)
end

@doc """
Retrieves a paginated list of customers
"""
@spec get_all() :: {:ok, [Customer.t()]} | {:error, PINXS.Error.t()}
def get_all() do
API.get("/customers", __MODULE__)
@spec get_all(PINXS.t()) :: {:ok, [Customer.t()]} | {:error, PINXS.Error.t()}
def get_all(%PINXS{} = config) do
API.get("/customers", __MODULE__, config)
end

@doc """
Retreives a specific page of customers
"""
@spec get_all(integer()) :: {:ok, [Customer.t()]} | {:error, PINXS.Error.t()}
def get_all(page) when is_integer(page) do
API.get("/customers?page=#{page}", __MODULE__)
@spec get_all(integer(), PINXS.t()) :: {:ok, [Customer.t()]} | {:error, PINXS.Error.t()}
def get_all(page, %PINXS{} = config) when is_integer(page) do
API.get("/customers?page=#{page}", __MODULE__, config)
end

@doc """
Retrieves all cards for the given customer
"""
@spec get_cards(Customer.t()) :: {:ok, [Card.t()]} | {:error, PINXS.Error.t()}
def get_cards(%Customer{token: token}) do
API.get("/customers/#{token}/cards", Card)
@spec get_cards(Customer.t(), PINXS.t()) :: {:ok, [Card.t()]} | {:error, PINXS.Error.t()}
def get_cards(%Customer{token: token}, %PINXS{} = config) do
API.get("/customers/#{token}/cards", Card, config)
end

@doc """
Retrieves all charges for customer
"""
@spec get_charges(Customer.t()) :: {:ok, [Charge.t]} | {:error, PINXS.Error.t()}
def get_charges(%Customer{token: token}) do
API.get("/customers/#{token}/charges", PINXS.Charges.Charge)
@spec get_charges(Customer.t(), PINXS.t()) :: {:ok, [Charge.t]} | {:error, PINXS.Error.t()}
def get_charges(%Customer{token: token}, %PINXS{} = config) do
API.get("/customers/#{token}/charges", PINXS.Charges.Charge, config)
end

# TODO Add 'Subscriptions'

@doc """
Updates a customer
"""
@spec update(Customer.t(), map()) :: {:ok, Customer.t()} | {:error, PINXS.Error.t()}
def update(%Customer{token: token}, params) when not is_nil(token) do
API.put("/customers/#{token}", params, __MODULE__)
@spec update(Customer.t(), map(), PINXS.t) :: {:ok, Customer.t()} | {:error, PINXS.Error.t()}
def update(%Customer{token: token}, params, %PINXS{} = config) when not is_nil(token) do
API.put("/customers/#{token}", params, __MODULE__, config)
end
end
24 changes: 15 additions & 9 deletions lib/http/api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,19 @@ defmodule PINXS.HTTP.API do
are available where extreme customisation is desired
"""

def delete(url), do: Client.delete(url)
def delete(url, module), do: delete(url) |> Response.transform(module)
def get(url), do: Client.get(url)
def get(url, module), do: get(url) |> Response.transform(module)
def search(url, params, module), do: Client.get(url, params) |> Response.transform(module)
def post(url, params), do: Client.post(url, params)
def post(url, params, module), do: post(url, params) |> Response.transform(module)
def put(url, params), do: Client.put(url, params)
def put(url, params, module), do: put(url, params) |> Response.transform(module)
def delete(url, config), do: Client.authenticated_delete(url, config)
def delete(url, module, config), do: delete(url, config) |> Response.transform(module)
def get(url, config), do: Client.authenticated_get(url, config)
def get(url, module, config), do: Client.authenticated_get(url, config) |> Response.transform(module)

def search(url, params, module, config),
do: Client.authenticated_search(url, params, config) |> Response.transform(module)

def post(url, params, config), do: Client.authenticated_post(url, params, config)

def post(url, params, module, config),
do: post(url, params, config) |> Response.transform(module)

def put(url, params, config), do: Client.authenticated_put(url, params, config)
def put(url, params, module, config), do: put(url, params, config) |> Response.transform(module)
end
Loading

0 comments on commit f7ff243

Please sign in to comment.