fix: stabilize admin tracking event display
This commit is contained in:
@@ -1456,9 +1456,19 @@ fn build_aliyun_sms_url(endpoint: &str) -> Result<String, SmsProviderError> {
|
||||
}
|
||||
|
||||
fn current_aliyun_timestamp() -> String {
|
||||
OffsetDateTime::now_utc()
|
||||
.format(&time::format_description::well_known::Rfc3339)
|
||||
.unwrap_or_else(|_| "1970-01-01T00:00:00Z".to_string())
|
||||
// 阿里云 OpenAPI ACS3 签名头 x-acs-date 要求使用不带小数秒的 UTC ISO 8601 格式,
|
||||
// 即 yyyy-MM-dd'T'HH:mm:ss'Z'。time crate 的 Rfc3339 会保留纳秒,
|
||||
// 形如 2026-05-07T14:23:59.364767Z,阿里云网关会判定为时间格式非法。
|
||||
let now = OffsetDateTime::now_utc();
|
||||
format!(
|
||||
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z",
|
||||
now.year(),
|
||||
u8::from(now.month()),
|
||||
now.day(),
|
||||
now.hour(),
|
||||
now.minute(),
|
||||
now.second()
|
||||
)
|
||||
}
|
||||
|
||||
fn canonicalize_aliyun_form_params(params: &BTreeMap<String, String>) -> String {
|
||||
@@ -1480,8 +1490,9 @@ fn build_aliyun_form_body(params: &BTreeMap<String, String>) -> String {
|
||||
}
|
||||
|
||||
fn hmac_sha256_hex(key: &[u8], content: &[u8]) -> Result<String, SmsProviderError> {
|
||||
let mut signer = HmacSha256::new_from_slice(key)
|
||||
.map_err(|error| SmsProviderError::InvalidConfig(format!("初始化短信签名器失败:{error}")))?;
|
||||
let mut signer = HmacSha256::new_from_slice(key).map_err(|error| {
|
||||
SmsProviderError::InvalidConfig(format!("初始化短信签名器失败:{error}"))
|
||||
})?;
|
||||
signer.update(content);
|
||||
Ok(hex_lower(&signer.finalize().into_bytes()))
|
||||
}
|
||||
@@ -2146,6 +2157,23 @@ mod tests {
|
||||
assert!(headers.get("x-acs-content-sha256").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn current_aliyun_timestamp_uses_acs_iso8601_format_without_fractional_seconds() {
|
||||
let timestamp = current_aliyun_timestamp();
|
||||
|
||||
assert_eq!(timestamp.len(), "2026-05-07T12:34:56Z".len());
|
||||
assert_eq!(timestamp.as_bytes()[4], b'-');
|
||||
assert_eq!(timestamp.as_bytes()[7], b'-');
|
||||
assert_eq!(timestamp.as_bytes()[10], b'T');
|
||||
assert_eq!(timestamp.as_bytes()[13], b':');
|
||||
assert_eq!(timestamp.as_bytes()[16], b':');
|
||||
assert!(timestamp.ends_with('Z'));
|
||||
assert!(!timestamp.contains('.'));
|
||||
assert!(timestamp.chars().enumerate().all(|(index, value)| {
|
||||
matches!(index, 4 | 7 | 10 | 13 | 16 | 19) || value.is_ascii_digit()
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aliyun_send_response_deserializes_pascal_case_fields() {
|
||||
let payload = serde_json::from_str::<AliyunSendSmsVerifyCodeResponse>(
|
||||
|
||||
Reference in New Issue
Block a user