feat: "同僚"改为"同伴" + KYC从三要素改为二要素
mobile-app: - profile_page.dart: 将所有"同僚"改为"同伴" identity-service: - 层级1实名认证从三要素(姓名+身份证+手机号)改为二要素(姓名+身份证号) - 使用阿里云 Id2MetaStandardVerify API - 二要素验证直接调用真实API,不使用mock - 保留三要素验证方法(verifyIdCardThreeFactor)备用 🤖 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
47e4ef2b33
commit
8173e1f973
|
|
@ -214,16 +214,17 @@ export class KycApplicationService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ========================================
|
* ========================================
|
||||||
* 层级1: 实名认证 - 提交三要素验证
|
* 层级1: 实名认证 - 提交二要素验证
|
||||||
* ========================================
|
* ========================================
|
||||||
* 验证姓名+身份证号+手机号(手机号从用户账户获取)
|
* 验证姓名+身份证号
|
||||||
|
* 注:保留手机号参数以兼容调用方,三要素验证功能保留备用
|
||||||
*/
|
*/
|
||||||
async submitRealNameVerification(
|
async submitRealNameVerification(
|
||||||
userId: string,
|
userId: string,
|
||||||
realName: string,
|
realName: string,
|
||||||
idCardNumber: string,
|
idCardNumber: string,
|
||||||
) {
|
) {
|
||||||
this.logger.log(`[KYC] [Level1] Submitting real name verification (3-factor) for user: ${userId}`);
|
this.logger.log(`[KYC] [Level1] Submitting real name verification (2-factor) for user: ${userId}`);
|
||||||
|
|
||||||
const config = await this.getKycConfig();
|
const config = await this.getKycConfig();
|
||||||
if (!config.level1Enabled) {
|
if (!config.level1Enabled) {
|
||||||
|
|
@ -259,20 +260,19 @@ export class KycApplicationService {
|
||||||
const attempt = await this.prisma.kycVerificationAttempt.create({
|
const attempt = await this.prisma.kycVerificationAttempt.create({
|
||||||
data: {
|
data: {
|
||||||
userId: BigInt(userId),
|
userId: BigInt(userId),
|
||||||
verificationType: 'ID_CARD_THREE',
|
verificationType: 'ID_CARD_TWO', // 二要素验证(姓名+身份证号)
|
||||||
provider: 'ALIYUN',
|
provider: 'ALIYUN',
|
||||||
requestId,
|
requestId,
|
||||||
inputData: {
|
inputData: {
|
||||||
realName: this.maskName(realName),
|
realName: this.maskName(realName),
|
||||||
idCardNumber: this.maskIdCard(idCardNumber),
|
idCardNumber: this.maskIdCard(idCardNumber),
|
||||||
phoneNumber: this.maskPhoneNumber(user.phoneNumber),
|
|
||||||
},
|
},
|
||||||
status: 'PENDING',
|
status: 'PENDING',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 调用阿里云三要素验证
|
// 调用阿里云二要素验证(姓名+身份证号)
|
||||||
const result = await this.aliyunKycProvider.verifyIdCard(
|
const result = await this.aliyunKycProvider.verifyIdCard(
|
||||||
realName,
|
realName,
|
||||||
idCardNumber,
|
idCardNumber,
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ export interface IdCardOcrResult {
|
||||||
/**
|
/**
|
||||||
* 阿里云实人认证服务 - 支持三层认证
|
* 阿里云实人认证服务 - 支持三层认证
|
||||||
*
|
*
|
||||||
* 层级1: 实名认证 - 三要素验证(姓名+身份证号+手机号)
|
* 层级1: 实名认证 - 二要素验证(姓名+身份证号)
|
||||||
|
* 备用:三要素验证(姓名+身份证号+手机号)- verifyIdCardThreeFactor
|
||||||
* 层级2: 实人认证 - 人脸活体检测
|
* 层级2: 实人认证 - 人脸活体检测
|
||||||
* 层级3: KYC - 证件照OCR识别验证
|
* 层级3: KYC - 证件照OCR识别验证
|
||||||
*
|
*
|
||||||
|
|
@ -86,22 +87,23 @@ export class AliyunKycProvider {
|
||||||
* 层级1: 实名认证 - 二要素验证(默认)
|
* 层级1: 实名认证 - 二要素验证(默认)
|
||||||
* ========================================
|
* ========================================
|
||||||
* 验证姓名和身份证号是否匹配
|
* 验证姓名和身份证号是否匹配
|
||||||
* 使用阿里云 IdCardTwoMetaVerify API (身份证二要素核验)
|
* 使用阿里云 Id2MetaStandardVerify API (身份证二要素标准版核验)
|
||||||
* 文档: https://help.aliyun.com/zh/id-verification/information-verification/developer-reference/api-cloudauth-2019-03-07-idcardtwometaverify
|
* 文档: https://help.aliyun.com/zh/id-verification/api-cloudauth-2019-03-07-id2metastandardverify-infor-verify
|
||||||
*/
|
*/
|
||||||
async verifyIdCard(
|
async verifyIdCard(
|
||||||
realName: string,
|
realName: string,
|
||||||
idCardNumber: string,
|
idCardNumber: string,
|
||||||
phoneNumber: string,
|
phoneNumber: string, // 保留参数以兼容调用方,但二要素验证不使用
|
||||||
requestId: string,
|
requestId: string,
|
||||||
): Promise<IdCardVerificationResult> {
|
): Promise<IdCardVerificationResult> {
|
||||||
// 暂时使用三要素验证(二要素需要单独开通权限)
|
// 使用二要素验证(姓名 + 身份证号)
|
||||||
return this.verifyIdCardThreeFactor(realName, idCardNumber, phoneNumber, requestId);
|
return this.verifyIdCardTwoFactor(realName, idCardNumber, requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 二要素验证:姓名 + 身份证号
|
* 二要素验证:姓名 + 身份证号
|
||||||
* 使用阿里云 IdCardTwoMetaVerify API
|
* 使用阿里云 Id2MetaStandardVerify API
|
||||||
|
* 文档: https://help.aliyun.com/zh/id-verification/api-cloudauth-2019-03-07-id2metastandardverify-infor-verify
|
||||||
*/
|
*/
|
||||||
async verifyIdCardTwoFactor(
|
async verifyIdCardTwoFactor(
|
||||||
realName: string,
|
realName: string,
|
||||||
|
|
@ -110,7 +112,7 @@ export class AliyunKycProvider {
|
||||||
): Promise<IdCardVerificationResult> {
|
): Promise<IdCardVerificationResult> {
|
||||||
this.logger.log(`[AliyunKYC] [Level1] Starting 2-factor verification, requestId: ${requestId}`);
|
this.logger.log(`[AliyunKYC] [Level1] Starting 2-factor verification, requestId: ${requestId}`);
|
||||||
|
|
||||||
// 二要素验证始终使用真实 API,不使用 mock
|
// 二要素验证直接调用真实API,不使用mock
|
||||||
if (!this.accessKeyId || !this.accessKeySecret) {
|
if (!this.accessKeyId || !this.accessKeySecret) {
|
||||||
this.logger.error('[AliyunKYC] KYC credentials not configured');
|
this.logger.error('[AliyunKYC] KYC credentials not configured');
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -3163,7 +3163,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 处理团队种植数区域的秘密点击(连续点击19次后等待2秒显示"我的同僚")
|
/// 处理团队种植数区域的秘密点击(连续点击19次后等待2秒显示"我的同伴")
|
||||||
Timer? _teamPlantingUnlockTimer;
|
Timer? _teamPlantingUnlockTimer;
|
||||||
|
|
||||||
void _onTeamPlantingTap() {
|
void _onTeamPlantingTap() {
|
||||||
|
|
@ -3300,7 +3300,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
'同僚种植树',
|
'同伴种植树',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontFamily: 'Inter',
|
fontFamily: 'Inter',
|
||||||
|
|
@ -3371,7 +3371,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'本人/同僚: ${referral['personal']} / ${referral['team']}',
|
'本人/同伴: ${referral['personal']} / ${referral['team']}',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontFamily: 'Inter',
|
fontFamily: 'Inter',
|
||||||
|
|
@ -3387,7 +3387,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 构建我的同僚树
|
/// 构建我的同伴树
|
||||||
Widget _buildMyTeamTree() {
|
Widget _buildMyTeamTree() {
|
||||||
// 创建或更新根节点(缓存以保持展开状态)
|
// 创建或更新根节点(缓存以保持展开状态)
|
||||||
// 只有在数据变化时才创建新的根节点
|
// 只有在数据变化时才创建新的根节点
|
||||||
|
|
@ -3410,7 +3410,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.only(top: 8),
|
padding: EdgeInsets.only(top: 8),
|
||||||
child: Text(
|
child: Text(
|
||||||
'我的同僚',
|
'我的同伴',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontFamily: 'Inter',
|
fontFamily: 'Inter',
|
||||||
|
|
@ -3437,7 +3437,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(20),
|
padding: EdgeInsets.all(20),
|
||||||
child: Text(
|
child: Text(
|
||||||
'暂无同僚',
|
'暂无同伴',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontFamily: 'Inter',
|
fontFamily: 'Inter',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue