补齐微信虚拟支付查单与补偿

接入微信官方虚拟支付查单并缓存稳定接口令牌
让用户确认与订单过期补偿统一核对支付类型、状态、金额和单号
增加单笔历史订单的 dry-run 与确认指纹补单工具
隔离运行时身份与敏感 openid 文件并补充配置契约和回归测试
This commit is contained in:
2026-07-13 13:12:44 +08:00
parent 06aa99e3eb
commit 2f69f2fda2
16 changed files with 1343 additions and 33 deletions
@@ -89,11 +89,14 @@ use crate::{
api_response::json_success_body,
auth::AuthenticatedAccessToken,
http_error::AppError,
platform_errors::map_wechat_error,
request_context::RequestContext,
state::AppState,
wechat::pay::{
build_wechat_payment_request, build_wechat_web_payment_request, current_unix_micros,
map_wechat_pay_error,
build_wechat_payment_request, build_wechat_virtual_payment_query_order_request,
build_wechat_web_payment_request, current_unix_micros,
is_wechat_virtual_payment_order_paid, map_wechat_pay_error,
paid_at_micros_from_wechat_virtual_payment_order, validate_wechat_virtual_payment_order,
},
};
@@ -389,6 +392,52 @@ pub async fn confirm_wechat_profile_recharge_order(
));
}
if order.payment_channel == PROFILE_RECHARGE_PAYMENT_CHANNEL_WECHAT_MINI_PROGRAM_VIRTUAL {
let openid = resolve_wechat_identity_for_payment(&state, &order.user_id)
.await
.map_err(|error| runtime_profile_error_response(&request_context, error))?;
let query_request = build_wechat_virtual_payment_query_order_request(
&state.config,
openid,
order.order_id.clone(),
)
.map_err(|error| {
runtime_profile_error_response(&request_context, map_wechat_error(error))
})?;
let wechat_order = state
.wechat_client()
.query_virtual_payment_order(query_request)
.await
.map_err(|error| {
runtime_profile_error_response(&request_context, map_wechat_error(error))
})?;
validate_wechat_virtual_payment_order(&order.order_id, order.amount_cents, &wechat_order)
.map_err(|error| {
runtime_profile_error_response(&request_context, map_wechat_error(error))
})?;
if !is_wechat_virtual_payment_order_paid(wechat_order.status) {
return Ok(json_success_body(
Some(&request_context),
build_wechat_profile_recharge_order_confirmation(center, order),
));
}
let paid_at_micros = paid_at_micros_from_wechat_virtual_payment_order(&wechat_order);
let (center, order) = state
.spacetime_client()
.mark_profile_recharge_order_paid(
wechat_order.order_id,
paid_at_micros,
wechat_order.wxpay_order_id.or(wechat_order.wx_order_id),
)
.await
.map_err(|error| {
runtime_profile_error_response(
&request_context,
map_runtime_profile_client_error(error),
)
})?;
state.publish_profile_recharge_order_update(order.order_id.clone());
return Ok(json_success_body(
Some(&request_context),
build_wechat_profile_recharge_order_confirmation(center, order),