br_wechat/
wecom.rs

1use chrono::Local;
2use json::{array, JsonValue, object};
3use log::{error, info};
4use crate::{WechatMethod};
5
6#[derive(Clone)]
7pub struct WeCom {
8    pub appid: String,
9    pub agent_id: String,
10    pub secret: String,
11    pub access_token: String,
12    pub expires_in: i64,
13}
14
15impl WeCom {
16    /// 获取访问用户身份
17    pub fn getuserinfo(&mut self, code: &str) -> Result<JsonValue, String> {
18        self.access_token()?;
19        let url = format!("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token={}&code={}", self.access_token, code);
20        let mut http = br_reqwest::Client::new();
21        http.get(url.as_str());
22        let res = http.send().unwrap();
23        let res = res.json().unwrap();
24
25        if res["errcode"].as_i32().unwrap() == 0 {
26            let mut user_info = self.clone().get_by_userid(res["userid"].to_string().as_str())?;
27            user_info["openid"] = self.clone().convert_to_openid(res["userid"].to_string().as_str())?["openid"].clone();
28            Ok(user_info)
29        } else {
30            error!("getuserinfo: {}", res["errmsg"].as_str().unwrap());
31            Err(res["errmsg"].to_string())
32        }
33    }
34
35    /// 获取成员详细信息
36    pub fn get_by_userid(&mut self, userid: &str) -> Result<JsonValue,String> {
37        self.access_token()?;
38        let url = format!("https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token={}&userid={}", self.access_token, userid);
39        let mut http = br_reqwest::Client::new();
40        http.get(url.as_str());
41        let res = http.send().unwrap();
42        let res = res.json().unwrap();
43        let mut user_info = object! {};
44        if res["errcode"].as_i32().unwrap() == 0 {
45            user_info = res.clone();
46        } else {
47            info!("get_by_userid: {}", res["errmsg"].as_str().unwrap());
48        }
49        Ok(user_info)
50    }
51
52    pub fn convert_to_openid(&mut self, userid: &str) -> Result<JsonValue,String> {
53        self.access_token()?;
54        let url = format!("https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid?access_token={}", self.access_token);
55        let mut http = br_reqwest::Client::new();
56        http.post(url.as_str());
57        http.raw_json(object! {
58            "userid": userid
59        });
60        let res = http.send().unwrap();
61        let res = res.json().unwrap();
62        let mut user_info = object! {};
63        if res["errcode"].as_i32().unwrap() == 0 {
64            user_info["userid"] = userid.into();
65            user_info["openid"] = res["openid"].clone();
66        } else {
67            info!("convert_to_openid: {}", res["errmsg"].as_str().unwrap());
68        }
69        Ok(user_info)
70    }
71
72    pub fn login_link(&mut self, redirect_uri: &str, state: &str) -> String {
73        let redirect_uri = urlencoding::encode(redirect_uri);
74        let url = format!("https://login.work.weixin.qq.com/wwlogin/sso/login?appid={}&redirect_uri={redirect_uri}&state={}&login_type=CorpApp&agentid={}", self.appid, state, self.agent_id);
75        url
76    }
77    pub fn get_department(&mut self) -> Result<JsonValue, String> {
78        self.access_token()?;
79        let url = format!("https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token={}", self.access_token);
80        let mut http = br_reqwest::Client::new();
81        http.get(url.as_str());
82        let res = http.send().unwrap();
83        let mut res = res.json().unwrap();
84        let mut data = array![];
85
86        let mut keys = object! {
87            "1":""
88        };
89        if res["errcode"].as_i32().unwrap() == 0 {
90            for item in res["department"].members_mut() {
91                // let userlist = self.get_simplelist(item["id"].to_string().as_str().clone());
92                if item["id"] == "1" {
93                    continue;
94                }
95                keys[item["id"].to_string()] = item["name"].as_str().unwrap().into();
96                item["sort"] = item["order"].to_string().into();
97                item["org_dept"] = keys[item["parentid"].to_string()].clone();
98
99                data.push(object! {
100                    name:item["name"].clone(),
101                    org_dept:item["org_dept"].clone(),
102                    sort:item["sort"].clone(),
103                    code:item["id"].clone(),
104                }).unwrap();
105            }
106            Ok(data)
107        } else {
108            error!("convert_to_openid: {}", res["errmsg"].as_str().unwrap());
109            Err(res["errmsg"].to_string())
110        }
111    }
112    pub fn get_simplelist(&mut self, department_id: &str) -> Result<JsonValue, String> {
113        self.access_token()?;
114        let url = format!("https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token={}&department_id={}", self.access_token, department_id);
115
116        let mut http = br_reqwest::Client::new();
117        http.post(url.as_str());
118        http.raw_json(object! {});
119        let res = http.send().unwrap();
120        let mut res = res.json().unwrap();
121
122        let mut data = array![];
123        if res["errcode"].as_i32().unwrap() == 0 {
124            for item in res["userlist"].members_mut() {
125                item.remove("department");
126                data.push(object! {
127                    name:item["name"].clone(),
128                    account:item["userid"].clone()
129                }).unwrap();
130            }
131            Ok(data)
132        } else {
133            error!("convert_to_openid: {}", res["errmsg"].as_str().unwrap());
134            Err(res["errmsg"].to_string())
135        }
136    }
137    pub fn get_simplelist_details(&mut self, department_id: &str) -> Result<JsonValue,String> {
138        self.access_token()?;
139        let url = format!("https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token={}&department_id={}", self.access_token, department_id);
140        let mut http = br_reqwest::Client::new();
141        http.post(url.as_str());
142        http.raw_json(object! {});
143        let res = http.send().unwrap();
144        let mut res = res.json().unwrap();
145        let mut data = array![];
146        if res["errcode"].as_i32().unwrap() == 0 {
147            for item in res["userlist"].members_mut() {
148                data.push(object! {
149                    status:item["status"].clone(),
150                    position:item["position"].clone(),
151                    department:item["department"].clone(),
152                    name:item["name"].clone(),
153                    account:item["userid"].clone()
154                }).unwrap();
155            }
156            Ok(data)
157        } else {
158            error!("convert_to_openid: {}", res["errmsg"].as_str().unwrap());
159            Err(res["errmsg"].to_string())
160        }
161    }
162}
163
164impl WechatMethod for WeCom {
165    fn access_token(&mut self) -> Result<JsonValue, String> {
166        let dt = Local::now();
167        let timestamp = dt.timestamp_millis();
168        if self.expires_in > timestamp {
169            return Ok(object! {
170                appid: self.appid.clone(),
171                access_token: self.access_token.clone(),
172                expires_in: self.expires_in
173            });
174        }
175        let url = format!("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={}&corpsecret={}", self.appid, self.secret);
176        let mut http = br_reqwest::Client::new();
177        http.get(url.as_str());
178        let res = match http.send() {
179            Ok(e) => e,
180            Err(e) => return Err(format!("Failed to get token from {}", e)),
181        };
182        let res = match res.json() {
183            Ok(e) => e,
184            Err(e) => return Err(format!("Failed to get token from {}", e)),
185        };
186        if res["errcode"].as_i32().unwrap() == 0 {
187            self.access_token = res["access_token"].to_string();
188            self.expires_in = timestamp + res["expires_in"].as_i64().unwrap();
189            Ok(object! {
190                appid: self.appid.clone(),
191                access_token: self.access_token.clone(),
192                expires_in: self.expires_in
193            })
194        } else {
195            info!("access_token: {}", res["errmsg"].as_str().unwrap());
196            Err(format!("access_token: {}", res["errmsg"].as_str().unwrap()))
197        }
198    }
199
200
201    fn check(&mut self) -> Result<bool, String> {
202        self.access_token()?;
203        Ok(true)
204    }
205
206    fn login(&mut self, _code: &str) -> Result<JsonValue, String> {
207        todo!()
208    }
209
210    fn getuserinfo(&mut self, _code: &str) -> Result<JsonValue, String> {
211        todo!()
212    }
213}