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
Reorganize Payment Gateway Structure and Fix Payment Method Creation #24
Changes from all commits
d8dbb4b
c647bd2
8bb1f52
8a07a63
2f80198
63f71df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
defmodule Ryal.PaymentGateway.Bogus do | ||
@moduledoc """ | ||
A very simple payment gateway module that provides the basic functions to fake | ||
create, update, and delete methods with a payment gateway. | ||
""" | ||
|
||
@doc "Simple bogus create function for an external_id." | ||
@spec create(atom, Ecto.Schema.t) :: {:ok, String.t} | ||
def create(_atom, _schema), do: {:ok, random_id()} | ||
|
||
@doc "Simple bogus update function." | ||
@spec update(atom, Ecto.Schema.t) :: {:ok, %{}} | ||
def update(_atom, _schema), do: {:ok, %{}} | ||
|
||
@doc "Simple bogus delete function." | ||
@spec delete(atom, Ecto.Schema.t) :: {:ok, %{}} | ||
def delete(_atom, _schema), do: {:ok, %{}} | ||
|
||
defp random_id do | ||
:rand.uniform * 10_000_000_000 | ||
|> round | ||
|> to_string | ||
|> String.ljust(10, ?0) | ||
end | ||
end |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
defmodule Ryal.PaymentGateway.Stripe do | ||
@moduledoc "Relevant functions for working with the Stipe API." | ||
|
||
alias Ryal.PaymentGatewayQuery | ||
|
||
@stripe_api_key Map.get(Ryal.payment_gateways(), :stripe) | ||
@stripe_base "https://#{@stripe_api_key}:@api.stripe.com" | ||
|
||
@spec create(atom, Ecto.Schema.t, String.t) :: {:ok, String.t} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to remove the need for an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At this level I agree. We shouldn't tie gateway usage to Ecto dependencies....Unless we are comitted to building on the Phoenix stack instead of a more general approach. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm good with sticking to Ecto. However, we don't really need Phoenix so much as we need Plug. To me, Ryal, ATM, will always require storage. It's up to the user if they want to mount the API. Ryal, however, would expect to be able to store data. Unless, of course, we move the logic for Ryal into another dependency. But that's a longer-term goal. We need Ryal working first. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok let's ship it and keep an eye on these dependencies as the code base grows. |
||
def create(type, schema, stripe_base \\ @stripe_base) | ||
|
||
def create(:credit_card, payment_method, stripe_base) do | ||
credit_card_data = payment_method.proxy.data | ||
customer_id = payment_method.user_id | ||
|> PaymentGatewayQuery.get_external_id("stripe") | ||
|> Ryal.repo.one! | ||
|
||
credit_card_path = "/v1/customers/#{customer_id}/sources" | ||
create_object credit_card_data, :credit_card, credit_card_path, stripe_base | ||
end | ||
|
||
def create(:customer, user, stripe_base) do | ||
create_object user, :customer, "/v1/customers", stripe_base | ||
end | ||
|
||
defp create_object(schema, type, path, stripe_base) do | ||
response = HTTPotion.post(stripe_base <> path, [body: params(type, schema)]) | ||
|
||
with {:ok, body} <- Poison.decode(response.body), | ||
do: {:ok, body["id"]} | ||
end | ||
|
||
@spec update(atom, Ecto.Schema.t, String.t) :: {:ok, %{}} | ||
def update(type, schema, stripe_base \\ @stripe_base) | ||
|
||
@doc "Updates information on Stripe when the user data changes." | ||
def update(:customer, payment_gateway, stripe_base) do | ||
user = payment_gateway.user | ||
|
||
response = stripe_base | ||
<> "/v1/customers/#{payment_gateway.external_id}" | ||
|> HTTPotion.post([body: params(:customer, user)]) | ||
|
||
Poison.decode(response.body) | ||
end | ||
|
||
@spec delete(atom, Ecto.Schema.t, String.t) :: {:ok, %{}} | ||
def delete(atom, schema, stripe_base \\ @stripe_base) | ||
|
||
@doc "Marks a customer account on Stripe as deleted." | ||
def delete(:customer, payment_gateway, stripe_base) do | ||
response = stripe_base | ||
<> "/v1/customers/#{payment_gateway.external_id}" | ||
|> HTTPotion.delete | ||
|
||
Poison.decode(response.body) | ||
end | ||
|
||
defp params(:credit_card, credit_card) do | ||
URI.encode_query %{ | ||
"source[object]" => "card", | ||
"source[exp_month]" => credit_card.month, | ||
"source[exp_year]" => credit_card.year, | ||
"source[number]" => credit_card.number, | ||
"source[cvc]" => credit_card.cvc, | ||
"source[name]" => credit_card.name | ||
} | ||
end | ||
|
||
defp params(:customer, user) do | ||
URI.encode_query %{ | ||
email: user.email, | ||
description: "Customer #{user.id} from Ryal." | ||
} | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
defmodule Ryal.PaymentGatewayQuery do | ||
@moduledoc "Queries for the `Ryal.PaymentGateway`." | ||
|
||
use Ryal.Web, :query | ||
|
||
alias Ryal.PaymentGateway | ||
|
||
@doc """ | ||
Have a user id and want to get its external_id to one of the payment | ||
gateways? This query should help you out fine. | ||
""" | ||
@spec get_external_id(integer, String.t) :: Ecto.Query.t | ||
def get_external_id(user_id, gateway_type) do | ||
from pg in PaymentGateway, | ||
where: [user_id: ^user_id, type: ^gateway_type], | ||
select: pg.external_id | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"id": "card_1AA3En2BZSQJcNSQ77orWzVS", | ||
"object": "card", | ||
"address_city": null, | ||
"address_country": null, | ||
"address_line1": null, | ||
"address_line1_check": null, | ||
"address_line2": null, | ||
"address_state": null, | ||
"address_zip": null, | ||
"address_zip_check": null, | ||
"brand": "Visa", | ||
"country": "US", | ||
"customer": "cus_AUIXSS9KUHRv5H", | ||
"cvc_check": null, | ||
"dynamic_last4": null, | ||
"exp_month": 8, | ||
"exp_year": 2018, | ||
"funding": "credit", | ||
"last4": "4242", | ||
"metadata": {}, | ||
"name": null, | ||
"tokenization_method": null | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pipe chain should start with a raw value.