Skip to content

Commit

Permalink
feat(desktop) Add Real Name Invitee Rewards (#5366)
Browse files Browse the repository at this point in the history
  • Loading branch information
HUAHUAI23 authored Feb 11, 2025
1 parent 3be90e5 commit ce4a525
Show file tree
Hide file tree
Showing 4 changed files with 386 additions and 103 deletions.
5 changes: 4 additions & 1 deletion frontend/desktop/src/pages/api/account/enterpriseRealName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ async function handleGet(req: NextApiRequest, res: NextApiResponse, userUid: str
});

if (!info || !info.additionalInfo) {
return jsonRes(res, { code: 200, data: { authTimes: realNameAuthProvider.maxFailedTimes } });
return jsonRes(res, {
code: 200,
data: { remainingAttempts: realNameAuthProvider.maxFailedTimes }
});
}

const additionalInfo = info.additionalInfo as unknown as AdditionalInfo;
Expand Down
171 changes: 162 additions & 9 deletions frontend/desktop/src/pages/api/account/enterpriseRealNameVerify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { globalPrisma } from '@/services/backend/db/init';
import { z } from 'zod';
import { PAYMENTSTATUS } from '@/types/response/enterpriseRealName';
import { AdditionalInfo } from '@/types/response/enterpriseRealName';
import { RealNameAuthProvider } from '@/pages/api/account/faceIdRealNameAuthCallback';
import { TencentCloudFaceAuthConfig } from '@/pages/api/account/faceIdRealNameAuthCallback';
import { getInviterInfo } from '@/utils/getInviteInfo';

const schema = z.object({
transAmt: z.string().min(1)
Expand All @@ -25,7 +28,33 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const payload = await verifyAccessToken(req.headers);
if (!payload) return jsonRes(res, { code: 401, message: 'Token is invalid' });

const userUid = payload.userUid;
const userId = payload.userId;

const inviteInfo = await getInviterInfo(userId);

try {
const realNameAuthProvider: RealNameAuthProvider | null =
await globalPrisma.realNameAuthProvider.findFirst({
where: {
backend: 'TENCENTCLOUD',
authType: 'tcloudFaceAuth'
}
});

if (!realNameAuthProvider) {
throw new Error('faceidRealNameAuth: Real name authentication provider not found');
}

const config: TencentCloudFaceAuthConfig =
realNameAuthProvider.config as TencentCloudFaceAuthConfig;

if (!config) {
throw new Error('faceidRealNameAuth: Real name authentication configuration not found');
}

const realNameAuthReward = config.realNameAuthReward;

const validationResult = schema.safeParse(req.body);
if (!validationResult.success) {
return jsonRes(res, {
Expand Down Expand Up @@ -60,16 +89,129 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)

const additionalInfo = info.additionalInfo as unknown as AdditionalInfo;

if (additionalInfo.transAmt === transAmt) {
await globalPrisma.enterpriseRealNameInfo.update({
where: { userUid: payload.userUid },
if (additionalInfo.transAmt !== transAmt) {
return jsonRes(res, {
code: 200,
message: 'transAmt_not_match',
data: {
isVerified: true,
additionalInfo: {
...additionalInfo,
paymentStatus: PAYMENTSTATUS.SUCCESS
authState: 'failed'
}
});
}

if (realNameAuthReward) {
await globalPrisma.$transaction(async (globalPrisma) => {
const currentAccount = await globalPrisma.account.findUniqueOrThrow({
where: { userUid }
});

if (!currentAccount.balance) {
throw new Error('enterpriseRealNameVerify: Account balance not found');
}

const currentActivityBonus = currentAccount.activityBonus || BigInt(0);
const realnameReward = BigInt(realNameAuthReward);

const newActivityBonus = currentActivityBonus + realnameReward;
const newBalance = currentAccount.balance + realnameReward;

const updatedAccount = await globalPrisma.account.update({
where: { userUid },
data: {
activityBonus: newActivityBonus,
balance: newBalance
}
});

const enterpriseRealNameInfo = await globalPrisma.enterpriseRealNameInfo.update({
where: { userUid: payload.userUid },
data: {
isVerified: true,
additionalInfo: {
...additionalInfo,
paymentStatus: PAYMENTSTATUS.SUCCESS
}
}
});

const accountTransaction = await globalPrisma.accountTransaction.create({
data: {
type: 'REALNAME_AUTH_REWARD',
userUid: userUid,
balance: realnameReward,
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: enterpriseRealNameInfo.id // You'll need to implement this function
}
});

await globalPrisma.userTask.updateMany({
where: {
userUid,
task: {
taskType: 'REAL_NAME_AUTH'
},
status: 'NOT_COMPLETED'
},
data: {
rewardStatus: 'COMPLETED',
status: 'COMPLETED',
completedAt: new Date()
}
});

if (inviteInfo.inviterId && inviteInfo.amount) {
const inviterUser = await globalPrisma.user.findUniqueOrThrow({
where: { id: inviteInfo.inviterId }
});

if (!inviterUser) {
throw new Error('enterpriseRealNameVerify: Inviter user not found');
}

const inviterAccount = await globalPrisma.account.findUniqueOrThrow({
where: { userUid: inviterUser.uid }
});

if (!inviterAccount.balance) {
throw new Error('enterpriseRealNameVerify: Inviter account balance not found');
}

const currentActivityBonus = inviterAccount.activityBonus || BigInt(0);
const realnameInviteReward = inviteInfo.amount;

const newActivityBonus = currentActivityBonus + realnameInviteReward;
const newBalance = inviterAccount.balance + realnameInviteReward;

await globalPrisma.account.update({
where: { userUid: inviterUser.uid },
data: {
activityBonus: newActivityBonus,
balance: newBalance
}
});

await globalPrisma.accountTransaction.create({
data: {
type: 'REALNAME_AUTH_INVITE_REWARD',
userUid: inviterUser.uid,
balance: realnameInviteReward,
balance_before: inviterAccount.balance,
deduction_balance: 0, // No deduction in this case
deduction_balance_before: inviterAccount.deduction_balance,
message: 'Real name authentication invite reward',
billing_id: enterpriseRealNameInfo.id // You'll need to implement this function
}
});
}

return {
account: updatedAccount,
transaction: accountTransaction,
enterpriseRealNameInfo: enterpriseRealNameInfo
};
});

return jsonRes(res, {
Expand All @@ -81,11 +223,22 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
});
}

await globalPrisma.enterpriseRealNameInfo.update({
where: { userUid: payload.userUid },
data: {
isVerified: true,
additionalInfo: {
...additionalInfo,
paymentStatus: PAYMENTSTATUS.SUCCESS
}
}
});

return jsonRes(res, {
code: 200,
message: 'transAmt_not_match',
data: {
authState: 'failed'
authState: 'success',
enterpriseRealName: additionalInfo.keyName
}
});
} catch (error) {
Expand Down
Loading

0 comments on commit ce4a525

Please sign in to comment.