From d8cf0690f2a8b73d56b12c2e2fbf7aec7ac8be09 Mon Sep 17 00:00:00 2001 From: lim Date: Mon, 11 Nov 2024 11:14:49 +0000 Subject: [PATCH 1/5] add realname auth reward --- .../api/account/faceIdRealNameAuthCallback.ts | 82 ++++++++++++++++--- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts b/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts index c265dd6394d..6ab6d5f6004 100644 --- a/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts +++ b/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts @@ -12,6 +12,7 @@ type TencentCloudFaceAuthConfig = { secretId: string; secretKey: string; ruleId: string; + realNameAuthReward?: number; }; type JsonValue = string | number | boolean | object | null; @@ -88,6 +89,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) throw new Error('faceidRealNameAuth: Real name authentication configuration not found'); } + const realNameAuthReward = config.realNameAuthReward; + const userRealNameFaceAuthInfo = await getUserRealNameInfo(bizToken, config); const isFaceRecognitionSuccess = userRealNameFaceAuthInfo.Text?.ErrCode === 0; @@ -145,15 +148,68 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) } if (isFaceRecognitionSuccess) { - await globalPrisma.userRealNameInfo.update({ - where: { userUid }, - data: { - realName: userRealNameFaceAuthInfo.Text?.Name, - idCard: userRealNameFaceAuthInfo.Text?.IdCard, - isVerified: true, - additionalInfo - } - }); + if (realNameAuthReward) { + await globalPrisma.$transaction(async (globalPrisma) => { + const currentAccount = await globalPrisma.account.findUniqueOrThrow({ + where: { userUid } + }); + + if (!currentAccount.balance) { + throw new Error('faceidRealNameAuth: Account balance not found'); + } + + const currentActivityBonus = currentAccount.activityBonus || BigInt(0); + const rewardBigInt = BigInt(realNameAuthReward); + + const newActivityBonus = currentActivityBonus + rewardBigInt; + const newBalance = currentAccount.balance + rewardBigInt; + + const updatedAccount = await globalPrisma.account.update({ + where: { userUid }, + data: { + activityBonus: newActivityBonus, + balance: newBalance + } + }); + + const userRealNameInfo = await globalPrisma.userRealNameInfo.update({ + where: { userUid }, + data: { + realName: userRealNameFaceAuthInfo.Text?.Name, + idCard: userRealNameFaceAuthInfo.Text?.IdCard, + isVerified: true, + additionalInfo: additionalInfo + } + }); + + const accountTransaction = await globalPrisma.accountTransaction.create({ + data: { + userUid, + type: 'REALNAME_AUTH_REWARD', + balance: newBalance, + deduction_balance: 0, // No deduction in this case + message: 'Real name authentication reward', + billing_id: userRealNameInfo.id // You'll need to implement this function + } + }); + + return { + account: updatedAccount, + transaction: accountTransaction, + userRealNameInfo: userRealNameInfo + }; + }); + } else { + await globalPrisma.userRealNameInfo.update({ + where: { userUid }, + data: { + realName: userRealNameFaceAuthInfo.Text?.Name, + idCard: userRealNameFaceAuthInfo.Text?.IdCard, + isVerified: true, + additionalInfo: additionalInfo + } + }); + } res.setHeader('Content-Type', 'text/html'); return res.send(` @@ -187,7 +243,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) data: { isVerified: false, idVerifyFailedTimes: { increment: 1 }, - additionalInfo + additionalInfo: additionalInfo } }); @@ -221,7 +277,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) } } catch (error) { console.error('faceidRealNameAuth: Internal error'); - console.error(error); + if (error instanceof Error) { + console.error('Error message:', error.message); + } else { + console.error('Unknown error:', error); + } res.setHeader('Content-Type', 'text/html'); return res.status(500).send(` From 8bb97f56ed4a956cb951f64a33b23edd4fa030ad Mon Sep 17 00:00:00 2001 From: lim Date: Tue, 12 Nov 2024 09:31:45 +0000 Subject: [PATCH 2/5] ok --- .../src/pages/api/account/faceIdRealNameAuthCallback.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts b/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts index 6ab6d5f6004..2d2598dcd3e 100644 --- a/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts +++ b/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts @@ -184,9 +184,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const accountTransaction = await globalPrisma.accountTransaction.create({ data: { - userUid, type: 'REALNAME_AUTH_REWARD', - balance: newBalance, + userUid: userUid, + balance: rewardBigInt, deduction_balance: 0, // No deduction in this case message: 'Real name authentication reward', billing_id: userRealNameInfo.id // You'll need to implement this function From 6204ed3d2e600777e05753e236339db5a6afff28 Mon Sep 17 00:00:00 2001 From: lim Date: Wed, 13 Nov 2024 06:49:19 +0000 Subject: [PATCH 3/5] change account transaction struct and add realname reward --- .../migration.sql | 3 ++ frontend/desktop/prisma/global/schema.prisma | 42 ++++++++++--------- .../src/components/account/RealNameModal.tsx | 3 ++ .../api/account/faceIdRealNameAuthCallback.ts | 2 + 4 files changed, 30 insertions(+), 20 deletions(-) create mode 100644 frontend/desktop/prisma/global/migrations/20241113062124_change_account_transaction_structure/migration.sql diff --git a/frontend/desktop/prisma/global/migrations/20241113062124_change_account_transaction_structure/migration.sql b/frontend/desktop/prisma/global/migrations/20241113062124_change_account_transaction_structure/migration.sql new file mode 100644 index 00000000000..21385ee9b40 --- /dev/null +++ b/frontend/desktop/prisma/global/migrations/20241113062124_change_account_transaction_structure/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "AccountTransaction" ADD COLUMN "balance_before" INT8; +ALTER TABLE "AccountTransaction" ADD COLUMN "deduction_balance_before" INT8; diff --git a/frontend/desktop/prisma/global/schema.prisma b/frontend/desktop/prisma/global/schema.prisma index 00526b0c2a2..b5cca6a11b4 100644 --- a/frontend/desktop/prisma/global/schema.prisma +++ b/frontend/desktop/prisma/global/schema.prisma @@ -45,15 +45,17 @@ model Account { } model AccountTransaction { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - type String - userUid String @db.Uuid - deduction_balance BigInt - balance BigInt - message String? - created_at DateTime @default(now()) @db.Timestamptz(3) - updated_at DateTime @default(now()) @db.Timestamptz(3) - billing_id String @db.Uuid + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + type String + userUid String @db.Uuid + deduction_balance BigInt + deduction_balance_before BigInt? + balance BigInt + balance_before BigInt? + message String? + created_at DateTime @default(now()) @db.Timestamptz(3) + updated_at DateTime @default(now()) @db.Timestamptz(3) + billing_id String @db.Uuid } model ErrorPaymentCreate { @@ -349,24 +351,24 @@ model Task { order Int isActive Boolean @default(true) isNewUserTask Boolean @default(false) - taskType TaskType + taskType TaskType createdAt DateTime @default(now()) @db.Timestamptz(3) updatedAt DateTime @updatedAt @db.Timestamptz(3) userTasks UserTask[] } model UserTask { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - userUid String @db.Uuid - taskId String @db.Uuid - status TaskStatus + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + userUid String @db.Uuid + taskId String @db.Uuid + status TaskStatus rewardStatus TaskStatus - completedAt DateTime - createdAt DateTime @default(now()) @db.Timestamptz(3) - updatedAt DateTime @updatedAt @db.Timestamptz(3) + completedAt DateTime + createdAt DateTime @default(now()) @db.Timestamptz(3) + updatedAt DateTime @updatedAt @db.Timestamptz(3) - user User @relation(fields: [userUid], references: [uid]) - task Task @relation(fields: [taskId], references: [id]) + user User @relation(fields: [userUid], references: [uid]) + task Task @relation(fields: [taskId], references: [id]) @@unique([userUid, taskId]) @@index([taskId]) @@ -383,4 +385,4 @@ enum TaskType { enum TaskStatus { NOT_COMPLETED COMPLETED -} \ No newline at end of file +} diff --git a/frontend/desktop/src/components/account/RealNameModal.tsx b/frontend/desktop/src/components/account/RealNameModal.tsx index 31f591fdaef..f955c4fa8da 100644 --- a/frontend/desktop/src/components/account/RealNameModal.tsx +++ b/frontend/desktop/src/components/account/RealNameModal.tsx @@ -364,7 +364,10 @@ export function FaceIdRealNameAuthORcode( realName: result.data?.realName }); + // refetch user info queryClient.invalidateQueries([session?.token, 'UserInfo']); + // refetch user amount + queryClient.invalidateQueries(['getAmount']); stopPolling(); diff --git a/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts b/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts index 2d2598dcd3e..07379944dc1 100644 --- a/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts +++ b/frontend/desktop/src/pages/api/account/faceIdRealNameAuthCallback.ts @@ -187,7 +187,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) type: 'REALNAME_AUTH_REWARD', userUid: userUid, balance: rewardBigInt, + balance_before: currentAccount.balance, deduction_balance: 0, // No deduction in this case + deduction_balance_before: currentAccount.deduction_balance, message: 'Real name authentication reward', billing_id: userRealNameInfo.id // You'll need to implement this function } From b0bca126bf25872219e189d417528c4e2371df75 Mon Sep 17 00:00:00 2001 From: lim Date: Wed, 13 Nov 2024 08:43:05 +0000 Subject: [PATCH 4/5] Optimized Copywriting --- frontend/desktop/public/locales/en/common.json | 4 ++-- frontend/desktop/public/locales/zh/common.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/desktop/public/locales/en/common.json b/frontend/desktop/public/locales/en/common.json index af112933f82..ff258937107 100644 --- a/frontend/desktop/public/locales/en/common.json +++ b/frontend/desktop/public/locales/en/common.json @@ -189,7 +189,7 @@ "realName_verification": "Real Name Verification", "realname_auth_now": "Click to verify your name", "realname_auth_reminder": "Real-name authentication reminder", - "realname_auth_reminder_desc": "Domestic availability zones require real-name authentication, and use without real-name authentication will be restricted.", + "realname_auth_reminder_desc": "Real-name verification is required for regions in China. Without real-name verification, top-up will be restricted. Successful real-name verification will be rewarded with a 5 yuan Sealos balance.", "realname_auth_tips_a": "1. Please ensure that the name, ID number and mobile phone number filled in are consistent.", "realname_auth_tips_b": "2. The number segments provided by some virtual operators may not pass verification. Please apply for a work order and pass manual verification.", "realname_info": "RealName", @@ -267,4 +267,4 @@ "you_can_view_fees_through_the_fee_center": "You can view fees through the fee center", "you_have_not_purchased_the_license": "You have not purchased the License", "yuan": "Yuan" -} \ No newline at end of file +} diff --git a/frontend/desktop/public/locales/zh/common.json b/frontend/desktop/public/locales/zh/common.json index 5676ca4bc82..2dd28b4245d 100644 --- a/frontend/desktop/public/locales/zh/common.json +++ b/frontend/desktop/public/locales/zh/common.json @@ -185,7 +185,7 @@ "realName_verification": "实名认证", "realname_auth_now": "点击进行实名", "realname_auth_reminder": "实名认证提醒", - "realname_auth_reminder_desc": "国内可用区需要实名认证,未实名认证将会被限制使用,", + "realname_auth_reminder_desc": "国内可用区需要实名认证,未实名认证将会被限制充值,实名认证成功奖励sealos余额5元", "realname_auth_tips_a": "1、请确保所填写的姓名、身份证号码和手机号码信息一致。", "realname_auth_tips_b": "2、部分虚拟运营商提供的号段可能无法验证通过,请申请工单通过人工协助认证。", "realname_info": "实名信息", @@ -260,4 +260,4 @@ "you_can_view_fees_through_the_fee_center": "您可通过费用中心查看费用", "you_have_not_purchased_the_license": "您还没有购买 License", "yuan": "元" -} \ No newline at end of file +} From bc401b31829a1fb074f2ca7797efc9ba1ee50cbc Mon Sep 17 00:00:00 2001 From: lim Date: Wed, 13 Nov 2024 09:23:34 +0000 Subject: [PATCH 5/5] ok --- frontend/desktop/public/locales/en/common.json | 2 +- frontend/desktop/public/locales/zh/common.json | 2 +- frontend/desktop/src/components/account/RealNameModal.tsx | 6 +++++- frontend/desktop/src/pages/api/platform/getCommonConfig.ts | 1 + frontend/desktop/src/types/system.ts | 2 ++ 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/frontend/desktop/public/locales/en/common.json b/frontend/desktop/public/locales/en/common.json index ff258937107..55132c941e7 100644 --- a/frontend/desktop/public/locales/en/common.json +++ b/frontend/desktop/public/locales/en/common.json @@ -189,7 +189,7 @@ "realName_verification": "Real Name Verification", "realname_auth_now": "Click to verify your name", "realname_auth_reminder": "Real-name authentication reminder", - "realname_auth_reminder_desc": "Real-name verification is required for regions in China. Without real-name verification, top-up will be restricted. Successful real-name verification will be rewarded with a 5 yuan Sealos balance.", + "realname_auth_reminder_desc": "Real-name verification is required for regions in China. Without real-name verification, top-up will be restricted. Successful real-name verification will be rewarded with a {{reward}} Sealos balance.", "realname_auth_tips_a": "1. Please ensure that the name, ID number and mobile phone number filled in are consistent.", "realname_auth_tips_b": "2. The number segments provided by some virtual operators may not pass verification. Please apply for a work order and pass manual verification.", "realname_info": "RealName", diff --git a/frontend/desktop/public/locales/zh/common.json b/frontend/desktop/public/locales/zh/common.json index 2dd28b4245d..3637b703759 100644 --- a/frontend/desktop/public/locales/zh/common.json +++ b/frontend/desktop/public/locales/zh/common.json @@ -185,7 +185,7 @@ "realName_verification": "实名认证", "realname_auth_now": "点击进行实名", "realname_auth_reminder": "实名认证提醒", - "realname_auth_reminder_desc": "国内可用区需要实名认证,未实名认证将会被限制充值,实名认证成功奖励sealos余额5元", + "realname_auth_reminder_desc": "国内可用区需要实名认证,未实名认证将会被限制充值,实名认证成功奖励 Sealos 余额 {{reward}} 元。", "realname_auth_tips_a": "1、请确保所填写的姓名、身份证号码和手机号码信息一致。", "realname_auth_tips_b": "2、部分虚拟运营商提供的号段可能无法验证通过,请申请工单通过人工协助认证。", "realname_info": "实名信息", diff --git a/frontend/desktop/src/components/account/RealNameModal.tsx b/frontend/desktop/src/components/account/RealNameModal.tsx index f955c4fa8da..ba31a37503b 100644 --- a/frontend/desktop/src/components/account/RealNameModal.tsx +++ b/frontend/desktop/src/components/account/RealNameModal.tsx @@ -46,6 +46,8 @@ import { DeleteIcon, PictureIcon, UploadIcon, AttachmentIcon } from '../icons'; export function useRealNameAuthNotification(props?: UseToastOptions) { const { t } = useTranslation(); + const { commonConfig } = useConfigStore((s) => s); + const realNameReward = commonConfig?.realNameReward; const realNameAuthNotification = useToast({ position: 'top', @@ -108,7 +110,9 @@ export function useRealNameAuthNotification(props?: UseToastOptions) { lineHeight="20px" letterSpacing="0.25px" > - {t('common:realname_auth_reminder_desc')} + {t('common:realname_auth_reminder_desc', { + reward: realNameReward + })}