use std::{collections::BTreeMap, time::{SystemTime, UNIX_EPOCH}};
use std::time::Duration;
use uuid::Uuid;
use crate::prp::PrpCrypto;
pub mod md5;
pub mod prp;
#[derive(Debug, Clone)]
pub struct RequestParametersHolder {
pub protocal_must_params: BTreeMap<String, String>,
pub protocal_opt_params: BTreeMap<String, String>,
pub application_params: BTreeMap<String, String>,
}
impl RequestParametersHolder {
pub fn new() -> Self {
Self {
protocal_must_params: BTreeMap::new(),
protocal_opt_params: BTreeMap::new(),
application_params: BTreeMap::new()
}
}
pub fn set_application_params(&mut self, application_params: BTreeMap<String, String>) -> &mut Self {
self.application_params = application_params;
self
}
pub fn set_protocal_must_params(&mut self, protocal_must_params: BTreeMap<String, String>) -> &mut Self {
self.protocal_must_params = protocal_must_params;
self
}
pub fn set_protocal_opt_params(&mut self, protocal_opt_params: BTreeMap<String, String>) -> &mut Self {
self.protocal_opt_params = protocal_opt_params;
self
}
pub fn get_sorted_map(&self) -> BTreeMap<&String, &String> {
let mut sorted_params = BTreeMap::new();
if self.application_params.len() > 0 {
for (k, v) in self.application_params.iter() {
sorted_params.insert(k, v);
}
}
if self.protocal_must_params.len() > 0 {
for (k, v) in self.protocal_must_params.iter() {
sorted_params.insert(k, v);
}
}
if self.protocal_opt_params.len() > 0 {
for (k, v) in self.protocal_opt_params.iter() {
sorted_params.insert(k, v);
}
}
sorted_params
}
pub fn get_signature_content(&self) -> String {
let pairs = self.get_sorted_map();
let signature_content = pairs.iter().map(|(k, v)| format!("{}={}", k, v)).collect::<Vec<String>>().join("&");
signature_content
}
}
pub trait StringExtern <T> {
fn add_form_param(&mut self, field_name: &str, field_value: T);
fn add_form_params(&mut self, field_name: &str, field_value: T);
}
impl <T: Sized + std::fmt::Display> StringExtern<T> for String {
fn add_form_param(&mut self, field_name: &str, field_value: T) {
self.push_str(format!("{}{}", field_name, field_value).as_str());
}
fn add_form_params(&mut self, field_name: &str, field_value: T) {
if !self.is_empty() {
self.push_str("&");
}
self.push_str(format!("{}={}", field_name, field_value).as_str());
}
}
#[allow(unused)]
pub fn get_sign(pairs: &BTreeMap<String, String>, secret: &str) -> String {
let keys = pairs
.iter()
.filter(|pair| pair.0.ne("key") && pair.0.ne("sign") && !pair.1.is_empty())
.map(|pair| pair.0.to_string())
.collect::<Vec<String>>();
let mut params = String::default();
for key in keys {
params.add_form_param(key.as_str(), &pairs[&key].as_str());
}
params = format!("{}{}{}",secret,params,secret);
md5::md5(params).to_uppercase()
}
#[allow(unused)]
pub fn get_sign_with_rsa(pairs: &BTreeMap<String, String>, private_key: &str) -> String {
let keys = pairs
.iter()
.filter(|pair| pair.0.ne("sign") && !pair.1.is_empty())
.map(|pair| pair.0.to_string())
.collect::<Vec<String>>();
let mut params = String::default();
for key in keys {
params.add_form_params(key.as_str(), &pairs[&key].as_str());
}
let prp = PrpCrypto::new(base64::decode(private_key).unwrap_or_default());
let sign = prp.rsa_sha256_sign_pkcs8(¶ms).unwrap_or_default();
sign
}
#[allow(unused)]
pub fn get_sign_params(pairs: &BTreeMap<String, String>, private_key: &str) -> String {
let keys = pairs
.iter()
.filter(|pair| pair.0.ne("key") && pair.0.ne("sign") && !pair.1.is_empty())
.map(|pair| pair.0.to_string())
.collect::<Vec<String>>();
let mut params = String::default();
for key in keys {
params.add_form_params(key.as_str(), &pairs[&key].as_str());
}
params
}
#[allow(unused)]
pub fn get_timestamp() -> i64 {
let start = SystemTime::now();
let since_the_epoch = start
.duration_since(UNIX_EPOCH)
.expect("Time went backwards");
let ms = since_the_epoch.as_secs() as i64 * 1000i64 + (since_the_epoch.subsec_nanos() as f64 / 1_000_000.0) as i64;
ms
}
pub fn merge_properties(mut source: serde_json::Value, target: serde_json::Value) -> serde_json::Value {
if let Some(data) = target.as_object() {
for (k, v) in data.into_iter() {
source[k] = v.to_owned();
}
}
source
}
pub fn remove_properties(mut source: serde_json::Value, props: Vec<&str>) -> serde_json::Value {
if let Some(data) = source.as_object_mut() {
for prop in props.iter() {
data.remove(&prop.to_string());
}
}
source
}
#[allow(unused)]
pub fn get_nonce_str() -> String {
Uuid::new_v4().to_simple().to_string()
}
#[allow(unused)]
pub fn current_timestamp() -> i64 {
SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or(Duration::from_secs(0)).as_secs() as i64
}
#[macro_export]
macro_rules! cfg_if {
(
$(
if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
) else+
else { $( $e_tokens:tt )* }
) => {
$crate::cfg_if! {
@__items () ;
$(
(( $i_meta ) ( $( $i_tokens )* )) ,
)+
(() ( $( $e_tokens )* )) ,
}
};
(
if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
$(
else if #[cfg( $e_meta:meta )] { $( $e_tokens:tt )* }
)*
) => {
$crate::cfg_if! {
@__items () ;
(( $i_meta ) ( $( $i_tokens )* )) ,
$(
(( $e_meta ) ( $( $e_tokens )* )) ,
)*
}
};
(@__items ( $( $_:meta , )* ) ; ) => {};
(
@__items ( $( $no:meta , )* ) ;
(( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
$( $rest:tt , )*
) => {
#[cfg(all(
$( $yes , )?
not(any( $( $no ),* ))
))]
$crate::cfg_if! { @__identity $( $tokens )* }
$crate::cfg_if! {
@__items ( $( $no , )* $( $yes , )? ) ;
$( $rest , )*
}
};
(@__identity $( $tokens:tt )* ) => {
$( $tokens )*
};
}
cfg_if! {if #[cfg(feature = "wechat")]{
pub mod xmlutil;
}}
#[test]
fn test() {
println!("{}", get_nonce_str());
}