fix(core): 修复LocalDateTime反序列化和微信支付参数验证问题

- 移除JacksonConfig中未使用的LocalDateTimeDeserializer导入
- 增强LocalDateTimeDeserializer支持时间戳格式解析,兼容前端发送的数字时间戳
- 添加构造函数支持自定义日期时间格式器
- 修复ShopDealerWithdrawController中微信支付批次号长度不足问题,使用零填充确保最小长度
- 添加微信支付服务中outBatchNo和outDetailNo参数长度验证规则
- 移除WxTransferService中的冗余代码行
This commit is contained in:
2026-01-29 01:19:51 +08:00
parent d93dd04211
commit 89177db718
4 changed files with 48 additions and 9 deletions

View File

@@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@@ -1,11 +1,14 @@
package com.gxwebsoft.common.core.config;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
/**
@@ -16,14 +19,43 @@ import java.time.format.DateTimeFormatter;
*/
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private final DateTimeFormatter formatter;
public LocalDateTimeDeserializer() {
this(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
public LocalDateTimeDeserializer(DateTimeFormatter formatter) {
this.formatter = formatter;
}
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = p.getValueAsString();
if (value != null && !value.isEmpty()) {
return LocalDateTime.parse(value, FORMATTER);
JsonToken t = p.currentToken();
ZoneId zoneId = ctxt.getTimeZone() != null ? ctxt.getTimeZone().toZoneId() : ZoneId.systemDefault();
// Accept epoch timestamps (seconds or millis) for compatibility with frontends that send numbers.
if (t == JsonToken.VALUE_NUMBER_INT) {
long ts = p.getLongValue();
// Heuristic: 10+ digits is seconds; 13+ digits is millis (most common in JS).
Instant instant = (String.valueOf(Math.abs(ts)).length() >= 13)
? Instant.ofEpochMilli(ts)
: Instant.ofEpochSecond(ts);
return LocalDateTime.ofInstant(instant, zoneId);
}
return null;
String value = p.getValueAsString();
if (value == null || value.isEmpty()) {
return null;
}
// Handle numeric timestamps passed as strings, e.g. "1769618486000"
if (value.chars().allMatch(Character::isDigit)) {
long ts = Long.parseLong(value);
Instant instant = (value.length() >= 13) ? Instant.ofEpochMilli(ts) : Instant.ofEpochSecond(ts);
return LocalDateTime.ofInstant(instant, zoneId);
}
return LocalDateTime.parse(value, formatter);
}
}

View File

@@ -60,9 +60,16 @@ public class WxTransferService {
if (StrUtil.isBlank(outBatchNo) || !outBatchNo.matches("^[0-9A-Za-z]+$")) {
throw PaymentException.paramError("outBatchNo不合法仅允许数字/大小写字母)");
}
// 微信接口限制:商家批次单号长度需在区间内(当前实测最小 5
if (outBatchNo.length() < 5 || outBatchNo.length() > 32) {
throw PaymentException.paramError("outBatchNo长度不合法要求 5-32");
}
if (StrUtil.isBlank(outDetailNo) || !outDetailNo.matches("^[0-9A-Za-z]+$")) {
throw PaymentException.paramError("outDetailNo不合法仅允许数字/大小写字母)");
}
if (outDetailNo.length() > 32) {
throw PaymentException.paramError("outDetailNo长度不合法最大 32");
}
// 微信要求金额单位为“分”,必须为整数
long amountFen = amountYuan
@@ -133,4 +140,3 @@ public class WxTransferService {
return s.substring(0, maxLen);
}
}

View File

@@ -138,8 +138,10 @@ public class ShopDealerWithdrawController extends BaseController {
return fail("用户openid为空无法发起微信转账");
}
String outBatchNo = "WD" + db.getId();
String outDetailNo = "WD" + db.getId() + "D1";
// 微信支付批量转账接口对 out_batch_no 有最小长度限制(当前为 >= 5
// 使用 0 填充,避免如 "WD59" 这种过短导致 PARAM_ERROR。
String outBatchNo = String.format("WD%03d", db.getId());
String outDetailNo = outBatchNo + "D1";
String remark = "分销商提现";
String userName = db.getRealName();