diff --git a/miniapp/pages/realname/index.vue b/miniapp/pages/realname/index.vue index 1255e99..77cac12 100644 --- a/miniapp/pages/realname/index.vue +++ b/miniapp/pages/realname/index.vue @@ -103,31 +103,35 @@ - - - - - - 请上传您的身份证正反面 - (我们仅用于实名认证) + + + + + + 请输入您的身份证号码 + + + - - - - - + + + 请输入您的姓名 + + - 拍照上传身份证正面 - - - - - - - - - 拍照上传身份证反面 @@ -214,16 +218,13 @@ maskIdNumber } from '@/utils/format.js' import { - get + get, + post } from '@/api/request.js' import { getToken } from '@/utils/storage.js' import Loading from '@/components/Loading/index.vue' - import config from '@/config/index.js' - - // 从统一配置获取 API 基础地址 - const BASE_URL = config.API_BASE_URL export default { name: 'RealnamePage', @@ -247,9 +248,9 @@ // 认证费用 - 从配置中获取 const verificationFee = computed(() => configStore.realNamePrice || 88) - // 身份证照片 - const idCardFront = ref('') - const idCardBack = ref('') + // 身份信息输入(二要素验证) + const idCardNumber = ref('') + const realName = ref('') // 认证结果 const verificationResult = ref(null) @@ -277,8 +278,9 @@ // 是否可以跳过支付(会员或已支付) const canSkipPayment = computed(() => userStore.isMember || isPaid.value) + // 是否可以提交(身份证号18位 + 姓名不为空) const canSubmit = computed(() => { - return idCardFront.value && idCardBack.value + return idCardNumber.value.length === 18 && realName.value.trim().length > 0 }) const maskedName = computed(() => { @@ -455,54 +457,39 @@ } /** - * 选择身份证正面照片 - */ - const chooseIdCardFront = () => { - uni.chooseImage({ - count: 1, - sizeType: ['compressed'], - sourceType: ['album', 'camera'], - success: (res) => { - idCardFront.value = res.tempFilePaths[0] - } - }) - } - - /** - * 选择身份证反面照片 - */ - const chooseIdCardBack = () => { - uni.chooseImage({ - count: 1, - sizeType: ['compressed'], - sourceType: ['album', 'camera'], - success: (res) => { - idCardBack.value = res.tempFilePaths[0] - } - }) - } - - /** - * 提交实名认证 (Requirements 12.3) + * 提交实名认证(二要素验证:姓名+身份证号) */ const handleSubmitVerification = async () => { if (!canSubmit.value || submitting.value) return + // 简单校验身份证号格式 + const idCardRegex = /^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/ + if (!idCardRegex.test(idCardNumber.value)) { + uni.showToast({ + title: '请输入正确的身份证号', + icon: 'none' + }) + return + } + submitting.value = true try { - // 上传身份证照片并提交认证 - const result = await uploadIdCards() + // 调用二要素验证接口 + const result = await post('/realname/submit', { + realName: realName.value.trim(), + idCard: idCardNumber.value.trim() + }) - if (result && (result.success || result.code === 0)) { + if (result && (result.success || result.code === 0) && result.data?.success) { // 认证成功,更新状态 userStore.setRealNameStatus(true) verificationResult.value = { - name: result.data.name, - idNumber: result.data.idNumber + name: result.data.maskedName, + idNumber: result.data.maskedIdCard } - // 进入结果页面 (Requirements 12.4) + // 进入结果页面 currentStep.value = 3 uni.showToast({ @@ -511,7 +498,7 @@ }) } else { uni.showToast({ - title: result?.message || '认证失败,请重试', + title: result?.data?.message || result?.message || '认证失败,请检查信息是否正确', icon: 'none' }) } @@ -526,103 +513,6 @@ } } - /** - * 上传身份证照片进行实名认证 - */ - const uploadIdCards = () => { - return new Promise((resolve, reject) => { - const token = getToken() - - // 同时上传正反面 - uni.uploadFile({ - url: `${BASE_URL}/api/app/realname/verify`, - filePath: idCardFront.value, - name: 'frontImage', - header: { - 'Authorization': `Bearer ${token}` - }, - success: async (uploadRes) => { - if (uploadRes.statusCode === 200) { - try { - const response = JSON.parse(uploadRes.data) - - // 检查API响应 - if (response.success || response.code === 0) { - const data = response.data - - // 如果需要单独上传反面 - if (data.needBackImage) { - const backResult = await uploadBackImage(token) - resolve(backResult) - } else { - resolve(response) - } - } else { - reject(new Error(response.message || '认证失败')) - } - } catch (e) { - reject(new Error('解析响应失败')) - } - } else if (uploadRes.statusCode === 401) { - reject(new Error('未授权,请重新登录')) - } else { - try { - const errorData = JSON.parse(uploadRes.data) - reject(new Error(errorData.message || '认证失败')) - } catch (e) { - reject(new Error('认证失败')) - } - } - }, - fail: (err) => { - console.error('上传失败:', err) - reject(new Error('网络连接失败')) - } - }) - }) - } - - /** - * 上传身份证反面 - */ - const uploadBackImage = (token) => { - return new Promise((resolve, reject) => { - uni.uploadFile({ - url: `${BASE_URL}/api/app/realname/verify/back`, - filePath: idCardBack.value, - name: 'backImage', - header: { - 'Authorization': `Bearer ${token}` - }, - success: (uploadRes) => { - if (uploadRes.statusCode === 200) { - try { - const response = JSON.parse(uploadRes.data) - - if (response.success || response.code === 0) { - resolve(response) - } else { - reject(new Error(response.message || '上传失败')) - } - } catch (e) { - reject(new Error('解析响应失败')) - } - } else { - try { - const errorData = JSON.parse(uploadRes.data) - reject(new Error(errorData.message || '上传失败')) - } catch (e) { - reject(new Error('上传失败')) - } - } - }, - fail: () => { - reject(new Error('网络连接失败')) - } - }) - }) - } - /** * 完成认证,返回上一页 */ @@ -679,8 +569,8 @@ submitting, currentStep, verificationFee, - idCardFront, - idCardBack, + idCardNumber, + realName, isVerified, canSubmit, canSkipPayment, @@ -692,8 +582,6 @@ handleNextStep, handleContactService, handleStepClick, - chooseIdCardFront, - chooseIdCardBack, handleSubmitVerification, handleDone } @@ -1190,7 +1078,44 @@ } } - // 步骤2: 上传页面 + // 步骤2: 身份信息输入页面 + .step-input { + .input-content { + padding: 40rpx 30rpx; + display: flex; + flex-direction: column; + gap: 40rpx; + + .input-group { + background: #fff; + border-radius: 24rpx; + padding: 32rpx; + + .input-label { + display: block; + font-size: 30rpx; + color: #333; + font-weight: 500; + margin-bottom: 24rpx; + } + + .input-box { + background: #F6F8FA; + border-radius: 16rpx; + padding: 0 24rpx; + + .input-field { + width: 100%; + height: 96rpx; + font-size: 32rpx; + color: #333; + } + } + } + } + } + + // 步骤2: 上传页面(保留旧样式兼容) .step-upload { .upload-content { padding: 40rpx 30rpx; diff --git a/server/src/XiangYi.AppApi/appsettings.json b/server/src/XiangYi.AppApi/appsettings.json index 1713d73..7ad0006 100644 --- a/server/src/XiangYi.AppApi/appsettings.json +++ b/server/src/XiangYi.AppApi/appsettings.json @@ -98,5 +98,14 @@ "SecretId": "AKIDVyMfzKZdZP8zkNyOdsFuSsBJDB7EScs0", "SecretKey": "89GWr7JPWYTL8ueHlAYowGZnvzKZjqs9", "Region": "ap-shanghai" + }, + "RealName": { + "Provider": "Tencent", + "Tencent": { + "SecretId": "AKIDVyMfzKZdZP8zkNyOdsFuSsBJDB7EScs0", + "SecretKey": "89GWr7JPWYTL8ueHlAYowGZnvzKZjqs9", + "Region": "ap-shanghai", + "SimilarityThreshold": 80 + } } }