fix: 使用请求 Host 头动态构建 notify_url + 迁移文档/测试
Some checks failed
Deploy Backend / deploy (push) Has been cancelled

根因:base_url 默认硬编码为 dev.xmclassmate.top,导致支付宝通知回调
(notify_url)指向开发服务器,RSA2 签名验证失败,订单延迟 12 分钟。

修复:
- 新增 get_base_url():优先用 APP_BASE_URL 环境变量,否则从请求
  Host 头获取当前域名,确保 notify_url 始终指向正确的服务器
- 生产 .env 已设置 APP_BASE_URL=https://xmclassmate.top
- .env.example 新增 APP_BASE_URL 文档

迁移文档:
- SERVER-MIGRATION-PLAN.md 新增阶段 3 关键配置章节
- 12 项迁移检查清单 + 历史问题复盘

部署测试:
- test.sh 新增 test_notify_url_domain:校验支付表单 notify_url
  域名与 BASE_URL 一致,迁移后自动捕获配置错误
This commit is contained in:
2026-07-23 12:09:52 +08:00
parent 65157475cb
commit 0b0757939b
3 changed files with 168 additions and 34 deletions

View File

@@ -272,6 +272,20 @@ fn check_payment_maintenance() -> Result<(), AppError> {
Ok(())
}
/// 构建基础 URL优先使用 APP_BASE_URL 环境变量,否则从请求 Host 头获取
/// 确保支付宝通知回调notify_url正确指向当前处理请求的服务器
fn get_base_url(req: &HttpRequest) -> String {
if let Ok(url) = std::env::var("APP_BASE_URL") {
return url;
}
let host = req
.headers()
.get("Host")
.and_then(|v| v.to_str().ok())
.unwrap_or("xmclassmate.top");
format!("https://{}", host)
}
fn extract_token(req: &HttpRequest) -> Option<String> {
req.headers()
.get("Authorization")?
@@ -783,8 +797,7 @@ pub async fn payment_page(
}
};
let base_url = std::env::var("APP_BASE_URL")
.unwrap_or_else(|_| "https://dev.xmclassmate.top".to_string());
let base_url = get_base_url(&req);
let notify_url = format!("{}/payment/notify", base_url);
let return_url = format!("{}/payment/success?order_no={}&jwt={}", base_url, order_no, token);
@@ -848,8 +861,7 @@ pub async fn alipay_pay_page(
let pkg = get_package_info(&query.package_type)
.ok_or_else(|| AppError::BadRequest("无效的套餐类型".to_string()))?;
let base_url = std::env::var("APP_BASE_URL")
.unwrap_or_else(|_| "https://dev.xmclassmate.top".to_string());
let base_url = get_base_url(&req);
let notify_url = format!("{}/payment/notify", base_url);
let return_url = format!("{}/payment/success?order_no={}", base_url, query.order_no);