Skip to content

Commit bc0fac5

Browse files
committed
remove cache directory and work on disbursements
1 parent 8a369e0 commit bc0fac5

File tree

7 files changed

+237
-78
lines changed

7 files changed

+237
-78
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ momoapi_elixir-*.tar
2626

2727
momoapi_elixir.iml
2828

29+
.elixir_ls
30+
31+
config

config/config.exs

Lines changed: 0 additions & 6 deletions
This file was deleted.

lib/momoapi_elixir/auth.ex

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ defmodule MomoapiElixir.Auth do
1919
end
2020
end
2121

22+
def authorise_disbursements(%{subscription_key: subscription_key} = config) do
23+
basic_auth_token = create_basic_auth_token(config)
24+
headers = [
25+
{"Authorization", "Basic #{basic_auth_token}"},
26+
{"Ocp-Apim-Subscription-Key", subscription_key}
27+
]
28+
case post("/disbursement/token/", [], headers) do
29+
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
30+
%{"access_token" => access_token} = Poison.decode!(body)
31+
access_token
32+
end
33+
end
34+
2235
def create_basic_auth_token(%{user_id: user_id, api_key: api_key}) do
2336
Base.encode64("#{user_id}:#{api_key}")
2437
end

lib/momoapi_elixir/collection.ex

Lines changed: 90 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,25 @@
11
defmodule MomoapiElixir.Collection do
2-
use HTTPoison.Base
2+
use GenServer
33

4-
@base_url Application.get_env(:momoapi_elixir, :base_url) || "https://sandbox.momodeveloper.mtn.com"
5-
6-
@config %{
7-
subscription_key: Application.get_env(:momoapi_elixir, :collections_subscription_key),
8-
user_id: Application.get_env(:momoapi_elixir, :collections_user_id),
9-
api_key: Application.get_env(:momoapi_elixir, :collections_api_key),
10-
callback_url: Application.get_env(:momoapi_elixir, :collections_callback_url),
11-
target_environment: Application.get_env(:momoapi_elixir, :target_environment)
12-
}
13-
14-
def process_request_url(url) do
15-
@base_url <> url
4+
defmodule Option do
5+
@enforce_keys ~w(subscription_key user_id api_key)a
6+
defstruct subscription_key: nil, user_id: nil, api_key: nil, callback_url: nil, target_environment: "sandbox"
167
end
178

18-
def process_request_headers(headers) do
19-
headers |> set_subscription_key(@config.subscription_key) |> set_target_environment(@config.target_environment || "sandbox")
9+
defmodule Client do
10+
use HTTPoison.Base
11+
@base_url Application.get_env(:momoapi_elixir, :base_url) || "https://sandbox.momodeveloper.mtn.com"
12+
13+
def process_request_url(url) do
14+
@base_url <> url
15+
end
2016
end
2117

22-
def process_response_body(body) do
23-
body |> Poison.decode!()
18+
def start(%Option{} = opts) do
19+
GenServer.start(__MODULE__, opts, name: __MODULE__)
2420
end
2521

22+
# Client
2623
@doc """
2724
This operation is used to request a payment from a consumer (Payer). The payer will be asked to authorize the payment.
2825
The transaction will be executed once the payer has authorized the payment. The requesttopay will be in status PENDING
@@ -35,73 +32,115 @@ defmodule MomoapiElixir.Collection do
3532
externalId: "123456",
3633
payer: %{
3734
partyIdType: "MSISDN",
38-
partyId: "256784275529"
35+
partyId: "46733123450"
3936
},
4037
payerMessage: "testing",
4138
payeeNote: "hello"
4239
}
4340
4441
"""
4542
def request_to_pay(body) do
46-
token = MomoapiElixir.Auth.authorise_collections(@config)
47-
headers = add_reference_id(reference_id()) |> add_token(token)
48-
request_to_pay(headers, body)
49-
end
50-
51-
defp request_to_pay(headers, body) do
52-
case post("/collection/v1_0/requesttopay", Poison.encode!(body), headers) do
53-
{:ok, %HTTPoison.Response{status_code: 202, body: _body}} -> reference_id
54-
end
43+
body = validate_collections(body)
44+
GenServer.call(__MODULE__, {:request_to_pay, body})
5545
end
5646

