← 返回首页
强力推荐

授权支付及商城系统

这是站长根据自身需求开发的简易的商城系统,集成支付宝扫码支付、授权密钥生成/验证/设备绑定等完整功能。同时作为小型的在线商店,适用于各类数字商品的授权销售。

体验版
功能不限
¥19.9
7天
  • 体验测试使用
包年版
包年订阅
¥399.0
365天
  • 每年付费,到期前1周提醒
终身版
终身许可
¥1,999.0
永久
  • 永久使用,无源码
源码版
终身许可
¥2,999.0
永久
  • 永久使用,提供源码,可进行二次开发

📖 详情说明

RONGYAN.CC 授权支付与商城系统 — 开发笔记

项目概述

RONGYAN.CC 授权支付与商城系统,集成支付宝扫码支付、授权密钥生成/验证/设备绑定、SMTP 邮件发送、下载令牌、商品套餐、商品详情页等完整功能。同时作为小型的在线商店运营,适用于各类数字商品的授权销售。


技术栈

层级 技术
后端语言 PHP 8.2
数据库 MySQL 8.0.45
Web 服务器 Nginx 1.31
支付 支付宝 alipay.trade.precreate(扫码支付)
邮件 SMTP SSL/TLS(纯 Socket 自实现,无第三方库)
前端 原生 HTML/CSS/JS,无框架
管理后台 SPA 单页应用

功能详解

1. 前台购买页面

