fix wechat virtual payment signature

This commit is contained in:
kdletters
2026-05-30 15:15:53 +08:00
parent 0edfc21a46
commit c02dcd8aaf

View File

@@ -1217,7 +1217,8 @@ fn build_wechat_virtual_pay_params(
}
let sign_data = sign_data.to_string();
let pay_sig = calc_wechat_virtual_payment_signature(state, &sign_data, false)?;
let signature = calc_wechat_virtual_payment_signature_with_key(&session_key, &sign_data)?;
let signature =
calc_wechat_virtual_payment_user_signature_with_key(&session_key, &sign_data)?;
Ok(WechatMiniProgramVirtualPayParamsResponse {
mode: mode.to_string(),
@@ -1251,7 +1252,7 @@ fn calc_wechat_virtual_payment_signature(
.ok_or_else(|| {
AppError::from_status(StatusCode::BAD_REQUEST).with_message("微信虚拟支付 AppKey 未配置")
})?;
calc_wechat_virtual_payment_signature_with_key(app_key, sign_data)
calc_wechat_virtual_payment_pay_signature_with_key(app_key, sign_data)
}
fn required_wechat_virtual_payment_config<'a>(
@@ -1264,7 +1265,7 @@ fn required_wechat_virtual_payment_config<'a>(
.ok_or_else(|| AppError::from_status(StatusCode::SERVICE_UNAVAILABLE).with_message(message))
}
fn calc_wechat_virtual_payment_signature_with_key(
fn calc_wechat_virtual_payment_pay_signature_with_key(
key: &str,
sign_data: &str,
) -> Result<String, AppError> {
@@ -1276,6 +1277,18 @@ fn calc_wechat_virtual_payment_signature_with_key(
Ok(to_lower_hex(mac.finalize().into_bytes().as_slice()))
}
fn calc_wechat_virtual_payment_user_signature_with_key(
session_key: &str,
sign_data: &str,
) -> Result<String, AppError> {
let mut mac = HmacSha256::new_from_slice(session_key.as_bytes()).map_err(|_| {
AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR)
.with_message("微信虚拟支付用户态签名密钥初始化失败")
})?;
mac.update(sign_data.as_bytes());
Ok(to_lower_hex(mac.finalize().into_bytes().as_slice()))
}
fn to_lower_hex(bytes: &[u8]) -> String {
const HEX: &[u8; 16] = b"0123456789abcdef";
let mut output = String::with_capacity(bytes.len() * 2);
@@ -1765,8 +1778,9 @@ mod tests {
};
use super::{
build_wechat_virtual_pay_params, format_profile_wallet_ledger_source_type,
normalize_admin_invite_code_metadata,
build_wechat_virtual_pay_params, calc_wechat_virtual_payment_pay_signature_with_key,
calc_wechat_virtual_payment_user_signature_with_key,
format_profile_wallet_ledger_source_type, normalize_admin_invite_code_metadata,
};
use axum::{
@@ -2345,6 +2359,29 @@ mod tests {
assert_eq!(sign_data["outTradeNo"], "item01order01");
}
#[test]
fn wechat_virtual_payment_signatures_match_official_examples() {
let post_body = r#"{"openid": "xxx", "user_ip": "127.0.0.1", "env": 0}"#;
let pay_sig =
calc_wechat_virtual_payment_pay_signature_with_key("12345", post_body)
.expect("pay signature should build");
let signature = calc_wechat_virtual_payment_user_signature_with_key(
"9hAb/NEYUlkaMBEsmFgzig==",
post_body,
)
.expect("user signature should build");
assert_eq!(
pay_sig,
"a1ab2651b927b6a766152cf864033417b85c1448fc3c6e1bedbbd7f49416e92f"
);
assert_eq!(
signature,
"089d9e8dc5d308977360c4b79ec600a93d736802802a807d634192328032f6c7"
);
}
#[tokio::test]
async fn profile_feedback_requires_authentication() {
let app = build_router(AppState::new(AppConfig::default()).expect("state should build"));