5747
@doc"""
5848
Get the balance of the account
5949
"""
6050
def get_balance do
61-
token = MomoapiElixir.Auth.authorise_collections(@config)
62-
headers = add_reference_id(reference_id()) |> add_token(token)
63-
get_balance(headers)
64-
end
65-
66-
defp get_balance(headers) do
67-
case get("/collection/v1_0/account/balance", headers) do
68-
{:ok, %HTTPoison.Response{body: body, status_code: 200}} -> body
69-
end
51+
GenServer.call(__MODULE__, :get_balance)
7052
end
7153

72-
7354
@doc """
7455
This method is used to retrieve transaction information. You can invoke it at intervals until your transaction fails or succeeds
7556
"""
7657
def get_transaction_status(reference_id) do
77-
token = MomoapiElixir.Auth.authorise_collections(@config)
78-
headers = add_reference_id(reference_id()) |> add_token(token)
79-
get_transaction_status(headers, reference_id)
58+
GenServer.call(__MODULE__, {:get_transaction_status, reference_id})
59+
end
60+
61+
# Callbacks
62+
def init(%Option{subscription_key: subscription_key, user_id: user_id, api_key: api_key}) do
63+
token = MomoapiElixir.Auth.authorise_collections(
64+
%{subscription_key: subscription_key, user_id: user_id, api_key: api_key}
65+
)
66+
{:ok, %{subscription_key: subscription_key, token: token}}
67+
end
68+
69+
def handle_call({:request_to_pay, body}, _from, state) do
70+
reference_id = reference_id()
71+
body_encoded = Poison.encode!(body)
72+
headers = [
73+
{"Authorization", "Bearer #{state.token}"},
74+
{"Ocp-Apim-Subscription-Key", state.subscription_key},
75+
{"X-Reference-Id", reference_id},
76+
{"X-Target-Environment", "sandbox"}
77+
]
78+
case Client.post("/collection/v1_0/requesttopay", body_encoded, headers) do
79+
{:ok, %HTTPoison.Response{status_code: 202, body: _body}} -> {:reply, reference_id, state}
80+
{:ok, %HTTPoison.Response{status_code: 500, body: body}} -> {:reply, {:error, %{code: 500, body: Poison.decode!(body)}}, state}
81+
{:ok, %HTTPoison.Response{status_code: 500, body: ""}} -> {:reply, {:error, %{code: 500, body: ""}}, state }
82+
{:ok, %HTTPoison.Response{status_code: 400, body: ""}} -> {:reply, {:error, %{code: 400, body: ""}}, state}
83+
{:ok, %HTTPoison.Response{status_code: 400, body: body}} -> {:reply, {:error, %{code: 400, body: Poison.decode!(body)}}, state}
84+
end
8085
end
8186

82-
def get_transaction_status(headers, reference_id) do
83-
case get("/collection/v1_0/requesttopay/#{reference_id}", headers) do
84-
{:ok, %HTTPoison.Response{body: body, status_code: 200}} -> body
87+
def handle_call(:get_balance, _from, state) do
88+
headers = [
89+
{"Authorization", "Bearer #{state.token}"},
90+
{"Ocp-Apim-Subscription-Key", state.subscription_key},
91+
{"X-Target-Environment", "sandbox"}
92+
]
93+
case Client.get("/collection/v1_0/account/balance", headers) do
94+
{:ok, %HTTPoison.Response{body: body, status_code: 200}} -> {:reply, Poison.decode!(body), state}
95+
{:ok, %HTTPoison.Response{body: body, status_code: 404}} -> {:reply, {:error, Poison.decode!(body)}, state}
96+
{:ok, %HTTPoison.Response{body: body, status_code: 500}} -> {:reply, {:error, Poison.decode!(body)}, state}
8597
end
8698
end
8799

