PAYATHON 2026

Payment jQuery plugin 如何验证 credit card 到期月份

支付老李

结论

月份字段只需检查两点:输入是否为整数,以及数值是否在 1 到 12 之间。原函数末尾的条件表达式不完整,也没有明确返回验证结果,所以函数最终返回 undefined。对它使用 ! 取反后,结果为 true,导致 invalid class 一直存在。

可以直接改成:

$.payment.validateCardMonthExpiry = function (month) {
    if (typeof month === 'object' && month !== null && 'month' in month) {
        month = month.month;
    }

    if (month === undefined || month === null) {
        return false;
    }

    month = $.trim(String(month));

    if (!/^\d{1,2}$/.test(month)) {
        return false;
    }

    month = parseInt(month, 10);

    return month >= 1 && month <= 12;
};

为什么字段始终无效

JavaScript 函数执行完毕时,如果没有遇到 return,就会默认返回 undefined。

调用代码又对返回值做了取反:

!$.payment.validateCardMonthExpiry(...)

也就是:

!undefined === true

所以 toggleClass() 每次都会添加 invalid class。

原函数中的这段代码也不是完整的 JavaScript 条件:

if (!(parseInt(month, 10)   currentTime;

验证月份不需要 currentTime。只验证月份时,只能检查格式和取值范围。要判断信用卡是否已经过期,还需要同时检查年份。

调用方式

如果 #month-holder 就是 <input> 元素,可以继续使用原来的调用方式:

$('#month-holder').toggleClass(
    'invalid',
    !$.payment.validateCardMonthExpiry($('#month-holder').val())
);

对应的 HTML 例如:

<input id="month-holder" type="text" inputmode="numeric" maxlength="2">

需要在输入变化时实时验证,可以这样写:

$('#month-holder').on('input blur', function () {
    $(this).toggleClass(
        'invalid',
        !$.payment.validateCardMonthExpiry($(this).val())
    );
});

如果 #month-holder 是输入框外层的容器,对它调用 .val() 通常会得到空值。这种情况下,应选中容器内实际的输入元素:

var month = $('#month-holder input').val();

$('#month-holder').toggleClass(
    'invalid',
    !$.payment.validateCardMonthExpiry(month)
);

如果还需要判断信用卡是否过期

月份合法不等于信用卡尚未过期。例如,03 是合法月份,但卡片是否过期还取决于年份。可以把月份和年份放在一起验证:

$.payment.validateCardExpiry = function (month, year) {
    if (!$.payment.validateCardMonthExpiry(month)) {
        return false;
    }

    month = parseInt(month, 10);
    year = parseInt(year, 10);

    if (!Number.isInteger(year)) {
        return false;
    }

    var now = new Date();
    var currentMonth = now.getMonth() + 1;
    var currentYear = now.getFullYear();

    return year > currentYear ||
        (year === currentYear && month >= currentMonth);
};

调用示例:

var isValid = $.payment.validateCardExpiry(
    $('#month-holder').val(),
    $('#year-holder').val()
);

$('#month-holder, #year-holder').toggleClass('invalid', !isValid);

信用卡通常在标注月份的最后一天到期。因此,年份和月份与当前年月相同时,一般仍应视为有效。代码使用 month >= currentMonth,而不是 month > currentMonth,原因就在这里。

注意事项

  • 01、1 和 12 都是合法月份。
  • 0、00、13、负数、小数及非数字内容都应返回 false。
  • 前端验证不能代替最终校验。实际支付流程仍应由支付服务端或支付网关完成校验。
  • 如果年份字段允许输入两位年份,例如 29,需要先确定转换规则,再与当前年份比较,不能直接将它当作四位年份处理。

备注:内容仅供参考。