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
Next Next commit
test authorize net
Added tests for authorize net library for the functions
authorize, capture, refund, void, store and unstore.
Added mock responses for the authorize net library for
functions authorize, capture, refund, void, store and
unstore. Added ResponseHandler module to parse gateway
responses. Added specs.
  • Loading branch information
arjun289 authored and pkrawat1 committed Jan 9, 2018
commit afdd12eebda94aee60f97b43a7acdc507650a3af
194 changes: 131 additions & 63 deletions lib/gringotts/gateways/authorize_net.ex
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ defmodule Gringotts.Gateways.AuthorizeNet do
use Gringotts.Gateways.Base
use Gringotts.Adapter, required_config: [:name, :transaction_key]

alias Gringotts.Gateways.AuthorizeNet.ResponseHandler

@test_url "https://apitest.authorize.net/xml/v1/request.api"
@production_url "https://api.authorize.net/xml/v1/request.api"
@header [{"Content-Type", "text/xml"}]
Expand All @@ -98,20 +100,10 @@ defmodule Gringotts.Gateways.AuthorizeNet do
void: "voidTransaction"
}

@response_type %{
auth_response: "authenticateTestResponse",
transaction_response: "createTransactionResponse",
error_response: "ErrorResponse",
customer_profile_response: "createCustomerProfileResponse",
customer_payment_profile_response: "createCustomerPaymentProfileResponse",
delete_customer_profile: "deleteCustomerProfileResponse"
}

@aut_net_namespace "AnetApi/xml/v1/schema/AnetApiSchema.xsd"

alias Gringotts.{
CreditCard,
Address,
Response
}

Expand Down Expand Up @@ -163,9 +155,10 @@ defmodule Gringotts.Gateways.AuthorizeNet do
iex> amount = 5
iex> result = Gringotts.purchase(Gringotts.Gateways.AuthorizeNet, amount, card, opts)
"""
@spec purchase(Float, CreditCard.t, Keyword.t) :: tuple
@spec purchase(float, CreditCard.t, Keyword.t) :: {:ok | :error, Response.t}
def purchase(amount, payment, opts) do
request_data = add_auth_purchase(amount, payment, opts, @transaction_type[:purchase])
request_data =
add_auth_purchase(amount, payment, opts, @transaction_type[:purchase])
response_data = commit(:post, request_data, opts)
respond(response_data)
end
Expand Down Expand Up @@ -216,9 +209,10 @@ defmodule Gringotts.Gateways.AuthorizeNet do
iex> amount = 5
iex> result = Gringotts.authorize(Gringotts.Gateways.AuthorizeNet, amount, card, opts)
"""
@spec authorize(Float, CreditCard.t, Keyword.t) :: tuple
@spec authorize(float, CreditCard.t, Keyword.t) :: {:ok | :error, Response.t}
def authorize(amount, payment, opts) do
request_data = add_auth_purchase(amount, payment, opts, @transaction_type[:authorize])
request_data =
add_auth_purchase(amount, payment, opts, @transaction_type[:authorize])
response_data = commit(:post, request_data, opts)
respond(response_data)
end
Expand All @@ -232,7 +226,7 @@ defmodule Gringotts.Gateways.AuthorizeNet do
* `refund/3` a settled transaction.
* `void/2` a transaction.

## Quirks
## Notes
* If a `capture` transaction needs to `void` then it should be done before it is settled. For AuthorieNet
all the transactions are settled after 24 hours.

