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

Remove wirecard and update upstream, ex_money #170

Merged
merged 1 commit into from
Jun 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 1 addition & 5 deletions .credo.exs
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,7 @@

# Deprecated checks (these will be deleted after a grace period)
#
{Credo.Check.Readability.Specs, false},
{Credo.Check.Warning.NameRedeclarationByAssignment, false},
{Credo.Check.Warning.NameRedeclarationByCase, false},
{Credo.Check.Warning.NameRedeclarationByDef, false},
{Credo.Check.Warning.NameRedeclarationByFn, false},
{Credo.Check.Readability.Specs, false}

# Custom checks can be created using `mix credo.gen.check`.
#
Expand Down
4 changes: 2 additions & 2 deletions .scripts/post-commit
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ RED='\033[1;31m'
LGRAY='\033[1;30m'
NC='\033[0m' # No Color

printf "${RED}Running 'mix credo --strict --format=oneline' on project...${NC}\n"
mix credo --strict --format=oneline
printf "${RED}Running 'mix credo --strict' on project...${NC}\n"
mix credo --strict
echo
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ matrix:
- elixir: "1.5.3"
script:
- mix coveralls.json
- elixir: "1.6.2"
- elixir: "1.6.5"

notifications:
email:
recipients:
- ananya95+travis@gmail.com
- ashish+travis@aviabird.com
43 changes: 31 additions & 12 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
# Changelog

## [`v1.1.1-rc`][tag-1_1_1-rc] (2018-06-04)

### Added

