fix: 修复京东账单带说明的金额解析失败

京东交易流水中,全额退款的订单金额会被写成「230.88(已全额退款)」这类带中文说明的文本,原实现直接按数值解析会抛异常,导致这些行被判为不可导入而丢失。现改为从金额文本中提取数值部分,兼容括号说明、货币符号与千分位。

变更内容:
- JdBillParser 金额解析改用正则从文本中提取数值(兼容「数字(说明)」、¥/¥ 符号与千分位逗号),替换原先按字符剔除符号的实现。

说明:
- 仅影响京东账单解析,支付宝、微信等其它解析器未改动。
- 实测京东流水 103 行(含 5 行「已全额退款」)全部可正常解析并导入。
This commit is contained in:
2026-09-30 16:14:08 +08:00
parent 15fd1a263d
commit caa0c01952
@@ -14,6 +14,8 @@ import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@@ -56,8 +58,8 @@ public class JdBillParser implements BillParser {
/** CSV 解析格式:逗号分隔并去除字段首尾空白(含制表符) */ /** CSV 解析格式:逗号分隔并去除字段首尾空白(含制表符) */
private static final CSVFormat CSV_FORMAT = CSVFormat.DEFAULT.builder().setTrim(true).build(); private static final CSVFormat CSV_FORMAT = CSVFormat.DEFAULT.builder().setTrim(true).build();
/** 金额中需要剔除的货币符号与分隔符 */ /** 金额中提取数值的正则:兼容「230.88(已全额退款)」等带说明、含货币符号与千分位的金额 */
private static final String AMOUNT_STRIP_PATTERN = "[¥¥,\\s]"; private static final Pattern AMOUNT_PATTERN = Pattern.compile("[-+]?\\d[\\d,]*(?:\\.\\d+)?");
/** JSON 序列化器,用于生成原始完整数据 */ /** JSON 序列化器,用于生成原始完整数据 */
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
@@ -163,9 +165,11 @@ public class JdBillParser implements BillParser {
String amountStr = get(header, values, COL_AMOUNT); String amountStr = get(header, values, COL_AMOUNT);
if (StringUtils.hasText(amountStr)) { if (StringUtils.hasText(amountStr)) {
try { // 金额可能带「(已全额退款)」等说明,仅提取其中的数值部分
row.setAmount(new BigDecimal(amountStr.replaceAll(AMOUNT_STRIP_PATTERN, ""))); Matcher matcher = AMOUNT_PATTERN.matcher(amountStr);
} catch (NumberFormatException e) { if (matcher.find()) {
row.setAmount(new BigDecimal(matcher.group().replace(",", "")));
} else {
row.setError("金额格式无法解析:" + amountStr); row.setError("金额格式无法解析:" + amountStr);
} }
} }