Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Mercadopago] Implemented refund #155

Closed
wants to merge 60 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
961dfcb
Added project logo
pkrawat1 Dec 29, 2017
90e8b3e
Added version for inch_ex
oyeb Jan 2, 2018
907723b
test case added for network failure
jyotigautam Jan 2, 2018
609a92c
[ci skip] Get more Open Source Helpers
schneems Jan 2, 2018
41f1de5
Codeclimate fixes (#68)
sivagollapalli Jan 3, 2018
2680289
FIX# code style for large numbers (#67)
sivagollapalli Jan 3, 2018
6e402e9
Stripe gateway minor fixes and docs update (#75)
chandradot99 Jan 4, 2018
ea11367
Using Address and Credit Card struct (#74)
jyotigautam Jan 4, 2018
df44753
Cams : Added error response handling (#65)
gopalshimpi Jan 4, 2018
afdd12e
test authorize net
arjun289 Dec 25, 2017
d5fda24
Introducing the Money protocol (#71)
oyeb Jan 10, 2018
6fafa1d
Update README.md
pkrawat1 Jan 10, 2018
9a4c89b
Adds a super useful mix task: gringotts.new
oyeb Jan 9, 2018
365c3f1
[money-protocol] Expansion: `to_string` and `to_integer` (#86)
oyeb Jan 19, 2018
6d1828f
add mix task for tests, mocks and integration
arjun289 Jan 17, 2018
a135692
[monei] Implements optional/extra params (#79)
oyeb Jan 21, 2018
ce7c6bd
Money integration with ANet and Anet test modification (#82)
arjun289 Jan 21, 2018
db9190b
[ANet] Corrected use of money protocol and examples (#92)
oyeb Jan 25, 2018
5e748e7
[trexle] Adds Money protocol (#84)
jyotigautam Jan 25, 2018
f3c0d58
[CAMS] Adds money protocol (#89)
gopalshimpi Jan 25, 2018
f2796b4
Fix doc example typos, and mock tests (#93)
oyeb Jan 25, 2018
fa1cd11
[mix-task] Fixed arg order in capture (#94)
oyeb Jan 25, 2018
5b15d30
Global Collect payment gateway integration. (#95)
jyotigautam Jan 25, 2018
99850ab
Introduces `Response.t` with docs (#119)
oyeb Feb 6, 2018
1920ced
Removes payment worker.
oyeb Feb 5, 2018
8622ded
Removed offending (now useless) test case
oyeb Feb 5, 2018
6aa6a86
Removed GenServer import. Fixes #8.
oyeb Feb 15, 2018
3768649
Refactored ResponseHandler, for new Response.t
oyeb Feb 9, 2018
e16fe72
Refactored `commit` and corrected avs, cvc result
oyeb Feb 9, 2018
6eef8ef
Correct a few doc examples
oyeb Feb 9, 2018
e3c86ce
Adds changelog, contributing guide and improves mix task (#117)
oyeb Mar 15, 2018
71a5bc3
[monei] Test fixes (#116)
oyeb Mar 15, 2018
cf39d54
Fix gringotts.new Option.parse call. (#125)
oyeb Mar 19, 2018
a9b76db
Adapts Stripe with the money protocol
oyeb Jan 29, 2018
f99f258
Adapted Trexle for new `Response.t`
oyeb Feb 9, 2018
a91deec
[CAMS] Adapt for new Response.t (#120)
oyeb Mar 21, 2018
7bf1857
Format project and migrate to CodeCov (#135)
oyeb Mar 22, 2018
a4082cb
[global-collect] Layout, docs improvements and code refactors (#111)
jyotigautam Mar 30, 2018
a444179
Initial Commit \n Implemented Authorize
subpal Mar 20, 2018
ea9c912
Implemented authorize
subpal Mar 20, 2018
2127fe9
Refined authorize function
subpal Mar 21, 2018
d7d74b9
Implemented authorize
subpal Mar 21, 2018
b776dc9
jgkg
subpal Mar 26, 2018
4a99128
Modification in authorize/3, and implemented capture
subpal Mar 26, 2018
a6b4298
Modification in authorize/3, and implemented capture
subpal Mar 26, 2018
94f5b1c
Modification in authorize/3, and implemented capture
subpal Mar 26, 2018
1d46184
Modification in authorize/3, and implemented capture
subpal Mar 26, 2018
5956d5b
Updated authorize/3
subpal Mar 27, 2018
fd135db
Updated authorize/3
subpal Mar 27, 2018
e7349da
Updated authorize/3
subpal Mar 28, 2018
5eabe34
Updated authorize/3
subpal Mar 31, 2018
b51e7f1
Authorize integration test cases created
subpal Mar 31, 2018
d0277b2
Authorize integration test cases created
subpal Mar 31, 2018
0e159ab
Authorize integration test cases created
subpal Mar 31, 2018
d0bda62
Applied elixer formatter.
subpal Apr 17, 2018
1357aa8
Capture and test cases
subpal Apr 17, 2018
699876f
Added test cases for capture
subpal Apr 17, 2018
3254c54
Implemented purchase
subpal Apr 17, 2018
9d52afa
Implemented void
subpal Apr 17, 2018
96f729c
Implemented Refund
subpal Apr 17, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Implemented Refund
1. Added refund
2. Added test cases
  • Loading branch information
subpal committed Apr 17, 2018
commit 96f729cbcb7dd03885bddc5767644c11ead68fd9
92 changes: 43 additions & 49 deletions lib/gringotts/gateways/mercadopago.ex
Original file line number Diff line number Diff line change
Expand Up @@ -95,76 +95,70 @@ defmodule Gringotts.Gateways.Mercadopago do
alias Gringotts.{CreditCard, Response}

@doc """
Performs a (pre) Authorize operation.
The authorization validates the `card` details with the banking network,
places a hold on the transaction `amount` in the customer’s issuing bank.
mercadoapgo's `authorize` returns authorization ID(available in the `Response.id` field) :
* `capture/3` _an_ amount.
* `void/2` a pre-authorization.
## Note
For a new customer, `customer_id` field should be ignored. Otherwise it should be provided.
Transfers `amount` from the customer to the merchant.

mercadopago attempts to process a purchase on behalf of the customer, by
debiting `amount` from the customer's account by charging the customer's
`card`.

## Example
### Authorization for new customer.
The following example shows how one would (pre) authorize a payment of 42 BRL on a sample `card`.
Ignore `customer_id`.
iex> amount = Money.new(42, :BRL)
iex> card = %Gringotts.CreditCard{first_name: "Lord", last_name: "Voldemort", number: "4509953566233704", year: 2099, month: 12, verification_code: "123", brand: "VISA"}
iex> opts = [email: "tommarvolo@riddle.com", order_id: 123123, payment_method_id: "visa", config: %{access_token: YOUR_ACCESS_TOKEN, public_key: YOUR_PUBLIC_KEY}]
iex> {:ok, auth_result} = Gringotts.authorize(Gringotts.Gateways.Mercadopago, amount, card, opts)
iex> auth_result.id # This is the authorization ID
iex> auth_result.token # This is the customer ID/token
### Authorization for old customer.
The following example shows how one would (pre) authorize a payment of 42 BRL on a sample `card`.
Mention `customer_id`.

The following example shows how one would process a payment worth 42 BRL in
one-shot, without (pre) authorization.

iex> amount = Money.new(42, :BRL)
iex> card = %Gringotts.CreditCard{first_name: "Hermione", last_name: "Granger", number: "4509953566233704", year: 2099, month: 12, verification_code: "123", brand: "VISA"}
iex> opts = [email: "hermione@granger.com", order_id: 123125, customer_id: "308537342-HStv9cJCgK0dWU", payment_method_id: "visa", config: %{access_token: YOUR_ACCESS_TOKEN, public_key: YOUR_PUBLIC_KEY}]
iex> {:ok, auth_result} = Gringotts.authorize(Gringotts.Gateways.Mercadopago, amount, card, opts)
iex> auth_result.id # This is the authorization ID
iex> auth_result.token # This is the customer ID/token
"""
iex> card = %Gringotts.CreditCard{first_name: "Harry", last_name: "Potter", number: "4200000000000000", year: 2099, month: 12, verification_code: "123", brand: "VISA"}
iex> {:ok, purchase_result} = Gringotts.purchase(Gringotts.Gateways.Mercadopago, amount, card, opts)
iex> purchase_result.token # This is the customer ID/token

@spec authorize(Money.t(), CreditCard.t(), keyword) :: {:ok | :error, Response}
def authorize(amount, %CreditCard{} = card, opts) do
"""
@spec purchase(Money.t(), CreditCard.t(), keyword) :: {:ok | :error, Response}
def purchase(amount, %CreditCard{} = card, opts) do
if Keyword.has_key?(opts, :customer_id) do
auth_token(amount, card, opts, opts[:customer_id], false)
auth_token(amount, card, opts, opts[:customer_id], true)
else
case create_customer(opts) do
{:error, res} -> {:error, res}
{:ok, customer_id} -> auth_token(amount, card, opts, customer_id, false)
{state, res} = create_customer(opts)

if state == :error do
{state, res}
else
auth_token(amount, card, opts, res, true)
end
end
end

@doc """
Voids the referenced payment.

This method attempts a reversal of a previous transaction referenced by
`payment_id`.
Refunds the `amount` to the customer's account with reference to a prior transfer.

> As a consequence, the customer will never see any booking on his statement.
mercadopago processes a full or partial refund worth `amount`, referencing a
previous `purchase/3` or `capture/3`.

## Note

> Only pending or in_process payments can be cancelled.
> You must have enough available money in your account so you can refund the payment amount successfully. Otherwise, you'll get a 400 Bad Request error.

> Cancelled coupon payments, deposits and/or transfers will be deposited in the buyer’s Mercadopago account.
> You can refund a payment within 90 days after it was accredited.

## Example
> You can only refund approved payments.

The following example shows how one would void a previous (pre)
authorization. Remember that our `capture/3` example only did a partial
capture.
> You can perform up to 20 partial refunds in one payment.

iex> {:ok, void_result} = Gringotts.void(Gringotts.Gateways.Mercadopago, auth_result.id, opts)
## Example

The following example shows how one would (completely) refund a previous
purchase (and similarily for captures).

iex> amount = Money.new(35, :BRL)
iex> {:ok, refund_result} = Gringotts.refund(Gringotts.Gateways.Mercadopago, purchase_result.id, amount)
"""
@spec void(String.t(), keyword) :: {:ok | :error, Response}
def void(payment_id, opts) do
# url = "#{@base_url}/v1/payments/#{payment_id}?access_token=#{opts[:config][:access_token]}"
@spec refund(Money.t(), String.t(), keyword) :: {:ok | :error, Response}
def refund(payment_id, amount, opts) do
{_, value, _, _} = Money.to_integer_exp(amount)

# url = "#{@base_url}/v1/payments/#{payment_id}/refunds?access_token=#{opts[:config][:access_token]}"
url_params = [access_token: opts[:config][:access_token]]
body = %{status: "cancelled"} |> Poison.encode!()
commit(:put, "/v1/payments/#{payment_id}", body, opts, params: url_params)
body = %{amount: value} |> Poison.encode!()
commit(:post, "/v1/payments/#{payment_id}/refunds", body, opts, params: url_params)
end

###############################################################################
Expand Down
27 changes: 18 additions & 9 deletions test/integration/gateways/mercadopago_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,33 @@ defmodule Gringotts.Integration.Gateways.MercadopagoTest do
installments: 1
]

describe "[void]" do
test "void success" do
use_cassette "mercadopago/void_success" do
{:ok, response} = Gateway.authorize(@sub_amount, @good_card, @good_opts)
{:ok, response} = Gateway.void(response.id, @good_opts)
describe "[refund]" do
test "refund success" do
use_cassette "mercadopago/refund_success" do
{:ok, response} = Gateway.purchase(@sub_amount, @good_card, @good_opts)
{:ok, response} = Gateway.refund(response.id, @sub_amount, @good_opts)
assert response.success == true
assert response.status_code == 200
assert response.status_code == 201
end
end

test "invalid payment_id" do
use_cassette "mercadopago/void_invalid_payment_id" do
{:ok, response} = Gateway.authorize(@sub_amount, @good_card, @good_opts)
use_cassette "mercadopago/refund_invalid_payment_id" do
{:ok, response} = Gateway.purchase(@sub_amount, @good_card, @good_opts)
id = response.id + 1
{:error, response} = Gateway.void(id, @good_opts)
{:error, response} = Gateway.refund(id, @sub_amount, @good_opts)
assert response.success == false
assert response.status_code == 404
end
end

test "extra amount refund" do
use_cassette "mercadopago/extra_amount_reund" do
{:ok, response} = Gateway.purchase(@sub_amount, @good_card, @good_opts)
{:error, response} = Gateway.refund(response.id, @amount, @good_opts)
assert response.success == false
assert response.status_code == 400
end
end
end
end