use std::sync::Arc;
use tokio::sync::RwLock;
use crate::config::WxPayConfig;
#[derive(Debug, Clone)]
pub struct Credentials {
app_id: String,
merchant_id: String,
api_v3_key: String,
cert_serial_number: String,
}
impl Credentials {
pub fn from_config(config: &WxPayConfig) -> Self {
Self {
app_id: config.app_id.clone(),
merchant_id: config.merchant_id.clone(),
api_v3_key: config.api_v3_key.clone(),
cert_serial_number: config.cert_serial_number.clone(),
}
}
pub fn app_id(&self) -> &str {
&self.app_id
}
pub fn merchant_id(&self) -> &str {
&self.merchant_id
}
pub fn api_v3_key(&self) -> &str {
&self.api_v3_key
}
pub fn cert_serial_number(&self) -> &str {
&self.cert_serial_number
}
}
#[derive(Debug)]
pub struct CredentialProvider {
credentials: Arc<RwLock<Credentials>>,
}
impl CredentialProvider {
pub fn new(config: &WxPayConfig) -> Self {
let credentials = Credentials::from_config(config);
Self {
credentials: Arc::new(RwLock::new(credentials)),
}
}
pub async fn get_credentials(&self) -> Credentials {
self.credentials.read().await.clone()
}
pub async fn update_credentials(&self, credentials: Credentials) {
let mut current = self.credentials.write().await;
*current = credentials;
}
}
impl Clone for CredentialProvider {
fn clone(&self) -> Self {
Self {
credentials: self.credentials.clone(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn create_test_config() -> WxPayConfig {
WxPayConfig::builder()
.app_id("wx88888888")
.merchant_id("1900000109")
.api_v3_key("abcdefghijklmnopqrstuvwxyz123456")
.private_key(vec![1, 2, 3, 4])
.cert_serial_number("CERT123456")
.build()
.unwrap()
}
#[test]
fn test_credentials_from_config() {
let config = create_test_config();
let credentials = Credentials::from_config(&config);
assert_eq!(credentials.app_id(), "wx88888888");
assert_eq!(credentials.merchant_id(), "1900000109");
assert_eq!(credentials.api_v3_key(), "abcdefghijklmnopqrstuvwxyz123456");
assert_eq!(credentials.cert_serial_number(), "CERT123456");
}
#[tokio::test]
async fn test_credential_provider() {
let config = create_test_config();
let provider = CredentialProvider::new(&config);
let credentials = provider.get_credentials().await;
assert_eq!(credentials.app_id(), "wx88888888");
}
#[tokio::test]
async fn test_credential_provider_update() {
let config = create_test_config();
let provider = CredentialProvider::new(&config);
let new_credentials = Credentials {
app_id: "wx99999999".to_string(),
merchant_id: "1900000209".to_string(),
api_v3_key: "abcdefghijklmnopqrstuvwxyz123456".to_string(),
cert_serial_number: "CERT999999".to_string(),
};
provider.update_credentials(new_credentials).await;
let credentials = provider.get_credentials().await;
assert_eq!(credentials.app_id(), "wx99999999");
assert_eq!(credentials.merchant_id(), "1900000209");
}
}