TUTORIAL

实名认证接口对接

实名认证接口对接

实名认证接口对接

金融、医疗、教育等行业的官网,常被法规要求对用户做实名认证——核实"你是你声称的那个人"。实现方式从简到繁依次是:身份证二要素核验(姓名+身份证号)、三要素(姓名+身份证号+手机号)、人脸活体检测。具体选哪种,取决于业务对身份真实性的要求强度。本篇以尧图医疗类项目的经验,讲清实名认证的对接要点。

一、身份证二要素核验

二要素核验是最基础的实名认证:把用户输入的姓名和身份证号提交给第三方接口,接口对接公安系统比对,返回一致或不一致。这是性价比最高的认证方式,单次调用几分钱,足以满足大多数合规要求。阿里云、腾讯云、百度云都提供这类 API,调用方式大同小异。

// 身份证二要素核验(阿里云市场)
async function verifyIdCard(name, idCard) {
  // 1. 基础格式校验,省一次接口调用费
  if (!/^[\u4e00-\u9fa5]{2,6}$/.test(name)) {
    return fail('姓名格式不正确');
  }
  if (!/^\d{17}[\dXx]$/.test(idCard)) {
    return fail('身份证号格式不正确');
  }
  // 2. 身份证号校验位验证(GB 11643-1999标准)
  if (!checkIdCardChecksum(idCard)) {
    return fail('身份证号校验失败');
  }
  // 3. 调用第三方核验接口
  const result = await http.post('https://idcard.market.alicloudapi.com/IDCard', {
    name, idCard
  }, {
    headers: { 'Authorization': 'APPCODE ' + APP_CODE }
  });
  // 4. 解析结果
  if (result.code === 0 && result.data.isMatch === '01') {
    return success('实名认证通过');
  }
  return fail('姓名与身份证号不匹配');
}

// 身份证校验位算法
function checkIdCardChecksum(id) {
  const weight = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2];
  const check = ['1','0','X','9','8','7','6','5','4','3','2'];
  let sum = 0;
  for (let i = 0; i < 17; i++) sum += parseInt(id[i]) * weight[i];
  return id[17].toUpperCase() === check[sum % 11];
}

先做本地格式校验再调接口,能省下不少无效调用——尧图统计过,约 20% 的请求是格式错误(手滑输错、位数不对)。身份证号自带校验位,用算法验证就能挡住大部分乱填的号,既省钱又快。校验通过后,认证结果要存库(姓名、身份证号脱敏存储),避免重复认证重复扣费。

二、OCR 识别与活体检测

二要素核验只能保证"姓名和身份证号匹配",但无法确认操作者本人就是身份证主人——身份证号泄露的情况并不少见。要确认"本人在操作",需要 OCR 识别身份证图片 + 人脸活体检测。OCR 把证件照上的信息提取出来,省去用户手动输入;活体检测要求用户做动作(眨眼、张嘴、转头),证明是真人而非照片。

// 完整实名认证流程:OCR → 二要素 → 活体检测
async function fullVerification(idCardFront, idCardBack, faceVideo) {
  // 步骤1:OCR识别身份证正反面
  const ocrResult = await ocrApi.recognizeIdCard(idCardFront, idCardBack);
  if (!ocrResult.success) return fail('身份证识别失败,请重新拍照');
  const { name, idCard, address, expireDate } = ocrResult.data;

  // 步骤2:检查证件是否过期
  if (new Date(expireDate) < new Date()) {
    return fail('身份证已过期');
  }

  // 步骤3:二要素核验(姓名+身份证号是否真实)
  const verifyResult = await verifyIdCard(name, idCard);
  if (!verifyResult.success) return fail('身份信息核验未通过');

  // 步骤4:活体检测(采集人脸视频,与身份证照片比对)
  const faceResult = await faceApi.livenessCheck({
    video: faceVideo,
    idCardImage: ocrResult.data.portrait,  // 身份证上的照片
    livenessType: 'action',  // 动作活体
    actions: ['blink', 'open_mouth', 'turn_head']
  });
  if (faceResult.score < 0.8) {
    return fail('人脸验证未通过,请重试');
  }

  // 步骤5:全部通过,保存认证状态(脱敏存储)
  await db.update('user_verify', {
    user_id: currentUserId,
    real_name: maskName(name),           // 张*三
    id_card: maskIdCard(idCard),          // 4101**********1234
    verify_status: 'verified',
    verify_time: now(),
    verify_method: 'face'
  });
  return success('实名认证成功');
}

活体检测的安全性在于"防翻拍"。单纯照片翻拍骗不过动作活体,但高清晰度视频翻拍可能蒙混过关。金融级场景建议用"数字活体"(屏幕随机数字,用户读出来),安全性更高但体验略重。尧图在医疗项目里用动作活体 + 人脸与证件照相似度阈值 0.8 的组合,既保证安全又不过度打扰用户。

三、敏感数据存储与合规

实名认证必然涉及身份证号、人脸照片等敏感信息,存储不当就是数据安全事故。尧图遵循三条原则:能不存就不存、必须存要加密、展示时必须脱敏。身份证号只存脱敏后的(如 4101**********1234),完整号码若必须留存则用 AES 加密存库;人脸照片认证完即删,只留认证结果状态。

// 敏感数据处理
function maskName(name) {
  // 张三 → 张*,欧阳娜娜 → 欧***娜
  if (name.length <= 2) return name[0] + '*';
  return name[0] + '*'.repeat(name.length - 2) + name[name.length - 1];
}

function maskIdCard(idCard) {
  // 410102199001011234 → 4101**********1234
  return idCard.slice(0, 4) + '*'.repeat(10) + idCard.slice(-4);
}

// 完整身份证号加密存储(如法规要求留存)
const crypto = require('crypto');
function encryptIdCard(idCard) {
  const cipher = crypto.createCipheriv('aes-256-gcm',
    SECRET_KEY, IV);
  let encrypted = cipher.update(idCard, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  return encrypted;  // 仅在司法调证时解密使用
}

合规层面,实名认证前必须获得用户明示授权——《个人信息保护法》要求采集敏感信息前单独告知用途并取得同意。尧图会在认证页面设置独立勾选的授权协议,记录授权时间和 IP 作为凭证。另外,认证频率要限制(如 24 小时内最多 3 次),防止有人拿接口当试错工具暴力撞库。把安全、合规、体验三者平衡好,实名认证才能既满足监管又不劝退用户。

返回教程列表