From 65157475cb5c93c01b4a06bec9179a4ea8d82c66 Mon Sep 17 00:00:00 2001 From: milky0217 Date: Wed, 22 Jul 2026 20:39:57 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BB=9F=E4=B8=80=E4=BD=BF=E7=94=A8=20a?= =?UTF-8?q?lipay.trade.page.pay=20+=20=E6=94=AF=E4=BB=98=E5=85=A8=E9=93=BE?= =?UTF-8?q?=E8=B7=AF=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 因支付宝产品仅开通电脑网站支付,移除 mobile/desktop 切换 - 统一使用 alipay.trade.page.pay + FAST_INSTANT_TRADE_PAY - 该接口在手机浏览器中也能跳转支付宝或显示移动端页面 - 新增 tests/payment_e2e_test.sh — 全链路支付测试脚本 --- src/handlers/payment.rs | 8 ++--- tests/payment_e2e_test.sh | 72 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 5 deletions(-) create mode 100755 tests/payment_e2e_test.sh diff --git a/src/handlers/payment.rs b/src/handlers/payment.rs index 6ff81d5..8f280ff 100644 --- a/src/handlers/payment.rs +++ b/src/handlers/payment.rs @@ -187,11 +187,9 @@ fn build_alipay_form_html( return_url: &str, is_mobile: bool, // true=手机网站支付, false=电脑网站支付 ) -> Result { - let (method, product_code) = if is_mobile { - ("alipay.trade.wap.pay", "QUICK_WAP_PAY") - } else { - ("alipay.trade.page.pay", "FAST_INSTANT_TRADE_PAY") - }; + // 注意:当前支付宝产品仅开通了 alipay.trade.page.pay(电脑网站支付) + // 该接口在手机浏览器中也能正常唤起支付宝 APP 或显示移动端页面 + let (method, product_code) = ("alipay.trade.page.pay", "FAST_INSTANT_TRADE_PAY"); let biz_content = serde_json::json!({ "out_trade_no": out_trade_no, diff --git a/tests/payment_e2e_test.sh b/tests/payment_e2e_test.sh new file mode 100755 index 0000000..bc79c40 --- /dev/null +++ b/tests/payment_e2e_test.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# ===== 全链路支付测试 ===== +# 运行: bash tests/payment_e2e_test.sh +set -e + +BASE_URL="https://xmclassmate.top" +echo "==========================================" +echo " 全链路支付测试" +echo " 环境: ${BASE_URL}" +echo "==========================================" + +# Step 1: 健康检查 +echo "" +echo "[1/5] 健康检查..." +HEALTH=$(curl -s -o /dev/null -w "%{http_code}" ${BASE_URL}/health) +echo " GET /health → HTTP ${HEALTH}" +[ "$HEALTH" = "200" ] && echo " ✅ 通过" || { echo " ❌ 失败"; exit 1; } + +# Step 2: 支付页面可访问 +echo "" +echo "[2/5] 支付页面..." +PAY_CODE=$(curl -s -o /dev/null -w "%{http_code}" ${BASE_URL}/payment) +echo " GET /payment → HTTP ${PAY_CODE}" +[ "$PAY_CODE" = "200" ] && echo " ✅ 通过(维护模式已关闭)" || { echo " ❌ 失败(返回503=维护中)"; exit 1; } + +# Step 3: 访客登录 +echo "" +echo "[3/5] 访客登录..." +LOGIN_RESULT=$(curl -s -X POST ${BASE_URL}/api/guest-login) +JWT=$(echo "$LOGIN_RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['token'])" 2>/dev/null) +USER_ID=$(echo "$LOGIN_RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['user_id'])" 2>/dev/null) +echo " POST /api/guest-login → user_id=${USER_ID}" +[ -n "$JWT" ] && echo " ✅ JWT 获取成功" || { echo " ❌ JWT 获取失败"; exit 1; } + +# Step 4: 用户信息 +echo "" +echo "[4/5] 用户信息..." +PROFILE=$(curl -s -H "Authorization: Bearer ${JWT}" ${BASE_URL}/api/user/profile) +echo " GET /api/user/profile → $(echo $PROFILE | python3 -c "import sys,json; print('is_member='+str(json.load(sys.stdin)['data']['is_member']))" 2>/dev/null)" + +# Step 5: 生成支付表单 +echo "" +echo "[5/5] 支付宝支付表单..." +RESULT=$(curl -s "${BASE_URL}/payment/page?package=monthly&jwt=${JWT}") + +if echo "$RESULT" | grep -q "sign"; then + METHOD=$(echo "$RESULT" | grep -oP '(?<=name="method" value=")[^"]+') + APP_ID_CHECK=$(echo "$RESULT" | grep -oP '(?<=name="app_id" value=")[^"]+') + GATEWAY=$(echo "$RESULT" | grep -oP '(?<=action=")[^"]+') + echo " method: ${METHOD}" + echo " app_id: ${APP_ID_CHECK}" + echo " gateway: ${GATEWAY}" + echo " ✅ 支付表单生成成功" +elif echo "$RESULT" | grep -q "失败\|Error"; then + echo " ❌ 支付表单生成失败" + echo "$RESULT" | grep -oP '(?<=]*>)[^<]+' | head -3 + exit 1 +else + echo " ❌ 未知响应" + echo "${RESULT:0:200}" + exit 1 +fi + +echo "" +echo "==========================================" +echo " 全链路测试通过 ✅" +echo "==========================================" +echo "" +echo "手动验证:" +echo "1. 打开 https://xmclassmate.top/payment" +echo "2. 点击「访客登录」→ 选择套餐 → 支付" +echo "3. 浏览器将跳转到支付宝 alipay.trade.page.pay 页面"