diff --git a/apps/h5-shop/src/pages/HomePage.tsx b/apps/h5-shop/src/pages/HomePage.tsx index 96e432f..e78d00c 100644 --- a/apps/h5-shop/src/pages/HomePage.tsx +++ b/apps/h5-shop/src/pages/HomePage.tsx @@ -24,7 +24,7 @@ function formatMoney(n: number) { function formatScanError(e: unknown): string { const msg = e instanceof Error ? e.message : '扫码失败,请重试'; if (/invalid signature/i.test(msg)) { - return '微信 JSSDK 签名校验失败:请确认公众号已配置 JS 接口安全域名为 m.runxian.top,并刷新页面后重试'; + return '微信 JSSDK 签名校验失败:请确认公众号已配置 JS 接口安全域名为 user.runxian.top,并刷新页面后重试'; } return msg; } diff --git a/deploy/enable-runxian-dukang-ssl.sh b/deploy/enable-runxian-dukang-ssl.sh index 04650e4..046495e 100644 --- a/deploy/enable-runxian-dukang-ssl.sh +++ b/deploy/enable-runxian-dukang-ssl.sh @@ -1,11 +1,10 @@ #!/usr/bin/env bash # 为杜康 runxian.top 申请 Let's Encrypt 并切换 HTTPS 配置 -# 三端 H5 统一入口 m.runxian.top(微信网页授权单域名) +# 三端 H5 统一入口 user.runxian.top/{user,shop,partner}/ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" DOMAINS=( - m.runxian.top user.runxian.top shop.runxian.top partner.runxian.top @@ -27,8 +26,7 @@ mkdir -p /var/www/certbot /var/log/nginx/dukang echo "==> 申请证书..." certbot certonly --webroot -w /var/www/certbot \ - --cert-name m.runxian.top \ - -d m.runxian.top \ + --cert-name user.runxian.top \ -d user.runxian.top \ -d shop.runxian.top \ -d partner.runxian.top \ @@ -46,14 +44,14 @@ systemctl reload nginx echo "==> 验证..." for url in \ - https://m.runxian.top/user/ \ - https://m.runxian.top/shop/ \ - https://m.runxian.top/partner/ \ - https://user.runxian.top/ \ + https://user.runxian.top/user/ \ + https://user.runxian.top/shop/ \ + https://user.runxian.top/partner/ \ + https://shop.runxian.top/ \ https://webadmin.runxian.top/ \ https://dkapi.runxian.top/api/v1/health; do code="$(curl -sf -o /dev/null -w '%{http_code}' "$url" || echo fail)" echo " $url -> $code" done -echo "==> runxian.top 杜康域名 HTTPS 已启用(H5 统一入口 m.runxian.top)" +echo "==> runxian.top 杜康域名 HTTPS 已启用(H5 统一入口 user.runxian.top)" diff --git a/deploy/nginx-runxian-dukang-ssl.conf b/deploy/nginx-runxian-dukang-ssl.conf index d659637..bf131a2 100644 --- a/deploy/nginx-runxian-dukang-ssl.conf +++ b/deploy/nginx-runxian-dukang-ssl.conf @@ -1,10 +1,10 @@ # 杜康好客 — runxian.top HTTPS # 执行: deploy/enable-runxian-dukang-ssl.sh -# 三端 H5 统一入口 m.runxian.top/{user,shop,partner}/ +# 三端 H5 统一入口 user.runxian.top/{user,shop,partner}/ server { listen 80; - server_name m.runxian.top user.runxian.top shop.runxian.top partner.runxian.top; + server_name user.runxian.top shop.runxian.top partner.runxian.top m.runxian.top; location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; @@ -12,7 +12,7 @@ server { } location / { - return 301 https://$host$request_uri; + return 301 https://user.runxian.top$request_uri; } } @@ -20,11 +20,22 @@ server { listen 443 ssl; server_name m.runxian.top; - access_log /var/log/nginx/dukang/runxian-m.access.log main; - error_log /var/log/nginx/dukang/runxian-m.error.log warn; + ssl_certificate /etc/letsencrypt/live/user.runxian.top/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/user.runxian.top/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; - ssl_certificate /etc/letsencrypt/live/m.runxian.top/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/m.runxian.top/privkey.pem; + return 301 https://user.runxian.top$request_uri; +} + +server { + listen 443 ssl; + server_name user.runxian.top; + + access_log /var/log/nginx/dukang/runxian-h5.access.log main; + error_log /var/log/nginx/dukang/runxian-h5.error.log warn; + + ssl_certificate /etc/letsencrypt/live/user.runxian.top/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/user.runxian.top/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; @@ -64,39 +75,33 @@ server { alias /opt/dukang-haoke/apps/h5-partner/dist/; try_files $uri $uri/ index.html; } -} -server { - listen 443 ssl; - server_name user.runxian.top; - - ssl_certificate /etc/letsencrypt/live/m.runxian.top/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/m.runxian.top/privkey.pem; - ssl_protocols TLSv1.2 TLSv1.3; - - return 301 https://m.runxian.top/user$request_uri; + # 旧 C 端根路径书签(无 /user 前缀)→ /user/... + location / { + return 302 /user$request_uri; + } } server { listen 443 ssl; server_name shop.runxian.top; - ssl_certificate /etc/letsencrypt/live/m.runxian.top/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/m.runxian.top/privkey.pem; + ssl_certificate /etc/letsencrypt/live/user.runxian.top/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/user.runxian.top/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - return 301 https://m.runxian.top/shop$request_uri; + return 301 https://user.runxian.top/shop$request_uri; } server { listen 443 ssl; server_name partner.runxian.top; - ssl_certificate /etc/letsencrypt/live/m.runxian.top/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/m.runxian.top/privkey.pem; + ssl_certificate /etc/letsencrypt/live/user.runxian.top/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/user.runxian.top/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - return 301 https://m.runxian.top/partner$request_uri; + return 301 https://user.runxian.top/partner$request_uri; } server { @@ -108,6 +113,8 @@ server { default_type "text/plain"; } + include /opt/dukang-haoke/deploy/nginx-deploy-webhook.conf; + location / { return 301 https://$host$request_uri; } @@ -120,13 +127,15 @@ server { access_log /var/log/nginx/dukang/runxian-api.access.log main; error_log /var/log/nginx/dukang/runxian-api.error.log warn; - ssl_certificate /etc/letsencrypt/live/m.runxian.top/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/m.runxian.top/privkey.pem; + ssl_certificate /etc/letsencrypt/live/user.runxian.top/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/user.runxian.top/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; client_max_body_size 20m; + include /opt/dukang-haoke/deploy/nginx-deploy-webhook.conf; + location / { proxy_pass http://127.0.0.1:8090; proxy_http_version 1.1; @@ -159,8 +168,8 @@ server { access_log /var/log/nginx/dukang/runxian-admin.access.log main; error_log /var/log/nginx/dukang/runxian-admin.error.log warn; - ssl_certificate /etc/letsencrypt/live/m.runxian.top/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/m.runxian.top/privkey.pem; + ssl_certificate /etc/letsencrypt/live/user.runxian.top/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/user.runxian.top/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; diff --git a/deploy/nginx-runxian-dukang.conf b/deploy/nginx-runxian-dukang.conf index 6487cf3..d260926 100644 --- a/deploy/nginx-runxian-dukang.conf +++ b/deploy/nginx-runxian-dukang.conf @@ -1,14 +1,13 @@ # 杜康好客 — runxian.top(HTTP) -# 三端 H5 统一入口 m.runxian.top/{user,shop,partner}/(微信网页授权单域名) -# 旧子域名 user/shop/partner 301 到统一入口;webadmin → 8094;dkapi → 8090 +# 三端 H5 统一入口 user.runxian.top/{user,shop,partner}/(微信网页授权单域名) +# shop/partner 子域名 301 到 user.runxian.top 路径;webadmin → 8094;dkapi → 8090 -# --- 统一 H5 入口(证书就绪前 HTTP;HTTPS 见 dukang-runxian-ssl.conf)--- server { listen 80; - server_name m.runxian.top; + server_name user.runxian.top; - access_log /var/log/nginx/dukang/runxian-m.access.log main; - error_log /var/log/nginx/dukang/runxian-m.error.log warn; + access_log /var/log/nginx/dukang/runxian-h5.access.log main; + error_log /var/log/nginx/dukang/runxian-h5.error.log warn; client_max_body_size 20m; @@ -51,28 +50,30 @@ server { alias /opt/dukang-haoke/apps/h5-partner/dist/; try_files $uri $uri/ index.html; } -} -# --- 旧 H5 子域名 → 统一入口(保留书签/推广链接)--- -server { - listen 80; - server_name user.runxian.top; - return 301 http://m.runxian.top/user$request_uri; + location / { + return 302 /user$request_uri; + } } server { listen 80; server_name shop.runxian.top; - return 301 http://m.runxian.top/shop$request_uri; + return 301 http://user.runxian.top/shop$request_uri; } server { listen 80; server_name partner.runxian.top; - return 301 http://m.runxian.top/partner$request_uri; + return 301 http://user.runxian.top/partner$request_uri; +} + +server { + listen 80; + server_name m.runxian.top; + return 301 http://user.runxian.top$request_uri; } -# --- HTTP: API --- server { listen 80; server_name dkapi.runxian.top; @@ -98,7 +99,6 @@ server { } } -# --- HTTP: admin-web --- server { listen 80; server_name webadmin.runxian.top; diff --git a/deploy/remote-continue-m-domain.sh b/deploy/remote-continue-m-domain.sh index 0d7ae1a..cf282de 100644 --- a/deploy/remote-continue-m-domain.sh +++ b/deploy/remote-continue-m-domain.sh @@ -1,10 +1,9 @@ #!/usr/bin/env bash -# 续部署:m.runxian.top 统一入口 + SSL 扩展 + nginx 切换 +# 续部署:user.runxian.top 统一路径入口 + nginx 切换 set -euo pipefail APP_ROOT="${APP_ROOT:-/opt/dukang-haoke}" -CERT_NAME="${CERT_CERT_NAME:-user.runxian.top}" -CERT_DIR="/etc/letsencrypt/live/${CERT_NAME}" +H5_BASE="https://user.runxian.top" cd "$APP_ROOT" @@ -12,63 +11,29 @@ echo "==> 1. PM2 重启(H5 dist 已含 /user|shop|partner/ 路径)" pm2 restart dukang-api dukang-h5-user dukang-h5-shop dukang-h5-partner dukang-admin-web pm2 save -echo "==> 2. 临时 ACME:m.runxian.top:80" -cat > /etc/nginx/conf.d/dukang-m-acme-temp.conf <<'EOF' -server { - listen 80; - server_name m.runxian.top; - location ^~ /.well-known/acme-challenge/ { - root /var/www/certbot; - default_type "text/plain"; - } - location / { return 404; } -} -EOF -nginx -t -systemctl reload nginx - -echo "==> 3. 扩展证书 SAN:加入 m.runxian.top" -certbot certonly --webroot -w /var/www/certbot \ - --expand --cert-name "$CERT_NAME" \ - -d user.runxian.top \ - -d shop.runxian.top \ - -d partner.runxian.top \ - -d webadmin.runxian.top \ - -d dkapi.runxian.top \ - -d m.runxian.top \ - --non-interactive --agree-tos -m admin@runxian.top - -echo "==> 4. 安装 nginx HTTPS 配置" +echo "==> 2. 安装 nginx HTTPS 配置" install -m 644 "$APP_ROOT/deploy/nginx-runxian-dukang-ssl.conf" /etc/nginx/conf.d/dukang-runxian.conf -sed -i "s|/etc/letsencrypt/live/m.runxian.top/|${CERT_DIR}/|g" /etc/nginx/conf.d/dukang-runxian.conf - -if ! grep -q nginx-deploy-webhook /etc/nginx/conf.d/dukang-runxian.conf; then - sed -i '/server_name dkapi.runxian.top;/a\ include /opt/dukang-haoke/deploy/nginx-deploy-webhook.conf;' \ - /etc/nginx/conf.d/dukang-runxian.conf -fi - -rm -f /etc/nginx/conf.d/dukang-m-acme-temp.conf nginx -t systemctl reload nginx -echo "==> 5. 更新 USER_H5_URL" +echo "==> 3. 更新 USER_H5_URL" ENV_FILE="$APP_ROOT/server/dukang-api/.env" if grep -q '^USER_H5_URL=' "$ENV_FILE"; then - sed -i 's|^USER_H5_URL=.*|USER_H5_URL=https://m.runxian.top/user|' "$ENV_FILE" + sed -i "s|^USER_H5_URL=.*|USER_H5_URL=${H5_BASE}/user|" "$ENV_FILE" else - echo 'USER_H5_URL=https://m.runxian.top/user' >> "$ENV_FILE" + echo "USER_H5_URL=${H5_BASE}/user" >> "$ENV_FILE" fi pm2 restart dukang-api -echo "==> 6. 验证" +echo "==> 4. 验证" for url in \ - "https://m.runxian.top/user/" \ - "https://m.runxian.top/shop/" \ - "https://m.runxian.top/partner/" \ - "https://user.runxian.top/" \ + "${H5_BASE}/user/" \ + "${H5_BASE}/shop/" \ + "${H5_BASE}/partner/" \ + "https://shop.runxian.top/" \ "https://dkapi.runxian.top/api/v1/health"; do code="$(curl -sk -o /dev/null -w '%{http_code}' "$url" || echo fail)" echo " $url -> $code" done -echo "==> m.runxian.top 部署完成" +echo "==> user.runxian.top 统一部署完成" diff --git a/scripts/configure-oss-cors.mjs b/scripts/configure-oss-cors.mjs index 3212980..28e19b8 100644 --- a/scripts/configure-oss-cors.mjs +++ b/scripts/configure-oss-cors.mjs @@ -57,7 +57,7 @@ const defaultOrigins = [ 'http://localhost:5173/user', 'http://localhost:5174/shop', 'http://localhost:5175/partner', - 'https://m.runxian.top', + 'https://user.runxian.top', ]; const allowedOrigin = (OSS_CORS_ORIGINS ?? defaultOrigins.join(',')) diff --git a/server/dukang-api/.env.example b/server/dukang-api/.env.example index b668735..26c15e3 100644 --- a/server/dukang-api/.env.example +++ b/server/dukang-api/.env.example @@ -26,15 +26,15 @@ MOCK_WECHAT=true WX_AUTHORIZE=false # C 端 H5 落地页(推广码二维码链接前缀) -# 本地开发:http://localhost:5173/user 生产统一入口:https://m.runxian.top/user +# 本地开发:http://localhost:5173/user 生产统一入口:https://user.runxian.top/user USER_H5_URL=http://localhost:5173/user # 反向代理后提取真实客户端 IP(下单 IP 定位) TRUST_PROXY=true # 微信 SDK(生产:WECHAT_AUTH_ENABLED=true,配置 WX_APP_ID / WX_APP_SECRET) -# OAuth 授权页由 /common/wechat/oauth-url 生成;三端统一入口 m.runxian.top/{user,shop,partner}。 -# 微信服务号「网页授权域名」「JS 接口安全域名」均配置 m.runxian.top(仅 1 个名额)。 +# OAuth 授权页由 /common/wechat/oauth-url 生成;三端统一入口 user.runxian.top/{user,shop,partner}。 +# 微信服务号「网页授权域名」「JS 接口安全域名」均配置 user.runxian.top(仅 1 个名额)。 WX_APP_ID= WX_APP_SECRET= WECHAT_AUTH_ENABLED=false diff --git a/server/dukang-api/.env.production.example b/server/dukang-api/.env.production.example index c211339..36f5a47 100644 --- a/server/dukang-api/.env.production.example +++ b/server/dukang-api/.env.production.example @@ -23,7 +23,7 @@ AUTO_APPROVE_STORE=false TRUST_PROXY=true # C 端 H5 落地页(推广码二维码;生产统一入口) -USER_H5_URL=https://m.runxian.top/user +USER_H5_URL=https://user.runxian.top/user WECHAT_AUTH_ENABLED=true WECHAT_PAY_ENABLED=true