diff --git a/backend/services/identity-service/src/infrastructure/external/kyc/aliyun-kyc.provider.ts b/backend/services/identity-service/src/infrastructure/external/kyc/aliyun-kyc.provider.ts index 269ec2d9..52f6d00e 100644 --- a/backend/services/identity-service/src/infrastructure/external/kyc/aliyun-kyc.provider.ts +++ b/backend/services/identity-service/src/infrastructure/external/kyc/aliyun-kyc.provider.ts @@ -86,7 +86,7 @@ export class AliyunKycProvider { * 层级1: 实名认证 - 手机号三要素验证 * ======================================== * 验证姓名、身份证号和手机号是否匹配 - * 使用阿里云 Mobile3MetaSimpleVerify API (手机号三要素核验简版) + * 使用阿里云 Mobile3MetaDetailVerify API (手机号三要素核验详版) * 文档: https://help.aliyun.com/zh/id-verification/information-verification/developer-reference/esf1ff158mxowkk6 */ async verifyIdCard( @@ -95,7 +95,7 @@ export class AliyunKycProvider { phoneNumber: string, requestId: string, ): Promise { - 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) { @@ -104,14 +104,14 @@ export class AliyunKycProvider { } try { - // 调用阿里云手机号三要素核验简版 API (Mobile3MetaSimpleVerify) + // 调用阿里云手机号三要素核验详版 API (Mobile3MetaDetailVerify) // 参数说明: // - ParamType: 加密方式 (normal=明文, md5=MD5加密, sm2=SM2加密) // - UserName: 姓名 // - IdentifyNum: 身份证号 // - Mobile: 手机号 const params = { - Action: 'Mobile3MetaSimpleVerify', + Action: 'Mobile3MetaDetailVerify', Version: '2019-03-07', Format: 'JSON', ParamType: 'normal', // 使用明文传输 @@ -125,20 +125,27 @@ export class AliyunKycProvider { // 打印完整的阿里云返回信息(脱敏后) this.logger.log(`[AliyunKYC] [Level1] Aliyun API Response: ${JSON.stringify(response, null, 2)}`); - // Mobile3MetaSimpleVerify 返回结果: + // Mobile3MetaDetailVerify 返回结果: // - Code: OK 表示请求成功 // - ResultObject.BizCode: 核验结果 // - 1: 校验一致 (成功) // - 2: 校验不一致 (失败) // - 3: 查无记录 (失败) + // - ResultObject.SubCode: 详细错误码(仅在失败时有意义) + // - 101: 验证通过,三要素校验一致 + // - 201: 手机号与姓名、证件号对比均不一致 + // - 202: 手机号与姓名一致,但与证件号不一致 + // - 203: 手机号与姓名不一致,但与证件号一致 + // - 204: 其他不一致 + // - 301: 查无记录 if (response.Code === 'OK' || response.Code === '200') { const bizCode = response.ResultObject?.BizCode; - const isConsistent = response.ResultObject?.IsConsistent; const subCode = response.ResultObject?.SubCode; + const isConsistent = response.ResultObject?.IsConsistent; // 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) { this.logger.log(`[AliyunKYC] [Level1] Verification SUCCESS for requestId: ${requestId}`); @@ -147,7 +154,8 @@ export class AliyunKycProvider { rawResponse: response, }; } 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})`); return { success: false, @@ -174,18 +182,35 @@ export class AliyunKycProvider { } /** - * 映射手机号三要素核验错误码 - * 阿里云 Mobile3MetaSimpleVerify 返回的 BizCode: - * - 1: 校验一致 (成功) - * - 2: 校验不一致 (失败) - * - 3: 查无记录 (失败) + * 映射手机号三要素核验详版错误码 (SubCode) + * 阿里云 Mobile3MetaDetailVerify 返回的 SubCode: + * - 101: 验证通过,三要素校验一致 + * - 201: 手机号与姓名、证件号对比均不一致 + * - 202: 手机号与姓名一致,但与证件号不一致 + * - 203: 手机号与姓名不一致,但与证件号一致 + * - 204: 其他不一致 + * - 301: 查无记录 */ - private mapMobile3MetaErrorCode(bizCode: string): string { - const errorMap: Record = { + private mapMobile3MetaDetailSubCode(subCode: string, bizCode: string): string { + const subCodeMap: Record = { + '101': '验证通过', + '201': '手机号与姓名、身份证号均不匹配', + '202': '手机号与身份证号不匹配', + '203': '手机号与姓名不匹配', + '204': '信息校验不一致', + '301': '查无记录,请确认信息是否正确', + }; + + if (subCode && subCodeMap[subCode]) { + return subCodeMap[subCode]; + } + + // 如果没有 SubCode,回退到 BizCode 映射 + const bizCodeMap: Record = { '2': '三要素信息校验不一致', '3': '查无记录,请确认信息是否正确', }; - return errorMap[bizCode] || `验证失败 (错误码: ${bizCode})`; + return bizCodeMap[bizCode] || `验证失败 (错误码: ${bizCode})`; } /**