br-wechat 0.0.23

This is an wechat
Documentation
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())
        }
    }
}