174 lines
7.9 KiB
JavaScript
174 lines
7.9 KiB
JavaScript
"use strict";
|
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
};
|
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
};
|
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
};
|
|
var TaskUserVerifyService_1;
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.TaskUserVerifyService = void 0;
|
|
const common_1 = require("@nestjs/common");
|
|
const typeorm_1 = require("@nestjs/typeorm");
|
|
const typeorm_2 = require("typeorm");
|
|
const user_verify_model_1 = require("../../../model/user_verify.model");
|
|
const getDelay = () => {
|
|
const randomMinutes = Math.floor(Math.random() * 51) + 10;
|
|
const delay = randomMinutes * 60 * 1000;
|
|
return delay;
|
|
};
|
|
let TaskUserVerifyService = TaskUserVerifyService_1 = class TaskUserVerifyService {
|
|
userVerifyModel;
|
|
logger = new common_1.Logger(TaskUserVerifyService_1.name);
|
|
constructor(userVerifyModel) {
|
|
this.userVerifyModel = userVerifyModel;
|
|
}
|
|
onModuleInit() {
|
|
this.logger.verbose('实名认证定时任务已加载');
|
|
this.scheduleNextAudit();
|
|
}
|
|
scheduleNextAudit() {
|
|
const delay = getDelay();
|
|
this.logger.verbose(`下一次实名认证审核将在 ${delay / 60 / 1000} 分钟后执行`);
|
|
setTimeout(() => {
|
|
void this.executeAuditAndScheduleNext();
|
|
}, delay);
|
|
}
|
|
async executeAuditAndScheduleNext() {
|
|
await this.autoAuditVerify();
|
|
this.scheduleNextAudit();
|
|
}
|
|
validateIdCard(idCardNo) {
|
|
const idCard = idCardNo.trim();
|
|
if (idCard.length === 18) {
|
|
const first17 = idCard.substring(0, 17);
|
|
if (!/^\d{17}$/.test(first17)) {
|
|
return { valid: false, message: '前 17 位必须是数字' };
|
|
}
|
|
const lastChar = idCard.charAt(17).toUpperCase();
|
|
if (!/^\d|X$/.test(lastChar)) {
|
|
return { valid: false, message: '第 18 位必须是数字或 X' };
|
|
}
|
|
const provinceCode = parseInt(idCard.substring(0, 2));
|
|
if (provinceCode < 11 || provinceCode > 82) {
|
|
return { valid: false, message: '无效的地区码' };
|
|
}
|
|
const birthYear = parseInt(idCard.substring(6, 10));
|
|
const birthMonth = parseInt(idCard.substring(10, 12));
|
|
const birthDay = parseInt(idCard.substring(12, 14));
|
|
const currentYear = new Date().getFullYear();
|
|
if (birthYear < 1900 ||
|
|
birthYear > currentYear ||
|
|
birthMonth < 1 ||
|
|
birthMonth > 12 ||
|
|
birthDay < 1 ||
|
|
birthDay > 31) {
|
|
return { valid: false, message: '无效的出生日期' };
|
|
}
|
|
const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
|
|
const checkCodes = [
|
|
'1',
|
|
'0',
|
|
'X',
|
|
'9',
|
|
'8',
|
|
'7',
|
|
'6',
|
|
'5',
|
|
'4',
|
|
'3',
|
|
'2',
|
|
];
|
|
let sum = 0;
|
|
for (let i = 0; i < 17; i++) {
|
|
sum += parseInt(first17.charAt(i)) * weights[i];
|
|
}
|
|
const mod = sum % 11;
|
|
const expectedCheckCode = checkCodes[mod];
|
|
if (lastChar !== expectedCheckCode) {
|
|
return { valid: false, message: '身份证校验码错误' };
|
|
}
|
|
return { valid: true };
|
|
}
|
|
if (idCard.length === 15) {
|
|
if (!/^\d{15}$/.test(idCard)) {
|
|
return { valid: false, message: '15 位身份证必须全部是数字' };
|
|
}
|
|
const provinceCode = parseInt(idCard.substring(0, 2));
|
|
if (provinceCode < 11 || provinceCode > 82) {
|
|
return { valid: false, message: '无效的地区码' };
|
|
}
|
|
return { valid: true };
|
|
}
|
|
return { valid: false, message: '身份证号长度必须是 15 或 18 位' };
|
|
}
|
|
validateName(realName) {
|
|
const name = realName.trim();
|
|
if (!name) {
|
|
return { valid: false, message: '姓名不能为空' };
|
|
}
|
|
if (name.length < 2 || name.length > 5) {
|
|
return { valid: false, message: '姓名长度应为 2-5 个汉字' };
|
|
}
|
|
if (!/^[\u4e00-\u9fa5]+$/.test(name)) {
|
|
return { valid: false, message: '姓名只能包含汉字' };
|
|
}
|
|
if (/(.)\1{2,}/.test(name)) {
|
|
return { valid: false, message: '姓名包含过多重复字符' };
|
|
}
|
|
return { valid: true };
|
|
}
|
|
async autoAuditVerify() {
|
|
this.logger.verbose('开始执行实名认证自动审核任务');
|
|
try {
|
|
const pendingRecords = await this.userVerifyModel.find({
|
|
where: { status: user_verify_model_1.VerifyAuditStatus.Pending },
|
|
});
|
|
this.logger.verbose(`待审核记录数:${pendingRecords.length}`);
|
|
let approvedCount = 0;
|
|
let rejectedCount = 0;
|
|
for (const record of pendingRecords) {
|
|
const idCardValidation = this.validateIdCard(record.idCardNo);
|
|
if (!idCardValidation.valid) {
|
|
await this.userVerifyModel.update({ id: record.id }, {
|
|
status: user_verify_model_1.VerifyAuditStatus.Rejected,
|
|
rejectReason: `身份证验证失败:${idCardValidation.message}`,
|
|
});
|
|
rejectedCount++;
|
|
this.logger.verbose(`实名认证审核拒绝 ID: ${record.id}, 原因:${idCardValidation.message}`);
|
|
continue;
|
|
}
|
|
const nameValidation = this.validateName(record.realName);
|
|
if (!nameValidation.valid) {
|
|
await this.userVerifyModel.update({ id: record.id }, {
|
|
status: user_verify_model_1.VerifyAuditStatus.Rejected,
|
|
rejectReason: `姓名验证失败:${nameValidation.message}`,
|
|
});
|
|
rejectedCount++;
|
|
this.logger.verbose(`实名认证审核拒绝 ID: ${record.id}, 原因:${nameValidation.message}`);
|
|
continue;
|
|
}
|
|
await this.userVerifyModel.update({ id: record.id }, { status: user_verify_model_1.VerifyAuditStatus.Approved });
|
|
approvedCount++;
|
|
this.logger.verbose(`实名认证审核通过 ID: ${record.id}, 姓名:${record.realName}`);
|
|
}
|
|
this.logger.verbose(`实名认证自动审核任务执行完成,通过:${approvedCount} 人,拒绝:${rejectedCount} 人`);
|
|
}
|
|
catch (error) {
|
|
this.logger.error(`实名认证自动审核任务执行失败`, error instanceof Error ? error.stack : error);
|
|
}
|
|
}
|
|
};
|
|
exports.TaskUserVerifyService = TaskUserVerifyService;
|
|
exports.TaskUserVerifyService = TaskUserVerifyService = TaskUserVerifyService_1 = __decorate([
|
|
(0, common_1.Injectable)(),
|
|
__param(0, (0, typeorm_1.InjectRepository)(user_verify_model_1.UserVerifyModel)),
|
|
__metadata("design:paramtypes", [typeorm_2.Repository])
|
|
], TaskUserVerifyService);
|
|
//# sourceMappingURL=task_user_verify.service.js.map
|