use chrono::Local;
use json::{JsonValue, object};
use log::{error, info};
use crate::{WechatMethod};
#[derive(Clone)]
pub struct Applet {
pub appid: String,
pub secret: String,
pub access_token: String,
pub expires_in: i64,
}
impl Applet {
fn access_token(&mut self) -> Result<String, String> {
let dt = Local::now();
let timestamp = dt.timestamp_millis();
if self.expires_in > timestamp {
return Ok(self.access_token.clone());
}
let url = format!("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", self.appid, self.secret);
let mut http = br_reqwest::Client::new();
http.get(url.as_str());
let res = http.send()?.json()?;
if res["errcode"].is_empty() {
self.access_token = res["access_token"].to_string();
self.expires_in = timestamp + res["expires_in"].as_i64().unwrap();
Ok(self.access_token.clone())
} else {
Err(res["errmsg"].to_string())
}
}
}
impl WechatMethod for Applet {
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://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", self.appid, self.secret);
let mut http = br_reqwest::Client::new();
http.get(url.as_str());
let res = http.send()?.json()?;
if res["errcode"].is_empty() {
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 {
Err(res["errmsg"].to_string())
}
}
fn check(&mut self) -> Result<bool, String> {
match self.access_token() {
Ok(_) => Ok(true),
Err(e) => Err(e),
}
}
fn code2_session(&mut self, code: &str) -> Result<JsonValue, String> {
let url = "https://api.weixin.qq.com/sns/jscode2session".to_string();
let mut http = br_reqwest::Client::new();
http.get(url.as_str()).raw_json(object! {
appid:self.appid.clone(),
secret:self.secret.clone(),
js_code:code,
grant_type:"authorization_code"
});
let res = http.send()?;
let res = res.json()?;
let mut user_info = object! {};
let res = json::parse(res.as_str().unwrap()).unwrap();
if res["errcode"].is_empty() {
user_info["session_key"] = res["session_key"].clone();
user_info["unionid"] = res["unionid"].as_str().unwrap_or("").into();
user_info["openid"] = res["openid"].clone();
} else {
info!("code2_session: {}", res["errmsg"].as_str().unwrap());
}
Ok(user_info)
}
fn login(&mut self, code: &str) -> Result<JsonValue, String> {
let mut http = br_reqwest::Client::new();
http.get("https://api.weixin.qq.com/sns/jscode2session".to_string().as_str());
http.header("Accept", "application/json");
http.header("User-Agent", "api");
http.header("Content-Type", "application/json");
http.query(object! {
appid: self.appid.as_str(),
secret: self.secret.as_str(),
js_code:code,
grant_type:"authorization_code",
});
match http.send()?.json() {
Ok(e) => Ok(e),
Err(e) => Err(e),
}
}
fn get_phone_number(&mut self, iv: &str, encrypted_data: &str, session_key: &str) -> Result<JsonValue, String> {
let data = br_crypto::aes::aes_128_cbc(iv, encrypted_data, session_key)?;
let mut data = json::parse(&data).unwrap();
data["phone"] = data["purePhoneNumber"].clone();
Ok(data)
}
fn getuserinfo(&mut self, code: &str) -> Result<JsonValue, String> {
self.access_token()?;
let url = format!("https://api.weixin.qq.com/wxa/getpluginopenpid?access_token={}", self.access_token);
let mut http = br_reqwest::Client::new();
http.post(url.as_str());
http.raw_json(object! {
code:code
});
let res = http.send()?;
let res = res.json()?;
let mut user_info = object! {};
if res["errcode"].as_i32().unwrap() == 0 {
user_info["userid"] = res["userid"].clone();
user_info["user_ticket"] = res["user_ticket"].clone();
Ok(user_info)
} else {
error!("getuserinfo: {}", res["errmsg"].as_str().unwrap());
Err(res["errmsg"].to_string())
}
}
fn send_message(&mut self, template_id: &str, page: &str, touser: &str, data: JsonValue, miniprogram_state: &str, lang: &str) -> Result<JsonValue, String> {
self.access_token()?;
let lang = if lang.is_empty() { "zh_CN" } else { lang };
let miniprogram_state = if miniprogram_state.is_empty() { "formal" } else { miniprogram_state };
let url = format!("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={}", self.access_token);
let mut http = br_reqwest::Client::new();
http.post(url.as_str());
http.raw_json(object! {
access_token:self.access_token()?,
template_id:template_id,
page:page,
touser:touser,
data:data,
miniprogram_state:miniprogram_state,
lang:lang
});
let res = http.send()?;
let res = res.json()?;
if res["errcode"].as_i32().unwrap() == 0 {
Ok(res["errmsg"].clone())
} else {
Err(res["errmsg"].to_string())
}
}
}