br_wechat/
applet.rs

1use chrono::Local;
2use json::{JsonValue, object};
3use log::info;
4use crate::{WechatMethod, ACCOUNT};
5
6#[derive(Clone)]
7pub struct Applet {
8    pub appid: String,
9    pub secret: String,
10    pub access_token: String,
11    pub expires_in: i64,
12}
13
14impl Applet {
15    fn access_token(&mut self) -> Result<String, String> {
16        let dt = Local::now();
17        let timestamp = dt.timestamp_millis();
18        if self.expires_in > timestamp {
19            return Ok(self.access_token.clone());
20        }
21        let url = format!("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", self.appid, self.secret);
22        let mut http = br_reqwest::Client::new();
23        http.get(url.as_str());
24        let res = http.send()?.json()?;
25        if res["errcode"].is_empty() {
26            self.access_token = res["access_token"].to_string();
27            self.expires_in = timestamp + res["expires_in"].as_i64().unwrap();
28            {
29                ACCOUNT.write().unwrap().get_mut(&self.appid.clone()).unwrap().access_token = self.access_token.clone();
30                ACCOUNT.write().unwrap().get_mut(&self.appid.clone()).unwrap().expires_in = self.expires_in;
31            }
32            Ok(self.access_token.clone())
33        } else {
34            Err(res["errmsg"].to_string())
35        }
36    }
37}
38
39impl WechatMethod for Applet {
40    fn check(&mut self) -> Result<bool, String> {
41        match self.access_token() {
42            Ok(_) => Ok(true),
43            Err(e) => Err(e),
44        }
45    }
46    /// 获取访问用户身份
47    fn code2_session(&mut self, code: &str) -> Result<JsonValue, String> {
48        let url = "https://api.weixin.qq.com/sns/jscode2session".to_string();
49        let mut http = br_reqwest::Client::new();
50        http.get(url.as_str()).raw_json(object! {
51            appid:self.appid.clone(),
52            secret:self.secret.clone(),
53            js_code:code,
54            grant_type:"authorization_code"
55        });
56        let res = http.send()?;
57        let res = res.json()?;
58        let mut user_info = object! {};
59        let res = json::parse(res.as_str().unwrap()).unwrap();
60        if res["errcode"].is_empty() {
61            user_info["session_key"] = res["session_key"].clone();
62            user_info["unionid"] = res["unionid"].as_str().unwrap_or("").into();
63            user_info["openid"] = res["openid"].clone();
64        } else {
65            info!("code2_session: {}", res["errmsg"].as_str().unwrap());
66        }
67        Ok(user_info)
68    }
69    fn login(&mut self, code: &str) -> Result<JsonValue, String> {
70        let mut http = br_reqwest::Client::new();
71        http.get("https://api.weixin.qq.com/sns/jscode2session".to_string().as_str());
72        http.header("Accept", "application/json");
73        http.header("User-Agent", "api");
74        http.header("Content-Type", "application/json");
75        http.query(object! {
76                appid: self.appid.as_str(),
77                secret: self.secret.as_str(),
78                js_code:code,
79                grant_type:"authorization_code",
80        });
81        match http.send()?.json() {
82            Ok(e) => Ok(e),
83            Err(e) => Err(e),
84        }
85    }
86    /// 获取手机号
87    fn get_phone_number(&mut self, iv: &str, encrypted_data: &str, session_key: &str) -> Result<JsonValue, String> {
88        let data = br_crypto::aes::aes_128_cbc(iv, encrypted_data, session_key)?;
89        let mut data = json::parse(&data).unwrap();
90        data["phone"] = data["purePhoneNumber"].clone();
91        Ok(data)
92    }
93
94    /// 获取访问用户身份
95    fn getuserinfo(&mut self, code: &str) -> Result<JsonValue, String> {
96        let url = format!("https://api.weixin.qq.com/wxa/getpluginopenpid?access_token={}", self.access_token()?);
97        let mut http = br_reqwest::Client::new();
98        http.post(url.as_str());
99        http.raw_json(object! {
100            code:code
101        });
102        let res = http.send()?;
103        let res = res.json()?;
104        let mut user_info = object! {};
105        if res["errcode"].as_i32().unwrap() == 0 {
106            user_info["userid"] = res["userid"].clone();
107            user_info["user_ticket"] = res["user_ticket"].clone();
108        } else {
109            info!("getuserinfo: {}", res["errmsg"].as_str().unwrap());
110        }
111        Ok(user_info)
112    }
113    fn send_message(&mut self, template_id: &str, page: &str, touser: &str, data: JsonValue, miniprogram_state: &str, lang: &str) -> Result<JsonValue, String> {
114        let lang = if lang.is_empty() { "zh_CN" } else { lang };
115        let miniprogram_state = if miniprogram_state.is_empty() { "formal" } else { miniprogram_state };
116        let url = format!("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={}", self.access_token()?);
117        let mut http = br_reqwest::Client::new();
118        http.post(url.as_str());
119        http.raw_json(object! {
120            access_token:self.access_token()?,
121            template_id:template_id,
122            page:page,
123            touser:touser,
124            data:data,
125            miniprogram_state:miniprogram_state,
126            lang:lang
127        });
128        let res = http.send()?;
129        let res = res.json()?;
130        if res["errcode"].as_i32().unwrap() == 0 {
131            Ok(res)
132        } else {
133            Err(res["errmsg"].to_string())
134        }
135    }
136}