use serde::{Serialize, Deserialize};
use serde_json::{json, Value};
use crate::{session::SessionStore, request::{RequestType}, WechatCommonResponse, LabradorResult, WechatCpClient};
use crate::wechat::cp::constants::{AGENTID, CODE, SNSAPI_BASE, SNSAPI_PRIVATEINFO, SNSAPI_USERINFO, USER_TICKET};
use crate::wechat::cp::method::{CpOauth2Method, WechatCpMethod};
#[derive(Debug, Clone)]
pub struct WechatCpOauth2<'a, T: SessionStore> {
client: &'a WechatCpClient<T>,
}
#[allow(unused)]
impl<'a, T: SessionStore> WechatCpOauth2<'a, T> {
#[inline]
pub fn new(client: &WechatCpClient<T>) -> WechatCpOauth2<T> {
WechatCpOauth2 {
client,
}
}
pub fn build_authorization_url(&self, redirect_uri: &str, scope: &str, state: Option<&str>) -> String {
let mut url = format!("{}?appid={}&redirect_uri={}&response_type=code&scope={}", CpOauth2Method::Oauth2Authorize.get_method(), &self.client.corp_id, urlencoding::encode(redirect_uri), scope);
if SNSAPI_PRIVATEINFO.eq(scope) || SNSAPI_USERINFO.eq(scope) {
url.push_str("&agentid=");
url.push_str(&self.client.agent_id.to_owned().unwrap_or_default().to_string())
}
if let Some(state) = state {
url.push_str("&state=");
url.push_str(state);
}
url.push_str("#wechat_redirect");
url
}
pub fn build_authorization_url_with_state(&self, state: &str) -> String {
self.build_authorization_with_url(&self.client.oauth2_redirect_uri.to_owned().unwrap_or_default(), state.into())
}
pub fn build_authorization_with_url(&self, redirect_uri: &str, state: Option<&str>) -> String {
self.build_authorization_url(redirect_uri, SNSAPI_BASE, state)
}
pub async fn get_user_info(&self, code: &str) -> LabradorResult<WechatCpOauth2UserInfo> {
self.get_user_info_with_agent(code, self.client.agent_id.to_owned().unwrap_or_default()).await
}
pub async fn get_user_info_new(&self, code: &str) -> LabradorResult<WechatCpOauth2UserInfo> {
let v = self.client.get(WechatCpMethod::Oauth2(CpOauth2Method::GetAuthUserInfo), vec![(CODE.to_string(), code.to_string())], RequestType::Json).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatCpOauth2UserInfo>(v)
}
pub async fn get_user_info_with_agent(&self, code: &str, agent_id: i32) -> LabradorResult<WechatCpOauth2UserInfo> {
let agent_id = agent_id.to_string();
let v = self.client.get(WechatCpMethod::Oauth2(CpOauth2Method::GetUserInfo), vec![(CODE.to_string(), code.to_string()), (AGENTID.to_string(), agent_id)], RequestType::Json).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatCpOauth2UserInfo>(v)
}
pub async fn get_user_detail(&self, user_ticket: &str) -> LabradorResult<WechatCpUserDetail> {
let v = self.client.post(WechatCpMethod::Oauth2(CpOauth2Method::GetUserDetail), vec![], json!({USER_TICKET: user_ticket}), RequestType::Json).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatCpUserDetail>(v)
}
pub async fn get_user_detail_new(&self, user_ticket: &str) -> LabradorResult<WechatCpUserDetail> {
let v = self.client.post(WechatCpMethod::Oauth2(CpOauth2Method::GetAuthUserDetail), vec![], json!({USER_TICKET: user_ticket}), RequestType::Json).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatCpUserDetail>(v)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WechatCpOauth2UserInfo {
#[serde(alias = "OpenId", alias = "openid")]
pub openid: Option<String>,
pub external_userid: Option<String>,
#[serde(alias = "UserId", alias = "userid")]
pub user_id: Option<String>,
pub user_ticket: Option<String>,
pub expires_in: Option<i64>,
#[serde(rename = "DeviceId")]
pub device_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WechatCpUserDetail {
pub userid: String,
pub name: Option<String>,
pub mobile: Option<String>,
pub gender: Option<String>,
pub email: Option<String>,
pub avatar: Option<String>,
pub qr_code: Option<String>,
}