You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

信用卡与账号掩码正则问题:奇数位卡号掩码异常修复请求

修复奇数位信用卡号掩码异常问题

需求背景

需对两类数据进行掩码处理,仅保留最后4位并维持原格式:

  • 信用卡:数字长度12-19位,支持含连字符/空格的格式
  • 账号:数字长度为8或9位

输入输出示例

  • 纯数字信用卡:123456789123 → xxxxxxxx9123
  • 带连字符信用卡:1234-5678-9123-4567 → xxxx-xxxx-xxxx-4567
  • 奇数位带连字符信用卡:1234-5678-9123-4567-891 → xxxx-xxxx-xxxx-xxx7-891
  • 混合文本场景:123123123123131For8640 → xxxxxxxxxx3131For8640
  • 账号:12345678 → xxxx5678
  • HTML嵌套场景:I m paying 2700 dollars with my credit card(<strong>123456789012345</strong>) to my account(<strong>12345678</strong>) → I m paying 2700 dollars with my credit card(<strong>xxxxxxxxxxx2345</strong>) to my account(<strong>xxxx5678</strong>)

现有代码问题

原MaskCreditCardNo方法在处理奇数位数字长度的信用卡号时出现掩码错误:

  • 预期结果:1234-5678-9123-4567-891 → xxxx-xxxx-xxxx-xxx7-891
  • 实际结果:1234-5678-9123-4567-891 → xxxx-xxxx-xxxx-xxxx-891

问题根源:原代码直接通过CCnumber.Substring(0, CCnumber.Length - 4)截取需掩码的部分,但带格式的信用卡号总长度减去4的范围,无法精准对应前N个需要掩码的数字位置(奇数位卡号的最后4位可能包含非数字字符),导致错误替换了本应保留的数字。

修复后的代码

private static string MaskIfAccountNumber(this string text)
{
    if (string.IsNullOrEmpty(text))
        return text;

    return Regex.Replace(text, "[0-9][0-9 ]{6,}[0-9]", match =>
    {
        string digits = string.Concat(match.Value.Where(c => char.IsDigit(c)));
        return digits.Length is 8 or 9 
            ? new string('x', digits.Length - 4) + digits.Substring(digits.Length - 4)
            : match.Value;
    });
}

public static string MaskIfContainCreditCardPanorAcctNum(this string value)
{
    if (string.IsNullOrEmpty(value))
        return value;

    var maskedAccountNumber = value.MaskIfAccountNumber();
    return maskedAccountNumber.MaskCreditCardNo();
}

public static string MaskCreditCardNo(this string value)
{
    if (string.IsNullOrWhiteSpace(value))
        return value;

    return Regex.Replace(value, "(\\d[\\s|-]?){10,}\\d", match =>
    {
        string ccNumber = match.Value;
        string digits = string.Concat(ccNumber.Where(c => char.IsDigit(c)));
        
        if (digits.Length < 12 || digits.Length > 19)
            return match.Value;

        // 收集所有数字在原字符串中的索引
        var digitIndices = ccNumber.Select((c, idx) => new { Char = c, Index = idx })
                                   .Where(x => char.IsDigit(x.Char))
                                   .Select(x => x.Index)
                                   .ToList();
        
        // 标记最后4个数字的索引为需保留的位置
        var keepIndices = digitIndices.Skip(digitIndices.Count - 4).ToHashSet();

        // 遍历替换非保留位的数字为x,保留原格式字符
        char[] result = ccNumber.ToCharArray();
        for (int i = 0; i < result.Length; i++)
        {
            if (char.IsDigit(result[i]) && !keepIndices.Contains(i))
            {
                result[i] = 'x';
            }
        }

        return new string(result);
    });
}

修复逻辑说明

  1. 账号掩码:保留原有逻辑,因账号为纯数字或仅含空格,长度固定,直接替换前长度-4位为x即可。
  2. 信用卡掩码优化:
    • 先提取卡号内所有数字,校验长度是否符合12-19位要求。
    • 定位原字符串中所有数字的索引,筛选出最后4个数字的索引作为保留位。
    • 遍历原卡号字符串,仅将非保留位的数字替换为x,完全保留连字符、空格等格式字符。
    • 该逻辑不受数字位数奇偶性影响,精准定位需保留的最后4位数字,彻底解决原代码的截取错误问题。

内容的提问来源于stack exchange,提问作者user3665818

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 23:05:56