diff --git a/lib/gringotts/gateways/mercadopago.ex b/lib/gringotts/gateways/mercadopago.ex index 0e52ec93..653a608c 100644 --- a/lib/gringotts/gateways/mercadopago.ex +++ b/lib/gringotts/gateways/mercadopago.ex @@ -156,6 +156,39 @@ defmodule Gringotts.Gateways.Mercadopago do end end + @doc """ + Captures a pre-authorized `amount`. + + `amount` is transferred to the merchant account by mercadopago used in the + pre-authorization referenced by `payment_id`. + + ## Note + mercadopago allows partial captures also. However, you can make a partial capture to a payment only **once**. + + > The authorization will be valid for 7 days. If you do not capture it by that time, it will be cancelled. + + > The specified amount can not exceed the originally reserved. + + > If you do not specify the amount, all the reserved money is captured. + + > In Argentina only available for Visa and American Express cards. + + ## Example + + The following example shows how one would (partially) capture a previously + authorized a payment worth 35 BRL by referencing the obtained authorization `id`. + + iex> amount = Money.new(35, :BRL) + iex> {:ok, capture_result} = Gringotts.capture(Gringotts.Gateways.Mercadopago, auth_result.id, amount, opts) + """ + @spec capture(String.t(), Money.t(), keyword) :: {:ok | :error, Response} + def capture(payment_id, amount, opts) do + {_, value, _, _} = Money.to_integer_exp(amount) + url_params = [access_token: opts[:config][:access_token]] + body = %{capture: true, transaction_amount: value} |> Poison.encode!() + commit(:put, "/v1/payments/#{payment_id}", body, opts, params: url_params) + end + ############################################################################### # PRIVATE METHODS # ############################################################################### @@ -202,7 +235,11 @@ defmodule Gringotts.Gateways.Mercadopago do defp create_token(%CreditCard{} = card, opts) do url_params = [public_key: opts[:config][:public_key]] - body = Poison.encode!(token_params(card)) + + body = + card + |> token_params() + |> Poison.encode!() {state, res} = commit(:post, "/v1/card_tokens/#{opts[:customer_id]}", body, opts, params: url_params) diff --git a/test/integration/gateways/mercadopago_test.exs b/test/integration/gateways/mercadopago_test.exs new file mode 100644 index 00000000..6c9779e2 --- /dev/null +++ b/test/integration/gateways/mercadopago_test.exs @@ -0,0 +1,64 @@ +defmodule Gringotts.Integration.Gateways.MercadopagoTest do + # Integration tests for the Mercadopago + + use ExUnit.Case, async: false + use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney + alias Gringotts.Gateways.Mercadopago, as: Gateway + + @moduletag integration: true + + @amount Money.new(45, :BRL) + @sub_amount Money.new(30, :BRL) + @config [ + access_token: "TEST-2774702803649645-031303-1b9d3d63acb57cdad3458d386eee62bd-307592510", + public_key: "TEST-911f45a1-0560-4c16-915e-a8833830b29a" + ] + @good_card %Gringotts.CreditCard{ + first_name: "Hermoine", + last_name: "Granger", + number: "4509953566233704", + year: 2030, + month: 07, + verification_code: "123", + brand: "VISA" + } + + @good_opts [ + email: "hermoine@granger.com", + order_id: 123_126, + customer_id: "311211654-YrXF6J0QikpIWX", + config: @config, + order_type: "mercadopago", + installments: 1 + ] + + describe "[capture]" do + test "capture success" do + use_cassette "mercadopago/capture_success" do + {:ok, response} = Gateway.authorize(@sub_amount, @good_card, @good_opts) + {:ok, response} = Gateway.capture(response.id, @sub_amount, @good_opts) + assert response.success == true + assert response.status_code == 200 + end + end + + test "invalid payment_id" do + use_cassette "mercadopago/capture_invalid_payment_id" do + {:ok, response} = Gateway.authorize(@sub_amount, @good_card, @good_opts) + id = response.id + 1 + {:error, response} = Gateway.capture(id, @sub_amount, @good_opts) + assert response.success == false + assert response.status_code == 404 + end + end + + test "extra amount capture" do + use_cassette "mercadopago/access_amount" do + {:ok, response} = Gateway.authorize(@sub_amount, @good_card, @good_opts) + {:error, response} = Gateway.capture(response.id, @amount, @good_opts) + assert response.success == false + assert response.status_code == 400 + end + end + end +end