1use bytes::Bytes;
2use serde::{Serialize, Deserialize};
3use serde_json::{json, Value};
4
5use crate::{session::SessionStore, request::{RequestType}, WechatCommonResponse, LabradorResult, WechatCrypto, current_timestamp, LabraError, JsapiTicket, JsapiSignature, get_timestamp, get_nonce_str, APIClient, WechatRequest, LabraResponse, LabraRequest, SimpleStorage, WechatCpProviderToken};
6use crate::wechat::cp::constants::{ACCESS_TOKEN, ACCESS_TOKEN_KEY, AGENT_CONFIG, AUTH_URL_INSTALL, PROVIDER_ACCESS_TOKEN, SUITE_ACCESS_TOKEN, TYPE};
7use crate::wechat::cp::method::WechatCpMethod;
8use crate::wechat::cp::AccessTokenResponse;
9
10mod tag;
11mod license;
12mod media;
13mod department;
14mod user;
15mod order;
16mod agent;
17mod auth;
18
19pub use tag::*;
20pub use license::*;
21pub use media::*;
22pub use department::*;
23pub use user::*;
24pub use order::*;
25pub use agent::*;
26use crate::wechat::cp::tp::auth::WechatCpTpAuth;
27
28
29#[allow(unused)]
31#[derive(Debug, Clone)]
32pub struct WechatCpTpClient<T: SessionStore> {
33 token: Option<String>,
34 corp_id: String,
36 aes_key: Option<String>,
38 provider_secret: Option<String>,
40 agent_id: Option<i32>,
41 suite_id: Option<String>,
43 suite_secret: Option<String>,
44 client: APIClient<T>,
45}
46
47#[allow(unused)]
48impl<T: SessionStore> WechatCpTpClient<T> {
49 fn from_client(client: APIClient<T>) -> WechatCpTpClient<T> {
50 WechatCpTpClient {
51 corp_id: client.app_key.to_owned(),
52 token: None,
53 aes_key: None,
54 agent_id: None,
55 suite_id: None,
56 suite_secret: None,
57 client,
58 provider_secret: None,
59 }
60 }
61
62 pub fn aes_key(mut self, aes_key: &str) -> Self {
63 self.aes_key = aes_key.to_string().into();
64 self
65 }
66
67 pub fn token(mut self, token: &str) -> Self {
68 self.token = token.to_string().into();
69 self
70 }
71
72 pub fn agent_id(mut self, agent_id: i32) -> Self {
73 self.agent_id = agent_id.into();
74 self
75 }
76
77 pub fn provider_secret(mut self, provider_secret: &str) -> Self {
78 self.provider_secret = provider_secret.to_string().into();
79 self
80 }
81
82 pub fn suite_id(mut self, suite_id: &str) -> Self {
83 self.suite_id = suite_id.to_string().into();
84 self
85 }
86
87 pub fn suite_secret(mut self, suite_secret: &str) -> Self {
88 self.suite_secret = suite_secret.to_string().into();
89 self
90 }
91
92 pub fn get_corpid(&self) -> &str {
93 &self.corp_id
94 }
95
96 fn key_with_prefix(&self, key: &str) -> String {
97 format!("cp:{}:{}", self.suite_id.to_owned().unwrap_or_default(), key)
98 }
99
100 pub fn new<S: Into<String>>(crop_id: S) -> WechatCpTpClient<SimpleStorage> {
102 let client = APIClient::<SimpleStorage>::from_session(crop_id.into(), "", "https://qyapi.weixin.qq.com", SimpleStorage::new());
103 WechatCpTpClient::<SimpleStorage>::from_client(client)
104 }
105
106 pub fn from_session<S: Into<String>>(crop_id: S, session: T) -> WechatCpTpClient<T> {
108 let client = APIClient::from_session(crop_id.into(), "", "https://qyapi.weixin.qq.com", session);
109 Self::from_client(client)
110 }
111
112 fn get_access_token(&self, auth_corp_id: &str) -> String {
114 let session = self.client.session();
115 session.get::<_, String>(self.key_with_prefix(auth_corp_id) + ACCESS_TOKEN_KEY, None).unwrap_or(None).unwrap_or_default()
116 }
117
118 pub fn check_signature(&self, signature: &str, timestamp: i64, nonce: &str, data: &str) -> LabradorResult<bool> {
123 let crp = WechatCrypto::new(&self.aes_key.to_owned().unwrap_or_default()).token(&self.token.to_owned().unwrap_or_default());
124 let _ = crp.check_signature(signature, timestamp, nonce, data)?;
125 Ok(true)
126 }
127
128 pub fn get_crypto(&self) -> WechatCrypto {
130 let crp = WechatCrypto::new(&self.aes_key.to_owned().unwrap_or_default()).token(&self.token.to_owned().unwrap_or_default());
131 crp
132 }
133
134 pub fn get_suite_ticket(&self) -> LabradorResult<String> {
137 let session = self.client.session();
138 let token_key = format!("{}_suite_ticket_key_cp", self.corp_id);
139 let expires_key = format!("{}_suite_ticket_expires_at_cp", self.corp_id);
140 let token: String = session.get(&token_key, Some("".to_owned()))?.unwrap_or_default();
141 let timestamp = current_timestamp();
142 let expires_at: i64 = session.get(&expires_key, Some(timestamp))?.unwrap_or_default();
143 if expires_at <= timestamp {
144 return Err(LabraError::ApiError("invaild suite ticket".to_string()));
145 }
146 Ok(token)
147 }
148
149 pub fn set_suite_ticket_expire(&self, suite_ticket: &str, expire_second: i64) -> LabradorResult<()> {
152 let expires_at = current_timestamp() + expire_second;
153 let session = self.client.session();
154 let token_key = format!("{}_suite_ticket_key_cp", self.corp_id);
155 let expires_key = format!("{}_suite_ticket_expires_at_cp", self.corp_id);
156 session.set(token_key.to_string(), suite_ticket, Some(expire_second as usize))?;
157 session.set(expires_key, expires_at, Some(expire_second as usize))?;
158 Ok(())
159 }
160
161 pub fn set_suite_ticket(&self, suite_ticket: &str) -> LabradorResult<()> {
169 self.set_suite_ticket_expire(suite_ticket, 28 * 60)
170 }
171
172 pub async fn get_suite_access_token(&self) -> LabradorResult<String> {
180 self.get_suite_access_token_force(false).await
181 }
182
183 pub async fn get_suite_access_token_force(&self, force_refresh: bool) -> LabradorResult<String> {
190 let session = self.client.session();
191 let token_key = format!("{}_suite_access_token_cp", self.corp_id);
192 let expires_key = format!("{}_suite_access_token_expires_at_cp", self.corp_id);
193 let token: String = session.get(&token_key, Some("".to_owned()))?.unwrap_or_default();
194 let timestamp = current_timestamp();
195 let expires_at: i64 = session.get(&expires_key, Some(timestamp))?.unwrap_or_default();
196 if expires_at <= timestamp || force_refresh {
197 let suite_ticket = self.get_suite_ticket().unwrap_or_default();
198 let req = json!({
199 "suite_id": self.suite_id,
200 "suite_secret": self.suite_secret,
201 "suite_ticket": suite_ticket
202 });
203 let result = self.client.post(WechatCpMethod::GetSuiteToken, vec![], req, RequestType::Json).await?.json::<Value>()?;
204 let result = WechatCommonResponse::parse::<WechatCpSuiteAccessTokenResponse>(result)?;
205 let token = result.suite_access_token;
206 let expires_in = result.expires_in;
207 let expires_at = current_timestamp() + expires_in - 200;
209 session.set(&token_key, token.to_owned(), Some(expires_in as usize));
210 session.set(&expires_key, expires_at, Some(expires_in as usize));
211 Ok(token.to_string())
212 } else {
213 Ok(token)
214 }
215 }
216
217 pub async fn get_suite_jsapi_ticket(&self, auth_corp_id: &str) -> LabradorResult<String> {
222 self.get_suite_jsapi_ticket_force(auth_corp_id, false).await
223 }
224
225 pub async fn get_suite_jsapi_ticket_force(&self, auth_corp_id: &str, force_refresh: bool) -> LabradorResult<String> {
230 let mut session = self.client.session();
231 let ticket_key = format!("{}_suite_jsapi_ticket_cp", self.corp_id);
232 let expires_key = format!("{}_suite_jsapi_ticket_expires_at_cp", self.corp_id);
233 let ticket: String = session.get(&ticket_key, Some("".to_string()))?.unwrap_or_default();
234 let timestamp = current_timestamp();
235 let expires_at: i64 = session.get(&expires_key, Some(timestamp))?.unwrap_or_default();
236 if expires_at <= timestamp || force_refresh {
237 let v = self.client.get(WechatCpMethod::GetSuiteJsapiTicket, vec![(TYPE.to_string(), AGENT_CONFIG.to_string()), (ACCESS_TOKEN.to_string(), self.get_access_token(auth_corp_id))], RequestType::Json).await?.json::<Value>()?;
238 let res = WechatCommonResponse::parse::<JsapiTicket>(v)?;
239 let ticket = res.ticket;
240 let expires_in = res.expires_in;
241 let expires_at = current_timestamp() + expires_in - 200;
243 session.set(&ticket_key, ticket.to_string(), Some(expires_in as usize));
244 session.set(&expires_key, expires_at, Some(expires_in as usize));
245 Ok(ticket.to_string())
246 } else {
247 Ok(ticket)
248 }
249 }
250
251 pub async fn get_auth_corp_jsapi_ticket(&self, auth_corp_id: &str) -> LabradorResult<String> {
256 self.get_auth_corp_jsapi_ticket_force(auth_corp_id, false).await
257 }
258
259 pub async fn get_auth_corp_jsapi_ticket_force(&self, auth_corp_id: &str, force_refresh: bool) -> LabradorResult<String> {
264 let mut session = self.client.session();
265 let ticket_key = format!("{}_auth_corp_jsapi_ticket_cp", self.corp_id);
266 let expires_key = format!("{}_auth_corp_jsapi_ticket_expires_at_cp", self.corp_id);
267 let ticket: String = session.get(&ticket_key, Some("".to_string()))?.unwrap_or_default();
268 let timestamp = current_timestamp();
269 let expires_at: i64 = session.get(&expires_key, Some(timestamp))?.unwrap_or_default();
270 if expires_at <= timestamp || force_refresh {
271 let res = self.client.get(WechatCpMethod::GetJsapiTicket, vec![(ACCESS_TOKEN.to_string(), self.get_access_token(auth_corp_id))], RequestType::Json).await?.json::<JsapiTicket>()?;
272 let ticket = res.ticket;
273 let expires_in = res.expires_in;
274 let expires_at = current_timestamp() + expires_in - 200;
276 session.set(&ticket_key, ticket.to_string(), Some(expires_in as usize));
277 session.set(&expires_key, expires_at, Some(expires_in as usize));
278 Ok(ticket.to_string())
279 } else {
280 Ok(ticket)
281 }
282 }
283
284
285 pub async fn get_corp_token(&self, auth_corpid: &str, permanent_code: &str) -> LabradorResult<AccessTokenResponse> {
289 self.get_corp_token_force(auth_corpid, permanent_code, false).await
290 }
291
292 pub async fn get_corp_token_force(&self, auth_corpid: &str, permanent_code: &str, force_refresh: bool) -> LabradorResult<AccessTokenResponse> {
296 let session = self.client.session();
297 let token_key = format!("{}_corp_access_token_cp", auth_corpid);
298 let expires_key = format!("{}_corp_access_token_expires_at_cp", auth_corpid);
299 let token: String = session.get(&token_key, Some("".to_owned()))?.unwrap_or_default();
300 let timestamp = get_timestamp();
301 let expires_at: i64 = session.get(&expires_key, Some(timestamp))?.unwrap_or_default();
302 if expires_at <= timestamp || force_refresh {
303 let suite_ticket = self.get_suite_ticket()?;
304 let req = json!({
305 "auth_corpid": auth_corpid,
306 "permanent_code": permanent_code,
307 });
308 let v = self.client.post(WechatCpMethod::GetCorpToken, vec![], req, RequestType::Json).await?.json::<Value>()?;
309 let result = WechatCommonResponse::parse::<AccessTokenResponse>(v)?;
310 let token = result.access_token.to_string();
311 let expires_in = result.expires_in;
312 let expires_at = get_timestamp() + expires_in - 200;
314 session.set(&token_key, token.to_owned(), Some(expires_in as usize));
315 session.set(&expires_key, expires_at, Some(expires_in as usize));
316 Ok(result)
317 } else {
318 Ok(AccessTokenResponse { access_token: token.to_string(), expires_in: expires_at })
319 }
320 }
321
322 pub async fn get_wechat_provider_token(&self) -> LabradorResult<String> {
326 let session = self.client.session();
327 let token_key = format!("{}_provider_access_token_cp", self.corp_id);
328 let expires_key = format!("{}_provider_access_token_expires_at_cp", self.corp_id);
329 let token: String = session.get(&token_key, Some("".to_owned()))?.unwrap_or_default();
330 let timestamp = get_timestamp();
331 let expires_at: i64 = session.get(&expires_key, Some(timestamp))?.unwrap_or_default();
332 if expires_at <= timestamp {
333 let req = json!({
334 "corpid": self.corp_id,
335 "provider_secret": self.provider_secret,
336 });
337 let v = self.client.post(WechatCpMethod::GetProviderToken, vec![], req, RequestType::Json).await?.json::<Value>()?;
338 let result = WechatCommonResponse::parse::<WechatCpProviderToken>(v)?;
339 let token = result.provider_access_token.to_string();
340 let expires_in = result.expires_in;
341 let expires_at = get_timestamp() + expires_in - 200;
343 session.set(&token_key, token.to_owned(), Some(expires_in as usize));
344 session.set(&expires_key, expires_at, Some(expires_in as usize));
345 Ok(token)
346 } else {
347 Ok(token)
348 }
349 }
350
351 pub async fn get_permanent_code_info(&self, auth_code: &str) -> LabradorResult<WechatCpThirdPermanentCodeInfo> {
355 let req = json!({
356 "auth_code": auth_code,
357 });
358 let result = self.post(WechatCpMethod::GetPermanentCode, vec![], req, RequestType::Json).await?.json::<Value>()?;
359 WechatCommonResponse::parse::<WechatCpThirdPermanentCodeInfo>(result)
360 }
361
362 pub async fn get_pre_auth_url(&self, redirect_uri: &str, state: Option<&str>) -> LabradorResult<String> {
366 let result = self.get(WechatCpMethod::GetPreAuthCode, vec![], RequestType::Json).await?.json::<WechatCpThirdPreauthCode>()?;
367 let mut pre_auth_url = format!("{}?suite_id={}&pre_auth_code={}&redirect_uri={}", AUTH_URL_INSTALL, self.suite_id.to_owned().unwrap_or_default(), result.pre_auth_code, urlencoding::encode(redirect_uri));
368 if let Some(state) = state {
369 pre_auth_url.push_str(&format!("&state={}", state));
370 }
371 Ok(pre_auth_url)
372 }
373
374 pub async fn set_session_info(&self, pre_auth_code: &str, app_ids: Vec<&str>, auth_type: u8) -> LabradorResult<WechatCommonResponse> {
378 let req = json!({
379 "pre_auth_code": pre_auth_code,
380 "session_info":
381 {
382 "appid": app_ids,
383 "auth_type": auth_type
384 }
385 });
386 self.post(WechatCpMethod::SetSessionInfo, vec![], req, RequestType::Json).await?.json::<WechatCommonResponse>()
387 }
388
389 pub async fn get_auth_info(&self, auth_corp_id: &str, permanent_code: &str) -> LabradorResult<WechatCpThirdAuthInfo> {
393 let req = json!({
394 "auth_corpid": auth_corp_id,
395 "permanent_code": permanent_code
396 });
397 let result = self.client.post(WechatCpMethod::GetAuthInfo, vec![], req, RequestType::Json).await?.json::<Value>()?;
398 WechatCommonResponse::parse::<WechatCpThirdAuthInfo>(result)
399 }
400
401
402 pub async fn get_admin_info(&self, auth_corp_id: &str, agent_id: i32) -> LabradorResult<Vec<AdminUserInfo>> {
407 let req = json!({
408 "auth_corpid": auth_corp_id,
409 "agentid": agent_id
410 });
411 let result = self.client.post(WechatCpMethod::GetAdminInfo, vec![], req, RequestType::Json).await?.json::<Value>()?;
412 let v = WechatCommonResponse::parse::<Value>(result)?;
413 serde_json::from_value::<Vec<AdminUserInfo>>(v["admin"].to_owned()).map_err(LabraError::from)
414 }
415
416
417 pub async fn get_app_qrcode_buffer(&self, suite_id: &str, appid: Option<i32>, state: Option<&str>, style: Option<u8>) -> LabradorResult<Bytes> {
422 let req = json!({
423 "suite_id": suite_id,
424 "appid": appid,
425 "state": state,
426 "style": style,
427 "result_type": 1
428 });
429 self.client.post(WechatCpMethod::GetAppQrcode, vec![], req, RequestType::Json).await?.bytes()
430 }
431
432 pub async fn get_app_qrcode_url(&self, suite_id: &str, appid: Option<i32>, state: Option<&str>, style: Option<u8>, result_type: Option<u8>) -> LabradorResult<String> {
437 let req = json!({
438 "suite_id": suite_id,
439 "appid": appid,
440 "state": state,
441 "style": style,
442 "result_type": 2
443 });
444 let v = self.client.post(WechatCpMethod::GetAppQrcode, vec![], req, RequestType::Json).await?.json::<Value>()?;
445 let v = WechatCommonResponse::parse::<Value>(v)?;
446 let qrcode = v["qrcode"].as_str().unwrap_or_default();
447 Ok(qrcode.to_string())
448 }
449
450 pub async fn corpid_to_opencorpid(&self, corpid: &str) -> LabradorResult<String> {
455 let req = json!({
456 "corpid": corpid,
457 });
458 let access_token = self.get_wechat_provider_token().await?;
459 let query = vec![(PROVIDER_ACCESS_TOKEN.to_string(), access_token)];
460 let v = self.client.post(WechatCpMethod::CorpToOpenCorpid, query, req, RequestType::Json).await?.json::<Value>()?;
461 let v = WechatCommonResponse::parse::<Value>(v)?;
462 let qrcode = v["open_corpid"].as_str().unwrap_or_default();
463 Ok(qrcode.to_string())
464 }
465
466 pub async fn create_auth_corp_jsapi_signature(&self, url: &str, auth_corp_id: &str) -> LabradorResult<JsapiSignature> {
472 Ok(self.created_wechat_jsapi_signature(url, auth_corp_id, &self.get_auth_corp_jsapi_ticket(auth_corp_id).await?))
473 }
474
475 pub async fn create_suite_jsapi_signature(&self, url: &str, auth_corp_id: &str) -> LabradorResult<JsapiSignature> {
481 Ok(self.created_wechat_jsapi_signature(url, auth_corp_id, &self.get_suite_jsapi_ticket(auth_corp_id).await?))
482 }
483
484 fn created_wechat_jsapi_signature(&self, url: &str, auth_corp_id: &str, jsapi_ticket: &str) -> JsapiSignature {
485 let timestamp = get_timestamp() / 1000;
486 let noncestr = get_nonce_str();
487 let signature = WechatCrypto::get_sha1_sign(&vec!["jsapi_ticket=".to_string() + &jsapi_ticket,
488 "noncestr=".to_string() + &noncestr,
489 "timestamp=".to_string() + ×tamp.to_string(), "url=".to_string() + &url].join("&"));
490 JsapiSignature {
491 app_id: auth_corp_id.to_string(),
492 nonce_str: noncestr,
493 url: url.to_string(),
494 signature,
495 timestamp,
496 }
497 }
498
499 async fn execute<D: WechatRequest, B: Serialize>(&self, request: D, corp_id: Option<&str>) -> LabradorResult<LabraResponse> {
504 let mut querys = request.get_query_params();
505 if request.is_need_token() {
506 if let Some(corp_id) = corp_id {
507 let access_token = self.get_access_token(corp_id);
508 if !access_token.is_empty() {
509 querys.insert(ACCESS_TOKEN.to_string(), access_token);
510 }
511 }
512 }
513 let params = querys.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect::<Vec<(String, String)>>();
514 let mut req = LabraRequest::<B>::new().url(request.get_api_method_name())
515 .params(params).method(request.get_request_method()).req_type(request.get_request_type()).body(request.get_request_body::<B>());
516 self.client.request(req).await
517 }
518
519 async fn post<D: Serialize>(&self, method: WechatCpMethod, mut querys: Vec<(String, String)>, data: D, request_type: RequestType) -> LabradorResult<LabraResponse> {
521 if method.need_token() {
522 let token = self.get_suite_access_token_force(false).await?;
523 querys.push((SUITE_ACCESS_TOKEN.to_string(), token));
524 }
525 self.client.post(method, querys, data, request_type).await
526 }
527
528 async fn get(&self, method: WechatCpMethod, mut params: Vec<(String, String)>, request_type: RequestType) -> LabradorResult<LabraResponse> {
530 if method.need_token() {
531 let token = self.get_suite_access_token_force(false).await?.to_string();
532 params.push((SUITE_ACCESS_TOKEN.to_string(), token));
533 }
534 self.client.get(method, params, request_type).await
535 }
536
537 pub fn department(&self) -> WechatCpTpDepartment<T> {
539 WechatCpTpDepartment::new(self)
540 }
541
542 pub fn license(&self) -> WechatCpTpLicense<T> {
544 WechatCpTpLicense::new(self)
545 }
546
547 pub fn media(&self) -> WechatCpTpMedia<T> {
549 WechatCpTpMedia::new(self)
550 }
551
552 pub fn order(&self) -> WechatCpTpOrder<T> {
554 WechatCpTpOrder::new(self)
555 }
556
557 pub fn tag(&self) -> WechatCpTpTag<T> {
559 WechatCpTpTag::new(self)
560 }
561
562 pub fn user(&self) -> WechatCpTpUser<T> {
564 WechatCpTpUser::new(self)
565 }
566
567 pub fn agent(&self) -> WechatCpTpAgent<T> {
569 WechatCpTpAgent::new(self)
570 }
571
572 pub fn auth(&self) -> WechatCpTpAuth<T> {
574 WechatCpTpAuth::new(self)
575 }
576}
577
578#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
581pub struct WechatCpSuiteAccessTokenResponse {
582 pub suite_access_token: String,
583 pub expires_in: i64,
584}
585
586#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
588pub struct WechatCpThirdPermanentCodeInfo {
589 pub access_token: Option<String>,
590 pub permanent_code: String,
591 pub auth_corp_info: AuthCorpInfo,
593 pub auth_info: Option<AuthInfo>,
595 pub auth_user_info: Option<AuthUserInfo>,
597 pub edition_info: Option<EditionInfo>,
599 pub expires_in: Option<i64>,
600 pub state: Option<String>,
602}
603
604
605#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
606pub struct AuthCorpInfo {
607 pub corpid: String,
608 pub corp_name: String,
609 pub corp_type: Option<String>,
610 pub corp_square_logo_url: Option<String>,
611 pub corp_round_logo_url: Option<String>,
612 pub corp_user_max: Option<i32>,
613 pub corp_agent_max: Option<i32>,
614 pub corp_full_name: Option<String>,
616 pub corp_wxqrcode: Option<String>,
618 pub corp_scale: Option<String>,
619 pub corp_industry: Option<String>,
620 pub corp_sub_industry: Option<String>,
621 pub location: Option<String>,
622 pub verified_end_time: Option<i64>,
624 pub subject_type: Option<u8>,
626}
627
628
629#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
631pub struct EditionInfo {
632 pub agent: Option<Vec<Agent>>,
633}
634
635
636#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
638pub struct AuthUserInfo {
639 pub userid: Option<String>,
640 pub name: Option<String>,
641 pub avatar: Option<String>,
642 pub open_userid: Option<String>,
644}
645
646
647#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
649pub struct AdminUserInfo {
650 pub userid: Option<String>,
651 pub open_userid: Option<String>,
653 pub auth_type: Option<u8>,
655}
656
657
658#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
660pub struct AuthInfo {
661 pub agent: Vec<Agent>,
663}
664
665#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
666pub struct Agent {
667 pub agentid: i32,
668 pub name: String,
669 pub round_logo_url: Option<String>,
670 pub square_logo_url: Option<String>,
671 pub edition_id: Option<String>,
673 pub edition_name: Option<String>,
675 pub app_status: Option<u8>,
688 pub auth_mode: Option<u8>,
690 pub is_customized_app: Option<bool>,
692 pub is_virtual_version: Option<bool>,
694 pub is_shared_from_other_corp: Option<bool>,
696 pub user_limit: Option<i32>,
704 pub expired_time: Option<i64>,
710 pub privilege: Option<Privilege>,
712}
713
714#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
716pub struct Privilege {
717 pub level: Option<u8>,
724 pub allow_party: Option<Vec<String>>,
725 pub allow_user: Option<Vec<i32>>,
726 pub extra_party: Option<Vec<i32>>,
727 pub extra_tag: Option<Vec<i32>>,
728 pub extra_user: Option<Vec<String>>,
729}
730
731
732#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
734pub struct WechatCpThirdPreauthCode {
735 pub pre_auth_code: String,
736 pub expires_in: i64,
737}
738
739
740#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
742pub struct WechatCpThirdAuthInfo {
743 pub dealer_corp_info: Option<DealerCorpInfo>,
745 pub auth_corp_info: Option<AuthCorpInfo>,
747 pub auth_info: Option<AuthInfo>,
749 pub edition_info: Option<EditionInfo>,
751}
752
753
754#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
756pub struct DealerCorpInfo {
757 pub corpid: Option<String>,
758 pub corp_name: Option<String>,
759}