Expand All @@ -253,7 +247,7 @@ defmodule Gringotts.Gateways.AuthorizeNet do
iex> id = "123456"
iex> result = Gringotts.capture(Gringotts.Gateways.AuthorizeNet, id, amount, opts)
"""
@spec capture(String.t, Float, Keyword.t) :: tuple
@spec capture(String.t, float, Keyword.t) :: {:ok | :error, Response.t}
def capture(id, amount, opts) do
request_data = normal_capture(amount, id, opts, @transaction_type[:capture])
response_data = commit(:post, request_data, opts)
Expand Down Expand Up @@ -283,7 +277,7 @@ defmodule Gringotts.Gateways.AuthorizeNet do
iex> amount = 5
iex> result = Gringotts.refund(Gringotts.Gateways.AuthorizeNet, amount, id, opts)
"""
@spec refund(Float, String.t, Keyword.t) :: tuple
@spec refund(float, String.t, Keyword.t) :: {:ok | :error, Response.t}
def refund(amount, id, opts) do
request_data = normal_refund(amount, id, opts, @transaction_type[:refund])
response_data = commit(:post, request_data, opts)
Expand All @@ -307,7 +301,7 @@ defmodule Gringotts.Gateways.AuthorizeNet do
iex> id = "123456"
iex> result = Gringotts.void(Gringotts.Gateways.AuthorizeNet, id, opts)
"""
@spec void(String.t, Keyword.t) :: tuple
@spec void(String.t, Keyword.t) :: {:ok | :error, Response.t}
def void(id, opts) do
request_data = normal_void(id, opts, @transaction_type[:void])
response_data = commit(:post, request_data, opts)
Expand All @@ -322,8 +316,9 @@ defmodule Gringotts.Gateways.AuthorizeNet do
can create customer payment profile by passing the `customer_profile_id` in the `opts`.
The gateway also provide a provision for a `validation mode`, there are two modes `liveMode`
and `testMode`, to know more about modes [see](https://developer.authorize.net/api/reference/index.html#customer-profiles-create-customer-profile).
By default `validation mode` is set to `testMode`.

## Quirks
## Notes
* The current version of this library supports only `credit card` as the payment profile.
* If a customer profile is created without the card info, then to create a payment profile
`card` info needs to be passed alongwith `cutomer_profile_id` to create it.
Expand All @@ -335,7 +330,7 @@ defmodule Gringotts.Gateways.AuthorizeNet do
## Optional Fields
opts = [
validation_mode: String,
billTo: %{
bill_to: %{
first_name: String, last_name: String, company: String, address: String,
city: String, state: String, zip: String, country: String
},
Expand All @@ -350,11 +345,12 @@ defmodule Gringotts.Gateways.AuthorizeNet do
iex> card = %CreditCard{number: "5424000000000015", year: 2020, month: 12, verification_code: "999"}
iex> result = Gringotts.store(Gringotts.Gateways.AuthorizeNet, card, opts)
"""
@spec store(CreditCard.t, Keyword.t) :: tuple
@spec store(CreditCard.t, Keyword.t) :: {:ok | :error, Response.t}
def store(card, opts) do
request_data = cond do
opts[:customer_profile_id] -> card |> create_customer_payment_profile(opts) |> generate
true -> card |> create_customer_profile(opts) |> generate
request_data = if opts[:customer_profile_id] do
card |> create_customer_payment_profile(opts) |> generate
else
card |> create_customer_profile(opts) |> generate
end
response_data = commit(:post, request_data, opts)
respond(response_data)
Expand All @@ -372,7 +368,7 @@ defmodule Gringotts.Gateways.AuthorizeNet do
iex> result = Gringotts.store(Gringotts.Gateways.AuthorizeNet, id, opts)
"""

@spec unstore(String.t, Keyword.t) :: tuple
@spec unstore(String.t, Keyword.t) :: {:ok | :error, Response.t}
def unstore(customer_profile_id, opts) do
request_data = customer_profile_id |> delete_customer_profile(opts) |> generate
response_data = commit(:post, request_data, opts)
Expand All @@ -386,38 +382,31 @@ defmodule Gringotts.Gateways.AuthorizeNet do
HTTPoison.request(method, path, payload, headers)
end

# Function to return a response
# Function to return a response
defp respond({:ok, %{body: body, status_code: 200}}) do
raw_response = naive_map(body)
cond do
raw_response[@response_type[:auth_response]] ->
response_check(raw_response[@response_type[:auth_response]], raw_response)
raw_response[@response_type[:transaction_response]] ->
response_check(raw_response[@response_type[:transaction_response]], raw_response)
raw_response[@response_type[:error_response]] ->
response_check(raw_response[@response_type[:error_response]], raw_response)
raw_response[@response_type[:customer_profile_response]] ->
response_check(raw_response[@response_type[:customer_profile_response]], raw_response)
raw_response[@response_type[:customer_payment_profile_response]] ->
response_check(raw_response[@response_type[:customer_payment_profile_response]], raw_response)
raw_response[@response_type[:delete_customer_profile]] ->
response_check(raw_response[@response_type[:delete_customer_profile]], raw_response)
end
response_type = ResponseHandler.check_response_type(raw_response)
response_check(raw_response[response_type], raw_response)
end

defp respond({:ok, %{body: body, status_code: code}}) do
{:error, Response.error(params: body, error_code: code)}
end

defp respond({:error, %{body: body, status_code: code}}) do
{:error, Response.error(raw: body, code: code)}
defp respond({:error, %HTTPoison.Error{} = error}) do
IO.inspect error
{:error, Response.error(error_code: error.id, message: "HTTPoison says '#{error.reason}'")}
end

# Functions to send successful and error responses depending on message received
# from gateway.

defp response_check(%{"messages" => %{"resultCode" => "Ok"}}, raw_response) do
{:ok, Response.success(raw: raw_response)}
{:ok, ResponseHandler.parse_gateway_success(raw_response)}
end

defp response_check(%{"messages" => %{"resultCode" => "Error"}}, raw_response) do
{:error, Response.error(raw: raw_response)}
{:error, ResponseHandler.parse_gateway_error(raw_response)}
end

#------------------- Helper functions for the interface functions-------------------
Expand All @@ -432,7 +421,7 @@ defmodule Gringotts.Gateways.AuthorizeNet do
])
|> generate
end

# function for formatting the request for normal capture
defp normal_capture(amount, id, opts, transaction_type) do
:createTransactionRequest
Expand All @@ -444,13 +433,6 @@ defmodule Gringotts.Gateways.AuthorizeNet do
|> generate
end

# function to format the request as an xml for the authenticate method
defp add_auth_request(opts) do
:authenticateTestRequest
|> element(%{xmlns: @aut_net_namespace}, [add_merchant_auth(opts[:config])])
|> generate
end

#function to format the request for normal refund
defp normal_refund(amount, id, opts, transaction_type) do
:createTransactionRequest
Expand Down Expand Up @@ -484,7 +466,9 @@ defmodule Gringotts.Gateways.AuthorizeNet do
add_billing_info(opts),
add_payment_source(card)
]),
element(:validationMode, opts[:validation_mode])
element(:validationMode,
(if opts[:validation_mode], do: opts[:validation_mode], else: "testMode")
)
])
end

Expand All @@ -496,10 +480,16 @@ defmodule Gringotts.Gateways.AuthorizeNet do
element(:description, opts[:profile][:description]),
element(:email, opts[:profile][:description]),
element(:paymentProfiles, [
element(:customerType, (if opts[:customer_type], do: opts[:customer_type], else: "individual")),
element(:customerType,
(if opts[:customer_type], do: opts[:customer_type], else: "individual")
),
add_billing_info(opts),
add_payment_source(card)
])
])
]),
]),
element(:validationMode,
(if opts[:validation_mode], do: opts[:validation_mode], else: "testMode")
)
])
end

Expand Down Expand Up @@ -553,7 +543,9 @@ defmodule Gringotts.Gateways.AuthorizeNet do
element(:payment, [
element(:creditCard, [
element(:cardNumber, opts[:payment][:card][:number]),
element(:expirationDate, join_string([opts[:payment][:card][:year], opts[:payment][:card][:month]], "-"))
element(:expirationDate,
join_string([opts[:payment][:card][:year], opts[:payment][:card][:month]], "-")
)
])
]),
add_ref_trans_id(id)
Expand Down Expand Up @@ -688,11 +680,87 @@ defmodule Gringotts.Gateways.AuthorizeNet do
end

defp base_url(opts) do
cond do
opts[:config][:mode] == :prod -> @production_url
opts[:config][:mode] == :test -> @test_url
true -> @test_url
end
if opts[:config][:mode] == :prod do
@production_url
else
@test_url
end
end

defmodule ResponseHandler do
@moduledoc false
alias Gringotts.Response

@response_type %{
auth_response: "authenticateTestResponse",
transaction_response: "createTransactionResponse",
error_response: "ErrorResponse",
customer_profile_response: "createCustomerProfileResponse",
customer_payment_profile_response: "createCustomerPaymentProfileResponse",
delete_customer_profile: "deleteCustomerProfileResponse"
}

def parse_gateway_success(raw_response) do
response_type = check_response_type(raw_response)
message = raw_response[response_type]["messages"]["message"]["text"]
avs_result = raw_response[response_type]["transactionResponse"]["avsResultCode"]
cvc_result = raw_response[response_type]["transactionResponse"]["cavvResultCode"]

[]
|> status_code(200)
|> set_message(message)
|> set_avs_result(avs_result)
|> set_cvc_result(cvc_result)
|> set_params(raw_response)
|> set_success(true)
|> handle_opts
end

def parse_gateway_error(raw_response) do
response_type = check_response_type(raw_response)

{message, error_code} = if raw_response[response_type]["transactionResponse"]["errors"] do
{raw_response[response_type]["messages"]["message"]["text"] <> " " <>
raw_response[response_type]["transactionResponse"]["errors"]["error"]["errorText"],
raw_response[response_type]["transactionResponse"]["errors"]["error"]["errorCode"]}
else
{raw_response[response_type]["messages"]["message"]["text"],
raw_response[response_type]["messages"]["message"]["code"]}
end

[]
|> status_code(200)
|> set_message(message)
|> set_error_code(error_code)
|> set_params(raw_response)
|> set_success(false)
|> handle_opts
end

def check_response_type(raw_response) do
cond do
raw_response[@response_type[:transaction_response]] -> "createTransactionResponse"
raw_response[@response_type[:error_response]] -> "ErrorResponse"
raw_response[@response_type[:customer_profile_response]] -> "createCustomerProfileResponse"
raw_response[@response_type[:customer_payment_profile_response]] -> "createCustomerPaymentProfileResponse"
raw_response[@response_type[:delete_customer_profile]] -> "deleteCustomerProfileResponse"
end
end

defp set_success(opts, value), do: opts ++ [success: value]
defp status_code(opts, code), do: opts ++ [status_code: code]
defp set_message(opts, message), do: opts ++ [message: message]
defp set_avs_result(opts, result), do: opts ++ [avs_result: result]
defp set_cvc_result(opts, result), do: opts ++ [cvc_result: result]
defp set_params(opts, raw_response), do: opts ++ [params: raw_response]
defp set_error_code(opts, code), do: opts ++ [error_code: code]

defp handle_opts(opts) do
case Keyword.fetch(opts, :success) do
{:ok, true} -> Response.success(opts)
{:ok, false} -> Response.error(opts)
end
end

end
end
2 changes: 1 addition & 1 deletion lib/gringotts/response.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ defmodule Gringotts.Response do
"""

defstruct [
:success, :authorization, :status_code, :error_code, :message,
:success, :authorization, :status_code, :error_code, :message,
:avs_result, :cvc_result, :params, :fraud_review
]

Expand Down
Loading