feat: 根据 User-Agent 自动切换手机/电脑网站支付
Some checks failed
Deploy Backend / deploy (push) Has been cancelled

- 新增 is_mobile_ua() 检测手机浏览器(mobile/android/iphone/ipad/harmonyos)
- build_alipay_form_html 新增 is_mobile 参数
- 手机端: alipay.trade.wap.pay + QUICK_WAP_PAY
- 桌面端: alipay.trade.page.pay + FAST_INSTANT_TRADE_PAY
- 同时应用于 payment_page 和 alipay_pay_page 两个入口
This commit is contained in:
2026-07-20 15:22:42 +08:00
parent a7ffd387d9
commit 6b0871f77d

View File

@@ -165,6 +165,17 @@ fn rsa2_verify(content: &str, sign: &str, public_key_pem: &str) -> Result<bool,
Ok(true)
}
/// 检测是否为移动端浏览器
fn is_mobile_ua(user_agent: &str) -> bool {
let ua = user_agent.to_lowercase();
ua.contains("mobile")
|| ua.contains("android")
|| ua.contains("iphone")
|| ua.contains("ipad")
|| ua.contains("phone")
|| ua.contains("harmonyos")
}
// ===== Helper: 生成支付宝支付表单 HTML =====
fn build_alipay_form_html(
@@ -174,12 +185,19 @@ fn build_alipay_form_html(
subject: &str,
notify_url: &str,
return_url: &str,
is_mobile: bool, // true=手机网站支付, false=电脑网站支付
) -> Result<String, String> {
let (method, product_code) = if is_mobile {
("alipay.trade.wap.pay", "QUICK_WAP_PAY")
} else {
("alipay.trade.page.pay", "FAST_INSTANT_TRADE_PAY")
};
let biz_content = serde_json::json!({
"out_trade_no": out_trade_no,
"total_amount": total_amount,
"subject": subject,
"product_code": "QUICK_WAP_PAY",
"product_code": product_code,
});
let biz_content_str =
@@ -188,7 +206,7 @@ fn build_alipay_form_html(
let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
let mut params: BTreeMap<&str, &str> = BTreeMap::new();
params.insert("app_id", &config.app_id);
params.insert("method", "alipay.trade.wap.pay");
params.insert("method", method);
params.insert("format", "JSON");
params.insert("charset", "utf-8");
params.insert("sign_type", "RSA2");
@@ -782,6 +800,14 @@ pub async fn payment_page(
let total_amount_str = format!("{:.2}", pkg.amount as f64 / 100.0);
// 根据 User-Agent 选择手机网站支付或电脑网站支付
let mobile = req
.headers()
.get("User-Agent")
.and_then(|v| v.to_str().ok())
.map(is_mobile_ua)
.unwrap_or(false);
match build_alipay_form_html(
&config,
&order_no,
@@ -789,6 +815,7 @@ pub async fn payment_page(
pkg.display_name,
&notify_url,
&return_url,
mobile,
) {
Ok(form_html) => Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
@@ -838,6 +865,13 @@ pub async fn alipay_pay_page(
let total_amount_str = format!("{:.2}", pkg.amount as f64 / 100.0);
let mobile = req
.headers()
.get("User-Agent")
.and_then(|v| v.to_str().ok())
.map(is_mobile_ua)
.unwrap_or(false);
match build_alipay_form_html(
&config,
&query.order_no,
@@ -845,6 +879,7 @@ pub async fn alipay_pay_page(
pkg.display_name,
&notify_url,
&return_url,
mobile,
) {
Ok(form_html) => Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")