line_login_api/api/
mod.rs

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}