Skip to content

Commit 13e8402

Browse files
committed
Add User.create_session/1 to generate a new access_token
1 parent f9a6a8b commit 13e8402

File tree

4 files changed

+132
-3
lines changed

4 files changed

+132
-3
lines changed

config/config.exs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ use Mix.Config
44

55
config :kite_connect_ex,
66
api_key: "api-key",
7-
api_secret: "api-secret"
7+
api_secret: "api-secret",
8+
request_options: [
9+
timeout: 5_000,
10+
recv_timeout: 5_000
11+
]

lib/kite_connect_ex/response.ex

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,35 @@ defmodule KiteConnectEx.Response do
66
@success_status_codes [200, 201]
77
@server_error_status_code 500
88

9+
@success_status "success"
10+
11+
@doc false
912
@spec parse_response(HTTPoison.Response.t()) :: success | error
1013
def parse_response(%HTTPoison.Response{} = response) do
1114
case response do
1215
%{body: body, status_code: status} when status in @success_status_codes ->
13-
{:ok, Jason.decode!(body)}
16+
parse_body(body)
1417

1518
%{body: body, status_code: status} ->
1619
{:error, Jason.decode!(body), status}
1720
end
1821
end
1922

23+
@doc false
2024
@spec parse_error(HTTPoison.Error.t()) :: error
2125
def parse_error(%HTTPoison.Error{} = error) do
2226
{:error, "invalid response - " <> inspect(error), @server_error_status_code}
2327
end
28+
29+
defp parse_body(%{"status" => @success_status, "data" => data} = body) do
30+
Jason.decode(data)
31+
|> case do
32+
{:ok, data} -> {:ok, data}
33+
{:error, _error} -> {:error, body, @server_error_status_code}
34+
end
35+
end
36+
37+
defp parse_body(body) do
38+
{:error, body, @server_error_status_code}
39+
end
2440
end

lib/kite_connect_ex/user.ex

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,49 @@ defmodule KiteConnectEx.User do
88
alias KiteConnectEx.Request
99

1010
@login_url "https://kite.zerodha.com/connect/login"
11+
@create_session_path "/session/token"
12+
13+
@keys [
14+
access_token: nil,
15+
api_key: nil,
16+
avatar_url: nil,
17+
broker: nil,
18+
email: nil,
19+
exchanges: nil,
20+
login_time: nil,
21+
meta: nil,
22+
order_types: nil,
23+
products: nil,
24+
public_token: nil,
25+
refresh_token: nil,
26+
silo: nil,
27+
user_id: nil,
28+
user_name: nil,
29+
user_shortname: nil,
30+
user_type: nil
31+
]
32+
33+
@type t :: %__MODULE__{
34+
access_token: String.t(),
35+
api_key: String.t(),
36+
avatar_url: String.t(),
37+
broker: String.t(),
38+
email: String.t(),
39+
exchanges: List.t(),
40+
login_time: String.t(),
41+
meta: map(),
42+
order_types: List.t(),
43+
products: List.t(),
44+
public_token: String.t(),
45+
refresh_token: String.t(),
46+
silo: String.t(),
47+
user_id: String.t(),
48+
user_name: String.t(),
49+
user_shortname: String.t(),
50+
user_type: String.t()
51+
}
52+
53+
defstruct [:original_json | @keys]
1154

1255
@doc """
1356
Get KiteConnect login endpoint
@@ -27,4 +70,70 @@ defmodule KiteConnectEx.User do
2770
defp api_key do
2871
Application.get_env(:kite_connect_ex, :api_key)
2972
end
73+
74+
@doc """
75+
Generate `access_token` using the `request_token`
76+
77+
## Example
78+
79+
{:ok, user_profile} = KiteConnectEx.User.create_session("request-token")
80+
"""
81+
@spec create_session(String.t()) :: {:ok, %__MODULE__{}} | Response.error()
82+
def create_session(request_token) when is_binary(request_token) do
83+
params = %{
84+
api_key: api_key(),
85+
request_token: request_token,
86+
checksum: generate_checksum(request_token)
87+
}
88+
89+
Request.post(@create_session_path, params, [], request_options())
90+
|> case do
91+
{:ok, user_data} ->
92+
user = %__MODULE__{new(user_data) | original_json: user_data}
93+
94+
{:ok, user}
95+
96+
{:error, error, status} ->
97+
{:error, error, status}
98+
end
99+
end
100+
101+
defp generate_checksum(request_token) do
102+
:crypto.hash(:sha256, api_key() <> request_token <> api_secret())
103+
|> Base.encode16(case: :lower)
104+
end
105+
106+
defp api_secret do
107+
Application.get_env(:kite_connect_ex, :api_secret)
108+
end
109+
110+
defp request_options do
111+
Application.get_env(:kite_connect_ex, :request_options, [])
112+
end
113+
114+
defp new(attributes) when is_map(attributes) do
115+
struct(__MODULE__, %{
116+
access_token: attributes["access_token"],
117+
api_key: attributes["api_key"],
118+
avatar_url: attributes["avatar_url"],
119+
broker: attributes["broker"],
120+
email: attributes["email"],
121+
exchanges: attributes["exchanges"],
122+
login_time: attributes["login_time"],
123+
meta: attributes["meta"],
124+
order_types: attributes["order_types"],
125+
products: attributes["products"],
126+
public_token: attributes["public_token"],
127+
refresh_token: attributes["refresh_token"],
128+
silo: attributes["silo"],
129+
user_id: attributes["user_id"],
130+
user_name: attributes["user_name"],
131+
user_shortname: attributes["user_shortname"],
132+
user_type: attributes["user_type"]
133+
})
134+
end
135+
136+
defp new(_) do
137+
struct(__MODULE__, %{})
138+
end
30139
end

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ defmodule KiteconnectEx.MixProject do
2626
defp deps do
2727
[
2828
{:httpoison, "~> 1.7"},
29-
{:jason, "~> 1.2"}
29+
{:jason, "~> 1.1"}
3030
]
3131
end
3232

0 commit comments

Comments
 (0)