100+
def handle_call({:get_transaction_status, reference_id}, _from, state) do
101+
headers = [
102+
{"Authorization", "Bearer #{state.token}"},
103+
{"Ocp-Apim-Subscription-Key", state.subscription_key},
104+
{"X-Target-Environment", "sandbox"},
105+
{"X-Reference-Id", reference_id},
106+
]
107+
case Client.get("/collection/v1_0/requesttopay/#{reference_id}", headers) do
108+
{:ok, %HTTPoison.Response{body: body, status_code: 200}} -> {:reply, Poison.decode!(body), state}
109+
end
110+
111+
end
112+
88113
defp reference_id do
89114
UUID.uuid4()
90115
end
91116

92-
defp set_subscription_key(headers \\ [], subscription_key) do
93-
[{"Ocp-Apim-Subscription-Key", subscription_key} | headers]
117+
defp validate_collections(
118+
%{
119+
amount: amount
120+
}
121+
) when is_nil(amount) or amount == "" do
122+
raise "Amount is required"
94123
end
95124

96-
defp set_target_environment(headers \\ [], target_environment) do
97-
[{"X-Target-Environment", target_environment} | headers]
125+
defp validate_collections(
126+
%{
127+
currency: currency
128+
}
129+
) when is_nil(currency) or currency == "" do
130+
raise "Currency is required"
98131
end
99132

100-
defp add_reference_id(headers \\ [], reference_id) do
101-
[{"X-Reference-Id", reference_id} | headers]
133+
defp validate_collections(
134+
%{
135+
payer: %{
136+
partyId: party_id
137+
},
138+
}
139+
) when is_nil(party_id) or party_id == "" do
140+
raise "Party id is required"
102141
end
103142

104-
defp add_token(headers \\ [], token) do
105-
[{"Authorization", "Bearer #{token}"} | headers]
143+
defp validate_collections(body) do
144+
body
106145
end
107146
end

lib/momoapi_elixir/disbursement.ex

Lines changed: 131 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,139 @@
11
defmodule MomoapiElixir.Disbursement do
2-
def transfer do
3-
#
2+
use GenServer
3+
4+
defmodule Option do
5+
@enforce_keys ~w(subscription_key user_id api_key)a
6+
defstruct subscription_key: nil, user_id: nil, api_key: nil, callback_url: nil, target_environment: "sandbox"
7+
end
8+
9+
defmodule Client do
10+
use HTTPoison.Base
11+
@base_url Application.get_env(:momoapi_elixir, :base_url) || "https://sandbox.momodeveloper.mtn.com"
12+
13+
def process_request_url(url) do
14+
@base_url <> url
15+
end
16+
end
17+
18+
def start(%Option{} = opts) do
19+
GenServer.start(__MODULE__, opts, name: __MODULE__)
20+
end
21+
22+
@doc """
23+
%{
24+
amount: "100",
25+
currency: "EUR",
26+
externalId: "947354",
27+
payee: %{
28+
partyIdType: "MSISDN",
29+
partyId: "+256776564739"
30+
},
31+
payerMessage: "testing",
32+
payeeNote: "hello"
33+
}
34+
"""
35+
36+
def transfer(body) do
37+
body = validate_disbursements(body)
38+
GenServer.call(__MODULE__, {:transfer, body})
439
end
540

6-
def get_balance(headers) do
7-
#
41+
def get_balance do
42+
GenServer.call(__MODULE__, :get_balance)
843
end
944

