[
  {
    "path": ".gitignore",
    "content": "/_build\n/deps\nerl_crash.dump\n*.ez\nNOTES\ndocs\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: elixir\nelixir:\n  - 1.3.0\nenv: MIX_ENV=test\notp_release:\n  - 19.0\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\nCopyright (c) 2015 Joshua Nussbaum\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "Commerce.Billing\n=================\n[![Build Status](https://secure.travis-ci.org/joshnuss/commerce_billing.svg?branch=master\n\"Build Status\")](https://travis-ci.org/joshnuss/commerce_billing)\n\nPayment processing library for Elixir. Based on [Shopify's](http://shopify.com) [ActiveMerchant](http://github.com/Shopify/active_merchant) ruby gem\n\n## Supported Gateways\n\n- Bogus\n- Stripe\n\n## Advantages of Elixir\n\n- **Fault tolerant**: Each worker is supervised, so a new worker is started in the event of errors. Network errors are caught and payment is retried (not yet working).\n- **Distributed**: Run workers on different machines.\n- **Scalable**: Run multiple workers and adjust number of workers as needed.\n- **Throughput**: Takes advantage of all cores. For example on my laptop with 4 cores (2 threads per core), I can do 100 authorizations with Stripe in 10 seconds. Thats 864,000 transactions per day. ebay does 1.4M/day.\n- **Hot code swap**: Update code while the system is running\n\n## Card processing example\n\n```elixir\nalias Commerce.Billing\nalias Billing.{CreditCard, Address, Worker, Gateways}\n\nconfig = %{credentials: {\"sk_test_BQokikJOvBiI2HlWgH4olfQ2\", \"\"},\n           default_currency: \"USD\"}\n\nWorker.start_link(Gateways.Stripe, config, name: :my_gateway)\n\ncard = %CreditCard{\n  name: \"John Smith\",\n  number: \"4242424242424242\",\n  expiration: {2017, 12},\n  cvc: \"123\"\n}\n\naddress = %Address{\n  street1: \"123 Main\",\n  city: \"New York\",\n  region: \"NY\",\n  country: \"US\",\n  postal_code: \"11111\"\n}\n\ncase Billing.authorize(:my_gateway, 199.95, card, billing_address: address,\n                                                   description: \"Amazing T-Shirt\") do\n  {:ok,    %{authorization: authorization}} ->\n    IO.puts(\"Payment authorized #{authorization}\")\n\n  {:error, %{code: :declined, reason: reason}} ->\n    IO.puts(\"Payment declined #{reason}\")\n\n  {:error, %{code: error}} ->\n    IO.puts(\"Payment error #{error}\")\nend\n```\n\n## Road Map\n\n- Support multiple gateways (PayPal, Stripe, Authorize.net, Braintree etc..)\n- Support gateways that bill directly and those that use html integrations.\n- Support recurring billing\n- Each gateway is hosted in a worker process and supervised.\n- Workers can be pooled. (using poolboy)\n- Workers can be spread on multiple nodes\n- The gateway is selected by first calling the \"Gateway Factory\" process. The \"Gateway Factory\" decides which gateway to use. Usually it will just be one type based on configuration setting in mix.exs (i.e. Stripe), but the Factory can be replaced with something fancier. It will enable scenarios like:\n    - Use one gateway for visa another for mastercard\n    - Use primary gateway (i.e PayPal), but when PayPal is erroring switch to secondary/backup gateway (i.e. Authorize.net)\n    - Currency specific gateway, i.e. use one gateway type for USD another for CAD\n- Retry on network failure\n\n## License\n\nMIT\n\n@joshnuss is a freelance software consultant. joshnuss@gmail.com\n"
  },
  {
    "path": "config/config.exs",
    "content": "# This file is responsible for configuring your application\n# and its dependencies. The Mix.Config module provides functions\n# to aid in doing so.\nuse Mix.Config\n\n# Note this file is loaded before any dependency and is restricted\n# to this project. If another project depends on this project, this\n# file won't be loaded nor affect the parent project.\n\n# Sample configuration:\n#\n#     config :my_dep,\n#       key: :value,\n#       limit: 42\n\n# It is also possible to import configuration files, relative to this\n# directory. For example, you can emulate configuration per environment\n# by uncommenting the line below and defining dev.exs, test.exs and such.\n# Configuration from the imported file will override the ones defined\n# here (which is why it is important to import them last).\n#\n#     import_config \"#{Mix.env}.exs\"\n"
  },
  {
    "path": "lib/commerce_billing/address.ex",
    "content": "defmodule Commerce.Billing.Address do\n  defstruct [:street1, :street2, :city, :region, :country, :postal_code, :phone]\nend\n"
  },
  {
    "path": "lib/commerce_billing/credit_card.ex",
    "content": "defmodule Commerce.Billing.CreditCard do\n  defstruct [:name, :number, :expiration, :cvc]\nend\n"
  },
  {
    "path": "lib/commerce_billing/gateways/base.ex",
    "content": "defmodule Commerce.Billing.Gateways.Base do\n  alias Commerce.Billing.Response\n\n  @doc false\n  defmacro __using__(_) do\n    quote location: :keep do\n      def purchase(_amount, _card_or_id, _opts)  do\n        not_implemented\n      end\n\n      def authorize(_amount, _card_or_id, _opts)  do\n        not_implemented\n      end\n\n      def capture(_id, _opts) do\n        not_implemented\n      end\n\n      def void(_id, _opts) do\n        not_implemented\n      end\n\n      def refund(_amount, _id, _opts) do\n        not_implemented\n      end\n\n      def store(_card, _opts) do\n        not_implemented\n      end\n\n      def unstore(_customer_id, _card_id, _opts) do\n        not_implemented\n      end\n\n      defp http(method, path, params \\\\ [], opts \\\\ []) do\n        credentials = Keyword.get(opts, :credentials)\n        headers     = [{\"Content-Type\", \"application/x-www-form-urlencoded\"}]\n        data        = params_to_string(params)\n\n        HTTPoison.request(method, path, data, headers, [hackney: [basic_auth: credentials]])\n      end\n\n      defp money_to_cents(amount) when is_float(amount) do\n        trunc(amount * 100)\n      end\n\n      defp money_to_cents(amount) do\n        amount\n      end\n\n      defp params_to_string(params) do\n        params |> Enum.filter(fn {_k, v} -> v != nil end)\n               |> URI.encode_query\n      end\n\n      @doc false\n      defp not_implemented do\n        {:error, Response.error(code: :not_implemented)}\n      end\n\n      defoverridable [purchase: 3, authorize: 3, capture: 2, void: 2, refund: 3, store: 2, unstore: 3]\n    end\n  end\nend\n"
  },
  {
    "path": "lib/commerce_billing/gateways/bogus.ex",
    "content": "defmodule Commerce.Billing.Gateways.Bogus do\n  use Commerce.Billing.Gateways.Base\n\n  alias Commerce.Billing.{\n    CreditCard,\n    Response\n  }\n\n  def authorize(_amount, _card_or_id, _opts),\n    do: success\n\n  def purchase(_amount, _card_or_id, _opts),\n    do: success\n\n  def capture(id, _opts),\n    do: success(id)\n\n  def void(id, _opts),\n    do: success(id)\n\n  def refund(_amount, id, _opts),\n    do: success(id)\n\n  def store(_card=%CreditCard{}, _opts),\n    do: success\n\n  def unstore(customer_id, nil, _opts),\n    do: success(customer_id)\n\n  def unstore(_customer_id, card_id, _opts),\n    do: success(card_id)\n\n  defp success,\n    do: {:ok, Response.success(authorization: random_string)}\n\n  defp success(id),\n    do: {:ok, Response.success(authorization: id)}\n\n  defp random_string(length \\\\ 10),\n    do: 1..length |> Enum.map(&random_char/1) |> Enum.join\n\n  defp random_char(_),\n    do: to_string(:crypto.rand_uniform(0,9))\nend\n"
  },
  {
    "path": "lib/commerce_billing/gateways/stripe.ex",
    "content": "defmodule Commerce.Billing.Gateways.Stripe do\n  @base_url \"https://api.stripe.com/v1\"\n\n  @cvc_code_translator %{\n    \"pass\" => \"M\",\n    \"fail\" => \"N\",\n    \"unchecked\" => \"P\"\n  }\n\n  @avs_code_translator %{\n    {\"pass\", \"pass\"} => \"Y\",\n    {\"pass\", \"fail\"} => \"A\",\n    {\"pass\", \"unchecked\"} => \"B\",\n    {\"fail\", \"pass\"} => \"Z\",\n    {\"fail\", \"fail\"} => \"N\",\n    {\"unchecked\", \"pass\"} => \"P\",\n    {\"unchecked\", \"unchecked\"} => \"I\"\n  }\n\n  use Commerce.Billing.Gateways.Base\n\n  alias Commerce.Billing.{\n    CreditCard,\n    Address,\n    Response\n  }\n\n  import Poison, only: [decode!: 1]\n\n  def purchase(amount, card_or_id, opts),\n    do: authorize(amount, card_or_id, [{:capture, true} | opts])\n\n  def authorize(amount, card_or_id, opts) do\n    config      = Keyword.fetch!(opts, :config)\n    description = Keyword.get(opts, :description)\n    address     = Keyword.get(opts, :billing_address)\n    customer_id = Keyword.get(opts, :customer_id)\n    currency    = Keyword.get(opts, :currency, config.default_currency)\n    capture     = Keyword.get(opts, :capture, false)\n\n    params = [capture: capture, description: description,\n              currency: currency, customer: customer_id] ++\n             amount_params(amount) ++\n             card_params(card_or_id) ++\n             address_params(address) ++\n             connect_params(opts)\n\n    commit(:post, \"charges\", params, opts)\n  end\n\n  def capture(id, opts) do\n    params = opts\n      |> Keyword.get(:amount)\n      |> amount_params\n\n    commit(:post, \"charges/#{id}/capture\", params, opts)\n  end\n\n  def void(id, opts),\n    do: commit(:post, \"charges/#{id}/refund\", [], opts)\n\n  def refund(amount, id, opts) do\n    params = amount_params(amount)\n\n    commit(:post, \"charges/#{id}/refund\", params, opts)\n  end\n\n  def store(card=%CreditCard{}, opts) do\n    customer_id = Keyword.get(opts, :customer_id)\n    params = card_params(card)\n\n    path = if customer_id, do: \"customers/#{customer_id}/card\", else: \"customers\"\n\n    commit(:post, path, params, opts)\n  end\n\n  def unstore(customer_id, nil, opts),\n    do: commit(:delete, \"customers/#{customer_id}\", [], opts)\n\n  def unstore(customer_id, card_id, opts),\n    do: commit(:delete, \"customers/#{customer_id}/#{card_id}\", [], opts)\n\n  defp amount_params(amount),\n    do: [amount: money_to_cents(amount)]\n\n  defp card_params(card=%CreditCard{}) do\n    {expiration_year, expiration_month} = card.expiration\n\n    [\"card[number]\":    card.number,\n     \"card[exp_year]\":  expiration_year,\n     \"card[exp_month]\": expiration_month,\n     \"card[cvc]\":       card.cvc,\n     \"card[name]\":      card.name]\n  end\n\n  defp card_params(id), do: [card: id]\n\n  defp address_params(address=%Address{}) do\n    [\"card[address_line1]\": address.street1,\n     \"card[address_line2]\": address.street2,\n     \"card[address_city]\":  address.city,\n     \"card[address_state]\": address.region,\n     \"card[address_zip]\":   address.postal_code,\n     \"card[address_country]\": address.country]\n  end\n\n  defp address_params(_), do: []\n\n  defp connect_params(opts),\n    do: Keyword.take(opts, [:destination, :application_fee])\n\n  defp commit(method, path, params, opts) do\n    config = Keyword.fetch!(opts, :config)\n\n    method\n      |> http(\"#{@base_url}/#{path}\", params, credentials: config.credentials)\n      |> respond\n  end\n\n  defp respond({:ok, %{status_code: 200, body: body}}) do\n    data = decode!(body)\n    {cvc_result, avs_result} = verification_result(data)\n\n    {:ok, Response.success(authorization: data[\"id\"], raw: data, cvc_result: cvc_result, avs_result: avs_result)}\n  end\n\n  defp respond({:ok, %{body: body, status_code: status_code}}) do\n    data = decode!(body)\n    {code, reason} = error(status_code, data[\"error\"])\n    {cvc_result, avs_result} = verification_result(data)\n\n    {:error, Response.error(code: code, reason: reason, raw: data, cvc_result: cvc_result, avs_result: avs_result)}\n  end\n\n  defp verification_result(%{\"card\" => card}) do\n    cvc_result = @cvc_code_translator[card[\"cvc_check\"]]\n    avs_result = @avs_code_translator[{card[\"address_line1_check\"], card[\"address_zip_check\"]}]\n\n    {cvc_result, avs_result}\n  end\n\n  defp verification_result(_), do: {\"N\",\"N\"}\n\n  defp error(status, _) when status >= 500,            do: {:server_error, nil}\n  defp error(_, %{\"type\" => \"invalid_request_error\"}), do: {:invalid_request, nil}\n  defp error(_, %{\"code\" => \"incorrect_number\"}),      do: {:declined, :invalid_number}\n  defp error(_, %{\"code\" => \"invalid_expiry_year\"}),   do: {:declined, :invalid_expiration}\n  defp error(_, %{\"code\" => \"invalid_expiry_month\"}),  do: {:declined, :invalid_expiration}\n  defp error(_, %{\"code\" => \"invalid_cvc\"}),           do: {:declined, :invalid_cvc}\n  defp error(_, %{\"code\" => \"rate_limit\"}),            do: {:rate_limit, nil}\n  defp error(_, _), do: {:declined, :unknown}\nend\n"
  },
  {
    "path": "lib/commerce_billing/response.ex",
    "content": "defmodule Commerce.Billing.Response do\n  defstruct [:success, :authorization, :code, :reason, :avs_result, :cvc_result, :raw]\n\n  def success(opts \\\\ []) do\n    new(true, opts)\n  end\n\n  def error(opts \\\\ []) do\n    new(false, opts)\n  end\n\n  defp new(success, opts) do\n    Map.merge(%__MODULE__{success: success}, Enum.into(opts, %{}))\n  end\nend\n"
  },
  {
    "path": "lib/commerce_billing/worker.ex",
    "content": "defmodule Commerce.Billing.Worker do\n  use GenServer\n\n  def start_link(gateway, config, opts \\\\ []) do\n    GenServer.start_link(__MODULE__, [gateway, config], opts)\n  end\n\n  def init([gateway, config]) do\n    {:ok, %{config: config, gateway: gateway}}\n  end\n\n  def handle_call({:authorize, amount, card, opts}, _from, state) do\n    response = state.gateway.authorize(amount, card, [{:config, state.config} | opts])\n    {:reply, response, state}\n  end\n\n  def handle_call({:purchase, amount, card, opts}, _from, state) do\n    response = state.gateway.purchase(amount, card, [{:config, state.config} | opts])\n    {:reply, response, state}\n  end\n\n  def handle_call({:capture, id, opts}, _from, state) do\n    response = state.gateway.capture(id, [{:config, state.config} | opts])\n    {:reply, response, state}\n  end\n\n  def handle_call({:void, id, opts}, _from, state) do\n    response = state.gateway.void(id, [{:config, state.config} | opts])\n    {:reply, response, state}\n  end\n\n  def handle_call({:refund, amount, id, opts}, _from, state) do\n    response = state.gateway.refund(amount, id, [{:config, state.config} | opts])\n    {:reply, response, state}\n  end\n\n  def handle_call({:store, card, opts}, _from, state) do\n    response = state.gateway.store(card, [{:config, state.config} | opts])\n    {:reply, response, state}\n  end\n\n  def handle_call({:unstore, customer_id, card_id, opts}, _from, state) do\n    response = state.gateway.unstore(customer_id, card_id, [{:config, state.config} | opts])\n    {:reply, response, state}\n  end\nend\n"
  },
  {
    "path": "lib/commerce_billing.ex",
    "content": "defmodule Commerce.Billing do\n  use Application\n\n  import GenServer, only: [call: 2]\n\n  # See http://elixir-lang.org/docs/stable/elixir/Application.html\n  # for more information on OTP Applications\n  def start(_type, _args) do\n    import Supervisor.Spec, warn: false\n\n    children = [\n      # Define workers and child supervisors to be supervised\n      # worker(Commerce.Billing.Worker, [arg1, arg2, arg3])\n    ]\n\n    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html\n    # for other strategies and supported options\n    opts = [strategy: :one_for_one, name: Commerce.Billing.Supervisor]\n    Supervisor.start_link(children, opts)\n  end\n\n  def authorize(worker, amount, card, opts \\\\ []),\n    do: call(worker, {:authorize, amount, card, opts})\n\n  def purchase(worker, amount, card, opts \\\\ []),\n    do: call(worker, {:purchase, amount, card, opts})\n\n  def capture(worker, id, opts \\\\ []),\n    do: call(worker, {:capture, id, opts})\n\n  def void(worker, id, opts \\\\ []),\n    do: call(worker, {:void, id, opts})\n\n  def refund(worker, amount, id, opts \\\\ []),\n    do: call(worker, {:refund, amount, id, opts})\n\n  def store(worker, card, opts \\\\ []),\n    do: call(worker, {:store, card, opts})\n\n  def unstore(worker, customer_id, card_id, opts \\\\ []),\n    do: call(worker, {:unstore, customer_id, card_id, opts})\nend\n"
  },
  {
    "path": "mix.exs",
    "content": "defmodule Commerce.Billing.Mixfile do\n  use Mix.Project\n\n  def project do\n    [app: :commerce_billing,\n     version: \"0.0.2\",\n     description: \"Credit card processing library\",\n     package: [\n       contributors: [\"Joshua Nussbaum\"],\n       licenses: [\"MIT\"],\n       links: %{github: \"https://github.com/joshnuss/commerce_billing\"}\n     ],\n     elixir: \">= 1.2.0\",\n     deps: deps]\n  end\n\n  # Configuration for the OTP application\n  #\n  # Type `mix help compile.app` for more information\n  def application do\n    [applications: [:httpoison, :hackney],\n     mod: {Commerce.Billing, []}]\n  end\n\n  # Dependencies can be hex.pm packages:\n  #\n  #   {:mydep, \"~> 0.3.0\"}\n  #\n  # Or git/path repositories:\n  #\n  #   {:mydep, git: \"https://github.com/elixir-lang/mydep.git\", tag: \"0.1\"}\n  #\n  # Type `mix help deps` for more examples and options\n  defp deps do\n    [{:poison, \"~> 3.0\"},\n     {:httpoison, \">= 0.7.1\"},\n     {:ex_doc, \">= 0.6.0\", only: :dev},\n     {:mock, \">= 0.1.0\", only: :test}]\n  end\nend\n"
  },
  {
    "path": "test/commerce_billing_test.exs",
    "content": "defmodule Commerce.BillingTest do\n  use ExUnit.Case\n\n  alias Commerce.Billing.Worker\n  import Commerce.Billing\n\n  defmodule FakeGateway do\n    def authorize(100, :card, _) do\n      :authorization_response\n    end\n\n    def purchase(100, :card, _) do\n      :purchase_response\n    end\n\n    def capture(1234, _) do\n      :capture_response\n    end\n\n    def void(1234, _) do\n      :void_response\n    end\n\n    def refund(100, 1234, _) do\n      :refund_response\n    end\n\n    def store(:card, _) do\n      :store_response\n    end\n\n    def unstore(123, 456, _) do\n      :unstore_response\n    end\n  end\n\n  setup do\n    {:ok, worker} = Worker.start_link(FakeGateway, :config)\n    {:ok, worker: worker}\n  end\n\n  test \"authorization\", %{worker: worker} do\n    assert authorize(worker, 100, :card, []) == :authorization_response\n  end\n\n  test \"purchase\", %{worker: worker} do\n    assert purchase(worker, 100, :card, []) == :purchase_response\n  end\n\n  test \"capture\", %{worker: worker} do\n    assert capture(worker, 1234, []) == :capture_response\n  end\n\n  test \"void\", %{worker: worker} do\n    assert void(worker, 1234, []) == :void_response\n  end\n\n  test \"refund\", %{worker: worker} do\n    assert refund(worker, 100, 1234, []) == :refund_response\n  end\n\n  test \"store\", %{worker: worker} do\n    assert store(worker, :card, []) == :store_response\n  end\n\n  test \"unstore\", %{worker: worker} do\n    assert unstore(worker, 123, 456, []) == :unstore_response\n  end\nend\n"
  },
  {
    "path": "test/gateways/bogus_test.exs",
    "content": "defmodule Commerce.Billing.Gateways.BogusTest do\n  use ExUnit.Case\n\n  alias Commerce.Billing.Response\n  alias Commerce.Billing.Gateways.Bogus, as: Gateway\n\n  test \"authorize\" do\n    {:ok, %Response{authorization: authorization, success: success}} =\n        Gateway.authorize(10.95, :card, [])\n\n    assert success\n    assert authorization != nil\n  end\n\n  test \"purchase\" do\n    {:ok, %Response{authorization: authorization, success: success}} =\n        Gateway.purchase(10.95, :card, [])\n\n    assert success\n    assert authorization != nil\n  end\n\n  test \"capture\" do\n    {:ok, %Response{authorization: authorization, success: success}} =\n        Gateway.capture(1234, [])\n\n    assert success\n    assert authorization != nil\n  end\n\n  test \"void\" do\n    {:ok, %Response{authorization: authorization, success: success}} =\n        Gateway.void(1234, [])\n\n    assert success\n    assert authorization != nil\n  end\n\n  test \"store\" do\n    {:ok, %Response{success: success}} =\n        Gateway.store(%Commerce.Billing.CreditCard{}, [])\n\n    assert success\n  end\n\n  test \"unstore with customer\" do\n    {:ok, %Response{success: success}} =\n        Gateway.unstore(1234, nil, [])\n\n    assert success\n  end\n\n  test \"unstore with card\" do\n    {:ok, %Response{success: success}} =\n        Gateway.unstore(nil, 456, [])\n\n    assert success\n  end\nend\n"
  },
  {
    "path": "test/gateways/stripe_test.exs",
    "content": "defmodule Commerce.Billing.Gateways.StripeTest do\n  use ExUnit.Case, async: false\n\n  import Mock\n\n  alias Commerce.Billing.{\n    CreditCard,\n    Address,\n    Response\n  }\n  alias Commerce.Billing.Gateways.Stripe, as: Gateway\n\n  defmacrop with_post(url, {status, response}, statement, do: block) do\n    quote do\n      {:ok, agent} = Agent.start_link(fn -> nil end)\n\n      requestFn = fn(:post, unquote(url), params, [{\"Content-Type\", \"application/x-www-form-urlencoded\"}], [hackney: [basic_auth: {'user', 'pass'}]]) ->\n        Agent.update(agent, fn(_) -> params end)\n        {:ok, %{status_code: unquote(status), body: unquote(response)}}\n      end\n\n      with_mock HTTPoison, [request: requestFn] do\n        unquote(statement)\n        var!(params) = Agent.get(agent, &(URI.decode_query(&1)))\n\n        unquote(block)\n\n        Agent.stop(agent)\n      end\n    end\n  end\n\n  defmacrop with_delete(url, {status, response}, do: block) do\n    quote do\n      requestFn = fn(:delete, unquote(url), params, [{\"Content-Type\", \"application/x-www-form-urlencoded\"}], [hackney: [basic_auth: {'user', 'pass'}]]) ->\n        {:ok, %{status_code: unquote(status), body: unquote(response)}}\n      end\n\n      with_mock HTTPoison, [request: requestFn], do: unquote(block)\n    end\n  end\n\n  setup do\n    config = %{credentials: {'user', 'pass'}, default_currency: \"USD\"}\n    {:ok, config: config}\n  end\n\n  test \"authorize success with credit card\", %{config: config} do\n    raw = ~S/\n      {\n        \"id\": \"1234\",\n        \"card\": {\n          \"cvc_check\": \"pass\",\n          \"address_line1_check\": \"unchecked\",\n          \"address_zip_check\": \"pass\"\n        }\n      }\n    /\n    card = %CreditCard{name: \"John Smith\", number: \"123456\", cvc: \"123\", expiration: {2015, 11}}\n    address = %Address{street1: \"123 Main\", street2: \"Suite 100\", city: \"New York\", region: \"NY\", country: \"US\", postal_code: \"11111\"}\n\n    with_post \"https://api.stripe.com/v1/charges\", {200, raw},\n        response = Gateway.authorize(10.95, card, billing_address: address, config: config) do\n\n      {:ok, %Response{authorization: authorization, success: success,\n                      avs_result: avs_result, cvc_result: cvc_result}} = response\n\n      assert success\n      assert params[\"capture\"] == \"false\"\n      assert params[\"currency\"] == \"USD\"\n      assert params[\"amount\"] == \"1095\"\n      assert params[\"card[name]\"] == \"John Smith\"\n      assert params[\"card[number]\"] == \"123456\"\n      assert params[\"card[exp_month]\"] == \"11\"\n      assert params[\"card[exp_year]\"] == \"2015\"\n      assert params[\"card[cvc]\"] == \"123\"\n      assert params[\"card[address_line1]\"] == \"123 Main\"\n      assert params[\"card[address_line2]\"] == \"Suite 100\"\n      assert params[\"card[address_city]\"] == \"New York\"\n      assert params[\"card[address_state]\"] == \"NY\"\n      assert params[\"card[address_country]\"] == \"US\"\n      assert params[\"card[address_zip]\"] == \"11111\"\n      assert authorization == \"1234\"\n      assert avs_result == \"P\"\n      assert cvc_result == \"M\"\n    end\n  end\n\n  test \"purchase success with credit card\", %{config: config} do\n    raw = ~S/\n      {\n        \"id\": \"1234\",\n        \"card\": {\n          \"cvc_check\": \"pass\",\n          \"address_line1_check\": \"unchecked\",\n          \"address_zip_check\": \"pass\"\n        }\n      }\n    /\n    card = %CreditCard{name: \"John Smith\", number: \"123456\", cvc: \"123\", expiration: {2015, 11}}\n    address = %Address{street1: \"123 Main\", street2: \"Suite 100\", city: \"New York\", region: \"NY\", country: \"US\", postal_code: \"11111\"}\n\n    with_post \"https://api.stripe.com/v1/charges\", {200, raw},\n        response = Gateway.purchase(10.95, card, billing_address: address, config: config) do\n\n      {:ok, %Response{authorization: authorization, success: success,\n                      avs_result: avs_result, cvc_result: cvc_result}} = response\n\n      assert success\n      assert params[\"capture\"] == \"true\"\n      assert params[\"currency\"] == \"USD\"\n      assert params[\"amount\"] == \"1095\"\n      assert params[\"card[name]\"] == \"John Smith\"\n      assert params[\"card[number]\"] == \"123456\"\n      assert params[\"card[exp_month]\"] == \"11\"\n      assert params[\"card[exp_year]\"] == \"2015\"\n      assert params[\"card[cvc]\"] == \"123\"\n      assert params[\"card[address_line1]\"] == \"123 Main\"\n      assert params[\"card[address_line2]\"] == \"Suite 100\"\n      assert params[\"card[address_city]\"] == \"New York\"\n      assert params[\"card[address_state]\"] == \"NY\"\n      assert params[\"card[address_country]\"] == \"US\"\n      assert params[\"card[address_zip]\"] == \"11111\"\n      assert authorization == \"1234\"\n      assert avs_result == \"P\"\n      assert cvc_result == \"M\"\n    end\n  end\n\n  test \"purchase success with credit card to a Connect account\", %{config: config} do\n    raw = ~S/\n      {\n        \"id\": \"1234\",\n        \"card\": {\n          \"cvc_check\": \"pass\",\n          \"address_line1_check\": \"unchecked\",\n          \"address_zip_check\": \"pass\"\n        }\n      }\n    /\n    card = %CreditCard{name: \"John Smith\", number: \"123456\", cvc: \"123\", expiration: {2015, 11}}\n    address = %Address{street1: \"123 Main\", street2: \"Suite 100\", city: \"New York\", region: \"NY\", country: \"US\", postal_code: \"11111\"}\n    destination = \"stripe_id\"\n    application_fee = 123\n\n    with_post \"https://api.stripe.com/v1/charges\", {200, raw},\n        response = Gateway.purchase(10.95, card, billing_address: address, config: config, destination: destination, application_fee: application_fee) do\n\n      {:ok, %Response{authorization: authorization, success: success,\n                      avs_result: avs_result, cvc_result: cvc_result}} = response\n\n      assert success\n      assert params[\"capture\"] == \"true\"\n      assert params[\"currency\"] == \"USD\"\n      assert params[\"amount\"] == \"1095\"\n      assert params[\"card[name]\"] == \"John Smith\"\n      assert params[\"card[number]\"] == \"123456\"\n      assert params[\"card[exp_month]\"] == \"11\"\n      assert params[\"card[exp_year]\"] == \"2015\"\n      assert params[\"card[cvc]\"] == \"123\"\n      assert params[\"card[address_line1]\"] == \"123 Main\"\n      assert params[\"card[address_line2]\"] == \"Suite 100\"\n      assert params[\"card[address_city]\"] == \"New York\"\n      assert params[\"card[address_state]\"] == \"NY\"\n      assert params[\"card[address_country]\"] == \"US\"\n      assert params[\"card[address_zip]\"] == \"11111\"\n      assert params[\"destination\"] == destination\n      assert params[\"application_fee\"] == \"123\"\n      assert authorization == \"1234\"\n      assert avs_result == \"P\"\n      assert cvc_result == \"M\"\n    end\n  end\n\n  test \"capture success\", %{config: config} do\n    raw = ~S/{\"id\": \"1234\"}/\n\n    with_post \"https://api.stripe.com/v1/charges/1234/capture\", {200, raw},\n        response = Gateway.capture(1234, amount: 19.95, config: config) do\n\n      {:ok, %Response{authorization: authorization, success: success}} = response\n\n      assert success\n      assert params[\"amount\"] == \"1995\"\n      assert authorization == \"1234\"\n    end\n  end\n\n  test \"void success\", %{config: config} do\n    raw = ~S/{\"id\": \"1234\"}/\n\n    with_post \"https://api.stripe.com/v1/charges/1234/refund\", {200, raw},\n        response = Gateway.void(1234, config: config) do\n\n      {:ok, %Response{authorization: authorization, success: success}} = response\n\n      assert success\n      assert params[\"amount\"] == nil\n      assert authorization == \"1234\"\n    end\n  end\n\n  test \"refund success\", %{config: config} do\n    raw = ~S/{\"id\": \"1234\"}/\n\n    with_post \"https://api.stripe.com/v1/charges/1234/refund\", {200, raw},\n        response = Gateway.refund(19.95, 1234, config: config) do\n\n      {:ok, %Response{authorization: authorization, success: success}} = response\n\n      assert success\n      assert params[\"amount\"] == \"1995\"\n      assert authorization == \"1234\"\n    end\n  end\n\n  test \"store credit card without customer\", %{config: config} do\n    raw = ~S/{\"id\": \"1234\"}/\n    card = %CreditCard{name: \"John Smith\", number: \"123456\", cvc: \"123\", expiration: {2015, 11}}\n\n    with_post \"https://api.stripe.com/v1/customers\", {200, raw},\n        response = Gateway.store(card, config: config) do\n\n      {:ok, %Response{authorization: authorization, success: success}} = response\n\n      assert success\n      assert params[\"card[name]\"] == \"John Smith\"\n      assert params[\"card[number]\"] == \"123456\"\n      assert params[\"card[exp_month]\"] == \"11\"\n      assert params[\"card[exp_year]\"] == \"2015\"\n      assert params[\"card[cvc]\"] == \"123\"\n      assert authorization == \"1234\"\n    end\n  end\n\n  test \"store credit card with customer\", %{config: config} do\n    raw = ~S/{\"id\": \"1234\"}/\n    card = %CreditCard{name: \"John Smith\", number: \"123456\", cvc: \"123\", expiration: {2015, 11}}\n\n    with_post \"https://api.stripe.com/v1/customers/1234/card\", {200, raw},\n        response = Gateway.store(card, customer_id: 1234, config: config) do\n\n      {:ok, %Response{authorization: authorization, success: success}} = response\n\n      assert success\n      assert params[\"card[name]\"] == \"John Smith\"\n      assert params[\"card[number]\"] == \"123456\"\n      assert params[\"card[exp_month]\"] == \"11\"\n      assert params[\"card[exp_year]\"] == \"2015\"\n      assert params[\"card[cvc]\"] == \"123\"\n      assert authorization == \"1234\"\n    end\n  end\n\n  test \"unstore credit card\", %{config: config} do\n    with_delete \"https://api.stripe.com/v1/customers/123/456\", {200, \"{}\"} do\n      {:ok, %Response{success: success}} = Gateway.unstore(123, 456, config: config)\n\n      assert success\n    end\n  end\n\n  test \"unstore customer\", %{config: config} do\n    with_delete \"https://api.stripe.com/v1/customers/123\", {200, \"{}\"} do\n      {:ok, %Response{success: success}} = Gateway.unstore(123, nil, config: config)\n\n      assert success\n    end\n  end\nend\n"
  },
  {
    "path": "test/test_helper.exs",
    "content": "ExUnit.start()\n"
  }
]