feat(kyc): 升级为三要素核验详版API,返回详细错误原因
- 从 Mobile3MetaSimpleVerify 改为 Mobile3MetaDetailVerify - 新增 SubCode 详细错误码映射: - 201: 手机号与姓名、身份证号均不匹配 - 202: 手机号与身份证号不匹配 - 203: 手机号与姓名不匹配 - 204: 其他不一致 - 301: 查无记录 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c3b50264cc
commit
c14b87305c
|
|
@ -86,7 +86,7 @@ export class AliyunKycProvider {
|
||||||
* 层级1: 实名认证 - 手机号三要素验证
|
* 层级1: 实名认证 - 手机号三要素验证
|
||||||
* ========================================
|
* ========================================
|
||||||
* 验证姓名、身份证号和手机号是否匹配
|
* 验证姓名、身份证号和手机号是否匹配
|
||||||
* 使用阿里云 Mobile3MetaSimpleVerify API (手机号三要素核验简版)
|
* 使用阿里云 Mobile3MetaDetailVerify API (手机号三要素核验详版)
|
||||||
* 文档: https://help.aliyun.com/zh/id-verification/information-verification/developer-reference/esf1ff158mxowkk6
|
* 文档: https://help.aliyun.com/zh/id-verification/information-verification/developer-reference/esf1ff158mxowkk6
|
||||||
*/
|
*/
|
||||||
async verifyIdCard(
|
async verifyIdCard(
|
||||||
|
|
@ -95,7 +95,7 @@ export class AliyunKycProvider {
|
||||||
phoneNumber: string,
|
phoneNumber: string,
|
||||||
requestId: string,
|
requestId: string,
|
||||||
): Promise<IdCardVerificationResult> {
|
): Promise<IdCardVerificationResult> {
|
||||||
this.logger.log(`[AliyunKYC] [Level1] Starting mobile 3-factor verification, requestId: ${requestId}`);
|
this.logger.log(`[AliyunKYC] [Level1] Starting mobile 3-factor verification (detail), requestId: ${requestId}`);
|
||||||
|
|
||||||
// 开发/测试环境:模拟验证
|
// 开发/测试环境:模拟验证
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
|
|
@ -104,14 +104,14 @@ export class AliyunKycProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 调用阿里云手机号三要素核验简版 API (Mobile3MetaSimpleVerify)
|
// 调用阿里云手机号三要素核验详版 API (Mobile3MetaDetailVerify)
|
||||||
// 参数说明:
|
// 参数说明:
|
||||||
// - ParamType: 加密方式 (normal=明文, md5=MD5加密, sm2=SM2加密)
|
// - ParamType: 加密方式 (normal=明文, md5=MD5加密, sm2=SM2加密)
|
||||||
// - UserName: 姓名
|
// - UserName: 姓名
|
||||||
// - IdentifyNum: 身份证号
|
// - IdentifyNum: 身份证号
|
||||||
// - Mobile: 手机号
|
// - Mobile: 手机号
|
||||||
const params = {
|
const params = {
|
||||||
Action: 'Mobile3MetaSimpleVerify',
|
Action: 'Mobile3MetaDetailVerify',
|
||||||
Version: '2019-03-07',
|
Version: '2019-03-07',
|
||||||
Format: 'JSON',
|
Format: 'JSON',
|
||||||
ParamType: 'normal', // 使用明文传输
|
ParamType: 'normal', // 使用明文传输
|
||||||
|
|
@ -125,20 +125,27 @@ export class AliyunKycProvider {
|
||||||
// 打印完整的阿里云返回信息(脱敏后)
|
// 打印完整的阿里云返回信息(脱敏后)
|
||||||
this.logger.log(`[AliyunKYC] [Level1] Aliyun API Response: ${JSON.stringify(response, null, 2)}`);
|
this.logger.log(`[AliyunKYC] [Level1] Aliyun API Response: ${JSON.stringify(response, null, 2)}`);
|
||||||
|
|
||||||
// Mobile3MetaSimpleVerify 返回结果:
|
// Mobile3MetaDetailVerify 返回结果:
|
||||||
// - Code: OK 表示请求成功
|
// - Code: OK 表示请求成功
|
||||||
// - ResultObject.BizCode: 核验结果
|
// - ResultObject.BizCode: 核验结果
|
||||||
// - 1: 校验一致 (成功)
|
// - 1: 校验一致 (成功)
|
||||||
// - 2: 校验不一致 (失败)
|
// - 2: 校验不一致 (失败)
|
||||||
// - 3: 查无记录 (失败)
|
// - 3: 查无记录 (失败)
|
||||||
|
// - ResultObject.SubCode: 详细错误码(仅在失败时有意义)
|
||||||
|
// - 101: 验证通过,三要素校验一致
|
||||||
|
// - 201: 手机号与姓名、证件号对比均不一致
|
||||||
|
// - 202: 手机号与姓名一致,但与证件号不一致
|
||||||
|
// - 203: 手机号与姓名不一致,但与证件号一致
|
||||||
|
// - 204: 其他不一致
|
||||||
|
// - 301: 查无记录
|
||||||
if (response.Code === 'OK' || response.Code === '200') {
|
if (response.Code === 'OK' || response.Code === '200') {
|
||||||
const bizCode = response.ResultObject?.BizCode;
|
const bizCode = response.ResultObject?.BizCode;
|
||||||
const isConsistent = response.ResultObject?.IsConsistent;
|
|
||||||
const subCode = response.ResultObject?.SubCode;
|
const subCode = response.ResultObject?.SubCode;
|
||||||
|
const isConsistent = response.ResultObject?.IsConsistent;
|
||||||
// BizCode === '1' 表示校验一致(成功)
|
// BizCode === '1' 表示校验一致(成功)
|
||||||
const isMatch = bizCode === '1';
|
const isMatch = bizCode === '1';
|
||||||
|
|
||||||
this.logger.log(`[AliyunKYC] [Level1] ResultObject: BizCode=${bizCode}, IsConsistent=${isConsistent}, SubCode=${subCode}`);
|
this.logger.log(`[AliyunKYC] [Level1] ResultObject: BizCode=${bizCode}, SubCode=${subCode}, IsConsistent=${isConsistent}`);
|
||||||
|
|
||||||
if (isMatch) {
|
if (isMatch) {
|
||||||
this.logger.log(`[AliyunKYC] [Level1] Verification SUCCESS for requestId: ${requestId}`);
|
this.logger.log(`[AliyunKYC] [Level1] Verification SUCCESS for requestId: ${requestId}`);
|
||||||
|
|
@ -147,7 +154,8 @@ export class AliyunKycProvider {
|
||||||
rawResponse: response,
|
rawResponse: response,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
const errorMsg = this.mapMobile3MetaErrorCode(bizCode);
|
// 使用 SubCode 获取详细错误原因
|
||||||
|
const errorMsg = this.mapMobile3MetaDetailSubCode(subCode, bizCode);
|
||||||
this.logger.warn(`[AliyunKYC] [Level1] Verification FAILED: ${errorMsg} (BizCode: ${bizCode}, SubCode: ${subCode})`);
|
this.logger.warn(`[AliyunKYC] [Level1] Verification FAILED: ${errorMsg} (BizCode: ${bizCode}, SubCode: ${subCode})`);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|
@ -174,18 +182,35 @@ export class AliyunKycProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 映射手机号三要素核验错误码
|
* 映射手机号三要素核验详版错误码 (SubCode)
|
||||||
* 阿里云 Mobile3MetaSimpleVerify 返回的 BizCode:
|
* 阿里云 Mobile3MetaDetailVerify 返回的 SubCode:
|
||||||
* - 1: 校验一致 (成功)
|
* - 101: 验证通过,三要素校验一致
|
||||||
* - 2: 校验不一致 (失败)
|
* - 201: 手机号与姓名、证件号对比均不一致
|
||||||
* - 3: 查无记录 (失败)
|
* - 202: 手机号与姓名一致,但与证件号不一致
|
||||||
|
* - 203: 手机号与姓名不一致,但与证件号一致
|
||||||
|
* - 204: 其他不一致
|
||||||
|
* - 301: 查无记录
|
||||||
*/
|
*/
|
||||||
private mapMobile3MetaErrorCode(bizCode: string): string {
|
private mapMobile3MetaDetailSubCode(subCode: string, bizCode: string): string {
|
||||||
const errorMap: Record<string, string> = {
|
const subCodeMap: Record<string, string> = {
|
||||||
|
'101': '验证通过',
|
||||||
|
'201': '手机号与姓名、身份证号均不匹配',
|
||||||
|
'202': '手机号与身份证号不匹配',
|
||||||
|
'203': '手机号与姓名不匹配',
|
||||||
|
'204': '信息校验不一致',
|
||||||
|
'301': '查无记录,请确认信息是否正确',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (subCode && subCodeMap[subCode]) {
|
||||||
|
return subCodeMap[subCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有 SubCode,回退到 BizCode 映射
|
||||||
|
const bizCodeMap: Record<string, string> = {
|
||||||
'2': '三要素信息校验不一致',
|
'2': '三要素信息校验不一致',
|
||||||
'3': '查无记录,请确认信息是否正确',
|
'3': '查无记录,请确认信息是否正确',
|
||||||
};
|
};
|
||||||
return errorMap[bizCode] || `验证失败 (错误码: ${bizCode})`;
|
return bizCodeMap[bizCode] || `验证失败 (错误码: ${bizCode})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue