更新完成:优化微信支付证书读取机制等等
This commit is contained in:
111
docs/SERVER_URL_REFACTOR_SUMMARY.md
Normal file
111
docs/SERVER_URL_REFACTOR_SUMMARY.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# 服务器URL配置重构总结
|
||||
|
||||
## 概述
|
||||
将项目中硬编码的服务器地址 `https://server.gxwebsoft.com/api` 改为从配置文件读取,提高了代码的可维护性和灵活性。
|
||||
|
||||
## 修改的文件
|
||||
|
||||
### 1. RequestUtil.java
|
||||
**文件路径**: `src/main/java/com/gxwebsoft/common/core/utils/RequestUtil.java`
|
||||
|
||||
**修改内容**:
|
||||
- 添加了 `ConfigProperties` 依赖注入
|
||||
- 移除了硬编码的 `host` 常量
|
||||
- 添加了 `getServerUrl()` 方法
|
||||
- 将所有 `host.concat(path)` 替换为 `getServerUrl().concat(path)`
|
||||
|
||||
**影响的方法**:
|
||||
- `balancePay()`
|
||||
- `getUserByPhone()`
|
||||
- `getByUserId()`
|
||||
- `saveUserByPhone()`
|
||||
- `updateUserBalance()`
|
||||
- `getParent()`
|
||||
- `updateUser()`
|
||||
- `getMpOrderQrCode()`
|
||||
- `getOrderQRCodeUnlimited()`
|
||||
- `updateUserMerchantId()`
|
||||
- `getWxConfig()`
|
||||
|
||||
### 2. JwtAuthenticationFilter.java
|
||||
**文件路径**: `src/main/java/com/gxwebsoft/common/core/security/JwtAuthenticationFilter.java`
|
||||
|
||||
**修改内容**:
|
||||
- 将硬编码的URL `"https://server.gxwebsoft.com/api/auth/user"`
|
||||
- 改为 `configProperties.getServerUrl() + "/auth/user"`
|
||||
|
||||
### 3. OaAppController.java
|
||||
**文件路径**: `src/main/java/com/gxwebsoft/oa/controller/OaAppController.java`
|
||||
|
||||
**修改内容**:
|
||||
- 添加了 `ConfigProperties` 依赖注入
|
||||
- 将硬编码的URL `"https://server.gxwebsoft.com/api/file/page"`
|
||||
- 改为 `configProperties.getServerUrl() + "/file/page"`
|
||||
|
||||
### 4. SwaggerConfig.java
|
||||
**文件路径**: `src/main/java/com/gxwebsoft/common/core/config/SwaggerConfig.java`
|
||||
|
||||
**修改内容**:
|
||||
- 将硬编码的URL `"https://server.gxwebsoft.com/api/system"`
|
||||
- 改为 `config.getServerUrl() + "/system"`
|
||||
|
||||
### 5. WxOfficialUtil.java
|
||||
**文件路径**: `src/main/java/com/gxwebsoft/common/core/utils/WxOfficialUtil.java`
|
||||
|
||||
**修改内容**:
|
||||
- 将硬编码的URL `"https://server.gxwebsoft.com/api/open/wx-official/accessToken"`
|
||||
- 改为 `pathConfig.getServerUrl() + "/open/wx-official/accessToken"`
|
||||
|
||||
### 6. ShopOrderServiceImpl.java
|
||||
**文件路径**: `src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java`
|
||||
|
||||
**修改内容**:
|
||||
- 将微信支付回调地址中的硬编码URL
|
||||
- 从 `"https://server.gxwebsoft.com/api/system/wx-pay/notify/"`
|
||||
- 改为 `config.getServerUrl() + "/system/wx-pay/notify/"`
|
||||
|
||||
## 配置文件设置
|
||||
|
||||
### 开发环境 (application-dev.yml)
|
||||
```yaml
|
||||
config:
|
||||
server-url: http://127.0.0.1:9091/api
|
||||
```
|
||||
|
||||
### 生产环境 (application-prod.yml)
|
||||
```yaml
|
||||
config:
|
||||
server-url: https://server.gxwebsoft.com/api
|
||||
```
|
||||
|
||||
### 默认配置 (application.yml)
|
||||
```yaml
|
||||
config:
|
||||
server-url: https://server.gxwebsoft.com/api
|
||||
```
|
||||
|
||||
## 优势
|
||||
|
||||
1. **可维护性**: 服务器地址集中管理,修改时只需要更新配置文件
|
||||
2. **环境适配**: 不同环境可以使用不同的服务器地址
|
||||
3. **部署灵活**: 部署时可以通过环境变量或外部配置文件覆盖
|
||||
4. **代码清洁**: 移除了硬编码,提高了代码质量
|
||||
|
||||
## 测试验证
|
||||
|
||||
创建了测试类 `ServerUrlConfigTest` 来验证配置是否正确读取:
|
||||
- 验证配置属性不为空
|
||||
- 验证URL格式正确
|
||||
- 验证开发环境使用本地地址
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 确保所有环境的配置文件都正确设置了 `server-url`
|
||||
2. 部署时需要根据实际环境调整配置
|
||||
3. 如果有新的代码需要调用服务器API,应该使用 `ConfigProperties.getServerUrl()` 而不是硬编码
|
||||
|
||||
## 后续建议
|
||||
|
||||
1. 可以考虑将其他硬编码的URL也进行类似的重构
|
||||
2. 建立代码规范,禁止在代码中硬编码URL
|
||||
3. 在CI/CD流程中添加检查,确保没有新的硬编码URL被引入
|
||||
79
docs/start_frp.sh
Executable file
79
docs/start_frp.sh
Executable file
@@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
cd /Users/gxwebsoft/frp/frp_0.63.0_darwin_arm64
|
||||
|
||||
echo "=== FRP客户端启动脚本 ==="
|
||||
|
||||
# 检查是否已有frpc进程运行
|
||||
if pgrep -f "frpc" > /dev/null; then
|
||||
echo "⚠️ 检测到frpc进程正在运行:"
|
||||
ps aux | grep frpc | grep -v grep
|
||||
echo ""
|
||||
echo "正在停止现有进程..."
|
||||
pkill -f frpc
|
||||
sleep 3
|
||||
|
||||
# 再次检查是否还有进程
|
||||
if pgrep -f "frpc" > /dev/null; then
|
||||
echo "❌ 无法停止现有进程,强制终止..."
|
||||
pkill -9 -f frpc
|
||||
sleep 2
|
||||
fi
|
||||
fi
|
||||
|
||||
# 检查配置文件是否存在(优先使用toml格式)
|
||||
CONFIG_FILE=""
|
||||
if [ -f "frpc.toml" ]; then
|
||||
CONFIG_FILE="frpc.toml"
|
||||
elif [ -f "frpc.ini" ]; then
|
||||
CONFIG_FILE="frpc.ini"
|
||||
else
|
||||
echo "❌ 错误:配置文件不存在(frpc.toml 或 frpc.ini)"
|
||||
echo "当前目录: $(pwd)"
|
||||
echo "目录内容:"
|
||||
ls -la
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📋 配置文件检查通过,使用: $CONFIG_FILE"
|
||||
|
||||
# 清理旧的日志文件
|
||||
if [ -f "frpc.log" ]; then
|
||||
mv frpc.log frpc.log.old
|
||||
fi
|
||||
|
||||
# 后台启动frpc客户端
|
||||
echo "🚀 正在启动FRP客户端..."
|
||||
nohup ./frpc -c $CONFIG_FILE > frpc.log 2>&1 &
|
||||
FRP_PID=$!
|
||||
|
||||
# 等待启动
|
||||
sleep 3
|
||||
|
||||
# 检查是否启动成功
|
||||
if pgrep -f "frpc" > /dev/null; then
|
||||
echo "✅ FRP客户端启动成功!"
|
||||
echo "📊 进程信息:"
|
||||
ps aux | grep frpc | grep -v grep
|
||||
echo ""
|
||||
echo "📄 日志文件: $(pwd)/frpc.log"
|
||||
echo "🔍 查看实时日志: tail -f $(pwd)/frpc.log"
|
||||
echo ""
|
||||
echo "📋 最新日志内容:"
|
||||
echo "----------------------------------------"
|
||||
tail -10 frpc.log
|
||||
echo "----------------------------------------"
|
||||
else
|
||||
echo "❌ FRP客户端启动失败!"
|
||||
echo "📄 错误日志:"
|
||||
echo "----------------------------------------"
|
||||
cat frpc.log
|
||||
echo "----------------------------------------"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🔧 常用管理命令:"
|
||||
echo " 查看进程: ps aux | grep frpc"
|
||||
echo " 停止服务: pkill -f frpc"
|
||||
echo " 查看日志: tail -f $(pwd)/frpc.log"
|
||||
echo " 检查端口: lsof -i | grep frp"
|
||||
@@ -37,7 +37,7 @@ public class SwaggerConfig {
|
||||
.name("科技小王子")
|
||||
.url("https://www.gxwebsoft.com")
|
||||
.email("170083662@qq.com"))
|
||||
.termsOfService("https://server.gxwebsoft.com/api/system"))
|
||||
.termsOfService(config.getServerUrl() + "/system"))
|
||||
.components(new Components()
|
||||
.addSecuritySchemes("Authorization",
|
||||
new SecurityScheme()
|
||||
|
||||
@@ -63,7 +63,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
map.put("username", jwtSubject.getUsername());
|
||||
map.put("tenantId", jwtSubject.getTenantId());
|
||||
// 链式构建请求
|
||||
String result = HttpRequest.post("https://server.gxwebsoft.com/api/auth/user")
|
||||
String result = HttpRequest.post(configProperties.getServerUrl() + "/auth/user")
|
||||
.header("Authorization", access_token)
|
||||
.header("Tenantid", jwtSubject.getTenantId().toString())
|
||||
.body(JSONUtil.toJSONString(map))//表单内容
|
||||
|
||||
@@ -44,7 +44,7 @@ public class PaymentCacheService {
|
||||
|
||||
if (ObjectUtil.isNotEmpty(payment)) {
|
||||
log.debug("从缓存获取支付配置成功: {}", primaryKey);
|
||||
// return payment;
|
||||
return payment;
|
||||
}
|
||||
|
||||
// 2. 如果 Payment:1* 格式不存在,尝试原有格式
|
||||
@@ -55,7 +55,7 @@ public class PaymentCacheService {
|
||||
log.debug("从兜底缓存获取支付配置成功: {}", fallbackKey);
|
||||
// 将查询结果缓存到 Payment:1* 格式
|
||||
redisUtil.set(primaryKey, payment);
|
||||
// return payment;
|
||||
return payment;
|
||||
}
|
||||
|
||||
// 3. 最后从数据库查询
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.gxwebsoft.common.core.utils;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.gxwebsoft.common.core.config.ConfigProperties;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.system.entity.Payment;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
@@ -9,6 +10,7 @@ import com.gxwebsoft.common.system.entity.UserRole;
|
||||
import com.gxwebsoft.shop.entity.ShopOrder;
|
||||
import com.gxwebsoft.shop.entity.ShopMerchantAccount;
|
||||
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -16,7 +18,10 @@ import java.util.HashMap;
|
||||
|
||||
@Component
|
||||
public class RequestUtil {
|
||||
private static final String host = "https://server.gxwebsoft.com/api";
|
||||
|
||||
@Autowired
|
||||
private ConfigProperties configProperties;
|
||||
|
||||
private static String ACCESS_TOKEN;
|
||||
private static String TENANT_ID;
|
||||
|
||||
@@ -28,6 +33,10 @@ public class RequestUtil {
|
||||
ACCESS_TOKEN = token;
|
||||
}
|
||||
|
||||
private String getServerUrl() {
|
||||
return configProperties.getServerUrl();
|
||||
}
|
||||
|
||||
// 预付请求付款(余额支付)
|
||||
public Object balancePay(ShopOrder order) {
|
||||
// 设置租户ID
|
||||
@@ -38,7 +47,7 @@ public class RequestUtil {
|
||||
String path = "/system/payment/balancePay";
|
||||
try {
|
||||
// 链式构建请求
|
||||
final String body = HttpRequest.post(host.concat(path))
|
||||
final String body = HttpRequest.post(getServerUrl().concat(path))
|
||||
.header("Tenantid", TENANT_ID)
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.body(JSONUtil.toJSONString(order))//表单内容
|
||||
@@ -77,7 +86,7 @@ public class RequestUtil {
|
||||
String path = "/system/user/getByPhone/" + phone;
|
||||
try {
|
||||
// 链式构建请求
|
||||
String result = HttpRequest.get(host.concat(path))
|
||||
String result = HttpRequest.get(getServerUrl().concat(path))
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.header("Tenantid", TENANT_ID)
|
||||
.timeout(20000)//超时,毫秒
|
||||
@@ -96,7 +105,7 @@ public class RequestUtil {
|
||||
String path = "/system/user/" + userId;
|
||||
try {
|
||||
// 链式构建请求
|
||||
String result = HttpRequest.get(host.concat(path))
|
||||
String result = HttpRequest.get(getServerUrl().concat(path))
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.header("Tenantid", TENANT_ID)
|
||||
.timeout(20000)//超时,毫秒
|
||||
@@ -131,7 +140,7 @@ public class RequestUtil {
|
||||
map.put("roles", roles);
|
||||
map.put("tenantId", TENANT_ID);
|
||||
// 链式构建请求
|
||||
String result = HttpRequest.post(host.concat(path))
|
||||
String result = HttpRequest.post(getServerUrl().concat(path))
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.header("Tenantid", TENANT_ID)
|
||||
.body(JSONUtil.toJSONString(map))//表单内容
|
||||
@@ -147,7 +156,7 @@ public class RequestUtil {
|
||||
public ApiResult<?> updateUserBalance(String path, User user) {
|
||||
try {
|
||||
// 链式构建请求
|
||||
final String body = HttpRequest.put(host.concat(path))
|
||||
final String body = HttpRequest.put(getServerUrl().concat(path))
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.header("Tenantid", TENANT_ID)
|
||||
.body(JSONUtil.toJSONString(user))
|
||||
@@ -163,7 +172,7 @@ public class RequestUtil {
|
||||
public User getParent(Integer userId) {
|
||||
try {
|
||||
// 链式构建请求
|
||||
final String result = HttpRequest.get(host.concat("/system/user-referee/getReferee/" + userId))
|
||||
final String result = HttpRequest.get(getServerUrl().concat("/system/user-referee/getReferee/" + userId))
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.header("Tenantid", TENANT_ID)
|
||||
.timeout(20000)
|
||||
@@ -182,7 +191,7 @@ public class RequestUtil {
|
||||
String path = "/system/user/";
|
||||
try {
|
||||
// 链式构建请求
|
||||
final String body = HttpRequest.put(host.concat(path))
|
||||
final String body = HttpRequest.put(getServerUrl().concat(path))
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.header("Tenantid", TENANT_ID)
|
||||
.body(JSONUtil.toJSONString(user))
|
||||
@@ -197,7 +206,7 @@ public class RequestUtil {
|
||||
String path = "/wx-login/getOrderQRCode/";
|
||||
try {
|
||||
// 链式构建请求
|
||||
final String body = HttpRequest.get(host.concat(path).concat(orderNo))
|
||||
final String body = HttpRequest.get(getServerUrl().concat(path).concat(orderNo))
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.header("tenantId", TENANT_ID)
|
||||
.timeout(20000)
|
||||
@@ -215,7 +224,7 @@ public class RequestUtil {
|
||||
String path = "/wx-login/getOrderQRCodeUnlimited/";
|
||||
try {
|
||||
// 链式构建请求
|
||||
final String body = HttpRequest.get(host.concat(path).concat(orderNo))
|
||||
final String body = HttpRequest.get(getServerUrl().concat(path).concat(orderNo))
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.header("tenantId", TENANT_ID)
|
||||
.timeout(20000)
|
||||
@@ -235,7 +244,7 @@ public class RequestUtil {
|
||||
String path = "/system/user/updateUserMerchantId";
|
||||
try {
|
||||
// 链式构建请求
|
||||
final String body = HttpRequest.put(host.concat(path))
|
||||
final String body = HttpRequest.put(getServerUrl().concat(path))
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.header("tenantId", TENANT_ID)
|
||||
.body(JSONUtil.toJSONString(user))
|
||||
@@ -250,7 +259,7 @@ public class RequestUtil {
|
||||
String path = "/system/setting?settingKey=mp-weixin";
|
||||
try {
|
||||
// 链式构建请求
|
||||
final String body = HttpRequest.get(host.concat(path))
|
||||
final String body = HttpRequest.get(getServerUrl().concat(path))
|
||||
.header("Authorization", ACCESS_TOKEN)
|
||||
.header("tenantId", TENANT_ID)
|
||||
.timeout(20000)
|
||||
|
||||
@@ -72,7 +72,7 @@ public class WxOfficialUtil {
|
||||
}
|
||||
|
||||
public String getCodeUrl() throws UnsupportedEncodingException {
|
||||
String encodedReturnUrl = URLEncoder.encode("https://server.gxwebsoft.com/api/open/wx-official/accessToken","UTF-8");
|
||||
String encodedReturnUrl = URLEncoder.encode(pathConfig.getServerUrl() + "/open/wx-official/accessToken","UTF-8");
|
||||
return "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+ this.appId +"&redirect_uri=" + encodedReturnUrl + "&response_type=code&scope=snsapi_userinfo&state="+ this.tenantId +"#wechat_redirect";
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import cn.hutool.http.HttpRequest;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.gxwebsoft.common.core.config.ConfigProperties;
|
||||
import com.gxwebsoft.common.core.security.JwtUtil;
|
||||
import com.gxwebsoft.common.core.utils.CommonUtil;
|
||||
import com.gxwebsoft.common.core.utils.RedisUtil;
|
||||
@@ -59,6 +60,8 @@ public class OaAppController extends BaseController {
|
||||
private OaAppUserService oaAppUserService;
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
@Resource
|
||||
private ConfigProperties configProperties;
|
||||
|
||||
@PreAuthorize("hasAuthority('oa:app:list')")
|
||||
@Operation(summary = "分页查询应用")
|
||||
@@ -249,7 +252,7 @@ public class OaAppController extends BaseController {
|
||||
// 读取项目附件(链式构建GET请求)
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("appId", d.getAppId());
|
||||
final String build = UrlBuilder.of("https://server.gxwebsoft.com/api/file/page").setQuery(new UrlQuery(map)).build();
|
||||
final String build = UrlBuilder.of(configProperties.getServerUrl() + "/file/page").setQuery(new UrlQuery(map)).build();
|
||||
String response = HttpRequest.get(build)
|
||||
.header("Authorization", param.getToken())
|
||||
.header("Tenantid", d.getTenantId().toString())
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.gxwebsoft.common.core.config.ConfigProperties;
|
||||
import com.gxwebsoft.common.core.config.CertificateProperties;
|
||||
import com.gxwebsoft.common.core.utils.RedisUtil;
|
||||
import com.gxwebsoft.common.core.utils.CertificateLoader;
|
||||
import com.gxwebsoft.common.core.utils.WechatCertAutoConfig;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.system.entity.Payment;
|
||||
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
|
||||
@@ -24,8 +25,8 @@ import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.wechat.pay.java.core.notification.NotificationConfig;
|
||||
import com.wechat.pay.java.core.notification.NotificationParser;
|
||||
import com.wechat.pay.java.core.notification.RSANotificationConfig;
|
||||
import com.wechat.pay.java.core.notification.RequestParam;
|
||||
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
||||
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@@ -67,6 +68,8 @@ public class ShopOrderController extends BaseController {
|
||||
private CertificateProperties certConfig;
|
||||
@Resource
|
||||
private CertificateLoader certificateLoader;
|
||||
@Resource
|
||||
private WechatCertAutoConfig wechatCertAutoConfig;
|
||||
@Value("${spring.profiles.active}")
|
||||
String active;
|
||||
|
||||
@@ -210,26 +213,14 @@ public class ShopOrderController extends BaseController {
|
||||
String key = "Payment:1:".concat(tenantId.toString());
|
||||
Payment payment = redisUtil.get(key, Payment.class);
|
||||
|
||||
// 证书配置
|
||||
String apiV3Key;
|
||||
String apiclientCert;
|
||||
|
||||
// 开发环境 - 使用证书加载器
|
||||
if (active.equals("dev")) {
|
||||
apiV3Key = certConfig.getWechatPay().getDev().getApiV3Key();
|
||||
apiclientCert = certificateLoader.loadCertificatePath(
|
||||
certConfig.getWechatPayCertPath(certConfig.getWechatPay().getDev().getWechatpayCertFile()));
|
||||
} else {
|
||||
// 生产环境
|
||||
if (ObjectUtil.isNotEmpty(payment)) {
|
||||
apiV3Key = payment.getApiKey();
|
||||
apiclientCert = certificateLoader.loadCertificatePath(
|
||||
conf.getUploadPath().concat("/file").concat(payment.getApiclientCert()));
|
||||
} else {
|
||||
throw new RuntimeException("生产环境未找到支付配置信息");
|
||||
}
|
||||
// 检查支付配置
|
||||
if (ObjectUtil.isEmpty(payment)) {
|
||||
throw new RuntimeException("未找到租户支付配置信息,租户ID: " + tenantId);
|
||||
}
|
||||
|
||||
logger.info("开始处理微信支付异步通知 - 租户ID: {}", tenantId);
|
||||
logger.info("支付配置信息 - 商户号: {}, 应用ID: {}", payment.getMchId(), payment.getAppId());
|
||||
|
||||
RequestParam requestParam = new RequestParam.Builder()
|
||||
.serialNumber(header.get("wechatpay-serial"))
|
||||
.nonce(header.get("wechatpay-nonce"))
|
||||
@@ -238,12 +229,51 @@ public class ShopOrderController extends BaseController {
|
||||
.body(body)
|
||||
.build();
|
||||
|
||||
// 如果已经初始化了 RSAAutoCertificateConfig,可直接使用
|
||||
// 没有的话,则构造一个
|
||||
NotificationConfig config = new RSANotificationConfig.Builder()
|
||||
.apiV3Key(apiV3Key)
|
||||
.certificatesFromPath(apiclientCert)
|
||||
.build();
|
||||
// 创建通知配置 - 使用与下单方法相同的证书配置逻辑
|
||||
NotificationConfig config;
|
||||
try {
|
||||
if (active.equals("dev")) {
|
||||
// 开发环境 - 构建包含租户号的私钥路径
|
||||
String tenantCertPath = "dev/wechat/" + tenantId;
|
||||
String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
|
||||
String privateKey = certificateLoader.loadCertificatePath(privateKeyPath);
|
||||
String apiV3Key = certConfig.getWechatPay().getDev().getApiV3Key();
|
||||
|
||||
// 使用自动证书配置
|
||||
config = new RSAAutoCertificateConfig.Builder()
|
||||
.merchantId(payment.getMchId())
|
||||
.privateKeyFromPath(privateKey)
|
||||
.merchantSerialNumber(payment.getMerchantSerialNumber())
|
||||
.apiV3Key(apiV3Key)
|
||||
.build();
|
||||
|
||||
logger.info("开发环境使用自动证书配置创建通知解析器");
|
||||
} else {
|
||||
// 生产环境 - 使用自动证书配置
|
||||
final String certRootPath = certConfig.getCertRootPath();
|
||||
final String certBasePath = certRootPath + "/file";
|
||||
|
||||
String privateKeyRelativePath = payment.getApiclientKey();
|
||||
String privateKeyFullPath = privateKeyRelativePath.startsWith("/")
|
||||
? certBasePath + privateKeyRelativePath
|
||||
: certBasePath + "/" + privateKeyRelativePath;
|
||||
String privateKey = certificateLoader.loadCertificatePath(privateKeyFullPath);
|
||||
String apiV3Key = payment.getApiKey();
|
||||
|
||||
// 使用自动证书配置
|
||||
config = new RSAAutoCertificateConfig.Builder()
|
||||
.merchantId(payment.getMchId())
|
||||
.privateKeyFromPath(privateKey)
|
||||
.merchantSerialNumber(payment.getMerchantSerialNumber())
|
||||
.apiV3Key(apiV3Key)
|
||||
.build();
|
||||
|
||||
logger.info("生产环境使用自动证书配置创建通知解析器");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("创建通知配置失败", e);
|
||||
throw new RuntimeException("微信支付通知配置失败: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
// 初始化 NotificationParser
|
||||
NotificationParser parser = new NotificationParser(config);
|
||||
|
||||
@@ -143,7 +143,7 @@ import com.gxwebsoft.common.core.service.PaymentCacheService;
|
||||
final Payer payer = new Payer();
|
||||
payer.setOpenid(order.getOpenid());
|
||||
request.setPayer(payer);
|
||||
request.setNotifyUrl("https://server.gxwebsoft.com/api/system/wx-pay/notify/" + order.getTenantId()); // 默认回调地址
|
||||
request.setNotifyUrl(config.getServerUrl() + "/system/wx-pay/notify/" + order.getTenantId()); // 默认回调地址
|
||||
// 测试环境
|
||||
if (active.equals("dev")) {
|
||||
amount.setTotal(1);
|
||||
|
||||
@@ -44,7 +44,7 @@ mqtt:
|
||||
# 框架配置
|
||||
config:
|
||||
# 生产环境接口
|
||||
server-url: https://server.gxwebsoft.com/api
|
||||
server-url: https://server.s209.websoft.top/api
|
||||
upload-path: /www/wwwroot/file.ws/
|
||||
|
||||
# 阿里云OSS云存储
|
||||
|
||||
@@ -106,9 +106,9 @@ config:
|
||||
swagger-version: 2.0
|
||||
token-key: WLgNsWJ8rPjRtnjzX/Gx2RGS80Kwnm/ZeLbvIL+NrBs=
|
||||
# 主服务器
|
||||
server-url: https://server.gxwebsoft.com/api
|
||||
server-url: https://server.s209.websoft.top/api
|
||||
# 文件服务器
|
||||
file-server: https://file.websoft.top
|
||||
file-server: https://file.wsdns.cn
|
||||
upload-path: /Users/gxwebsoft/Documents/uploads/
|
||||
local-upload-path: /Users/gxwebsoft/Documents/uploads/
|
||||
|
||||
@@ -170,4 +170,3 @@ certificate:
|
||||
app-cert-public-key-file: "appCertPublicKey.crt"
|
||||
alipay-cert-public-key-file: "alipayCertPublicKey.crt"
|
||||
alipay-root-cert-file: "alipayRootCert.crt"
|
||||
|
||||
|
||||
51
src/test/java/com/gxwebsoft/config/ServerUrlConfigTest.java
Normal file
51
src/test/java/com/gxwebsoft/config/ServerUrlConfigTest.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package com.gxwebsoft.config;
|
||||
|
||||
import com.gxwebsoft.common.core.config.ConfigProperties;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* 服务器URL配置测试
|
||||
* 验证server-url配置是否正确从配置文件读取
|
||||
*/
|
||||
@SpringBootTest
|
||||
@ActiveProfiles("dev")
|
||||
public class ServerUrlConfigTest {
|
||||
|
||||
@Autowired
|
||||
private ConfigProperties configProperties;
|
||||
|
||||
@Test
|
||||
public void testServerUrlConfiguration() {
|
||||
// 验证配置属性不为空
|
||||
assertNotNull(configProperties, "ConfigProperties should not be null");
|
||||
|
||||
// 验证server-url配置正确读取
|
||||
String serverUrl = configProperties.getServerUrl();
|
||||
assertNotNull(serverUrl, "Server URL should not be null");
|
||||
assertFalse(serverUrl.isEmpty(), "Server URL should not be empty");
|
||||
|
||||
// 在开发环境下,应该是本地地址
|
||||
assertTrue(serverUrl.contains("127.0.0.1") || serverUrl.contains("localhost"),
|
||||
"In dev environment, server URL should contain localhost or 127.0.0.1");
|
||||
|
||||
System.out.println("当前配置的服务器URL: " + serverUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerUrlFormat() {
|
||||
String serverUrl = configProperties.getServerUrl();
|
||||
|
||||
// 验证URL格式
|
||||
assertTrue(serverUrl.startsWith("http://") || serverUrl.startsWith("https://"),
|
||||
"Server URL should start with http:// or https://");
|
||||
assertTrue(serverUrl.endsWith("/api"),
|
||||
"Server URL should end with /api");
|
||||
|
||||
System.out.println("服务器URL格式验证通过: " + serverUrl);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user