wx_rust_open/config/impl/
wx_open_default_config_impl.rs1use std::collections::HashMap;
10use std::sync::{Arc, Mutex, RwLock};
11use tokio::sync::Mutex as AsyncMutex;
12
13use wx_rust_common::config::TokenEntry;
14
15use crate::config::{API_DEFAULT_HOST_URL, WxOpenConfigStorage, WxOpenHostConfig};
16
17fn now() -> i64 {
19 std::time::SystemTime::now()
20 .duration_since(std::time::UNIX_EPOCH)
21 .map(|d| d.as_secs() as i64)
22 .unwrap_or(0)
23}
24
25#[derive(Debug)]
27pub struct WxOpenDefaultConfig {
28 component_app_id: RwLock<Option<String>>,
29 component_app_secret: RwLock<Option<String>>,
30 component_token: RwLock<Option<String>>,
31 component_aes_key: RwLock<Option<String>>,
32 component_verify_ticket: RwLock<Option<String>>,
33 component_access_token: Mutex<Option<TokenEntry>>,
34 component_access_token_lock: Arc<AsyncMutex<()>>,
35 locks: Mutex<HashMap<String, Arc<AsyncMutex<()>>>>,
37 authorizer_refresh_tokens: Mutex<HashMap<String, TokenEntry>>,
39 authorizer_access_tokens: Mutex<HashMap<String, TokenEntry>>,
41 jsapi_tickets: Mutex<HashMap<String, TokenEntry>>,
43 card_api_tickets: Mutex<HashMap<String, TokenEntry>>,
45 http_proxy_host: RwLock<Option<String>>,
46 http_proxy_port: i32,
47 http_proxy_username: RwLock<Option<String>>,
48 http_proxy_password: RwLock<Option<String>>,
49 retry_sleep_millis: i32,
50 max_retry_times: i32,
51 api_host_url: RwLock<Option<String>>,
54 access_token_url: RwLock<Option<String>>,
56 host_config: RwLock<WxOpenHostConfig>,
57 component_api_signature_rsa_private_key: RwLock<Option<String>>,
58 component_api_signature_aes_key: RwLock<Option<String>>,
59 component_api_signature_rsa_private_key_sn: RwLock<Option<String>>,
60 component_api_signature_aes_key_sn: RwLock<Option<String>>,
61}
62
63impl WxOpenDefaultConfig {
64 pub fn new() -> Self {
67 Self {
68 component_app_id: RwLock::new(None),
69 component_app_secret: RwLock::new(None),
70 component_token: RwLock::new(None),
71 component_aes_key: RwLock::new(None),
72 component_verify_ticket: RwLock::new(None),
73 component_access_token: Mutex::new(None),
74 component_access_token_lock: Arc::new(AsyncMutex::new(())),
75 locks: Mutex::new(HashMap::new()),
76 authorizer_refresh_tokens: Mutex::new(HashMap::new()),
77 authorizer_access_tokens: Mutex::new(HashMap::new()),
78 jsapi_tickets: Mutex::new(HashMap::new()),
79 card_api_tickets: Mutex::new(HashMap::new()),
80 http_proxy_host: RwLock::new(None),
81 http_proxy_port: 0,
82 http_proxy_username: RwLock::new(None),
83 http_proxy_password: RwLock::new(None),
84 retry_sleep_millis: 1000,
85 max_retry_times: 5,
86 api_host_url: RwLock::new(None),
87 access_token_url: RwLock::new(None),
88 host_config: RwLock::new(WxOpenHostConfig::new()),
89 component_api_signature_rsa_private_key: RwLock::new(None),
90 component_api_signature_aes_key: RwLock::new(None),
91 component_api_signature_rsa_private_key_sn: RwLock::new(None),
92 component_api_signature_aes_key_sn: RwLock::new(None),
93 }
94 }
95
96 pub fn set_component_app_id(&mut self, v: impl Into<String>) -> &mut Self {
100 *self.component_app_id.write().unwrap() = Some(v.into());
101 self
102 }
103
104 pub fn set_component_app_secret(&mut self, v: impl Into<String>) -> &mut Self {
106 *self.component_app_secret.write().unwrap() = Some(v.into());
107 self
108 }
109
110 pub fn set_component_token(&mut self, v: impl Into<String>) -> &mut Self {
112 *self.component_token.write().unwrap() = Some(v.into());
113 self
114 }
115
116 pub fn set_component_aes_key(&mut self, v: impl Into<String>) -> &mut Self {
118 *self.component_aes_key.write().unwrap() = Some(v.into());
119 self
120 }
121
122 pub fn set_component_verify_ticket(&mut self, v: impl Into<String>) -> &mut Self {
124 *self.component_verify_ticket.write().unwrap() = Some(v.into());
125 self
126 }
127
128 pub fn set_http_proxy_host(&mut self, v: impl Into<String>) -> &mut Self {
130 *self.http_proxy_host.write().unwrap() = Some(v.into());
131 self
132 }
133
134 pub fn set_http_proxy_port(&mut self, v: i32) -> &mut Self {
136 self.http_proxy_port = v;
137 self
138 }
139
140 pub fn set_http_proxy_username(&mut self, v: impl Into<String>) -> &mut Self {
142 *self.http_proxy_username.write().unwrap() = Some(v.into());
143 self
144 }
145
146 pub fn set_http_proxy_password(&mut self, v: impl Into<String>) -> &mut Self {
148 *self.http_proxy_password.write().unwrap() = Some(v.into());
149 self
150 }
151
152 pub fn set_retry_sleep_millis(&mut self, v: i32) -> &mut Self {
154 self.retry_sleep_millis = v;
155 self
156 }
157
158 pub fn set_max_retry_times(&mut self, v: i32) -> &mut Self {
160 self.max_retry_times = v;
161 self
162 }
163
164 pub fn set_api_host_url(&mut self, v: impl Into<String>) -> &mut Self {
166 *self.api_host_url.write().unwrap() = Some(v.into());
167 self
168 }
169
170 pub fn set_access_token_url(&mut self, v: impl Into<String>) -> &mut Self {
172 *self.access_token_url.write().unwrap() = Some(v.into());
173 self
174 }
175
176 pub fn api_host_url(&self) -> Option<String> {
178 self.api_host_url.read().unwrap().clone()
179 }
180
181 pub fn access_token_url(&self) -> Option<String> {
183 self.access_token_url.read().unwrap().clone()
184 }
185
186 pub fn effective_api_host_url(&self) -> String {
190 if let Some(api_host_url) = self.api_host_url() {
191 if !api_host_url.is_empty() {
192 return api_host_url;
193 }
194 }
195 API_DEFAULT_HOST_URL.to_string()
196 }
197
198 fn get_token_string(map: &Mutex<HashMap<String, TokenEntry>>, key: &str) -> Option<String> {
200 let guard = map.lock().unwrap();
201 match guard.get(key) {
202 Some(t) if !t.is_expired(now()) => Some(t.value.clone()),
203 _ => None,
204 }
205 }
206
207 fn expire_token(map: &Mutex<HashMap<String, TokenEntry>>, key: &str) {
209 let mut guard = map.lock().unwrap();
210 guard.remove(key);
211 }
212
213 fn update_token(
219 map: &Mutex<HashMap<String, TokenEntry>>,
220 key: &str,
221 token: &str,
222 expires_in_seconds: Option<i32>,
223 ) {
224 let mut guard = map.lock().unwrap();
225 let entry = guard.entry(key.to_string()).or_insert_with(|| TokenEntry {
226 value: String::new(),
227 expires_at: None,
228 });
229 entry.value = token.to_string();
230 if let Some(expires_in) = expires_in_seconds {
231 if expires_in != -1 {
232 entry.expires_at = Some(now() + (expires_in - 200).max(0) as i64);
233 }
234 }
235 }
236}
237
238impl WxOpenConfigStorage for WxOpenDefaultConfig {
239 fn component_app_id(&self) -> Option<String> {
240 self.component_app_id.read().unwrap().clone()
241 }
242
243 fn set_component_app_id(&self, component_app_id: &str) {
244 *self.component_app_id.write().unwrap() = Some(component_app_id.to_string());
245 }
246
247 fn component_app_secret(&self) -> Option<String> {
248 self.component_app_secret.read().unwrap().clone()
249 }
250
251 fn set_component_app_secret(&self, component_app_secret: &str) {
252 *self.component_app_secret.write().unwrap() = Some(component_app_secret.to_string());
253 }
254
255 fn component_token(&self) -> Option<String> {
256 self.component_token.read().unwrap().clone()
257 }
258
259 fn set_component_token(&self, component_token: &str) {
260 *self.component_token.write().unwrap() = Some(component_token.to_string());
261 }
262
263 fn component_aes_key(&self) -> Option<String> {
264 self.component_aes_key.read().unwrap().clone()
265 }
266
267 fn set_component_aes_key(&self, component_aes_key: &str) {
268 *self.component_aes_key.write().unwrap() = Some(component_aes_key.to_string());
269 }
270
271 fn component_verify_ticket(&self) -> Option<String> {
272 self.component_verify_ticket.read().unwrap().clone()
273 }
274
275 fn set_component_verify_ticket(&self, component_verify_ticket: &str) {
276 *self.component_verify_ticket.write().unwrap() = Some(component_verify_ticket.to_string());
277 }
278
279 fn component_access_token(&self) -> Option<String> {
280 let guard = self.component_access_token.lock().unwrap();
281 guard.as_ref().map(|t| t.value.clone())
282 }
283
284 fn is_component_access_token_expired(&self) -> bool {
285 let guard = self.component_access_token.lock().unwrap();
286 match guard.as_ref() {
287 Some(t) => t.is_expired(now()),
288 None => true,
289 }
290 }
291
292 fn expire_component_access_token(&self) {
293 let mut guard = self.component_access_token.lock().unwrap();
294 *guard = None;
295 }
296
297 fn update_component_access_token_with_expiry(
298 &self,
299 component_access_token: &str,
300 expires_in_seconds: i32,
301 ) {
302 let mut guard = self.component_access_token.lock().unwrap();
303 *guard = Some(TokenEntry {
304 value: component_access_token.to_string(),
305 expires_at: Some(now() + (expires_in_seconds - 200).max(0) as i64),
307 });
308 }
309
310 fn component_access_token_lock(&self) -> Arc<AsyncMutex<()>> {
311 self.component_access_token_lock.clone()
312 }
313
314 fn lock_by_key(&self, key: &str) -> Arc<AsyncMutex<()>> {
315 let mut guard = self.locks.lock().unwrap();
317 guard
318 .entry(key.to_string())
319 .or_insert_with(|| Arc::new(AsyncMutex::new(())))
320 .clone()
321 }
322
323 fn wx_open_host_config(&self) -> Option<WxOpenHostConfig> {
324 let mut host_config = self.host_config.read().unwrap().clone();
325 if let Some(api_host_url) = self.api_host_url() {
327 if !api_host_url.is_empty() {
328 host_config.api_host = api_host_url;
329 }
330 }
331 Some(host_config)
332 }
333
334 fn authorizer_refresh_token(&self, app_id: &str) -> Option<String> {
335 Self::get_token_string(&self.authorizer_refresh_tokens, app_id)
336 }
337
338 fn set_authorizer_refresh_token(&self, app_id: &str, authorizer_refresh_token: &str) {
339 Self::update_token(
340 &self.authorizer_refresh_tokens,
341 app_id,
342 authorizer_refresh_token,
343 None,
344 );
345 }
346
347 fn authorizer_access_token(&self, app_id: &str) -> Option<String> {
348 Self::get_token_string(&self.authorizer_access_tokens, app_id)
349 }
350
351 fn is_authorizer_access_token_expired(&self, app_id: &str) -> bool {
352 Self::get_token_string(&self.authorizer_access_tokens, app_id).is_none()
353 }
354
355 fn expire_authorizer_access_token(&self, app_id: &str) {
356 Self::expire_token(&self.authorizer_access_tokens, app_id);
357 }
358
359 fn update_authorizer_access_token_with_expiry(
360 &self,
361 app_id: &str,
362 authorizer_access_token: &str,
363 expires_in_seconds: i32,
364 ) {
365 Self::update_token(
366 &self.authorizer_access_tokens,
367 app_id,
368 authorizer_access_token,
369 Some(expires_in_seconds),
370 );
371 }
372
373 fn jsapi_ticket(&self, app_id: &str) -> Option<String> {
374 Self::get_token_string(&self.jsapi_tickets, app_id)
375 }
376
377 fn is_jsapi_ticket_expired(&self, app_id: &str) -> bool {
378 Self::get_token_string(&self.jsapi_tickets, app_id).is_none()
379 }
380
381 fn expire_jsapi_ticket(&self, app_id: &str) {
382 Self::expire_token(&self.jsapi_tickets, app_id);
383 }
384
385 fn update_jsapi_ticket(&self, app_id: &str, jsapi_ticket: &str, expires_in_seconds: i32) {
386 Self::update_token(
387 &self.jsapi_tickets,
388 app_id,
389 jsapi_ticket,
390 Some(expires_in_seconds),
391 );
392 }
393
394 fn card_api_ticket(&self, app_id: &str) -> Option<String> {
395 Self::get_token_string(&self.card_api_tickets, app_id)
396 }
397
398 fn is_card_api_ticket_expired(&self, app_id: &str) -> bool {
399 Self::get_token_string(&self.card_api_tickets, app_id).is_none()
400 }
401
402 fn expire_card_api_ticket(&self, app_id: &str) {
403 Self::expire_token(&self.card_api_tickets, app_id);
404 }
405
406 fn update_card_api_ticket(&self, app_id: &str, card_api_ticket: &str, expires_in_seconds: i32) {
407 Self::update_token(
408 &self.card_api_tickets,
409 app_id,
410 card_api_ticket,
411 Some(expires_in_seconds),
412 );
413 }
414
415 fn http_proxy_host(&self) -> Option<String> {
416 self.http_proxy_host.read().unwrap().clone()
417 }
418
419 fn http_proxy_port(&self) -> i32 {
420 self.http_proxy_port
421 }
422
423 fn http_proxy_username(&self) -> Option<String> {
424 self.http_proxy_username.read().unwrap().clone()
425 }
426
427 fn http_proxy_password(&self) -> Option<String> {
428 self.http_proxy_password.read().unwrap().clone()
429 }
430
431 fn retry_sleep_millis(&self) -> i32 {
432 self.retry_sleep_millis
433 }
434
435 fn max_retry_times(&self) -> i32 {
436 self.max_retry_times
437 }
438
439 fn component_api_signature_rsa_private_key(&self) -> Option<String> {
440 self.component_api_signature_rsa_private_key
441 .read()
442 .unwrap()
443 .clone()
444 }
445
446 fn set_component_api_signature_rsa_private_key(&self, api_signature_rsa_private_key: &str) {
447 *self
448 .component_api_signature_rsa_private_key
449 .write()
450 .unwrap() = Some(api_signature_rsa_private_key.to_string());
451 }
452
453 fn component_api_signature_aes_key(&self) -> Option<String> {
454 self.component_api_signature_aes_key.read().unwrap().clone()
455 }
456
457 fn set_component_api_signature_aes_key(&self, api_signature_aes_key: &str) {
458 *self.component_api_signature_aes_key.write().unwrap() =
459 Some(api_signature_aes_key.to_string());
460 }
461
462 fn component_api_signature_rsa_private_key_sn(&self) -> Option<String> {
463 self.component_api_signature_rsa_private_key_sn
464 .read()
465 .unwrap()
466 .clone()
467 }
468
469 fn set_component_api_signature_rsa_private_key_sn(
470 &self,
471 api_signature_rsa_private_key_sn: &str,
472 ) {
473 *self
474 .component_api_signature_rsa_private_key_sn
475 .write()
476 .unwrap() = Some(api_signature_rsa_private_key_sn.to_string());
477 }
478
479 fn component_api_signature_aes_key_sn(&self) -> Option<String> {
480 self.component_api_signature_aes_key_sn
481 .read()
482 .unwrap()
483 .clone()
484 }
485
486 fn set_component_api_signature_aes_key_sn(&self, api_signature_aes_key_sn: &str) {
487 *self.component_api_signature_aes_key_sn.write().unwrap() =
488 Some(api_signature_aes_key_sn.to_string());
489 }
490}
491
492impl Default for WxOpenDefaultConfig {
493 fn default() -> Self {
494 Self::new()
495 }
496}