* **core:** Remove the protocol implementation for `ex_money` since they
implement it for us
[e1cb32](https://github.com/kipcole9/money/commit/e1cb325a28a8318864ff1cbfbbb67574379a82c0)
* **development:** Removed those annoying compiler warnings!
* **docs:** Add docs about the money protocol.

### Changed

Remove support of [Wirecard](http://wirecard.com/) as we failed to implement it completely and it is
not at all usable. It is being archived in
[`wirecard`](https://github.com/aviabird/gringotts/tree/wirecard) branch.

## [`v1.1.0`][tag-1_1_0] (2018-04-22)

### Added

* **api:** Introduces a `Money` protocol ([#71][pr#71])
* **core:** Introduces Response.t ([#119][pr#91])
* **development:** Adds a useful mix task gringotts.new ([#78][pr#78])
* **core:** Introduces `Response.t` ([#119][pr#91])
* **development:** Adds a useful mix task `gringotts.new` ([#78][pr#78]) to help
with adding more gateways!
* **docs:** Adds changelog, contributing guide ([#117][pr#117])

### Changed

* **api:** Deprecates use of `floats` for money amounts, check issue [#62][iss#62] ([#71][pr#71])
* **core:** Removes payment worker, no application, no worker now after josevalim [pointed it][jose-feedback] ([#118][pr#118])
* **api:** Deprecates use of `floats` for money amounts, check issue
[#62][iss#62] ([#71][pr#71])
* **core:** Removes payment worker, no application, no worker now after
@josevalim [pointed it][joses-feedback] ([#118][pr#118])

[iss#62]: https://github.com/aviabird/gringotts/issues/62
[pr#71]: https://github.com/aviabird/gringotts/pulls/71
Expand All @@ -21,14 +40,13 @@
[pr#117]: https://github.com/aviabird/gringotts/pulls/117
[pr#78]:https://github.com/aviabird/gringotts/pulls/78
[pr#86]:https://github.com/aviabird/gringotts/pulls/86
[jose-feedback]:https://elixirforum.com/t/gringotts-a-complete-payment-library-for-elixir-and-phoenix-framework/11054/41

[joses-feedback]:https://elixirforum.com/t/gringotts-a-complete-payment-library-for-elixir-and-phoenix-framework/11054/41

## [`v1.0.2`][tag-1_0_2] (2017-12-27)

### Added

* New Gateway: **Trexle**
* Gringotts now supports [Trexle](http://trexle.com/) as well :tada:

### Changed

Expand All @@ -49,12 +67,13 @@
* **api:** Initial public API release.
* **core:** Single worker architecture, config fetched from `config.exs`
* **api:** Supported Gateways:
- Stripe
- MONEI
- Paymill
- WireCard
- CAMSa
- [Stripe](http://stripe.com/)
- [MONEI](http://monei.net/)
- [Paymill](https://www.paymill.com/en/)
- [WireCard](http://wirecard.com/)
- [CAMS](http://www.centralams.com/)

[tag-1_1_1_rc]: https://github.com/aviabird/gringotts/releases/tag/v1.1.1-rc
[tag-1_1_0]: https://github.com/aviabird/gringotts/compare/1.1.0...1.0.2
[tag-1_0_2]: https://github.com/aviabird/gringotts/compare/1.0.2...1.0.1
[tag-1_0_1]: https://github.com/aviabird/gringotts/compare/1.0.1...1.0.0
Expand Down
77 changes: 49 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</p>

<p align="center">
Gringotts is a payment processing library in Elixir integrating various payment gateways, drawing motivation for Shopify's <a href="https://github.com/activemerchant/active_merchant"><code>activemerchant</code></a> gem. Checkout the <a href="https://gringottspay.herokuapp.com/" target="_">Demo</a> here.
Gringotts is a payment processing library in Elixir integrating various payment gateways, drawing motivation for Shopify's <a href="https://github.com/activemerchant/active_merchant"><code>activemerchant</code></a> gem. Checkout the <a href="https://gringottspay.herokuapp.com/" target="_">demo here</a>.
</p>
<p align="center">
<a href="https://travis-ci.org/aviabird/gringotts"><img src="https://travis-ci.org/aviabird/gringotts.svg?branch=master" alt='Build Status' /></a> <a href='https://coveralls.io/github/aviabird/gringotts?branch=master'><img src='https://coveralls.io/repos/github/aviabird/gringotts/badge.svg?branch=master' alt='Coverage Status' /></a> <a href=""><img src="https://img.shields.io/hexpm/v/gringotts.svg"/></a> <a href="https://inch-ci.org/github/aviabird/gringotts"><img src="http://inch-ci.org/github/aviabird/gringotts.svg?branch=master" alt="Docs coverage"></img></a> <a href="https://gitter.im/aviabird/gringotts"><img src="https://badges.gitter.im/aviabird/gringotts.svg"/></a>
Expand All @@ -25,10 +25,10 @@ Add `gringotts` to the list of dependencies of your application.

def deps do
[
{:gringotts, "~> 1.0"},
{:gringotts, "~> 1.1"},
# ex_money provides an excellent Money library, and integrates
# out-of-the-box with Gringotts
{:ex_money, "~> 1.1.0"}
{:ex_money, "> 2.5.0"}
]
end
```
Expand All @@ -51,11 +51,12 @@ config :gringotts, Gringotts.Gateways.Monei,
entityId: "your_secret_channel_id"
```

Copy and paste this code in a module or an `IEx` session
Copy and paste this code in a module or an `IEx` session, or use this handy
[`.iex.exs`][monei-bindings] for all the bindings.

```elixir
alias Gringotts.Gateways.Monei
alias Gringotts.{CreditCard}
alias Gringotts.CreditCard

# a fake sample card that will work now because the Gateway is by default
# in "test" mode.
Expand Down Expand Up @@ -83,18 +84,51 @@ end

[hexpm]: https://hex.pm/packages/gringotts
[monei]: http://www.monei.net
[monei-bindings]: https://gist.github.com/oyeb/a2e2ac5986cc90a12a6136f6bf1357e5

## On the `Gringotts.Money` protocol and money representation

All financial applications must take proper care when representing money in
their system. Using simple `float`ing values might lead to losses in the real
world due to [various reasons][floating-issues].

Most payment gateways are strict about the formatting of the `amount` in the
request, hence we cannot render arbitrary floating amounts like
`$4.99999`. Moreover, such amounts might mean something to your application but
they don't have any value in the real world (since you can't charge someone for
a fraction of a US cent).

Your application **must round** such amounts before invoking Gringotts **and manage
any remainders sensibly** yourself.

> Gringotts may perform rounding using the [`half-even`][wiki-half-even]
strategy, but it will discard remainders if any.

### Supported "Money" libraries

Gringotts does not ship with any library to work with monies. You are free to
choose any monie library you wish, as long as they implement the
[`Gringotts.Money`][protocol] for their type!

That said, we recommend [`ex_money`][ex_money] (above [`v2.6.0`][2_6_0]) to
represent monies. You just have to add it in your `deps()`.

[protocol]: https://github.com/aviabird/gringotts/blob/dev/lib/gringotts/money.ex
[floating-issues]: https://elixirforum.com/t/comparison-of-decimals-not-logical/770/21
[wiki-half-even]: https://en.wikipedia.org/wiki/Rounding#Round_half_to_even
[ex-money]: https://github.com/kipcole9/money
[2_6_0]: https://github.com/kipcole9/money/releases/tag/v2.6.0

## Supported Gateways

| Gateway | Supported countries |
| ------ | ----- |
| [Authorize.Net][anet] | AD, AT, AU, BE, BG, CA, CH, CY, CZ, DE, DK, ES, FI, FR, GB, GB, GI, GR, HU, IE, IT, LI, LU, MC, MT, NL, NO, PL, PT, RO, SE, SI, SK, SM, TR, US, VA |
| [CAMS][cams] | AU, US |
| [MONEI][monei] | DE, EE, ES, FR, IT, US |
| [PAYMILL][paymill] | AD, AT, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FO, FR, GB, GI, GR, HU, IE, IL, IS, IT, LI, LT, LU, LV, MT, NL, NO, PL, PT, RO, SE, SI, SK, TR, VA |
| [Stripe][stripe] | AT, AU, BE, CA, CH, DE, DK, ES, FI, FR, GB, IE, IN, IT, LU, NL, NO, SE, SG, US |
| [TREXLE][trexle] | AD, AE, AT, AU, BD, BE, BG, BN, CA, CH, CY, CZ, DE, DK, EE, EG, ES, FI, FR, GB, GI, GR, HK, HU, ID, IE, IL, IM, IN, IS, IT, JO, KW, LB, LI, LK, LT, LU, LV, MC, MT, MU, MV, MX, MY, NL, NO, NZ, OM, PH, PL, PT, QA, RO, SA, SE, SG, SI, SK, SM, TR, TT, UM, US, VA, VN, ZA |
| [Wirecard][wirecard] | AD, AT, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FR, GB, GI, GR, HU, IE, IL, IM, IS, IT, LI, LT, LU, LV, MC, MT, NL, NO, PL, PT, RO, SE, SI, SK, SM, TR, VA |
| Gateway | PCI compliance | `purchase` | `authorize` | `capture` | `void` | `refund` | (card) `store` | (card) `unstore` |
|-----------------------|----------------|------------|-------------|-----------|----------|----------|----------------|------------------|
| [Authorize.Net][anet] | mandatory | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| [CAMS][cams] | mandatory | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#10060; | &#10060; |
| [MONEI][monei] | mandatory | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#10060; |
| [PAYMILL][paymill] | optional | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#10060; | &#10060; |
| [Stripe][stripe] | optional | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; | &#9989; |
| [TREXLE][trexle] | mandatory | &#9989; | &#9989; | &#9989; | &#10060; | &#9989; | &#9989; | &#10060; |

[anet]: http://www.authorize.net/
[cams]: https://www.centralams.com/
Expand All @@ -105,7 +139,7 @@ end
[wirecard]: http://www.wirecard.com
[demo]: https://gringottspay.herokuapp.com/

## Road Map
## [Road Map][roadmap]

Apart from supporting more and more gateways, we also keep a somewhat detailed
plan for the future on our [wiki][roadmap].
Expand All @@ -116,19 +150,6 @@ plan for the future on our [wiki][roadmap].

Gringotts has a nice ring to it. Also [this][reason].

#### 2. What is the worker doing in the middle?

We wanted to "supervise" our payments, and power utilities to process recurring
payments, subscriptions with it. But yes, as of now, it is a bottle neck and
unnecessary.

It's slated to be removed in [`v2.0.0`][milestone-2_0_0_alpha] and any
supervised/async/parallel work can be explicitly managed via native elixir
constructs.

**In fact, it's already been removed from our [dev](#) branch.**

[milestone-2_0_0_alpha]: https://github.com/aviabird/gringotts/milestone/3
[reason]: http://harrypotter.wikia.com/wiki/Gringotts

## License
Expand Down
73 changes: 46 additions & 27 deletions lib/gringotts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ defmodule Gringotts do

## Standard API arguments

All requests to Gringotts are served by a supervised worker, this might be
made optional in future releases.

### `gateway` (Module) Name

The `gateway` to which this request is made. This is required in all API calls
Expand All @@ -29,24 +26,24 @@ defmodule Gringotts do
the transaction. `amount` is polymorphic thanks to the `Gringotts.Money`
protocol which can even be implemented by your very own custom Money type!

> Currently, we support only [`ex_money`][ex_money]'s `Money` type. Please
don't forget to add the `ex_money` lib to your deps!

#### Note

Gringotts supports [`ex_money`][ex_money] out of the box, just drop `ex_money`
types in this argument and everything will work as expected.

> Support for [`monetized`][monetized] and [`money`][money] is on the
> way, track it [here][iss-money-lib-support]!

Otherwise, just wrap your `amount` with the `currency` together in a `Map` like so,
money = %{value: Decimal.new("100.50"), currency: "USD"}
> Support for [`monetized`][monetized] and [`money`][money] would be nice, but
is currently not planned.

> When this highly precise `amount` is serialized into the network request, we
> use a potentially lossy `Gringotts.Money.to_string/1` or
> `Gringotts.Money.to_integer/1` to perform rounding (if required) using the
> [`half-even`][wiki-half-even] strategy.
>
> **Hence, to ensure transparency, protect sanity and save _real_ money, we
> STRONGLY RECOMMEND that merchants perform any required rounding and handle
> **Hence, to protect your interests, and save _real_ money, we STRONGLY
> RECOMMEND that (you) merchants perform any required rounding and handle
> remainders in their application logic -- before passing the `amount` to
> Gringotts's API.**

Expand All @@ -63,14 +60,23 @@ defmodule Gringotts do
[ex_money]: https://hexdocs.pm/ex_money/readme.html
[monetized]: https://hexdocs.pm/monetized/
[money]: https://hexdocs.pm/money/Money.html
[iss-money-lib-support]: https://github.com/aviabird/gringotts/projects/3#card-6801146
[wiki-half-even]: https://en.wikipedia.org/wiki/Rounding#Round_half_to_even

### `card`, a payment source

Gringotts provides a `Gringotts.CreditCard` type to hold card parameters
which merchants fetch from their clients. The same type can also hold Debit
card details.
Gringotts provides a `Gringotts.CreditCard` type to hold card parameters which
merchants fetch from their clients. You (the merchant) needs to be PCI-DSS
compliant to be able to use this.

> The same type can also hold Debit card details.

Some gateways do not provide direct API integrations even for PCI compliant
merchants, and force every merchant to use their client-side integration to
generate a card token.

Thus for such gateways, Gringotts accepts a `string` card-token instead of (or
in addition to) a `CreditCard.t` struct. Please refer the "Notes" section of
your chosen gateway to find what the card argument accepts.

#### Note

Expand Down Expand Up @@ -153,9 +159,14 @@ defmodule Gringotts do
gateway,

amount = Money.new("4.2", :USD)
# IF YOU DON'T USE ex_money
# amount = %{value: Decimal.new("4.2"), currency: "EUR"}
card = %Gringotts.CreditCard{first_name: "Harry", last_name: "Potter", number: "4200000000000000", year: 2099, month: 12, verification_code: "123", brand: "VISA"}
card = %Gringotts.CreditCard{
first_name: "Harry",
last_name: "Potter",
number: "4200000000000000",
year: 2099, month: 12,
verification_code: "123",
brand: "VISA"
}
{:ok, auth_result} = Gringotts.authorize(Gringotts.Gateways.XYZ, amount, card, opts)
"""
def authorize(gateway, amount, card, opts \\ []) do
Expand All @@ -175,10 +186,8 @@ defmodule Gringotts do
To capture $4.20 on a previously authorized payment worth $4.20 by referencing
the obtained authorization `id` with the `XYZ` gateway,

auth_result # The result of an `authorize/3` request.
amount = Money.new("4.2", :USD)
# IF YOU DON'T USE ex_money
# amount = %{value: Decimal.new("4.2"), currency: "EUR"}
card = %Gringotts.CreditCard{first_name: "Harry", last_name: "Potter", number: "4200000000000000", year: 2099, month: 12, verification_code: "123", brand: "VISA"}
Gringotts.capture(Gringotts.Gateways.XYZ, amount, auth_result.id, opts)
"""
def capture(gateway, id, amount, opts \\ []) do
Expand All @@ -204,9 +213,14 @@ defmodule Gringotts do
To process a purchase worth $4.2, with the `XYZ` gateway,

amount = Money.new("4.2", :USD)
# IF YOU DON'T USE ex_money
# amount = %{value: Decimal.new("4.2"), currency: "EUR"}
card = %Gringotts.CreditCard{first_name: "Harry", last_name: "Potter", number: "4200000000000000", year: 2099, month: 12, verification_code: "123", brand: "VISA"}
card = %Gringotts.CreditCard{
first_name: "Harry",
last_name: "Potter",
number: "4200000000000000",
year: 2099, month: 12,
verification_code: "123",
brand: "VISA"
}
Gringotts.purchase(Gringotts.Gateways.XYZ, amount, card, opts)
"""
def purchase(gateway, amount, card, opts \\ []) do
Expand All @@ -225,8 +239,6 @@ defmodule Gringotts do
gateway,

amount = Money.new("4.2", :USD)
# IF YOU DON'T USE ex_money
# amount = %{value: Decimal.new("4.2"), currency: "EUR"}
Gringotts.purchase(Gringotts.Gateways.XYZ, amount, id, opts)
"""
def refund(gateway, amount, id, opts \\ []) do
Expand All @@ -237,7 +249,7 @@ defmodule Gringotts do
@doc """
Stores the payment-source data for later use, returns a `token`.

> The token must be returned in the `Response.authorization` field.
> The token must be returned in the `Response.token` field.

## Note

Expand All @@ -247,7 +259,14 @@ defmodule Gringotts do

To store a card (a payment-source) for future use, with the `XYZ` gateway,

card = %Gringotts.CreditCard{first_name: "Jo", last_name: "Doe", number: "4200000000000000", year: 2099, month: 12, verification_code: "123", brand: "VISA"}
card = %Gringotts.CreditCard{
first_name: "Harry",
last_name: "Potter",
number: "4200000000000000",
year: 2099, month: 12,
verification_code: "123",
brand: "VISA"
}
Gringotts.store(Gringotts.Gateways.XYZ, card, opts)
"""
def store(gateway, card, opts \\ []) do
Expand Down
Loading