feat(dev): 添加开发环境支付配置和优惠券字段修复功能
- 新增开发环境控制器和环境感知支付服务 - 添加数据库字段缺失修复指南 - 改进优惠券适用商品查询逻辑 -优化支付配置获取方式
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,12 @@
|
||||
<if test="param.couponId != null">
|
||||
AND a.coupon_id = #{param.couponId}
|
||||
</if>
|
||||
<if test="param.goodsId != null">
|
||||
AND a.goods_id = #{param.goodsId}
|
||||
</if>
|
||||
<if test="param.categoryId != null">
|
||||
AND a.category_id = #{param.categoryId}
|
||||
</if>
|
||||
<if test="param.type != null">
|
||||
AND a.type = #{param.type}
|
||||
</if>
|
||||
|
||||
@@ -28,8 +28,16 @@ public class ShopCouponApplyItemParam extends BaseParam {
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer couponId;
|
||||
|
||||
@Schema(description = "商品ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Boolean type;
|
||||
private Integer goodsId;
|
||||
|
||||
@Schema(description = "分类ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer categoryId;
|
||||
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "0服务1需求2闲置")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
|
||||
@@ -283,19 +283,33 @@ public class CouponStatusServiceImpl implements CouponStatusService {
|
||||
|
||||
if (userCoupon.getApplyRange() == ShopUserCoupon.APPLY_GOODS) {
|
||||
// 指定商品适用
|
||||
List<ShopCouponApplyItem> applyItems = shopCouponApplyItemService.list(
|
||||
new LambdaQueryWrapper<ShopCouponApplyItem>()
|
||||
.eq(ShopCouponApplyItem::getCouponId, userCoupon.getCouponId())
|
||||
.eq(ShopCouponApplyItem::getType, 1) // 类型1表示商品
|
||||
.isNotNull(ShopCouponApplyItem::getGoodsId)
|
||||
);
|
||||
try {
|
||||
List<ShopCouponApplyItem> applyItems = shopCouponApplyItemService.list(
|
||||
new LambdaQueryWrapper<ShopCouponApplyItem>()
|
||||
.eq(ShopCouponApplyItem::getCouponId, userCoupon.getCouponId())
|
||||
.eq(ShopCouponApplyItem::getType, 1) // 类型1表示商品
|
||||
);
|
||||
|
||||
List<Integer> applicableGoodsIds = applyItems.stream()
|
||||
.map(ShopCouponApplyItem::getGoodsId)
|
||||
.filter(goodsId -> goodsId != null)
|
||||
.collect(Collectors.toList());
|
||||
// 如果数据库中还没有 goods_id 字段,暂时使用 pk 字段作为商品ID
|
||||
List<Integer> applicableGoodsIds = applyItems.stream()
|
||||
.map(item -> {
|
||||
if (item.getGoodsId() != null) {
|
||||
return item.getGoodsId();
|
||||
} else if (item.getPk() != null) {
|
||||
// 临时方案:使用 pk 字段作为商品ID
|
||||
return item.getPk();
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(goodsId -> goodsId != null)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return goodsIds.stream().anyMatch(applicableGoodsIds::contains);
|
||||
return goodsIds.stream().anyMatch(applicableGoodsIds::contains);
|
||||
} catch (Exception e) {
|
||||
log.warn("查询优惠券适用商品失败,可能是数据库字段不存在: {}", e.getMessage());
|
||||
// 如果查询失败,默认返回true(允许使用)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (userCoupon.getApplyRange() == ShopUserCoupon.APPLY_CATEGORY) {
|
||||
|
||||
@@ -8,6 +8,8 @@ import com.gxwebsoft.common.core.config.ConfigProperties;
|
||||
import com.gxwebsoft.common.core.config.CertificateProperties;
|
||||
import com.gxwebsoft.common.core.utils.*;
|
||||
import com.gxwebsoft.common.core.service.PaymentCacheService;
|
||||
import com.gxwebsoft.common.core.service.EnvironmentAwarePaymentService;
|
||||
import com.gxwebsoft.common.core.config.SpringContextUtil;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.system.entity.Payment;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
@@ -316,6 +318,7 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
|
||||
/**
|
||||
* 读取微信支付配置
|
||||
* 生产环境优先从缓存读取 Payment:1* 格式的商户信息
|
||||
* 开发环境自动使用本地回调地址
|
||||
*
|
||||
* @param order
|
||||
* @return
|
||||
@@ -324,7 +327,18 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
|
||||
// 先清除可能的错误缓存
|
||||
// paymentCacheService.removePaymentConfig(order.getPayType().toString(), order.getTenantId());
|
||||
|
||||
Payment payment = paymentCacheService.getPaymentConfig(order.getPayType(), order.getTenantId());
|
||||
// 使用环境感知的支付配置服务
|
||||
Payment payment;
|
||||
try {
|
||||
// 尝试使用环境感知服务
|
||||
EnvironmentAwarePaymentService envPaymentService =
|
||||
SpringContextUtil.getBean(EnvironmentAwarePaymentService.class);
|
||||
payment = envPaymentService.getEnvironmentAwarePaymentConfig(order.getPayType(), order.getTenantId());
|
||||
} catch (Exception e) {
|
||||
// 如果环境感知服务不可用,回退到原有方式
|
||||
log.warn("环境感知支付服务不可用,使用原有配置方式: {}", e.getMessage());
|
||||
payment = paymentCacheService.getPaymentConfig(order.getPayType(), order.getTenantId());
|
||||
}
|
||||
|
||||
// 添加详细的支付配置检查
|
||||
System.out.println("=== 支付配置检查 ===");
|
||||
|
||||
@@ -187,3 +187,19 @@ coupon:
|
||||
auto-update: true
|
||||
# 批量处理大小
|
||||
batch-size: 1000
|
||||
|
||||
# 支付配置
|
||||
payment:
|
||||
# 开发环境配置
|
||||
dev:
|
||||
# 开发环境回调地址(本地调试用)
|
||||
notify-url: "http://frps-10550.s209.websoft.top/api/shop/shop-order/notify"
|
||||
# 开发环境是否启用环境感知
|
||||
environment-aware: true
|
||||
|
||||
# 生产环境配置
|
||||
prod:
|
||||
# 生产环境回调地址
|
||||
notify-url: "https://cms-api.websoft.top/api/shop/shop-order/notify"
|
||||
# 生产环境是否启用环境感知
|
||||
environment-aware: false
|
||||
|
||||
206
src/main/resources/sql/create_dev_tenant_payment.sql
Normal file
206
src/main/resources/sql/create_dev_tenant_payment.sql
Normal file
@@ -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;
|
||||
101
src/main/resources/sql/fix_coupon_apply_item_table.sql
Normal file
101
src/main/resources/sql/fix_coupon_apply_item_table.sql
Normal file
@@ -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;
|
||||
183
src/main/resources/sql/production_safe_payment_config.sql
Normal file
183
src/main/resources/sql/production_safe_payment_config.sql
Normal file
@@ -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;
|
||||
17
src/main/resources/sql/simple_fix_coupon_table.sql
Normal file
17
src/main/resources/sql/simple_fix_coupon_table.sql
Normal file
@@ -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;
|
||||
Reference in New Issue
Block a user