| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- use axum::{extract::{Query, State}, response::Redirect};
- use crate::{AppState, datasource::Datasource, log, LogLevel::*};
- use serde::Deserialize;
- const APPID: &str = "wx664469117500d259";
- const APPSECRET : &str = "11ec6e6d4b9062f00a4fc08c529293be";
- // const APPSECRET : &str = "wx664469117500d259";
- #[derive(serde::Deserialize)]
- pub struct QueryParams {
- code: String,
- state: String,
- }
- #[allow(dead_code)]
- #[derive(Deserialize)]
- pub struct WxGetToken{
- access_token: String,
- expires_in: usize,
- refresh_token: String,
- openid: String,
- scope:String
- }
- /*
- https://open.weixin.qq.com/connect/oauth2/authorize?appid=
- &redirect_uri=http://192.168.24.101:3000/auth&response_type=code&scope=snsapi_base&state=1#wechat_redirect
- wx664469117500d259
- wxdf57fde70a442828
- */
- #[allow(dead_code)]
- #[derive(Deserialize)]
- pub struct WxUserInfo{
- openid: String,
- nickname: String,
- sex: u16,
- headimgurl: String,
- }
- pub async fn auth(
- // headers: HeaderMap,
- State(state): State<AppState>,
- Query(q): Query<QueryParams>
- ) -> Redirect {
- /*
- 从公众号跳转时会访问 http://{{host}}/api/auth?code={code}&state={state}
- code为获取token所需中间码
- state为授权链接的state用于防止越权,用途不明
- */
- // 访问以获取微信token
- log(Debug, format!("authing code+:`{}` state:`{}`",q.code,q.state));
- // reqwest::Client::builder().build()?.get(url).send().await;
- let webcli = match reqwest::Client::builder()
- .timeout(std::time::Duration::from_secs(3))
- .build()
- {
- Ok(cli) => cli,
- Err(e) => {
- log(Warning, format!("rewest client builder failed:: {e}"));
- return Redirect::to(format!("{}/null",crate::WEBP).as_str())
- }
- };
- log(Debug, format!("web client init"));
- // webcli.get("url").send();
- let a = match webcli.get(format!(
- "https://api.weixin.qq.com/sns/oauth2/access_token?appid={}&secret={}&code={}&grant_type=authorization_code",
- // "https://iotplatform.worldflying.cn/api/wx/auth?appid={}&secret={}&code={}&state={}&grant_type=authorization_code",
- APPID,
- APPSECRET,
- q.code,
- // q.state
- )).send().await {
- Ok(a) => {
- // log(Info, format!("dealing"));
- let v = a.text().await;
- log(Debug, format!("dealing\n{:?}",v));
- let v = if let Ok(v)=v {v}else {
- return Redirect::to(format!("{}/null",crate::WEBP).as_str());
- };
-
- match
- serde_json::from_str::<WxGetToken>(v.as_str())
- // a.json::<WxGetToken>().await
- {
- Ok(b) => b,
- Err(e) =>{
- log(Error, format!("redirect 2 {e}, raw:{v}"));
- return Redirect::to(format!("{}/null",crate::WEBP).as_str())
- }
- }
- },
- Err(e) => {
- log(Debug, format!("redirect 0 {e}"));
- return Redirect::to(format!("{}/null",crate::WEBP).as_str())
- }
- };
- // let host = headers.get("host")
- // .and_then(|hv| hv.to_str().ok())
- // .unwrap_or("localhost:3000");
- log(Debuging, format!("in authing"));
- let token=super::token(32);
- let res = super::check_openid(&state, a.openid.clone()).await;
- if let Ok((id,mqid)) = res{
- // 用户已经注册 函数末尾发生跳转到主页
- if let Err(e) = state.db_lite.execute("update user set token=? where id=?", (token.clone(), id)).await{
- println!("{e}");
- };
- // 已注册时绑定设备
- if let Some(sn)= q.state.strip_prefix("did="){
- log(Debuging, format!("got did: {}",sn));
- if let Err(e) = state.db_lite.execute("update device set belongto=? where sn=? and belongto=0", (id,sn)).await{
- println!("{e}");
- }else if let Ok(did) = state.db_lite.query("select id from device where sn=?", [sn], |r|{r.get::<usize,i64>(0)}).await{
- // if let Some(did)=state.db_lite.last_insert_rowid().await.ok(){ // 错误位置:update不会给last_insert_rowid
- if let Err(e) = state.db_lite.execute("insert into map_user_device (uid, did)values(?,?)", (id,did)).await{
- println!("{e}");
- } else{
- if let Some(mq) = state.mq_detail{
- if let Err(e)=mq.db_mq_map.execute(
- "insert into pub (clientid,topic,deadline)values(?,?,9223372036854775807),(?,?,9223372036854775807)",
- (mqid.clone(),format!("{}/cmd",sn),mqid.clone(),format!("/wf/Iot/device/{sn}"))).await{
- log(Warning, format!("on register with device: {e}"));
- };
-
- if let Err(e)=mq.db_mq_map.execute(
- "insert into sub (clientid,topic,deadline)values(?,?,9223372036854775807),(?,?,9223372036854775807)",
- (mqid.clone(),format!("{}/state",sn),mqid.clone(),format!("/wf/Iot/client/{sn}"))).await{
- log(Warning, format!("on register with device: {e}"));
- };
- }
- }
- };
- }
- } else if a.scope !="snsapi_userinfo"{
- // 用户未注册,跳转获取用户详细信息
- log(Debug, "send redirect for get uinfo".to_string());
- return Redirect::to(
- format!("https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx664469117500d259&redirect_uri=https%3A%2F%2Fwww.worldflying.cn%2Ftools%2Fwxredirect%2Fplc.html&response_type=code&scope=snsapi_userinfo&state={}#wechat_redirect",q.state).as_str()
- // format!("https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx664469117500d259&redirect_uri=https%3A%2F%2Fwww.worldflying.cn%2Ftools%2Fwxredirect%2Fiot.html&response_type=code&scope=snsapi_userinfo&state={}#wechat_redirect",q.state).as_str()
- )
- } else {
- // 带用户信息的重定向收取目标分支,保存用户数据并创建mqtt相关信息
- let b:WxUserInfo = if let Ok(b) = {if let Ok(b) = reqwest::get(format!(
- "https://api.weixin.qq.com/sns/userinfo?access_token={}&openid={}&lang=zh_CN",
- a.access_token,
- a.openid.clone()
- )).await{b.json().await} else {
- log(Info, "redirect 4".to_string());
- return Redirect::to(format!("{}/null",crate::WEBP).as_str())}}{b} else {
- log(Info, "redirect 5".to_string());
- return Redirect::to(format!("{}/null",crate::WEBP).as_str())};
- let mqid = format!("webu{}",super::token(5));
- if let Err(e) = state.db_lite.execute(
- "insert into user (uname,nickname,passwd,headimgurl,openid,sex,token,mqid) values(?,?,?,?,?,?,?,?)",
- (b.nickname.clone(),b.nickname.clone(),"",b.headimgurl,b.openid,b.sex,token.clone(),mqid.clone())).await{
- println!("{e}");
- }
- let uid = match state.db_lite.last_insert_rowid().await{
- Ok(id) => id,
- Err(e) => {
- println!("{e}");
- 0
- }
- };
- if let Err(e) = state.db_lite.execute(
- "insert into area (name,sup,createby)values(?,0,?)",
- (format!("{}的家",b.nickname.clone()),uid)
- ).await{println!("{e}")};
- let area_sup: i64;
- if let Err(e) = state.db_lite.execute(
- "insert into map_user_area (uid,aid)values(?,?)",
- [uid,{area_sup=match state.db_lite.last_insert_rowid().await{Ok(id)=>id,Err(e)=>{println!("{e}");0}};area_sup}]
- ).await{println!("{e}")};
- if let Err(e) = state.db_lite.execute(
- "insert into area (name,sup,createby)values('客厅',?,?)",
- [area_sup,uid]
- ).await{println!("{e}")};
- // 未注册时绑定设备
- if let Some(sn)= q.state.strip_prefix("did="){
- log(Debuging, format!("got did: {}",sn));
- if let Err(e) = state.db_lite.execute("update device set belongto=? where sn=? and belongto=0", (uid,sn)).await{
- println!("{e}");
- }else if let Ok(did) = state.db_lite.query("select id from device where sn=?", [sn], |r|{r.get::<usize,i64>(0)}).await{
- // if let Some(did)=state.db_lite.last_insert_rowid().await.ok(){ // 错误位置:update不会给last_insert_rowid
- if let Err(e) = state.db_lite.execute("insert into map_user_device (uid, did)values(?,?)", (uid,did)).await{
- println!("{e}");
- }
- };
- if let Some(mq) = state.mq_detail{
- if let Err(e)=mq.db_mq_map.execute(
- "insert into pub (clientid,topic,deadline)values(?,?,9223372036854775807),(?,?,9223372036854775807)",
- (mqid.clone(),format!("{}/cmd",sn),mqid.clone(),format!("/wf/Iot/device/{sn}"))).await{
- log(Warning, format!("on register with device: {e}"));
- };
-
- if let Err(e)=mq.db_mq_map.execute(
- "insert into sub (clientid,topic,deadline)values(?,?,9223372036854775807),(?,?,9223372036854775807)",
- (mqid.clone(),format!("{}/state",sn),mqid.clone(),format!("/wf/Iot/client/{sn}"))).await{
- log(Warning, format!("on register with device: {e}"));
- };
- }
- }
- log(Debug, "register success".to_string());
- // 注册成功 函数末尾发生跳转到主页
- // return Redirect::to(format!("http://124.222.106.170/plc_ctrl?token={}#{}",token.clone(),q.state).as_str());
- };
- // request::Request::get("body");
- // log(Info, format!("bad happend {:?}",res));
- log(Debug, format!("redirect back with token, state: {}",q.state));
- return Redirect::to(format!("{}?token={}{}",crate::WEBP,token.clone(),if q.state.starts_with("?"){format!("#{}",q.state)}else{"".to_string()}).as_str());
- // return Redirect::to(format!("{}?token={}",crate::WEBP,token.clone()).as_str());
- }
|