fix wechat mini program virtual payment flow
This commit is contained in:
@@ -4,6 +4,7 @@ use axum::{
|
||||
http::{HeaderMap, StatusCode},
|
||||
response::Response,
|
||||
};
|
||||
use hmac::{Hmac, Mac};
|
||||
use module_runtime::{
|
||||
AnalyticsGranularity, PROFILE_RECHARGE_PAYMENT_CHANNEL_MOCK,
|
||||
PROFILE_RECHARGE_PAYMENT_CHANNEL_WECHAT_H5,
|
||||
@@ -24,7 +25,6 @@ use module_runtime::{
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_json::{Value, json};
|
||||
use hmac::{Hmac, Mac};
|
||||
use sha2::Sha256;
|
||||
use shared_contracts::runtime::{
|
||||
ANALYTICS_GRANULARITY_DAY, ANALYTICS_GRANULARITY_MONTH, ANALYTICS_GRANULARITY_QUARTER,
|
||||
@@ -1187,10 +1187,6 @@ fn build_wechat_virtual_pay_params(
|
||||
AppError::from_status(StatusCode::BAD_REQUEST)
|
||||
.with_message("当前微信登录态缺少 session_key,请重新登录后再试")
|
||||
})?;
|
||||
let product = module_runtime::runtime_profile_recharge_product_by_id(&order.product_id)
|
||||
.ok_or_else(|| {
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_message("充值商品不存在")
|
||||
})?;
|
||||
let offer_id = required_wechat_virtual_payment_config(
|
||||
state
|
||||
.config
|
||||
@@ -1198,7 +1194,7 @@ fn build_wechat_virtual_pay_params(
|
||||
.as_deref(),
|
||||
"微信虚拟支付 OfferId 未配置",
|
||||
)?;
|
||||
let mode = match product.kind {
|
||||
let mode = match order.kind {
|
||||
RuntimeProfileRechargeProductKind::Points => "short_series_coin",
|
||||
RuntimeProfileRechargeProductKind::Membership => "short_series_goods",
|
||||
};
|
||||
@@ -1215,9 +1211,9 @@ fn build_wechat_virtual_pay_params(
|
||||
"openId": openid,
|
||||
}).to_string(),
|
||||
});
|
||||
if product.kind == RuntimeProfileRechargeProductKind::Membership {
|
||||
sign_data["productId"] = json!(product.product_id);
|
||||
sign_data["goodsPrice"] = json!(product.price_cents);
|
||||
if order.kind == RuntimeProfileRechargeProductKind::Membership {
|
||||
sign_data["productId"] = json!(order.product_id);
|
||||
sign_data["goodsPrice"] = json!(order.amount_cents);
|
||||
}
|
||||
let sign_data = sign_data.to_string();
|
||||
let pay_sig = calc_wechat_virtual_payment_signature(state, &sign_data, false)?;
|
||||
@@ -1242,7 +1238,10 @@ fn calc_wechat_virtual_payment_signature(
|
||||
.config
|
||||
.wechat_mini_program_virtual_payment_sandbox_app_key
|
||||
.as_deref()
|
||||
.or(state.config.wechat_mini_program_virtual_payment_app_key.as_deref())
|
||||
.or(state
|
||||
.config
|
||||
.wechat_mini_program_virtual_payment_app_key
|
||||
.as_deref())
|
||||
} else {
|
||||
state
|
||||
.config
|
||||
@@ -1250,8 +1249,7 @@ fn calc_wechat_virtual_payment_signature(
|
||||
.as_deref()
|
||||
}
|
||||
.ok_or_else(|| {
|
||||
AppError::from_status(StatusCode::BAD_REQUEST)
|
||||
.with_message("微信虚拟支付 AppKey 未配置")
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_message("微信虚拟支付 AppKey 未配置")
|
||||
})?;
|
||||
calc_wechat_virtual_payment_signature_with_key(app_key, sign_data)
|
||||
}
|
||||
@@ -2294,6 +2292,59 @@ mod tests {
|
||||
assert!(!params.signature.is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn wechat_virtual_pay_params_accept_admin_membership_product_ids() {
|
||||
let state = seed_authenticated_state_with_config(AppConfig {
|
||||
wechat_mini_program_virtual_payment_offer_id: Some("offer-1".to_string()),
|
||||
wechat_mini_program_virtual_payment_app_key: Some("app-key-1".to_string()),
|
||||
wechat_mini_program_virtual_payment_env: 0,
|
||||
..fast_spacetime_timeout_config()
|
||||
})
|
||||
.await;
|
||||
let wechat_login = state
|
||||
.wechat_auth_service()
|
||||
.resolve_login(ResolveWechatLoginInput {
|
||||
profile: WechatIdentityProfile {
|
||||
provider_uid: "openid-user-item01".to_string(),
|
||||
provider_union_id: Some("union-user-item01".to_string()),
|
||||
display_name: Some("资料页用户".to_string()),
|
||||
avatar_url: None,
|
||||
session_key: Some("session-key-item01".to_string()),
|
||||
},
|
||||
})
|
||||
.await
|
||||
.expect("wechat identity should seed");
|
||||
let order = RuntimeProfileRechargeOrderRecord {
|
||||
order_id: "item01order01".to_string(),
|
||||
user_id: wechat_login.user.id,
|
||||
product_id: "item01".to_string(),
|
||||
product_title: "测试道具".to_string(),
|
||||
kind: RuntimeProfileRechargeProductKind::Membership,
|
||||
amount_cents: 100,
|
||||
status: RuntimeProfileRechargeOrderStatus::Pending,
|
||||
payment_channel: PROFILE_RECHARGE_PAYMENT_CHANNEL_WECHAT_MINI_PROGRAM_VIRTUAL
|
||||
.to_string(),
|
||||
paid_at: None,
|
||||
paid_at_micros: None,
|
||||
provider_transaction_id: None,
|
||||
created_at: "2026-05-27T10:00:00Z".to_string(),
|
||||
created_at_micros: 1_779_842_400_000_000,
|
||||
points_delta: 0,
|
||||
membership_expires_at: None,
|
||||
membership_expires_at_micros: None,
|
||||
};
|
||||
|
||||
let params = build_wechat_virtual_pay_params(&state, &order, "openid-user-item01")
|
||||
.expect("custom membership virtual pay params should build");
|
||||
let sign_data: Value =
|
||||
serde_json::from_str(¶ms.sign_data).expect("sign data should be valid json");
|
||||
|
||||
assert_eq!(params.mode, "short_series_goods");
|
||||
assert_eq!(sign_data["productId"], "item01");
|
||||
assert_eq!(sign_data["goodsPrice"], 100);
|
||||
assert_eq!(sign_data["outTradeNo"], "item01order01");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn profile_feedback_requires_authentication() {
|
||||
let app = build_router(AppState::new(AppConfig::default()).expect("state should build"));
|
||||
|
||||
Reference in New Issue
Block a user