fix(order): validate V5Pay prefix before case folding

This commit is contained in:
zhx 2026-07-10 20:43:51 +08:00
parent 534574eb71
commit 58dd20c70a
2 changed files with 13 additions and 4 deletions

View File

@ -41,12 +41,12 @@ public final class V5PayOrderNoUtils {
private static String normalizedPrefix(String prefix) {
String value = Objects.toString(prefix, DEFAULT_PREFIX).trim();
String normalized = (value.isBlank() ? DEFAULT_PREFIX : value).toUpperCase(Locale.ROOT);
if (!PREFIX_PATTERN.matcher(normalized).matches()) {
// 无分隔订单号若允许数字前缀会产生命名空间碰撞符号和 Unicode 同样不符合支付方格式
String rawPrefix = value.isBlank() ? DEFAULT_PREFIX : value;
if (!PREFIX_PATTERN.matcher(rawPrefix).matches()) {
// 必须在大小写转换前校验原文否则 ı/ß Unicode 可能折叠成 ASCII 并与合法命名空间碰撞
throw new IllegalArgumentException("V5Pay order prefix must contain only ASCII letters");
}
return normalized;
return rawPrefix.toUpperCase(Locale.ROOT);
}
private static boolean isValidLocalOrderNo(String localOrderNo) {

View File

@ -48,6 +48,15 @@ public class V5PaySignUtilsTest {
assertInvalidOrderNo("1ASLAN", "23");
}
@Test
public void unicodeCaseFoldingCannotAliasAsciiNamespace() {
Assert.assertEquals("ASLANI23", V5PayOrderNoUtils.providerOrderNo("aslani", "23"));
Assert.assertEquals("ASSLAN23", V5PayOrderNoUtils.providerOrderNo("asslan", "23"));
// Java 大写会将 dotless-i sharp-s 折叠成 ASCII原文校验必须在转换之前完成
assertInvalidOrderNo("aslanı", "23");
assertInvalidOrderNo("aßlan", "23");
}
@Test
public void orderParserRejectsOtherNamespaceEmptyAndIllegalCharacters() {
Assert.assertEquals("", V5PayOrderNoUtils.localOrderNo("ASLAN", "LALU123"));