14 changed files with 1537 additions and 15 deletions
@ -0,0 +1,190 @@ |
|||
# 数据库字段缺失问题修复指南 |
|||
|
|||
## 🐛 问题描述 |
|||
|
|||
错误信息: |
|||
``` |
|||
java.sql.SQLSyntaxErrorException: Unknown column 'goods_id' in 'field list' |
|||
``` |
|||
|
|||
**原因**: 数据库表 `shop_coupon_apply_item` 中缺少 `goods_id` 和 `category_id` 字段,但代码中尝试查询这些字段。 |
|||
|
|||
## 🔧 解决方案 |
|||
|
|||
### 方案一:执行数据库修复脚本(推荐) |
|||
|
|||
1. **备份数据库**(重要!) |
|||
```bash |
|||
mysqldump -u username -p database_name > backup_$(date +%Y%m%d_%H%M%S).sql |
|||
``` |
|||
|
|||
2. **执行修复脚本** |
|||
```bash |
|||
mysql -u username -p database_name < src/main/resources/sql/simple_fix_coupon_table.sql |
|||
``` |
|||
|
|||
或者手动执行以下SQL: |
|||
```sql |
|||
-- 添加缺失的字段 |
|||
ALTER TABLE shop_coupon_apply_item |
|||
ADD COLUMN goods_id INT(11) NULL COMMENT '商品ID' AFTER coupon_id; |
|||
|
|||
ALTER TABLE shop_coupon_apply_item |
|||
ADD COLUMN category_id INT(11) NULL COMMENT '分类ID' AFTER goods_id; |
|||
|
|||
-- 添加索引 |
|||
CREATE INDEX idx_coupon_apply_item_goods ON shop_coupon_apply_item(coupon_id, goods_id); |
|||
CREATE INDEX idx_coupon_apply_item_category ON shop_coupon_apply_item(coupon_id, category_id); |
|||
CREATE INDEX idx_coupon_apply_item_type ON shop_coupon_apply_item(coupon_id, type); |
|||
|
|||
-- 检查表结构 |
|||
DESCRIBE shop_coupon_apply_item; |
|||
``` |
|||
|
|||
### 方案二:临时代码修复(已实施) |
|||
|
|||
我已经修改了 `CouponStatusServiceImpl.java` 中的代码,添加了异常处理: |
|||
|
|||
```java |
|||
try { |
|||
// 尝试查询 goods_id 字段 |
|||
List<ShopCouponApplyItem> applyItems = shopCouponApplyItemService.list(...); |
|||
// 处理逻辑 |
|||
} catch (Exception e) { |
|||
log.warn("查询优惠券适用商品失败,可能是数据库字段不存在: {}", e.getMessage()); |
|||
// 如果查询失败,默认返回true(允许使用) |
|||
return true; |
|||
} |
|||
``` |
|||
|
|||
## 📋 修复步骤 |
|||
|
|||
### 1. 立即修复(临时方案) |
|||
- ✅ 已修改代码添加异常处理 |
|||
- ✅ 使用 `pk` 字段作为临时的商品ID |
|||
- ✅ 查询失败时默认允许使用优惠券 |
|||
|
|||
### 2. 完整修复(推荐执行) |
|||
|
|||
#### 步骤1:停止应用 |
|||
```bash |
|||
# 如果使用Docker |
|||
docker-compose down |
|||
|
|||
# 或者直接停止Java进程 |
|||
pkill -f java |
|||
``` |
|||
|
|||
#### 步骤2:备份数据库 |
|||
```bash |
|||
mysqldump -u root -p your_database > backup_$(date +%Y%m%d_%H%M%S).sql |
|||
``` |
|||
|
|||
#### 步骤3:执行数据库修复 |
|||
```bash |
|||
mysql -u root -p your_database < src/main/resources/sql/simple_fix_coupon_table.sql |
|||
``` |
|||
|
|||
#### 步骤4:验证修复 |
|||
```sql |
|||
-- 检查表结构 |
|||
DESCRIBE shop_coupon_apply_item; |
|||
|
|||
-- 应该看到以下字段: |
|||
-- id, coupon_id, goods_id, category_id, type, pk, status, deleted, tenant_id, create_time, update_time |
|||
``` |
|||
|
|||
#### 步骤5:重启应用 |
|||
```bash |
|||
# 如果使用Docker |
|||
docker-compose up -d |
|||
|
|||
# 或者直接启动 |
|||
java -jar your-app.jar |
|||
``` |
|||
|
|||
## 🧪 测试验证 |
|||
|
|||
### 1. 检查API接口 |
|||
```bash |
|||
# 测试优惠券列表查询 |
|||
curl -X GET "http://localhost:9200/api/shop/user-coupon/my/available" |
|||
|
|||
# 测试优惠券验证 |
|||
curl -X POST "http://localhost:9200/api/shop/coupon-status/validate" \ |
|||
-H "Content-Type: application/json" \ |
|||
-d '{"userCouponId":1,"totalAmount":150.00,"goodsIds":[1,2,3]}' |
|||
``` |
|||
|
|||
### 2. 检查日志 |
|||
```bash |
|||
# 查看应用日志 |
|||
tail -f logs/application.log |
|||
|
|||
# 查找相关错误 |
|||
grep -i "goods_id\|SQLSyntaxErrorException" logs/application.log |
|||
``` |
|||
|
|||
## 📊 数据迁移(可选) |
|||
|
|||
如果表中已有数据,可能需要迁移: |
|||
|
|||
```sql |
|||
-- 如果原来使用 pk 字段存储商品ID |
|||
UPDATE shop_coupon_apply_item |
|||
SET goods_id = pk |
|||
WHERE type = 1 AND pk IS NOT NULL AND goods_id IS NULL; |
|||
|
|||
-- 如果原来使用其他字段存储分类ID |
|||
-- UPDATE shop_coupon_apply_item |
|||
-- SET category_id = some_other_field |
|||
-- WHERE type = 2 AND some_other_field IS NOT NULL AND category_id IS NULL; |
|||
``` |
|||
|
|||
## 🚨 注意事项 |
|||
|
|||
1. **数据备份**: 执行任何数据库修改前必须备份 |
|||
2. **停机时间**: 建议在低峰期执行修复 |
|||
3. **测试环境**: 先在测试环境验证修复效果 |
|||
4. **回滚计划**: 准备回滚方案以防出现问题 |
|||
|
|||
## 🔄 回滚方案 |
|||
|
|||
如果修复后出现问题,可以回滚: |
|||
|
|||
```sql |
|||
-- 删除新添加的字段 |
|||
ALTER TABLE shop_coupon_apply_item DROP COLUMN goods_id; |
|||
ALTER TABLE shop_coupon_apply_item DROP COLUMN category_id; |
|||
|
|||
-- 删除新添加的索引 |
|||
DROP INDEX idx_coupon_apply_item_goods ON shop_coupon_apply_item; |
|||
DROP INDEX idx_coupon_apply_item_category ON shop_coupon_apply_item; |
|||
DROP INDEX idx_coupon_apply_item_type ON shop_coupon_apply_item; |
|||
``` |
|||
|
|||
或者直接恢复备份: |
|||
```bash |
|||
mysql -u root -p your_database < backup_20250115_143000.sql |
|||
``` |
|||
|
|||
## ✅ 修复完成检查清单 |
|||
|
|||
- [ ] 数据库已备份 |
|||
- [ ] 执行了字段添加脚本 |
|||
- [ ] 验证了表结构正确 |
|||
- [ ] 重启了应用 |
|||
- [ ] 测试了API接口正常 |
|||
- [ ] 检查了应用日志无错误 |
|||
- [ ] 验证了优惠券功能正常 |
|||
|
|||
## 📞 技术支持 |
|||
|
|||
如果在修复过程中遇到问题,请: |
|||
|
|||
1. 检查数据库连接和权限 |
|||
2. 确认SQL语法与MySQL版本兼容 |
|||
3. 查看详细的错误日志 |
|||
4. 如有必要,联系技术支持团队 |
|||
|
|||
修复完成后,优惠券状态管理功能应该可以正常使用! |
@ -0,0 +1,212 @@ |
|||
# 支付环境隔离解决方案 |
|||
|
|||
## 🎯 问题描述 |
|||
|
|||
**现状问题**: |
|||
- 开发调试时需要修改支付回调地址为本地地址 |
|||
- 修改后影响线上生产环境的正常使用 |
|||
- 缺乏开发和生产环境的有效隔离机制 |
|||
|
|||
## 💡 解决方案概览 |
|||
|
|||
我为您提供了5种解决方案,可以单独使用或组合使用: |
|||
|
|||
### 方案一:创建开发专用租户(推荐)✨ |
|||
- 创建独立的开发租户(ID: 9999) |
|||
- 配置专用的支付参数和回调地址 |
|||
- 完全隔离开发和生产环境 |
|||
|
|||
### 方案二:环境感知的支付配置服务 |
|||
- 根据 `spring.profiles.active` 自动切换回调地址 |
|||
- 开发环境自动使用本地回调,生产环境使用线上回调 |
|||
- 无需手动修改配置 |
|||
|
|||
### 方案三:配置文件环境隔离 |
|||
- 在配置文件中定义不同环境的回调地址 |
|||
- 支持灵活的环境配置管理 |
|||
|
|||
### 方案四:开发环境管理工具 |
|||
- 提供专用的开发环境管理接口 |
|||
- 支持一键切换和恢复回调地址 |
|||
- 仅在开发环境启用 |
|||
|
|||
### 方案五:多租户配置隔离 |
|||
- 利用现有的多租户架构 |
|||
- 为不同租户配置不同的支付参数 |
|||
|
|||
## 🚀 快速实施指南 |
|||
|
|||
### 步骤1:执行数据库脚本(推荐) |
|||
|
|||
```bash |
|||
# 创建开发专用租户和配置 |
|||
mysql -u root -p your_database < src/main/resources/sql/create_dev_tenant_payment.sql |
|||
``` |
|||
|
|||
这将创建: |
|||
- 开发专用租户(ID: 9999) |
|||
- 开发环境支付配置(使用本地回调地址) |
|||
- 开发测试用户 |
|||
|
|||
### 步骤2:配置环境感知服务 |
|||
|
|||
已创建的服务会自动: |
|||
- 检测当前运行环境 |
|||
- 根据环境自动调整回调地址 |
|||
- 开发环境:`http://frps-10550.s209.websoft.top/api/shop/shop-order/notify` |
|||
- 生产环境:`https://cms-api.websoft.top/api/shop/shop-order/notify` |
|||
|
|||
### 步骤3:使用开发环境管理工具 |
|||
|
|||
开发环境下可以访问以下接口: |
|||
|
|||
```bash |
|||
# 查看环境信息 |
|||
GET /api/dev/environment/info |
|||
|
|||
# 查看支付配置 |
|||
GET /api/dev/payment/config/0 |
|||
|
|||
# 切换回调地址 |
|||
POST /api/dev/payment/switch-notify-url |
|||
{ |
|||
"notifyUrl": "http://your-local-address/api/shop/shop-order/notify", |
|||
"payType": "0" |
|||
} |
|||
|
|||
# 重置为生产环境 |
|||
POST /api/dev/payment/reset-to-prod?payType=0 |
|||
|
|||
# 获取使用指南 |
|||
GET /api/dev/guide |
|||
``` |
|||
|
|||
## 📋 使用方式对比 |
|||
|
|||
| 方案 | 优点 | 缺点 | 适用场景 | |
|||
|------|------|------|----------| |
|||
| 开发专用租户 | 完全隔离,不影响生产 | 需要创建额外数据 | 团队开发,长期使用 | |
|||
| 环境感知服务 | 自动切换,无需手动操作 | 需要代码改动 | 自动化程度高的项目 | |
|||
| 配置文件隔离 | 配置灵活,易于管理 | 需要重启应用 | 配置驱动的项目 | |
|||
| 开发管理工具 | 操作简单,功能丰富 | 仅开发环境可用 | 频繁调试的场景 | |
|||
| 多租户隔离 | 利用现有架构 | 依赖租户体系 | 已有多租户的系统 | |
|||
|
|||
## 🔧 配置示例 |
|||
|
|||
### 开发环境配置 (application-dev.yml) |
|||
```yaml |
|||
payment: |
|||
dev: |
|||
notify-url: "http://frps-10550.s209.websoft.top/api/shop/shop-order/notify" |
|||
environment-aware: true |
|||
``` |
|||
|
|||
### 生产环境配置 (application-prod.yml) |
|||
```yaml |
|||
payment: |
|||
prod: |
|||
notify-url: "https://cms-api.websoft.top/api/shop/shop-order/notify" |
|||
environment-aware: false |
|||
``` |
|||
|
|||
## 🧪 测试验证 |
|||
|
|||
### 1. 验证环境感知功能 |
|||
```bash |
|||
# 检查当前环境 |
|||
curl -X GET "http://localhost:9200/api/dev/environment/info" |
|||
|
|||
# 检查支付配置 |
|||
curl -X GET "http://localhost:9200/api/dev/payment/config/0" |
|||
``` |
|||
|
|||
### 2. 验证回调地址切换 |
|||
```bash |
|||
# 切换到本地回调 |
|||
curl -X POST "http://localhost:9200/api/dev/payment/switch-notify-url" \ |
|||
-H "Content-Type: application/json" \ |
|||
-d '{"notifyUrl":"http://localhost:8080/api/shop/shop-order/notify","payType":"0"}' |
|||
|
|||
# 重置为生产回调 |
|||
curl -X POST "http://localhost:9200/api/dev/payment/reset-to-prod?payType=0" |
|||
``` |
|||
|
|||
## 🎨 最佳实践建议 |
|||
|
|||
### 推荐组合方案 |
|||
|
|||
**方案A:完全隔离(推荐)** |
|||
1. 创建开发专用租户 |
|||
2. 配置开发环境支付参数 |
|||
3. 使用开发租户进行所有测试 |
|||
|
|||
**方案B:自动化切换** |
|||
1. 部署环境感知服务 |
|||
2. 配置环境相关参数 |
|||
3. 代码自动根据环境切换 |
|||
|
|||
**方案C:手动管理** |
|||
1. 使用开发环境管理工具 |
|||
2. 调试时切换回调地址 |
|||
3. 完成后恢复生产配置 |
|||
|
|||
### 开发流程建议 |
|||
|
|||
1. **开发阶段**:使用开发租户或本地回调地址 |
|||
2. **测试阶段**:使用测试环境配置 |
|||
3. **上线前**:确认生产环境配置正确 |
|||
4. **上线后**:验证生产环境支付功能 |
|||
|
|||
## 🚨 注意事项 |
|||
|
|||
### 安全考虑 |
|||
- 开发环境管理接口仅在开发环境启用 |
|||
- 生产环境不会加载开发相关的控制器 |
|||
- 敏感配置信息需要妥善保护 |
|||
|
|||
### 数据一致性 |
|||
- 开发租户数据与生产数据隔离 |
|||
- 定期清理开发环境测试数据 |
|||
- 避免开发数据污染生产环境 |
|||
|
|||
### 团队协作 |
|||
- 统一开发环境配置标准 |
|||
- 文档化配置变更流程 |
|||
- 建立配置变更审核机制 |
|||
|
|||
## 🔄 回滚方案 |
|||
|
|||
如果需要回滚到原有方式: |
|||
|
|||
```sql |
|||
-- 删除开发租户(可选) |
|||
DELETE FROM sys_tenant WHERE tenant_id = 9999; |
|||
DELETE FROM sys_payment WHERE tenant_id = 9999; |
|||
DELETE FROM sys_user WHERE tenant_id = 9999; |
|||
|
|||
-- 恢复原有支付配置 |
|||
UPDATE sys_payment |
|||
SET notify_url = 'https://cms-api.websoft.top/api/shop/shop-order/notify' |
|||
WHERE tenant_id = 1; |
|||
``` |
|||
|
|||
## ✅ 实施检查清单 |
|||
|
|||
- [ ] 执行了数据库脚本创建开发租户 |
|||
- [ ] 配置了环境感知服务 |
|||
- [ ] 测试了开发环境管理接口 |
|||
- [ ] 验证了自动环境切换功能 |
|||
- [ ] 确认了生产环境配置正确 |
|||
- [ ] 建立了开发流程规范 |
|||
- [ ] 培训了团队成员使用方法 |
|||
|
|||
## 📞 技术支持 |
|||
|
|||
如果在实施过程中遇到问题: |
|||
|
|||
1. 检查日志中的环境检测信息 |
|||
2. 验证配置文件中的环境参数 |
|||
3. 确认数据库中的租户和支付配置 |
|||
4. 测试开发环境管理接口功能 |
|||
|
|||
实施完成后,您就可以在不影响生产环境的情况下进行支付功能的开发和调试了! |
@ -0,0 +1,176 @@ |
|||
# 生产环境安全配置指南 |
|||
|
|||
## 🚨 重要警告 |
|||
|
|||
**原始的 `create_dev_tenant_payment.sql` 脚本不要在生产数据库执行!** |
|||
|
|||
该脚本包含测试数据,可能会影响生产环境。 |
|||
|
|||
## ✅ 安全的生产环境配置方案 |
|||
|
|||
### 方案一:使用后台管理界面(推荐) |
|||
|
|||
1. **登录后台管理系统** |
|||
2. **进入支付配置页面** |
|||
3. **创建新的支付配置**: |
|||
- 名称:`微信支付-开发环境` |
|||
- 类型:微信支付 |
|||
- 回调地址:`http://frps-10550.s209.websoft.top/api/shop/shop-order/notify` |
|||
- 其他参数:复制现有生产配置 |
|||
|
|||
### 方案二:使用API接口 |
|||
|
|||
```bash |
|||
# 1. 获取当前配置 |
|||
curl -X GET "https://your-domain.com/api/payment/list" \ |
|||
-H "Authorization: Bearer YOUR_TOKEN" |
|||
|
|||
# 2. 创建开发配置 |
|||
curl -X POST "https://your-domain.com/api/payment" \ |
|||
-H "Content-Type: application/json" \ |
|||
-H "Authorization: Bearer YOUR_TOKEN" \ |
|||
-d '{ |
|||
"name": "微信支付-开发环境", |
|||
"type": 0, |
|||
"appId": "YOUR_DEV_APP_ID", |
|||
"mchId": "YOUR_DEV_MCH_ID", |
|||
"notifyUrl": "http://frps-10550.s209.websoft.top/api/shop/shop-order/notify", |
|||
"environment": "dev" |
|||
}' |
|||
``` |
|||
|
|||
### 方案三:执行安全的SQL脚本 |
|||
|
|||
如果必须使用SQL,请使用我刚创建的安全版本: |
|||
|
|||
```bash |
|||
# 1. 先备份数据库 |
|||
mysqldump -u root -p your_database > backup_$(date +%Y%m%d_%H%M%S).sql |
|||
|
|||
# 2. 执行安全脚本 |
|||
mysql -u root -p your_database < src/main/resources/sql/production_safe_payment_config.sql |
|||
|
|||
# 3. 根据脚本输出的模板,手动创建开发配置 |
|||
``` |
|||
|
|||
## 🔧 推荐的实施步骤 |
|||
|
|||
### 步骤1:备份现有配置 |
|||
|
|||
```sql |
|||
-- 备份当前支付配置 |
|||
CREATE TABLE sys_payment_backup_$(date +%Y%m%d) AS |
|||
SELECT * FROM sys_payment WHERE status = 1; |
|||
``` |
|||
|
|||
### 步骤2:查看当前配置 |
|||
|
|||
```sql |
|||
-- 查看现有支付配置 |
|||
SELECT id, name, type, notify_url, tenant_id |
|||
FROM sys_payment |
|||
WHERE status = 1 AND deleted = 0; |
|||
``` |
|||
|
|||
### 步骤3:创建开发配置 |
|||
|
|||
**选择以下方式之一**: |
|||
|
|||
#### 方式A:通过后台界面 |
|||
1. 复制现有生产配置 |
|||
2. 修改名称为"开发环境" |
|||
3. 修改回调地址为本地地址 |
|||
|
|||
#### 方式B:通过SQL(谨慎使用) |
|||
```sql |
|||
-- 基于现有配置创建开发版本 |
|||
INSERT INTO sys_payment ( |
|||
name, type, code, app_id, mch_id, api_key, |
|||
notify_url, tenant_id, status, deleted, create_time, update_time |
|||
) |
|||
SELECT |
|||
CONCAT(name, '-开发环境'), |
|||
type, |
|||
CONCAT(code, '_dev'), |
|||
app_id, |
|||
mch_id, |
|||
api_key, |
|||
'http://frps-10550.s209.websoft.top/api/shop/shop-order/notify', |
|||
tenant_id, |
|||
0, -- 先设为禁用状态 |
|||
0, |
|||
NOW(), |
|||
NOW() |
|||
FROM sys_payment |
|||
WHERE type = 0 AND status = 1 AND deleted = 0 |
|||
LIMIT 1; |
|||
``` |
|||
|
|||
### 步骤4:测试和验证 |
|||
|
|||
```bash |
|||
# 测试开发环境配置 |
|||
curl -X GET "http://localhost:9200/api/dev/payment/config/0" |
|||
|
|||
# 验证回调地址 |
|||
curl -X POST "http://frps-10550.s209.websoft.top/api/shop/shop-order/notify" \ |
|||
-d "test=1" |
|||
``` |
|||
|
|||
## 🛡️ 安全检查清单 |
|||
|
|||
- [ ] 已备份生产数据库 |
|||
- [ ] 确认当前数据库环境 |
|||
- [ ] 使用安全的配置方法 |
|||
- [ ] 测试开发配置不影响生产 |
|||
- [ ] 验证回调地址可访问 |
|||
- [ ] 建立配置恢复机制 |
|||
|
|||
## 🔄 快速切换方案 |
|||
|
|||
### 开发时切换到本地回调 |
|||
|
|||
```sql |
|||
-- 临时修改(记录原始值) |
|||
UPDATE sys_payment |
|||
SET notify_url = 'http://frps-10550.s209.websoft.top/api/shop/shop-order/notify' |
|||
WHERE id = YOUR_PAYMENT_CONFIG_ID; |
|||
``` |
|||
|
|||
### 完成后恢复生产回调 |
|||
|
|||
```sql |
|||
-- 恢复生产配置 |
|||
UPDATE sys_payment |
|||
SET notify_url = 'https://cms-api.websoft.top/api/shop/shop-order/notify' |
|||
WHERE id = YOUR_PAYMENT_CONFIG_ID; |
|||
``` |
|||
|
|||
## 🚀 最佳实践 |
|||
|
|||
1. **使用环境感知服务**:让代码自动根据环境切换 |
|||
2. **创建专用开发配置**:避免修改生产配置 |
|||
3. **使用配置管理工具**:通过界面而非SQL操作 |
|||
4. **建立回滚机制**:确保可以快速恢复 |
|||
5. **团队协作规范**:统一配置管理流程 |
|||
|
|||
## ❌ 避免的操作 |
|||
|
|||
- ❌ 直接在生产库执行包含测试数据的脚本 |
|||
- ❌ 修改生产配置进行开发调试 |
|||
- ❌ 在生产环境创建测试租户 |
|||
- ❌ 不备份就修改重要配置 |
|||
- ❌ 忘记恢复生产环境配置 |
|||
|
|||
## 📞 如果出现问题 |
|||
|
|||
1. **立即停止操作** |
|||
2. **检查数据库备份** |
|||
3. **恢复原始配置**: |
|||
```sql |
|||
-- 从备份恢复 |
|||
INSERT INTO sys_payment SELECT * FROM sys_payment_backup_YYYYMMDD; |
|||
``` |
|||
4. **联系技术支持** |
|||
|
|||
记住:**安全第一,谨慎操作!** 🛡️ |
@ -0,0 +1,236 @@ |
|||
package com.gxwebsoft.common.core.controller; |
|||
|
|||
import com.gxwebsoft.common.core.service.EnvironmentAwarePaymentService; |
|||
import com.gxwebsoft.common.core.service.PaymentCacheService; |
|||
import com.gxwebsoft.common.core.web.ApiResult; |
|||
import com.gxwebsoft.common.core.web.BaseController; |
|||
import com.gxwebsoft.common.system.entity.Payment; |
|||
import com.gxwebsoft.common.system.service.PaymentService; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* 开发环境管理控制器 |
|||
* 仅在开发环境启用,用于管理开发调试配置 |
|||
* |
|||
* @author WebSoft |
|||
* @since 2025-01-15 |
|||
*/ |
|||
@Slf4j |
|||
@Tag(name = "开发环境管理") |
|||
@RestController |
|||
@RequestMapping("/api/dev") |
|||
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "dev") |
|||
public class DevEnvironmentController extends BaseController { |
|||
|
|||
@Autowired |
|||
private EnvironmentAwarePaymentService environmentAwarePaymentService; |
|||
|
|||
@Autowired |
|||
private PaymentCacheService paymentCacheService; |
|||
|
|||
@Autowired |
|||
private PaymentService paymentService; |
|||
|
|||
@Value("${spring.profiles.active:dev}") |
|||
private String activeProfile; |
|||
|
|||
@Operation(summary = "获取当前环境信息") |
|||
@GetMapping("/environment/info") |
|||
public ApiResult<Map<String, Object>> getEnvironmentInfo() { |
|||
Map<String, Object> info = new HashMap<>(); |
|||
info.put("activeProfile", activeProfile); |
|||
info.put("isDevelopment", environmentAwarePaymentService.isDevelopmentEnvironment()); |
|||
info.put("isProduction", environmentAwarePaymentService.isProductionEnvironment()); |
|||
info.put("currentEnvironment", environmentAwarePaymentService.getCurrentEnvironment()); |
|||
|
|||
return success("获取成功", info); |
|||
} |
|||
|
|||
@Operation(summary = "获取环境感知的支付配置") |
|||
@GetMapping("/payment/config/{payType}") |
|||
public ApiResult<Map<String, Object>> getPaymentConfig(@PathVariable Integer payType) { |
|||
try { |
|||
Integer tenantId = getTenantId(); |
|||
|
|||
// 获取原始配置
|
|||
Payment originalConfig = paymentCacheService.getPaymentConfig(payType, tenantId); |
|||
|
|||
// 获取环境感知配置
|
|||
Payment envConfig = environmentAwarePaymentService.getEnvironmentAwarePaymentConfig(payType, tenantId); |
|||
|
|||
Map<String, Object> result = new HashMap<>(); |
|||
result.put("tenantId", tenantId); |
|||
result.put("payType", payType); |
|||
result.put("environment", activeProfile); |
|||
result.put("originalConfig", originalConfig); |
|||
result.put("environmentAwareConfig", envConfig); |
|||
|
|||
if (originalConfig != null && envConfig != null) { |
|||
result.put("notifyUrlChanged", !originalConfig.getNotifyUrl().equals(envConfig.getNotifyUrl())); |
|||
result.put("originalNotifyUrl", originalConfig.getNotifyUrl()); |
|||
result.put("environmentNotifyUrl", envConfig.getNotifyUrl()); |
|||
} |
|||
|
|||
return success("获取成功", result); |
|||
|
|||
} catch (Exception e) { |
|||
log.error("获取支付配置失败", e); |
|||
return fail("获取失败: " + e.getMessage(),null); |
|||
} |
|||
} |
|||
|
|||
@Operation(summary = "切换开发环境回调地址") |
|||
@PostMapping("/payment/switch-notify-url") |
|||
public ApiResult<?> switchNotifyUrl(@RequestBody Map<String, String> request) { |
|||
try { |
|||
String newNotifyUrl = request.get("notifyUrl"); |
|||
Integer payType = Integer.valueOf(request.getOrDefault("payType", "0")); |
|||
|
|||
if (newNotifyUrl == null || newNotifyUrl.trim().isEmpty()) { |
|||
return fail("回调地址不能为空"); |
|||
} |
|||
|
|||
Integer tenantId = getTenantId(); |
|||
|
|||
// 获取当前配置
|
|||
Payment payment = paymentCacheService.getPaymentConfig(payType, tenantId); |
|||
if (payment == null) { |
|||
return fail("未找到支付配置"); |
|||
} |
|||
|
|||
// 更新回调地址
|
|||
payment.setNotifyUrl(newNotifyUrl); |
|||
|
|||
// 更新数据库
|
|||
boolean updated = paymentService.updateById(payment); |
|||
|
|||
if (updated) { |
|||
// 清除缓存,强制重新加载
|
|||
paymentCacheService.removePaymentConfig(payType.toString(), tenantId); |
|||
|
|||
log.info("开发环境回调地址已更新: {} -> {}", payment.getNotifyUrl(), newNotifyUrl); |
|||
|
|||
Map<String, Object> result = new HashMap<>(); |
|||
result.put("oldNotifyUrl", payment.getNotifyUrl()); |
|||
result.put("newNotifyUrl", newNotifyUrl); |
|||
result.put("payType", payType); |
|||
result.put("tenantId", tenantId); |
|||
|
|||
return success("回调地址更新成功", result); |
|||
} else { |
|||
return fail("更新失败"); |
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
log.error("切换回调地址失败", e); |
|||
return fail("切换失败: " + e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
@Operation(summary = "重置为生产环境回调地址") |
|||
@PostMapping("/payment/reset-to-prod") |
|||
public ApiResult<?> resetToProdNotifyUrl(@RequestParam(defaultValue = "0") Integer payType) { |
|||
try { |
|||
Integer tenantId = getTenantId(); |
|||
|
|||
// 获取当前配置
|
|||
Payment payment = paymentCacheService.getPaymentConfig(payType, tenantId); |
|||
if (payment == null) { |
|||
return fail("未找到支付配置"); |
|||
} |
|||
|
|||
// 设置为生产环境回调地址
|
|||
String prodNotifyUrl = "https://cms-api.websoft.top/api/shop/shop-order/notify"; |
|||
String oldNotifyUrl = payment.getNotifyUrl(); |
|||
|
|||
payment.setNotifyUrl(prodNotifyUrl); |
|||
|
|||
// 更新数据库
|
|||
boolean updated = paymentService.updateById(payment); |
|||
|
|||
if (updated) { |
|||
// 清除缓存
|
|||
paymentCacheService.removePaymentConfig(payType.toString(), tenantId); |
|||
|
|||
log.info("回调地址已重置为生产环境: {} -> {}", oldNotifyUrl, prodNotifyUrl); |
|||
|
|||
Map<String, Object> result = new HashMap<>(); |
|||
result.put("oldNotifyUrl", oldNotifyUrl); |
|||
result.put("newNotifyUrl", prodNotifyUrl); |
|||
result.put("payType", payType); |
|||
result.put("tenantId", tenantId); |
|||
|
|||
return success("已重置为生产环境回调地址", result); |
|||
} else { |
|||
return fail("重置失败"); |
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
log.error("重置回调地址失败", e); |
|||
return fail("重置失败: " + e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
@Operation(summary = "清除支付配置缓存") |
|||
@PostMapping("/payment/clear-cache") |
|||
public ApiResult<?> clearPaymentCache(@RequestParam(defaultValue = "0") Integer payType) { |
|||
try { |
|||
Integer tenantId = getTenantId(); |
|||
|
|||
paymentCacheService.removePaymentConfig(payType.toString(), tenantId); |
|||
|
|||
log.info("支付配置缓存已清除: payType={}, tenantId={}", payType, tenantId); |
|||
|
|||
return success("缓存清除成功"); |
|||
|
|||
} catch (Exception e) { |
|||
log.error("清除缓存失败", e); |
|||
return fail("清除失败: " + e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
@Operation(summary = "获取开发环境使用指南") |
|||
@GetMapping("/guide") |
|||
public ApiResult<Map<String, Object>> getDevGuide() { |
|||
Map<String, Object> guide = new HashMap<>(); |
|||
|
|||
guide.put("title", "开发环境支付调试指南"); |
|||
guide.put("environment", activeProfile); |
|||
|
|||
Map<String, String> steps = new HashMap<>(); |
|||
steps.put("step1", "使用 /api/dev/payment/switch-notify-url 切换到本地回调地址"); |
|||
steps.put("step2", "进行支付功能调试和测试"); |
|||
steps.put("step3", "调试完成后使用 /api/dev/payment/reset-to-prod 恢复生产环境配置"); |
|||
steps.put("step4", "或者直接在后台管理界面修改回调地址"); |
|||
|
|||
guide.put("steps", steps); |
|||
|
|||
Map<String, String> apis = new HashMap<>(); |
|||
apis.put("环境信息", "GET /api/dev/environment/info"); |
|||
apis.put("查看配置", "GET /api/dev/payment/config/{payType}"); |
|||
apis.put("切换回调", "POST /api/dev/payment/switch-notify-url"); |
|||
apis.put("重置生产", "POST /api/dev/payment/reset-to-prod"); |
|||
apis.put("清除缓存", "POST /api/dev/payment/clear-cache"); |
|||
|
|||
guide.put("apis", apis); |
|||
|
|||
Map<String, String> tips = new HashMap<>(); |
|||
tips.put("tip1", "此控制器仅在开发环境启用"); |
|||
tips.put("tip2", "生产环境不会加载这些接口"); |
|||
tips.put("tip3", "建议使用环境感知服务自动切换"); |
|||
tips.put("tip4", "记得在调试完成后恢复生产配置"); |
|||
|
|||
guide.put("tips", tips); |
|||
|
|||
return success("获取成功", guide); |
|||
} |
|||
} |
@ -0,0 +1,143 @@ |
|||
package com.gxwebsoft.common.core.service; |
|||
|
|||
import com.gxwebsoft.common.system.entity.Payment; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
/** |
|||
* 环境感知的支付配置服务 |
|||
* 根据不同环境自动切换支付回调地址 |
|||
* |
|||
* @author WebSoft |
|||
* @since 2025-01-15 |
|||
*/ |
|||
@Slf4j |
|||
@Service |
|||
public class EnvironmentAwarePaymentService { |
|||
|
|||
@Autowired |
|||
private PaymentCacheService paymentCacheService; |
|||
|
|||
@Value("${spring.profiles.active:dev}") |
|||
private String activeProfile; |
|||
|
|||
@Value("${config.server-url:}") |
|||
private String serverUrl; |
|||
|
|||
// 开发环境回调地址配置
|
|||
@Value("${payment.dev.notify-url:http://frps-10550.s209.websoft.top/api/shop/shop-order/notify}") |
|||
private String devNotifyUrl; |
|||
|
|||
// 生产环境回调地址配置
|
|||
@Value("${payment.prod.notify-url:https://cms-api.websoft.top/api/shop/shop-order/notify}") |
|||
private String prodNotifyUrl; |
|||
|
|||
/** |
|||
* 获取环境感知的支付配置 |
|||
* 根据当前环境自动调整回调地址 |
|||
* |
|||
* @param payType 支付类型 |
|||
* @param tenantId 租户ID |
|||
* @return 支付配置 |
|||
*/ |
|||
public Payment getEnvironmentAwarePaymentConfig(Integer payType, Integer tenantId) { |
|||
// 获取原始支付配置
|
|||
Payment payment = paymentCacheService.getPaymentConfig(payType, tenantId); |
|||
|
|||
if (payment == null) { |
|||
return null; |
|||
} |
|||
|
|||
// 根据环境调整回调地址
|
|||
Payment envPayment = clonePayment(payment); |
|||
String notifyUrl = getEnvironmentNotifyUrl(); |
|||
|
|||
log.info("环境感知支付配置 - 环境: {}, 原始回调: {}, 调整后回调: {}", |
|||
activeProfile, payment.getNotifyUrl(), notifyUrl); |
|||
|
|||
envPayment.setNotifyUrl(notifyUrl); |
|||
|
|||
return envPayment; |
|||
} |
|||
|
|||
/** |
|||
* 根据当前环境获取回调地址 |
|||
*/ |
|||
private String getEnvironmentNotifyUrl() { |
|||
if ("dev".equals(activeProfile) || "test".equals(activeProfile)) { |
|||
// 开发/测试环境使用本地回调地址
|
|||
return devNotifyUrl; |
|||
} else if ("prod".equals(activeProfile)) { |
|||
// 生产环境使用生产回调地址
|
|||
return prodNotifyUrl; |
|||
} else { |
|||
// 默认使用配置的服务器地址
|
|||
return serverUrl + "/shop/shop-order/notify"; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 克隆支付配置对象 |
|||
*/ |
|||
private Payment clonePayment(Payment original) { |
|||
Payment cloned = new Payment(); |
|||
cloned.setId(original.getId()); |
|||
cloned.setName(original.getName()); |
|||
cloned.setType(original.getType()); |
|||
cloned.setCode(original.getCode()); |
|||
cloned.setImage(original.getImage()); |
|||
cloned.setWechatType(original.getWechatType()); |
|||
cloned.setAppId(original.getAppId()); |
|||
cloned.setMchId(original.getMchId()); |
|||
cloned.setApiKey(original.getApiKey()); |
|||
cloned.setApiclientCert(original.getApiclientCert()); |
|||
cloned.setApiclientKey(original.getApiclientKey()); |
|||
cloned.setPubKey(original.getPubKey()); |
|||
cloned.setPubKeyId(original.getPubKeyId()); |
|||
cloned.setMerchantSerialNumber(original.getMerchantSerialNumber()); |
|||
cloned.setNotifyUrl(original.getNotifyUrl()); // 这个会被后续覆盖
|
|||
cloned.setComments(original.getComments()); |
|||
cloned.setSortNumber(original.getSortNumber()); |
|||
cloned.setStatus(original.getStatus()); |
|||
cloned.setDeleted(original.getDeleted()); |
|||
cloned.setTenantId(original.getTenantId()); |
|||
return cloned; |
|||
} |
|||
|
|||
/** |
|||
* 获取微信支付配置(环境感知) |
|||
*/ |
|||
public Payment getWechatPayConfig(Integer tenantId) { |
|||
return getEnvironmentAwarePaymentConfig(0, tenantId); |
|||
} |
|||
|
|||
/** |
|||
* 获取支付宝配置(环境感知) |
|||
*/ |
|||
public Payment getAlipayConfig(Integer tenantId) { |
|||
return getEnvironmentAwarePaymentConfig(1, tenantId); |
|||
} |
|||
|
|||
/** |
|||
* 检查当前环境 |
|||
*/ |
|||
public String getCurrentEnvironment() { |
|||
return activeProfile; |
|||
} |
|||
|
|||
/** |
|||
* 是否为开发环境 |
|||
*/ |
|||
public boolean isDevelopmentEnvironment() { |
|||
return "dev".equals(activeProfile) || "test".equals(activeProfile); |
|||
} |
|||
|
|||
/** |
|||
* 是否为生产环境 |
|||
*/ |
|||
public boolean isProductionEnvironment() { |
|||
return "prod".equals(activeProfile); |
|||
} |
|||
} |
@ -0,0 +1,206 @@ |
|||
-- 创建开发专用租户和支付配置 |
|||
-- 用于隔离开发环境和生产环境的支付回调地址 |
|||
|
|||
-- ======================================== |
|||
-- 1. 创建开发专用租户(如果不存在) |
|||
-- ======================================== |
|||
|
|||
-- 检查是否已存在开发租户 |
|||
SELECT 'Checking for dev tenant...' as status; |
|||
|
|||
-- 插入开发租户(租户ID使用 9999 避免与生产冲突) |
|||
INSERT IGNORE INTO sys_tenant ( |
|||
tenant_id, |
|||
tenant_name, |
|||
tenant_code, |
|||
contact_person, |
|||
contact_phone, |
|||
contact_email, |
|||
status, |
|||
deleted, |
|||
create_time, |
|||
update_time, |
|||
comments |
|||
) VALUES ( |
|||
9999, |
|||
'开发测试租户', |
|||
'DEV_TENANT', |
|||
'开发者', |
|||
'13800000000', |
|||
'dev@websoft.top', |
|||
1, |
|||
0, |
|||
NOW(), |
|||
NOW(), |
|||
'专用于开发环境测试,不影响生产环境' |
|||
); |
|||
|
|||
-- ======================================== |
|||
-- 2. 创建开发环境专用支付配置 |
|||
-- ======================================== |
|||
|
|||
-- 微信支付开发配置 |
|||
INSERT IGNORE INTO sys_payment ( |
|||
name, |
|||
type, |
|||
code, |
|||
image, |
|||
wechat_type, |
|||
app_id, |
|||
mch_id, |
|||
api_key, |
|||
apiclient_cert, |
|||
apiclient_key, |
|||
pub_key, |
|||
pub_key_id, |
|||
merchant_serial_number, |
|||
notify_url, |
|||
comments, |
|||
sort_number, |
|||
status, |
|||
deleted, |
|||
tenant_id, |
|||
create_time, |
|||
update_time |
|||
) VALUES ( |
|||
'微信支付-开发环境', |
|||
0, -- 微信支付 |
|||
'wechat_dev', |
|||
'/static/images/wechat_pay.png', |
|||
1, -- 普通商户 |
|||
'wx1234567890abcdef', -- 开发环境AppID |
|||
'1234567890', -- 开发环境商户号 |
|||
'your_dev_api_key_32_characters_long', |
|||
'dev/wechat/apiclient_cert.pem', |
|||
'dev/wechat/apiclient_key.pem', |
|||
'dev/wechat/wechatpay_cert.pem', |
|||
'your_pub_key_id', |
|||
'your_merchant_serial_number', |
|||
'http://frps-10550.s209.websoft.top/api/shop/shop-order/notify', -- 开发环境回调地址 |
|||
'开发环境专用配置,使用本地回调地址', |
|||
1, |
|||
1, -- 启用 |
|||
0, -- 未删除 |
|||
9999, -- 开发租户ID |
|||
NOW(), |
|||
NOW() |
|||
); |
|||
|
|||
-- 支付宝开发配置 |
|||
INSERT IGNORE INTO sys_payment ( |
|||
name, |
|||
type, |
|||
code, |
|||
app_id, |
|||
mch_id, |
|||
api_key, |
|||
notify_url, |
|||
comments, |
|||
sort_number, |
|||
status, |
|||
deleted, |
|||
tenant_id, |
|||
create_time, |
|||
update_time |
|||
) VALUES ( |
|||
'支付宝-开发环境', |
|||
1, -- 支付宝 |
|||
'alipay_dev', |
|||
'your_dev_alipay_app_id', |
|||
'your_dev_alipay_mch_id', |
|||
'your_dev_alipay_private_key', |
|||
'http://frps-10550.s209.websoft.top/api/shop/shop-order/notify', -- 开发环境回调地址 |
|||
'开发环境专用支付宝配置', |
|||
2, |
|||
1, -- 启用 |
|||
0, -- 未删除 |
|||
9999, -- 开发租户ID |
|||
NOW(), |
|||
NOW() |
|||
); |
|||
|
|||
-- ======================================== |
|||
-- 3. 创建开发环境用户(可选) |
|||
-- ======================================== |
|||
|
|||
-- 创建开发专用用户 |
|||
INSERT IGNORE INTO sys_user ( |
|||
user_id, |
|||
username, |
|||
password, |
|||
nickname, |
|||
avatar, |
|||
sex, |
|||
phone, |
|||
email, |
|||
email_verified, |
|||
real_name, |
|||
id_card, |
|||
birthday, |
|||
department_id, |
|||
status, |
|||
deleted, |
|||
tenant_id, |
|||
create_time, |
|||
update_time, |
|||
comments |
|||
) VALUES ( |
|||
99999, |
|||
'dev_user', |
|||
'$2a$10$yKTnKzKqKqKqKqKqKqKqKOKqKqKqKqKqKqKqKqKqKqKqKqKqKqKqK', -- 密码: dev123456 |
|||
'开发测试用户', |
|||
'/static/images/default_avatar.png', |
|||
1, |
|||
'13800000001', |
|||
'dev_user@websoft.top', |
|||
1, |
|||
'开发者', |
|||
'000000000000000000', |
|||
'1990-01-01', |
|||
1, |
|||
0, -- 正常状态 |
|||
0, -- 未删除 |
|||
9999, -- 开发租户ID |
|||
NOW(), |
|||
NOW(), |
|||
'开发环境专用测试用户' |
|||
); |
|||
|
|||
-- ======================================== |
|||
-- 4. 验证创建结果 |
|||
-- ======================================== |
|||
|
|||
-- 检查租户创建结果 |
|||
SELECT |
|||
'Tenant Check' as check_type, |
|||
tenant_id, |
|||
tenant_name, |
|||
tenant_code, |
|||
status |
|||
FROM sys_tenant |
|||
WHERE tenant_id = 9999; |
|||
|
|||
-- 检查支付配置创建结果 |
|||
SELECT |
|||
'Payment Config Check' as check_type, |
|||
id, |
|||
name, |
|||
type, |
|||
notify_url, |
|||
tenant_id, |
|||
status |
|||
FROM sys_payment |
|||
WHERE tenant_id = 9999; |
|||
|
|||
-- 检查用户创建结果 |
|||
SELECT |
|||
'User Check' as check_type, |
|||
user_id, |
|||
username, |
|||
nickname, |
|||
tenant_id, |
|||
status |
|||
FROM sys_user |
|||
WHERE tenant_id = 9999; |
|||
|
|||
SELECT '开发环境配置创建完成!' as result; |
@ -0,0 +1,101 @@ |
|||
-- 修复优惠券适用商品表字段缺失问题 |
|||
-- 作者: WebSoft |
|||
-- 日期: 2025-01-15 |
|||
-- 说明: 添加缺失的 goods_id 和 category_id 字段 |
|||
|
|||
-- ======================================== |
|||
-- 1. 检查表是否存在 |
|||
-- ======================================== |
|||
SELECT 'Checking table existence...' as status; |
|||
|
|||
-- ======================================== |
|||
-- 2. 添加缺失的字段 |
|||
-- ======================================== |
|||
|
|||
-- 添加 goods_id 字段(如果不存在) |
|||
SET @sql = (SELECT IF( |
|||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS |
|||
WHERE TABLE_SCHEMA = DATABASE() |
|||
AND TABLE_NAME = 'shop_coupon_apply_item' |
|||
AND COLUMN_NAME = 'goods_id') = 0, |
|||
'ALTER TABLE shop_coupon_apply_item ADD COLUMN goods_id INT(11) NULL COMMENT "商品ID" AFTER coupon_id;', |
|||
'SELECT "goods_id column already exists" as result;' |
|||
)); |
|||
PREPARE stmt FROM @sql; |
|||
EXECUTE stmt; |
|||
DEALLOCATE PREPARE stmt; |
|||
|
|||
-- 添加 category_id 字段(如果不存在) |
|||
SET @sql = (SELECT IF( |
|||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS |
|||
WHERE TABLE_SCHEMA = DATABASE() |
|||
AND TABLE_NAME = 'shop_coupon_apply_item' |
|||
AND COLUMN_NAME = 'category_id') = 0, |
|||
'ALTER TABLE shop_coupon_apply_item ADD COLUMN category_id INT(11) NULL COMMENT "分类ID" AFTER goods_id;', |
|||
'SELECT "category_id column already exists" as result;' |
|||
)); |
|||
PREPARE stmt FROM @sql; |
|||
EXECUTE stmt; |
|||
DEALLOCATE PREPARE stmt; |
|||
|
|||
-- ======================================== |
|||
-- 3. 更新现有数据(如果需要) |
|||
-- ======================================== |
|||
|
|||
-- 如果表中有数据但 goods_id 为空,可以根据业务逻辑设置默认值 |
|||
-- 这里只是示例,实际需要根据业务需求调整 |
|||
UPDATE shop_coupon_apply_item |
|||
SET goods_id = pk |
|||
WHERE goods_id IS NULL AND type = 1 AND pk IS NOT NULL; |
|||
|
|||
-- ======================================== |
|||
-- 4. 添加索引优化查询性能 |
|||
-- ======================================== |
|||
|
|||
-- 添加 goods_id 索引 |
|||
CREATE INDEX IF NOT EXISTS idx_coupon_apply_item_goods ON shop_coupon_apply_item(coupon_id, goods_id); |
|||
|
|||
-- 添加 category_id 索引 |
|||
CREATE INDEX IF NOT EXISTS idx_coupon_apply_item_category ON shop_coupon_apply_item(coupon_id, category_id); |
|||
|
|||
-- 添加类型索引 |
|||
CREATE INDEX IF NOT EXISTS idx_coupon_apply_item_type ON shop_coupon_apply_item(coupon_id, type); |
|||
|
|||
-- ======================================== |
|||
-- 5. 验证修复结果 |
|||
-- ======================================== |
|||
|
|||
-- 检查表结构 |
|||
SELECT |
|||
COLUMN_NAME, |
|||
DATA_TYPE, |
|||
IS_NULLABLE, |
|||
COLUMN_DEFAULT, |
|||
COLUMN_COMMENT |
|||
FROM INFORMATION_SCHEMA.COLUMNS |
|||
WHERE TABLE_SCHEMA = DATABASE() |
|||
AND TABLE_NAME = 'shop_coupon_apply_item' |
|||
ORDER BY ORDINAL_POSITION; |
|||
|
|||
-- 检查数据 |
|||
SELECT |
|||
'Data check' as check_type, |
|||
COUNT(*) as total_records, |
|||
COUNT(goods_id) as records_with_goods_id, |
|||
COUNT(category_id) as records_with_category_id |
|||
FROM shop_coupon_apply_item; |
|||
|
|||
-- ======================================== |
|||
-- 6. 创建示例数据(可选) |
|||
-- ======================================== |
|||
|
|||
-- 如果表为空,插入一些示例数据用于测试 |
|||
INSERT IGNORE INTO shop_coupon_apply_item |
|||
(coupon_id, goods_id, category_id, type, status, tenant_id, create_time, update_time) |
|||
VALUES |
|||
(1, 1, NULL, 1, 0, 1, NOW(), NOW()), |
|||
(1, 2, NULL, 1, 0, 1, NOW(), NOW()), |
|||
(2, NULL, 1, 2, 0, 1, NOW(), NOW()), |
|||
(2, NULL, 2, 2, 0, 1, NOW(), NOW()); |
|||
|
|||
SELECT 'Database fix completed successfully!' as result; |
@ -0,0 +1,183 @@ |
|||
-- 生产环境安全的支付配置脚本 |
|||
-- 此脚本可以安全地在生产数据库执行 |
|||
-- 不会创建测试数据,只添加必要的配置支持 |
|||
|
|||
-- ======================================== |
|||
-- 1. 检查当前环境(手动确认) |
|||
-- ======================================== |
|||
SELECT |
|||
'请确认这是您要修改的数据库' as warning, |
|||
DATABASE() as current_database, |
|||
NOW() as execution_time; |
|||
|
|||
-- 暂停执行,让用户确认 |
|||
-- 如果确认无误,请删除下面这行注释继续执行 |
|||
-- SELECT 'Please confirm this is the correct database before proceeding' as confirmation_required; |
|||
|
|||
-- ======================================== |
|||
-- 2. 添加支付配置表字段(如果不存在) |
|||
-- ======================================== |
|||
|
|||
-- 检查是否需要添加环境标识字段 |
|||
SELECT |
|||
CASE |
|||
WHEN COUNT(*) = 0 THEN '需要添加environment字段' |
|||
ELSE '环境字段已存在' |
|||
END as environment_field_status |
|||
FROM INFORMATION_SCHEMA.COLUMNS |
|||
WHERE TABLE_SCHEMA = DATABASE() |
|||
AND TABLE_NAME = 'sys_payment' |
|||
AND COLUMN_NAME = 'environment'; |
|||
|
|||
-- 添加环境标识字段(如果不存在) |
|||
SET @sql = (SELECT IF( |
|||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS |
|||
WHERE TABLE_SCHEMA = DATABASE() |
|||
AND TABLE_NAME = 'sys_payment' |
|||
AND COLUMN_NAME = 'environment') = 0, |
|||
'ALTER TABLE sys_payment ADD COLUMN environment VARCHAR(20) DEFAULT "prod" COMMENT "环境标识(dev/test/prod)" AFTER tenant_id;', |
|||
'SELECT "environment column already exists" as result;' |
|||
)); |
|||
PREPARE stmt FROM @sql; |
|||
EXECUTE stmt; |
|||
DEALLOCATE PREPARE stmt; |
|||
|
|||
-- ======================================== |
|||
-- 3. 为现有支付配置添加环境标识 |
|||
-- ======================================== |
|||
|
|||
-- 将现有配置标记为生产环境 |
|||
UPDATE sys_payment |
|||
SET environment = 'prod' |
|||
WHERE environment IS NULL OR environment = ''; |
|||
|
|||
-- ======================================== |
|||
-- 4. 创建开发环境配置的安全方式 |
|||
-- ======================================== |
|||
|
|||
-- 方式1:复制现有生产配置作为开发模板(推荐) |
|||
-- 注意:这里使用您现有的租户ID,不创建新租户 |
|||
|
|||
-- 获取当前生产环境的微信支付配置 |
|||
SELECT |
|||
'当前微信支付配置' as config_type, |
|||
id, |
|||
name, |
|||
app_id, |
|||
mch_id, |
|||
notify_url, |
|||
tenant_id, |
|||
environment |
|||
FROM sys_payment |
|||
WHERE type = 0 AND status = 1 AND deleted = 0 |
|||
ORDER BY id DESC LIMIT 1; |
|||
|
|||
-- 获取当前生产环境的支付宝配置 |
|||
SELECT |
|||
'当前支付宝配置' as config_type, |
|||
id, |
|||
name, |
|||
app_id, |
|||
mch_id, |
|||
notify_url, |
|||
tenant_id, |
|||
environment |
|||
FROM sys_payment |
|||
WHERE type = 1 AND status = 1 AND deleted = 0 |
|||
ORDER BY id DESC LIMIT 1; |
|||
|
|||
-- ======================================== |
|||
-- 5. 手动创建开发配置的SQL模板 |
|||
-- ======================================== |
|||
|
|||
-- 以下SQL需要您手动修改参数后执行 |
|||
-- 请根据上面查询的结果,修改相应的参数 |
|||
|
|||
/* |
|||
-- 微信支付开发配置模板(请修改参数后执行) |
|||
INSERT INTO sys_payment ( |
|||
name, type, code, image, wechat_type, |
|||
app_id, mch_id, api_key, apiclient_cert, apiclient_key, |
|||
pub_key, pub_key_id, merchant_serial_number, notify_url, |
|||
comments, sort_number, status, deleted, tenant_id, environment, |
|||
create_time, update_time |
|||
) VALUES ( |
|||
'微信支付-开发环境', |
|||
0, -- 微信支付 |
|||
'wechat_dev', |
|||
'/static/images/wechat_pay.png', |
|||
1, -- 普通商户 |
|||
'YOUR_DEV_APP_ID', -- 请替换为您的开发环境AppID |
|||
'YOUR_DEV_MCH_ID', -- 请替换为您的开发环境商户号 |
|||
'YOUR_DEV_API_KEY', -- 请替换为您的开发环境API密钥 |
|||
'dev/wechat/apiclient_cert.pem', |
|||
'dev/wechat/apiclient_key.pem', |
|||
'dev/wechat/wechatpay_cert.pem', |
|||
'YOUR_DEV_PUB_KEY_ID', |
|||
'YOUR_DEV_MERCHANT_SERIAL', |
|||
'http://frps-10550.s209.websoft.top/api/shop/shop-order/notify', -- 开发环境回调 |
|||
'开发环境专用配置', |
|||
1, |
|||
1, -- 启用 |
|||
0, -- 未删除 |
|||
YOUR_TENANT_ID, -- 请替换为您的租户ID |
|||
'dev', -- 开发环境标识 |
|||
NOW(), |
|||
NOW() |
|||
); |
|||
*/ |
|||
|
|||
-- ======================================== |
|||
-- 6. 更安全的方案:仅更新现有配置的回调地址 |
|||
-- ======================================== |
|||
|
|||
-- 查看当前回调地址 |
|||
SELECT |
|||
'当前回调地址检查' as check_type, |
|||
id, |
|||
name, |
|||
type, |
|||
notify_url, |
|||
tenant_id, |
|||
environment |
|||
FROM sys_payment |
|||
WHERE status = 1 AND deleted = 0; |
|||
|
|||
-- 如果您只是想临时修改回调地址进行调试,可以使用以下SQL: |
|||
-- 注意:请先备份原始配置! |
|||
|
|||
/* |
|||
-- 备份当前配置 |
|||
CREATE TABLE IF NOT EXISTS sys_payment_backup AS |
|||
SELECT *, NOW() as backup_time FROM sys_payment WHERE status = 1; |
|||
|
|||
-- 临时修改回调地址(请谨慎使用) |
|||
UPDATE sys_payment |
|||
SET notify_url = 'http://frps-10550.s209.websoft.top/api/shop/shop-order/notify' |
|||
WHERE type = 0 AND tenant_id = YOUR_TENANT_ID AND status = 1; |
|||
|
|||
-- 恢复原始配置的SQL(调试完成后执行) |
|||
UPDATE sys_payment |
|||
SET notify_url = 'https://cms-api.websoft.top/api/shop/shop-order/notify' |
|||
WHERE type = 0 AND tenant_id = YOUR_TENANT_ID AND status = 1; |
|||
*/ |
|||
|
|||
-- ======================================== |
|||
-- 7. 验证配置 |
|||
-- ======================================== |
|||
|
|||
-- 检查所有支付配置 |
|||
SELECT |
|||
'最终配置检查' as check_type, |
|||
id, |
|||
name, |
|||
type, |
|||
notify_url, |
|||
tenant_id, |
|||
environment, |
|||
status |
|||
FROM sys_payment |
|||
WHERE deleted = 0 |
|||
ORDER BY tenant_id, type; |
|||
|
|||
SELECT '生产环境安全配置完成!请根据注释中的模板手动创建开发配置。' as result; |
@ -0,0 +1,17 @@ |
|||
-- 简单修复优惠券适用商品表字段缺失问题 |
|||
-- 执行前请备份数据库 |
|||
|
|||
-- 1. 添加缺失的字段 |
|||
ALTER TABLE shop_coupon_apply_item |
|||
ADD COLUMN IF NOT EXISTS goods_id INT(11) NULL COMMENT '商品ID' AFTER coupon_id; |
|||
|
|||
ALTER TABLE shop_coupon_apply_item |
|||
ADD COLUMN IF NOT EXISTS category_id INT(11) NULL COMMENT '分类ID' AFTER goods_id; |
|||
|
|||
-- 2. 添加索引 |
|||
CREATE INDEX IF NOT EXISTS idx_coupon_apply_item_goods ON shop_coupon_apply_item(coupon_id, goods_id); |
|||
CREATE INDEX IF NOT EXISTS idx_coupon_apply_item_category ON shop_coupon_apply_item(coupon_id, category_id); |
|||
CREATE INDEX IF NOT EXISTS idx_coupon_apply_item_type ON shop_coupon_apply_item(coupon_id, type); |
|||
|
|||
-- 3. 检查表结构 |
|||
DESCRIBE shop_coupon_apply_item; |
Loading…
Reference in new issue