use chrono::Local;
use json::{array, JsonValue, object};
use log::{error, info};
use crate::{WechatMethod};
#[derive(Clone)]
pub struct WeCom {
pub appid: String,
pub agent_id: String,
pub secret: String,
pub access_token: String,
pub expires_in: i64,
}
impl WeCom {
pub fn getuserinfo(&mut self, code: &str) -> Result<JsonValue, String> {
self.access_token()?;
let url = format!("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token={}&code={}", self.access_token, code);
let mut http = br_reqwest::Client::new();
http.get(url.as_str());
let res = http.send().unwrap();
let res = res.json().unwrap();
if res["errcode"].as_i32().unwrap() == 0 {
let mut user_info = self.clone().get_by_userid(res["userid"].to_string().as_str())?;
user_info["openid"] = self.clone().convert_to_openid(res["userid"].to_string().as_str())?["openid"].clone();
Ok(user_info)
} else {
error!("getuserinfo: {}", res["errmsg"].as_str().unwrap());
Err(res["errmsg"].to_string())
}
}
pub fn get_by_userid(&mut self, userid: &str) -> Result<JsonValue,String> {
self.access_token()?;
let url = format!("https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token={}&userid={}", self.access_token, userid);
let mut http = br_reqwest::Client::new();
http.get(url.as_str());
let res = http.send().unwrap();
let res = res.json().unwrap();
let mut user_info = object! {};
if res["errcode"].as_i32().unwrap() == 0 {
user_info = res.clone();
} else {
info!("get_by_userid: {}", res["errmsg"].as_str().unwrap());
}
Ok(user_info)
}
pub fn convert_to_openid(&mut self, userid: &str) -> Result<JsonValue,String> {
self.access_token()?;
let url = format!("https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid?access_token={}", self.access_token);
let mut http = br_reqwest::Client::new();
http.post(url.as_str());
http.raw_json(object! {
"userid": userid
});
let res = http.send().unwrap();
let res = res.json().unwrap();
let mut user_info = object! {};
if res["errcode"].as_i32().unwrap() == 0 {
user_info["userid"] = userid.into();
user_info["openid"] = res["openid"].clone();
} else {
info!("convert_to_openid: {}", res["errmsg"].as_str().unwrap());
}
Ok(user_info)
}
pub fn login_link(&mut self, redirect_uri: &str, state: &str) -> String {
let redirect_uri = urlencoding::encode(redirect_uri);
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);
url
}
pub fn get_department(&mut self) -> Result<JsonValue, String> {
self.access_token()?;
let url = format!("https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token={}", self.access_token);
let mut http = br_reqwest::Client::new();
http.get(url.as_str());
let res = http.send().unwrap();
let mut res = res.json().unwrap();
let mut data = array![];
let mut keys = object! {
"1":""
};
if res["errcode"].as_i32().unwrap() == 0 {
for item in res["department"].members_mut() {
if item["id"] == "1" {
continue;
}
keys[item["id"].to_string()] = item["name"].as_str().unwrap().into();
item["sort"] = item["order"].to_string().into();
item["org_dept"] = keys[item["parentid"].to_string()].clone();
data.push(object! {
name:item["name"].clone(),
org_dept:item["org_dept"].clone(),
sort:item["sort"].clone(),
code:item["id"].clone(),
}).unwrap();
}
Ok(data)
} else {
error!("convert_to_openid: {}", res["errmsg"].as_str().unwrap());
Err(res["errmsg"].to_string())
}
}
pub fn get_simplelist(&mut self, department_id: &str) -> Result<JsonValue, String> {
self.access_token()?;
let url = format!("https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token={}&department_id={}", self.access_token, department_id);
let mut http = br_reqwest::Client::new();
http.post(url.as_str());
http.raw_json(object! {});
let res = http.send().unwrap();
let mut res = res.json().unwrap();
let mut data = array![];
if res["errcode"].as_i32().unwrap() == 0 {
for item in res["userlist"].members_mut() {
item.remove("department");
data.push(object! {
name:item["name"].clone(),
account:item["userid"].clone()
}).unwrap();
}
Ok(data)
} else {
error!("convert_to_openid: {}", res["errmsg"].as_str().unwrap());
Err(res["errmsg"].to_string())
}
}
pub fn get_simplelist_details(&mut self, department_id: &str) -> Result<JsonValue,String> {
self.access_token()?;
let url = format!("https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token={}&department_id={}", self.access_token, department_id);
let mut http = br_reqwest::Client::new();
http.post(url.as_str());
http.raw_json(object! {});
let res = http.send().unwrap();
let mut res = res.json().unwrap();
let mut data = array![];
if res["errcode"].as_i32().unwrap() == 0 {
for item in res["userlist"].members_mut() {
data.push(object! {
status:item["status"].clone(),
position:item["position"].clone(),
department:item["department"].clone(),
name:item["name"].clone(),
account:item["userid"].clone()
}).unwrap();
}
Ok(data)
} else {
error!("convert_to_openid: {}", res["errmsg"].as_str().unwrap());
Err(res["errmsg"].to_string())
}
}
}
impl WechatMethod for WeCom {
fn access_token(&mut self) -> Result<JsonValue, String> {
let dt = Local::now();
let timestamp = dt.timestamp_millis();
if self.expires_in > timestamp {
return Ok(object! {
appid: self.appid.clone(),
access_token: self.access_token.clone(),
expires_in: self.expires_in
});
}
let url = format!("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={}&corpsecret={}", self.appid, self.secret);
let mut http = br_reqwest::Client::new();
http.get(url.as_str());
let res = match http.send() {
Ok(e) => e,
Err(e) => return Err(format!("Failed to get token from {}", e)),
};
let res = match res.json() {
Ok(e) => e,
Err(e) => return Err(format!("Failed to get token from {}", e)),
};
if res["errcode"].as_i32().unwrap() == 0 {
self.access_token = res["access_token"].to_string();
self.expires_in = timestamp + res["expires_in"].as_i64().unwrap();
Ok(object! {
appid: self.appid.clone(),
access_token: self.access_token.clone(),
expires_in: self.expires_in
})
} else {
info!("access_token: {}", res["errmsg"].as_str().unwrap());
Err(format!("access_token: {}", res["errmsg"].as_str().unwrap()))
}
}
fn check(&mut self) -> Result<bool, String> {
self.access_token()?;
Ok(true)
}
fn login(&mut self, _code: &str) -> Result<JsonValue, String> {
todo!()
}
fn getuserinfo(&mut self, _code: &str) -> Result<JsonValue, String> {
todo!()
}
}