diff --git a/.travis.yml b/.travis.yml index b9e7c7baa..e7f47d360 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,3 +31,6 @@ before_install: script: mix coveralls.travis after_script: - mix inch.report +notifications: + email: + on_success: never diff --git a/lib/stripe/connect/account.ex b/lib/stripe/connect/account.ex index f6a131234..b28f9b2d9 100644 --- a/lib/stripe/connect/account.ex +++ b/lib/stripe/connect/account.ex @@ -185,11 +185,7 @@ defmodule Stripe.Account do decline_charge_on: decline_charge_on | nil, default_currency: String.t() | nil, email: String.t() | nil, - external_account: - Stripe.ExternalAccount.create_params_for_bank_account() - | Stripe.ExternalAccount.create_params_for_card() - | String.t() - | nil, + external_account: String.t() | nil, legal_entity: legal_entity, metadata: Stripe.Types.metadata() | nil, payout_schedule: Stripe.Types.transfer_schedule() | nil, @@ -253,11 +249,7 @@ defmodule Stripe.Account do decline_charge_on: decline_charge_on | nil, default_currency: String.t() | nil, email: String.t() | nil, - external_account: - Stripe.ExternalAccount.create_params_for_bank_account() - | Stripe.ExternalAccount.create_params_for_card() - | String.t() - | nil, + external_account: String.t() | nil, legal_entity: legal_entity, metadata: Stripe.Types.metadata() | nil, payout_schedule: Stripe.Types.transfer_schedule() | nil, diff --git a/lib/stripe/connect/external_account.ex b/lib/stripe/connect/external_account.ex index 1a9f9ff2e..0f47c9b6a 100644 --- a/lib/stripe/connect/external_account.ex +++ b/lib/stripe/connect/external_account.ex @@ -9,104 +9,109 @@ defmodule Stripe.ExternalAccount do - Update an external account - Delete an external account - Does not yet render lists or take options. - - Probably does not yet work for credit cards. - Stripe API reference: https://stripe.com/docs/api#external_accounts """ - alias Stripe.Util + import Stripe.Request - defp endpoint(managed_account_id) do - "accounts/#{managed_account_id}/external_accounts" + defp accounts_plural_endpoint(%{account: id}) do + "accounts/" <> id <> "/external_accounts" end @type t :: Stripe.BankAccount.t() | Stripe.Card.t() @type create_params :: %{ - external_account: - create_params_for_bank_account - | create_params_for_card - | String.t(), default_for_currency: boolean | nil, + external_account: String.t(), metadata: Stripe.Types.metadata() | nil } - @type create_params_for_bank_account :: %{ - object: String.t(), - account_number: String.t(), - country: String.t(), - currency: String.t(), - account_holder_name: String.t() | nil, - account_holder_type: String.t() | nil, - routing_number: String.t() | nil - } - - @type create_params_for_card :: %{ - object: String.t(), - exp_month: String.t(), - exp_year: String.t(), - number: String.t(), - address_city: String.t() | nil, - address_country: String.t() | nil, - address_line1: String.t() | nil, - address_line2: String.t() | nil, - address_state: String.t() | nil, - address_zip: String.t() | nil, - currency: String.t() | nil, - cvc: String.t() | nil, - default_for_currency: String.t() | nil, - metadata: Stripe.Types.metadata() | nil, - name: String.t() | nil - } - @doc """ Create an external account. + + Only accepts a `token` and not a hash of values. """ - @spec create(map, Keyword.t()) :: {:ok, t} | {:error, Stripe.api_error_struct()} - def create(changes, opts = [connect_account: managed_account_id]) do - endpoint = endpoint(managed_account_id) - Stripe.Request.create(endpoint, changes, opts) + @spec create(map, Keyword.t()) :: {:ok, t} | {:error, Stripe.Error.t()} + def create(%{account: _, token: token} = params, opts \\ []) do + endpoint = params |> accounts_plural_endpoint() + + updated_params = + params + |> Map.put(:external_account, token) + |> Map.delete(:token) + |> Map.delete(:account) + + new_request(opts) + |> put_endpoint(endpoint) + |> put_params(updated_params) + |> put_method(:post) + |> make_request() end @doc """ Retrieve an external account. """ - @spec retrieve(String.t(), Keyword.t()) :: {:ok, t} | {:error, Stripe.api_error_struct()} - def retrieve(id, opts = [connect_account: managed_account_id]) do - endpoint = endpoint(managed_account_id) <> "/" <> id - Stripe.Request.retrieve(endpoint, opts) + @spec retrieve(Stripe.id() | t, map, Stripe.options()) :: {:ok, t} | {:error, Stripe.Error.t()} + def retrieve(id, %{account: _} = params, opts \\ []) do + endpoint = params |> accounts_plural_endpoint() + + new_request(opts) + |> put_endpoint(endpoint <> "/#{get_id!(id)}") + |> put_method(:get) + |> make_request() end @doc """ Update an external account. - - Takes the `id` and a map of changes. """ - @spec update(String.t(), map, list) :: {:ok, t} | {:error, Stripe.api_error_struct()} - def update(id, changes, opts = [connect_account: managed_account_id]) do - endpoint = endpoint(managed_account_id) <> "/" <> id - Stripe.Request.update(endpoint, changes, opts) + @spec update(Stripe.id() | t, map, Stripe.options()) :: {:ok, t} | {:error, Stripe.Error.t()} + def update(id, %{account: _} = params, opts \\ []) do + endpoint = params |> accounts_plural_endpoint() + + new_request(opts) + |> put_endpoint(endpoint <> "/#{get_id!(id)}") + |> put_method(:post) + |> put_params(params |> Map.delete(:account)) + |> make_request() end @doc """ Delete an external account. """ - @spec delete(t | String.t(), list) :: :ok | {:error, Stripe.api_error_struct()} - def delete(account, opts = [connect_account: managed_account_id]) do - id = Util.normalize_id(account) - endpoint = endpoint(managed_account_id) <> "/" <> id - Stripe.Request.delete(endpoint, %{}, opts) + @spec delete(Stripe.id() | t, map, Stripe.options()) :: {:ok, t} | {:error, Stripe.Error.t()} + def delete(id, %{account: _} = params, opts \\ []) do + endpoint = params |> accounts_plural_endpoint() + + new_request(opts) + |> put_endpoint(endpoint <> "/#{get_id!(id)}") + |> put_method(:delete) + |> make_request() end @doc """ List all external accounts. + + Takes either `:bank_account` or `:card` to determine which object to list. """ - @spec list(map, Keyword.t()) :: {:ok, Stripe.List.t()} | {:error, Stripe.api_error_struct()} - def list(params \\ %{}, opts = [connect_account: managed_account_id]) do - endpoint = endpoint(managed_account_id) - params = Map.merge(params, %{"object" => "bank_account"}) - Stripe.Request.retrieve(params, endpoint, opts) + @spec list(atom, map, Stripe.options()) :: {:ok, Stripe.List.of(t)} | {:error, Stripe.Error.t()} + def list(atom, params, opts \\ []) + def list(:bank_account, %{account: _} = params, opts) do + endpoint = params |> accounts_plural_endpoint() + params = params |> Map.put(:object, "bank_account") + do_list(endpoint, params, opts) + end + def list(:card, %{account: _} = params, opts) do + endpoint = params |> accounts_plural_endpoint() + params = params |> Map.put(:object, "card") + do_list(endpoint, params, opts) + end + + @spec do_list(String.t, map, Stripe.options()) :: {:ok, Stripe.List.of(t)} | {:error, Stripe.Error.t()} + defp do_list(endpoint, params, opts) do + new_request(opts) + |> put_endpoint(endpoint) + |> put_method(:get) + |> put_params(params |> Map.delete(:account)) + |> make_request() end end diff --git a/test/stripe/connect/external_account_test.exs b/test/stripe/connect/external_account_test.exs new file mode 100644 index 000000000..a85b73a67 --- /dev/null +++ b/test/stripe/connect/external_account_test.exs @@ -0,0 +1,65 @@ +defmodule Stripe.ExternalAccountTest do + use Stripe.StripeCase, async: true + + describe "create/2" do + test "creates a bank account for an account" do + assert {:ok, _} = Stripe.ExternalAccount.create(%{account: "acct_123", token: "tok_stripetestbank"}) + assert_stripe_requested(:post, "/v1/accounts/acct_123/external_accounts") + end + + test "creates a card for an account" do + assert {:ok, _} = Stripe.ExternalAccount.create(%{account: "acct_123", token: "tok_amex"}) + assert_stripe_requested(:post, "/v1/accounts/acct_123/external_accounts") + end + end + + describe "retrieve/2" do + test "retrieves a bank account" do + assert {:ok, _} = Stripe.ExternalAccount.retrieve("ba_123", %{account: "acct_123"}) + assert_stripe_requested(:get, "/v1/accounts/acct_123/external_accounts/ba_123") + end + + test "retrieves a card" do + assert {:ok, _} = Stripe.ExternalAccount.retrieve("card_123", %{account: "acct_123"}) + assert_stripe_requested(:get, "/v1/accounts/acct_123/external_accounts/card_123") + end + end + + describe "update/2" do + test "updates a bank account" do + assert {:ok, _} = Stripe.ExternalAccount.update("ba_123", %{account: "acct_123"}) + assert_stripe_requested(:post, "/v1/accounts/acct_123/external_accounts/ba_123") + end + + test "updates a card" do + assert {:ok, _} = Stripe.ExternalAccount.update("card_123", %{account: "acct_123"}) + assert_stripe_requested(:post, "/v1/accounts/acct_123/external_accounts/card_123") + end + end + + describe "delete/2" do + test "deletes a bank account" do + assert {:ok, _} = Stripe.ExternalAccount.delete("ba_123", %{account: "acct_123"}) + assert_stripe_requested(:delete, "/v1/accounts/acct_123/external_accounts/ba_123") + end + + test "deletes a card" do + assert {:ok, _} = Stripe.ExternalAccount.delete("card_123", %{account: "acct_123"}) + assert_stripe_requested(:delete, "/v1/accounts/acct_123/external_accounts/card_123") + end + end + + describe "list/3" do + test "lists all bank accounts for an account" do + assert {:ok, %Stripe.List{data: bank_accounts}} = Stripe.ExternalAccount.list(:bank_account, %{account: "acct_123"}) + assert_stripe_requested(:get, "/v1/accounts/acct_123/external_accounts?object=bank_account") + assert is_list(bank_accounts) + end + + test "lists all cards for an account" do + assert {:ok, %Stripe.List{data: cards}} = Stripe.ExternalAccount.list(:card, %{account: "acct_123"}) + assert_stripe_requested(:get, "/v1/accounts/acct_123/external_accounts?object=card") + assert is_list(cards) + end + end +end