wx_rust_open/api/impl/
wx_open_o_auth2_service_impl.rs1use std::sync::{Arc, Weak};
24
25use async_trait::async_trait;
26
27use wx_rust_common::bean::WxOAuth2UserInfo;
28use wx_rust_common::bean::oauth2::WxOAuth2AccessToken;
29use wx_rust_common::enums::WxType;
30use wx_rust_common::error::WxErrorException;
31use wx_rust_common::service::WxOAuth2Service;
32use wx_rust_common::util::http::{RequestExecutor, SimpleGetRequestExecutor};
33
34use crate::api::WxOpenService;
35use crate::enums::url_ma_domain::{
36 oauth2_access_token_url, oauth2_refresh_token_url, oauth2_userinfo_url,
37 oauth2_validate_token_url, qrconnect_url,
38};
39
40pub struct WxOpenOAuth2ServiceImpl {
42 app_id: String,
44 app_secret: String,
46 wx_open_service: Weak<dyn WxOpenService>,
49}
50
51impl WxOpenOAuth2ServiceImpl {
52 pub fn new(
61 app_id: String,
62 app_secret: String,
63 wx_open_service: Arc<dyn WxOpenService>,
64 ) -> Self {
65 Self {
66 app_id,
67 app_secret,
68 wx_open_service: Arc::downgrade(&wx_open_service),
69 }
70 }
71
72 async fn bare_get(&self, url: &str) -> Result<String, WxErrorException> {
76 let svc = self
77 .wx_open_service
78 .upgrade()
79 .ok_or_else(|| WxErrorException::from_code(-99, "门面服务已被释放"))?;
80 let executor = SimpleGetRequestExecutor::new(svc.http_client().clone());
81 executor.execute(url, String::new(), WxType::Open).await
82 }
83
84 pub async fn validate_access_token(
92 &self,
93 token: &WxOAuth2AccessToken,
94 ) -> Result<bool, WxErrorException> {
95 let svc = self
96 .wx_open_service
97 .upgrade()
98 .ok_or_else(|| WxErrorException::from_code(-99, "门面服务已被释放"))?;
99 let config = svc.wx_open_config_storage();
100 let url = oauth2_validate_token_url(config.as_ref(), &token.access_token, &token.open_id);
101 match self.bare_get(&url).await {
102 Ok(_) => Ok(true),
103 Err(e) if e.error_code() != Some(-99) => Ok(false),
104 Err(e) => Err(e),
105 }
106 }
107}
108
109#[async_trait]
110impl WxOAuth2Service for WxOpenOAuth2ServiceImpl {
111 fn build_authorization_url(&self, redirect_uri: &str, scope: &str, state: &str) -> String {
118 use percent_encoding::{NON_ALPHANUMERIC, utf8_percent_encode};
119 let encoded_redirect = utf8_percent_encode(redirect_uri, NON_ALPHANUMERIC).to_string();
121 let state = state.trim();
123 qrconnect_url(&self.app_id, &encoded_redirect, scope, state)
124 }
125
126 async fn get_access_token(&self, code: &str) -> Result<WxOAuth2AccessToken, WxErrorException> {
130 self.get_access_token_with(&self.app_id, &self.app_secret, code)
131 .await
132 }
133
134 async fn get_access_token_with(
138 &self,
139 app_id: &str,
140 app_secret: &str,
141 code: &str,
142 ) -> Result<WxOAuth2AccessToken, WxErrorException> {
143 let svc = self
144 .wx_open_service
145 .upgrade()
146 .ok_or_else(|| WxErrorException::from_code(-99, "门面服务已被释放"))?;
147 let config = svc.wx_open_config_storage();
148 let url = oauth2_access_token_url(config.as_ref(), app_id, app_secret, code);
149 let response = self.bare_get(&url).await?;
150 serde_json::from_str(&response).map_err(|e| WxErrorException::Serde(e.to_string()))
151 }
152
153 async fn refresh_access_token(
157 &self,
158 refresh_token: &str,
159 ) -> Result<WxOAuth2AccessToken, WxErrorException> {
160 let svc = self
161 .wx_open_service
162 .upgrade()
163 .ok_or_else(|| WxErrorException::from_code(-99, "门面服务已被释放"))?;
164 let config = svc.wx_open_config_storage();
165 let url = oauth2_refresh_token_url(config.as_ref(), &self.app_id, refresh_token);
166 let response = self.bare_get(&url).await?;
167 serde_json::from_str(&response).map_err(|e| WxErrorException::Serde(e.to_string()))
168 }
169
170 async fn get_user_info(
174 &self,
175 token: &WxOAuth2AccessToken,
176 lang: &str,
177 ) -> Result<WxOAuth2UserInfo, WxErrorException> {
178 let lang = if lang.is_empty() { "zh_CN" } else { lang };
179 let svc = self
180 .wx_open_service
181 .upgrade()
182 .ok_or_else(|| WxErrorException::from_code(-99, "门面服务已被释放"))?;
183 let config = svc.wx_open_config_storage();
184 let url = oauth2_userinfo_url(config.as_ref(), &token.access_token, &token.open_id, lang);
185 let response = self.bare_get(&url).await?;
186 serde_json::from_str(&response).map_err(|e| WxErrorException::Serde(e.to_string()))
187 }
188}