1045
def get_transaction_status(reference_id) do
11-
#
46+
GenServer.call(__MODULE__, {:get_transaction_status, reference_id})
47+
end
48+
49+
# Callbacks
50+
def init(%Option{subscription_key: subscription_key, user_id: user_id, api_key: api_key}) do
51+
token = MomoapiElixir.Auth.authorise_disbursements(
52+
%{subscription_key: subscription_key, user_id: user_id, api_key: api_key}
53+
)
54+
{:ok, %{subscription_key: subscription_key, token: token}}
55+
end
56+
57+
def handle_call({:transfer, body}, _from, state) do
58+
reference_id = reference_id()
59+
body_encoded = Poison.encode!(body)
60+
headers = [
61+
{"Authorization", "Bearer #{state.token}"},
62+
{"Ocp-Apim-Subscription-Key", state.subscription_key},
63+
{"X-Reference-Id", reference_id},
64+
{"X-Target-Environment", "sandbox"}
65+
]
66+
case Client.post("/disbursement/v1_0/transfer", body_encoded, headers) do
67+
{:ok, %HTTPoison.Response{status_code: 202, body: _body}} ->
68+
{:reply, reference_id, state}
69+
{:ok, %HTTPoison.Response{status_code: 500, body: body}} ->
70+
{:reply, {:error, %{code: 500, body: Poison.decode!(body)}}, state}
71+
{:ok, %HTTPoison.Response{status_code: 500, body: ""}} ->
72+
{:reply, {:error, %{code: 500, body: ""}}, state}
73+
{:ok, %HTTPoison.Response{status_code: 400, body: ""}} ->
74+
{:reply, {:error, %{code: 400, body: ""}}, state}
75+
{:ok, %HTTPoison.Response{status_code: 400, body: body}} ->
76+
{:reply, {:error, %{code: 400, body: Poison.decode!(body)}}, state}
77+
end
78+
end
79+
80+
def handle_call(:get_balance, _from, state) do
81+
headers = [
82+
{"Authorization", "Bearer #{state.token}"},
83+
{"Ocp-Apim-Subscription-Key", state.subscription_key},
84+
{"X-Target-Environment", "sandbox"}
85+
]
86+
case Client.get("/disbursement/v1_0/account/balance", headers) do
87+
{:ok, %HTTPoison.Response{body: body, status_code: 200}} -> {:reply, Poison.decode!(body), state}
88+
{:ok, %HTTPoison.Response{body: body, status_code: 404}} -> {:reply, {:error, Poison.decode!(body)}, state}
89+
{:ok, %HTTPoison.Response{body: body, status_code: 500}} -> {:reply, {:error, Poison.decode!(body)}, state}
90+
{:ok, %HTTPoison.Response{body: body, status_code: 503}} -> {:reply, {:error, Poison.decode!(body)}, state}
91+
end
92+
end
93+
94+
def handle_call({:get_transaction_status, reference_id}, _from, state) do
95+
headers = [
96+
{"Authorization", "Bearer #{state.token}"},
97+
{"Ocp-Apim-Subscription-Key", state.subscription_key},
98+
{"X-Target-Environment", "sandbox"},
99+
{"X-Reference-Id", reference_id},
100+
]
101+
case Client.get("/disbursement/v1_0/transfer/#{reference_id}", headers) do
102+
{:ok, %HTTPoison.Response{body: body, status_code: 200}} -> {:reply, Poison.decode!(body), state}
103+
end
104+
end
105+
106+
defp reference_id do
107+
UUID.uuid4()
108+
end
109+
110+
defp validate_disbursements(
111+
%{
112+
amount: amount
113+
}
114+
) when is_nil(amount) or amount == "" do
115+
raise "Amount is required"
116+
end
117+
118+
defp validate_disbursements(
119+
%{
120+
currency: currency
121+
}
122+
) when is_nil(currency) or currency == "" do
123+
raise "Currency is required"
124+
end
125+
126+
defp validate_disbursements(
127+
%{
128+
payer: %{
129+
partyId: party_id
130+
},
131+
}
132+
) when is_nil(party_id) or party_id == "" do
133+
raise "Party id is required"
134+
end
135+
136+
defp validate_disbursements(body) do
137+
body
12138
end
13139
end

lib/momoapi_elixir/mix/tasks/provision.ex

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
defmodule Mix.Tasks.Provision do
22
use Mix.Task
33

4-
# @reference_id UUID.uuid4()
54
@base_url "https://sandbox.momodeveloper.mtn.com"
65

76
@shortdoc "Creates the user id and user api key."

lib/momoapi_elixir/response.ex

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)