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,需要先确定转换规则,再与当前年份比较,不能直接将它当作四位年份处理。
备注:内容仅供参考。
