Created
January 22, 2016 19:28
-
-
Save imetallica/b0fd851f94ee5967318a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule Merchant.Gateways.PayPal do | |
| @moduledoc """ | |
| The PayPal api. It connects with the PayPal's REST API. | |
| """ | |
| use HTTPoison.Base | |
| use Merchant.Gateway | |
| alias Merchant.Gateways.PayPal | |
| @sandbox_api "https://api.sandbox.paypal.com/" | |
| @live_api "https://api.paypal.com/" | |
| @token_api_path "v1/oauth2/token" | |
| @grant_type_client_credentials "grant_type=client_credentials" | |
| defmodule Credentials do | |
| @moduledoc """ | |
| Credentials used by PayPal module. | |
| """ | |
| defstruct username: "", password: "", test: "" | |
| end | |
| defmodule PayerVisa do | |
| @moduledoc """ | |
| A Payer structure. All *fields* are required: | |
| - *payment_method*: String. (We only support "credit_card") | |
| - *funding_instruments* : [ | |
| - *credit_card*: Merchant.Card | |
| ] | |
| """ | |
| defstruct payment_method: "credit_card", | |
| funding_instruments: [ | |
| credit_card: %Merchant.Cards.Visa{} | |
| ] | |
| end | |
| defmodule PayerMC do | |
| @moduledoc """ | |
| A Payer structure. All *fields* are required: | |
| - *payment_method*: String. (We only support "credit_card") | |
| - *funding_instruments* : [ | |
| - *credit_card*: Merchant.Card | |
| ] | |
| """ | |
| defstruct payment_method: "credit_card", | |
| funding_instruments: [ | |
| credit_card: %Merchant.Cards.MasterCard{} | |
| ] | |
| end | |
| defmodule Transaction do | |
| @moduledoc """ | |
| A Transaction structure. All *fields* are required: | |
| - description: String. (Give a description to the transaction.) | |
| - *ammount*: | |
| - *currency*: String. (A 3-letter currency code. All supported | |
| currencies are listed below.) | |
| - *total*: String. (Total to be charged. 10 characters max with | |
| support for 2 decimal places.) | |
| - details: | |
| - shipping: String. (Amount charged for shipping. 10 characters | |
| max with support for 2 decimal places.) | |
| - subtotal: String. (Amount of the subtotal of the items. | |
| Required if line items are specified. 10 | |
| characters max, with support for 2 decimal | |
| places.) | |
| - tax: String. (Amount charged for tax. 10 characters max | |
| with support for 2 decimal places.) | |
| ## Supported currencies Currency Code | |
| Australian dollar AUD | |
| Brazilian real** BRL | |
| Canadian dollar CAD | |
| Czech koruna CZK | |
| Danish krone DKK | |
| Euro EUR | |
| Hong Kong dollar HKD | |
| Hungarian forint* HUF | |
| Israeli new shekel ILS | |
| Japanese yen* JPY | |
| Malaysian ringgit** MYR | |
| Mexican peso MXN | |
| New Taiwan dollar* TWD | |
| New Zealand dollar NZD | |
| Norwegian krone NOK | |
| Philippine peso PHP | |
| Polish złoty PLN | |
| Pound sterling GBP | |
| Russian ruble RUB | |
| Singapore dollar SGD | |
| Swedish krona SEK | |
| Swiss franc CHF | |
| Thai baht THB | |
| Turkish lira** TRY | |
| United States dollar USD | |
| * This currency does not support decimals. Passing a decimal amount will | |
| result in an error. | |
| ** This currency is supported as a payment currency and a currency balance | |
| for in-country PayPal accounts only. | |
| """ | |
| defstruct description: "", | |
| ammount: [ | |
| currency: "USD", | |
| total: "", | |
| details: [ | |
| shipping: "", | |
| subtotal: "", | |
| tax: "" | |
| ] | |
| ] | |
| end | |
| def get_paypal_creds do | |
| configs = Application.get_env!(:merchant, :paypal) | |
| %Credentials{ | |
| username: configs.username, | |
| password: configs.password, | |
| test: configs.test} | |
| end | |
| @doc """ | |
| This function sends the credentials to the PayPal's oauth2 server and it | |
| expects either the data or throws an error. | |
| """ | |
| def get_token!(cred) do | |
| case cred.test do | |
| true -> | |
| response = PayPal.post!( | |
| @sandbox_api <> @token_api_path, | |
| @grant_type_client_credentials, | |
| [{"Accept", "application/json"}, | |
| {"Content-Type", "application/x-www-form-urlencoded"}, | |
| generate_paypal_request_id()], | |
| [hackney: | |
| [basic_auth: {cred.username, cred.password}]]) | |
| |> check_response |> Map.get("access_token") | |
| false -> Paypal.get!(@live_api <> @token_api_path, [], | |
| [hackney: [basic_auth: {cred.username, cred.password}]]) | |
| _ -> raise "Not configured." | |
| end | |
| end | |
| # Request ID is to allow requests to be unique in paypal. It encodes in base64. | |
| # Finally it returns a tuple, that can be used directly into paypal's headers. | |
| defp generate_paypal_request_id do | |
| str_system_time = Integer.to_string :erlang.system_time(:milli_seconds) | |
| str_random_numb = Float.to_string :rand.uniform() | |
| rnd = :base64.encode(str_system_time <> str_random_numb) | |
| {"PayPal-Request-Id", rnd} | |
| end | |
| defp check_response(response) do | |
| IO.inspect(response.status_code) | |
| body = Poison.decode!(response.body) | |
| case response.status_code do | |
| x when x >= 200 and x < 300 -> | |
| IO.inspect body | |
| body | |
| x when x >= 400 and x < 500 -> | |
| error = Map.get(body, "error") | |
| error_description = Map.get(body, "error_description") | |
| raise "#{x}. #{error}: #{error_description}" | |
| x when x >= 500 and x < 600 -> | |
| raise "#{x}. PayPal is misbehaving. Please try again" | |
| end | |
| end | |
| defimpl AvailableCards, for: Merchant.Cards.MasterCard do | |
| def support_card?(_card), do: true | |
| def normalize_card(card) do | |
| Map.update!(card, :type, fn x -> | |
| x = "mastercard" | |
| end) | |
| end | |
| end | |
| defimpl AvailableCards, for: Merchant.Cards.Visa do | |
| def support_card?(_card), do: true | |
| def normalize_card(card) do | |
| Map.update!(card, :type, fn x -> | |
| x = "visa" | |
| end) | |
| end | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment