七、本地跑通 saas-starter

本章在本地把 saas-starter 当作真实业务 SaaS 跑起来,先验收 SaaS 自身,不拼完整支付链路。

重要

🎯 重要:本章目标: 证明 SaaS 能启动、能连业务库、能创建匿名会话,且已写入后续调用 web-pay 所需的商户号与应用身份。

本章做到这些即可:

  • 本地 SaaS 后端、前端可访问

  • 业务库连接正常

  • 匿名会话可创建

  • mchNoappIdAppSecret 已写入配置

本章不做:

  • 创建支付订单、跳转收银台、验证支付通知

  • 把本机 SaaS、本机收银台、本机运营平台拼成支付闭环

为什么先不拼本地支付闭环: 完整支付依赖收银台、支付网关 API、运营平台商户/应用/通道、支付平台公网回调和 SaaS 通知地址。本章先证明 SaaS 自身可用,避免把端口、隧道、跨域、回调地址等问题提前混在一起。

推荐顺序: 第 8 章先完成 web-pay 上线配置 → 第 9 章回到本机,集中验证 saas-starter 下单、收银台、付款回调与业务订阅更新。

7.1 saas-starter 脚本速读

saas-starter 的脚本都在 saas-starter/env-scripts/:

小技巧

🧰 先认脚本,再启动 SaaS。 本章主要用配置脚本、后端启动脚本和停止脚本;生产构建和上传脚本等线上部署时再处理。

脚本 作用 什么时候用
rename-saas-service.sh 写入 SaaS 前后端配置、少量前端展示文案和上传脚本 SSH 默认值 第一次配置 SaaS 或调整部署信息时
start-local-test-backend.sh 构建并启动 SaaS 后端,创建 cloudflared 隧道,生成 logs/application-local-tunnel.yml 本地跑 SaaS 后端;第 9 章验证支付通知时也会用到
stop.sh 停止 SaaS 本地后端和 cloudflared 隧道;如果你用 CLI 启动前端,也可按实际端口清理前端进程 本地联调结束或端口冲突时
build-prod-backend.sh 生产方式构建 backend/target/saas-starter.jar 线上部署前构建后端
build-prod-frontend.sh 生产方式构建 H5 前端 frontend/dist 线上部署前构建前端
upload-saas-backend-jars.sh 上传 backend/target/saas-starter.jar 到云服务器 后端生产构建完成后,需要把 SaaS 后端 Jar 上传到服务器时

saas-starter 本地与部署脚本分工

警告

⚠️ 本章不要先跑生产构建和上传脚本。先确认本地 SaaS 后端、H5 前端和业务库连接正常,再进入后续线上部署章节。

7.2 执行 saas-starter 配置脚本

SaaS 示例项目有自己的配置脚本:

saas-starter/env-scripts/rename-saas-service.sh

重要

📌 这一步会把第 3 章和第 6 章记录的信息写入 SaaS 配置。 尤其是 mchNoappIdAppSecret,后面 SaaS 调用 web-pay 都依赖这组值。

运行前先准备 03 章里的 saas-starter-deploy-info.md,脚本会按下面顺序询问:

脚本会询问 示例 说明
服务名 saas-starter 只能使用小写字母、数字和中划线;空值默认 saas-starter
根域名 example.cn 自己申请的根域名,脚本会自动生成 SaaS 前端和后端域名
收银台前端域名 pay.example.cn 与web-pay配置一致,填 web-pay 统一收银台前端域名,不需要写 https://
收银台后端域名 pay-api.example.cn 与web-pay配置一致,填 web-pay 支付网关后端域名,不需要写 https://
PostgreSQL 内网连接地址(不含端口) 192.168.1.100 与web-pay配置一致,云服务器线上运行用;写入 SaaS application.yml
PostgreSQL 公网连接地址(不含端口) 123.45.67.89 与web-pay配置一致,本机联调用;写入 SaaS application-local.yml
PostgreSQL 数据库名称 saas_starter 与web-pay配置一致,必须和 RDS 中新建的 SaaS 业务库一致
数据库用户名和密码 你的 RDS 业务用户 与web-pay配置一致,写入 SaaS 后端配置
SSH 账户地址 / 账户 / 密码 12.34.56.78 / root / 自行填写强密码 与web-pay配置一致,写入 upload-saas-backend-jars.sh 的默认值
Zhcpay 商户号、AppID、AppSecret web-pay 运营平台应用信息 SaaS 后端调用 web-pay 时使用

备注

💡 如果你本章只是先跑通教程,服务名可以直接回车保留 saas-starter,不用真的改成新产品名。

危险

🔐 脚本会写入敏感配置。 数据库密码、SSH 信息和 web-pay AppSecret 只应该保存在你控制的本地环境或私有仓库中,不要放进公开截图、公开文档或前端可见配置。

在 SaaS 项目目录执行:

cd saas-starter
chmod +x ./env-scripts/rename-saas-service.sh
./env-scripts/rename-saas-service.sh

脚本执行完成后会直接写入这些文件:

文件 写入内容
backend/src/main/resources/application.yml 生产后端端口 9220、PostgreSQL 内网 JDBC、Zhcpay 身份、收银台前后端 URL、SaaS 生产站点和通知地址
backend/src/main/resources/application-local.yml 本地后端端口 9220、PostgreSQL 公网 JDBC、Zhcpay 身份、收银台前后端 URL、本地站点 http://localhost:5173
frontend/.env 生产 SaaS API Base 和前端展示名
frontend/.env.development 本地 SaaS API Base http://localhost:9220/api/v1 和开发展示名
env-scripts/upload-saas-backend-jars.sh SSH 账户地址、账户和密码默认值

脚本还会替换少量用户可见的 SaaS Starter 前端展示文案,例如浏览器标题、关于页、协议/隐私文案。它不会修改 Java 包名、Maven artifactIdbackend/target/saas-starter.jar、数据库表名或本地存储 key。

saas-starter 配置脚本写入前后端配置

小技巧

💡 如果后面重新运行配置脚本,已经启动的 SaaS 后端需要重启才会读取新的 Spring 配置;前端 .env 变化也要重新运行 H5 前端。

7.3 启动前检查

确认:

警告

⚠️ 这些项通过后再启动 SaaS。 如果业务库、支付身份或配置脚本有一项没准备好,后端可能能启动,但页面接口或后续支付联调会很快报错。

  • 第 5 章已经确认 web-pay 本地服务可启动。

  • 第 6 章已经创建商户和应用,并把 mchNoappIdAppSecret 记录到 saas-starter-deploy-info.md

  • RDS 中已经创建 SaaS 业务库,例如 saas_starter。业务库可以是空库,启动脚本会自动检查并初始化 SaaS 基础业务表。

  • 已按 7.2 执行 saas-starter/env-scripts/rename-saas-service.sh,脚本已经把配置直接写入前后端配置文件。

  • saas-starter/backend/src/main/resources/application-local.yml 能连接 SaaS 业务库。

SaaS 本地启动前检查项

7.4 配置 SaaS 支付身份

SaaS 后端调用 web-pay 时,必须带上 web-pay 运营平台里创建的应用身份。

SaaS 后端调用 web-pay 的应用身份

这些值已经由 7.2 的配置脚本直接写入 saas-starter/backend/src/main/resources/application-local.ymlapplication.yml。你可以检查本地配置:

zhcpay:
  mch-no: "你的商户号"
  app-id: "web-pay运营平台应用AppId"
  app-secret: "web-pay运营平台应用AppSecret"

重要

🎯 SaaS 支付身份只属于后端。 前端页面不需要知道 AppSecret;它只负责请求 SaaS 后端,由 SaaS 后端再用这组身份调用 web-pay。

这些值来自第 6 章的本地支付配置。如果你还没创建应用,先回到第 6 章创建商户和应用,再重新执行 7.2 的配置脚本并重启 SaaS 后端。

警告

⚠️ mch-noapp-idapp-secret 必须来自同一个 web-pay 应用。混用不同应用的值时,常见表现是创建订单失败、签名校验失败,或第 9 章回调通知无法被 SaaS 正确验签。

7.5 启动 SaaS 后端

进入 saas-starter,直接启动后端:

cd saas-starter
./env-scripts/start-local-test-backend.sh

脚本会做这些事:

重要

🚀 这一步只启动 SaaS 后端。 SaaS 前端仍然需要用 HBuilderX 单独运行;后端脚本不会替你打开 H5 页面。

动作 说明
构建后端 Jar 输出 backend/target/saas-starter.jar
检查并初始化数据库 读取 application-local.yml 的 PostgreSQL 连接,缺少 t_usert_saas_pay_ordert_vip_subscriptiont_redeem_code 时自动执行 backend/sql/init_pg.sql
启动 SaaS 后端 默认 http://localhost:9220
创建 cloudflared 隧道 把本机 9220 暴露为公网通知地址
写入通知覆盖配置 生成 logs/application-local-tunnel.yml
写入前端公网提示 生成 frontend/.env.development.local,其中公网 VITE_API_BASE_URL 默认保持注释

SaaS 后端本地启动流程

logs/application-local-tunnel.yml 会把 zhcpay.notify-url 覆盖成本次 cloudflared 公网地址。这个地址是第 9 章验证支付通知时使用的准备项;本章只确认文件生成和 SaaS 后端正常启动。

备注

📌 本章看到 cloudflared 地址生成即可,不用急着拿它做支付通知验收。真正验证 web-pay 回调 SaaS 的链路放到第 9 章。

警告

⚠️ 每次重启后端脚本都可能生成新的 SaaS cloudflared 地址。第 9 章如果要用本机 SaaS 接收通知,必须以本次启动生成的 logs/application-local-tunnel.yml 为准。

7.6 启动 SaaS 前端

SaaS 前端是 uni-app H5 项目。uni-app 是 DCloud 推出的跨端前端框架,写法接近 Vue,同一套页面和业务代码可以按需要编译到 H5、微信小程序、App 等不同端。本教程当前主流程只要求跑通 H5,也就是浏览器里的 SaaS 页面。

备注

📌 这里说的 “H5” 可以先理解成普通网页版本。后面部署到线上时,build-prod-frontend.sh 生成的 frontend/dist 就是给 Nginx、对象存储或 CDN 托管的 H5 静态文件。

uni-app 对这个 SaaS 模板的好处主要有:

优势 对本教程有什么用
Vue 风格开发 页面、组件、状态组织都比较接近常见前端开发方式,新手上手成本低
多端能力预留 当前先跑 H5,以后如果要扩展小程序或 App,不用从零重写整套页面
页面配置集中 pages.json 统一管理页面路由、标题和导航栏配置
构建产物清晰 生产构建后输出 frontend/dist,方便接入 CDN 或静态托管
和 HBuilderX 集成好 可以直接“运行到浏览器”,适合本地调试和查看控制台输出

重要

💡 本教程优先推荐用 HBuilderX 启动 SaaS 前端,不是因为命令行不能跑,而是因为 HBuilderX 对 uni-app 的项目识别、运行到浏览器、控制台日志和内置编译链路更完整,新手少踩环境坑。

HBuilderX 是 DCloud 官方 IDE。你可以把它理解成“专门为 uni-app 做了深度集成的编辑器”:它能识别 frontend 里的 uni-app 配置,提供运行、编译、预览、控制台日志等入口。你不需要先理解所有前端构建细节,先把页面跑起来、确认接口能访问即可。

HBuilderX 启动 uni-app H5 并连接本地 API

小技巧

📁 第一次打开项目时,请打开 saas-starter/frontend 这个目录,不要打开整个 web-pay 仓库根目录。HBuilderX 需要从前端项目目录识别 pages.jsonmanifest.jsonpackage.json

推荐用 HBuilderX 启动:

  1. 打开 HBuilderX。

  2. 选择 文件 -> 打开目录,打开 saas-starter/frontend

  3. 选择 运行 -> 运行到浏览器 -> Chrome 或你常用的浏览器。

  4. 以 HBuilderX 控制台输出的地址为准,默认通常是:

http://localhost:5173

小技巧

💡 如果 HBuilderX 提示安装浏览器运行插件、uni-app 编译插件或相关依赖,按提示安装即可。运行成功后,重点看 HBuilderX 控制台输出的本地访问地址,不要只凭记忆猜端口。

如果前端接口报错,检查:

saas-starter/frontend/.env.development
saas-starter/frontend/.env.development.local

重要

🎯 本机浏览器联调时 API 应该指向 http://localhost:9220/api/v1frontend/.env.development.local 里的公网 API 默认保持注释,只有真机或公网环境需要直接访问 cloudflared API 时才取消注释。

7.7 本地页面验收

7.5、7.6 启动完成后,在浏览器打开 SaaS H5,做本章最后一轮肉眼确认。

重要

页面能打开且接口正常,就说明 SaaS 本地链路通过。 本章不验证支付下单和收银台跳转;那部分放到第 9 章统一验收。

建议至少点开这些页面:

页面 在本项目里对应什么 过关信号
我的 H5 默认首页,展示昵称与功能入口 页面不白屏,头像区与菜单能渲染
续费管理 首页功能入口进入 订阅状态卡片能加载,无持续 loading
开通专业版 订阅方案页 套餐列表能显示;此时不要求点支付
设置 通用功能入口进入 静态页与路由跳转正常

再确认两件事:

  • 首次打开时,浏览器网络面板或 logs/backend.local.log 里能看到 POST /api/v1/session/anonymous,说明匿名会话已创建。

  • 后端日志没有数据库连接失败、端口占用或启动异常堆栈。

小技巧

🧪 页面白屏或接口报错时,先对照 7.6 检查 frontend/.env.development 里的 VITE_API_BASE_URL 是否指向 http://localhost:9220,再查 logs/backend.local.log

SaaS 本地 H5 页面验收边界

SaaS 本地 H5:我的与续费管理 SaaS 本地 H5:开通专业版与设置

7.8 停止 SaaS 本地服务

后端和隧道用脚本停止:

cd saas-starter
./env-scripts/stop.sh

如果前端是 HBuilderX 启动的,在 HBuilderX 里停止运行即可。

小技巧

💡 后端配置、数据库连接、Zhcpay 身份或 logs/application-local-tunnel.yml 变化后,重启 SaaS 后端;前端 .env 变化后,重启 HBuilderX 里的 H5 运行任务。

停止 SaaS 本地后端、隧道与前端运行

常用日志:

saas-starter/logs/backend.local.log
saas-starter/logs/backend.local.tunnel.log
saas-starter/logs/application-local-tunnel.yml

警告

⚠️ 如果页面仍然在请求旧地址,先确认 HBuilderX 已停止并重新运行,再清理浏览器缓存或打开无痕窗口复测。

7.9 本章完成标准

重要

本章完成后,只证明 SaaS 自身本地可用。 支付订单、收银台跳转和支付通知不要在这里硬验收,否则会把第 9 章的完整支付链路问题提前混进来。

  • 已执行 SaaS 配置脚本,配置已写入 application-local.ymlapplication.yml、前端 .env 文件。

  • http://localhost:9220/api/health 可访问。

  • http://localhost:5173 或 HBuilderX 输出的 H5 地址能打开 SaaS 前端。

  • SaaS 后端日志没有数据库连接错误。

  • SaaS 配置中 api-base-urlcashier-base-url 已写入第 3 章规划的 web-pay 线上域名。

  • 已理解本章不要求本机 SaaS 与本机收银台/运营平台完成支付闭环。

  • SaaS H5 首次打开可以创建匿名会话。

  • 本章不要求支付订单跳转成功;支付闭环统一放到第 9 章验证。

本地跑通 saas-starter 的完成标准

参见

➡️ 下一步进入第 8 章,把 web-pay 的线上部署方式跑通。第 9 章再回到本机,让 saas-starter 创建订单并完成支付闭环验收。