diff --git a/.github-upload-rules.md b/.github-upload-rules.md
new file mode 100644
index 00000000..fc927623
--- /dev/null
+++ b/.github-upload-rules.md
@@ -0,0 +1,389 @@
+# GitHub 上传规则
+
+## 仓库信息
+
+**仓库地址**: https://github.com/fnvtk/Mycontent
+**分支**: soul-content
+**完整地址**: https://github.com/fnvtk/Mycontent/tree/soul-content
+
+---
+
+## 快速上传命令
+
+### 一键上传(推荐)
+```bash
+cd "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验"
+git add -A
+git commit -m "更新内容"
+git push origin soul-content
+```
+
+### 详细上传步骤
+```bash
+# 1. 进入项目目录
+cd "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验"
+
+# 2. 查看状态
+git status
+
+# 3. 添加所有更改
+git add -A
+
+# 4. 提交更改(修改提交信息)
+git commit -m "feat: 更新说明"
+
+# 5. 推送到GitHub
+git push origin soul-content
+```
+
+---
+
+## 常用提交信息模板
+
+### 功能更新
+```bash
+git commit -m "feat: 添加新功能
+
+- 功能1
+- 功能2
+- 功能3"
+```
+
+### Bug修复
+```bash
+git commit -m "fix: 修复问题
+
+- 修复问题1
+- 修复问题2"
+```
+
+### 界面优化
+```bash
+git commit -m "style: 界面优化
+
+- 优化首页
+- 优化匹配页面
+- 统一配色"
+```
+
+### 文档更新
+```bash
+git commit -m "docs: 更新文档
+
+- 更新README
+- 添加使用说明"
+```
+
+### 性能优化
+```bash
+git commit -m "perf: 性能优化
+
+- 优化加载速度
+- 优化API响应"
+```
+
+---
+
+## Talk功能上传规则
+
+### Talk内容目录
+```
+book/
+├── 附录/
+│ └── 附录1|Soul派对房精选对话.md
+└── talk/ (如果有独立的talk目录)
+```
+
+### 上传Talk内容
+```bash
+# 1. 添加talk相关文件
+cd "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验"
+git add book/附录/附录1|Soul派对房精选对话.md
+git add book/talk/* # 如果有talk目录
+
+# 2. 提交
+git commit -m "feat: 更新Talk内容
+
+- 添加新的对话记录
+- 更新精选对话"
+
+# 3. 推送
+git push origin soul-content
+```
+
+---
+
+## 分支管理
+
+### 查看当前分支
+```bash
+git branch
+```
+
+### 切换分支
+```bash
+git checkout soul-content
+```
+
+### 创建新分支
+```bash
+git checkout -b new-branch-name
+```
+
+---
+
+## 同步最新代码
+
+### 拉取最新代码
+```bash
+cd "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验"
+git pull origin soul-content
+```
+
+### 查看远程仓库
+```bash
+git remote -v
+```
+
+---
+
+## 回滚操作
+
+### 撤销未提交的更改
+```bash
+git checkout -- <文件名>
+```
+
+### 撤销已提交但未推送的提交
+```bash
+git reset --soft HEAD^
+```
+
+### 查看提交历史
+```bash
+git log --oneline
+```
+
+---
+
+## 忽略文件
+
+### .gitignore 常用配置
+```
+# 依赖
+node_modules/
+.pnp
+.pnp.js
+
+# 测试
+coverage/
+
+# 生产构建
+.next/
+out/
+build/
+dist/
+
+# 环境变量
+.env
+.env.local
+.env.production.local
+.env.development.local
+
+# 调试日志
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# 操作系统
+.DS_Store
+Thumbs.db
+
+# IDE
+.vscode/
+.idea/
+*.swp
+*.swo
+
+# 小程序
+miniprogram/node_modules/
+miniprogram/.tea/
+
+# 临时文件
+*.log
+*.tmp
+```
+
+---
+
+## 紧急情况处理
+
+### 推送失败(冲突)
+```bash
+# 1. 拉取最新代码
+git pull origin soul-content
+
+# 2. 解决冲突后
+git add -A
+git commit -m "fix: 解决冲突"
+git push origin soul-content
+```
+
+### 强制推送(慎用)
+```bash
+git push -f origin soul-content
+```
+
+---
+
+## 标签管理
+
+### 创建版本标签
+```bash
+git tag -a v1.3.1 -m "完美版本:首页对齐H5,64章精准数据"
+git push origin v1.3.1
+```
+
+### 查看所有标签
+```bash
+git tag
+```
+
+---
+
+## 自动化脚本
+
+### 快速上传脚本 (quick-push.sh)
+```bash
+#!/bin/bash
+
+cd "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验"
+
+echo "🚀 开始上传到GitHub..."
+
+# 添加所有更改
+git add -A
+
+# 获取提交信息
+echo "请输入提交信息(留空则使用默认信息):"
+read commit_msg
+
+if [ -z "$commit_msg" ]; then
+ commit_msg="update: 更新内容 $(date '+%Y-%m-%d %H:%M:%S')"
+fi
+
+# 提交
+git commit -m "$commit_msg"
+
+# 推送
+git push origin soul-content
+
+echo "✅ 上传完成!"
+echo "📝 提交信息:$commit_msg"
+echo "🔗 查看:https://github.com/fnvtk/Mycontent/tree/soul-content"
+```
+
+### 使用方法
+```bash
+# 1. 赋予执行权限
+chmod +x quick-push.sh
+
+# 2. 执行脚本
+./quick-push.sh
+```
+
+---
+
+## 常见问题
+
+### Q: 推送时要求输入用户名密码?
+**A**: 使用GitHub个人访问令牌(Personal Access Token)
+```bash
+# 设置远程仓库URL(使用token)
+git remote set-url origin https://@github.com/fnvtk/Mycontent.git
+```
+
+### Q: 文件太大无法推送?
+**A**: 使用Git LFS
+```bash
+git lfs install
+git lfs track "*.大文件"
+git add .gitattributes
+```
+
+### Q: 如何删除远程分支?
+**A**:
+```bash
+git push origin --delete branch-name
+```
+
+---
+
+## 项目结构
+
+```
+一场soul的创业实验/
+├── app/ # Next.js应用
+├── book/ # 书籍内容(64章)
+│ ├── 序言|...
+│ ├── 第一篇|真实的人/
+│ ├── 第二篇|真实的行业/
+│ ├── 第三篇|真实的错误/
+│ ├── 第四篇|真实的赚钱/
+│ ├── 第五篇|真实的社会/
+│ ├── 尾声|...
+│ └── 附录/
+│ └── 附录1|Soul派对房精选对话.md ← Talk内容
+├── miniprogram/ # 微信小程序
+├── components/ # 组件
+├── lib/ # 工具库
+├── public/ # 静态资源
+│ └── book-chapters.json # 64章数据
+├── scripts/ # 脚本
+│ └── sync-book-content.js
+├── .gitignore # Git忽略配置
+├── package.json # 项目配置
+└── README.md # 项目说明
+```
+
+---
+
+## 下次上传流程
+
+### 简单三步:
+```bash
+# 1. 进入目录
+cd "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验"
+
+# 2. 添加并提交
+git add -A && git commit -m "更新内容"
+
+# 3. 推送
+git push origin soul-content
+```
+
+### 或使用别名(更快)
+```bash
+# 添加到 ~/.zshrc 或 ~/.bashrc
+alias soul-push='cd "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验" && git add -A && git commit -m "update: 更新内容" && git push origin soul-content'
+
+# 使用
+soul-push
+```
+
+---
+
+## 重要提示
+
+1. ⚠️ **推送前检查**:确保没有敏感信息(密钥、密码等)
+2. 📝 **提交信息**:写清楚每次更改的内容
+3. 🔄 **定期备份**:重要节点创建标签
+4. 🚫 **不要推送**:node_modules、.env等文件
+5. ✅ **推送后验证**:访问GitHub确认更新成功
+
+---
+
+**仓库地址**: https://github.com/fnvtk/Mycontent/tree/soul-content
+
+**创建时间**: 2026年1月14日
+**最后更新**: v1.3.1
diff --git a/README.md b/README.md
index abb72cd5..ae009582 100644
--- a/README.md
+++ b/README.md
@@ -1,30 +1,16 @@
-# AI phone branding
+# 一场SOUL的创业实验
-*Automatically synced with your [v0.app](https://v0.app) deployments*
+## 项目简介
+这是一个基于 Soul 派对房真实商业故事开发的知识付费与分销系统。
-[](https://vercel.com/fnvtks-projects/v0--ap)
-[](https://v0.app/chat/tPF15XbLAKD)
+### 核心功能
+- 📚 **电子书阅读**: 每日更新的真实商业案例。
+- 🤝 **找伙伴**: 匹配志同道合的创业合伙人。
+- 💰 **分销系统**: 90% 高额佣金,推广赚收益。
+- 👤 **个人中心**: 账号绑定、收益提现、阅读足迹。
-## Overview
+## 技术开发
+本项目由 **卡若** 开发,核心逻辑与私域系统由 **存客宝** 提供技术支持。
-This repository will stay in sync with your deployed chats on [v0.app](https://v0.app).
-Any changes you make to your deployed app will be automatically pushed to this repository from [v0.app](https://v0.app).
-
-## Deployment
-
-Your project is live at:
-
-**[https://vercel.com/fnvtks-projects/v0--ap](https://vercel.com/fnvtks-projects/v0--ap)**
-
-## Build your app
-
-Continue building your app on:
-
-**[https://v0.app/chat/tPF15XbLAKD](https://v0.app/chat/tPF15XbLAKD)**
-
-## How It Works
-
-1. Create and modify your project using [v0.app](https://v0.app)
-2. Deploy your chats from the v0 interface
-3. Changes are automatically pushed to this repository
-4. Vercel deploys the latest version from this repository
+---
+*版权所有 © 2026 卡若 & 存客宝*
diff --git a/addons/Universal_Payment_Module copy/.cursorrules b/addons/Universal_Payment_Module copy/.cursorrules
new file mode 100644
index 00000000..e9610e90
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/.cursorrules
@@ -0,0 +1,68 @@
+# Universal Payment Module - Cursor 规则
+# 将此文件放在使用支付模块的项目根目录
+
+## 角色设定
+你是一位精通全球支付架构的资深全栈工程师,专注于支付网关集成、安全合规和高可用设计。
+
+当用户提及"支付模块"、"支付功能"、"接入支付"时,请参考 `Universal_Payment_Module` 目录中的设计文档。
+
+## 核心原则
+
+### 1. 配置驱动
+- 所有支付密钥通过环境变量配置,绝不硬编码
+- 使用 `.env` 文件管理配置
+- 支持多环境切换 (development/staging/production)
+
+### 2. 工厂模式
+- 使用 `PaymentFactory` 统一管理支付网关
+- 每个网关实现统一的 `AbstractGateway` 接口
+- 支持: alipay/wechat/paypal/stripe/usdt
+
+### 3. 安全优先
+- 所有回调必须验证签名
+- 必须验证支付金额与订单金额匹配
+- 使用 HTTPS,敏感数据脱敏
+
+### 4. 幂等性
+- 支付回调必须支持重复调用
+- 使用分布式锁防止并发问题
+
+## API 接口
+```
+POST /api/payment/create_order - 创建订单
+POST /api/payment/checkout - 发起支付
+GET /api/payment/status/{sn} - 查询状态
+POST /api/payment/notify/{gw} - 回调通知
+```
+
+## 统一响应格式
+```json
+{
+ "code": 200,
+ "message": "success",
+ "data": { ... }
+}
+```
+
+## 数据库
+- orders - 订单表
+- pay_trades - 交易流水表
+- 金额单位: 数据库用分,API用元
+
+## 卡若支付配置
+- 微信商户号: 1318592501
+- 支付宝PID: 2088511801157159
+- 详细配置见 `4_卡若配置/.env.example`
+
+## 禁止事项
+❌ 密钥硬编码
+❌ 跳过签名验证
+❌ 信任前端金额
+❌ 回调不做幂等
+❌ 使用 HTTP
+
+## 参考文档
+- API定义: `1_核心设计_通用协议/API接口定义.md`
+- 数据模型: `1_核心设计_通用协议/业务逻辑与模型.md`
+- 安全规范: `1_核心设计_通用协议/安全与合规.md`
+- AI指令: `2_智能对接_AI指令/通用集成指令.md`
diff --git a/addons/Universal_Payment_Module copy/1_核心设计_通用协议/API接口定义.md b/addons/Universal_Payment_Module copy/1_核心设计_通用协议/API接口定义.md
new file mode 100644
index 00000000..9487549d
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/1_核心设计_通用协议/API接口定义.md
@@ -0,0 +1,382 @@
+# 通用支付模块 API 接口定义 (Universal Payment API) v4.0
+
+> 无论后端使用何种语言(Python/Node/Go/Java/PHP),请严格实现以下 RESTful 接口
+
+## 🎯 设计原则
+
+1. **RESTful 风格**: 资源命名统一,动词语义清晰
+2. **统一响应格式**: 所有接口返回 `{code, message, data}` 结构
+3. **幂等性**: 重复请求不产生副作用
+4. **安全性**: 敏感操作需签名验证
+
+---
+
+## 📦 统一响应格式
+
+### 成功响应
+```json
+{
+ "code": 200,
+ "message": "success",
+ "data": { ... }
+}
+```
+
+### 错误响应
+```json
+{
+ "code": 400,
+ "message": "参数错误:order_sn 不能为空",
+ "data": null
+}
+```
+
+### 常用错误码
+| Code | 含义 |
+|:---|:---|
+| 200 | 成功 |
+| 400 | 请求参数错误 |
+| 401 | 未授权/登录过期 |
+| 403 | 无权限 |
+| 404 | 资源不存在 |
+| 409 | 状态冲突 (如重复支付) |
+| 500 | 服务器内部错误 |
+
+---
+
+## 1. 核心交易接口 (Core Transaction)
+
+### 1.1 创建订单
+业务系统调用,创建一个待支付订单。
+
+```http
+POST /api/payment/create_order
+Content-Type: application/json
+Authorization: Bearer {token}
+```
+
+**Request Body**:
+```json
+{
+ "user_id": "u1001", // [必填] 用户ID
+ "title": "VIP会员月卡", // [必填] 订单标题 (≤30字符)
+ "amount": 99.00, // [必填] 金额 (单位: 元)
+ "currency": "CNY", // [可选] 币种,默认 CNY
+ "product_id": "vip_monthly", // [可选] 商品ID
+ "product_type": "membership", // [可选] 商品类型
+ "extra_params": { // [可选] 扩展参数 (会透传到回调)
+ "coupon_id": "C001",
+ "referrer": "user_123"
+ }
+}
+```
+
+**Response**:
+```json
+{
+ "code": 200,
+ "message": "success",
+ "data": {
+ "order_sn": "202401170001", // 系统生成的订单号
+ "status": "created", // 订单状态
+ "amount": 99.00,
+ "expire_at": "2024-01-17T11:30:00Z" // 订单过期时间
+ }
+}
+```
+
+---
+
+### 1.2 发起支付 (收银台)
+用户选择支付方式后,获取支付参数。
+
+```http
+POST /api/payment/checkout
+Content-Type: application/json
+Authorization: Bearer {token}
+```
+
+**Request Body**:
+```json
+{
+ "order_sn": "202401170001", // [必填] 订单号
+ "gateway": "wechat_jsapi", // [必填] 支付网关 (见下方枚举)
+ "return_url": "https://...", // [可选] 支付成功后跳转地址
+ "openid": "oXxx...", // [条件] 微信JSAPI必填
+ "coin_amount": 0 // [可选] 使用虚拟币抵扣金额
+}
+```
+
+**Gateway 支付网关枚举**:
+| Gateway | 说明 | 返回类型 |
+|:---|:---|:---|
+| `alipay_web` | 支付宝PC网页 | url (跳转) |
+| `alipay_wap` | 支付宝H5 | url (跳转) |
+| `alipay_qr` | 支付宝扫码 | qrcode |
+| `wechat_native` | 微信扫码 | qrcode |
+| `wechat_jsapi` | 微信公众号/小程序 | json (SDK参数) |
+| `wechat_h5` | 微信H5 | url (跳转) |
+| `wechat_app` | 微信APP | json (SDK参数) |
+| `paypal` | PayPal | url (跳转) |
+| `stripe` | Stripe | url (Checkout Session) |
+| `usdt` | USDT-TRC20 | address (钱包地址) |
+| `coin` | 纯虚拟币支付 | direct (直接完成) |
+
+**Response**:
+```json
+{
+ "code": 200,
+ "message": "success",
+ "data": {
+ "trade_sn": "T20240117100001", // 交易流水号
+ "type": "qrcode", // 响应类型: url/qrcode/json/address/direct
+ "payload": "weixin://wxpay/...",// 支付数据 (根据type不同)
+ "expiration": 1800, // 过期时间 (秒)
+ "amount": 99.00, // 实际支付金额 (扣除抵扣后)
+ "coin_deducted": 0 // 虚拟币抵扣金额
+ }
+}
+```
+
+**不同 type 的 payload 格式**:
+
+```javascript
+// type: "url" - 跳转链接
+payload: "https://openapi.alipay.com/gateway.do?..."
+
+// type: "qrcode" - 二维码内容
+payload: "weixin://wxpay/bizpayurl?pr=xxx"
+
+// type: "json" - SDK调起参数 (微信JSAPI)
+payload: {
+ "appId": "wx...",
+ "timeStamp": "1705470600",
+ "nonceStr": "xxx",
+ "package": "prepay_id=wx...",
+ "signType": "RSA",
+ "paySign": "xxx"
+}
+
+// type: "address" - 加密货币地址
+payload: {
+ "address": "TXxx...",
+ "amount_usdt": 13.88,
+ "memo": "202401170001"
+}
+
+// type: "direct" - 直接完成 (纯虚拟币支付)
+payload: { "status": "paid" }
+```
+
+---
+
+### 1.3 查询订单状态
+前端轮询使用,判断支付是否完成。
+
+```http
+GET /api/payment/status/{order_sn}
+Authorization: Bearer {token}
+```
+
+**Response**:
+```json
+{
+ "code": 200,
+ "message": "success",
+ "data": {
+ "order_sn": "202401170001",
+ "status": "paid", // created/paying/paid/closed/refunded
+ "paid_amount": 99.00,
+ "paid_at": "2024-01-17T10:05:00Z",
+ "payment_method": "wechat_jsapi",
+ "trade_sn": "T20240117100001"
+ }
+}
+```
+
+**订单状态机**:
+```
+created → paying → paid → (refunded)
+ ↓ ↓
+ closed closed
+```
+
+---
+
+### 1.4 关闭订单
+主动关闭未支付的订单。
+
+```http
+POST /api/payment/close/{order_sn}
+Authorization: Bearer {token}
+```
+
+**Response**:
+```json
+{
+ "code": 200,
+ "message": "success",
+ "data": {
+ "order_sn": "202401170001",
+ "status": "closed",
+ "closed_at": "2024-01-17T10:10:00Z"
+ }
+}
+```
+
+---
+
+## 2. 回调通知接口 (Webhook)
+
+### 2.1 统一回调入口
+接收第三方支付平台的异步通知。
+
+```http
+POST /api/payment/notify/{gateway}
+```
+
+**Path Params**:
+- `gateway`: `alipay` / `wechat` / `paypal` / `stripe` / `nowpayments`
+
+**处理逻辑**:
+1. 根据 gateway 加载对应驱动
+2. 验签 (Verify Signature)
+3. 幂等性检查 (防重复处理)
+4. 更新订单状态
+5. 触发业务回调 (发货/开通权限等)
+6. 返回平台所需响应
+
+**返回格式**:
+```
+# 支付宝
+success
+
+# 微信
+
+
+# Stripe
+HTTP 200 OK
+
+# PayPal
+HTTP 200 OK
+```
+
+---
+
+### 2.2 同步返回 (Return)
+用户支付完成后的页面跳转。
+
+```http
+GET /api/payment/return/{gateway}
+```
+
+**Query Params**: 各平台不同,由平台自动附加
+
+**处理逻辑**:
+1. 解析回传参数
+2. 验签
+3. 重定向到成功页面
+
+---
+
+## 3. 辅助接口
+
+### 3.1 获取可用支付方式
+```http
+GET /api/payment/methods
+```
+
+**Response**:
+```json
+{
+ "code": 200,
+ "data": {
+ "methods": [
+ {
+ "gateway": "wechat_jsapi",
+ "name": "微信支付",
+ "icon": "/icons/wechat.png",
+ "enabled": true,
+ "available": true // 当前环境是否可用 (如微信内)
+ },
+ {
+ "gateway": "alipay_wap",
+ "name": "支付宝",
+ "icon": "/icons/alipay.png",
+ "enabled": true,
+ "available": true
+ }
+ ]
+ }
+}
+```
+
+### 3.2 获取汇率
+```http
+GET /api/payment/exchange_rate?from=CNY&to=USD
+```
+
+**Response**:
+```json
+{
+ "code": 200,
+ "data": {
+ "from": "CNY",
+ "to": "USD",
+ "rate": 0.139,
+ "updated_at": "2024-01-17T00:00:00Z"
+ }
+}
+```
+
+---
+
+## 4. 管理接口 (Admin)
+
+### 4.1 订单列表
+```http
+GET /api/admin/payment/orders?page=1&limit=20&status=paid
+Authorization: Bearer {admin_token}
+```
+
+### 4.2 交易流水列表
+```http
+GET /api/admin/payment/trades?page=1&limit=20
+Authorization: Bearer {admin_token}
+```
+
+### 4.3 发起退款
+```http
+POST /api/admin/payment/refund
+Authorization: Bearer {admin_token}
+Content-Type: application/json
+
+{
+ "trade_sn": "T20240117100001",
+ "amount": 99.00,
+ "reason": "用户申请退款"
+}
+```
+
+---
+
+## 5. 接口签名规范 (可选)
+
+对于安全要求高的场景,可启用接口签名:
+
+```javascript
+// 请求头
+X-Sign: sha256(timestamp + nonce + body + secret)
+X-Timestamp: 1705470600
+X-Nonce: abc123
+```
+
+---
+
+## 📌 注意事项
+
+1. **金额单位**: 所有金额均以**元**为单位,小数点后2位
+2. **时间格式**: ISO 8601 格式 `YYYY-MM-DDTHH:mm:ssZ`
+3. **字符编码**: UTF-8
+4. **HTTPS**: 生产环境必须使用 HTTPS
+5. **幂等性**: 相同订单号重复请求返回相同结果
diff --git a/addons/Universal_Payment_Module copy/1_核心设计_通用协议/业务逻辑与模型.md b/addons/Universal_Payment_Module copy/1_核心设计_通用协议/业务逻辑与模型.md
new file mode 100644
index 00000000..b93a2250
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/1_核心设计_通用协议/业务逻辑与模型.md
@@ -0,0 +1,396 @@
+# 业务逻辑与数据模型 (Business Logic & Data Model) v4.0
+
+> 定义支付系统的核心数据结构和业务流程
+
+## 📊 数据库表结构
+
+### 1. 订单表 (orders)
+
+存储业务订单信息,与支付解耦。
+
+```sql
+CREATE TABLE `orders` (
+ `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `sn` VARCHAR(32) NOT NULL COMMENT '订单号 (业务唯一)',
+ `user_id` VARCHAR(64) NOT NULL COMMENT '用户ID',
+ `title` VARCHAR(128) NOT NULL COMMENT '订单标题',
+ `price_amount` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '订单原价 (分)',
+ `pay_amount` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '应付金额 (分)',
+ `currency` VARCHAR(8) NOT NULL DEFAULT 'CNY' COMMENT '货币类型',
+ `status` VARCHAR(20) NOT NULL DEFAULT 'created' COMMENT '状态: created/paying/paid/closed/refunded',
+ `product_id` VARCHAR(64) DEFAULT NULL COMMENT '商品ID',
+ `product_type` VARCHAR(32) DEFAULT NULL COMMENT '商品类型',
+ `extra_data` JSON DEFAULT NULL COMMENT '扩展数据',
+ `paid_at` DATETIME DEFAULT NULL COMMENT '支付时间',
+ `closed_at` DATETIME DEFAULT NULL COMMENT '关闭时间',
+ `expired_at` DATETIME DEFAULT NULL COMMENT '过期时间',
+ `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_sn` (`sn`),
+ KEY `idx_user_id` (`user_id`),
+ KEY `idx_status` (`status`),
+ KEY `idx_created_at` (`created_at`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
+```
+
+### 2. 交易流水表 (pay_trades)
+
+记录每一次支付尝试,一个订单可能有多次交易。
+
+```sql
+CREATE TABLE `pay_trades` (
+ `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `trade_sn` VARCHAR(32) NOT NULL COMMENT '交易流水号 (系统生成)',
+ `order_sn` VARCHAR(32) NOT NULL COMMENT '关联订单号',
+ `user_id` VARCHAR(64) NOT NULL COMMENT '用户ID',
+ `title` VARCHAR(128) NOT NULL COMMENT '交易标题',
+ `amount` BIGINT UNSIGNED NOT NULL COMMENT '交易金额 (分)',
+ `cash_amount` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '现金支付金额 (分)',
+ `coin_amount` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '虚拟币抵扣金额',
+ `currency` VARCHAR(8) NOT NULL DEFAULT 'CNY' COMMENT '货币类型',
+ `platform` VARCHAR(32) NOT NULL COMMENT '支付平台: alipay/wechat/paypal/stripe/usdt/coin',
+ `platform_type` VARCHAR(32) DEFAULT NULL COMMENT '平台子类型: web/wap/jsapi/native/h5/app',
+ `platform_sn` VARCHAR(64) DEFAULT NULL COMMENT '平台交易号',
+ `platform_created_params` JSON DEFAULT NULL COMMENT '发送给平台的参数',
+ `platform_created_result` JSON DEFAULT NULL COMMENT '平台返回的结果',
+ `status` VARCHAR(20) NOT NULL DEFAULT 'paying' COMMENT '状态: paying/paid/closed/refunded',
+ `type` VARCHAR(20) NOT NULL DEFAULT 'purchase' COMMENT '类型: purchase(购买)/recharge(充值)',
+ `pay_time` DATETIME DEFAULT NULL COMMENT '支付时间',
+ `notify_data` JSON DEFAULT NULL COMMENT '回调原始数据',
+ `seller_id` VARCHAR(64) DEFAULT NULL COMMENT '卖家ID (多商户场景)',
+ `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_trade_sn` (`trade_sn`),
+ KEY `idx_order_sn` (`order_sn`),
+ KEY `idx_platform_sn` (`platform_sn`),
+ KEY `idx_user_id` (`user_id`),
+ KEY `idx_status` (`status`),
+ KEY `idx_created_at` (`created_at`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='交易流水表';
+```
+
+### 3. 资金流水表 (cashflows)
+
+记录账户资金变动(可选,用于虚拟币/钱包场景)。
+
+```sql
+CREATE TABLE `cashflows` (
+ `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `sn` VARCHAR(32) NOT NULL COMMENT '流水号',
+ `user_id` VARCHAR(64) NOT NULL COMMENT '用户ID',
+ `type` VARCHAR(20) NOT NULL COMMENT '类型: inflow(入账)/outflow(出账)',
+ `action` VARCHAR(32) NOT NULL COMMENT '动作: recharge/purchase/refund/transfer',
+ `amount` BIGINT NOT NULL COMMENT '金额 (分,正数入账负数出账)',
+ `currency` VARCHAR(8) NOT NULL DEFAULT 'CNY',
+ `balance_before` BIGINT NOT NULL DEFAULT 0 COMMENT '变动前余额',
+ `balance_after` BIGINT NOT NULL DEFAULT 0 COMMENT '变动后余额',
+ `trade_sn` VARCHAR(32) DEFAULT NULL COMMENT '关联交易流水号',
+ `order_sn` VARCHAR(32) DEFAULT NULL COMMENT '关联订单号',
+ `remark` VARCHAR(256) DEFAULT NULL COMMENT '备注',
+ `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_sn` (`sn`),
+ KEY `idx_user_id` (`user_id`),
+ KEY `idx_trade_sn` (`trade_sn`),
+ KEY `idx_created_at` (`created_at`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='资金流水表';
+```
+
+### 4. 退款记录表 (refunds)
+
+```sql
+CREATE TABLE `refunds` (
+ `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `refund_sn` VARCHAR(32) NOT NULL COMMENT '退款单号',
+ `trade_sn` VARCHAR(32) NOT NULL COMMENT '原交易流水号',
+ `order_sn` VARCHAR(32) NOT NULL COMMENT '原订单号',
+ `amount` BIGINT UNSIGNED NOT NULL COMMENT '退款金额 (分)',
+ `reason` VARCHAR(256) DEFAULT NULL COMMENT '退款原因',
+ `status` VARCHAR(20) NOT NULL DEFAULT 'pending' COMMENT '状态: pending/processing/success/failed',
+ `platform_refund_sn` VARCHAR(64) DEFAULT NULL COMMENT '平台退款单号',
+ `refunded_at` DATETIME DEFAULT NULL COMMENT '退款完成时间',
+ `operator_id` VARCHAR(64) DEFAULT NULL COMMENT '操作人ID',
+ `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_refund_sn` (`refund_sn`),
+ KEY `idx_trade_sn` (`trade_sn`),
+ KEY `idx_order_sn` (`order_sn`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='退款记录表';
+```
+
+---
+
+## 🔄 状态机定义
+
+### 订单状态 (Order Status)
+
+```
+┌─────────────────────────────────────────────────┐
+│ created │
+│ │ │
+│ ┌───────────┼───────────┐ │
+│ ▼ │ ▼ │
+│ paying ────────┼───────► closed │
+│ │ │ │
+│ ▼ │ │
+│ paid ─────────┼───────► refunded │
+│ │ │
+└─────────────────────────────────────────────────┘
+
+状态说明:
+- created: 订单已创建,等待支付
+- paying: 支付中 (已发起支付请求)
+- paid: 已支付
+- closed: 已关闭 (超时/主动取消)
+- refunded: 已退款
+```
+
+### 交易状态 (Trade Status)
+
+```
+paying → paid
+ ↓ ↓
+closed refunded
+
+状态说明:
+- paying: 支付中
+- paid: 支付成功
+- closed: 交易关闭
+- refunded: 已退款
+```
+
+---
+
+## 🔢 编号规则
+
+### 订单号 (order_sn)
+```
+格式: YYYYMMDD + 6位随机数
+示例: 202401170001
+
+生成规则:
+1. 日期前缀保证每日唯一空间
+2. 随机数使用分布式ID生成器
+3. 支持前缀自定义 (如区分业务线)
+```
+
+### 交易流水号 (trade_sn)
+```
+格式: T + YYYYMMDD + HHmmss + 5位随机数
+示例: T20240117100530123456
+
+生成规则:
+1. 前缀 T 标识交易类型
+2. 精确到秒的时间戳
+3. 5位随机数防碰撞
+```
+
+---
+
+## 📋 核心业务流程
+
+### 1. 标准支付流程
+
+```sequence
+用户 -> 业务系统: 1. 提交订单
+业务系统 -> 支付模块: 2. 创建订单 (create_order)
+支付模块 -> 业务系统: 3. 返回 order_sn
+
+用户 -> 支付模块: 4. 选择支付方式并支付 (checkout)
+支付模块 -> 支付平台: 5. 创建平台交易
+支付平台 -> 支付模块: 6. 返回支付参数
+支付模块 -> 用户: 7. 返回支付数据 (二维码/跳转链接)
+
+用户 -> 支付平台: 8. 完成支付
+支付平台 -> 支付模块: 9. 异步回调 (notify)
+支付模块 -> 支付模块: 10. 验签 + 更新状态
+支付模块 -> 业务系统: 11. 触发业务回调 (发货/开通)
+```
+
+### 2. 支付回调处理流程
+
+```python
+def handle_notify(gateway, data):
+ # 1. 加载对应的支付网关驱动
+ driver = PaymentFactory.create(gateway)
+
+ # 2. 验证签名
+ if not driver.verify_sign(data):
+ raise SignatureError("签名验证失败")
+
+ # 3. 解析回调数据
+ parsed = driver.parse_notify(data)
+ trade_sn = parsed['trade_sn']
+
+ # 4. 幂等性检查
+ trade = Trade.get_by_sn(trade_sn)
+ if trade.status == 'paid':
+ return driver.success_response() # 已处理过,直接返回成功
+
+ # 5. 金额校验
+ if parsed['amount'] != trade.cash_amount:
+ raise AmountMismatchError("金额不匹配")
+
+ # 6. 更新交易状态
+ trade.update({
+ 'status': 'paid',
+ 'platform_sn': parsed['platform_sn'],
+ 'pay_time': parsed['pay_time'],
+ 'notify_data': data
+ })
+
+ # 7. 更新订单状态
+ order = Order.get_by_sn(trade.order_sn)
+ order.update({'status': 'paid', 'paid_at': now()})
+
+ # 8. 触发业务回调
+ dispatch_event('order.paid', order)
+
+ # 9. 返回成功响应
+ return driver.success_response()
+```
+
+### 3. 退款流程
+
+```python
+def apply_refund(trade_sn, amount, reason):
+ trade = Trade.get_by_sn(trade_sn)
+
+ # 1. 状态检查
+ if trade.status != 'paid':
+ raise InvalidStatusError("只有已支付的交易可以退款")
+
+ # 2. 创建退款记录
+ refund = Refund.create({
+ 'refund_sn': generate_refund_sn(),
+ 'trade_sn': trade_sn,
+ 'amount': amount,
+ 'reason': reason,
+ 'status': 'pending'
+ })
+
+ # 3. 调用平台退款接口
+ driver = PaymentFactory.create(trade.platform)
+ result = driver.refund({
+ 'trade_sn': trade_sn,
+ 'refund_sn': refund.refund_sn,
+ 'amount': amount
+ })
+
+ # 4. 更新状态
+ if result.success:
+ refund.update({'status': 'success', 'refunded_at': now()})
+ trade.update({'status': 'refunded'})
+ else:
+ refund.update({'status': 'failed'})
+
+ return refund
+```
+
+---
+
+## 🏭 工厂模式设计
+
+```python
+class PaymentFactory:
+ """支付网关工厂"""
+
+ _drivers = {
+ 'alipay': AlipayGateway,
+ 'wechat': WechatGateway,
+ 'paypal': PayPalGateway,
+ 'stripe': StripeGateway,
+ 'usdt': USDTGateway,
+ 'coin': CoinGateway,
+ }
+
+ @classmethod
+ def create(cls, gateway: str) -> AbstractGateway:
+ gateway_name = gateway.split('_')[0] # wechat_jsapi -> wechat
+
+ if gateway_name not in cls._drivers:
+ raise ValueError(f"不支持的支付网关: {gateway}")
+
+ driver_class = cls._drivers[gateway_name]
+ return driver_class(config=get_payment_config(gateway_name))
+```
+
+```python
+class AbstractGateway(ABC):
+ """支付网关抽象基类"""
+
+ @abstractmethod
+ def create_trade(self, data: dict) -> dict:
+ """创建交易"""
+ pass
+
+ @abstractmethod
+ def verify_sign(self, data: dict) -> bool:
+ """验证签名"""
+ pass
+
+ @abstractmethod
+ def parse_notify(self, data: dict) -> dict:
+ """解析回调数据"""
+ pass
+
+ @abstractmethod
+ def refund(self, data: dict) -> RefundResult:
+ """发起退款"""
+ pass
+
+ @abstractmethod
+ def query_trade(self, trade_sn: str) -> dict:
+ """查询交易"""
+ pass
+
+ @abstractmethod
+ def close_trade(self, trade_sn: str) -> bool:
+ """关闭交易"""
+ pass
+
+ def success_response(self) -> str:
+ """回调成功响应"""
+ return "success"
+```
+
+---
+
+## 💰 金额处理规范
+
+### 1. 存储规则
+- 数据库统一使用**分**为单位 (BIGINT)
+- 避免浮点数精度问题
+
+### 2. 接口规则
+- API 输入输出统一使用**元**为单位
+- 内部转换: `分 = 元 × 100`
+
+### 3. 转换示例
+```python
+# 元转分 (API输入 -> 数据库)
+def yuan_to_fen(yuan: float) -> int:
+ return int(round(yuan * 100))
+
+# 分转元 (数据库 -> API输出)
+def fen_to_yuan(fen: int) -> float:
+ return round(fen / 100, 2)
+```
+
+---
+
+## 🔐 幂等性设计
+
+### 1. 订单创建幂等
+- 使用 `(user_id, product_id, created_date)` 组合判断
+- 或使用客户端传入的幂等键 `idempotency_key`
+
+### 2. 支付回调幂等
+- 检查交易状态,已支付则直接返回成功
+- 使用数据库事务 + 行锁保证并发安全
+
+### 3. 退款幂等
+- 同一笔交易只能退款一次 (或限制总退款金额)
diff --git a/addons/Universal_Payment_Module copy/1_核心设计_通用协议/安全与合规.md b/addons/Universal_Payment_Module copy/1_核心设计_通用协议/安全与合规.md
new file mode 100644
index 00000000..009567de
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/1_核心设计_通用协议/安全与合规.md
@@ -0,0 +1,383 @@
+# 支付安全与合规指南 (Security & Compliance) v4.0
+
+> 支付系统安全最佳实践,保护你的资金和用户数据
+
+## 🔐 密钥安全
+
+### 1. 密钥存储原则
+
+```
+❌ 错误做法:
+- 将密钥硬编码在代码中
+- 将密钥提交到 Git 仓库
+- 通过即时通讯工具传输密钥
+- 使用弱密码作为 API Key
+
+✅ 正确做法:
+- 使用环境变量存储密钥
+- 使用专业密钥管理服务 (AWS KMS, HashiCorp Vault)
+- 定期轮换密钥
+- 最小权限原则
+```
+
+### 2. .gitignore 必须包含
+
+```gitignore
+# 支付密钥相关
+.env
+.env.local
+.env.*.local
+*.pem
+*.key
+cert/
+config/payment.yml
+secrets/
+```
+
+### 3. 密钥轮换
+
+- 定期更换 API 密钥 (建议每 90 天)
+- 发现泄露立即作废并重新生成
+- 保留旧密钥短暂过渡期
+
+---
+
+## 🔒 通信安全
+
+### 1. HTTPS 强制
+
+```nginx
+# Nginx 配置示例
+server {
+ listen 80;
+ server_name your-domain.com;
+ return 301 https://$server_name$request_uri;
+}
+
+server {
+ listen 443 ssl http2;
+ server_name your-domain.com;
+
+ ssl_certificate /path/to/fullchain.pem;
+ ssl_certificate_key /path/to/privkey.pem;
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
+
+ # HSTS
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+}
+```
+
+### 2. 证书管理
+
+- 使用受信任的 CA 签发证书
+- 定期检查证书有效期
+- 推荐 Let's Encrypt 自动续期
+
+---
+
+## ✅ 签名验证
+
+### 1. 支付宝签名验证
+
+```python
+from Crypto.PublicKey import RSA
+from Crypto.Signature import PKCS1_v1_5
+from Crypto.Hash import SHA256
+import base64
+
+def verify_alipay_sign(params: dict, sign: str, public_key: str) -> bool:
+ """验证支付宝签名"""
+ # 1. 参数排序
+ sorted_params = sorted([(k, v) for k, v in params.items() if k != 'sign' and v])
+
+ # 2. 拼接待签名字符串
+ sign_str = '&'.join([f'{k}={v}' for k, v in sorted_params])
+
+ # 3. RSA2 验签
+ key = RSA.import_key(f"-----BEGIN PUBLIC KEY-----\n{public_key}\n-----END PUBLIC KEY-----")
+ verifier = PKCS1_v1_5.new(key)
+ hash_obj = SHA256.new(sign_str.encode('utf-8'))
+
+ try:
+ verifier.verify(hash_obj, base64.b64decode(sign))
+ return True
+ except (ValueError, TypeError):
+ return False
+```
+
+### 2. 微信签名验证
+
+```python
+import hashlib
+
+def verify_wechat_sign(params: dict, sign: str, api_key: str) -> bool:
+ """验证微信支付签名"""
+ # 1. 参数排序
+ sorted_params = sorted([(k, v) for k, v in params.items() if k != 'sign' and v])
+
+ # 2. 拼接待签名字符串
+ sign_str = '&'.join([f'{k}={v}' for k, v in sorted_params])
+ sign_str += f'&key={api_key}'
+
+ # 3. MD5 签名
+ calculated_sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
+
+ return calculated_sign == sign
+```
+
+---
+
+## 💰 金额校验
+
+### 1. 回调金额必须验证
+
+```python
+def handle_payment_notify(trade_sn: str, paid_amount: int):
+ """处理支付回调时必须验证金额"""
+ trade = get_trade_by_sn(trade_sn)
+
+ # 金额必须严格匹配
+ if paid_amount != trade.cash_amount:
+ log.error(f"金额不匹配! 订单:{trade.cash_amount}, 回调:{paid_amount}")
+ raise AmountMismatchError()
+
+ # 继续处理...
+```
+
+### 2. 防止金额篡改
+
+```python
+# 前端传入的金额仅用于展示,实际金额从后端订单读取
+def checkout(order_sn: str, gateway: str):
+ order = get_order(order_sn)
+
+ # 金额从数据库读取,不信任前端
+ amount = order.pay_amount
+
+ return create_trade(order_sn, amount, gateway)
+```
+
+---
+
+## 🛡️ 回调安全
+
+### 1. IP 白名单
+
+```python
+# 支付平台回调 IP 白名单
+PAYMENT_IP_WHITELIST = {
+ 'alipay': [
+ '110.75.0.0/16',
+ '203.209.0.0/16'
+ ],
+ 'wechat': [
+ '101.226.0.0/16',
+ '140.207.0.0/16'
+ ]
+}
+
+def verify_callback_ip(gateway: str, client_ip: str) -> bool:
+ """验证回调来源 IP"""
+ import ipaddress
+
+ whitelist = PAYMENT_IP_WHITELIST.get(gateway, [])
+ client = ipaddress.ip_address(client_ip)
+
+ for cidr in whitelist:
+ if client in ipaddress.ip_network(cidr):
+ return True
+
+ return False
+```
+
+### 2. 防重放攻击
+
+```python
+import time
+
+def check_notify_timestamp(timestamp: int) -> bool:
+ """检查回调时间戳,防止重放攻击"""
+ now = int(time.time())
+
+ # 允许 5 分钟的时间差
+ if abs(now - timestamp) > 300:
+ log.warning(f"回调时间戳异常: {timestamp}")
+ return False
+
+ return True
+```
+
+### 3. 幂等性处理
+
+```python
+def process_notify_idempotent(trade_sn: str, notify_data: dict):
+ """幂等性处理回调"""
+
+ # 使用分布式锁
+ lock_key = f"payment_notify:{trade_sn}"
+
+ with redis_lock(lock_key, timeout=10):
+ trade = get_trade_by_sn(trade_sn)
+
+ # 已处理过,直接返回成功
+ if trade.status == 'paid':
+ return success_response()
+
+ # 处理支付成功逻辑
+ update_trade_to_paid(trade, notify_data)
+
+ return success_response()
+```
+
+---
+
+## 📝 日志审计
+
+### 1. 必须记录的日志
+
+```python
+import logging
+
+payment_logger = logging.getLogger('payment')
+
+# 创建交易日志
+payment_logger.info(f"创建交易 | trade_sn={trade_sn} | order_sn={order_sn} | amount={amount} | gateway={gateway}")
+
+# 回调日志
+payment_logger.info(f"收到回调 | gateway={gateway} | trade_sn={trade_sn} | raw_data={raw_data[:500]}")
+
+# 签名验证日志
+payment_logger.info(f"签名验证 | trade_sn={trade_sn} | result={verify_result}")
+
+# 状态变更日志
+payment_logger.info(f"状态变更 | trade_sn={trade_sn} | from={old_status} | to={new_status}")
+
+# 退款日志
+payment_logger.info(f"发起退款 | refund_sn={refund_sn} | trade_sn={trade_sn} | amount={amount}")
+```
+
+### 2. 敏感信息脱敏
+
+```python
+def mask_sensitive(data: dict) -> dict:
+ """敏感信息脱敏"""
+ sensitive_keys = ['card_no', 'id_card', 'phone', 'bank_account']
+
+ masked = data.copy()
+ for key in sensitive_keys:
+ if key in masked:
+ value = str(masked[key])
+ if len(value) > 4:
+ masked[key] = value[:2] + '*' * (len(value) - 4) + value[-2:]
+
+ return masked
+```
+
+---
+
+## 🚨 异常处理
+
+### 1. 支付异常分类
+
+```python
+class PaymentError(Exception):
+ """支付基础异常"""
+ pass
+
+class SignatureError(PaymentError):
+ """签名验证失败"""
+ pass
+
+class AmountMismatchError(PaymentError):
+ """金额不匹配"""
+ pass
+
+class OrderExpiredError(PaymentError):
+ """订单已过期"""
+ pass
+
+class DuplicatePaymentError(PaymentError):
+ """重复支付"""
+ pass
+
+class RefundError(PaymentError):
+ """退款失败"""
+ pass
+```
+
+### 2. 统一异常处理
+
+```python
+@app.exception_handler(PaymentError)
+async def payment_exception_handler(request, exc):
+ return JSONResponse(
+ status_code=400,
+ content={
+ "code": 400,
+ "message": str(exc),
+ "data": None
+ }
+ )
+```
+
+---
+
+## ✅ 合规要求
+
+### 1. PCI DSS 合规 (信用卡)
+
+- 不存储完整卡号、CVV、PIN
+- 使用 Stripe/PayPal 等符合 PCI DSS 的支付网关
+- 定期安全评估
+
+### 2. GDPR 合规 (欧盟用户)
+
+- 明确告知用户数据用途
+- 提供数据删除功能
+- 用户同意授权
+
+### 3. 中国支付合规
+
+- 接入持牌支付机构
+- 实名认证
+- 交易限额管理
+
+---
+
+## 📋 安全检查清单
+
+```markdown
+## 上线前安全检查
+
+### 密钥管理
+- [ ] 所有密钥通过环境变量配置
+- [ ] 密钥未提交到代码仓库
+- [ ] 生产环境密钥与测试环境隔离
+
+### 通信安全
+- [ ] 启用 HTTPS
+- [ ] 证书有效且受信任
+- [ ] 启用 HSTS
+
+### 签名验证
+- [ ] 所有回调验签
+- [ ] 验签失败拒绝处理
+
+### 金额校验
+- [ ] 回调金额与订单金额比对
+- [ ] 金额从后端读取
+
+### 日志审计
+- [ ] 关键操作有日志
+- [ ] 敏感信息脱敏
+
+### 异常处理
+- [ ] 异常不泄露敏感信息
+- [ ] 有统一异常处理
+
+### 回调安全
+- [ ] IP 白名单验证 (可选)
+- [ ] 幂等性处理
+- [ ] 防重放攻击
+```
diff --git a/addons/Universal_Payment_Module copy/1_核心设计_通用协议/标准配置模板.yaml b/addons/Universal_Payment_Module copy/1_核心设计_通用协议/标准配置模板.yaml
new file mode 100644
index 00000000..225a7af1
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/1_核心设计_通用协议/标准配置模板.yaml
@@ -0,0 +1,133 @@
+# ============================================================================
+# 全球支付模块标准配置模板 (Universal Payment Config Template) v4.0
+# ============================================================================
+# 适用于: Python, Node.js, Go, Java, PHP 等任意后端语言
+# 使用方法: 将此配置映射到你项目的环境变量 (.env, config.py, application.yml)
+# ============================================================================
+
+# ----------------------------------------------------------------------------
+# 1. 基础环境 (Environment)
+# ----------------------------------------------------------------------------
+APP_ENV: "production" # development / staging / production
+APP_NAME: "MyApp" # 应用名称 (用于日志/标题)
+APP_URL: "https://your-site.com" # 你的网站域名 (用于回调地址生成)
+APP_CURRENCY: "CNY" # 默认货币: CNY, USD, EUR
+
+# ----------------------------------------------------------------------------
+# 2. 数据库 (Database) - 存储订单和交易流水
+# ----------------------------------------------------------------------------
+DB_CONNECTION: "mysql" # mysql / postgres / mongodb / sqlite
+DB_HOST: "127.0.0.1"
+DB_PORT: "3306"
+DB_DATABASE: "payment_db"
+DB_USERNAME: "root"
+DB_PASSWORD: "your_password"
+
+# 自动创建的表:
+# - orders (订单表)
+# - pay_trades (交易流水表)
+# - cashflows (资金流水表)
+
+# ----------------------------------------------------------------------------
+# 3. 支付宝 (Alipay) - 中国市场
+# ----------------------------------------------------------------------------
+ALIPAY_ENABLED: true
+ALIPAY_MODE: "production" # sandbox / production
+ALIPAY_APP_ID: "" # 开放平台应用 AppID
+ALIPAY_PID: "" # 商户 PID (合作伙伴ID)
+ALIPAY_SELLER_EMAIL: "" # 收款支付宝账号
+ALIPAY_PRIVATE_KEY: "" # 商户私钥 (RSA2)
+ALIPAY_PUBLIC_KEY: "" # 支付宝公钥
+ALIPAY_MD5_KEY: "" # MD5 密钥 (旧版接口)
+
+# 回调地址 (系统自动拼接 APP_URL)
+# 同步回调: ${APP_URL}/api/payment/return/alipay
+# 异步回调: ${APP_URL}/api/payment/notify/alipay
+
+# ----------------------------------------------------------------------------
+# 4. 微信支付 (Wechat Pay) - 中国市场
+# ----------------------------------------------------------------------------
+WECHAT_ENABLED: true
+WECHAT_MODE: "production" # sandbox / production
+
+# 公众号/网站支付
+WECHAT_APPID: "" # 公众号/网站 AppID
+WECHAT_APP_SECRET: "" # AppSecret
+
+# 服务号 (如果有独立服务号)
+WECHAT_SERVICE_APPID: "" # 服务号 AppID
+WECHAT_SERVICE_SECRET: "" # 服务号 AppSecret
+
+# 商户信息
+WECHAT_MCH_ID: "" # 商户号
+WECHAT_MCH_KEY: "" # 商户平台 API 密钥 (32位)
+WECHAT_MCH_KEY_V3: "" # APIv3 密钥 (如使用v3接口)
+
+# 证书路径 (相对于项目根目录)
+WECHAT_CERT_PATH: "./cert/wechat/apiclient_cert.pem"
+WECHAT_KEY_PATH: "./cert/wechat/apiclient_key.pem"
+WECHAT_CERT_SERIAL: "" # 证书序列号 (v3接口需要)
+
+# 小程序 (如果有)
+WECHAT_MINI_APPID: "" # 小程序 AppID
+WECHAT_MINI_SECRET: "" # 小程序 AppSecret
+
+# 回调地址
+# 异步回调: ${APP_URL}/api/payment/notify/wechat
+
+# ----------------------------------------------------------------------------
+# 5. PayPal - 全球市场
+# ----------------------------------------------------------------------------
+PAYPAL_ENABLED: true
+PAYPAL_MODE: "live" # sandbox / live
+PAYPAL_CLIENT_ID: "" # Client ID
+PAYPAL_CLIENT_SECRET: "" # Client Secret
+PAYPAL_WEBHOOK_ID: "" # Webhook ID (用于验证回调)
+
+# 回调地址: ${APP_URL}/api/payment/notify/paypal
+
+# ----------------------------------------------------------------------------
+# 6. Stripe - 全球市场
+# ----------------------------------------------------------------------------
+STRIPE_ENABLED: true
+STRIPE_MODE: "live" # test / live
+STRIPE_PUBLIC_KEY: "" # pk_live_xxx 或 pk_test_xxx
+STRIPE_SECRET_KEY: "" # sk_live_xxx 或 sk_test_xxx
+STRIPE_WEBHOOK_SECRET: "" # whsec_xxx
+
+# 回调地址: ${APP_URL}/api/payment/notify/stripe
+
+# ----------------------------------------------------------------------------
+# 7. USDT (加密货币) - Web3 / 抗审查支付
+# ----------------------------------------------------------------------------
+USDT_ENABLED: false
+USDT_GATEWAY_TYPE: "nowpayments" # nowpayments / native
+
+# 选项 A: NOWPayments (第三方托管)
+NOWPAYMENTS_API_KEY: ""
+NOWPAYMENTS_IPN_SECRET: ""
+
+# 选项 B: Native (原生 TRC20 监听)
+TRON_NODE_API: "https://api.trongrid.io"
+TRON_WALLET_ADDRESS: "" # 你的 USDT-TRC20 收款地址
+TRON_API_KEY: "" # TronGrid API Key
+TRON_CHECK_INTERVAL: 60 # 轮询间隔 (秒)
+
+# ----------------------------------------------------------------------------
+# 8. 高级配置 (Advanced)
+# ----------------------------------------------------------------------------
+# 虚拟币/积分系统
+COIN_ENABLED: false # 是否启用虚拟币抵扣
+COIN_RATE: 100 # 1元 = 100虚拟币
+
+# 订单配置
+ORDER_EXPIRE_MINUTES: 30 # 订单过期时间 (分钟)
+TRADE_SN_PREFIX: "T" # 交易流水号前缀
+
+# 日志配置
+PAYMENT_LOG_LEVEL: "info" # debug / info / warning / error
+PAYMENT_LOG_PATH: "./logs/payment.log"
+
+# 安全配置
+PAYMENT_IP_WHITELIST: "" # 回调IP白名单 (逗号分隔)
+PAYMENT_SIGN_TYPE: "RSA2" # 签名类型: RSA2, MD5
diff --git a/addons/Universal_Payment_Module copy/2_智能对接_AI指令/Cursor规则.md b/addons/Universal_Payment_Module copy/2_智能对接_AI指令/Cursor规则.md
new file mode 100644
index 00000000..ad7d0ddc
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/2_智能对接_AI指令/Cursor规则.md
@@ -0,0 +1,266 @@
+# Universal Payment Module - Cursor 规则
+
+> 将此文件复制为项目根目录的 `.cursorrules` 或 `.cursor/rules/payment.md`
+
+---
+
+## 基础设定
+
+你是一位精通全球支付架构的资深全栈工程师,专注于支付网关集成、安全合规和高可用设计。
+
+当用户提及"支付模块"、"支付功能"、"接入支付"时,请参考 `Universal_Payment_Module` 目录中的设计文档。
+
+---
+
+## 核心原则
+
+### 1. 配置驱动
+- 所有支付密钥通过环境变量配置,绝不硬编码
+- 使用 `.env` 文件管理配置,参考 `标准配置模板.yaml`
+- 支持多环境切换 (development/staging/production)
+
+### 2. 工厂模式
+- 使用 `PaymentFactory` 统一管理支付网关
+- 每个网关实现统一的 `AbstractGateway` 接口
+- 支持动态添加新的支付渠道
+
+### 3. 安全优先
+- 所有回调必须验证签名
+- 必须验证支付金额与订单金额匹配
+- 使用 HTTPS,敏感数据脱敏
+- 参考 `安全与合规.md`
+
+### 4. 幂等性
+- 支付回调必须支持重复调用
+- 使用分布式锁防止并发问题
+- 检查交易状态后再处理
+
+### 5. 状态机
+- 订单状态: created → paying → paid → refunded/closed
+- 状态变更必须记录日志
+- 不允许跳跃式状态变更
+
+---
+
+## API 规范
+
+严格按照 `API接口定义.md` 实现以下接口:
+
+```
+POST /api/payment/create_order - 创建订单
+POST /api/payment/checkout - 发起支付
+GET /api/payment/status/{sn} - 查询状态
+POST /api/payment/close/{sn} - 关闭订单
+POST /api/payment/notify/{gw} - 回调通知
+GET /api/payment/return/{gw} - 同步返回
+GET /api/payment/methods - 获取支付方式
+```
+
+### 统一响应格式
+
+```json
+{
+ "code": 200,
+ "message": "success",
+ "data": { ... }
+}
+```
+
+---
+
+## 数据库模型
+
+参考 `业务逻辑与模型.md`,必须创建以下表:
+
+1. **orders** - 订单表 (业务订单)
+2. **pay_trades** - 交易流水表 (支付记录)
+3. **cashflows** - 资金流水表 (可选)
+4. **refunds** - 退款记录表
+
+金额单位:
+- 数据库存储使用**分** (BIGINT)
+- API 输入输出使用**元** (float)
+
+---
+
+## 支付网关 Gateway
+
+### 支付宝 Alipay
+- SDK: `alipay-sdk-python` / `alipay-sdk-java` / `alipay/aop-sdk`
+- 签名: RSA2
+- 回调: POST,form 表单格式
+
+### 微信支付 Wechat
+- SDK: `wechatpay-python-v3` / `wechatpay-java`
+- 签名: HMAC-SHA256 / RSA (v3)
+- 回调: POST,XML 格式
+
+### PayPal
+- SDK: `paypal-rest-sdk`
+- 认证: OAuth 2.0
+- 回调: Webhook,JSON 格式
+
+### Stripe
+- SDK: `stripe`
+- 认证: API Key
+- 回调: Webhook,JSON 格式
+
+---
+
+## 代码生成模板
+
+### Python FastAPI
+
+```python
+# app/services/payment_factory.py
+from abc import ABC, abstractmethod
+from app.config import settings
+
+class AbstractGateway(ABC):
+ @abstractmethod
+ async def create_trade(self, data: dict) -> dict:
+ pass
+
+ @abstractmethod
+ def verify_sign(self, data: dict) -> bool:
+ pass
+
+ @abstractmethod
+ def parse_notify(self, data: dict) -> dict:
+ pass
+
+class PaymentFactory:
+ _gateways = {}
+
+ @classmethod
+ def register(cls, name: str, gateway_class):
+ cls._gateways[name] = gateway_class
+
+ @classmethod
+ def create(cls, name: str) -> AbstractGateway:
+ gateway_name = name.split('_')[0]
+ if gateway_name not in cls._gateways:
+ raise ValueError(f"不支持的支付网关: {name}")
+ return cls._gateways[gateway_name]()
+```
+
+### Node.js Express
+
+```typescript
+// src/services/PaymentFactory.ts
+export abstract class AbstractGateway {
+ abstract createTrade(data: CreateTradeDTO): Promise;
+ abstract verifySign(data: Record): boolean;
+ abstract parseNotify(data: Record): NotifyResult;
+}
+
+export class PaymentFactory {
+ private static gateways: Map AbstractGateway> = new Map();
+
+ static register(name: string, gateway: new () => AbstractGateway) {
+ this.gateways.set(name, gateway);
+ }
+
+ static create(name: string): AbstractGateway {
+ const gatewayName = name.split('_')[0];
+ const GatewayClass = this.gateways.get(gatewayName);
+ if (!GatewayClass) {
+ throw new Error(`不支持的支付网关: ${name}`);
+ }
+ return new GatewayClass();
+ }
+}
+```
+
+---
+
+## 回调处理模板
+
+```python
+async def handle_notify(gateway: str, raw_data: bytes | dict):
+ """统一回调处理"""
+
+ # 1. 获取网关驱动
+ driver = PaymentFactory.create(gateway)
+
+ # 2. 验证签名
+ if not driver.verify_sign(raw_data):
+ logger.error(f"签名验证失败 | gateway={gateway}")
+ raise SignatureError()
+
+ # 3. 解析数据
+ parsed = driver.parse_notify(raw_data)
+ trade_sn = parsed['trade_sn']
+
+ # 4. 幂等检查
+ async with redis_lock(f"notify:{trade_sn}"):
+ trade = await get_trade(trade_sn)
+
+ if trade.status == 'paid':
+ return driver.success_response()
+
+ # 5. 金额校验
+ if parsed['amount'] != trade.cash_amount:
+ logger.error(f"金额不匹配 | sn={trade_sn}")
+ raise AmountMismatchError()
+
+ # 6. 更新状态
+ await update_trade_status(trade_sn, 'paid', parsed)
+
+ # 7. 触发业务回调
+ await dispatch_event('order.paid', trade.order_sn)
+
+ return driver.success_response()
+```
+
+---
+
+## 日志规范
+
+关键操作必须记录日志:
+
+```python
+logger.info(f"创建交易 | trade_sn={sn} | order={order_sn} | amount={amount}")
+logger.info(f"收到回调 | gateway={gw} | trade_sn={sn}")
+logger.info(f"签名验证 | trade_sn={sn} | result={ok}")
+logger.info(f"状态变更 | trade_sn={sn} | {old} → {new}")
+logger.error(f"支付失败 | trade_sn={sn} | error={err}")
+```
+
+---
+
+## 测试规范
+
+1. **单元测试**: 测试签名生成/验证、金额转换
+2. **集成测试**: 使用沙箱环境测试完整支付流程
+3. **Mock 测试**: 模拟回调接口测试
+
+---
+
+## 禁止事项
+
+❌ 密钥硬编码在代码中
+❌ 跳过签名验证
+❌ 信任前端传入的金额
+❌ 回调不做幂等处理
+❌ 敏感信息打印到日志
+❌ 使用 HTTP 而非 HTTPS
+
+---
+
+## 参考文档路径
+
+```
+Universal_Payment_Module/
+├── 1_核心设计_通用协议/
+│ ├── 标准配置模板.yaml # 配置参考
+│ ├── API接口定义.md # 接口规范
+│ ├── 业务逻辑与模型.md # 数据模型
+│ └── 安全与合规.md # 安全规范
+├── 2_智能对接_AI指令/
+│ ├── 通用集成指令.md # AI 提示词
+│ └── Cursor规则.md # 本文件
+└── 3_逻辑参考_通用实现/
+ ├── 前端收银台Demo.html
+ └── 后端源码/
+```
diff --git a/addons/Universal_Payment_Module copy/2_智能对接_AI指令/通用集成指令.md b/addons/Universal_Payment_Module copy/2_智能对接_AI指令/通用集成指令.md
new file mode 100644
index 00000000..a886e178
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/2_智能对接_AI指令/通用集成指令.md
@@ -0,0 +1,234 @@
+# 通用支付模块 AI 智能对接指令 (Integration Prompt) v4.0
+
+> 发送此指令给 AI 助手 (Cursor/ChatGPT/Claude),自动生成支付集成代码
+
+---
+
+## 🎯 角色设定
+
+```
+你是一位精通全球支付架构的资深全栈架构师,专注于:
+- 支付网关集成 (Alipay/Wechat/PayPal/Stripe/USDT)
+- 安全合规 (签名验证/HTTPS/PCI DSS)
+- 高可用设计 (幂等性/状态机/分布式锁)
+```
+
+---
+
+## 📋 任务目标
+
+我提供了一个**配置驱动 (Configuration-Driven)** 的通用支付模块设计。
+请根据我的项目环境,将此支付功能无缝集成。
+
+---
+
+## 📚 核心资源 (请先阅读)
+
+1. **标准配置模板**: `1_核心设计_通用协议/标准配置模板.yaml`
+2. **API 接口契约**: `1_核心设计_通用协议/API接口定义.md`
+3. **数据模型**: `1_核心设计_通用协议/业务逻辑与模型.md`
+4. **安全规范**: `1_核心设计_通用协议/安全与合规.md`
+
+---
+
+## 🔧 集成模式
+
+### 模式 A: 嵌入式集成 (Library Mode) ⭐推荐
+
+适用于将支付功能直接写在现有的后端项目中。
+
+**执行步骤**:
+1. **环境识别**: 检查项目语言 (Python/Node/Go/Java/PHP)
+2. **依赖安装**: 推荐 SDK
+3. **配置加载**: 读取环境变量
+4. **模型生成**: 创建 ORM 模型 (Order/Trade/Refund)
+5. **网关工厂**: 实现 PaymentFactory + 各网关 Driver
+6. **接口实现**: 按 `API接口定义.md` 实现 Controller
+7. **回调处理**: 实现回调验签和状态更新
+
+---
+
+### 模式 B: 微服务集成 (Microservice Mode)
+
+适用于将支付功能独立部署为一个服务。
+
+**执行步骤**:
+1. **服务生成**: 创建独立的支付服务项目
+2. **Docker化**: 编写 `Dockerfile` 和 `docker-compose.yml`
+3. **网关代理**: 配置 `/api/payment/*` 路由转发
+
+---
+
+## 📝 给 AI 的标准执行指令
+
+### 快速集成 (复制此内容发送给 AI)
+
+```
+请读取 `Universal_Payment_Module` 目录下的所有设计文档。
+
+我的当前项目信息:
+- 语言/框架: [Python FastAPI / Node.js Express / Java Spring Boot / Go Gin / PHP Laravel]
+- 数据库: [MySQL / PostgreSQL / MongoDB]
+- 集成模式: [模式 A 嵌入式 / 模式 B 微服务]
+
+请执行以下任务:
+1. 生成依赖安装命令
+2. 生成数据库迁移/模型代码
+3. 生成支付网关工厂类
+4. 生成 API 接口代码 (严格按 API接口定义.md)
+5. 生成回调处理代码
+6. 生成配置读取代码
+
+要求:
+- 使用工厂模式管理支付网关
+- 所有配置通过环境变量读取
+- 包含完整的签名验证逻辑
+- 包含幂等性处理
+- 添加中文注释
+```
+
+---
+
+## 🐍 Python FastAPI 示例指令
+
+```
+我的项目使用 Python FastAPI + SQLAlchemy + MySQL。
+
+请根据 Universal_Payment_Module 文档,生成:
+
+1. requirements.txt 依赖
+2. app/models/payment.py - 数据模型
+3. app/services/payment_factory.py - 支付网关工厂
+4. app/services/gateways/alipay.py - 支付宝网关
+5. app/services/gateways/wechat.py - 微信支付网关
+6. app/routers/payment.py - API 路由
+7. app/config/payment.py - 配置加载
+
+特别要求:
+- 使用 async/await 异步处理
+- 集成 alipay-sdk-python 和 wechatpay-python-v3
+- 回调接口支持 XML 和 JSON 格式
+```
+
+---
+
+## 🟢 Node.js Express 示例指令
+
+```
+我的项目使用 Node.js Express + Prisma + PostgreSQL。
+
+请根据 Universal_Payment_Module 文档,生成:
+
+1. package.json 依赖
+2. prisma/schema.prisma - 数据模型
+3. src/services/PaymentFactory.ts - 支付网关工厂
+4. src/services/gateways/AlipayGateway.ts
+5. src/services/gateways/WechatGateway.ts
+6. src/routes/payment.ts - API 路由
+7. src/config/payment.ts - 配置加载
+
+特别要求:
+- 使用 TypeScript
+- 使用 alipay-sdk 和 wechatpay-node-v3
+- 实现完整的错误处理
+```
+
+---
+
+## ☕ Java Spring Boot 示例指令
+
+```
+我的项目使用 Java Spring Boot + MyBatis + MySQL。
+
+请根据 Universal_Payment_Module 文档,生成:
+
+1. pom.xml 依赖
+2. entity/ - 实体类
+3. mapper/ - MyBatis Mapper
+4. service/PaymentFactory.java - 支付网关工厂
+5. service/gateway/AlipayGateway.java
+6. service/gateway/WechatGateway.java
+7. controller/PaymentController.java - API 控制器
+8. config/PaymentConfig.java - 配置类
+
+特别要求:
+- 使用 alipay-sdk-java 和 wechatpay-java
+- 使用 @Transactional 事务管理
+- 实现统一异常处理
+```
+
+---
+
+## 🐘 PHP Laravel 示例指令
+
+```
+我的项目使用 PHP Laravel + Eloquent + MySQL。
+
+请根据 Universal_Payment_Module 文档,生成:
+
+1. composer.json 依赖
+2. database/migrations/ - 数据库迁移
+3. app/Models/ - Eloquent 模型
+4. app/Services/PaymentFactory.php - 支付网关工厂
+5. app/Services/Gateways/AlipayGateway.php
+6. app/Services/Gateways/WechatGateway.php
+7. app/Http/Controllers/PaymentController.php
+8. routes/api.php - 路由定义
+9. config/payment.php - 配置文件
+
+特别要求:
+- 使用 alipay/aop-sdk 和 wechatpay/wechatpay
+- 使用 Laravel 的服务容器
+- 实现中间件验签
+```
+
+---
+
+## 🔥 高级指令:前端收银台
+
+```
+请根据 Universal_Payment_Module 文档,生成前端收银台组件。
+
+技术栈: [Vue 3 / React / 原生 JS]
+
+要求:
+1. 支持多种支付方式切换
+2. 扫码支付显示二维码
+3. 轮询支付状态
+4. 适配移动端
+5. 显示支付倒计时
+6. 美观的 UI (可使用 TailwindCSS)
+```
+
+---
+
+## 🔥 高级指令:Docker 部署
+
+```
+请为 Universal_Payment_Module 生成 Docker 部署配置。
+
+要求:
+1. Dockerfile (多阶段构建)
+2. docker-compose.yml (包含 MySQL + Redis)
+3. nginx.conf (反向代理 + HTTPS)
+4. .env.example (环境变量模板)
+5. deploy.sh (一键部署脚本)
+```
+
+---
+
+## ⚠️ 注意事项
+
+1. **密钥安全**: 生成的代码中不要硬编码任何密钥
+2. **签名验证**: 必须实现完整的签名验证逻辑
+3. **幂等处理**: 回调必须支持幂等
+4. **金额校验**: 必须验证回调金额与订单金额匹配
+5. **日志记录**: 关键操作必须记录日志
+
+---
+
+## 📞 支持
+
+如有问题,请联系:
+- 微信: 28533368
+- 作者: 卡若
diff --git a/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/前端收银台Demo.html b/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/前端收银台Demo.html
new file mode 100644
index 00000000..060af045
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/前端收银台Demo.html
@@ -0,0 +1,748 @@
+
+
+
+
+
+ 通用收银台 v4.0
+
+
+
+
+
+
+
+
+
VIP会员月卡
+
+ ¥
+ 99.00
+
+
+ 订单号: 202401170001
+ 29:59
+
+
+
+
+
+
选择支付方式
+
+
+
+
+
+
+
+
+
+
🅿️
+
+
PayPal
+
支持信用卡,海外用户推荐
+
+
+
+
+
+
+
₮
+
+
USDT (TRC20)
+
加密货币支付
+
+
+
+
+
+
+
+
+
+
![支付二维码]()
+
+
请使用微信扫描二维码支付
+
二维码有效期 30 分钟,请尽快支付
+
+
+
+
+
+
+
+
+
+
+
+
+
✓
+
支付成功
+
感谢您的购买,订单已完成
+
+
+
+
+
+ 🔒 安全支付由卡若私域提供技术支持
+
+
+
+
+
+
+
diff --git a/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/后端源码/python/alipay_gateway.py b/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/后端源码/python/alipay_gateway.py
new file mode 100644
index 00000000..e17e637d
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/后端源码/python/alipay_gateway.py
@@ -0,0 +1,294 @@
+"""
+支付宝网关实现 (Alipay Gateway)
+基于 www.lytiao.com 项目提取
+
+作者: 卡若
+版本: v4.0
+"""
+
+import json
+import base64
+import hashlib
+import logging
+from typing import Dict, Any, Optional
+from urllib.parse import urlencode, parse_qs
+
+try:
+ from Crypto.PublicKey import RSA
+ from Crypto.Signature import PKCS1_v1_5
+ from Crypto.Hash import SHA256
+except ImportError:
+ print("请安装 pycryptodome: pip install pycryptodome")
+
+from payment_factory import (
+ AbstractGateway, CreateTradeData, TradeResult, NotifyResult,
+ SignatureError, logger
+)
+
+
+class AlipayGateway(AbstractGateway):
+ """
+ 支付宝网关
+
+ 支持:
+ - 电脑网站支付 (platform_type='web')
+ - 手机网站支付 (platform_type='wap')
+ - 扫码支付 (platform_type='qr')
+ """
+
+ GATEWAY_URL = 'https://openapi.alipay.com/gateway.do'
+ SANDBOX_URL = 'https://openapi.alipaydev.com/gateway.do'
+
+ def __init__(self, config: Dict[str, Any]):
+ super().__init__(config)
+ self.app_id = config.get('app_id', '')
+ self.pid = config.get('pid', '')
+ self.seller_email = config.get('seller_email', '')
+ self.private_key = config.get('private_key', '')
+ self.public_key = config.get('public_key', '')
+ self.md5_key = config.get('md5_key', '')
+
+ def create_trade(self, data: CreateTradeData) -> TradeResult:
+ """创建支付宝交易"""
+ platform_type = data.platform_type.capitalize()
+
+ if platform_type == 'Web':
+ return self._create_web_trade(data)
+ elif platform_type == 'Wap':
+ return self._create_wap_trade(data)
+ elif platform_type == 'Qr':
+ return self._create_qr_trade(data)
+ else:
+ raise ValueError(f"不支持的支付类型: {platform_type}")
+
+ def _create_web_trade(self, data: CreateTradeData) -> TradeResult:
+ """电脑网站支付"""
+ biz_content = {
+ 'subject': data.goods_title[:256],
+ 'out_trade_no': data.trade_sn,
+ 'total_amount': str(data.amount / 100), # 分转元
+ 'product_code': 'FAST_INSTANT_TRADE_PAY',
+ 'body': data.goods_detail[:128] if data.goods_detail else '',
+ 'passback_params': json.dumps(data.attach) if data.attach else '',
+ }
+
+ params = self._build_params('alipay.trade.page.pay', biz_content, data.return_url, data.notify_url)
+
+ # 生成签名
+ sign = self._generate_sign(params)
+ params['sign'] = sign
+
+ # 构建跳转URL
+ pay_url = f"{self.GATEWAY_URL}?{urlencode(params)}"
+
+ return TradeResult(
+ type='url',
+ payload=pay_url,
+ trade_sn=data.trade_sn
+ )
+
+ def _create_wap_trade(self, data: CreateTradeData) -> TradeResult:
+ """手机网站支付"""
+ biz_content = {
+ 'subject': data.goods_title[:256],
+ 'out_trade_no': data.trade_sn,
+ 'total_amount': str(data.amount / 100),
+ 'product_code': 'QUICK_WAP_WAY',
+ 'body': data.goods_detail[:128] if data.goods_detail else '',
+ 'passback_params': json.dumps(data.attach) if data.attach else '',
+ }
+
+ params = self._build_params('alipay.trade.wap.pay', biz_content, data.return_url, data.notify_url)
+ sign = self._generate_sign(params)
+ params['sign'] = sign
+
+ pay_url = f"{self.GATEWAY_URL}?{urlencode(params)}"
+
+ return TradeResult(
+ type='url',
+ payload=pay_url,
+ trade_sn=data.trade_sn
+ )
+
+ def _create_qr_trade(self, data: CreateTradeData) -> TradeResult:
+ """扫码支付 (当面付)"""
+ biz_content = {
+ 'subject': data.goods_title[:256],
+ 'out_trade_no': data.trade_sn,
+ 'total_amount': str(data.amount / 100),
+ 'body': data.goods_detail[:128] if data.goods_detail else '',
+ }
+
+ params = self._build_params('alipay.trade.precreate', biz_content, '', data.notify_url)
+ sign = self._generate_sign(params)
+ params['sign'] = sign
+
+ # 调用接口获取二维码
+ import requests
+ response = requests.post(self.GATEWAY_URL, data=params)
+ result = response.json()
+
+ if 'alipay_trade_precreate_response' in result:
+ resp = result['alipay_trade_precreate_response']
+ if resp.get('code') == '10000':
+ return TradeResult(
+ type='qrcode',
+ payload=resp['qr_code'],
+ trade_sn=data.trade_sn
+ )
+
+ raise Exception(f"创建支付宝扫码支付失败: {result}")
+
+ def _build_params(self, method: str, biz_content: dict, return_url: str, notify_url: str) -> dict:
+ """构建公共参数"""
+ import time
+
+ params = {
+ 'app_id': self.app_id,
+ 'method': method,
+ 'charset': 'utf-8',
+ 'sign_type': 'RSA2',
+ 'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
+ 'version': '1.0',
+ 'biz_content': json.dumps(biz_content, ensure_ascii=False),
+ }
+
+ if return_url:
+ params['return_url'] = return_url
+ if notify_url:
+ params['notify_url'] = notify_url
+
+ return params
+
+ def _generate_sign(self, params: dict) -> str:
+ """生成RSA2签名"""
+ # 排序并拼接
+ sorted_params = sorted([(k, v) for k, v in params.items() if v])
+ sign_str = '&'.join([f'{k}={v}' for k, v in sorted_params])
+
+ # RSA2签名
+ key = RSA.import_key(f"-----BEGIN RSA PRIVATE KEY-----\n{self.private_key}\n-----END RSA PRIVATE KEY-----")
+ signer = PKCS1_v1_5.new(key)
+ hash_obj = SHA256.new(sign_str.encode('utf-8'))
+ signature = signer.sign(hash_obj)
+
+ return base64.b64encode(signature).decode('utf-8')
+
+ def verify_sign(self, data: Dict[str, Any]) -> bool:
+ """验证支付宝签名"""
+ sign = data.pop('sign', '')
+ sign_type = data.pop('sign_type', 'RSA2')
+
+ if not sign:
+ return False
+
+ # 排序并拼接
+ sorted_params = sorted([(k, v) for k, v in data.items() if v and k != 'sign_type'])
+ sign_str = '&'.join([f'{k}={v}' for k, v in sorted_params])
+
+ try:
+ key = RSA.import_key(f"-----BEGIN PUBLIC KEY-----\n{self.public_key}\n-----END PUBLIC KEY-----")
+ verifier = PKCS1_v1_5.new(key)
+ hash_obj = SHA256.new(sign_str.encode('utf-8'))
+ verifier.verify(hash_obj, base64.b64decode(sign))
+ return True
+ except (ValueError, TypeError) as e:
+ logger.error(f"支付宝签名验证失败: {e}")
+ return False
+
+ def parse_notify(self, data: Dict[str, Any]) -> NotifyResult:
+ """解析支付宝回调"""
+ trade_status = data.get('trade_status', '')
+
+ if trade_status in ['TRADE_SUCCESS', 'TRADE_FINISHED']:
+ status = 'paid'
+ else:
+ status = 'failed'
+
+ # 解析透传参数
+ attach = {}
+ passback = data.get('passback_params', '')
+ if passback:
+ try:
+ attach = json.loads(passback)
+ except:
+ pass
+
+ # 解析支付时间
+ import time
+ gmt_payment = data.get('gmt_payment', '')
+ if gmt_payment:
+ pay_time = int(time.mktime(time.strptime(gmt_payment, '%Y-%m-%d %H:%M:%S')))
+ else:
+ pay_time = int(time.time())
+
+ return NotifyResult(
+ status=status,
+ trade_sn=data.get('out_trade_no', ''),
+ platform_sn=data.get('trade_no', ''),
+ pay_amount=int(float(data.get('total_amount', 0)) * 100),
+ pay_time=pay_time,
+ currency='CNY',
+ attach=attach,
+ raw_data=data
+ )
+
+ def close_trade(self, trade_sn: str) -> bool:
+ """关闭交易"""
+ biz_content = {
+ 'out_trade_no': trade_sn,
+ }
+
+ params = self._build_params('alipay.trade.close', biz_content, '', '')
+ sign = self._generate_sign(params)
+ params['sign'] = sign
+
+ import requests
+ response = requests.post(self.GATEWAY_URL, data=params)
+ result = response.json()
+
+ resp = result.get('alipay_trade_close_response', {})
+ return resp.get('code') == '10000'
+
+ def query_trade(self, trade_sn: str) -> Optional[NotifyResult]:
+ """查询交易"""
+ biz_content = {
+ 'out_trade_no': trade_sn,
+ }
+
+ params = self._build_params('alipay.trade.query', biz_content, '', '')
+ sign = self._generate_sign(params)
+ params['sign'] = sign
+
+ import requests
+ response = requests.post(self.GATEWAY_URL, data=params)
+ result = response.json()
+
+ resp = result.get('alipay_trade_query_response', {})
+ if resp.get('code') == '10000' and resp.get('trade_status') in ['TRADE_SUCCESS', 'TRADE_FINISHED']:
+ return self.parse_notify(resp)
+
+ return None
+
+ def refund(self, trade_sn: str, refund_sn: str, amount: int, reason: str = '') -> bool:
+ """发起退款"""
+ biz_content = {
+ 'out_trade_no': trade_sn,
+ 'out_request_no': refund_sn,
+ 'refund_amount': str(amount / 100),
+ 'refund_reason': reason or '用户申请退款',
+ }
+
+ params = self._build_params('alipay.trade.refund', biz_content, '', '')
+ sign = self._generate_sign(params)
+ params['sign'] = sign
+
+ import requests
+ response = requests.post(self.GATEWAY_URL, data=params)
+ result = response.json()
+
+ resp = result.get('alipay_trade_refund_response', {})
+ return resp.get('code') == '10000'
+
+ def success_response(self) -> str:
+ return 'success'
diff --git a/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/后端源码/python/payment_factory.py b/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/后端源码/python/payment_factory.py
new file mode 100644
index 00000000..bc1791bd
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/后端源码/python/payment_factory.py
@@ -0,0 +1,339 @@
+"""
+支付网关工厂 (Payment Gateway Factory)
+基于 www.lytiao.com 项目提取的支付逻辑,适配 Python FastAPI
+
+作者: 卡若
+版本: v4.0
+"""
+
+import os
+import time
+import hashlib
+import logging
+from abc import ABC, abstractmethod
+from typing import Dict, Any, Optional, Tuple
+from dataclasses import dataclass
+from enum import Enum
+
+logger = logging.getLogger('payment')
+
+
+class PaymentPlatform(Enum):
+ """支付平台枚举"""
+ ALIPAY = 'alipay'
+ WECHAT = 'wechat'
+ PAYPAL = 'paypal'
+ STRIPE = 'stripe'
+ USDT = 'usdt'
+ COIN = 'coin'
+
+
+class TradeType(Enum):
+ """交易类型"""
+ PURCHASE = 'purchase' # 购买
+ RECHARGE = 'recharge' # 充值
+
+
+class TradeStatus(Enum):
+ """交易状态"""
+ PAYING = 'paying'
+ PAID = 'paid'
+ CLOSED = 'closed'
+ REFUNDED = 'refunded'
+
+
+@dataclass
+class CreateTradeData:
+ """创建交易请求数据"""
+ goods_title: str
+ goods_detail: str
+ trade_sn: str
+ order_sn: str
+ amount: int # 金额,单位:分
+ notify_url: str
+ return_url: str = ''
+ platform_type: str = 'web' # web/wap/jsapi/native/h5/app
+ create_ip: str = ''
+ open_id: str = '' # 微信JSAPI支付需要
+ attach: Dict[str, Any] = None
+
+
+@dataclass
+class TradeResult:
+ """交易结果"""
+ type: str # url/qrcode/json/address/direct
+ payload: Any # 支付数据
+ trade_sn: str
+ expiration: int = 1800 # 过期时间(秒)
+
+
+@dataclass
+class NotifyResult:
+ """回调解析结果"""
+ status: str
+ trade_sn: str
+ platform_sn: str
+ pay_amount: int # 分
+ pay_time: int # 时间戳
+ currency: str = 'CNY'
+ attach: Dict[str, Any] = None
+ raw_data: Dict[str, Any] = None
+
+
+class PaymentException(Exception):
+ """支付异常基类"""
+ pass
+
+
+class SignatureError(PaymentException):
+ """签名验证失败"""
+ pass
+
+
+class AmountMismatchError(PaymentException):
+ """金额不匹配"""
+ pass
+
+
+class GatewayNotFoundError(PaymentException):
+ """支付网关不存在"""
+ pass
+
+
+class AbstractGateway(ABC):
+ """
+ 支付网关抽象基类
+ 所有支付网关必须实现此接口
+ """
+
+ def __init__(self, config: Dict[str, Any] = None):
+ self.config = config or {}
+
+ @abstractmethod
+ def create_trade(self, data: CreateTradeData) -> TradeResult:
+ """
+ 创建交易
+
+ Args:
+ data: 交易数据
+
+ Returns:
+ TradeResult: 包含支付参数的结果
+ """
+ pass
+
+ @abstractmethod
+ def verify_sign(self, data: Dict[str, Any]) -> bool:
+ """
+ 验证签名
+
+ Args:
+ data: 回调原始数据
+
+ Returns:
+ bool: 签名是否有效
+ """
+ pass
+
+ @abstractmethod
+ def parse_notify(self, data: Any) -> NotifyResult:
+ """
+ 解析回调数据
+
+ Args:
+ data: 回调原始数据 (可能是dict或xml字符串)
+
+ Returns:
+ NotifyResult: 解析后的结果
+ """
+ pass
+
+ @abstractmethod
+ def close_trade(self, trade_sn: str) -> bool:
+ """
+ 关闭交易
+
+ Args:
+ trade_sn: 交易流水号
+
+ Returns:
+ bool: 是否关闭成功
+ """
+ pass
+
+ @abstractmethod
+ def query_trade(self, trade_sn: str) -> Optional[NotifyResult]:
+ """
+ 查询交易状态
+
+ Args:
+ trade_sn: 交易流水号
+
+ Returns:
+ NotifyResult: 交易状态,未支付返回None
+ """
+ pass
+
+ @abstractmethod
+ def refund(self, trade_sn: str, refund_sn: str, amount: int, reason: str = '') -> bool:
+ """
+ 发起退款
+
+ Args:
+ trade_sn: 原交易流水号
+ refund_sn: 退款单号
+ amount: 退款金额(分)
+ reason: 退款原因
+
+ Returns:
+ bool: 是否成功
+ """
+ pass
+
+ def success_response(self) -> str:
+ """回调成功响应"""
+ return 'success'
+
+ def fail_response(self) -> str:
+ """回调失败响应"""
+ return 'fail'
+
+
+class PaymentFactory:
+ """
+ 支付网关工厂
+
+ 使用示例:
+ # 注册网关
+ PaymentFactory.register('alipay', AlipayGateway)
+ PaymentFactory.register('wechat', WechatGateway)
+
+ # 创建网关实例
+ gateway = PaymentFactory.create('wechat_jsapi')
+ result = gateway.create_trade(data)
+ """
+
+ _gateways: Dict[str, type] = {}
+
+ @classmethod
+ def register(cls, name: str, gateway_class: type):
+ """注册支付网关"""
+ cls._gateways[name] = gateway_class
+ logger.info(f"注册支付网关: {name}")
+
+ @classmethod
+ def create(cls, gateway: str) -> AbstractGateway:
+ """
+ 创建支付网关实例
+
+ Args:
+ gateway: 网关名称,格式如 'wechat_jsapi',会取下划线前的部分
+
+ Returns:
+ AbstractGateway: 网关实例
+ """
+ gateway_name = gateway.split('_')[0]
+
+ if gateway_name not in cls._gateways:
+ raise GatewayNotFoundError(f"不支持的支付网关: {gateway}")
+
+ gateway_class = cls._gateways[gateway_name]
+ config = cls._get_gateway_config(gateway_name)
+
+ return gateway_class(config)
+
+ @classmethod
+ def _get_gateway_config(cls, gateway_name: str) -> Dict[str, Any]:
+ """获取网关配置"""
+ config_map = {
+ 'alipay': {
+ 'app_id': os.getenv('ALIPAY_APP_ID', ''),
+ 'pid': os.getenv('ALIPAY_PID', ''),
+ 'seller_email': os.getenv('ALIPAY_SELLER_EMAIL', ''),
+ 'private_key': os.getenv('ALIPAY_PRIVATE_KEY', ''),
+ 'public_key': os.getenv('ALIPAY_PUBLIC_KEY', ''),
+ 'md5_key': os.getenv('ALIPAY_MD5_KEY', ''),
+ },
+ 'wechat': {
+ 'appid': os.getenv('WECHAT_APPID', ''),
+ 'app_secret': os.getenv('WECHAT_APP_SECRET', ''),
+ 'mch_id': os.getenv('WECHAT_MCH_ID', ''),
+ 'mch_key': os.getenv('WECHAT_MCH_KEY', ''),
+ 'cert_path': os.getenv('WECHAT_CERT_PATH', ''),
+ 'key_path': os.getenv('WECHAT_KEY_PATH', ''),
+ },
+ 'paypal': {
+ 'client_id': os.getenv('PAYPAL_CLIENT_ID', ''),
+ 'client_secret': os.getenv('PAYPAL_CLIENT_SECRET', ''),
+ 'mode': os.getenv('PAYPAL_MODE', 'sandbox'),
+ },
+ 'stripe': {
+ 'public_key': os.getenv('STRIPE_PUBLIC_KEY', ''),
+ 'secret_key': os.getenv('STRIPE_SECRET_KEY', ''),
+ 'webhook_secret': os.getenv('STRIPE_WEBHOOK_SECRET', ''),
+ },
+ }
+
+ return config_map.get(gateway_name, {})
+
+ @classmethod
+ def get_enabled_gateways(cls) -> list:
+ """获取已启用的支付网关列表"""
+ enabled = []
+
+ if os.getenv('ALIPAY_ENABLED', 'false').lower() == 'true':
+ enabled.append({
+ 'gateway': 'alipay',
+ 'name': '支付宝',
+ 'icon': '/icons/alipay.png',
+ 'types': ['web', 'wap', 'qr']
+ })
+
+ if os.getenv('WECHAT_ENABLED', 'false').lower() == 'true':
+ enabled.append({
+ 'gateway': 'wechat',
+ 'name': '微信支付',
+ 'icon': '/icons/wechat.png',
+ 'types': ['native', 'jsapi', 'h5', 'app']
+ })
+
+ if os.getenv('PAYPAL_ENABLED', 'false').lower() == 'true':
+ enabled.append({
+ 'gateway': 'paypal',
+ 'name': 'PayPal',
+ 'icon': '/icons/paypal.png',
+ 'types': ['redirect']
+ })
+
+ if os.getenv('STRIPE_ENABLED', 'false').lower() == 'true':
+ enabled.append({
+ 'gateway': 'stripe',
+ 'name': 'Stripe',
+ 'icon': '/icons/stripe.png',
+ 'types': ['redirect']
+ })
+
+ return enabled
+
+
+def generate_trade_sn(prefix: str = 'T') -> str:
+ """
+ 生成交易流水号
+
+ 格式: 前缀 + 年月日时分秒 + 5位随机数
+ 示例: T2024011710053012345
+ """
+ import random
+ timestamp = time.strftime('%Y%m%d%H%M%S')
+ random_num = random.randint(10000, 99999)
+ return f"{prefix}{timestamp}{random_num}"
+
+
+def yuan_to_fen(yuan: float) -> int:
+ """元转分"""
+ return int(round(yuan * 100))
+
+
+def fen_to_yuan(fen: int) -> float:
+ """分转元"""
+ return round(fen / 100, 2)
diff --git a/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/后端源码/python/wechat_gateway.py b/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/后端源码/python/wechat_gateway.py
new file mode 100644
index 00000000..b6d09eb9
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/3_逻辑参考_通用实现/后端源码/python/wechat_gateway.py
@@ -0,0 +1,317 @@
+"""
+微信支付网关实现 (Wechat Pay Gateway)
+基于 www.lytiao.com 项目提取
+
+作者: 卡若
+版本: v4.0
+"""
+
+import json
+import time
+import hashlib
+import logging
+import xml.etree.ElementTree as ET
+from typing import Dict, Any, Optional
+from urllib.parse import urlencode
+import uuid
+
+from payment_factory import (
+ AbstractGateway, CreateTradeData, TradeResult, NotifyResult,
+ SignatureError, logger
+)
+
+
+class WechatGateway(AbstractGateway):
+ """
+ 微信支付网关
+
+ 支持:
+ - Native扫码支付 (platform_type='native')
+ - JSAPI公众号/小程序支付 (platform_type='jsapi')
+ - H5支付 (platform_type='h5')
+ - APP支付 (platform_type='app')
+ """
+
+ UNIFIED_ORDER_URL = 'https://api.mch.weixin.qq.com/pay/unifiedorder'
+ ORDER_QUERY_URL = 'https://api.mch.weixin.qq.com/pay/orderquery'
+ CLOSE_ORDER_URL = 'https://api.mch.weixin.qq.com/pay/closeorder'
+ REFUND_URL = 'https://api.mch.weixin.qq.com/secapi/pay/refund'
+
+ def __init__(self, config: Dict[str, Any]):
+ super().__init__(config)
+ self.appid = config.get('appid', '')
+ self.app_secret = config.get('app_secret', '')
+ self.mch_id = config.get('mch_id', '')
+ self.mch_key = config.get('mch_key', '')
+ self.cert_path = config.get('cert_path', '')
+ self.key_path = config.get('key_path', '')
+
+ def create_trade(self, data: CreateTradeData) -> TradeResult:
+ """创建微信支付交易"""
+ platform_type = data.platform_type.upper()
+
+ # 构建统一下单参数
+ params = {
+ 'appid': self.appid,
+ 'mch_id': self.mch_id,
+ 'nonce_str': self._generate_nonce(),
+ 'body': data.goods_title[:128],
+ 'out_trade_no': data.trade_sn,
+ 'total_fee': str(data.amount), # 微信以分为单位
+ 'spbill_create_ip': data.create_ip or '127.0.0.1',
+ 'notify_url': data.notify_url,
+ 'trade_type': platform_type,
+ 'attach': json.dumps(data.attach) if data.attach else '',
+ }
+
+ # JSAPI需要openid
+ if platform_type == 'JSAPI':
+ if not data.open_id:
+ raise ValueError("微信JSAPI支付需要提供 openid")
+ params['openid'] = data.open_id
+
+ # H5支付需要scene_info
+ if platform_type == 'MWEB':
+ params['scene_info'] = json.dumps({
+ 'h5_info': {
+ 'type': 'Wap',
+ 'wap_url': data.return_url,
+ 'wap_name': data.goods_title[:32]
+ }
+ })
+
+ # 生成签名
+ params['sign'] = self._generate_sign(params)
+
+ # 调用统一下单接口
+ import requests
+ xml_data = self._dict_to_xml(params)
+ response = requests.post(self.UNIFIED_ORDER_URL, data=xml_data.encode('utf-8'))
+ result = self._xml_to_dict(response.text)
+
+ if result.get('return_code') != 'SUCCESS':
+ raise Exception(f"微信支付统一下单失败: {result.get('return_msg')}")
+
+ if result.get('result_code') != 'SUCCESS':
+ raise Exception(f"微信支付统一下单失败: {result.get('err_code_des')}")
+
+ # 根据类型返回不同格式
+ if platform_type == 'NATIVE':
+ # 扫码支付返回二维码链接
+ return TradeResult(
+ type='qrcode',
+ payload=result['code_url'],
+ trade_sn=data.trade_sn
+ )
+
+ elif platform_type == 'JSAPI':
+ # 公众号支付返回JS SDK参数
+ prepay_id = result['prepay_id']
+ js_params = {
+ 'appId': self.appid,
+ 'timeStamp': str(int(time.time())),
+ 'nonceStr': self._generate_nonce(),
+ 'package': f'prepay_id={prepay_id}',
+ 'signType': 'MD5',
+ }
+ js_params['paySign'] = self._generate_sign(js_params)
+
+ return TradeResult(
+ type='json',
+ payload=js_params,
+ trade_sn=data.trade_sn
+ )
+
+ elif platform_type == 'MWEB':
+ # H5支付返回跳转链接
+ mweb_url = result['mweb_url']
+ if data.return_url:
+ mweb_url += f"&redirect_url={urlencode({'': data.return_url})[1:]}"
+
+ return TradeResult(
+ type='url',
+ payload=mweb_url,
+ trade_sn=data.trade_sn
+ )
+
+ elif platform_type == 'APP':
+ # APP支付返回SDK参数
+ prepay_id = result['prepay_id']
+ app_params = {
+ 'appid': self.appid,
+ 'partnerid': self.mch_id,
+ 'prepayid': prepay_id,
+ 'package': 'Sign=WXPay',
+ 'noncestr': self._generate_nonce(),
+ 'timestamp': str(int(time.time())),
+ }
+ app_params['sign'] = self._generate_sign(app_params)
+
+ return TradeResult(
+ type='json',
+ payload=app_params,
+ trade_sn=data.trade_sn
+ )
+
+ else:
+ raise ValueError(f"不支持的微信支付类型: {platform_type}")
+
+ def verify_sign(self, data: Dict[str, Any]) -> bool:
+ """验证微信签名"""
+ sign = data.pop('sign', '')
+ if not sign:
+ return False
+
+ calculated_sign = self._generate_sign(data)
+ return calculated_sign == sign
+
+ def parse_notify(self, data: Any) -> NotifyResult:
+ """解析微信回调"""
+ # 如果是XML字符串,先转换为dict
+ if isinstance(data, str):
+ data = self._xml_to_dict(data)
+
+ # 验证签名
+ if not self.verify_sign(data.copy()):
+ raise SignatureError("微信签名验证失败")
+
+ result_code = data.get('result_code', '')
+
+ if result_code == 'SUCCESS':
+ status = 'paid'
+ else:
+ status = 'failed'
+
+ # 解析透传参数
+ attach = {}
+ attach_str = data.get('attach', '')
+ if attach_str:
+ try:
+ attach = json.loads(attach_str)
+ except:
+ pass
+
+ # 解析支付时间 (格式: 20240117100530)
+ time_end = data.get('time_end', '')
+ if time_end:
+ pay_time = int(time.mktime(time.strptime(time_end, '%Y%m%d%H%M%S')))
+ else:
+ pay_time = int(time.time())
+
+ return NotifyResult(
+ status=status,
+ trade_sn=data.get('out_trade_no', ''),
+ platform_sn=data.get('transaction_id', ''),
+ pay_amount=int(data.get('cash_fee', 0)),
+ pay_time=pay_time,
+ currency=data.get('fee_type', 'CNY'),
+ attach=attach,
+ raw_data=data
+ )
+
+ def close_trade(self, trade_sn: str) -> bool:
+ """关闭微信交易"""
+ params = {
+ 'appid': self.appid,
+ 'mch_id': self.mch_id,
+ 'out_trade_no': trade_sn,
+ 'nonce_str': self._generate_nonce(),
+ }
+ params['sign'] = self._generate_sign(params)
+
+ import requests
+ xml_data = self._dict_to_xml(params)
+ response = requests.post(self.CLOSE_ORDER_URL, data=xml_data.encode('utf-8'))
+ result = self._xml_to_dict(response.text)
+
+ return result.get('result_code') == 'SUCCESS'
+
+ def query_trade(self, trade_sn: str) -> Optional[NotifyResult]:
+ """查询微信交易"""
+ params = {
+ 'appid': self.appid,
+ 'mch_id': self.mch_id,
+ 'out_trade_no': trade_sn,
+ 'nonce_str': self._generate_nonce(),
+ }
+ params['sign'] = self._generate_sign(params)
+
+ import requests
+ xml_data = self._dict_to_xml(params)
+ response = requests.post(self.ORDER_QUERY_URL, data=xml_data.encode('utf-8'))
+ result = self._xml_to_dict(response.text)
+
+ if result.get('trade_state') == 'SUCCESS':
+ return self.parse_notify(result)
+
+ return None
+
+ def refund(self, trade_sn: str, refund_sn: str, amount: int, reason: str = '') -> bool:
+ """微信退款 (需要证书)"""
+ # 先查询原交易获取金额
+ query_result = self.query_trade(trade_sn)
+ if not query_result:
+ return False
+
+ params = {
+ 'appid': self.appid,
+ 'mch_id': self.mch_id,
+ 'nonce_str': self._generate_nonce(),
+ 'out_trade_no': trade_sn,
+ 'out_refund_no': refund_sn,
+ 'total_fee': str(query_result.pay_amount),
+ 'refund_fee': str(amount),
+ 'refund_desc': reason or '用户申请退款',
+ }
+ params['sign'] = self._generate_sign(params)
+
+ import requests
+ xml_data = self._dict_to_xml(params)
+
+ # 退款需要证书
+ response = requests.post(
+ self.REFUND_URL,
+ data=xml_data.encode('utf-8'),
+ cert=(self.cert_path, self.key_path)
+ )
+ result = self._xml_to_dict(response.text)
+
+ return result.get('result_code') == 'SUCCESS'
+
+ def success_response(self) -> str:
+ """微信回调成功响应"""
+ return ''
+
+ def fail_response(self) -> str:
+ """微信回调失败响应"""
+ return ''
+
+ def _generate_nonce(self) -> str:
+ """生成随机字符串"""
+ return uuid.uuid4().hex
+
+ def _generate_sign(self, params: dict) -> str:
+ """生成MD5签名"""
+ # 排序并拼接
+ sorted_params = sorted([(k, v) for k, v in params.items() if v and k != 'sign'])
+ sign_str = '&'.join([f'{k}={v}' for k, v in sorted_params])
+ sign_str += f'&key={self.mch_key}'
+
+ # MD5签名
+ return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
+
+ def _dict_to_xml(self, data: dict) -> str:
+ """字典转XML"""
+ xml = ['']
+ for k, v in data.items():
+ if isinstance(v, str):
+ xml.append(f'<{k}>{k}>')
+ else:
+ xml.append(f'<{k}>{v}{k}>')
+ xml.append('')
+ return ''.join(xml)
+
+ def _xml_to_dict(self, xml_str: str) -> dict:
+ """XML转字典"""
+ root = ET.fromstring(xml_str)
+ return {child.tag: child.text for child in root}
diff --git a/addons/Universal_Payment_Module copy/4_卡若配置/env.example.txt b/addons/Universal_Payment_Module copy/4_卡若配置/env.example.txt
new file mode 100644
index 00000000..345aba6e
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/4_卡若配置/env.example.txt
@@ -0,0 +1,101 @@
+# ============================================================================
+# 卡若私域支付配置 (Karuo Payment Config)
+# ============================================================================
+# ⚠️ 警告: 此文件包含敏感信息,请勿提交到 Git!
+# 使用方法: 复制此文件为 .env 并填入真实值
+# ============================================================================
+
+# ----------------------------------------------------------------------------
+# 1. 基础环境
+# ----------------------------------------------------------------------------
+APP_ENV=production
+APP_NAME=卡若私域
+APP_URL=https://www.lytiao.com
+APP_CURRENCY=CNY
+
+# ----------------------------------------------------------------------------
+# 2. 数据库 (卡若私域数据库)
+# ----------------------------------------------------------------------------
+DB_CONNECTION=mysql
+DB_HOST=10.88.182.62
+DB_PORT=3306
+DB_DATABASE=payment_db
+DB_USERNAME=root
+DB_PASSWORD=Vtka(agu)-1
+
+# ----------------------------------------------------------------------------
+# 3. 支付宝 (Alipay)
+# ----------------------------------------------------------------------------
+ALIPAY_ENABLED=true
+ALIPAY_MODE=production
+ALIPAY_APP_ID=
+ALIPAY_PID=2088511801157159
+ALIPAY_SELLER_EMAIL=zhengzhiqun@vip.qq.com
+ALIPAY_PRIVATE_KEY=
+ALIPAY_PUBLIC_KEY=
+ALIPAY_MD5_KEY=lz6ey1h3kl9zqkgtjz3avb5gk37wzbrp
+
+# ----------------------------------------------------------------------------
+# 4. 微信支付 (Wechat Pay)
+# ----------------------------------------------------------------------------
+WECHAT_ENABLED=true
+WECHAT_MODE=production
+
+# 网站/H5支付
+WECHAT_APPID=wx432c93e275548671
+WECHAT_APP_SECRET=25b7e7fdb7998e5107e242ebb6ddabd0
+
+# 服务号 (JSAPI)
+WECHAT_SERVICE_APPID=wx7c0dbf34ddba300d
+WECHAT_SERVICE_SECRET=f865ef18c43dfea6cbe3b1f1aebdb82e
+
+# 商户信息
+WECHAT_MCH_ID=1318592501
+WECHAT_MCH_KEY=wx3e31b068be59ddc131b068be59ddc2
+
+# 证书路径
+WECHAT_CERT_PATH=./cert/wechat/apiclient_cert.pem
+WECHAT_KEY_PATH=./cert/wechat/apiclient_key.pem
+
+# MP文件验证码
+WECHAT_MP_VERIFY=SP8AfZJyAvprRORT
+
+# ----------------------------------------------------------------------------
+# 5. PayPal (暂未启用)
+# ----------------------------------------------------------------------------
+PAYPAL_ENABLED=false
+PAYPAL_MODE=sandbox
+PAYPAL_CLIENT_ID=
+PAYPAL_CLIENT_SECRET=
+
+# ----------------------------------------------------------------------------
+# 6. Stripe (暂未启用)
+# ----------------------------------------------------------------------------
+STRIPE_ENABLED=false
+STRIPE_MODE=test
+STRIPE_PUBLIC_KEY=
+STRIPE_SECRET_KEY=
+STRIPE_WEBHOOK_SECRET=
+
+# ----------------------------------------------------------------------------
+# 7. USDT (暂未启用)
+# ----------------------------------------------------------------------------
+USDT_ENABLED=false
+USDT_GATEWAY_TYPE=nowpayments
+NOWPAYMENTS_API_KEY=
+NOWPAYMENTS_IPN_SECRET=
+
+# ----------------------------------------------------------------------------
+# 8. 高级配置
+# ----------------------------------------------------------------------------
+# 虚拟币/积分
+COIN_ENABLED=false
+COIN_RATE=100
+
+# 订单配置
+ORDER_EXPIRE_MINUTES=30
+TRADE_SN_PREFIX=T
+
+# 日志
+PAYMENT_LOG_LEVEL=info
+PAYMENT_LOG_PATH=./logs/payment.log
diff --git a/addons/Universal_Payment_Module copy/README.md b/addons/Universal_Payment_Module copy/README.md
new file mode 100644
index 00000000..be151a97
--- /dev/null
+++ b/addons/Universal_Payment_Module copy/README.md
@@ -0,0 +1,142 @@
+# 🌐 全球通用支付模块 (Universal Payment Module) v4.0
+
+> **配置驱动 (Configuration-Driven)** | **API 优先 (API-First)** | **AI 智能对接**
+>
+> 让任何语言的项目在 5 分钟内接入支付宝、微信支付、PayPal、Stripe 和 USDT
+
+## 📂 模块结构
+
+```
+Universal_Payment_Module/
+├── 1_核心设计_通用协议/ # [灵魂] 定义了支付的"法律"
+│ ├── 标准配置模板.yaml # 填空即可配置所有支付参数
+│ ├── API接口定义.md # 无论用什么语言,接口都长这样
+│ ├── 业务逻辑与模型.md # 数据库表结构设计 (Order/PayTrade)
+│ └── 安全与合规.md # 支付安全最佳实践
+│
+├── 2_智能对接_AI指令/ # [工具] AI 编译器
+│ ├── 通用集成指令.md # 发给 AI,自动生成代码
+│ └── Cursor规则.md # Cursor IDE 专用规则
+│
+├── 3_逻辑参考_通用实现/ # [参考] 可直接复用的代码
+│ ├── 前端收银台Demo.html # 原生 JS 实现的通用收银台
+│ ├── 后端源码/ # 多语言参考实现
+│ │ ├── php/ # PHP (Laravel/Symfony)
+│ │ ├── python/ # Python (FastAPI/Django)
+│ │ ├── nodejs/ # Node.js (Express/NestJS)
+│ │ └── java/ # Java (Spring Boot)
+│ └── 前端模板/ # Vue/React/原生JS 模板
+│
+├── 4_卡若配置/ # [私有] 卡若的支付密钥 (勿提交Git)
+│ └── .env.example # 配置示例
+│
+└── README.md # 本说明文档
+```
+
+## 🚀 极速对接 (3步完成)
+
+### 第一步:配置 (Config)
+```bash
+# 1. 复制配置模板到你的项目
+cp 1_核心设计_通用协议/标准配置模板.yaml your-project/.env
+
+# 2. 填入你的支付密钥
+```
+
+### 第二步:生成代码 (Generate with AI)
+```
+发送给 Cursor/ChatGPT:
+"请读取 Universal_Payment_Module 目录,我的项目是 Python FastAPI,
+采用嵌入式集成,帮我生成支付模块代码。"
+```
+
+### 第三步:前端接入 (Frontend)
+```javascript
+// 只需调用一个 API
+const result = await fetch('/api/payment/checkout', {
+ method: 'POST',
+ body: JSON.stringify({ order_sn: '202401170001', gateway: 'wechat_jsapi' })
+});
+```
+
+## 🌍 支持的支付渠道
+
+| 渠道 | 能力 | 场景 | 状态 |
+|:---|:---|:---|:---|
+| **支付宝 Alipay** | 扫码/H5/APP/小程序 | 中国市场 (CNY) | ✅ 已实现 |
+| **微信支付 Wechat** | JSAPI/Native/H5/APP/小程序 | 中国市场 (CNY) | ✅ 已实现 |
+| **PayPal** | 信用卡/订阅 | 全球市场 (USD/EUR) | ✅ 已实现 |
+| **Stripe** | 信用卡/订阅/Apple Pay | 全球市场 | ✅ 已实现 |
+| **USDT (TRC20)** | 链上转账/监听 | Web3/抗审查 | ✅ 已实现 |
+
+## ✨ v4.0 核心特性
+
+### 1. 配置驱动 (Zero-Code Config)
+- 所有密钥通过环境变量注入,无需改动代码
+- 支持多环境切换 (development/production)
+
+### 2. 工厂模式 (Payment Factory)
+```python
+# 所有支付网关统一接口
+payment = PaymentFactory.create('wechat')
+result = payment.create_trade(order)
+```
+
+### 3. 幂等性保障 (Idempotency)
+- 回调通知自动去重
+- 订单状态机管理
+
+### 4. AI 智能生成
+- 提供 Cursor/Copilot 专用提示词
+- 一键生成任意语言的完整实现
+
+## 📖 快速参考
+
+### 创建订单
+```http
+POST /api/payment/create_order
+Content-Type: application/json
+
+{
+ "user_id": "u1001",
+ "title": "VIP会员",
+ "amount": 99.00,
+ "currency": "CNY",
+ "product_id": "vip_monthly"
+}
+```
+
+### 发起支付
+```http
+POST /api/payment/checkout
+Content-Type: application/json
+
+{
+ "order_sn": "202401170001",
+ "gateway": "wechat_jsapi",
+ "openid": "oXxx..."
+}
+```
+
+### 支付状态查询
+```http
+GET /api/payment/status/202401170001
+```
+
+## 🔐 安全须知
+
+1. **密钥安全**: 所有密钥存放在 `.env`,**绝不提交到 Git**
+2. **HTTPS 强制**: 生产环境必须启用 HTTPS
+3. **签名验证**: 所有回调必须验签
+4. **金额校验**: 支付金额必须与订单金额匹配
+
+## 📚 相关文档
+
+- [API 接口定义](./1_核心设计_通用协议/API接口定义.md)
+- [数据库模型](./1_核心设计_通用协议/业务逻辑与模型.md)
+- [AI 集成指令](./2_智能对接_AI指令/通用集成指令.md)
+- [Cursor 规则](./2_智能对接_AI指令/Cursor规则.md)
+
+---
+
+**作者**: 卡若 | **联系**: 28533368 (微信) | **更新**: 2026-01-17
diff --git a/addons/Universal_Payment_Module/1_核心设计_通用协议/API接口定义.md b/addons/Universal_Payment_Module/1_核心设计_通用协议/API接口定义.md
deleted file mode 100644
index 10008242..00000000
--- a/addons/Universal_Payment_Module/1_核心设计_通用协议/API接口定义.md
+++ /dev/null
@@ -1,94 +0,0 @@
-# 通用支付模块 API 接口定义 (Universal Payment API)
-
-无论后端使用何种语言(Python/Node/Go),请严格实现以下 RESTful 接口。
-
-## 1. 核心交易接口 (Core Transaction)
-
-### 1.1 创建订单
-* **URL**: `POST /api/payment/create_order`
-* **Description**: 业务系统通知支付模块创建一个待支付订单。
-* **Request Body**:
- \`\`\`json
- {
- "user_id": "u1001", // 用户ID
- "title": "VIP Membership", // 订单标题
- "amount": 99.00, // 金额 (法币单位: 元 / 美元)
- "currency": "CNY", // 币种: CNY, USD
- "product_id": "vip_01", // 商品ID
- "extra_params": {} // 扩展参数
- }
- \`\`\`
-* **Response**:
- \`\`\`json
- {
- "code": 200,
- "data": {
- "order_sn": "202310270001", // 支付系统生成的唯一订单号
- "status": "created"
- }
- }
- \`\`\`
-
-### 1.2 发起支付 (收银台)
-* **URL**: `POST /api/payment/checkout`
-* **Description**: 用户选择支付方式后,获取支付参数。
-* **Request Body**:
- \`\`\`json
- {
- "order_sn": "202310270001",
- "gateway": "alipay_qr", // 支付方式: alipay_qr, wechat_jsapi, paypal, usdt, stripe
- "return_url": "https://...", // 支付成功后前端跳转地址
- "openid": "..." // 微信JSAPI支付必填
- }
- \`\`\`
-* **Response**:
- \`\`\`json
- {
- "code": 200,
- "data": {
- "type": "url", // url (跳转), qrcode (扫码), json (SDK参数), address (USDT)
- "payload": "https://...", // 具体内容
- "expiration": 1800 // 过期时间(秒)
- }
- }
- \`\`\`
-
-### 1.3 查询订单状态
-* **URL**: `GET /api/payment/status/{order_sn}`
-* **Description**: 前端轮询使用。
-* **Response**:
- \`\`\`json
- {
- "code": 200,
- "data": {
- "status": "paid", // created, paying, paid, closed
- "paid_amount": 99.00,
- "paid_at": "2023-10-27 10:00:00"
- }
- }
- \`\`\`
-
----
-
-## 2. 回调通知接口 (Webhook)
-
-### 2.1 统一回调入口
-* **URL**: `POST /api/payment/notify/{gateway}`
-* **Description**: 接收第三方支付平台的异步通知。
-* **Path Params**:
- * `gateway`: `alipay`, `wechat`, `paypal`, `stripe`, `nowpayments`
-* **Logic**:
- 1. 根据 gateway 加载对应驱动。
- 2. 验签 (Verify Signature)。
- 3. 幂等性检查 (Idempotency Check)。
- 4. 更新订单状态。
- 5. 返回平台所需的响应字符串 (e.g. `success`, `200 OK`).
-
----
-
-## 3. 辅助接口
-
-### 3.1 获取汇率
-* **URL**: `GET /api/payment/exchange_rate`
-* **Params**: `from=USD&to=CNY`
-* **Response**: `{"rate": 7.21}`
diff --git a/addons/Universal_Payment_Module/1_核心设计_通用协议/标准配置模板.yaml b/addons/Universal_Payment_Module/1_核心设计_通用协议/标准配置模板.yaml
deleted file mode 100644
index 03dd6fe6..00000000
--- a/addons/Universal_Payment_Module/1_核心设计_通用协议/标准配置模板.yaml
+++ /dev/null
@@ -1,70 +0,0 @@
-# 全球支付模块标准配置模板 (Standard Config)
-
-# 无论你使用 Python, Node.js, Go 还是 Java,请将此配置映射到你的环境(如 .env, config.py, config.js)
-
-# -------------------------------------------------------------------
-# 1. 基础环境 (Environment)
-# -------------------------------------------------------------------
-APP_ENV: "production" # development / production
-APP_URL: "https://your-site.com" # 你的网站域名 (用于回调)
-
-# -------------------------------------------------------------------
-# 2. 数据库 (Database)
-# -------------------------------------------------------------------
-# 系统会自动生成 order 和 pay_trade 表
-DB_CONNECTION: "mysql" # mysql / postgres / sqlite
-DB_HOST: "127.0.0.1"
-DB_PORT: "3306"
-DB_DATABASE: "payment_db"
-DB_USERNAME: "root"
-DB_PASSWORD: "password"
-
-# -------------------------------------------------------------------
-# 3. 支付宝 (Alipay) - CN
-# -------------------------------------------------------------------
-ALIPAY_ENABLED: true
-ALIPAY_APP_ID: "20210001..."
-ALIPAY_PRIVATE_KEY: "MIIETv..." # 商户私钥
-ALIPAY_PUBLIC_KEY: "MIIBIj..." # 支付宝公钥
-
-# -------------------------------------------------------------------
-# 4. 微信支付 (Wechat Pay) - CN
-# -------------------------------------------------------------------
-WECHAT_ENABLED: true
-WECHAT_APP_ID: "wx123456..." # 公众号/小程序 AppID
-WECHAT_MCH_ID: "1234567890" # 商户号
-WECHAT_API_V3_KEY: "abcdef..." # APIv3 密钥 (32位)
-WECHAT_CERT_SERIAL: "45F59C..." # 证书序列号
-WECHAT_PRIVATE_KEY_PATH: "./cert/apiclient_key.pem"
-WECHAT_CERT_PATH: "./cert/apiclient_cert.pem"
-
-# -------------------------------------------------------------------
-# 5. PayPal - Global
-# -------------------------------------------------------------------
-PAYPAL_ENABLED: true
-PAYPAL_MODE: "live" # sandbox / live
-PAYPAL_CLIENT_ID: "Af7s8..."
-PAYPAL_CLIENT_SECRET: "EKd9..."
-
-# -------------------------------------------------------------------
-# 6. Stripe - Global
-# -------------------------------------------------------------------
-STRIPE_ENABLED: true
-STRIPE_PUBLIC_KEY: "pk_live_..."
-STRIPE_SECRET_KEY: "sk_live_..."
-STRIPE_WEBHOOK_SECRET: "whsec_..."
-
-# -------------------------------------------------------------------
-# 7. USDT (Crypto) - Web3
-# -------------------------------------------------------------------
-USDT_ENABLED: true
-USDT_GATEWAY_TYPE: "nowpayments" # nowpayments / native (原生监听)
-
-# 选项 A: NOWPayments (第三方网关)
-NOWPAYMENTS_API_KEY: "R1G..."
-NOWPAYMENTS_IPN_SECRET: "secret..."
-
-# 选项 B: Native (原生监听 - TRC20)
-TRON_NODE_API: "https://api.trongrid.io"
-TRON_WALLET_ADDRESS: "T9yD14Nj9..." # 你的收款地址
-TRON_CHECK_INTERVAL: 60 # 轮询间隔 (秒)
diff --git a/addons/Universal_Payment_Module/2_智能对接_AI指令/通用集成指令.md b/addons/Universal_Payment_Module/2_智能对接_AI指令/通用集成指令.md
deleted file mode 100644
index f89dc28b..00000000
--- a/addons/Universal_Payment_Module/2_智能对接_AI指令/通用集成指令.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# 通用支付模块智能对接指令 (AI Integration Prompt) v3.0
-
-**角色设定**: 你是一位精通全球支付架构(Alipay/Wechat/PayPal/Stripe/USDT)的资深全栈架构师。
-
-**任务目标**:
-我提供了一个**完全配置驱动 (Configuration-Driven)** 的通用支付模块设计。
-请你根据我的目标项目环境,将此支付功能无缝集成进去。
-
-**核心资源 (Input)**:
-1. **标准配置模板**: `1_核心设计_通用协议/标准配置模板.yaml` (所有支付参数的 Key)
-2. **API 接口契约**: `1_核心设计_通用协议/API接口定义.md` (标准 RESTful 接口)
-3. **核心业务模型**: `1_核心设计_通用协议/业务逻辑与模型.md` (数据库表结构)
-
-**集成模式 (选择一种)**:
-
-### 模式 A: 嵌入式集成 (Library Mode) - *推荐*
-适用于将支付功能直接写在现有的后端项目中 (如 Django app, NestJS module)。
-
-**步骤**:
-1. **环境识别**: 检查我的项目语言 (Python/Node/Go/Java)。
-2. **依赖安装**: 根据语言推荐 SDK (e.g. `alipay-sdk-python`, `stripe`).
-3. **配置加载**: 创建代码读取 `标准配置模板.yaml` 中的环境变量。
-4. **模型生成**: 根据 `业务逻辑与模型.md` 生成 ORM 代码 (User/Order/PayTrade)。
-5. **接口实现**: 严格按照 `API接口定义.md` 实现 Controller/View。
- * *要求*: 使用工厂模式 (`PaymentFactory`) 管理不同网关。
-
-### 模式 B: 微服务集成 (Microservice Mode)
-适用于将支付功能独立部署为一个 Docker 容器。
-
-**步骤**:
-1. **服务生成**: 用 Go (Gin) 或 Node.js (Express) 生成一个独立服务。
-2. **Docker化**: 编写 `Dockerfile` 和 `docker-compose.yml`。
-3. **网关代理**: 配置 Nginx 或 API Gateway 将 `/api/payment` 转发给此服务。
-
----
-
-**给 AI 的执行指令 (Prompt)**:
-
-> "请读取 `Universal_Payment_Module` 目录下的所有设计文档。
-> 我的当前项目是基于 **[你的语言/框架]** 的。
-> 请采用 **[模式 A / 模式 B]** 为我集成支付功能。
-> 1. 首先生成依赖安装命令。
-> 2. 然后生成数据库模型代码。
-> 3. 最后实现符合 `API接口定义.md` 的核心接口代码。"
diff --git a/addons/Universal_Payment_Module/3_逻辑参考_通用实现/前端收银台Demo.html b/addons/Universal_Payment_Module/3_逻辑参考_通用实现/前端收银台Demo.html
deleted file mode 100644
index 3a68421f..00000000
--- a/addons/Universal_Payment_Module/3_逻辑参考_通用实现/前端收银台Demo.html
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
- 通用收银台 Demo
-
-
-
-
-
-
-
订单支付
-
¥ 99.00
-
订单号: 202310270001
-
-
-
-
-
-
![QRCode]()
-
请扫描二维码支付
-
-
-
-
-
-
-
-
-
diff --git a/addons/Universal_Payment_Module/README.md b/addons/Universal_Payment_Module/README.md
deleted file mode 100644
index 06c4ae2a..00000000
--- a/addons/Universal_Payment_Module/README.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# 全球通用支付模块 (Universal Payment Module) v3.0
-
-这是一个**配置驱动 (Configuration-Driven)**、**API 优先 (API-First)** 的全球支付解决方案包。
-它通过标准化的协议和 AI 指令,让任何语言的项目都能在 5 分钟内接入支付宝、微信、PayPal、Stripe 和 USDT。
-
-## 📂 模块结构 (Directory Structure)
-
-\`\`\`
-Universal_Payment_Module/
-├── 1_核心设计_通用协议/ # [灵魂] 定义了支付的“法律”
-│ ├── 标准配置模板.yaml # [新增] 填空即可配置所有支付参数
-│ ├── API接口定义.md # [新增] 无论用什么语言,接口都长这样
-│ ├── 业务逻辑与模型.md # 数据库表结构设计 (Order/PayTrade)
-│ └── 接口注册指南.md # 申请 Key 的教程
-│
-├── 2_智能对接_AI指令/ # [工具] AI 编译器
-│ └── 通用集成指令.md # 发给 AI,自动生成代码
-│
-├── 3_逻辑参考_通用实现/ # [参考]
-│ ├── 前端收银台Demo.html # [新增] 原生 JS 实现的通用收银台
-│ ├── 后端源码/ # PHP 参考实现
-│ └── 前端模板/ # Twig 参考模板
-│
-└── README.md # 本说明文档
-\`\`\`
-
-## 🚀 极速对接 (Integration Guide)
-
-### 第一步:配置 (Config)
-1. 打开 `1_核心设计_通用协议/标准配置模板.yaml`。
-2. 将文件内容复制到你项目的配置文件中(如 `.env` 或 `config.py`)。
-3. 填入你申请到的 `APP_ID`, `PRIVATE_KEY` 等参数。
-
-### 第二步:生成代码 (Generate)
-1. 复制 `2_智能对接_AI指令/通用集成指令.md` 的内容。
-2. 打开 AI 助手,发送指令:
- > "我的项目是用 **Python FastAPI** 写的。请根据上述文档,采用 **模式 A (嵌入式)** 为我集成支付功能。"
-3. AI 会为你生成:
- * `pip install ...` 命令
- * `models.py` (数据库模型)
- * `payment_router.py` (API 接口)
-
-### 第三步:前端接入 (Frontend)
-1. 参考 `3_逻辑参考_通用实现/前端收银台Demo.html`。
-2. 将其中的 `API_BASE` 替换为你后端实际的 API 地址。
-3. 即可拥有一个支持 **扫码、跳转、加密货币支付** 的全功能收银台。
-
-## 🌍 支持能力
-| 渠道 | 能力 | 适用场景 |
-| :--- | :--- | :--- |
-| **Alipay / Wechat** | 扫码 / H5 / APP | 中国市场 (CNY) |
-| **PayPal / Stripe** | 信用卡 / 订阅 | 全球市场 (USD/EUR...) |
-| **USDT (TRC20)** | 链上转账 / 监听 | Web3 / 抗审查支付 |
-
-## ✨ v3.0 优化亮点
-* **配置驱动**: 不再需要改代码里的硬编码,所有参数通过配置文件注入。
-* **API 契约**: 明确了输入输出格式,前后端对接不再扯皮。
-* **前端 Demo**: 提供了一个不依赖任何框架的原生 JS 收银台,复制即用。
diff --git a/api/soul导师顾问接口.md b/api/soul导师顾问接口.md
new file mode 100644
index 00000000..7a1c2636
--- /dev/null
+++ b/api/soul导师顾问接口.md
@@ -0,0 +1,413 @@
+# 对外获客线索上报接口文档(V1)
+
+## 一、接口概述
+
+- **接口名称**:对外获客线索上报接口
+- **接口用途**:供第三方系统向【存客宝】上报客户线索(手机号 / 微信号等),用于后续的跟进、标签管理和画像分析。
+- **接口协议**:HTTP
+- **请求方式**:`POST`
+- **请求地址**: `https://ckbapi.quwanzhi.com/v1/api/scenarios`
+
+> 具体 URL 以实际环境配置为准。
+
+- **数据格式**:
+ - 推荐:`application/json`
+ - 兼容:`application/x-www-form-urlencoded`
+- **字符编码**:`UTF-8`
+
+---
+
+## 二、鉴权与签名
+
+### 2.1 必填鉴权字段
+
+| 字段名 | 类型 | 必填 | 说明 |
+|-------------|--------|------|---------------------------------------|
+| `apiKey` | string | 是 | 分配给第三方的接口密钥(每个任务唯一)|
+| `sign` | string | 是 | 签名值 |
+| `timestamp` | int | 是 | 秒级时间戳(与服务器时间差不超过 5 分钟) |
+
+### 2.2 时间戳校验
+
+服务器会校验 `timestamp` 是否在当前时间前后 **5 分钟** 内:
+
+- 通过条件:`|server_time - timestamp| <= 300`
+- 超出范围则返回:`请求已过期`
+
+### 2.3 签名生成规则
+
+接口采用自定义签名机制。**签名字段为 `sign`,生成步骤如下:**
+
+假设本次请求的所有参数为 `params`,其中包括业务参数 + `apiKey` + `timestamp` + `sign` + 可能存在的 `portrait` 对象。
+
+#### 第一步:移除特定字段
+
+从 `params` 中移除以下字段:
+
+- `sign` —— 自身不参与签名
+- `apiKey` —— 不参与参数拼接,仅在最后一步参与二次 MD5
+- `portrait` —— 整个画像对象不参与签名(即使内部还有子字段)
+
+> 说明:`portrait` 通常是一个 JSON 对象,字段较多,为避免签名实现复杂且双方难以对齐,统一不参与签名。
+
+#### 第二步:移除空值字段
+
+从剩余参数中,移除值为:
+
+- `null`
+- 空字符串 `''`
+
+的字段,这些字段不参与签名。
+
+#### 第三步:按参数名升序排序
+
+对剩余参数按**参数名(键名)升序排序**,排序规则为标准的 ASCII 升序:
+
+```text
+例如: name, phone, source, timestamp
+```
+
+#### 第四步:拼接参数值
+
+将排序后的参数 **只取“值”**,按顺序直接拼接为一个字符串,中间不加任何分隔符:
+
+- 示例:
+ 排序后参数为:
+
+ ```text
+ name = 张三
+ phone = 13800000000
+ source = 微信广告
+ timestamp = 1710000000
+ ```
+
+ 则拼接:
+
+ ```text
+ stringToSign = "张三13800000000微信广告1710000000"
+ ```
+
+#### 第五步:第一次 MD5
+
+对上一步拼接得到的字符串做一次 MD5:
+
+\[
+\text{firstMd5} = \text{MD5}(\text{stringToSign})
+\]
+
+#### 第六步:拼接 apiKey 再次 MD5
+
+将第一步的结果与 `apiKey` 直接拼接,再做一次 MD5,得到最终签名值:
+
+\[
+\text{sign} = \text{MD5}(\text{firstMd5} + \text{apiKey})
+\]
+
+#### 第七步:放入请求
+
+将第六步得到的 `sign` 填入请求参数中的 `sign` 字段即可。
+
+> 建议:
+> - 使用小写 MD5 字符串(双方约定统一即可)。
+> - 请确保参与签名的参数与最终请求发送的参数一致(包括是否传空值)。
+
+### 2.4 签名示例(PHP 伪代码)
+
+```php
+$params = [
+ 'apiKey' => 'YOUR_API_KEY',
+ 'timestamp' => '1710000000',
+ 'phone' => '13800000000',
+ 'name' => '张三',
+ 'source' => '微信广告',
+ 'remark' => '通过H5落地页留资',
+ // 'portrait' => [...], // 如有画像,这里会存在,但不参与签名
+ // 'sign' => '待生成',
+];
+
+// 1. 去掉 sign、apiKey、portrait
+unset($params['sign'], $params['apiKey'], $params['portrait']);
+
+// 2. 去掉空值
+$params = array_filter($params, function($value) {
+ return !is_null($value) && $value !== '';
+});
+
+// 3. 按键名升序排序
+ksort($params);
+
+// 4. 拼接参数值
+$stringToSign = implode('', array_values($params));
+
+// 5. 第一次 MD5
+$firstMd5 = md5($stringToSign);
+
+// 6. 第二次 MD5(拼接 apiKey)
+$apiKey = 'YOUR_API_KEY';
+$sign = md5($firstMd5 . $apiKey);
+
+// 将 $sign 作为字段发送
+$params['sign'] = $sign;
+```
+
+---
+
+## 三、请求参数说明
+
+### 3.1 主标识字段(至少传一个)
+
+| 字段名 | 类型 | 必填 | 说明 |
+|-----------|--------|------|-------------------------------------------|
+| `wechatId`| string | 否 | 微信号,存在时优先作为主标识 |
+| `phone` | string | 否 | 手机号,当 `wechatId` 为空时用作主标识 |
+
+### 3.2 基础信息字段
+
+| 字段名 | 类型 | 必填 | 说明 |
+|------------|--------|------|-------------------------|
+| `name` | string | 否 | 客户姓名 |
+| `source` | string | 否 | 线索来源描述,如“百度推广”、“抖音直播间” |
+| `remark` | string | 否 | 备注信息 |
+| `tags` | string | 否 | 逗号分隔的“微信标签”,如:`"高意向,电商,女装"` |
+| `siteTags` | string | 否 | 逗号分隔的“站内标签”,用于站内进一步细分 |
+
+
+### 3.3 用户画像字段 `portrait`(可选)
+
+`portrait` 为一个对象(JSON),用于记录用户的行为画像数据。
+
+#### 3.3.1 基本示例
+
+```json
+"portrait": {
+ "type": 1,
+ "source": 1,
+ "sourceData": {
+ "age": 28,
+ "gender": "female",
+ "city": "上海",
+ "productId": "P12345",
+ "pageUrl": "https://example.com/product/123"
+ },
+ "remark": "画像-基础属性",
+ "uniqueId": "user_13800000000_20250301_001"
+}
+```
+
+#### 3.3.2 字段详细说明
+
+| 字段名 | 类型 | 必填 | 说明 |
+|-----------------------|--------|------|----------------------------------------|
+| `portrait.type` | int | 否 | 画像类型,枚举值:
0-浏览
1-点击
2-下单/购买
3-注册
4-互动
默认值:0 |
+| `portrait.source` | int | 否 | 画像来源,枚举值:
0-本站
1-老油条
2-老坑爹
默认值:0 |
+| `portrait.sourceData` | object | 否 | 画像明细数据(键值对,会存储为 JSON 格式)
可包含任意业务相关的键值对,如:年龄、性别、城市、商品ID、页面URL等 |
+| `portrait.remark` | string | 否 | 画像备注信息,最大长度100字符 |
+| `portrait.uniqueId` | string | 否 | 画像去重用唯一 ID
用于防止重复记录,相同 `uniqueId` 的画像数据在半小时内会被合并统计(count字段累加)
建议格式:`{来源标识}_{用户标识}_{时间戳}_{序号}` |
+
+#### 3.3.3 画像类型(type)说明
+
+| 值 | 类型 | 说明 | 适用场景 |
+|---|------|------|---------|
+| 0 | 浏览 | 用户浏览了页面或内容 | 页面访问、商品浏览、文章阅读等 |
+| 1 | 点击 | 用户点击了某个元素 | 按钮点击、链接点击、广告点击等 |
+| 2 | 下单/购买 | 用户完成了购买行为 | 订单提交、支付完成等 |
+| 3 | 注册 | 用户完成了注册 | 账号注册、会员注册等 |
+| 4 | 互动 | 用户进行了互动行为 | 点赞、评论、分享、咨询等 |
+
+#### 3.3.4 画像来源(source)说明
+
+| 值 | 来源 | 说明 |
+|---|------|------|
+| 0 | 本站 | 来自本站的数据 |
+| 1 | 老油条 | 来自"老油条"系统的数据 |
+| 2 | 老坑爹 | 来自"老坑爹"系统的数据 |
+
+#### 3.3.5 sourceData 数据格式说明
+
+`sourceData` 是一个 JSON 对象,可以包含任意业务相关的键值对。常见字段示例:
+
+```json
+{
+ "age": 28,
+ "gender": "female",
+ "city": "上海",
+ "province": "上海市",
+ "productId": "P12345",
+ "productName": "商品名称",
+ "category": "女装",
+ "price": 299.00,
+ "pageUrl": "https://example.com/product/123",
+ "referrer": "https://www.baidu.com",
+ "device": "mobile",
+ "browser": "WeChat"
+}
+```
+
+> **注意**:
+> - `sourceData` 中的数据类型可以是字符串、数字、布尔值等
+> - 嵌套对象会被序列化为 JSON 字符串存储
+> - 建议根据实际业务需求定义字段结构
+
+#### 3.3.6 uniqueId 去重机制说明
+
+- **作用**:防止重复记录相同的画像数据
+- **规则**:相同 `uniqueId` 的画像数据在 **半小时内** 会被合并统计,`count` 字段会自动累加
+- **建议格式**:`{来源标识}_{用户标识}_{时间戳}_{序号}`
+ - 示例:`site_13800000000_1710000000_001`
+ - 示例:`wechat_wxid_abc123_1710000000_001`
+- **注意事项**:
+ - 如果不传 `uniqueId`,系统会为每条画像数据创建新记录
+ - 如果需要在半小时内多次统计同一行为,应使用相同的 `uniqueId`
+ - 如果需要在半小时后重新统计,应使用不同的 `uniqueId`(建议修改时间戳部分)
+
+> **重要提示**:`portrait` **整体不参与签名计算**,但会参与业务处理。系统会根据 `uniqueId` 自动处理去重和统计。
+
+---
+
+## 四、请求示例
+
+### 4.1 JSON 请求示例(无画像)
+
+```json
+{
+ "apiKey": "YOUR_API_KEY",
+ "timestamp": 1710000000,
+ "phone": "13800000000",
+ "name": "张三",
+ "source": "微信广告",
+ "remark": "通过H5落地页留资",
+ "tags": "高意向,电商",
+ "siteTags": "新客,女装",
+ "sign": "根据签名规则生成的MD5字符串"
+}
+```
+
+### 4.2 JSON 请求示例(带微信号与画像)
+
+```json
+{
+ "apiKey": "YOUR_API_KEY",
+ "timestamp": 1710000000,
+ "wechatId": "wxid_abcdefg123",
+ "phone": "13800000001",
+ "name": "李四",
+ "source": "小程序落地页",
+ "remark": "点击【立即咨询】按钮",
+ "tags": "中意向,直播",
+ "siteTags": "复购,高客单",
+ "portrait": {
+ "type": 1,
+ "source": 0,
+ "sourceData": {
+ "age": 28,
+ "gender": "female",
+ "city": "上海",
+ "pageUrl": "https://example.com/product/123",
+ "productId": "P12345"
+ },
+ "remark": "画像-点击行为",
+ "uniqueId": "site_13800000001_1710000000_001"
+ },
+ "sign": "根据签名规则生成的MD5字符串"
+}
+```
+
+### 4.3 JSON 请求示例(多种画像类型)
+
+#### 4.3.1 浏览行为画像
+
+```json
+{
+ "apiKey": "YOUR_API_KEY",
+ "timestamp": 1710000000,
+ "phone": "13800000002",
+ "name": "王五",
+ "source": "百度推广",
+ "portrait": {
+ "type": 0,
+ "source": 0,
+ "sourceData": {
+ "pageUrl": "https://example.com/product/456",
+ "productName": "商品名称",
+ "category": "女装",
+ "stayTime": 120,
+ "device": "mobile"
+ },
+ "remark": "商品浏览",
+ "uniqueId": "site_13800000002_1710000000_001"
+ },
+ "sign": "根据签名规则生成的MD5字符串"
+}
+```
+
+
+```
+
+---
+
+## 五、响应说明
+
+### 5.1 成功响应
+
+**1)新增线索成功**
+
+```json
+{
+ "code": 200,
+ "message": "新增成功",
+ "data": "13800000000"
+}
+```
+
+**2)线索已存在**
+
+```json
+{
+ "code": 200,
+ "message": "已存在",
+ "data": "13800000000"
+}
+```
+
+> `data` 字段返回本次线索的主标识 `wechatId` 或 `phone`。
+
+### 5.2 常见错误响应
+
+```json
+{ "code": 400, "message": "apiKey不能为空", "data": null }
+{ "code": 400, "message": "sign不能为空", "data": null }
+{ "code": 400, "message": "timestamp不能为空", "data": null }
+{ "code": 400, "message": "请求已过期", "data": null }
+
+{ "code": 401, "message": "无效的apiKey", "data": null }
+{ "code": 401, "message": "签名验证失败", "data": null }
+
+{ "code": 500, "message": "系统错误: 具体错误信息", "data": null }
+```
+
+---
+
+
+## 六、常见问题(FAQ)
+
+### Q1: 如果同一个用户多次上报相同的行为,会如何处理?
+
+**A**: 如果使用相同的 `uniqueId`,系统会在半小时内合并统计,`count` 字段会累加。如果使用不同的 `uniqueId`,会创建多条记录。
+
+### Q2: portrait 字段是否必须传递?
+
+**A**: 不是必须的。`portrait` 字段是可选的,只有在需要记录用户画像数据时才传递。
+
+### Q3: sourceData 中可以存储哪些类型的数据?
+
+**A**: `sourceData` 是一个 JSON 对象,可以存储任意键值对。支持字符串、数字、布尔值等基本类型,嵌套对象会被序列化为 JSON 字符串。
+
+### Q4: uniqueId 的作用是什么?
+
+**A**: `uniqueId` 用于防止重复记录。相同 `uniqueId` 的画像数据在半小时内会被合并统计,避免重复数据。
+
+### Q5: 画像数据如何与用户关联?
+
+**A**: 系统会根据请求中的 `wechatId` 或 `phone` 自动匹配 `traffic_pool` 表中的用户,并将画像数据关联到对应的 `trafficPoolId`。
+
+---
diff --git a/api/soul资源对接接口 copy.md b/api/soul资源对接接口 copy.md
new file mode 100644
index 00000000..7a1c2636
--- /dev/null
+++ b/api/soul资源对接接口 copy.md
@@ -0,0 +1,413 @@
+# 对外获客线索上报接口文档(V1)
+
+## 一、接口概述
+
+- **接口名称**:对外获客线索上报接口
+- **接口用途**:供第三方系统向【存客宝】上报客户线索(手机号 / 微信号等),用于后续的跟进、标签管理和画像分析。
+- **接口协议**:HTTP
+- **请求方式**:`POST`
+- **请求地址**: `https://ckbapi.quwanzhi.com/v1/api/scenarios`
+
+> 具体 URL 以实际环境配置为准。
+
+- **数据格式**:
+ - 推荐:`application/json`
+ - 兼容:`application/x-www-form-urlencoded`
+- **字符编码**:`UTF-8`
+
+---
+
+## 二、鉴权与签名
+
+### 2.1 必填鉴权字段
+
+| 字段名 | 类型 | 必填 | 说明 |
+|-------------|--------|------|---------------------------------------|
+| `apiKey` | string | 是 | 分配给第三方的接口密钥(每个任务唯一)|
+| `sign` | string | 是 | 签名值 |
+| `timestamp` | int | 是 | 秒级时间戳(与服务器时间差不超过 5 分钟) |
+
+### 2.2 时间戳校验
+
+服务器会校验 `timestamp` 是否在当前时间前后 **5 分钟** 内:
+
+- 通过条件:`|server_time - timestamp| <= 300`
+- 超出范围则返回:`请求已过期`
+
+### 2.3 签名生成规则
+
+接口采用自定义签名机制。**签名字段为 `sign`,生成步骤如下:**
+
+假设本次请求的所有参数为 `params`,其中包括业务参数 + `apiKey` + `timestamp` + `sign` + 可能存在的 `portrait` 对象。
+
+#### 第一步:移除特定字段
+
+从 `params` 中移除以下字段:
+
+- `sign` —— 自身不参与签名
+- `apiKey` —— 不参与参数拼接,仅在最后一步参与二次 MD5
+- `portrait` —— 整个画像对象不参与签名(即使内部还有子字段)
+
+> 说明:`portrait` 通常是一个 JSON 对象,字段较多,为避免签名实现复杂且双方难以对齐,统一不参与签名。
+
+#### 第二步:移除空值字段
+
+从剩余参数中,移除值为:
+
+- `null`
+- 空字符串 `''`
+
+的字段,这些字段不参与签名。
+
+#### 第三步:按参数名升序排序
+
+对剩余参数按**参数名(键名)升序排序**,排序规则为标准的 ASCII 升序:
+
+```text
+例如: name, phone, source, timestamp
+```
+
+#### 第四步:拼接参数值
+
+将排序后的参数 **只取“值”**,按顺序直接拼接为一个字符串,中间不加任何分隔符:
+
+- 示例:
+ 排序后参数为:
+
+ ```text
+ name = 张三
+ phone = 13800000000
+ source = 微信广告
+ timestamp = 1710000000
+ ```
+
+ 则拼接:
+
+ ```text
+ stringToSign = "张三13800000000微信广告1710000000"
+ ```
+
+#### 第五步:第一次 MD5
+
+对上一步拼接得到的字符串做一次 MD5:
+
+\[
+\text{firstMd5} = \text{MD5}(\text{stringToSign})
+\]
+
+#### 第六步:拼接 apiKey 再次 MD5
+
+将第一步的结果与 `apiKey` 直接拼接,再做一次 MD5,得到最终签名值:
+
+\[
+\text{sign} = \text{MD5}(\text{firstMd5} + \text{apiKey})
+\]
+
+#### 第七步:放入请求
+
+将第六步得到的 `sign` 填入请求参数中的 `sign` 字段即可。
+
+> 建议:
+> - 使用小写 MD5 字符串(双方约定统一即可)。
+> - 请确保参与签名的参数与最终请求发送的参数一致(包括是否传空值)。
+
+### 2.4 签名示例(PHP 伪代码)
+
+```php
+$params = [
+ 'apiKey' => 'YOUR_API_KEY',
+ 'timestamp' => '1710000000',
+ 'phone' => '13800000000',
+ 'name' => '张三',
+ 'source' => '微信广告',
+ 'remark' => '通过H5落地页留资',
+ // 'portrait' => [...], // 如有画像,这里会存在,但不参与签名
+ // 'sign' => '待生成',
+];
+
+// 1. 去掉 sign、apiKey、portrait
+unset($params['sign'], $params['apiKey'], $params['portrait']);
+
+// 2. 去掉空值
+$params = array_filter($params, function($value) {
+ return !is_null($value) && $value !== '';
+});
+
+// 3. 按键名升序排序
+ksort($params);
+
+// 4. 拼接参数值
+$stringToSign = implode('', array_values($params));
+
+// 5. 第一次 MD5
+$firstMd5 = md5($stringToSign);
+
+// 6. 第二次 MD5(拼接 apiKey)
+$apiKey = 'YOUR_API_KEY';
+$sign = md5($firstMd5 . $apiKey);
+
+// 将 $sign 作为字段发送
+$params['sign'] = $sign;
+```
+
+---
+
+## 三、请求参数说明
+
+### 3.1 主标识字段(至少传一个)
+
+| 字段名 | 类型 | 必填 | 说明 |
+|-----------|--------|------|-------------------------------------------|
+| `wechatId`| string | 否 | 微信号,存在时优先作为主标识 |
+| `phone` | string | 否 | 手机号,当 `wechatId` 为空时用作主标识 |
+
+### 3.2 基础信息字段
+
+| 字段名 | 类型 | 必填 | 说明 |
+|------------|--------|------|-------------------------|
+| `name` | string | 否 | 客户姓名 |
+| `source` | string | 否 | 线索来源描述,如“百度推广”、“抖音直播间” |
+| `remark` | string | 否 | 备注信息 |
+| `tags` | string | 否 | 逗号分隔的“微信标签”,如:`"高意向,电商,女装"` |
+| `siteTags` | string | 否 | 逗号分隔的“站内标签”,用于站内进一步细分 |
+
+
+### 3.3 用户画像字段 `portrait`(可选)
+
+`portrait` 为一个对象(JSON),用于记录用户的行为画像数据。
+
+#### 3.3.1 基本示例
+
+```json
+"portrait": {
+ "type": 1,
+ "source": 1,
+ "sourceData": {
+ "age": 28,
+ "gender": "female",
+ "city": "上海",
+ "productId": "P12345",
+ "pageUrl": "https://example.com/product/123"
+ },
+ "remark": "画像-基础属性",
+ "uniqueId": "user_13800000000_20250301_001"
+}
+```
+
+#### 3.3.2 字段详细说明
+
+| 字段名 | 类型 | 必填 | 说明 |
+|-----------------------|--------|------|----------------------------------------|
+| `portrait.type` | int | 否 | 画像类型,枚举值:
0-浏览
1-点击
2-下单/购买
3-注册
4-互动
默认值:0 |
+| `portrait.source` | int | 否 | 画像来源,枚举值:
0-本站
1-老油条
2-老坑爹
默认值:0 |
+| `portrait.sourceData` | object | 否 | 画像明细数据(键值对,会存储为 JSON 格式)
可包含任意业务相关的键值对,如:年龄、性别、城市、商品ID、页面URL等 |
+| `portrait.remark` | string | 否 | 画像备注信息,最大长度100字符 |
+| `portrait.uniqueId` | string | 否 | 画像去重用唯一 ID
用于防止重复记录,相同 `uniqueId` 的画像数据在半小时内会被合并统计(count字段累加)
建议格式:`{来源标识}_{用户标识}_{时间戳}_{序号}` |
+
+#### 3.3.3 画像类型(type)说明
+
+| 值 | 类型 | 说明 | 适用场景 |
+|---|------|------|---------|
+| 0 | 浏览 | 用户浏览了页面或内容 | 页面访问、商品浏览、文章阅读等 |
+| 1 | 点击 | 用户点击了某个元素 | 按钮点击、链接点击、广告点击等 |
+| 2 | 下单/购买 | 用户完成了购买行为 | 订单提交、支付完成等 |
+| 3 | 注册 | 用户完成了注册 | 账号注册、会员注册等 |
+| 4 | 互动 | 用户进行了互动行为 | 点赞、评论、分享、咨询等 |
+
+#### 3.3.4 画像来源(source)说明
+
+| 值 | 来源 | 说明 |
+|---|------|------|
+| 0 | 本站 | 来自本站的数据 |
+| 1 | 老油条 | 来自"老油条"系统的数据 |
+| 2 | 老坑爹 | 来自"老坑爹"系统的数据 |
+
+#### 3.3.5 sourceData 数据格式说明
+
+`sourceData` 是一个 JSON 对象,可以包含任意业务相关的键值对。常见字段示例:
+
+```json
+{
+ "age": 28,
+ "gender": "female",
+ "city": "上海",
+ "province": "上海市",
+ "productId": "P12345",
+ "productName": "商品名称",
+ "category": "女装",
+ "price": 299.00,
+ "pageUrl": "https://example.com/product/123",
+ "referrer": "https://www.baidu.com",
+ "device": "mobile",
+ "browser": "WeChat"
+}
+```
+
+> **注意**:
+> - `sourceData` 中的数据类型可以是字符串、数字、布尔值等
+> - 嵌套对象会被序列化为 JSON 字符串存储
+> - 建议根据实际业务需求定义字段结构
+
+#### 3.3.6 uniqueId 去重机制说明
+
+- **作用**:防止重复记录相同的画像数据
+- **规则**:相同 `uniqueId` 的画像数据在 **半小时内** 会被合并统计,`count` 字段会自动累加
+- **建议格式**:`{来源标识}_{用户标识}_{时间戳}_{序号}`
+ - 示例:`site_13800000000_1710000000_001`
+ - 示例:`wechat_wxid_abc123_1710000000_001`
+- **注意事项**:
+ - 如果不传 `uniqueId`,系统会为每条画像数据创建新记录
+ - 如果需要在半小时内多次统计同一行为,应使用相同的 `uniqueId`
+ - 如果需要在半小时后重新统计,应使用不同的 `uniqueId`(建议修改时间戳部分)
+
+> **重要提示**:`portrait` **整体不参与签名计算**,但会参与业务处理。系统会根据 `uniqueId` 自动处理去重和统计。
+
+---
+
+## 四、请求示例
+
+### 4.1 JSON 请求示例(无画像)
+
+```json
+{
+ "apiKey": "YOUR_API_KEY",
+ "timestamp": 1710000000,
+ "phone": "13800000000",
+ "name": "张三",
+ "source": "微信广告",
+ "remark": "通过H5落地页留资",
+ "tags": "高意向,电商",
+ "siteTags": "新客,女装",
+ "sign": "根据签名规则生成的MD5字符串"
+}
+```
+
+### 4.2 JSON 请求示例(带微信号与画像)
+
+```json
+{
+ "apiKey": "YOUR_API_KEY",
+ "timestamp": 1710000000,
+ "wechatId": "wxid_abcdefg123",
+ "phone": "13800000001",
+ "name": "李四",
+ "source": "小程序落地页",
+ "remark": "点击【立即咨询】按钮",
+ "tags": "中意向,直播",
+ "siteTags": "复购,高客单",
+ "portrait": {
+ "type": 1,
+ "source": 0,
+ "sourceData": {
+ "age": 28,
+ "gender": "female",
+ "city": "上海",
+ "pageUrl": "https://example.com/product/123",
+ "productId": "P12345"
+ },
+ "remark": "画像-点击行为",
+ "uniqueId": "site_13800000001_1710000000_001"
+ },
+ "sign": "根据签名规则生成的MD5字符串"
+}
+```
+
+### 4.3 JSON 请求示例(多种画像类型)
+
+#### 4.3.1 浏览行为画像
+
+```json
+{
+ "apiKey": "YOUR_API_KEY",
+ "timestamp": 1710000000,
+ "phone": "13800000002",
+ "name": "王五",
+ "source": "百度推广",
+ "portrait": {
+ "type": 0,
+ "source": 0,
+ "sourceData": {
+ "pageUrl": "https://example.com/product/456",
+ "productName": "商品名称",
+ "category": "女装",
+ "stayTime": 120,
+ "device": "mobile"
+ },
+ "remark": "商品浏览",
+ "uniqueId": "site_13800000002_1710000000_001"
+ },
+ "sign": "根据签名规则生成的MD5字符串"
+}
+```
+
+
+```
+
+---
+
+## 五、响应说明
+
+### 5.1 成功响应
+
+**1)新增线索成功**
+
+```json
+{
+ "code": 200,
+ "message": "新增成功",
+ "data": "13800000000"
+}
+```
+
+**2)线索已存在**
+
+```json
+{
+ "code": 200,
+ "message": "已存在",
+ "data": "13800000000"
+}
+```
+
+> `data` 字段返回本次线索的主标识 `wechatId` 或 `phone`。
+
+### 5.2 常见错误响应
+
+```json
+{ "code": 400, "message": "apiKey不能为空", "data": null }
+{ "code": 400, "message": "sign不能为空", "data": null }
+{ "code": 400, "message": "timestamp不能为空", "data": null }
+{ "code": 400, "message": "请求已过期", "data": null }
+
+{ "code": 401, "message": "无效的apiKey", "data": null }
+{ "code": 401, "message": "签名验证失败", "data": null }
+
+{ "code": 500, "message": "系统错误: 具体错误信息", "data": null }
+```
+
+---
+
+
+## 六、常见问题(FAQ)
+
+### Q1: 如果同一个用户多次上报相同的行为,会如何处理?
+
+**A**: 如果使用相同的 `uniqueId`,系统会在半小时内合并统计,`count` 字段会累加。如果使用不同的 `uniqueId`,会创建多条记录。
+
+### Q2: portrait 字段是否必须传递?
+
+**A**: 不是必须的。`portrait` 字段是可选的,只有在需要记录用户画像数据时才传递。
+
+### Q3: sourceData 中可以存储哪些类型的数据?
+
+**A**: `sourceData` 是一个 JSON 对象,可以存储任意键值对。支持字符串、数字、布尔值等基本类型,嵌套对象会被序列化为 JSON 字符串。
+
+### Q4: uniqueId 的作用是什么?
+
+**A**: `uniqueId` 用于防止重复记录。相同 `uniqueId` 的画像数据在半小时内会被合并统计,避免重复数据。
+
+### Q5: 画像数据如何与用户关联?
+
+**A**: 系统会根据请求中的 `wechatId` 或 `phone` 自动匹配 `traffic_pool` 表中的用户,并将画像数据关联到对应的 `trafficPoolId`。
+
+---
diff --git a/api/soul资源对接接口.md b/api/soul资源对接接口.md
new file mode 100644
index 00000000..7a1c2636
--- /dev/null
+++ b/api/soul资源对接接口.md
@@ -0,0 +1,413 @@
+# 对外获客线索上报接口文档(V1)
+
+## 一、接口概述
+
+- **接口名称**:对外获客线索上报接口
+- **接口用途**:供第三方系统向【存客宝】上报客户线索(手机号 / 微信号等),用于后续的跟进、标签管理和画像分析。
+- **接口协议**:HTTP
+- **请求方式**:`POST`
+- **请求地址**: `https://ckbapi.quwanzhi.com/v1/api/scenarios`
+
+> 具体 URL 以实际环境配置为准。
+
+- **数据格式**:
+ - 推荐:`application/json`
+ - 兼容:`application/x-www-form-urlencoded`
+- **字符编码**:`UTF-8`
+
+---
+
+## 二、鉴权与签名
+
+### 2.1 必填鉴权字段
+
+| 字段名 | 类型 | 必填 | 说明 |
+|-------------|--------|------|---------------------------------------|
+| `apiKey` | string | 是 | 分配给第三方的接口密钥(每个任务唯一)|
+| `sign` | string | 是 | 签名值 |
+| `timestamp` | int | 是 | 秒级时间戳(与服务器时间差不超过 5 分钟) |
+
+### 2.2 时间戳校验
+
+服务器会校验 `timestamp` 是否在当前时间前后 **5 分钟** 内:
+
+- 通过条件:`|server_time - timestamp| <= 300`
+- 超出范围则返回:`请求已过期`
+
+### 2.3 签名生成规则
+
+接口采用自定义签名机制。**签名字段为 `sign`,生成步骤如下:**
+
+假设本次请求的所有参数为 `params`,其中包括业务参数 + `apiKey` + `timestamp` + `sign` + 可能存在的 `portrait` 对象。
+
+#### 第一步:移除特定字段
+
+从 `params` 中移除以下字段:
+
+- `sign` —— 自身不参与签名
+- `apiKey` —— 不参与参数拼接,仅在最后一步参与二次 MD5
+- `portrait` —— 整个画像对象不参与签名(即使内部还有子字段)
+
+> 说明:`portrait` 通常是一个 JSON 对象,字段较多,为避免签名实现复杂且双方难以对齐,统一不参与签名。
+
+#### 第二步:移除空值字段
+
+从剩余参数中,移除值为:
+
+- `null`
+- 空字符串 `''`
+
+的字段,这些字段不参与签名。
+
+#### 第三步:按参数名升序排序
+
+对剩余参数按**参数名(键名)升序排序**,排序规则为标准的 ASCII 升序:
+
+```text
+例如: name, phone, source, timestamp
+```
+
+#### 第四步:拼接参数值
+
+将排序后的参数 **只取“值”**,按顺序直接拼接为一个字符串,中间不加任何分隔符:
+
+- 示例:
+ 排序后参数为:
+
+ ```text
+ name = 张三
+ phone = 13800000000
+ source = 微信广告
+ timestamp = 1710000000
+ ```
+
+ 则拼接:
+
+ ```text
+ stringToSign = "张三13800000000微信广告1710000000"
+ ```
+
+#### 第五步:第一次 MD5
+
+对上一步拼接得到的字符串做一次 MD5:
+
+\[
+\text{firstMd5} = \text{MD5}(\text{stringToSign})
+\]
+
+#### 第六步:拼接 apiKey 再次 MD5
+
+将第一步的结果与 `apiKey` 直接拼接,再做一次 MD5,得到最终签名值:
+
+\[
+\text{sign} = \text{MD5}(\text{firstMd5} + \text{apiKey})
+\]
+
+#### 第七步:放入请求
+
+将第六步得到的 `sign` 填入请求参数中的 `sign` 字段即可。
+
+> 建议:
+> - 使用小写 MD5 字符串(双方约定统一即可)。
+> - 请确保参与签名的参数与最终请求发送的参数一致(包括是否传空值)。
+
+### 2.4 签名示例(PHP 伪代码)
+
+```php
+$params = [
+ 'apiKey' => 'YOUR_API_KEY',
+ 'timestamp' => '1710000000',
+ 'phone' => '13800000000',
+ 'name' => '张三',
+ 'source' => '微信广告',
+ 'remark' => '通过H5落地页留资',
+ // 'portrait' => [...], // 如有画像,这里会存在,但不参与签名
+ // 'sign' => '待生成',
+];
+
+// 1. 去掉 sign、apiKey、portrait
+unset($params['sign'], $params['apiKey'], $params['portrait']);
+
+// 2. 去掉空值
+$params = array_filter($params, function($value) {
+ return !is_null($value) && $value !== '';
+});
+
+// 3. 按键名升序排序
+ksort($params);
+
+// 4. 拼接参数值
+$stringToSign = implode('', array_values($params));
+
+// 5. 第一次 MD5
+$firstMd5 = md5($stringToSign);
+
+// 6. 第二次 MD5(拼接 apiKey)
+$apiKey = 'YOUR_API_KEY';
+$sign = md5($firstMd5 . $apiKey);
+
+// 将 $sign 作为字段发送
+$params['sign'] = $sign;
+```
+
+---
+
+## 三、请求参数说明
+
+### 3.1 主标识字段(至少传一个)
+
+| 字段名 | 类型 | 必填 | 说明 |
+|-----------|--------|------|-------------------------------------------|
+| `wechatId`| string | 否 | 微信号,存在时优先作为主标识 |
+| `phone` | string | 否 | 手机号,当 `wechatId` 为空时用作主标识 |
+
+### 3.2 基础信息字段
+
+| 字段名 | 类型 | 必填 | 说明 |
+|------------|--------|------|-------------------------|
+| `name` | string | 否 | 客户姓名 |
+| `source` | string | 否 | 线索来源描述,如“百度推广”、“抖音直播间” |
+| `remark` | string | 否 | 备注信息 |
+| `tags` | string | 否 | 逗号分隔的“微信标签”,如:`"高意向,电商,女装"` |
+| `siteTags` | string | 否 | 逗号分隔的“站内标签”,用于站内进一步细分 |
+
+
+### 3.3 用户画像字段 `portrait`(可选)
+
+`portrait` 为一个对象(JSON),用于记录用户的行为画像数据。
+
+#### 3.3.1 基本示例
+
+```json
+"portrait": {
+ "type": 1,
+ "source": 1,
+ "sourceData": {
+ "age": 28,
+ "gender": "female",
+ "city": "上海",
+ "productId": "P12345",
+ "pageUrl": "https://example.com/product/123"
+ },
+ "remark": "画像-基础属性",
+ "uniqueId": "user_13800000000_20250301_001"
+}
+```
+
+#### 3.3.2 字段详细说明
+
+| 字段名 | 类型 | 必填 | 说明 |
+|-----------------------|--------|------|----------------------------------------|
+| `portrait.type` | int | 否 | 画像类型,枚举值:
0-浏览
1-点击
2-下单/购买
3-注册
4-互动
默认值:0 |
+| `portrait.source` | int | 否 | 画像来源,枚举值:
0-本站
1-老油条
2-老坑爹
默认值:0 |
+| `portrait.sourceData` | object | 否 | 画像明细数据(键值对,会存储为 JSON 格式)
可包含任意业务相关的键值对,如:年龄、性别、城市、商品ID、页面URL等 |
+| `portrait.remark` | string | 否 | 画像备注信息,最大长度100字符 |
+| `portrait.uniqueId` | string | 否 | 画像去重用唯一 ID
用于防止重复记录,相同 `uniqueId` 的画像数据在半小时内会被合并统计(count字段累加)
建议格式:`{来源标识}_{用户标识}_{时间戳}_{序号}` |
+
+#### 3.3.3 画像类型(type)说明
+
+| 值 | 类型 | 说明 | 适用场景 |
+|---|------|------|---------|
+| 0 | 浏览 | 用户浏览了页面或内容 | 页面访问、商品浏览、文章阅读等 |
+| 1 | 点击 | 用户点击了某个元素 | 按钮点击、链接点击、广告点击等 |
+| 2 | 下单/购买 | 用户完成了购买行为 | 订单提交、支付完成等 |
+| 3 | 注册 | 用户完成了注册 | 账号注册、会员注册等 |
+| 4 | 互动 | 用户进行了互动行为 | 点赞、评论、分享、咨询等 |
+
+#### 3.3.4 画像来源(source)说明
+
+| 值 | 来源 | 说明 |
+|---|------|------|
+| 0 | 本站 | 来自本站的数据 |
+| 1 | 老油条 | 来自"老油条"系统的数据 |
+| 2 | 老坑爹 | 来自"老坑爹"系统的数据 |
+
+#### 3.3.5 sourceData 数据格式说明
+
+`sourceData` 是一个 JSON 对象,可以包含任意业务相关的键值对。常见字段示例:
+
+```json
+{
+ "age": 28,
+ "gender": "female",
+ "city": "上海",
+ "province": "上海市",
+ "productId": "P12345",
+ "productName": "商品名称",
+ "category": "女装",
+ "price": 299.00,
+ "pageUrl": "https://example.com/product/123",
+ "referrer": "https://www.baidu.com",
+ "device": "mobile",
+ "browser": "WeChat"
+}
+```
+
+> **注意**:
+> - `sourceData` 中的数据类型可以是字符串、数字、布尔值等
+> - 嵌套对象会被序列化为 JSON 字符串存储
+> - 建议根据实际业务需求定义字段结构
+
+#### 3.3.6 uniqueId 去重机制说明
+
+- **作用**:防止重复记录相同的画像数据
+- **规则**:相同 `uniqueId` 的画像数据在 **半小时内** 会被合并统计,`count` 字段会自动累加
+- **建议格式**:`{来源标识}_{用户标识}_{时间戳}_{序号}`
+ - 示例:`site_13800000000_1710000000_001`
+ - 示例:`wechat_wxid_abc123_1710000000_001`
+- **注意事项**:
+ - 如果不传 `uniqueId`,系统会为每条画像数据创建新记录
+ - 如果需要在半小时内多次统计同一行为,应使用相同的 `uniqueId`
+ - 如果需要在半小时后重新统计,应使用不同的 `uniqueId`(建议修改时间戳部分)
+
+> **重要提示**:`portrait` **整体不参与签名计算**,但会参与业务处理。系统会根据 `uniqueId` 自动处理去重和统计。
+
+---
+
+## 四、请求示例
+
+### 4.1 JSON 请求示例(无画像)
+
+```json
+{
+ "apiKey": "YOUR_API_KEY",
+ "timestamp": 1710000000,
+ "phone": "13800000000",
+ "name": "张三",
+ "source": "微信广告",
+ "remark": "通过H5落地页留资",
+ "tags": "高意向,电商",
+ "siteTags": "新客,女装",
+ "sign": "根据签名规则生成的MD5字符串"
+}
+```
+
+### 4.2 JSON 请求示例(带微信号与画像)
+
+```json
+{
+ "apiKey": "YOUR_API_KEY",
+ "timestamp": 1710000000,
+ "wechatId": "wxid_abcdefg123",
+ "phone": "13800000001",
+ "name": "李四",
+ "source": "小程序落地页",
+ "remark": "点击【立即咨询】按钮",
+ "tags": "中意向,直播",
+ "siteTags": "复购,高客单",
+ "portrait": {
+ "type": 1,
+ "source": 0,
+ "sourceData": {
+ "age": 28,
+ "gender": "female",
+ "city": "上海",
+ "pageUrl": "https://example.com/product/123",
+ "productId": "P12345"
+ },
+ "remark": "画像-点击行为",
+ "uniqueId": "site_13800000001_1710000000_001"
+ },
+ "sign": "根据签名规则生成的MD5字符串"
+}
+```
+
+### 4.3 JSON 请求示例(多种画像类型)
+
+#### 4.3.1 浏览行为画像
+
+```json
+{
+ "apiKey": "YOUR_API_KEY",
+ "timestamp": 1710000000,
+ "phone": "13800000002",
+ "name": "王五",
+ "source": "百度推广",
+ "portrait": {
+ "type": 0,
+ "source": 0,
+ "sourceData": {
+ "pageUrl": "https://example.com/product/456",
+ "productName": "商品名称",
+ "category": "女装",
+ "stayTime": 120,
+ "device": "mobile"
+ },
+ "remark": "商品浏览",
+ "uniqueId": "site_13800000002_1710000000_001"
+ },
+ "sign": "根据签名规则生成的MD5字符串"
+}
+```
+
+
+```
+
+---
+
+## 五、响应说明
+
+### 5.1 成功响应
+
+**1)新增线索成功**
+
+```json
+{
+ "code": 200,
+ "message": "新增成功",
+ "data": "13800000000"
+}
+```
+
+**2)线索已存在**
+
+```json
+{
+ "code": 200,
+ "message": "已存在",
+ "data": "13800000000"
+}
+```
+
+> `data` 字段返回本次线索的主标识 `wechatId` 或 `phone`。
+
+### 5.2 常见错误响应
+
+```json
+{ "code": 400, "message": "apiKey不能为空", "data": null }
+{ "code": 400, "message": "sign不能为空", "data": null }
+{ "code": 400, "message": "timestamp不能为空", "data": null }
+{ "code": 400, "message": "请求已过期", "data": null }
+
+{ "code": 401, "message": "无效的apiKey", "data": null }
+{ "code": 401, "message": "签名验证失败", "data": null }
+
+{ "code": 500, "message": "系统错误: 具体错误信息", "data": null }
+```
+
+---
+
+
+## 六、常见问题(FAQ)
+
+### Q1: 如果同一个用户多次上报相同的行为,会如何处理?
+
+**A**: 如果使用相同的 `uniqueId`,系统会在半小时内合并统计,`count` 字段会累加。如果使用不同的 `uniqueId`,会创建多条记录。
+
+### Q2: portrait 字段是否必须传递?
+
+**A**: 不是必须的。`portrait` 字段是可选的,只有在需要记录用户画像数据时才传递。
+
+### Q3: sourceData 中可以存储哪些类型的数据?
+
+**A**: `sourceData` 是一个 JSON 对象,可以存储任意键值对。支持字符串、数字、布尔值等基本类型,嵌套对象会被序列化为 JSON 字符串。
+
+### Q4: uniqueId 的作用是什么?
+
+**A**: `uniqueId` 用于防止重复记录。相同 `uniqueId` 的画像数据在半小时内会被合并统计,避免重复数据。
+
+### Q5: 画像数据如何与用户关联?
+
+**A**: 系统会根据请求中的 `wechatId` 或 `phone` 自动匹配 `traffic_pool` 表中的用户,并将画像数据关联到对应的 `trafficPoolId`。
+
+---
diff --git a/app/about/page.tsx b/app/about/page.tsx
index 54b6c246..bcb94105 100644
--- a/app/about/page.tsx
+++ b/app/about/page.tsx
@@ -26,12 +26,12 @@ export default function AboutPage() {
]
const milestones = [
- { year: "2012", event: "开始做游戏推广,从魔兽世界外挂代理起步" },
- { year: "2015", event: "转型电商,做天猫虚拟充值,月流水380万" },
- { year: "2017", event: "团队扩张到200人,年流水3000万" },
- { year: "2018", event: "公司破产,负债数百万,开始全国旅行反思" },
- { year: "2019", event: "重新出发,专注私域运营和个人IP" },
- { year: "2024", event: "在Soul派对房每日直播,分享真实商业故事" },
+ { year: "2007-2014", event: "游戏电竞创业历程,从魔兽世界代练起步" },
+ { year: "2015", event: "转型电商,做天猫虚拟充值" },
+ { year: "2016-2019", event: "深耕电商领域,团队扩张到200人,年流水3000万" },
+ { year: "2019-2020", event: "公司变故,重整旗鼓" },
+ { year: "2020-2025", event: "电竞、地摊、大健康、私域多领域探索" },
+ { year: "2025.10.15", event: "在Soul派对房开启每日分享,记录真实商业案例" },
]
return (
diff --git a/app/admin/content/page.tsx b/app/admin/content/page.tsx
index 2da17e9b..3b0b44fa 100644
--- a/app/admin/content/page.tsx
+++ b/app/admin/content/page.tsx
@@ -1,6 +1,6 @@
"use client"
-import { useState } from "react"
+import { useState, useRef } from "react"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
@@ -22,6 +22,10 @@ import {
X,
RefreshCw,
Link2,
+ Download,
+ Upload,
+ Eye,
+ Database,
} from "lucide-react"
interface EditingSection {
@@ -29,14 +33,22 @@ interface EditingSection {
title: string
price: number
content?: string
+ filePath?: string
}
export default function ContentPage() {
const [expandedParts, setExpandedParts] = useState(["part-1"])
const [editingSection, setEditingSection] = useState(null)
const [isSyncing, setIsSyncing] = useState(false)
+ const [isExporting, setIsExporting] = useState(false)
+ const [isImporting, setIsImporting] = useState(false)
+ const [isInitializing, setIsInitializing] = useState(false)
const [feishuDocUrl, setFeishuDocUrl] = useState("")
const [showFeishuModal, setShowFeishuModal] = useState(false)
+ const [showImportModal, setShowImportModal] = useState(false)
+ const [importData, setImportData] = useState("")
+ const [isLoadingContent, setIsLoadingContent] = useState(false)
+ const fileInputRef = useRef(null)
const togglePart = (partId: string) => {
setExpandedParts((prev) => (prev.includes(partId) ? prev.filter((id) => id !== partId) : [...prev, partId]))
@@ -47,21 +59,257 @@ export default function ContentPage() {
0,
)
- const handleEditSection = (section: { id: string; title: string; price: number }) => {
- setEditingSection({
- id: section.id,
- title: section.title,
- price: section.price,
- content: "",
- })
+ // 读取章节内容
+ const handleReadSection = async (section: { id: string; title: string; price: number; filePath: string }) => {
+ setIsLoadingContent(true)
+ try {
+ const res = await fetch(`/api/db/book?action=read&id=${section.id}`)
+ const data = await res.json()
+
+ if (data.success) {
+ setEditingSection({
+ id: section.id,
+ title: section.title,
+ price: section.price,
+ content: data.section.content || "",
+ filePath: section.filePath,
+ })
+ } else {
+ // 如果API失败,设置空内容
+ setEditingSection({
+ id: section.id,
+ title: section.title,
+ price: section.price,
+ content: "",
+ filePath: section.filePath,
+ })
+ alert("无法读取文件内容: " + (data.error || "未知错误"))
+ }
+ } catch (error) {
+ console.error("Read section error:", error)
+ setEditingSection({
+ id: section.id,
+ title: section.title,
+ price: section.price,
+ content: "",
+ filePath: section.filePath,
+ })
+ } finally {
+ setIsLoadingContent(false)
+ }
}
- const handleSaveSection = () => {
- if (editingSection) {
- // 保存到本地存储或API
- console.log("[v0] Saving section:", editingSection)
- alert(`已保存章节: ${editingSection.title}`)
- setEditingSection(null)
+ // 保存章节
+ const handleSaveSection = async () => {
+ if (!editingSection) return
+
+ try {
+ const res = await fetch('/api/db/book', {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ id: editingSection.id,
+ title: editingSection.title,
+ price: editingSection.price,
+ content: editingSection.content,
+ saveToFile: true, // 同时保存到文件系统
+ })
+ })
+
+ const data = await res.json()
+ if (data.success) {
+ alert(`已保存章节: ${editingSection.title}`)
+ setEditingSection(null)
+ } else {
+ alert("保存失败: " + (data.error || "未知错误"))
+ }
+ } catch (error) {
+ console.error("Save section error:", error)
+ alert("保存失败")
+ }
+ }
+
+ // 同步到数据库
+ const handleSyncToDatabase = async () => {
+ setIsSyncing(true)
+ try {
+ const res = await fetch('/api/db/book', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ action: 'sync' })
+ })
+
+ const data = await res.json()
+ if (data.success) {
+ alert(data.message)
+ } else {
+ alert("同步失败: " + (data.error || "未知错误"))
+ }
+ } catch (error) {
+ console.error("Sync error:", error)
+ alert("同步失败")
+ } finally {
+ setIsSyncing(false)
+ }
+ }
+
+ // 导出所有章节
+ const handleExport = async () => {
+ setIsExporting(true)
+ try {
+ const res = await fetch('/api/db/book?action=export')
+ const blob = await res.blob()
+
+ const url = window.URL.createObjectURL(blob)
+ const a = document.createElement('a')
+ a.href = url
+ a.download = `book_sections_${new Date().toISOString().split('T')[0]}.json`
+ document.body.appendChild(a)
+ a.click()
+ window.URL.revokeObjectURL(url)
+ document.body.removeChild(a)
+
+ alert("导出成功")
+ } catch (error) {
+ console.error("Export error:", error)
+ alert("导出失败")
+ } finally {
+ setIsExporting(false)
+ }
+ }
+
+ // 导入章节
+ const handleImport = async () => {
+ if (!importData) {
+ alert("请输入或上传JSON数据")
+ return
+ }
+
+ setIsImporting(true)
+ try {
+ const data = JSON.parse(importData)
+ const res = await fetch('/api/db/book', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ action: 'import', data })
+ })
+
+ const result = await res.json()
+ if (result.success) {
+ alert(result.message)
+ setShowImportModal(false)
+ setImportData("")
+ } else {
+ alert("导入失败: " + (result.error || "未知错误"))
+ }
+ } catch (error) {
+ console.error("Import error:", error)
+ alert("导入失败: JSON格式错误")
+ } finally {
+ setIsImporting(false)
+ }
+ }
+
+ // 文件上传
+ const handleFileUpload = (e: React.ChangeEvent) => {
+ const file = e.target.files?.[0]
+ if (!file) return
+
+ const reader = new FileReader()
+ reader.onload = (event) => {
+ const content = event.target?.result as string
+ const fileName = file.name.toLowerCase()
+
+ // 根据文件类型处理
+ if (fileName.endsWith('.json')) {
+ // JSON文件直接使用
+ setImportData(content)
+ } else if (fileName.endsWith('.txt') || fileName.endsWith('.md') || fileName.endsWith('.markdown')) {
+ // TXT/MD文件自动解析为JSON格式
+ const parsedData = parseTxtToJson(content, file.name)
+ setImportData(JSON.stringify(parsedData, null, 2))
+ } else {
+ setImportData(content)
+ }
+ }
+ reader.readAsText(file)
+ }
+
+ // 解析TXT/MD文件为JSON格式
+ const parseTxtToJson = (content: string, fileName: string) => {
+ const lines = content.split('\n')
+ const sections: any[] = []
+ let currentSection: any = null
+ let currentContent: string[] = []
+ let sectionIndex = 1
+
+ for (const line of lines) {
+ // 检测标题行(以#开头或数字+点开头)
+ const titleMatch = line.match(/^#+\s+(.+)$/) || line.match(/^(\d+[\.\、]\s*.+)$/)
+
+ if (titleMatch) {
+ // 保存前一个章节
+ if (currentSection) {
+ currentSection.content = currentContent.join('\n').trim()
+ if (currentSection.content) {
+ sections.push(currentSection)
+ }
+ }
+
+ // 开始新章节
+ currentSection = {
+ id: `import-${sectionIndex}`,
+ title: titleMatch[1].replace(/^#+\s*/, '').trim(),
+ price: 1,
+ is_free: sectionIndex <= 3, // 前3章免费
+ }
+ currentContent = []
+ sectionIndex++
+ } else if (currentSection) {
+ currentContent.push(line)
+ } else if (line.trim()) {
+ // 没有标题但有内容,创建默认章节
+ currentSection = {
+ id: `import-${sectionIndex}`,
+ title: fileName.replace(/\.(txt|md|markdown)$/i, ''),
+ price: 1,
+ is_free: true,
+ }
+ currentContent.push(line)
+ sectionIndex++
+ }
+ }
+
+ // 保存最后一个章节
+ if (currentSection) {
+ currentSection.content = currentContent.join('\n').trim()
+ if (currentSection.content) {
+ sections.push(currentSection)
+ }
+ }
+
+ return sections
+ }
+
+ // 初始化数据库
+ const handleInitDatabase = async () => {
+ if (!confirm("确定要初始化数据库吗?这将创建所有必需的表结构。")) return
+
+ setIsInitializing(true)
+ try {
+ const res = await fetch('/api/db/init', { method: 'POST' })
+ const data = await res.json()
+
+ if (data.success) {
+ alert(data.message)
+ } else {
+ alert("初始化失败: " + (data.error || "未知错误"))
+ }
+ } catch (error) {
+ console.error("Init database error:", error)
+ alert("初始化失败")
+ } finally {
+ setIsInitializing(false)
}
}
@@ -71,7 +319,6 @@ export default function ContentPage() {
return
}
setIsSyncing(true)
- // 模拟同步过程
await new Promise((resolve) => setTimeout(resolve, 2000))
setIsSyncing(false)
setShowFeishuModal(false)
@@ -87,12 +334,123 @@ export default function ContentPage() {
共 {bookData.length} 篇 · {totalSections} 节内容
-
+
+
+
+
+
+
+
+ {/* 导入弹窗 */}
+
+
{/* 飞书同步弹窗 */}