首页 /index.php

  • 商品卡片网格展示:封面图、商品名、描述、"¥XX 起"(取最低套餐价/商品价)
  • 点击封面图触发灯箱放大
  • "查看详情"渐变按钮 → 跳转 /product/{slug}.html(SEO 友好 URL)
  • 底部邮箱输入框 + 购买按钮(仅当商品无套餐时使用

商品详情页 /product.php

  • 封面大图 + 图片缩略图列表(点击切换)
  • 图片灯箱:上一张/下一张、键盘方向键、页码计数器
  • 套餐卡片:名称、价格、时长、徽章(热门/推荐)、特性列表(✔ 图标)
  • 点击选中套餐 → 输入邮箱 → "立即购买"跳转支付
  • Markdown 详情区域(切到 Preview 看渲染效果)

2. 支付宝支付

流程: 用户扫码 → 前端轮询 status.php → 异步 notify.php 创建订单 + 发邮件

  • pay.php:支持 plan_id 参数,按套餐显示价格名称;调用 alipay.trade.precreate 获取二维码;检测 UA 判断移动端展示深链;60 秒轮询倒计时
  • notify.php:验证 RSA2 签名(UTF-8/GBK 双兼容),幂等性检查,事务创建订单+授权+下载令牌,发送双邮件(客户+管理员);读取 passback_params 中的 plan_id 传递给 createOrderFromPayment()
  • status.php:查询 payment_records 返回 {paid: true/false}
  • return.php:同步跳转页,显示授权密钥或购买凭证

3. 授权验证(付费内容)

  • verify.php:双模式(license_key 优先,order_no 兼容旧版),首次激活设备绑定,IP 限流(10 次/小时)
  • validate.php:离线签名验证,校验 HMAC-SHA256 签名,检查过期
  • lib/ProductLicense.php:RSA 2048 密钥对生成/签名/验证;使用 substr($payload, -256) 提取签名(修复 RSA 二进制签名含 | 的 bug)

4. 下载系统

  • 购买时自动生成 32 位随机 hex 令牌,7 天有效,最多下载 5 次
  • 套餐专属下载:若套餐指定了 download_id,使用 product_downloads 中的链接;否则使用商品默认 download_url
  • 本地文件通过 PHP readfile() 代理下载(不暴露真实路径)
  • 远程 URL 回退到 302 跳转
  • 管理员可在后台重置令牌 + 发送新链接邮件

5. 邮件系统

  • 纯 Socket 实现 SMTP,支持 SSL (465) 和 TLS (587)
  • LOGIN 认证,Base64 编码
  • Multipart/alternative MIME(纯文本+HTML)
  • 模板:授权密钥邮件 / 购买凭证邮件 / 下载链接邮件 / 过期提醒邮件 / 7 日内到期提醒

6. 商品套餐系统

  • 每个商品可设置多个价格套餐(名称、价格、时长、特性、徽章、排序)
  • 套餐可关联不同的下载文件(download_id
  • 首页展示 "¥XX 起"(取最低套餐价)
  • 详情页展示套餐卡片供用户选择
  • 支付时传递 plan_id → 订单使用套餐价格和时长

7. 下载文件管理

  • 商品级下载文件 CRUD(名称 + URL)
  • 套餐可指定专属下载文件(不指定则使用商品默认)
  • 删除下载文件时自动清空已关联套餐的 download_id
  • 创建/编辑商品时通过 downloads_data JSON 批量保存

8. 商品图片系统

  • 多图上传(GD 生成缩略图),拖拽排序(SortableJS)
  • 第一张自动设为封面(带"封面"徽章)
  • 存储格式:uploads/YYYY/MM/ 目录
  • 前台支持缩略图切换 + 灯箱浏览

9. SEO URL(Slug)

  • productsslug 唯一索引
  • 前台 URL:/product/{slug}.html
  • 管理员可自定义 slug,留空时自动从商品名生成
  • 系统通过 Nginx try_files + PHP 路由 实现(不是 Nginx rewrite),详情见下方"部署说明"

10. 管理后台

12 个功能模块:

页面/功能 说明
数据看板 统计卡片 + 7 日趋势图
商品管理 增删改查,内联表单(非弹窗),套餐编辑下载文件管理,图片上传
订单管理 列表/搜索/筛选,延长/撤销/删除/重置下载
授权管理 列表,启用/禁用/删除
支付设置 支付宝 AppID、RSA2 密钥、沙箱模式
支付记录 列表 + 删除
系统设置 站点标题、Logo、导航栏、Hero、SEO
帐户设置 修改用户名/邮箱/头像/密码
邮件设置 SMTP 配置 + 测试发送
操作日志 查询/按日期清除

11. 定时任务

0 2 * * * php /path/to/cron/expire-licenses.php

执行三项操作:

  • 过期 order(status → expired)
  • 禁用 license(is_valid → 0)
  • 发送 7 日内到期提醒

关键设计决策

决策 说明
RSA 签名(非 HMAC) 防止授权密钥被伪造,即使数据库被拖
域名无关验证 不绑域名,授权通用
失败关闭 授权缺失/过期 → 前端 403,管理员始终可访问
开发/发布分离 开发环境在 key-api/final/ 构建版添加授权检+混淆
Tokenizer 混淆 避免正则替换误匹配
substr($payload, -256) 提取签名 修复 RSA 2048 二进制签名含 \| 导致截断的 bug
licenses.license_key 改为 VARCHAR(500) 适配 RSA 密钥长度
Slug URL 走 PHP 路由 比 Nginx rewrite 简单:try_files $uri /index.php?$query_string + PHP 检测 /product/{slug}.html
inline 商品表单 不弹窗,内容直接嵌在页面中,自然填充右侧面板
套餐嵌入商品表单 plans_data JSON 序列化到隐藏 input,随商品一起提交,无需独立 API
下载文件 CRUD + 套餐引用 可复用,多个套餐可共用同一下载文件

版权

RONGYAN.CC 授权支付与商城系统 https://rongyan.cc mail:me@rongyan.cc


部署说明

1. 数据库

导入 database.sql(需依次执行全部建表/改表语句),MySQL 8.0+。

2. 环境配置

复制 .env.example.env,配置数据库连接、APP_URL、SIGN_SECRET。

3. Nginx 伪静态配置(宝塔面板)

这一步是关键,必须手动修改 Nginx 配置,而不是用宝塔的"伪静态"功能。

宝塔自带的伪静态功能会加在 location ~ [^/]\.php(/|$)之后,而 slug 路由需要先于 PHP 解析生效。具体的做法是:

找到网站设置 → Nginx 配置文件中 #REWRITE-END 注释的位置,在它下面添加以下规则:

location ~ \.html$ {
    try_files $uri /index.php?$query_string;
}

为什么不能使用宝塔的"伪静态"(设置 → 伪静态):

  • 宝塔的伪静态功能生成的规则放在 server 块的靠后位置,在 PHP 解析块之后
  • Slug URL(如 /product/shop_system.html)会先被 PHP 解析块匹配(按 php 文件处理),导致 404
  • 必须通过 #REWRITE-END 标记手动插入,确保 .html 先被 try_files 捕获

验证方式:访问 https://lab.rongyan.cc/product/shop_system.html 不返回 404 即为生效。

4. Nginx 完整配置要点


# 宝塔自动生成的 PHP 解析块(保留不动)
location ~ [^/]\.php(/|$) {
    # ... 宝塔自动内容 ...
}

# 手动添加:在 #REWRITE-END 下插入
location ~ \.html$ {
    try_files $uri /index.php?$query_string;
}

5. 其他

  • 设置 crontab:0 2 * * * php /path/to/cron/expire-licenses.php

开发历史(按时间倒序)

  • 生成加密版专用干净 database.sql:仅保留示例商品 + 系统设置 + 默认管理员,移除支付密钥/SMTP密码/订单等敏感数据
  • 优化商品详情页布局:有套餐时功能特性移至左侧图片下方展示;无套餐时价格和特性在右侧展示
  • 首页移除商品卡片图片,缩短卡片高度
  • 修复套餐下载链接 Bug:updateProduct() 先保存 downloads(取新 ID 映射),再保存 plans(用映射后 download_id)
  • 修复套餐下载选择下拉不刷新:loadDownloads()addDownload()/removeDownload() 后调用 renderPlans() 同步更新
  • 修复独立保存套餐时 download_id 丢失(api.php /plans/save 缺少 download_id 字段)
  • 修复支付返回页下载按钮不显示:return.php 改用 download_tokens 表判断,不再依赖 p.download_url
  • 新增下载文件管理:每个商品可管理多个下载链接,套餐可指定专用下载
  • 新增商品套餐系统:多价格/多时长套餐,套餐卡片选择,支付宝传递 plan_id
  • 商品详情页:图片轮播+灯箱+Markdown 详情
  • 商品编辑改为内联表单(不再弹窗)
  • 新增 Slug URL 系统:产品 SEO 友好 URL /product/{slug}.html
  • 首页改为 "¥XX 起" + "查看详情" + 卡片图片灯箱
  • 增强授权密钥字段为 VARCHAR(500) 以支持 RSA 长度
  • 修复 RSA 二进制签名提取 Bug(strrpos 改为 substr($payload, -256)
  • 修复管理后台弹窗嵌套的 </div> 缺失 Bug
  • 商品图片系统:多图上传、GD 缩略图、SortableJS 拖拽排序
  • 新增 is_licensed 字段区分授权类/非授权类商品
  • 新增下载令牌系统
  • 清理调试日志,改用 error_log 轻量审计
  • 集成支付宝扫码支付
  • 初始搭建:PHP + MySQL + 管理后台 SPA

后续开发功能展望

  • 有可能增加新的支付通道,如腾讯支付等其它热门支付渠道