1use crate::{LineApiResponse, LineLoginClient};
2use serde::{Deserialize, Serialize};
3use serde_json::json;
4
5impl LineLoginClient {
6 pub async fn create_token(
7 &self,
8 code: &str,
9 redirect_uri: &str,
10 ) -> LineApiResponse<LineLoginCreateTokenResponse> {
11 let req = LineLoginCreateTokenRequest {
12 grant_type: "authorization_code".to_string(),
13 code: code.to_string(),
14 redirect_uri: redirect_uri.to_string(),
15 client_id: self.client_id(),
16 client_secret: self.client_secret(),
17 code_verifier: None,
18 };
19
20 self.http_post("https://api.line.me/oauth2/v2.1/token", req, "")
21 .await
22 }
23
24 pub async fn token_verify(&self, token: &str) -> LineApiResponse<LineLoginTokenVerifyResponse> {
25 self.http_get(
26 format!(
27 "https://api.line.me/oauth2/v2.1/verify?access_token={}",
28 token
29 )
30 .as_str(),
31 &json!({}),
32 "",
33 )
34 .await
35 }
36 pub async fn update_access_token(
37 &self,
38 refresh_token: &str,
39 ) -> LineApiResponse<LineLoginUpdateAccessTokenResponse> {
40 let req = LineLoginUpdateAccessTokenRequest {
41 grant_type: "refresh_token".to_string(),
42 refresh_token: refresh_token.to_string(),
43 client_id: self.client_id(),
44 client_secret: self.client_secret(),
45 };
46
47 self.http_post("https://api.line.me/oauth2/v2.1/token", json!(req), "")
48 .await
49 }
50 pub async fn revoke_access_token(&self, access_token: &str) -> LineApiResponse<()> {
51 let req = LineLoginRevokeAccessTokenRequest {
52 access_token: access_token.to_string(),
53 client_id: self.client_id(),
54 client_secret: self.client_secret(),
55 };
56 let res: LineApiResponse<LineLoginEmptyResponse> = self
57 .http_post("https://api.line.me/oauth2/v2.1/revoke", json!(req), "")
58 .await;
59
60 match res {
61 Ok(_) => Ok(()),
62 Err(e) => {
63 if e.status() == 200 {
64 Ok(())
65 } else {
66 Err(e)
67 }
68 }
69 }
70 }
71 pub async fn id_token_verify(
72 &self,
73 id_token: &str,
74 nonce: Option<String>,
75 user_id: Option<String>,
76 ) -> LineApiResponse<LineLoginIdTokenVerifyResponse> {
77 let client_id = self.client_id();
78 let req = LineLoginIdTokenVerifyRequest {
79 id_token: id_token.to_string(),
80 client_id,
81 nonce,
82 user_id,
83 };
84 self.http_post("https://api.line.me/oauth2/v2.1/verify", req, "")
85 .await
86 }
87 pub async fn user_info(
88 &self,
89 access_token: &str,
90 ) -> LineApiResponse<LineLoginUserInfoResponse> {
91 self.http_get(
92 "https://api.line.me/oauth2/v2.1/userinfo",
93 &json!({}),
94 access_token,
95 )
96 .await
97 }
98 pub async fn profile(&self, access_token: &str) -> LineApiResponse<LineLoginProfileResponse> {
99 self.http_get("https://api.line.me/v2/profile", &json!({}), access_token)
100 .await
101 }
102 pub async fn friend_ship(&self, access_token: &str) -> LineApiResponse<LineLoginFriendShip> {
103 self.http_get(
104 "https://api.line.me/friendship/v1/status",
105 &json!({}),
106 access_token,
107 )
108 .await
109 }
110}
111
112#[derive(Debug, Default, Deserialize, Serialize, Clone)]
113pub struct LineLoginEmptyResponse {}
114
115#[derive(Debug, Default, Deserialize, Serialize, Clone)]
116pub struct LineLoginCreateTokenRequest {
117 pub grant_type: String,
118 pub code: String,
119 pub redirect_uri: String,
120 pub client_id: String,
121 pub client_secret: String,
122 #[serde(skip_serializing_if = "Option::is_none")]
123 code_verifier: Option<String>,
124}
125
126#[derive(Debug, Default, Deserialize, Serialize, Clone)]
127pub struct LineLoginCreateTokenResponse {
128 pub access_token: String,
129 pub expires_in: u64,
130 pub id_token: String,
131 pub refresh_token: String,
132 pub scope: String,
133 pub token_type: String,
134}
135
136#[derive(Debug, Default, Deserialize, Serialize, Clone)]
137pub struct LineLoginTokenVerifyResponse {
138 pub scope: String,
139 pub client_id: String,
140 pub expires_in: u64,
141}
142
143#[derive(Debug, Default, Deserialize, Serialize, Clone)]
144struct LineLoginUpdateAccessTokenRequest {
145 pub grant_type: String,
146 pub refresh_token: String,
147 pub client_id: String,
148 pub client_secret: String,
149}
150
151#[derive(Debug, Default, Deserialize, Serialize, Clone)]
152pub struct LineLoginUpdateAccessTokenResponse {
153 pub token_type: String,
154 pub access_token: String,
155 pub refresh_token: String,
156 pub expires_in: u64,
157 pub scope: String,
158}
159
160#[derive(Debug, Default, Deserialize, Serialize, Clone)]
161struct LineLoginRevokeAccessTokenRequest {
162 pub access_token: String,
163 pub client_id: String,
164 pub client_secret: String,
165}
166
167#[derive(Debug, Default, Deserialize, Serialize, Clone)]
168pub struct LineLoginIdTokenVerifyRequest {
169 pub id_token: String,
170 pub client_id: String,
171 #[serde(skip_serializing_if = "Option::is_none")]
172 pub nonce: Option<String>,
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub user_id: Option<String>,
175}
176
177#[derive(Debug, Default, Deserialize, Serialize, Clone)]
178pub struct LineLoginIdTokenVerifyResponse {
179 pub iss: String,
180 pub sub: String,
181 pub aud: String,
182 pub exp: u64,
183 pub iat: u64,
184 #[serde(skip_serializing_if = "Option::is_none")]
185 pub auth_time: Option<u64>,
186 #[serde(skip_serializing_if = "Option::is_none")]
187 pub nonce: Option<String>,
188 #[serde(skip_serializing_if = "Option::is_none")]
189 pub amr: Option<Vec<String>>,
190 #[serde(skip_serializing_if = "Option::is_none")]
191 pub name: Option<String>,
192 #[serde(skip_serializing_if = "Option::is_none")]
193 pub picture: Option<String>,
194 #[serde(skip_serializing_if = "Option::is_none")]
195 pub email: Option<String>,
196}
197
198#[derive(Debug, Default, Deserialize, Serialize, Clone)]
199pub struct LineLoginUserInfoResponse {
200 pub sub: String,
201 #[serde(skip_serializing_if = "Option::is_none")]
202 pub name: Option<String>,
203 #[serde(skip_serializing_if = "Option::is_none")]
204 pub picture: Option<String>,
205}
206
207#[derive(Debug, Default, Deserialize, Serialize, Clone)]
208pub struct LineLoginProfileResponse {
209 #[serde(rename = "userId")]
210 pub user_id: String,
211 #[serde(rename = "displayName")]
212 pub display_name: String,
213 #[serde(skip_serializing_if = "Option::is_none")]
214 #[serde(rename = "pictureUrl")]
215 pub picture_url: Option<String>,
216 #[serde(skip_serializing_if = "Option::is_none")]
217 #[serde(rename = "statusMessage")]
218 pub status_message: Option<String>,
219}
220
221#[derive(Debug, Default, Deserialize, Serialize, Clone)]
222pub struct LineLoginFriendShip {
223 #[serde(rename = "friendFlag")]
224 pub friend_flag: bool,
225}